Merge pull request #290 from andzejsp/lollms-patchy

Lollms patchy
This commit is contained in:
Saifeddine ALOUI 2023-06-14 17:27:36 +02:00 committed by GitHub
commit f29968ba33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 282 additions and 150 deletions

14
web/package-lock.json generated
View File

@ -18,7 +18,8 @@
"papaparse": "^5.4.1",
"socket.io-client": "^4.6.1",
"vue": "^3.2.47",
"vue-router": "^4.1.6"
"vue-router": "^4.1.6",
"vuex": "^4.0.2"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.2.0",
@ -3187,6 +3188,17 @@
"vue": "^3.2.0"
}
},
"node_modules/vuex": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz",
"integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==",
"dependencies": {
"@vue/devtools-api": "^6.0.0-beta.11"
},
"peerDependencies": {
"vue": "^3.0.2"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@ -20,7 +20,8 @@
"papaparse": "^5.4.1",
"socket.io-client": "^4.6.1",
"vue": "^3.2.47",
"vue-router": "^4.1.6"
"vue-router": "^4.1.6",
"vuex": "^4.0.2"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.2.0",

View File

@ -22,7 +22,7 @@
{{isMounted ? 'Unmount':'Mount'}}
<span
class="inline-flex items-center justify-center w-4 h-4 ml-2 text-xs font-semibold text-blue-800 bg-blue-200 rounded-full">
<input disabled id="default-checkbox" type="checkbox" v-model="isMounted" @change.stop="toggleMounted"
<input disabled id="default-checkbox" type="checkbox" v-model="isMounted"
class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
</span>
</button>
@ -78,11 +78,13 @@ export default {
onSelected: Function,
selected: Boolean,
onMounted: Function,
full_path:String
},
data() {
return {
isMounted: false
isMounted: false,
name:this.personality.name
};
},
mounted() {

View File

@ -1,11 +1,12 @@
<template>
<div class="absolute bottom-16 right-2 z-20 flex flex-col gap-3 min-w-[300px]">
<TransitionGroup name="toastItem" tag="div">
<div v-for=" t in toastArr" :key="t.id">
<div v-for=" t in toastArr" :key="t.id" class="relative">
<div class="flex items-center w-full max-w-xs p-4 mb-4 text-gray-500 bg-white rounded-lg shadow dark:text-gray-400 dark:bg-gray-800"
role="alert">
<div class="flex flex-row items-center">
<slot>
<div v-if="t.success"
class="inline-flex items-center justify-center flex-shrink-0 w-8 h-8 text-green-500 bg-green-100 rounded-lg dark:bg-green-800 dark:text-green-200">
<i data-feather="check"></i>
@ -20,8 +21,17 @@
</slot>
</div>
<div class="absolute top-2 right-2">
<button type="button" @click.stop="t.copy(t.message)"
class=" bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700">
<span class="sr-only">Copy message</span>
<i data-feather="clipboard" class="w-5 h-5"></i>
</button>
<button type="button" @click="close(t.id)"
class="ml-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700">
class=" bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700">
<span class="sr-only">Close</span>
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
@ -30,6 +40,7 @@
clip-rule="evenodd"></path>
</svg>
</button>
</div>
</div>
</div>
@ -58,6 +69,35 @@ export default {
close(id) {
this.toastArr = this.toastArr.filter(item => item.id != id)
},
copyToClipBoard(content) {
// const id = parseInt(((new Date()).getTime() * Math.random()).toString()).toString()
// const toastObj = {
// id: id,
// success: true,
// message: "Copied to clipboard successfully",
// show: true,
// copy: this.copyToClipBoard(this.message)
// }
navigator.clipboard.writeText(content);
// this.toastArr.push(toastObj)
nextTick(() => {
feather.replace()
})
// setTimeout(() => {
// this.toastArr = this.toastArr.filter(item => item.id != id)
// }, duration_s * 1000);
},
showToast(message, duration_s = 3, success = true) {
const id = parseInt(((new Date()).getTime() * Math.random()).toString()).toString()
@ -65,7 +105,8 @@ export default {
id: id,
success: success,
message: message,
show: true
show: true,
copy: this.copyToClipBoard(message)
}

View File

@ -1,4 +1,5 @@
import { createApp } from 'vue'
import { createApp, ref } from 'vue'
import { createStore } from 'vuex'
import App from './App.vue'
import router from './router'
@ -6,6 +7,23 @@ import './assets/tailwind.css'
const app = createApp(App)
// Create a new store instance.
const store = createStore({
state () {
return {
count: 0,
mountedPersonalities: {}
}
},
mutations: {
increment (state) {
state.count++
}
}
})
app.use(router)
app.use(store)
app.mount('#app')

View File

@ -1151,6 +1151,7 @@ export default {
},
async activated() {
console.log('settings changed',this.$store.state.mountedPersonalities)
// This lifecycle hook runs every time you switch from other page back to this page (vue-router)
// To fix scrolling back to last message, this hook is needed.
// If anyone knows hor to fix scroll issue when changing pages, please do fix it :D

View File

@ -226,7 +226,8 @@
<div v-if="configFile.model_name" class="mr-2">|</div>
<div v-if="configFile.model_name" class="text-base font-semibold cursor-pointer select-none items-center">
<div v-if="configFile.model_name"
class="text-base font-semibold cursor-pointer select-none items-center">
<div class="flex gap-1 items-center">
<img :src="imgModel" class="w-8 h-8 rounded-lg object-fill">
<h3 class="font-bold font-large text-lg line-clamp-1">
@ -329,20 +330,19 @@
<div v-if="configFile.personalities" class="mr-2">|</div>
<!-- LIST OF MOUNTED PERSONALITIES -->
<div v-if="configFile.personalities"
class=" text-base font-semibold cursor-pointer select-none items-center ">
class=" text-base font-semibold cursor-pointer select-none items-center flex flex-row">
<!-- LIST -->
<div class="flex -space-x-4 items-center " v-if="mountedPersArr.length > 0" >
<!-- ITEM -->
<div class="relative hover:-translate-y-2 duration-300 hover:z-10 shrink-0 "
v-for="(item, index) in mountedPersArr" :key="index + '-' + item.name">
<div class="group ">
v-for="(item, index) in mountedPersArr" :key="index + '-' + item.name" ref="mountedPersonalities">
<div class="group items-center flex flex-row">
<button @click.stop="onPersonalitySelected(item)">
<img :src="item.$refs.imgElement.src"
<img :src="bUrl + item.avatar" @error="personalityImgPlacehodler"
class="w-8 h-8 rounded-full object-fill text-red-700 border-2 active:scale-90 group-hover:border-secondary "
:class="item.selected ? 'border-secondary':'border-transparent z-0'"
:title="item.personality.name"
>
:class="configFile.active_personality_id == configFile.personalities.indexOf(item.full_path) ? 'border-secondary' : 'border-transparent z-0'"
:title="item.name">
</button>
<button @click.stop="onPersonalityMounted(item)">
@ -351,7 +351,8 @@
title="Unmount personality">
<!-- UNMOUNT BUTTON -->
<svg aria-hidden="true" class="w-4 h-4 text-red-600 hover:text-red-500 "
fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
fill="currentColor" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd"
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
clip-rule="evenodd"></path>
@ -389,7 +390,8 @@
<select id="persCat" @change="update_setting('personality_category', $event.target.value, refresh)"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
<option v-for="item in persCatgArr" :selected="item === this.configFile.personality_category">{{
<option v-for="(item, index) in persCatgArr" :key="index"
:selected="item == this.configFile.personality_category">{{
item
}}
@ -419,6 +421,7 @@
<TransitionGroup name="bounce">
<personality-entry ref="personalitiesZoo" v-for="(pers, index) in personalitiesFiltered"
:key="'index-' + index + '-' + pers.name" :personality="pers"
:full_path="pers.full_path"
:selected="configFile.active_personality_id == configFile.personalities.findIndex(item => item === pers.full_path)"
:on-selected="onPersonalitySelected" :on-mounted="onPersonalityMounted" />
</TransitionGroup>
@ -604,7 +607,7 @@
</div>
</div>
</div>
<!-- sdasdas -->
</div>
</div>
</div>
@ -691,6 +694,7 @@ import defaultModelImgPlaceholder from "../assets/default_model.png"
import defaultPersonalityImgPlaceholder from "../assets/logo.svg"
import AddModelDialog from "@/components/AddModelDialog.vue";
const bUrl = import.meta.env.VITE_GPT4ALL_API_BASEURL
axios.defaults.baseURL = import.meta.env.VITE_GPT4ALL_API_BASEURL
export default {
components: {
@ -746,8 +750,8 @@ export default {
diskUsage: {},
ramUsage: {},
mountedPersArr: [],
isMounted: false // Needed to wait for $refs to be rendered
isMounted: false, // Needed to wait for $refs to be rendered
bUrl: bUrl // for personality images
}
},
@ -789,6 +793,7 @@ export default {
.then(response => {
this.models = response.data;
this.models.sort((a, b) => a.title.localeCompare(b.title))
this.fetchCustomModels()
})
.catch(error => {
@ -821,12 +826,14 @@ export default {
});
},
async onPersonalitySelected(pers) {
console.log('on pers', pers)
// eslint-disable-next-line no-unused-vars
if (this.isLoading) {
this.$refs.toast.showToast("Loading... please wait", 4, false)
}
if (pers.personality) {
this.isLoading=true
console.log('ppa',pers)
if (pers) {
if (pers.selected) {
this.$refs.toast.showToast("Personality already selected", 4, true)
@ -841,7 +848,7 @@ export default {
const res = await this.select_personality(pers)
if (res.status) {
this.$refs.toast.showToast("Selected personality:\n" + pers.personality.name, 4, true)
this.$refs.toast.showToast("Selected personality:\n" + pers.name, 4, true)
}
@ -851,28 +858,11 @@ export default {
}
// const res = this.update_setting('personality_folder', pers.personality.folder, () => {
// this.$refs.toast.showToast("Selected personality:\n" + pers.personality.name, 4, true)
// console.log('selecting', pers)
// //this.mountPersonality(pers)
// this.onPersonalityMounted(pers)
// //this.configFile.personalities[configFile.active_personality_id] = pers.personality.language + "/" + pers.personality.category + "/" + pers.personality.name
// if (!pers.isMounted) {
// // }else{
// // console.log('elsing')
// // this.refresh()
// }
// })
nextTick(() => {
feather.replace()
})
this.isLoading=false
}
},
@ -1035,15 +1025,24 @@ export default {
refresh() {
// No need to refresh all lists because they never change during using application.
// On settings change only config file chnages.
//
//this.api_get_req("list_bindings").then(response => { this.bindingsArr = response })
this.api_get_req("list_models").then(response => { this.modelsArr = response })
//this.api_get_req("list_personalities_languages").then(response => { this.persLangArr = response })
this.api_get_req("list_personalities_categories").then(response => { this.persCatgArr = response })
//this.api_get_req("list_languages").then(response => { this.langArr = response })
this.api_get_req("list_models").then(response => {
this.modelsArr = response
this.modelsArr.sort()
})
this.api_get_req("list_personalities_categories").then(response => {
this.persCatgArr = response
this.persCatgArr.sort()
})
this.api_get_req("get_config").then(response => {
this.getPersonalitiesArr().then(() => {
this.getMountedPersonalities()
})
console.log("Received config")
this.configFile = response
@ -1057,27 +1056,33 @@ export default {
model.selected = false;
}
});
})
}).then(() => {
this.api_get_req("get_current_personality_path_infos").then(response => {
this.configFile.personality_language = response["personality_language"]
this.configFile.personality_category = response["personality_category"]
this.configFile.personality_folder = response["personality_name"]
console.log("received infos")
});
})
this.api_get_req("list_personalities").then(response => {
this.persArr = response
this.persArr.sort()
console.log(`Listed personalities:\n${response}`)
})
this.api_get_req("disk_usage").then(response => {
this.diskUsage = response
})
this.api_get_req("ram_usage").then(response => {
this.ramUsage = response
})
//console.log('ram',this.ramUsage)
this.getPersonalitiesArr()
this.fetchModels();
this.getMountedPersonalities()
},
// Accordeon stuff
toggleAccordion() {
@ -1251,7 +1256,7 @@ export default {
const personalitiesArray = catdictionary[catkey];
const modPersArr = personalitiesArray.map((item) => {
const isMounted = config.personalities.includes(langkey + '/' + catkey + '/' + item.name)
const isMounted = config.personalities.includes(langkey + '/' + catkey + '/' + item.folder)
// if (isMounted) {
// console.log(item)
// }
@ -1259,7 +1264,7 @@ export default {
newItem = item
newItem.category = catkey // add new props to items
newItem.language = langkey // add new props to items
newItem.full_path = langkey + '/' + catkey + '/' + item.name // add new props to items
newItem.full_path = langkey + '/' + catkey + '/' + item.folder // add new props to items
newItem.isMounted = isMounted // add new props to items
return newItem
})
@ -1273,13 +1278,10 @@ export default {
}
}
// console.log(this.configFile)
// console.log(this.configFile.personality_category)
// console.log(this.configFile.personality_language)
// console.log("Personalities")
//console.log(this.personalities)
this.personalities.sort((a, b) => a.name.localeCompare(b.name))
this.personalitiesFiltered = this.personalities.filter((item) => item.category === this.configFile.personality_category && item.language === this.configFile.personality_language)
//console.log(`Personalities filtered ${this.personalitiesFiltered}`)
this.personalitiesFiltered.sort()
this.isLoading = false
@ -1290,7 +1292,6 @@ export default {
async mount_personality(pers) {
if (!pers) { return { 'status': false, 'error': 'no personality - mount_personality' } }
try {
const obj = {
language: pers.language,
@ -1315,12 +1316,12 @@ export default {
},
async unmount_personality(pers) {
if (!pers) { return { 'status': false, 'jig': 'no personality - unmount_personality' } }
if (!pers) { return { 'status': false, 'error': 'no personality - unmount_personality' } }
const obj = {
language: pers.language,
category: pers.category,
name: pers.name
folder: pers.folder
}
@ -1339,9 +1340,9 @@ export default {
},
async select_personality(pers) {
if (!pers) { return { 'status': false, 'jig': 'no personality - select_personality' } }
if (!pers) { return { 'status': false, 'error': 'no personality - select_personality' } }
console.log('select pers', pers)
const id = this.configFile.personalities.findIndex(item=> item === pers.personality.full_path)
const id = this.configFile.personalities.findIndex(item => item === pers.full_path)
const obj = {
id: id
@ -1353,6 +1354,10 @@ export default {
if (res) {
this.configFile = await this.api_get_req("get_config")
let personality_path_infos = await this.api_get_req("get_current_personality_path_infos")
this.configFile.personality_language = personality_path_infos["personality_language"]
this.configFile.personality_category = personality_path_infos["personality_category"]
this.configFile.personality_folder = personality_path_infos["personality_name"]
return res.data
}
@ -1363,6 +1368,7 @@ export default {
},
async mountPersonality(pers) {
this.isLoading=true
console.log('mount pers', pers)
if (!pers) { return }
@ -1379,7 +1385,7 @@ export default {
this.$refs.toast.showToast("Personality mounted", 4, true)
pers.isMounted = true
const res2 = await this.select_personality(pers)
const res2 = await this.select_personality(pers.personality)
if (res2.status) {
this.$refs.toast.showToast("Selected personality:\n" + pers.personality.name, 4, true)
@ -1389,26 +1395,46 @@ export default {
pers.isMounted = false
this.$refs.toast.showToast("Could not mount personality\nError: " + res.error, 4, false)
}
this.isLoading=false
},
async unmountPersonality(pers) {
this.isLoading=true
if (!pers) { return }
const res = await this.unmount_personality(pers.personality)
const res = await this.unmount_personality(pers.personality || pers)
if (res.status) {
this.configFile.personalities = res.personalities
this.$refs.toast.showToast("Personality unmounted", 4, true)
pers.isMounted = false
const persId = this.personalities.findIndex(item => item.full_path == pers.full_path)
const persFilteredId = this.personalitiesFiltered.findIndex(item => item.full_path == pers.full_path)
const persIdZoo = this.$refs.personalitiesZoo.findIndex(item => item.full_path == pers.full_path)
console.log('ppp', this.personalities[persId])
this.personalities[persId].isMounted = false
if (persFilteredId > -1) {
this.personalitiesFiltered[persFilteredId].isMounted = false
}
if (persIdZoo > -1) {
this.$refs.personalitiesZoo[persIdZoo].isMounted = false
}
//pers.isMounted = false
this.getMountedPersonalities()
// Select some other personality
const lastPers = this.mountedPersArr[this.mountedPersArr.length - 1]
console.log(lastPers, this.mountedPersArr.length)
const res2 = await this.select_personality(lastPers)
const res2 = await this.select_personality(lastPers.personality)
if (res2.status) {
this.$refs.toast.showToast("Selected personality:\n" + lastPers.personality.name, 4, true)
this.$refs.toast.showToast("Selected personality:\n" + lastPers.name, 4, true)
}
@ -1417,7 +1443,7 @@ export default {
this.$refs.toast.showToast("Could not unmount personality\nError: " + res.error, 4, false)
}
this.isLoading=false
},
getMountedPersonalities() {
@ -1426,11 +1452,11 @@ export default {
for (let i = 0; i < this.configFile.personalities.length; i++) {
const full_path_item = this.configFile.personalities[i]
const index = this.$refs.personalitiesZoo.findIndex(item => item.personality.full_path == full_path_item)
//console.log('perrs listo',this.personalities)
const index = this.personalities.findIndex(item => item.full_path == full_path_item)
if (index) {
const pers = this.$refs.personalitiesZoo[index]
const pers = this.personalities[index]
if (pers) {
mountedPersArr.push(pers)
@ -1442,14 +1468,19 @@ export default {
this.mountedPersArr = []
this.mountedPersArr = mountedPersArr
//this.mountedPersArr = mountedPersArr
console.log('getMountedPersonalities', mountedPersArr.length)
console.log('getMountedPersonalities', mountedPersArr)
console.log('fig', this.configFile.personality_category)
nextTick(()=>{
console.log('accc',this.$refs.mountedPersonalities)
this.$store.state.mountedPersonalities = this.$refs.mountedPersonalities
})
},
onPersonalityMounted(persItem) {
this.isLoading=true
console.log('on sel ', persItem)
if (this.configFile.personalities.includes(persItem.personality.full_path)) {
if (this.configFile.personalities.includes(persItem.full_path)) {
//this.$refs.toast.showToast("Personality already mounted", 4, false)
//return
//persItem.ismounted = false
@ -1466,16 +1497,22 @@ export default {
}
}
this.isLoading=true
},
personalityImgPlacehodler(event) {
event.target.src = defaultPersonalityImgPlaceholder
},
}, async mounted() {
//this.$refs.mountedPersonalities
this.isLoading = true
nextTick(() => {
feather.replace()
})
this.configFile = await this.api_get_req("get_config")
let personality_path_infos = await this.api_get_req("get_current_personality_path_infos")
this.configFile.personality_language = personality_path_infos["personality_language"]
@ -1488,21 +1525,39 @@ export default {
}
this.fetchModels();
this.bindingsArr = await this.api_get_req("list_bindings")
this.modelsArr = await this.api_get_req("list_models")
this.persLangArr = await this.api_get_req("list_personalities_languages")
this.persCatgArr = await this.api_get_req("list_personalities_categories")
this.persArr = await this.api_get_req("list_personalities")
this.langArr = await this.api_get_req("list_languages")
this.bindingsArr.sort((a, b) => a.name.localeCompare(b.name))
this.modelsArr.sort()
this.persLangArr.sort()
this.persCatgArr.sort()
this.persArr.sort()
this.langArr.sort()
await this.getPersonalitiesArr()
this.bindings = await this.api_get_req("list_bindings")
this.bindings.sort((a, b) => a.name.localeCompare(b.name))
this.isLoading = false
this.diskUsage = await this.api_get_req("disk_usage")
this.ramUsage = await this.api_get_req("ram_usage")
this.isMounted = true
this.getMountedPersonalities()
this.isMounted = true
},
activated(){
// console.log('accc',this.$refs.mountedPersonalities)
// this.$store.state.mountedPersonalities = this.$refs.mountedPersonalities
},
computed: {
disk_available_space() {
@ -1555,17 +1610,17 @@ export default {
return defaultModelImgPlaceholder
}
},
imgPersonality() {
if (!this.isMounted) {
return
}
try {
return this.$refs.personalitiesZoo[this.$refs.personalitiesZoo.findIndex(item => item.personality.folder == this.configFile.personality_folder)].$refs.imgElement.src
}
catch (error) {
return defaultPersonalityImgPlaceholder
}
},
// imgPersonality() {
// if (!this.isMounted) {
// return
// }
// try {
// return this.$refs.personalitiesZoo[this.$refs.personalitiesZoo.findIndex(item => item.personality.folder == this.configFile.personality_folder)].$refs.imgElement.src
// }
// catch (error) {
// return defaultPersonalityImgPlaceholder
// }
// },
},
@ -1629,7 +1684,9 @@ export default {
})
},
settingsChanged() {
settingsChanged(val) {
//this.$store.settingsChanged=val
nextTick(() => {
feather.replace()