enhanced ui

This commit is contained in:
Saifeddine ALOUI
2024-01-02 00:53:49 +01:00
parent 123b0fef72
commit 70dc2f4663
16 changed files with 4081 additions and 3880 deletions

View File

@ -19,4 +19,6 @@ packaging
fastapi fastapi
uvicorn uvicorn
python-socketio
python-socketio[client]
python-socketio[asyncio_client] python-socketio[asyncio_client]

View File

@ -5,7 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue</title> <title>Vite + Vue</title>
<script type="module" crossorigin src="/assets/index-gD_iVx44.js"></script> <script type="module" crossorigin src="/assets/index-xU-eXePa.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-tsveoIuX.css"> <link rel="stylesheet" crossorigin href="/assets/index-tsveoIuX.css">
</head> </head>
<body> <body>

View File

@ -1,7 +1,8 @@
import { createApp } from 'vue'; import { createApp } from 'vue';
import { createRouter, createWebHistory } from 'vue-router'; import { createRouter, createWebHistory } from 'vue-router';
import { createStore } from 'vuex'
import App from './App.vue'; import App from './App.vue';
import Install from './components/Install.vue'; import Install from './views/Install.vue';
import './style.css'; import './style.css';
const routes = [ const routes = [
{ {
@ -16,4 +17,51 @@ const router = createRouter({
routes, routes,
}); });
// Create a new store instance.
export const store = createStore({
state () {
return {
// count: 0,
yesNoDialog:null,
universalForm:null,
toast:null,
messageBox:null,
api_get_req:null,
startSpeechRecognition:null,
ready:false,
loading_infos: "",
loading_progress: 0,
version : "unknown",
settingsChanged:false,
isConnected: false, // Add the isConnected property
isModelOk: false,
isGenerating: false,
config:null,
mountedPers:null,
mountedPersArr:[],
mountedExtensions:[],
bindingsZoo:[],
modelsArr:[],
selectedModel:null,
personalities:[],
diskUsage:null,
ramUsage:null,
vramUsage:null,
modelsZoo:[],
installedModels:[],
currentModel:null,
extensionsZoo:[],
databases:[],
}
},
mutations: {
},
getters: {
},
actions: {
}
})
createApp(App).use(router).mount('#app'); createApp(App).use(router).mount('#app');

View File

@ -1,5 +1,6 @@
<template> <template>
<div class="flex flex-col items-center justify-center rounded-lg m-2 shadow-lg hover:border-primary dark:hover:border-primary hover:border-solid hover:border-2 border-2 border-transparent even:bg-bg-light-discussion-odd dark:even:bg-bg-dark-discussion-odd flex flex-col flex-grow flex-wrap overflow-visible p-4 pb-2"> <div class="flex flex-col items-center justify-center rounded-lg m-2 shadow-lg hover:border-primary dark:hover:border-primary hover:border-solid hover:border-2 border-2 border-transparent even:bg-bg-light-discussion-odd dark:even:bg-bg-dark-discussion-odd flex flex-col flex-grow flex-wrap overflow-visible p-4 pb-2">
<img :src = "LoLLMSLogo">
<h1 class="text-4xl font-bold mb-4">LOLLMS installation tool</h1> <h1 class="text-4xl font-bold mb-4">LOLLMS installation tool</h1>
<p class="text-left"> <p class="text-left">
Welcome to the installer of lollms. Here you can select your install profile.<br> Welcome to the installer of lollms. Here you can select your install profile.<br>
@ -7,11 +8,11 @@
</p> </p>
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<label class="flex items-center"> <label class="flex items-center">
<input type="radio" value="nvidia" v-model="selectedOption" class="mr-2"> <input type="radio" value="cuda" v-model="selectedOption" class="mr-2">
Use NVIDIA GPU with CUDA Use NVIDIA GPU with CUDA
</label> </label>
<label class="flex items-center"> <label class="flex items-center">
<input type="radio" value="amd" v-model="selectedOption" class="mr-2"> <input type="radio" value="rocm" v-model="selectedOption" class="mr-2">
Use AMD GPU with ROCm Use AMD GPU with ROCm
</label> </label>
<label class="flex items-center"> <label class="flex items-center">
@ -27,16 +28,23 @@
Install Install
</button> </button>
</div> </div>
<MessageBox ></MessageBox>
</template> </template>
<script> <script>
import MessageBox from '../components/messageBox.vue';
import axios from 'axios'; import axios from 'axios';
import LoLLMSLogo from '../assets/logo.png'
export default { export default {
data() { data() {
return { return {
LoLLMSLogo:LoLLMSLogo,
selectedOption: "cpu", selectedOption: "cpu",
}; };
}, },
components:{
MessageBox
},
methods: { methods: {
install() { install() {
axios.post("/start_installing",{mode:this.selectedOption}).then(()=>{ axios.post("/start_installing",{mode:this.selectedOption}).then(()=>{

View File

@ -1,10 +1,18 @@
"""
Project: lollms_installer
Author: Your Name
Description: This tool is designed to install and configure the LoLLMS system on your machine. LoLLMS is a multi-bindings, multi-personalities LLM full-stack system for AI applications in robotics. It provides a user-friendly interface for setting up and managing the system.
"""
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel from pydantic import BaseModel
import uvicorn import uvicorn
from lollms.paths import LollmsPaths from lollms.paths import LollmsPaths
from lollms.main_config import LOLLMSConfig from lollms.main_config import LOLLMSConfig
from lollms.utilities import check_and_install_torch, PackageManager from lollms.utilities import check_and_install_torch, PackageManager, check_torch_version, reinstall_pytorch_with_cuda, reinstall_pytorch_with_cpu, reinstall_pytorch_with_rocm
from lollms.com import NotificationType, NotificationDisplayType, LoLLMsCom
from lollms.types import MSG_TYPE, SENDER_TYPES
from lollms.app import LollmsApplication
from pathlib import Path from pathlib import Path
from ascii_colors import ASCIIColors from ascii_colors import ASCIIColors
import subprocess import subprocess
@ -13,6 +21,7 @@ from pathlib import Path
from starlette.responses import FileResponse from starlette.responses import FileResponse
from starlette.requests import Request from starlette.requests import Request
import webbrowser import webbrowser
import socketio
root_path = Path(__file__).parent.parent.parent.parent root_path = Path(__file__).parent.parent.parent.parent
global_path = root_path/"global_paths_cfg.yaml" global_path = root_path/"global_paths_cfg.yaml"
@ -34,8 +43,12 @@ ASCIIColors.red("|_____|_____|_____|_____|_|_|_|_____|")
ASCIIColors.red(" Configurator ") ASCIIColors.red(" Configurator ")
ASCIIColors.red(" LoLLMS configuratoin tool") ASCIIColors.red(" LoLLMS configuratoin tool")
ASCIIColors.yellow(f"Root dir : {root_path}") ASCIIColors.yellow(f"Root dir : {root_path}")
app = FastAPI(debug=True)
sio = socketio.AsyncServer(async_mode='asgi')
app = FastAPI(debug=True)
app.mount("/socket.io", socketio.ASGIApp(sio))
lollms_app = LollmsApplication("lollms_installer",config=config,lollms_paths=lollms_paths, load_binding=False, load_model=False, socketio=sio)
# Serve the index.html file for all routes # Serve the index.html file for all routes
@app.get("/{full_path:path}") @app.get("/{full_path:path}")
@ -50,21 +63,60 @@ async def serve_index(request: Request, full_path: Path):
# app.mount("/", StaticFiles(directory=root_path/"scripts/python/lollms_installer/frontend/dist"), name="static") # app.mount("/", StaticFiles(directory=root_path/"scripts/python/lollms_installer/frontend/dist"), name="static")
class InstallProperties(BaseModel): class InstallProperties(BaseModel):
mode: str mode: str
@app.post("/start_installing") @app.post("/start_installing")
def start_installing(data: InstallProperties): def start_installing(data: InstallProperties):
"""
Handle the start_installing endpoint.
Parameters:
- **data**: An instance of the `InstallProperties` model containing the installation mode.
Returns:
- A dictionary with a "message" key indicating the success of the installation.
"""
if data.mode=="cpu": if data.mode=="cpu":
config.enable_gpu=False config.enable_gpu=False
try:
lollms_app.ShowBlockingMessage("Installing pytorch for CPU")
reinstall_pytorch_with_cpu()
config.save_config() config.save_config()
else: lollms_app.HideBlockingMessage()
except:
lollms_app.HideBlockingMessage()
elif data.mode=="cuda":
config.enable_gpu=True config.enable_gpu=True
try:
lollms_app.ShowBlockingMessage("Installing pytorch for nVidia GPU (cuda)")
reinstall_pytorch_with_cuda()
config.save_config() config.save_config()
lollms_app.HideBlockingMessage()
except:
lollms_app.HideBlockingMessage()
elif data.mode=="rocm":
config.enable_gpu=True
try:
lollms_app.ShowBlockingMessage("Installing pytorch for AMD GPU (rocm)")
reinstall_pytorch_with_rocm()
config.save_config()
lollms_app.HideBlockingMessage()
except:
lollms_app.HideBlockingMessage()
elif data.mode=="metal":
try:
lollms_app.ShowBlockingMessage("Installing pytorch for Apple Silicon (Metal)")
config.enable_gpu=False
reinstall_pytorch_with_cpu()
config.save_config()
lollms_app.HideBlockingMessage()
except:
lollms_app.HideBlockingMessage()
# Your code here # Your code here
return {"message": "Item created successfully"} return {"message": "Item created successfully"}
if __name__ == "__main__": if __name__ == "__main__":
webbrowser.open(f"http://localhost:8000") webbrowser.open(f"http://localhost:8000")
uvicorn.run(app, host="0.0.0.0", port=8000) uvicorn.run(app, host="localhost", port=8000)

3845
web/dist/assets/index-0655b628.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
web/dist/index.html vendored
View File

@ -6,8 +6,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LoLLMS WebUI - Welcome</title> <title>LoLLMS WebUI - Welcome</title>
<script type="module" crossorigin src="/assets/index-5f09bbb6.js"></script> <script type="module" crossorigin src="/assets/index-0655b628.js"></script>
<link rel="stylesheet" href="/assets/index-fdc1d634.css"> <link rel="stylesheet" href="/assets/index-a45078bc.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -72,7 +72,7 @@
title="Edit message" @click.stop="editMsgMode = true"> title="Edit message" @click.stop="editMsgMode = true">
<i data-feather="edit"></i> <i data-feather="edit"></i>
</div> </div>
<div v-if="editMsgMode" class="text-lg hover:text-secondary duration-75 active:scale-90 p-2 cursor-pointer" <div v-if="editMsgMode" class="text-lg hover:text-secondary duration-75 active:scale-90 p-2 cursor-pointer hover:border-2"
title="Add python block" @click.stop="addBlock('python')"> title="Add python block" @click.stop="addBlock('python')">
<img :src="python_block" width="25" height="25"> <img :src="python_block" width="25" height="25">
</div> </div>
@ -80,6 +80,11 @@
title="Add javascript block" @click.stop="addBlock('javascript')"> title="Add javascript block" @click.stop="addBlock('javascript')">
<img :src="javascript_block" width="25" height="25"> <img :src="javascript_block" width="25" height="25">
</div> </div>
<div v-if="editMsgMode" class="text-lg hover:text-secondary duration-75 active:scale-90 p-2 cursor-pointer"
title="Add json block" @click.stop="addBlock('json')">
<img :src="json_block" width="25" height="25">
</div>
<div v-if="editMsgMode" class="text-lg hover:text-secondary duration-75 active:scale-90 p-2 cursor-pointer" <div v-if="editMsgMode" class="text-lg hover:text-secondary duration-75 active:scale-90 p-2 cursor-pointer"
title="Add c++ block" @click.stop="addBlock('c++')"> title="Add c++ block" @click.stop="addBlock('c++')">
<img :src="cpp_block" width="25" height="25"> <img :src="cpp_block" width="25" height="25">
@ -268,6 +273,7 @@ import axios from 'axios';
import python_block from '@/assets/python_block.png'; import python_block from '@/assets/python_block.png';
import javascript_block from '@/assets/javascript_block.svg'; import javascript_block from '@/assets/javascript_block.svg';
import json_block from '@/assets/json_block.png';
import cpp_block from '@/assets/cpp_block.png'; import cpp_block from '@/assets/cpp_block.png';
import html5_block from '@/assets/html5_block.png'; import html5_block from '@/assets/html5_block.png';
import LaTeX_block from '@/assets/LaTeX_block.png'; import LaTeX_block from '@/assets/LaTeX_block.png';
@ -299,6 +305,7 @@ export default {
cpp_block:cpp_block, cpp_block:cpp_block,
html5_block:html5_block, html5_block:html5_block,
LaTeX_block:LaTeX_block, LaTeX_block:LaTeX_block,
json_block:json_block,
javascript_block:javascript_block, javascript_block:javascript_block,
python_block:python_block, python_block:python_block,
bash_block:bash_block, bash_block:bash_block,
@ -342,7 +349,28 @@ export default {
const textarea = event.target; const textarea = event.target;
const start = textarea.selectionStart; const start = textarea.selectionStart;
const end = textarea.selectionEnd; const end = textarea.selectionEnd;
const isShiftPressed = event.shiftKey;
if (start === end) {
// If no text is selected, insert a tab or backtab as usual
if (isShiftPressed) {
if(textarea.value.substring(start - 4,start)==" "){
// Backtab
const textBefore = textarea.value.substring(0, start - 4);
const textAfter = textarea.value.substring(end);
// Remove the tab character (or spaces if you prefer) before the cursor position
const newText = textBefore + textAfter;
// Update the textarea content and cursor position
this.message.content = newText;
this.$nextTick(() => {
textarea.selectionStart = textarea.selectionEnd = start - 4;
});
}
} else {
// Tab
const textBefore = textarea.value.substring(0, start); const textBefore = textarea.value.substring(0, start);
const textAfter = textarea.value.substring(end); const textAfter = textarea.value.substring(end);
@ -354,9 +382,43 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
textarea.selectionStart = textarea.selectionEnd = start + 4; textarea.selectionStart = textarea.selectionEnd = start + 4;
}); });
}
} else {
// If text is selected, insert a tab or backtab at the beginning of each selected line
const lines = textarea.value.substring(start, end).split('\n');
const updatedLines = lines.map((line) => {
if (line.trim() === '') {
return line; // Skip empty lines
} else if (isShiftPressed) {
// Backtab
if (line.startsWith(' ')) {
return line.substring(4); // Remove the tab character (or spaces if you prefer)
} else {
return line; // Line doesn't start with a tab, skip backtab
}
} else {
// Tab
return ' ' + line; // Insert a tab character (or spaces if you prefer) at the beginning of the line
}
});
const textBefore = textarea.value.substring(0, start);
const textAfter = textarea.value.substring(end);
// Update the textarea content with the modified lines
const newText = textBefore + updatedLines.join('\n') + textAfter;
this.message.content = newText;
// Update the textarea selection range
this.$nextTick(() => {
textarea.selectionStart = start;
textarea.selectionEnd = end + (updatedLines.length * 4); // Adjust selection end based on the added tabs
});
}
event.preventDefault(); event.preventDefault();
}, },
onVoicesChanged() { onVoicesChanged() {
// This event will be triggered when the voices are loaded // This event will be triggered when the voices are loaded
this.voices = this.speechSynthesis.getVoices(); this.voices = this.speechSynthesis.getVoices();
@ -460,15 +522,29 @@ export default {
this.expanded = !this.expanded; this.expanded = !this.expanded;
}, },
addBlock(bloc_name){ addBlock(bloc_name){
let p =this.$refs.mdTextarea.selectionStart let ss =this.$refs.mdTextarea.selectionStart
if(p==0 || this.message.content[p-1]=="\n"){ let se =this.$refs.mdTextarea.selectionEnd
this.message.content = this.message.content.slice(0, p) + "```"+bloc_name+"\n\n```\n" + this.message.content.slice(p) if(ss==se){
p = p+4+bloc_name.length if(speechSynthesis==0 || this.message.content[ss-1]=="\n"){
this.message.content = this.message.content.slice(0, ss) + "```"+bloc_name+"\n\n```\n" + this.message.content.slice(ss)
ss = ss+4+bloc_name.length
} }
else{ else{
this.message.content = this.message.content.slice(0, p) + "\n```"+bloc_name+"\n\n```\n" + this.message.content.slice(p) this.message.content = this.message.content.slice(0, ss) + "\n```"+bloc_name+"\n\n```\n" + this.message.content.slice(ss)
ss = ss+3+bloc_name.length
}
}
else{
if(speechSynthesis==0 || this.message.content[ss-1]=="\n"){
this.message.content = this.message.content.slice(0, ss) + "```"+bloc_name+"\n"+this.message.content.slice(ss, se)+"\n```\n" + this.message.content.slice(se)
ss = ss+4+bloc_name.length
}
else{
this.message.content = this.message.content.slice(0, ss) + "\n```"+bloc_name+"\n"+this.message.content.slice(ss, se)+"\n```\n" + this.message.content.slice(se)
p = p+3+bloc_name.length p = p+3+bloc_name.length
} }
}
this.$refs.mdTextarea.focus(); this.$refs.mdTextarea.focus();
this.$refs.mdTextarea.selectionStart = this.$refs.mdTextarea.selectionEnd = p; this.$refs.mdTextarea.selectionStart = this.$refs.mdTextarea.selectionEnd = p;
}, },

View File

@ -66,6 +66,10 @@
title="Add javascript block" @click.stop="addBlock('javascript')"> title="Add javascript block" @click.stop="addBlock('javascript')">
<img :src="javascript_block" width="25" height="25"> <img :src="javascript_block" width="25" height="25">
</div> </div>
<div class="text-lg hover:text-secondary duration-75 active:scale-90 p-2 cursor-pointer"
title="Add json block" @click.stop="addBlock('json')">
<img :src="json_block" width="25" height="25">
</div>
<div class="text-lg hover:text-secondary duration-75 active:scale-90 p-2 cursor-pointer" <div class="text-lg hover:text-secondary duration-75 active:scale-90 p-2 cursor-pointer"
title="Add c++ block" @click.stop="addBlock('c++')"> title="Add c++ block" @click.stop="addBlock('c++')">
<img :src="cpp_block" width="25" height="25"> <img :src="cpp_block" width="25" height="25">
@ -210,6 +214,8 @@ const bUrl = import.meta.env.VITE_LOLLMS_API_BASEURL
import python_block from '@/assets/python_block.png'; import python_block from '@/assets/python_block.png';
import javascript_block from '@/assets/javascript_block.svg'; import javascript_block from '@/assets/javascript_block.svg';
import json_block from '@/assets/json_block.png';
import cpp_block from '@/assets/cpp_block.png'; import cpp_block from '@/assets/cpp_block.png';
import html5_block from '@/assets/html5_block.png'; import html5_block from '@/assets/html5_block.png';
import LaTeX_block from '@/assets/LaTeX_block.png'; import LaTeX_block from '@/assets/LaTeX_block.png';
@ -368,6 +374,7 @@ export default {
html5_block:html5_block, html5_block:html5_block,
LaTeX_block:LaTeX_block, LaTeX_block:LaTeX_block,
javascript_block:javascript_block, javascript_block:javascript_block,
json_block:json_block,
python_block:python_block, python_block:python_block,
bash_block:bash_block, bash_block:bash_block,

View File

@ -2445,8 +2445,9 @@ export default {
//this.settingsChanged = true //this.settingsChanged = true
let pth = pers.language==null?pers.full_path:pers.full_path+":"+pers.language
if (pers.isMounted && this.configFile.personalities.includes(pers.full_path)) { console.log("pth",pth)
if (pers.isMounted && this.configFile.personalities.includes(pth)) {
const res = await this.select_personality(pers) const res = await this.select_personality(pers)
console.log('pers is mounted', res) console.log('pers is mounted', res)
@ -3553,7 +3554,9 @@ export default {
}, },
async select_personality(pers) { async select_personality(pers) {
if (!pers) { return { 'status': false, 'error': 'no personality - select_personality' } } if (!pers) { return { 'status': false, 'error': 'no personality - select_personality' } }
const id = this.configFile.personalities.findIndex(item => item === pers.full_path) let pth = pers.language==null?pers.full_path:pers.full_path+":"+pers.language
console.log("pth",pth)
const id = this.configFile.personalities.findIndex(item => item === pth)
const obj = { const obj = {
id: id id: id