mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2025-04-10 12:19:58 +00:00
upgraded vue code
This commit is contained in:
parent
2c565e8696
commit
325cd5b627
110
app.py
110
app.py
@ -22,6 +22,7 @@ import re
|
||||
import traceback
|
||||
import threading
|
||||
import sys
|
||||
from tqdm import tqdm
|
||||
from pyaipersonality import AIPersonality
|
||||
from pyGpt4All.db import DiscussionsDB, Discussion
|
||||
from flask import (
|
||||
@ -39,6 +40,7 @@ import gc
|
||||
from geventwebsocket.handler import WebSocketHandler
|
||||
from gevent.pywsgi import WSGIServer
|
||||
import requests
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
|
||||
app = Flask("GPT4All-WebUI", static_url_path="/static", static_folder="static")
|
||||
socketio = SocketIO(app, cors_allowed_origins="*", async_mode='gevent', ping_timeout=30, ping_interval=15)
|
||||
@ -160,12 +162,7 @@ class Gpt4AllWebUI(GPT4AllAPI):
|
||||
self.add_endpoint(
|
||||
"/get_available_models", "get_available_models", self.get_available_models, methods=["GET"]
|
||||
)
|
||||
self.add_endpoint(
|
||||
"/install_model", "install_model", self.install_model, methods=["POST"]
|
||||
)
|
||||
self.add_endpoint(
|
||||
"/uninstall_model", "uninstall_model", self.uninstall_model, methods=["POST"]
|
||||
)
|
||||
|
||||
|
||||
self.add_endpoint(
|
||||
"/extensions", "extensions", self.extensions, methods=["GET"]
|
||||
@ -212,6 +209,77 @@ class Gpt4AllWebUI(GPT4AllAPI):
|
||||
@socketio.on('disconnect')
|
||||
def disconnect():
|
||||
print('Client disconnected')
|
||||
|
||||
@socketio.on('install_model')
|
||||
def install_model(data):
|
||||
model_path = data["path"]
|
||||
progress = 0
|
||||
installation_dir = Path(f'./models/{self.config["backend"]}/')
|
||||
filename = Path(model_path).name
|
||||
installation_path = installation_dir / filename
|
||||
print("Model install requested")
|
||||
print(f"Model path : {model_path}")
|
||||
|
||||
if installation_path.exists():
|
||||
print("Error: Model already exists")
|
||||
data.installing = False
|
||||
socketio.emit('install_progress',{'status': 'failed', 'error': 'model already exists'})
|
||||
|
||||
socketio.emit('install_progress',{'status': 'progress', 'progress': progress})
|
||||
|
||||
response = requests.get(model_path, stream=True)
|
||||
file_size = int(response.headers.get('Content-Length'))
|
||||
downloaded_size = 0
|
||||
CHUNK_SIZE = 4096
|
||||
|
||||
def download_chunk(url, start_byte, end_byte, fileobj):
|
||||
headers = {'Range': f'bytes={start_byte}-{end_byte}'}
|
||||
response = requests.get(url, headers=headers, stream=True)
|
||||
|
||||
for chunk in response.iter_content(chunk_size=CHUNK_SIZE):
|
||||
if chunk:
|
||||
fileobj.seek(start_byte)
|
||||
fileobj.write(chunk)
|
||||
start_byte += len(chunk)
|
||||
|
||||
def download_file(url, file_path, num_threads=4):
|
||||
response = requests.head(url)
|
||||
file_size = int(response.headers.get('Content-Length'))
|
||||
|
||||
with open(file_path, 'wb') as fileobj:
|
||||
with tqdm(total=file_size, unit='B', unit_scale=True, unit_divisor=1024) as pbar:
|
||||
with ThreadPoolExecutor(max_workers=num_threads) as executor:
|
||||
futures = []
|
||||
chunk_size = file_size // num_threads
|
||||
|
||||
for i in range(num_threads):
|
||||
start_byte = i * chunk_size
|
||||
end_byte = start_byte + chunk_size - 1 if i < num_threads - 1 else file_size - 1
|
||||
futures.append(executor.submit(download_chunk, url, start_byte, end_byte, fileobj))
|
||||
|
||||
for future in tqdm(as_completed(futures), total=num_threads):
|
||||
future.result()
|
||||
pbar.update(chunk_size)
|
||||
|
||||
# Usage example
|
||||
download_file(model_path, installation_path, num_threads=4)
|
||||
|
||||
socketio.emit('install_progress',{'status': 'succeeded', 'error': ''})
|
||||
|
||||
@socketio.on('uninstall_model')
|
||||
def uninstall_model(data):
|
||||
model_path = data['path']
|
||||
installation_dir = Path(f'./models/{self.config["backend"]}/')
|
||||
filename = Path(model_path).name
|
||||
installation_path = installation_dir / filename
|
||||
|
||||
if not installation_path.exists():
|
||||
socketio.emit('install_progress',{'status': 'failed', 'error': ''})
|
||||
|
||||
installation_path.unlink()
|
||||
socketio.emit('install_progress',{'status': 'succeeded', 'error': ''})
|
||||
|
||||
|
||||
|
||||
@socketio.on('generate_msg')
|
||||
def generate_msg(data):
|
||||
@ -702,7 +770,7 @@ class Gpt4AllWebUI(GPT4AllAPI):
|
||||
|
||||
|
||||
def get_available_models(self):
|
||||
response = requests.get(f' https://gpt4all.io/models/models.json')
|
||||
response = requests.get(f'https://gpt4all.io/models/models.json')
|
||||
model_list = response.json()
|
||||
|
||||
models = []
|
||||
@ -710,7 +778,8 @@ class Gpt4AllWebUI(GPT4AllAPI):
|
||||
filename = model['filename']
|
||||
filesize = model['filesize']
|
||||
path = f'https://gpt4all.io/models/{filename}'
|
||||
is_installed = Path(f'/models/{self.config["backend"]}/{filename}').is_file()
|
||||
local_path = Path(f'./models/{self.config["backend"]}/{filename}')
|
||||
is_installed = local_path.exists()
|
||||
models.append({
|
||||
'title': model['filename'],
|
||||
'icon': '/icons/default.png', # Replace with the path to the model icon
|
||||
@ -721,31 +790,6 @@ class Gpt4AllWebUI(GPT4AllAPI):
|
||||
})
|
||||
return jsonify(models)
|
||||
|
||||
def install_model(self):
|
||||
model_path = request.json.get('path')
|
||||
installation_dir = Path('/models/llamacpp/')
|
||||
filename = Path(model_path).name
|
||||
installation_path = installation_dir / filename
|
||||
|
||||
if installation_path.exists():
|
||||
return jsonify({'status': 'Already installed'})
|
||||
|
||||
response = requests.get(model_path)
|
||||
with open(installation_path, 'wb') as f:
|
||||
f.write(response.content)
|
||||
return jsonify({'status':True})
|
||||
|
||||
def uninstall_model(self):
|
||||
model_path = request.json.get('path')
|
||||
installation_dir = Path('/models/llamacpp/')
|
||||
filename = Path(model_path).name
|
||||
installation_path = installation_dir / filename
|
||||
|
||||
if not installation_path.exists():
|
||||
return jsonify({'status':False})
|
||||
|
||||
installation_path.unlink()
|
||||
return jsonify({'status':True})
|
||||
|
||||
def get_config(self):
|
||||
return jsonify(self.config)
|
||||
|
@ -1,8 +1,5 @@
|
||||
<template>
|
||||
<div
|
||||
class="flex items-center p-4 hover:bg-primary-light rounded-lg mb-2 shadow-lg"
|
||||
:class="{ 'bg-primary-light': selected }"
|
||||
>
|
||||
<div class="flex items-center p-4 hover:bg-primary-light rounded-lg mb-2 shadow-lg">
|
||||
<div class="flex-shrink-0">
|
||||
<i :class="`fas ${icon} text-xl`"></i>
|
||||
</div>
|
||||
@ -22,15 +19,31 @@
|
||||
<button
|
||||
class="px-4 py-2 rounded-md text-white font-bold transition-colors duration-300"
|
||||
:class="[isInstalled ? 'bg-red-500 hover:bg-red-600' : 'bg-green-500 hover:bg-green-600']"
|
||||
:disabled="installing || uninstalling"
|
||||
@click="toggleInstall"
|
||||
>
|
||||
{{ isInstalled ? 'Uninstall' : 'Install' }}
|
||||
<template v-if="installing">
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="h-2 w-20 bg-gray-300 rounded"></div>
|
||||
<span>Installing...</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="uninstalling">
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="h-2 w-20 bg-gray-300 rounded"></div>
|
||||
<span>Uninstalling...</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ isInstalled ? 'Uninstall' : 'Install' }}
|
||||
</template>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { socket, state } from '@/services/websocket.js'
|
||||
export default {
|
||||
props: {
|
||||
title: String,
|
||||
@ -38,15 +51,30 @@ export default {
|
||||
path: String,
|
||||
description: String,
|
||||
isInstalled: Boolean,
|
||||
onToggleInstall: Function,
|
||||
selected: Boolean // Use a boolean selected prop
|
||||
onInstall: Function,
|
||||
onUninstall: Function,
|
||||
selected: Boolean
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
installing: false,
|
||||
uninstalling: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
toggleInstall() {
|
||||
this.onToggleInstall(this.isInstalled, this.path);
|
||||
if (this.isInstalled) {
|
||||
this.uninstalling = true;
|
||||
// Simulate uninstallation delay (replace this with your WebSocket logic)
|
||||
this.onUninstall(this);
|
||||
} else {
|
||||
this.installing = true;
|
||||
this.onInstall(this);
|
||||
|
||||
}
|
||||
},
|
||||
handleSelection() {
|
||||
if (this.isInstalled && !this.selected) { // Only emit event if installed and not already selected
|
||||
if (this.isInstalled && !this.selected) {
|
||||
this.$emit('update:selected', true);
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,8 @@
|
||||
<div class="overflow-y-auto max-h-96 no-scrollbar p-2">
|
||||
<model-entry v-for="(model, index) in models" :key="index" :title="model.title" :icon="model.icon"
|
||||
:path="model.path" :description="model.description" :is-installed="model.isInstalled"
|
||||
:on-toggle-install="toggleInstall" />
|
||||
:on-install="onInstall"
|
||||
:on-uninstall="onUninstall" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -292,6 +293,7 @@ import { nextTick } from 'vue'
|
||||
import MessageBox from "@/components/MessageBox.vue";
|
||||
import YesNoDialog from "@/components/YesNoDialog.vue";
|
||||
import ModelEntry from '@/components/ModelEntry.vue';
|
||||
import { socket, state } from '@/services/websocket.js'
|
||||
axios.defaults.baseURL = import.meta.env.VITE_GPT4ALL_API_BASEURL
|
||||
export default {
|
||||
components: {
|
||||
@ -309,6 +311,8 @@ export default {
|
||||
data() {
|
||||
|
||||
return {
|
||||
// Websocket
|
||||
socket: socket,
|
||||
// Models zoo installer stuff
|
||||
models: [],
|
||||
// Accordeon stuff
|
||||
@ -340,18 +344,63 @@ export default {
|
||||
});
|
||||
},
|
||||
// Model installation
|
||||
toggleInstall(isInstalled, path) {
|
||||
const endpoint = isInstalled ? '/uninstall_model' : '/install_model';
|
||||
axios.post(endpoint, { path })
|
||||
.then((response) => {
|
||||
console.log(response.data.status);
|
||||
// Update the isInstalled property of the corresponding model
|
||||
const index = this.models.findIndex((model) => model.path === path);
|
||||
this.$set(this.models[index], 'isInstalled', isInstalled);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
onInstall(model_object) {
|
||||
let isInstalled = model_object.isInstalled
|
||||
let path = model_object.path
|
||||
this.showProgress = true;
|
||||
this.progress = 0;
|
||||
console.log("installing...")
|
||||
|
||||
const progressListener = (response) => {
|
||||
if (response.status === 'progress') {
|
||||
this.progress = message.progress;
|
||||
} else if (message.status === 'succeeded') {
|
||||
// Installation completed
|
||||
model_object.installing = false;
|
||||
this.showProgress = false;
|
||||
// Update the isInstalled property of the corresponding model
|
||||
const index = this.models.findIndex((model) => model.path === path);
|
||||
this.models[index].isInstalled = true;
|
||||
|
||||
this.socket.off('install_progress', progressListener);
|
||||
} else if (message.status === 'failed') {
|
||||
// Installation failed or encountered an error
|
||||
model_object.installing = false;
|
||||
this.showProgress = false;
|
||||
this.socket.off('install_progress', progressListener);
|
||||
console.error('Installation failed:', message.error);
|
||||
}
|
||||
};
|
||||
this.socket.on('install_progress', progressListener);
|
||||
this.socket.emit('install_model', { path: path });
|
||||
|
||||
|
||||
},
|
||||
onUninstall(model_object) {
|
||||
console.log("uninstalling model...")
|
||||
const progressListener = (response) => {
|
||||
if (response.status === 'progress') {
|
||||
this.progress = message.progress;
|
||||
} else if (message.status === 'succeeded') {
|
||||
// Installation completed
|
||||
model_object.uninstalling = false;
|
||||
|
||||
this.showProgress = false;
|
||||
// Update the isInstalled property of the corresponding model
|
||||
const index = this.models.findIndex((model) => model.path === path);
|
||||
this.models[index].isInstalled = false;
|
||||
|
||||
this.socket.off('install_progress', progressListener);
|
||||
} else if (message.status === 'failed') {
|
||||
// Installation failed or encountered an error
|
||||
model_object.uninstalling = false;
|
||||
this.showProgress = false;
|
||||
this.socket.off('install_progress', progressListener);
|
||||
console.error('Installation failed:', message.error);
|
||||
}
|
||||
};
|
||||
this.socket.on('install_progress', progressListener);
|
||||
this.socket.emit('uninstall_model', { path: model_object.path });
|
||||
},
|
||||
// messagebox ok stuff
|
||||
onMessageBoxOk() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user