mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2024-12-18 20:17:50 +00:00
upgraded
This commit is contained in:
parent
2bb27eb420
commit
e21d192f44
@ -114,13 +114,13 @@ def parse_requirements_file(requirements_path):
|
||||
class LoLLMsAPI(LollmsApplication):
|
||||
def __init__(self, config:LOLLMSConfig, socketio, config_file_path:str, lollms_paths: LollmsPaths) -> None:
|
||||
|
||||
self.socketio = socketio
|
||||
super().__init__("Lollms_webui",config, lollms_paths, callback=self.process_chunk, notification_callback=self.notify)
|
||||
|
||||
|
||||
self.busy = False
|
||||
self.nb_received_tokens = 0
|
||||
|
||||
self.socketio = socketio
|
||||
self.config_file_path = config_file_path
|
||||
self.cancel_gen = False
|
||||
|
||||
@ -298,6 +298,10 @@ class LoLLMsAPI(LollmsApplication):
|
||||
else:
|
||||
filename = parts[4]
|
||||
installation_path = installation_dir / filename
|
||||
elif model_type=="gpt4all":
|
||||
filename = data["variant_name"]
|
||||
model_path = "http://gpt4all.io/models/gguf/"+filename
|
||||
installation_path = installation_dir / filename
|
||||
else:
|
||||
filename = Path(model_path).name
|
||||
installation_path = installation_dir / filename
|
||||
|
5
app.py
5
app.py
@ -382,6 +382,7 @@ try:
|
||||
|
||||
self.add_endpoint("/get_server_address", "get_server_address", self.get_server_address, methods=["GET"])
|
||||
|
||||
self.add_endpoint("/get_model_status", "get_model_status", self.get_model_status, methods=["GET"])
|
||||
|
||||
self.add_endpoint(
|
||||
"/delete_discussion",
|
||||
@ -501,7 +502,8 @@ try:
|
||||
"/open_code_folder", "open_code_folder", self.open_code_folder, methods=["POST"]
|
||||
)
|
||||
|
||||
|
||||
def get_model_status(self):
|
||||
return jsonify({"status":self.model is not None})
|
||||
|
||||
def get_server_address(self):
|
||||
server_address = request.host_url
|
||||
@ -958,6 +960,7 @@ try:
|
||||
for per in self.mounted_personalities:
|
||||
per.model = self.model
|
||||
except Exception as ex:
|
||||
trace_exception(ex)
|
||||
self.notify("It looks like you we couldn't load the model.\nThis can hapen when you don't have enough VRAM. Please restart the program.",False,30)
|
||||
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit dfb5470d8d63927de91d0589229712290e13a6e4
|
||||
Subproject commit 8b2b885e63a6a675fe34bb8c2d559cc7fd0ed61a
|
3836
web/dist/assets/index-2875d455.js
vendored
Normal file
3836
web/dist/assets/index-2875d455.js
vendored
Normal file
File diff suppressed because one or more lines are too long
8
web/dist/assets/index-4ffd8c20.css
vendored
Normal file
8
web/dist/assets/index-4ffd8c20.css
vendored
Normal file
File diff suppressed because one or more lines are too long
192
web/dist/assets/index-86f0c808.js
vendored
192
web/dist/assets/index-86f0c808.js
vendored
File diff suppressed because one or more lines are too long
8
web/dist/assets/index-cb75143a.css
vendored
8
web/dist/assets/index-cb75143a.css
vendored
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">
|
||||
<title>LoLLMS WebUI - Welcome</title>
|
||||
<script type="module" crossorigin src="/assets/index-86f0c808.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-cb75143a.css">
|
||||
<script type="module" crossorigin src="/assets/index-2875d455.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-4ffd8c20.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
18
web/package-lock.json
generated
18
web/package-lock.json
generated
@ -24,6 +24,7 @@
|
||||
"papaparse": "^5.4.1",
|
||||
"prismjs": "^1.29.0",
|
||||
"socket.io-client": "^4.6.1",
|
||||
"three": "^0.159.0",
|
||||
"vue": "^3.2.47",
|
||||
"vue-inline-svg": "^2.1.3",
|
||||
"vue-router": "^4.1.6",
|
||||
@ -1023,9 +1024,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz",
|
||||
"integrity": "sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==",
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz",
|
||||
"integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
"form-data": "^4.0.0",
|
||||
@ -3650,6 +3651,11 @@
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/three": {
|
||||
"version": "0.159.0",
|
||||
"resolved": "https://registry.npmjs.org/three/-/three-0.159.0.tgz",
|
||||
"integrity": "sha512-eCmhlLGbBgucuo4VEA9IO3Qpc7dh8Bd4VKzr7WfW4+8hMcIfoAVi1ev0pJYN9PTTsCslbcKgBwr2wNZ1EvLInA=="
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
@ -3760,9 +3766,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "4.4.11",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-4.4.11.tgz",
|
||||
"integrity": "sha512-ksNZJlkcU9b0lBwAGZGGaZHCMqHsc8OpgtoYhsQ4/I2v5cnpmmmqe5pM4nv/4Hn6G/2GhTdj0DhZh2e+Er1q5A==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz",
|
||||
"integrity": "sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.18.10",
|
||||
|
@ -26,6 +26,7 @@
|
||||
"papaparse": "^5.4.1",
|
||||
"prismjs": "^1.29.0",
|
||||
"socket.io-client": "^4.6.1",
|
||||
"three": "^0.159.0",
|
||||
"vue": "^3.2.47",
|
||||
"vue-inline-svg": "^2.1.3",
|
||||
"vue-router": "^4.1.6",
|
||||
|
@ -308,7 +308,7 @@ export default {
|
||||
},
|
||||
toggleSelected(force=false) {
|
||||
this.onSelected(this,force)
|
||||
model.selected = true;
|
||||
this.model.selected = true;
|
||||
nextTick(() => {
|
||||
feather.replace()
|
||||
})
|
||||
|
@ -5,6 +5,9 @@
|
||||
<RouterLink :to="{ name: 'discussions' }" class="link-item dark:link-item-dark">
|
||||
Discussions
|
||||
</RouterLink>
|
||||
<RouterLink :to="{ name: 'interactive' }" class="link-item dark:link-item-dark">
|
||||
Interactive
|
||||
</RouterLink>
|
||||
<RouterLink :to="{ name: 'playground' }" class="link-item dark:link-item-dark">
|
||||
Playground
|
||||
</RouterLink>
|
||||
|
@ -17,6 +17,12 @@
|
||||
<!-- GITHUB AND THEME BUTTONS -->
|
||||
<div class="flex gap-3 flex-1 items-center justify-end">
|
||||
|
||||
<div v-if="isModelOK" title="Model is ok" class="text-green-500">
|
||||
M
|
||||
</div>
|
||||
<div v-if="!isModelOK" title="Model is not ok" class="text-red-500">
|
||||
M
|
||||
</div>
|
||||
<div v-if="!isGenerating" title="Text is not being generated. Ready to generate" class="text-green-500">
|
||||
<i data-feather="flag"></i>
|
||||
</div>
|
||||
@ -89,6 +95,9 @@ import { mapState } from 'vuex';
|
||||
export default {
|
||||
name: 'TopBar',
|
||||
computed:{
|
||||
isModelOK(){
|
||||
return this.$store.state.isModelOk;
|
||||
},
|
||||
isGenerating(){
|
||||
return this.$store.state.isGenerating;
|
||||
},
|
||||
|
@ -30,6 +30,7 @@ export const store = createStore({
|
||||
version : "unknown",
|
||||
settingsChanged:false,
|
||||
isConnected: false, // Add the isConnected property
|
||||
isModelOk: false,
|
||||
isGenerating: false,
|
||||
config:null,
|
||||
mountedPers:null,
|
||||
@ -56,6 +57,9 @@ export const store = createStore({
|
||||
setIsConnected(state, isConnected) {
|
||||
state.isConnected = isConnected;
|
||||
},
|
||||
setIsModelOk(state, isModelOk) {
|
||||
state.isModelOk = isModelOk;
|
||||
},
|
||||
setIsGenerating(state, isGenerating) {
|
||||
state.isGenerating = isGenerating;
|
||||
},
|
||||
@ -115,6 +119,9 @@ export const store = createStore({
|
||||
getIsConnected(state) {
|
||||
return state.isConnected
|
||||
},
|
||||
getIsModelOk(state) {
|
||||
return state.isModelOk;
|
||||
},
|
||||
getIsGenerating(state) {
|
||||
return state.isGenerating
|
||||
},
|
||||
@ -313,6 +320,10 @@ export const store = createStore({
|
||||
const response = await axios.get('/get_available_models');
|
||||
commit('setModelsZoo',response.data.filter(model => model.variants && model.variants.length>0))
|
||||
},
|
||||
async refreshModelStatus({ commit }) {
|
||||
let modelstatus = await api_get_req("get_model_status");
|
||||
commit('setIsModelOk',modelstatus["status"])
|
||||
},
|
||||
async refreshModels({ commit }) {
|
||||
console.log("Fetching models")
|
||||
let modelsArr = await api_get_req("list_models");
|
||||
@ -323,6 +334,7 @@ export const store = createStore({
|
||||
commit('setselectedModel',selectedModel["model"])
|
||||
}
|
||||
commit('setModelsArr',modelsArr)
|
||||
console.log("setModelsArr",modelsArr)
|
||||
this.state.modelsZoo.map((item)=>{
|
||||
item.isInstalled=modelsArr.includes(item.name)
|
||||
})
|
||||
@ -520,6 +532,8 @@ app.mixin({
|
||||
this.$store.state.loading_infos = "Getting active models"
|
||||
this.$store.state.loading_progress = 100
|
||||
await this.$store.dispatch('refreshModels');
|
||||
await this.$store.dispatch('refreshModelStatus');
|
||||
|
||||
|
||||
this.$store.state.ready = true;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import SettingsView from '../views/SettingsView.vue'
|
||||
import TrainingView from '../views/TrainingView.vue'
|
||||
import QuantizingView from '../views/QuantizingView.vue'
|
||||
import DiscussionsView from '../views/DiscussionsView.vue'
|
||||
import InteractiveView from '../views/InteractiveView.vue'
|
||||
|
||||
|
||||
const router = createRouter({
|
||||
@ -46,6 +47,11 @@ const router = createRouter({
|
||||
name: 'discussions',
|
||||
component: DiscussionsView
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
name: 'interactive',
|
||||
component: InteractiveView
|
||||
},
|
||||
|
||||
],
|
||||
// scrollBehavior
|
||||
|
@ -1992,6 +1992,14 @@ export default {
|
||||
return this.$store.state.loading_progress;
|
||||
}
|
||||
},
|
||||
isModelOk:{
|
||||
get(){
|
||||
return this.$store.state.isModelOk;
|
||||
},
|
||||
set(val){
|
||||
this.$store.state.isModelOk=val
|
||||
}
|
||||
},
|
||||
isGenerating:{
|
||||
get(){
|
||||
return this.$store.state.isGenerating;
|
||||
|
136
web/src/views/InteractiveView.vue
Normal file
136
web/src/views/InteractiveView.vue
Normal file
@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<div ref="webglContainer">
|
||||
<div v-if="!personality.scene_path && (!personality.avatar || personality.avatar === '')">
|
||||
<!-- Display text when there's no scene_path or empty avatar -->
|
||||
Personality does not have an avatar.
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as THREE from 'three';
|
||||
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
|
||||
import { TextureLoader } from 'three';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
personality: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isReady:{
|
||||
get() {
|
||||
return this.$store.state.ready;
|
||||
},
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'$store.state.mountedPersArr': 'updatePersonality',
|
||||
'$store.state.config.active_personality_id': 'updatePersonality',
|
||||
},
|
||||
async mounted() {
|
||||
while (this.isReady === false) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 100)); // Wait for 100ms
|
||||
}
|
||||
console.log("ready")
|
||||
this.updatePersonality();
|
||||
this.initWebGLScene();
|
||||
},
|
||||
beforeDestroy() {
|
||||
// Clean up WebGL resources here
|
||||
},
|
||||
methods: {
|
||||
initWebGLScene() {
|
||||
// Set up your Three.js scene here
|
||||
this.scene = new THREE.Scene();
|
||||
this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
|
||||
this.renderer = new THREE.WebGLRenderer();
|
||||
this.renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
this.$refs.webglContainer.appendChild(this.renderer.domElement);
|
||||
|
||||
// Example: Add a cube to the scene
|
||||
const geometry = new THREE.BoxGeometry();
|
||||
const material = new THREE.MeshPhongMaterial({ color: 0x00ff00 }); // Phong material for better shading
|
||||
this.cube = new THREE.Mesh(geometry, material);
|
||||
this.scene.add(this.cube);
|
||||
|
||||
// Add lights
|
||||
const ambientLight = new THREE.AmbientLight(0x404040); // Ambient light
|
||||
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); // Directional light
|
||||
directionalLight.position.set(0, 1, 0); // Set light direction
|
||||
this.scene.add(ambientLight);
|
||||
this.scene.add(directionalLight);
|
||||
|
||||
this.camera.position.z = 5;
|
||||
|
||||
// Animation loop
|
||||
this.animate();
|
||||
},
|
||||
updatePersonality() {
|
||||
const { mountedPersArr, config } = this.$store.state;
|
||||
|
||||
// Get the active personality based on active_personality_id
|
||||
const activePersonality = mountedPersArr[config.active_personality_id];
|
||||
console.log("activePersonality:",activePersonality)
|
||||
|
||||
|
||||
// Update the personality property
|
||||
this.$emit('update:personality', activePersonality);
|
||||
},
|
||||
loadScene(scenePath) {
|
||||
const loader = new GLTFLoader();
|
||||
loader.load(scenePath, (gltf) => {
|
||||
// Remove existing cube
|
||||
this.scene.remove(this.cube);
|
||||
|
||||
// Add loaded model to the scene
|
||||
this.cube = gltf.scene;
|
||||
this.scene.add(this.cube);
|
||||
});
|
||||
},
|
||||
showBoxWithAvatar(avatarUrl) {
|
||||
// Remove existing cube
|
||||
this.scene.remove(this.cube);
|
||||
|
||||
// Create a box with avatar texture
|
||||
const geometry = new THREE.BoxGeometry();
|
||||
const texture = new TextureLoader().load(avatarUrl);
|
||||
const material = new THREE.MeshBasicMaterial({ map: texture });
|
||||
this.cube = new THREE.Mesh(geometry, material);
|
||||
this.scene.add(this.cube);
|
||||
},
|
||||
showDefaultCube() {
|
||||
// Remove existing cube
|
||||
this.scene.remove(this.cube);
|
||||
|
||||
// Create a default cube
|
||||
const geometry = new THREE.BoxGeometry();
|
||||
const material = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
|
||||
this.cube = new THREE.Mesh(geometry, material);
|
||||
this.scene.add(this.cube);
|
||||
},
|
||||
animate() {
|
||||
requestAnimationFrame(this.animate);
|
||||
|
||||
// Rotate the cube
|
||||
if (this.cube) {
|
||||
this.cube.rotation.x += 0.01;
|
||||
this.cube.rotation.y += 0.01;
|
||||
}
|
||||
|
||||
this.renderer.render(this.scene, this.camera);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#webglContainer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
</style>
|
||||
|
@ -838,7 +838,7 @@
|
||||
<TransitionGroup name="list">
|
||||
<BindingEntry ref="bindingZoo" v-for="(binding, index) in bindingsZoo"
|
||||
:key="'index-' + index + '-' + binding.folder" :binding="binding"
|
||||
:on-selected="onSelectedBinding" :on-reinstall="onReinstallBinding"
|
||||
:on-selected="onBindingSelected" :on-reinstall="onReinstallBinding"
|
||||
:on-unInstall="onUnInstallBinding"
|
||||
:on-install="onInstallBinding" :on-settings="onSettingsBinding"
|
||||
:on-reload-binding="onReloadBinding"
|
||||
@ -987,7 +987,7 @@
|
||||
:key="'index-' + index + '-' + model.name"
|
||||
:model="model"
|
||||
:is-installed="model.isInstalled" :on-install="onInstall"
|
||||
:on-uninstall="onUninstall" :on-selected="onSelected"
|
||||
:on-uninstall="onUninstall" :on-selected="onModelSelected"
|
||||
:selected="model.name === configFile.model_name"
|
||||
:model_type="model.model_type" :on-copy="onCopy" :on-copy-link="onCopyLink"
|
||||
:on-cancel-install="onCancelInstall" />
|
||||
@ -2023,7 +2023,7 @@ export default {
|
||||
socket.on('install_progress', progressListener);
|
||||
|
||||
|
||||
socket.emit('install_model', { path: path, type:model_object.model.type });
|
||||
socket.emit('install_model', { path: path, name: model_object.model.name, variant_name:this.selected_variant.name, type:model_object.model.type });
|
||||
console.log("Started installation, please wait");
|
||||
},
|
||||
|
||||
@ -2359,7 +2359,7 @@ export default {
|
||||
}
|
||||
|
||||
},
|
||||
onSelected(model_object, force=false) {
|
||||
onModelSelected(model_object, force=false) {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
if (this.isLoading) {
|
||||
this.$refs.toast.showToast("Loading... please wait", 4, false)
|
||||
@ -2378,6 +2378,9 @@ export default {
|
||||
this.is_loading_zoo = false
|
||||
})
|
||||
self.updateModelsZoo()
|
||||
api_get_req("get_model_status").then((res)=>{
|
||||
this.$store.commit('setIsModelOk', res);
|
||||
})
|
||||
}else{
|
||||
this.$refs.toast.showToast("Couldn't select model:\n" + model_object.name, 4, false)
|
||||
nextTick(() => {
|
||||
@ -2614,7 +2617,7 @@ export default {
|
||||
|
||||
})
|
||||
},
|
||||
onSelectedBinding(binding_object) {
|
||||
onBindingSelected(binding_object) {
|
||||
console.log("Binding selected")
|
||||
if (!binding_object.binding.installed) {
|
||||
this.$refs.toast.showToast("Binding is not installed:\n" + binding_object.binding.name, 4, false)
|
||||
@ -2625,6 +2628,9 @@ export default {
|
||||
this.update_binding(binding_object.binding.folder)
|
||||
this.binding_changed = true;
|
||||
}
|
||||
api_get_req("get_model_status").then((res)=>{
|
||||
this.$store.commit('setIsModelOk', res);
|
||||
})
|
||||
},
|
||||
onInstallBinding(binding_object) {
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 3a251d29f9939f4693a4282f7e97d98fa740ebee
|
||||
Subproject commit 968874a56a744ecbf96f27647e534f631a0acd15
|
@ -1 +1 @@
|
||||
Subproject commit 23e4c917ec9d3d315aa8b15eb05c761febe8df12
|
||||
Subproject commit 8c808362ec7a45075e0829c6b4a34e1839a11744
|
@ -1 +1 @@
|
||||
Subproject commit fd7026e66aa53ccefd84c1d48d1e9816ee5db6bc
|
||||
Subproject commit cf08de77a73d737584a979a61652878134d7ce0b
|
@ -1 +1 @@
|
||||
Subproject commit ff554d12a41043e119f787d7cbba4f69fcc619f5
|
||||
Subproject commit 3a686417015113168c7dcb3fdd9943347d4088de
|
Loading…
Reference in New Issue
Block a user