Added model listing and install (WIP)

This commit is contained in:
saloui 2023-05-10 23:33:08 +02:00
parent 91eaf1c786
commit 38a136e72f
6 changed files with 149 additions and 11 deletions

57
app.py
View File

@ -38,6 +38,7 @@ from pathlib import Path
import gc
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
import requests
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)
@ -155,6 +156,16 @@ class Gpt4AllWebUI(GPT4AllAPI):
self.add_endpoint(
"/get_config", "get_config", self.get_config, methods=["GET"]
)
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"]
@ -687,6 +698,52 @@ class Gpt4AllWebUI(GPT4AllAPI):
return jsonify({"status":"ok"})
def get_available_models(self):
response = requests.get(f' https://gpt4all.io/models/models.json')
model_list = response.json()
models = []
for model in model_list:
filename = model['filename']
filesize = model['filesize']
path = f'https://gpt4all.io/models/{filename}'
is_installed = Path(f'/models.llamacpp/{filename}').is_file()
models.append({
'title': model['filename'],
'icon': '/icons/default.png', # Replace with the path to the model icon
'description': model['description'],
'isInstalled': is_installed,
'path': path,
'filesize': filesize,
})
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)

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">
<title>GPT4All - WEBUI</title>
<script type="module" crossorigin src="/assets/index-9638e0a4.js"></script>
<link rel="stylesheet" href="/assets/index-6cb502cf.css">
<script type="module" crossorigin src="/assets/index-79091f1a.js"></script>
<link rel="stylesheet" href="/assets/index-7089b32c.css">
</head>
<body>
<div id="app"></div>

View File

@ -0,0 +1,39 @@
<template>
<div class="flex items-center space-x-4 py-4">
<div class="flex-shrink-0">
<i :class="`fas ${icon} text-xl`"></i>
</div>
<div class="flex-1">
<h3 class="font-bold text-lg">{{ title }}</h3>
<p class="text-gray-600">{{ description }}</p>
</div>
<div class="flex-shrink-0">
<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']"
@click="toggleInstall"
>
{{ isInstalled ? 'Uninstall' : 'Install' }}
</button>
</div>
</div>
</template>
<script>
export default {
props: {
title: String,
icon: String,
path: String,
description: String,
isInstalled: Boolean,
onToggleInstall: Function,
},
methods: {
toggleInstall() {
this.onToggleInstall(this.isInstalled, this.path);
},
},
};
</script>

View File

@ -63,6 +63,18 @@
</select>
</div>
<div class="space-y-4">
<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"
/>
</div>
</div>
</div>
@ -279,11 +291,13 @@ import feather from 'feather-icons'
import { nextTick } from 'vue'
import MessageBox from "@/components/MessageBox.vue";
import YesNoDialog from "@/components/YesNoDialog.vue";
import ModelEntry from '@/components/ModelEntry.vue';
axios.defaults.baseURL = import.meta.env.VITE_GPT4ALL_API_BASEURL
export default {
components: {
MessageBox,
YesNoDialog
YesNoDialog,
ModelEntry
},
setup() {
@ -295,6 +309,8 @@ export default {
data() {
return {
// Models zoo installer stuff
models: [],
// Accordeon stuff
bec_collapsed: false,
pc_collapsed: false,
@ -310,7 +326,33 @@ export default {
showConfirmation:false
}
},
created() {
this.fetchModels();
}, methods: {
fetchModels() {
axios.get('/get_available_models')
.then(response => {
this.models = response.data;
})
.catch(error => {
console.log(error);
});
},
// 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);
});
},
// messagebox ok stuff
onMessageBoxOk() {
console.log("OK button clicked");