mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2025-02-06 10:59:23 +00:00
Added model listing and install (WIP)
This commit is contained in:
parent
91eaf1c786
commit
38a136e72f
57
app.py
57
app.py
@ -38,6 +38,7 @@ from pathlib import Path
|
|||||||
import gc
|
import gc
|
||||||
from geventwebsocket.handler import WebSocketHandler
|
from geventwebsocket.handler import WebSocketHandler
|
||||||
from gevent.pywsgi import WSGIServer
|
from gevent.pywsgi import WSGIServer
|
||||||
|
import requests
|
||||||
|
|
||||||
app = Flask("GPT4All-WebUI", static_url_path="/static", static_folder="static")
|
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)
|
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(
|
self.add_endpoint(
|
||||||
"/get_config", "get_config", self.get_config, methods=["GET"]
|
"/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(
|
self.add_endpoint(
|
||||||
"/extensions", "extensions", self.extensions, methods=["GET"]
|
"/extensions", "extensions", self.extensions, methods=["GET"]
|
||||||
@ -687,6 +698,52 @@ class Gpt4AllWebUI(GPT4AllAPI):
|
|||||||
return jsonify({"status":"ok"})
|
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):
|
def get_config(self):
|
||||||
return jsonify(self.config)
|
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
4
web/dist/index.html
vendored
@ -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>GPT4All - WEBUI</title>
|
<title>GPT4All - WEBUI</title>
|
||||||
<script type="module" crossorigin src="/assets/index-9638e0a4.js"></script>
|
<script type="module" crossorigin src="/assets/index-79091f1a.js"></script>
|
||||||
<link rel="stylesheet" href="/assets/index-6cb502cf.css">
|
<link rel="stylesheet" href="/assets/index-7089b32c.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
39
web/src/components/ModelEntry.vue
Normal file
39
web/src/components/ModelEntry.vue
Normal 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>
|
||||||
|
|
@ -63,6 +63,18 @@
|
|||||||
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -279,11 +291,13 @@ import feather from 'feather-icons'
|
|||||||
import { nextTick } from 'vue'
|
import { nextTick } from 'vue'
|
||||||
import MessageBox from "@/components/MessageBox.vue";
|
import MessageBox from "@/components/MessageBox.vue";
|
||||||
import YesNoDialog from "@/components/YesNoDialog.vue";
|
import YesNoDialog from "@/components/YesNoDialog.vue";
|
||||||
|
import ModelEntry from '@/components/ModelEntry.vue';
|
||||||
axios.defaults.baseURL = import.meta.env.VITE_GPT4ALL_API_BASEURL
|
axios.defaults.baseURL = import.meta.env.VITE_GPT4ALL_API_BASEURL
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
MessageBox,
|
MessageBox,
|
||||||
YesNoDialog
|
YesNoDialog,
|
||||||
|
ModelEntry
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
|
|
||||||
@ -295,6 +309,8 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
// Models zoo installer stuff
|
||||||
|
models: [],
|
||||||
// Accordeon stuff
|
// Accordeon stuff
|
||||||
bec_collapsed: false,
|
bec_collapsed: false,
|
||||||
pc_collapsed: false,
|
pc_collapsed: false,
|
||||||
@ -310,7 +326,33 @@ export default {
|
|||||||
showConfirmation:false
|
showConfirmation:false
|
||||||
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.fetchModels();
|
||||||
}, methods: {
|
}, 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
|
// messagebox ok stuff
|
||||||
onMessageBoxOk() {
|
onMessageBoxOk() {
|
||||||
console.log("OK button clicked");
|
console.log("OK button clicked");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user