This commit is contained in:
Saifeddine ALOUI 2023-12-08 01:00:22 +01:00
parent 2bb27eb420
commit e21d192f44
22 changed files with 4061 additions and 221 deletions

View File

@ -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
View File

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

File diff suppressed because one or more lines are too long

8
web/dist/assets/index-4ffd8c20.css vendored Normal file

File diff suppressed because one or more lines are too long

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>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
View File

@ -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",

View File

@ -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",

View File

@ -308,7 +308,7 @@ export default {
},
toggleSelected(force=false) {
this.onSelected(this,force)
model.selected = true;
this.model.selected = true;
nextTick(() => {
feather.replace()
})

View File

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

View File

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

View File

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

View File

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

View File

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

View 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>

View File

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