upgraded vue code

This commit is contained in:
ParisNeo 2023-05-11 21:36:52 +02:00
parent 2c565e8696
commit 325cd5b627
3 changed files with 176 additions and 55 deletions

110
app.py
View File

@ -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)

View File

@ -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);
}
}

View File

@ -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() {