upgraded all the ui. Added gguf support

This commit is contained in:
Saifeddine ALOUI 2023-08-25 21:47:28 +02:00
parent 7437f87432
commit 1d947e33b2
14 changed files with 466 additions and 461 deletions

View File

@ -833,7 +833,7 @@ class LoLLMsAPPI(LollmsApplication):
self.mounted_personalities=[] self.mounted_personalities=[]
loaded = self.mounted_personalities loaded = self.mounted_personalities
loaded_names = [f"{p.category}/{p.personality_folder_name}" for p in loaded] loaded_names = [f"{p.category}/{p.personality_folder_name}:{p.selected_language}" if p.selected_language else f"{p.category}/{p.personality_folder_name}" for p in loaded]
mounted_personalities=[] mounted_personalities=[]
ASCIIColors.success(f" ╔══════════════════════════════════════════════════╗ ") ASCIIColors.success(f" ╔══════════════════════════════════════════════════╗ ")
ASCIIColors.success(f" ║ Building mounted Personalities ║ ") ASCIIColors.success(f" ║ Building mounted Personalities ║ ")
@ -848,12 +848,13 @@ class LoLLMsAPPI(LollmsApplication):
if personality in loaded_names: if personality in loaded_names:
mounted_personalities.append(loaded[loaded_names.index(personality)]) mounted_personalities.append(loaded[loaded_names.index(personality)])
else: else:
personality_path = self.lollms_paths.personalities_zoo_path/f"{personality}" personality_path = self.lollms_paths.personalities_zoo_path/f"{personality}" if not ":" in personality else self.lollms_paths.personalities_zoo_path/f"{personality.split(':')[0]}"
try: try:
personality = AIPersonality(personality_path, personality = AIPersonality(personality_path,
self.lollms_paths, self.lollms_paths,
self.config, self.config,
model=self.model, model=self.model,
selected_language=personality.split(":")[1] if ":" in personality else None,
run_scripts=True) run_scripts=True)
mounted_personalities.append(personality) mounted_personalities.append(personality)
except Exception as ex: except Exception as ex:
@ -868,6 +869,7 @@ class LoLLMsAPPI(LollmsApplication):
self.config, self.config,
self.model, self.model,
run_scripts=True, run_scripts=True,
selected_language=personality.split(":")[1] if ":" in personality else None,
installation_option=InstallOption.FORCE_INSTALL) installation_option=InstallOption.FORCE_INSTALL)
mounted_personalities.append(personality) mounted_personalities.append(personality)
except Exception as ex: except Exception as ex:
@ -875,7 +877,8 @@ class LoLLMsAPPI(LollmsApplication):
trace_exception(ex) trace_exception(ex)
ASCIIColors.info(f"Unmounting personality") ASCIIColors.info(f"Unmounting personality")
to_remove.append(i) to_remove.append(i)
personality = AIPersonality(None, self.lollms_paths, personality = AIPersonality(None,
self.lollms_paths,
self.config, self.config,
self.model, self.model,
run_scripts=True, run_scripts=True,

21
app.py
View File

@ -495,7 +495,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
presets = [] presets = []
for filename in presets_folder.glob('*.yaml'): for filename in presets_folder.glob('*.yaml'):
print(filename) print(filename)
with open(filename, 'r') as file: with open(filename, 'r', encoding='utf-8') as file:
preset = yaml.safe_load(file) preset = yaml.safe_load(file)
if preset is not None: if preset is not None:
presets.append(preset) presets.append(preset)
@ -510,7 +510,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
self.copy_files("presets",presets_folder) self.copy_files("presets",presets_folder)
fn = preset_data.name.lower().replace(" ","_") fn = preset_data.name.lower().replace(" ","_")
filename = presets_folder/f"{fn}.yaml" filename = presets_folder/f"{fn}.yaml"
with open(filename, 'r') as file: with open(filename, 'w', encoding='utf-8') as file:
yaml.dump(preset_data) yaml.dump(preset_data)
return jsonify({"status": True}) return jsonify({"status": True})
@ -813,10 +813,15 @@ class LoLLMsWebUI(LoLLMsAPPI):
def apply_settings(self): def apply_settings(self):
data = request.get_json()
try:
for key in self.config.config.keys():
self.config.config[key] = data["config"].get(key, self.config.config[key])
ASCIIColors.success("OK") ASCIIColors.success("OK")
self.rebuild_personalities() self.rebuild_personalities()
return jsonify({"status":True}) return jsonify({"status":True})
except Exception as ex:
return jsonify({"status":False,"error":str(ex)})
def ram_usage(self): def ram_usage(self):
@ -1106,7 +1111,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
ASCIIColors.info(f"- Selecting model ...") ASCIIColors.info(f"- Selecting model ...")
# Define the file types # Define the file types
filetypes = [ filetypes = [
("Model file", self.binding.file_extension), ("Model file", self.binding.supported_file_extensions),
] ]
# Create the Tkinter root window # Create the Tkinter root window
root = Tk() root = Tk()
@ -1345,14 +1350,17 @@ class LoLLMsWebUI(LoLLMsAPPI):
category = data['category'] category = data['category']
name = data['folder'] name = data['folder']
language = data.get('language', None)
package_path = f"{category}/{name}" package_path = f"{category}/{name}"
package_full_path = self.lollms_paths.personalities_zoo_path/package_path package_full_path = self.lollms_paths.personalities_zoo_path/package_path
config_file = package_full_path / "config.yaml" config_file = package_full_path / "config.yaml"
if config_file.exists(): if config_file.exists():
if language:
package_path += ":" + language
self.config["personalities"].append(package_path) self.config["personalities"].append(package_path)
self.mounted_personalities = self.rebuild_personalities() self.mounted_personalities = self.rebuild_personalities()
self.personality = self.mounted_personalities[self.config["active_personality_id"]] self.personality = self.mounted_personalities[self.config["active_personality_id"]]
self.apply_settings()
ASCIIColors.success("ok") ASCIIColors.success("ok")
if self.config["active_personality_id"]<0: if self.config["active_personality_id"]<0:
return jsonify({"status": False, return jsonify({"status": False,
@ -1405,7 +1413,6 @@ class LoLLMsWebUI(LoLLMsAPPI):
self.config["personalities"].append(package_path) self.config["personalities"].append(package_path)
self.mounted_personalities = self.rebuild_personalities() self.mounted_personalities = self.rebuild_personalities()
self.personality = self.mounted_personalities[self.config["active_personality_id"]] self.personality = self.mounted_personalities[self.config["active_personality_id"]]
self.apply_settings()
ASCIIColors.success("ok") ASCIIColors.success("ok")
if self.config["active_personality_id"]<0: if self.config["active_personality_id"]<0:
return jsonify({"status": False, return jsonify({"status": False,
@ -1444,7 +1451,6 @@ class LoLLMsWebUI(LoLLMsAPPI):
self.personalities = ["generic/lollms"] self.personalities = ["generic/lollms"]
self.mounted_personalities = self.rebuild_personalities() self.mounted_personalities = self.rebuild_personalities()
self.personality = self.mounted_personalities[self.config["active_personality_id"]] self.personality = self.mounted_personalities[self.config["active_personality_id"]]
self.apply_settings()
ASCIIColors.success("ok") ASCIIColors.success("ok")
return jsonify({ return jsonify({
"status": True, "status": True,
@ -1571,7 +1577,6 @@ class LoLLMsWebUI(LoLLMsAPPI):
if id<len(self.mounted_personalities): if id<len(self.mounted_personalities):
self.config["active_personality_id"]=id self.config["active_personality_id"]=id
self.personality = self.mounted_personalities[self.config["active_personality_id"]] self.personality = self.mounted_personalities[self.config["active_personality_id"]]
self.apply_settings()
ASCIIColors.success("ok") ASCIIColors.success("ok")
print(f"Mounted {self.personality.name}") print(f"Mounted {self.personality.name}")
return jsonify({ return jsonify({

View File

@ -0,0 +1,30 @@
name: Translate code file strings
content: |
Instruction: Translate the comments and values of the @<File type:yaml:json:all_programming_language_options>@ file from @<Source language:all_language_options>@ to @<Destination language:all_language_options>@.
Session 1:
```@<File type:yaml:json:all_programming_language_options>@ language=english
# This is a comment
parameter_1: this is parameter 1
parameter_2: this is parameter 2
parameter_3: 25
parameter_4: |
This is a multi
line parameter
```
Translation:
```@<File type:yaml:json:all_programming_language_options>@ language=french
# Ceci est un commentaire
parameter_1: ceci est le paramètre 1
parameter_2: ceci est le paramètre 2
parameter_3: 25
parameter_4: |
Ceci est un paramètre
multiligne
```
Session 2:
```@<File type:yaml:json:all_programming_language_options>@ language=@<Source language:all_language_options>@
@<Put your yaml data here>@
```
Translation:
```@<File type:yaml:json:all_programming_language_options>@ language=@<Destination language:all_language_options>@@<generation_placeholder>@
```

8
web/dist/assets/index-5b957acd.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"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LoLLMS WebUI - Welcome</title> <title>LoLLMS WebUI - Welcome</title>
<script type="module" crossorigin src="/assets/index-7262b344.js"></script> <script type="module" crossorigin src="/assets/index-76ec0c11.js"></script>
<link rel="stylesheet" href="/assets/index-d072d96d.css"> <link rel="stylesheet" href="/assets/index-5b957acd.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

View File

@ -13,7 +13,7 @@
:style="{ cursor:!this.disableFocus ? 'pointer' : ''}" :style="{ cursor:!this.disableFocus ? 'pointer' : ''}"
> >
<!-- Title --> <!-- Title -->
<div v-if="title" @click="shrink=true" class="font-bold mb-2 cursor-pointer">{{ title }}</div> <div v-if="title" @click="shrink=true" :class="{'text-center p-2 m-2 bg-gray-200':!is_subcard}" class="bg-gray-100 rounded-lg pl-2 pr-2 mb-2 font-bold cursor-pointer">{{ title }}</div>
<div v-if="isHorizontal" class="flex flex-wrap"> <div v-if="isHorizontal" class="flex flex-wrap">
<!-- Card Content --> <!-- Card Content -->
@ -25,7 +25,7 @@
<slot></slot> <slot></slot>
</div> </div>
</div> </div>
<div v-show="shrink===true" @click="shrink=false" class="bg-white dark:bg-gray-700 border-blue-300 rounded-lg shadow-lg p-2 h-10 cursor-pointer"> <div v-show="shrink===true" @click="shrink=false" class="bg-white text-center text-2xl dark:bg-gray-700 border-blue-300 rounded-lg shadow-lg p-2 h-10 cursor-pointer">
+ +
</div> </div>
</template> </template>
@ -33,6 +33,10 @@
<script> <script>
export default { export default {
props: { props: {
is_subcard:{
type:Boolean,
default:false
},
is_shrunk: { is_shrunk: {
type:Boolean, type:Boolean,
default:false default:false

View File

@ -7,7 +7,8 @@
<div v-if="isMenuOpen" class="menu-list flex-grow" :style="menuPosition" ref="menu"> <div v-if="isMenuOpen" class="menu-list flex-grow" :style="menuPosition" ref="menu">
<ul class="flex-grow menu-ul"> <ul class="flex-grow menu-ul">
<li v-for="(command, index) in commands" :key="index" @click="executeCommand(command)" class="menu-command menu-li flex-grow hover:bg-blue-400 "> <li v-for="(command, index) in commands" :key="index" @click="executeCommand(command)" class="menu-command menu-li flex-grow hover:bg-blue-400 ">
<img v-if="command.icon && !command.is_file" :src="command.icon" :alt="command.name" class="menu-icon"> <img v-if="command.icon && !command.icon.includes('feather') && !command.is_file" :src="command.icon" :alt="command.name" class="menu-icon">
<i v-if="command.icon && command.icon.includes('feather') && !command.is_file" :data-feather="command.icon.split(':')[1]" class="mr-2"></i>
<span v-else class="menu-icon"></span> <span v-else class="menu-icon"></span>
<span>{{ command.name }}</span> <span>{{ command.name }}</span>
</li> </li>
@ -18,6 +19,8 @@
</template> </template>
<script> <script>
import { nextTick } from 'vue'
import feather from 'feather-icons'
export default { export default {
props: { props: {
commands: { commands: {
@ -58,6 +61,9 @@ handleClickOutside(event) {
// Remove the click event listener when the menu closes // Remove the click event listener when the menu closes
window.removeEventListener('click', this.handleClickOutside); window.removeEventListener('click', this.handleClickOutside);
} }
nextTick(() => {
feather.replace()
})
}, },
executeCommand(command) { executeCommand(command) {
if (typeof this[command.value] === 'function') { if (typeof this[command.value] === 'function') {
@ -85,6 +91,9 @@ handleClickOutside(event) {
// Listen to window resize to reposition the menu if needed // Listen to window resize to reposition the menu if needed
window.addEventListener('resize', this.positionMenu); window.addEventListener('resize', this.positionMenu);
this.positionMenu(); // Initial positioning this.positionMenu(); // Initial positioning
nextTick(() => {
feather.replace()
})
}, },
beforeDestroy() { beforeDestroy() {
// Cleanup the event listener // Cleanup the event listener
@ -157,4 +166,3 @@ handleClickOutside(event) {
text-align: left; text-align: left;
} }
</style> </style>

View File

@ -334,7 +334,8 @@ export default {
try { try {
const obj = { const obj = {
category: pers.category, category: pers.category,
folder: pers.folder folder: pers.folder,
language: pers.lang
} }
const res = await axios.post('/mount_personality', obj); const res = await axios.post('/mount_personality', obj);
@ -355,7 +356,8 @@ export default {
try { try {
const obj = { const obj = {
category: pers.category, category: pers.category,
folder: pers.folder folder: pers.folder,
language: pers.lang
} }
const res = await axios.post('/remount_personality', obj); const res = await axios.post('/remount_personality', obj);

View File

@ -1,7 +1,7 @@
<template> <template>
<div <div
class=" min-w-96 items-start p-4 hover:bg-primary-light rounded-lg mb-2 shadow-lg border-2 cursor-pointer active:scale-95 duration-75 select-none" class=" min-w-96 items-start p-4 hover:bg-primary-light rounded-lg mb-2 shadow-lg border-2 cursor-pointer active:scale-95 duration-75 select-none"
@click.stop="toggleSelected" :class="selected_computed ? 'border-primary-light' : 'border-transparent'" @click.stop="toggleSelected" tabindex="-1" :class="selected_computed ? 'border-primary-light' : 'border-transparent'"
:title="!personality.installed ? 'Not installed' : ''"> :title="!personality.installed ? 'Not installed' : ''">
<div :class="!personality.installed ? 'opacity-50' : ''"> <div :class="!personality.installed ? 'opacity-50' : ''">
@ -19,41 +19,10 @@
<i data-feather="send" class="w-5"></i> <i data-feather="send" class="w-5"></i>
<span class="sr-only">Talk</span> <span class="sr-only">Talk</span>
</button> </button>
<InteractiveMenu :commands="commandsList">
</div> </InteractiveMenu>
<div class="flex items-center flex-row-reverse gap-2 my-1">
<!-- CONTROLS -->
<button v-if="selected_computed" type="button" title="Settings" @click.stop="toggleSettings"
class="inline-flex items-center gap-2 px-3 py-2 text-xs font-medium text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
Settings
<span class="sr-only">Settings</span>
</button>
<button v-if="selected_computed" title="Click to Reinstall personality" type="button" @click.stop="toggleReinstall"
class="inline-flex items-center gap-2 px-3 py-2 text-xs font-medium text-center focus:outline-none text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:ring-red-300 rounded-lg dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-900">
Reinstall personality
<span class="sr-only">Reinstall personality</span>
</button>
<button v-if="!isMounted" title="Mount personality" type="button"
@click.stop="toggleMounted"
class="inline-flex items-center gap-2 px-3 py-2 text-xs font-medium text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
Mount
<span class="sr-only">Click to install</span>
</button>
<button v-if="isMounted" title="Unmount personality" type="button" @click.stop="toggleMounted"
class="inline-flex items-center gap-2 px-3 py-2 text-xs font-medium text-center focus:outline-none text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:ring-red-300 rounded-lg dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-900">
Unmount
<span class="sr-only">Remove</span>
</button>
<button v-if="isMounted" title="Remount personality (useful if you have changed it)" type="button" @click.stop="reMount"
class="inline-flex items-center gap-2 px-3 py-2 text-xs font-medium text-center focus:outline-none text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-red-300 rounded-lg dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-900">
<i data-feather="refresh-ccw" class="w-5"></i>
<span class="sr-only">Remount</span>
</button>
</div> </div>
<div class=""> <div class="">
<div class=""> <div class="">
@ -64,6 +33,21 @@
{{ personality.author }} {{ personality.author }}
</div> </div>
<div v-if="personality.languages" class="flex items-center">
<i data-feather="globe" class="w-5 m-1"></i>
<b>Languages:&nbsp;</b>
<select id="languages" v-model ="personality.lang"
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, index) in personality.languages" :key="index"
:selected="item == personality.languages[0]">{{
item
}}
</option>
</select>
</div>
<div class="flex items-center"> <div class="flex items-center">
<i data-feather="bookmark" class="w-5 m-1"></i> <i data-feather="bookmark" class="w-5 m-1"></i>
<b>Category:&nbsp;</b> <b>Category:&nbsp;</b>
@ -89,6 +73,8 @@ import { nextTick } from 'vue'
import feather from 'feather-icons' import feather from 'feather-icons'
import botImgPlaceholder from "../assets/logo.svg" import botImgPlaceholder from "../assets/logo.svg"
import userImgPlaceholder from "../assets/default_user.svg" import userImgPlaceholder from "../assets/default_user.svg"
import InteractiveMenu from "@/components/InteractiveMenu.vue"
const bUrl = import.meta.env.VITE_LOLLMS_API_BASEURL const bUrl = import.meta.env.VITE_LOLLMS_API_BASEURL
export default { export default {
props: { props: {
@ -102,12 +88,30 @@ export default {
onReinstall: Function, onReinstall: Function,
onSettings: Function onSettings: Function
}, },
components:{
InteractiveMenu
},
data() { data() {
return { return {
isMounted: false, isMounted: false,
name: this.personality.name name: this.personality.name,
}; };
}, },
computed:{
commandsList(){
let main_menu = [
{name:this.isMounted?"unmount":"mount", icon: "feather:settings", is_file:false, value:this.toggleMounted},
{name:"reinstall", icon: "feather:terminal", is_file:false, value:this.toggleReinstall},
];
if(this.selected){
main_menu.push({name:"settings", icon: "feather:settings", is_file:false, value:this.toggleSettings})
}
return main_menu
},
selected_computed(){
return this.selected
}
},
mounted() { mounted() {
this.isMounted = this.personality.isMounted this.isMounted = this.personality.isMounted
@ -118,11 +122,6 @@ export default {
}) })
}, },
computed: {
selected_computed(){
return this.selected
}
},
methods: { methods: {
getImgUrl() { getImgUrl() {
return bUrl + this.personality.avatar return bUrl + this.personality.avatar
@ -134,7 +133,9 @@ selected_computed(){
this.onTalk(this) this.onTalk(this)
}, },
toggleSelected() { toggleSelected() {
if(this.isMounted){
this.onSelected(this) this.onSelected(this)
}
}, },
reMount(){ reMount(){
this.onRemount(this) this.onRemount(this)

View File

@ -120,7 +120,8 @@ export const store = createStore({
//let personality_path_infos = await this.api_get_req("get_current_personality_path_infos") //let personality_path_infos = await this.api_get_req("get_current_personality_path_infos")
configFile.personality_category = personality_path_infos[0] configFile.personality_category = personality_path_infos[0]
configFile.personality_folder = personality_path_infos[1] configFile.personality_folder = personality_path_infos[1]
console.log("Recovered config")
console.log(configFile)
commit('setConfig', configFile); commit('setConfig', configFile);
} catch (error) { } catch (error) {
console.log(error.message, 'refreshConfig'); console.log(error.message, 'refreshConfig');
@ -131,12 +132,12 @@ export const store = createStore({
let personalities = [] let personalities = []
const catdictionary = await api_get_req("get_all_personalities") const catdictionary = await api_get_req("get_all_personalities")
const catkeys = Object.keys(catdictionary); // returns categories const catkeys = Object.keys(catdictionary); // returns categories
console.log("Personalities recovered:"+this.state.config.personalities)
for (let j = 0; j < catkeys.length; j++) { for (let j = 0; j < catkeys.length; j++) {
const catkey = catkeys[j]; const catkey = catkeys[j];
const personalitiesArray = catdictionary[catkey]; const personalitiesArray = catdictionary[catkey];
const modPersArr = personalitiesArray.map((item) => { const modPersArr = personalitiesArray.map((item) => {
const isMounted = this.state.config.personalities.includes(catkey + '/' + item.folder) const isMounted = this.state.config.personalities.includes(catkey + '/' + item.folder)
// if (isMounted) { // if (isMounted) {
// console.log(item) // console.log(item)
@ -175,7 +176,7 @@ export const store = createStore({
mountedPersArr.push(pers) mountedPersArr.push(pers)
} }
else { else {
mountedPersArr.push(this.state.personalities[this.state.personalities.findIndex(item => item.full_path == "english/generic/lollms")]) mountedPersArr.push(this.state.personalities[this.state.personalities.findIndex(item => item.full_path == "generic/lollms")])
} }
} }
console.log("Personalities list",this.state.personalities) console.log("Personalities list",this.state.personalities)

View File

@ -35,11 +35,13 @@
<div class="border-2 text-blue-600 border-blue-300 p-2 rounded shadow-lg hover:border-gray-600 dark:link-item-dark cursor-pointer" @click="tab_id='render'" :class="{'bg-blue-200':tab_id=='render'}"> <div class="border-2 text-blue-600 border-blue-300 p-2 rounded shadow-lg hover:border-gray-600 dark:link-item-dark cursor-pointer" @click="tab_id='render'" :class="{'bg-blue-200':tab_id=='render'}">
Render Render
</div> </div>
</div> </div>
<div v-if="tab_id === 'source'"> <div v-if="tab_id === 'source'">
<textarea v-model="text" id="text_element" class="mt-4 h-64 p-2 rounded shadow-lg overflow-y-scroll w-full dark:bg-bg-dark scrollbar-thin scrollbar-track-bg-light-tone scrollbar-thumb-bg-light-tone-panel hover:scrollbar-thumb-primary dark:scrollbar-track-bg-dark-tone dark:scrollbar-thumb-bg-dark-tone-panel dark:hover:scrollbar-thumb-primary active:scrollbar-thumb-secondary" type="text"></textarea> <textarea
@click="text_element_clicked"
v-model="text"
id="text_element"
class="mt-4 h-64 p-2 rounded shadow-lg overflow-y-scroll w-full dark:bg-bg-dark scrollbar-thin scrollbar-track-bg-light-tone scrollbar-thumb-bg-light-tone-panel hover:scrollbar-thumb-primary dark:scrollbar-track-bg-dark-tone dark:scrollbar-thumb-bg-dark-tone-panel dark:hover:scrollbar-thumb-primary active:scrollbar-thumb-secondary" type="text"></textarea>
<span>Cursor position {{ cursorPosition }}</span> <span>Cursor position {{ cursorPosition }}</span>
</div> </div>
<div v-else> <div v-else>
@ -48,8 +50,8 @@
</div> </div>
</div> </div>
</div> </div>
<Card title="settings" class="slider-container ml-0 mr-0" :isHorizontal="false" :disableHoverAnimation="true" :disableFocus="true"> <Card title="settings" class="slider-container ml-0 mr-0 max-width" :isHorizontal="false" :disableHoverAnimation="true" :disableFocus="true">
<Card title="Model" class="slider-container ml-0 mr-0" :isHorizontal="false" :disableHoverAnimation="true" :disableFocus="true"> <Card title="Model" class="slider-container ml-0 mr-0" :is_subcard="true" :isHorizontal="false" :disableHoverAnimation="true" :disableFocus="true">
<select v-model="selectedModel" @change="setModel" class="m-0 border-2 rounded-md shadow-sm w-full"> <select v-model="selectedModel" @change="setModel" class="m-0 border-2 rounded-md shadow-sm w-full">
<option v-for="model in models" :key="model" :value="model"> <option v-for="model in models" :key="model" :value="model">
{{ model }} {{ model }}
@ -72,8 +74,8 @@
</div> </div>
</Card> </Card>
<Card title="Presets" class="slider-container ml-0 mr-0" :isHorizontal="false" :disableHoverAnimation="true" :disableFocus="true"> <Card title="Presets" class="slider-container ml-0 mr-0" :is_subcard="true" :isHorizontal="false" :disableHoverAnimation="true" :disableFocus="true">
<select v-model="selectedPreset" class="m-0 border-2 rounded-md shadow-sm w-full"> <select v-model="selectedPreset" class="mb-2 border-2 rounded-md shadow-sm w-full">
<option v-for="preset in presets" :key="preset" :value="preset"> <option v-for="preset in presets" :key="preset" :value="preset">
{{ preset.name }} {{ preset.name }}
</option> </option>
@ -85,7 +87,7 @@
<button class="w-6 ml-2 hover:text-secondary duration-75 active:scale-90 cursor-pointer" @click="reloadPresets" title="Reload presets list"><i data-feather="refresh-ccw"></i></button> <button class="w-6 ml-2 hover:text-secondary duration-75 active:scale-90 cursor-pointer" @click="reloadPresets" title="Reload presets list"><i data-feather="refresh-ccw"></i></button>
</Card> </Card>
<Card title="Generation params" class="slider-container ml-0 mr-0" :isHorizontal="false" :disableHoverAnimation="true" :disableFocus="true"> <Card title="Generation params" class="slider-container ml-0 mr-0" :is_subcard="true" :isHorizontal="false" :disableHoverAnimation="true" :disableFocus="true">
<div class="slider-container ml-2 mr-2"> <div class="slider-container ml-2 mr-2">
<h3 class="text-gray-600">Temperature</h3> <h3 class="text-gray-600">Temperature</h3>
@ -322,24 +324,6 @@ export default {
Card Card
}, },
mounted() { mounted() {
const text_element = document.getElementById('text_element');
text_element.addEventListener('input', () => {
try{
this.cursorPosition = text_element.selectionStart;
}
catch{
}
});
text_element.addEventListener('click', () => {
try{
this.cursorPosition = text_element.selectionStart;
}
catch{
}
});
axios.get('list_models').then(response => { axios.get('list_models').then(response => {
console.log("List models "+response.data) console.log("List models "+response.data)
this.models=response.data this.models=response.data
@ -444,6 +428,27 @@ export default {
}, },
}, },
methods:{ methods:{
text_element_changed(){
console.log("text_element_changed")
try{
this.cursorPosition = this.$refs.text_element.selectionStart;
}
catch (e) {
// The "error" event is fired when an exception occurs
console.log("Error occurred:", e);
}
},
text_element_clicked(){
console.log("text_element_clicked")
try{
this.cursorPosition = this.$refs.text_element.selectionStart;
console.log(this.cursorPosition)
}
catch (e) {
// The "error" event is fired when an exception occurs
console.log("Error occurred:", e);
}
},
setModel(){ setModel(){
this.selecting_model=true this.selecting_model=true
axios.post("/update_setting", { axios.post("/update_setting", {
@ -452,8 +457,10 @@ export default {
}).then((response) => { }).then((response) => {
console.log(response); console.log(response);
this.$refs.toast.showToast(`Model changed to this.selectedModel`,4,true) this.$refs.toast.showToast(`Model changed to this.selectedModel`,4,true)
this.selecting_model=false
}).catch(err=>{ }).catch(err=>{
this.$refs.toast.showToast(`Error ${err}`,4,true) this.$refs.toast.showToast(`Error ${err}`,4,true)
this.selecting_model=false
}); });
}, },

View File

@ -31,7 +31,31 @@
</div> </div>
<div class="flex gap-3 flex-1 items-center justify-end"> <div class="flex gap-3 flex-1 items-center justify-end">
<button
title="Clear uploads"
class="text-2xl hover:text-secondary duration-75 active:scale-90"
@click="api_get_req('clear_uploads').then((res)=>{if(res.status){this.$refs.toast.showToast('Success!', 4, true)}else{this.$refs.toast.showToast(['failed!'], 4, false)}})"
>
<i data-feather="trash-2"></i>
</button>
<button
title="Restart program"
class="text-2xl hover:text-secondary duration-75 active:scale-90"
@click="api_get_req('restart_program').then((res)=>{if(res.status){this.$refs.toast.showToast('Success!', 4, true)}else{this.$refs.toast.showToast(['failed!'], 4, false)}})"
>
<i data-feather="refresh-ccw"></i>
</button>
<button
title="Upgrade program "
class="text-2xl hover:text-secondary duration-75 active:scale-90"
@click="api_get_req('update_software').then((res)=>{if(res.status){this.$refs.toast.showToast('Success!', 4, true)}else{this.$refs.toast.showToast('Success!', 4, true)}})"
>
<i data-feather="arrow-up-circle"></i>
<div v-if="has_updates" >
<i data-feather="alert-circle"></i>
</div>
</button>
<div class="flex gap-3 items-center"> <div class="flex gap-3 items-center">
<div v-if="settingsChanged" class="flex gap-3 items-center"> <div v-if="settingsChanged" class="flex gap-3 items-center">
Apply changes: Apply changes:
@ -543,18 +567,11 @@
type="text" type="text"
id="db_path" id="db_path"
required required
v-model="db_path" v-model="configFile.db_path"
@change="settingsChanged=true"
class="w-full w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600 dark:bg-gray-600" class="w-full w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600 dark:bg-gray-600"
> >
</td> </td>
<td>
<button
class="hover:text-secondary dark:bg-gray-600 bg-blue-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
@click="update_setting('db_path', db_path)"
>
<i data-feather="check"></i>
</button>
</td>
</tr> </tr>
<tr> <tr>
<td style="min-width: 200px;"> <td style="min-width: 200px;">
@ -565,18 +582,11 @@
type="checkbox" type="checkbox"
id="enable_gpu" id="enable_gpu"
required required
v-model="enable_gpu" v-model="configFile.enable_gpu"
@change="settingsChanged=true"
class="w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600" class="w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600"
> >
</td> </td>
<td>
<button
class="hover:text-secondary dark:bg-gray-600 bg-blue-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
@click="update_setting('enable_gpu', enable_gpu)"
>
<i data-feather="check"></i>
</button>
</td>
</tr> </tr>
<tr> <tr>
<td style="min-width: 200px;"> <td style="min-width: 200px;">
@ -587,18 +597,11 @@
type="checkbox" type="checkbox"
id="auto_update" id="auto_update"
required required
v-model="auto_update" v-model="configFile.auto_update"
@change="settingsChanged=true"
class="w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600" class="w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600"
> >
</td> </td>
<td>
<button
class="hover:text-secondary dark:bg-gray-600 bg-blue-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
@click="update_setting('auto_update', auto_update)"
>
<i data-feather="check"></i>
</button>
</td>
</tr> </tr>
</table> </table>
</div> </div>
@ -614,18 +617,11 @@
type="text" type="text"
id="user_name" id="user_name"
required required
v-model="userName" v-model="configFile.userName"
@change="settingsChanged=true"
class="w-full w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600" class="w-full w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600"
> >
</td> </td>
<td>
<button
class="hover:text-secondary dark:bg-gray-600 bg-blue-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
@click="update_setting('user_name', userName)"
>
<i data-feather="check"></i>
</button>
</td>
</tr> </tr>
<!-- Row 3 --> <!-- Row 3 -->
<tr> <tr>
@ -634,18 +630,10 @@
</td> </td>
<td style="width: 100%;"> <td style="width: 100%;">
<label for="avatar-upload"> <label for="avatar-upload">
<img :src="user_avatar" class="w-50 h-50 rounded-full" style="max-width: 50px; max-height: 50px; cursor: pointer;"> <img :src="configFile.user_avatar" class="w-50 h-50 rounded-full" style="max-width: 50px; max-height: 50px; cursor: pointer;">
</label> </label>
<input type="file" id="avatar-upload" style="display: none" @change="uploadAvatar"> <input type="file" id="avatar-upload" style="display: none" @change="uploadAvatar">
</td> </td>
<td>
<button
class="hover:text-secondary dark:bg-gray-600 bg-blue-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
@click="update_setting('user_name', userName)"
>
<i data-feather="check"></i>
</button>
</td>
</tr> </tr>
<!-- Row 4 --> <!-- Row 4 -->
<tr> <tr>
@ -657,18 +645,11 @@
type="checkbox" type="checkbox"
id="use_user_name_in_discussions" id="use_user_name_in_discussions"
required required
v-model="use_user_name_in_discussions" v-model="configFile.use_user_name_in_discussions"
@change="settingsChanged=true"
class=" w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600" class=" w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600"
> >
</td> </td>
<td>
<button
class="hover:text-secondary dark:bg-gray-600 bg-blue-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
@click="update_setting('use_user_name_in_discussions', use_user_name_in_discussions)"
>
<i data-feather="check"></i>
</button>
</td>
</tr> </tr>
</table> </table>
</div> </div>
@ -684,25 +665,19 @@
type="checkbox" type="checkbox"
id="auto_speak" id="auto_speak"
required required
v-model="auto_speak" v-model="configFile.auto_speak"
@change="settingsChanged=true"
class="w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600" class="w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600"
> >
</td> </td>
<td>
<button
class="hover:text-secondary dark:bg-gray-600 bg-blue-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
@click="update_setting('auto_speak', auto_speak)"
>
<i data-feather="check"></i>
</button>
</td>
</tr> </tr>
<tr> <tr>
<td style="min-width: 200px;"> <td style="min-width: 200px;">
<label for="audio_pitch" class="text-sm font-bold" style="margin-right: 1rem;">audio pitch:</label> <label for="audio_pitch" class="text-sm font-bold" style="margin-right: 1rem;">audio pitch:</label>
</td> </td>
<td> <td>
<input id="audio_pitch" v-model="audio_pitch" <input id="audio_pitch" v-model="configFile.audio_pitch"
@change="settingsChanged=true"
type="range" min="0" max="10" step="0.1" type="range" min="0" max="10" step="0.1"
class="flex-none h-2 mt-14 mb-2 w-full bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700 focus:ring-blue-500 focus:border-blue-500 dark:border-gray-600 dark:placeholder-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500"> class="flex-none h-2 mt-14 mb-2 w-full bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700 focus:ring-blue-500 focus:border-blue-500 dark:border-gray-600 dark:placeholder-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500">
@ -710,14 +685,6 @@
class="w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600" class="w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600"
>{{ audio_pitch }}</p> >{{ audio_pitch }}</p>
</td> </td>
<td>
<button
class="hover:text-secondary dark:bg-gray-600 bg-blue-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
@click="update_setting('audio_pitch', audio_pitch)"
>
<i data-feather="check"></i>
</button>
</td>
</tr> </tr>
<tr> <tr>
@ -728,7 +695,8 @@
<!-- Select element for choosing the input audio language --> <!-- Select element for choosing the input audio language -->
<select <select
id="audio_in_language" id="audio_in_language"
v-model="audio_in_language" v-model="configFile.audio_in_language"
@change="settingsChanged=true"
class="w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600" class="w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600"
> >
<!-- Options with language codes and corresponding language names --> <!-- Options with language codes and corresponding language names -->
@ -737,14 +705,6 @@
</option> </option>
</select> </select>
</td> </td>
<td>
<button
class="hover:text-secondary dark:bg-gray-600 bg-blue-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
@click="update_setting('audio_in_language', audio_in_language)"
>
<i data-feather="check"></i>
</button>
</td>
</tr> </tr>
<tr> <tr>
<td style="min-width: 200px;"> <td style="min-width: 200px;">
@ -754,7 +714,8 @@
<!-- Select element for choosing the output audio voice --> <!-- Select element for choosing the output audio voice -->
<select <select
id="audio_out_voice" id="audio_out_voice"
v-model="audio_out_voice" v-model="configFile.audio_out_voice"
@change="settingsChanged=true"
class="w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600" class="w-full mt-1 px-2 py-1 border border-gray-300 rounded dark:bg-gray-600"
> >
<!-- Options with available voices in the browser --> <!-- Options with available voices in the browser -->
@ -763,14 +724,6 @@
</option> </option>
</select> </select>
</td> </td>
<td>
<button
class="hover:text-secondary dark:bg-gray-600 bg-blue-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
@click="update_setting('audio_out_voice', audio_out_voice)"
>
<i data-feather="check"></i>
</button>
</td>
</tr> </tr>
@ -781,31 +734,6 @@
<!-- Row 0 -->
<div class="flex flex-row">
<button
class="text-2xl hover:text-secondary duration-75 active:scale-90"
@click="api_get_req('clear_uploads').then((res)=>{if(res.status){this.$refs.toast.showToast('Success!', 4, true)}else{this.$refs.toast.showToast(['failed!'], 4, false)}})"
>
<i data-feather="trash-2">Clear uploads</i>
</button>
<button
title="Restart program"
class="text-2xl hover:text-secondary duration-75 active:scale-90"
@click="api_get_req('restart_program').then((res)=>{if(res.status){this.$refs.toast.showToast('Success!', 4, true)}else{this.$refs.toast.showToast(['failed!'], 4, false)}})"
>
<i data-feather="arrow-down-circle">Res tart program</i>
</button>
<button
class="text-2xl hover:text-secondary duration-75 active:scale-90"
@click="api_get_req('update_software').then((res)=>{if(res.status){this.$refs.toast.showToast('Success!', 4, true)}else{this.$refs.toast.showToast('Success!', 4, true)}})"
>
Upgrade program
<div v-if="has_updates" >
<i data-feather="alert-circle"></i>
</div>
</button>
</div>
@ -1316,6 +1244,7 @@
<personality-entry ref="personalitiesZoo" v-for="(pers, index) in personalitiesFiltered" <personality-entry ref="personalitiesZoo" v-for="(pers, index) in personalitiesFiltered"
:key="'index-' + index + '-' + pers.name" :personality="pers" :key="'index-' + index + '-' + pers.name" :personality="pers"
:full_path="pers.full_path" :full_path="pers.full_path"
:on-remount="onRemount"
:selected="configFile.active_personality_id == configFile.personalities.findIndex(item => item === pers.full_path)" :selected="configFile.active_personality_id == configFile.personalities.findIndex(item => item === pers.full_path)"
:on-selected="onPersonalitySelected" :on-mounted="onPersonalityMounted" :on-reinstall="onPersonalityReinstall" :on-selected="onPersonalitySelected" :on-mounted="onPersonalityMounted" :on-reinstall="onPersonalityReinstall"
:on-settings="onSettingsPersonality" /> :on-settings="onSettingsPersonality" />
@ -1815,6 +1744,7 @@ export default {
}, },
async constructor() { async constructor() {
console.log("Constructing")
this.isLoading = true this.isLoading = true
nextTick(() => { nextTick(() => {
feather.replace() feather.replace()
@ -1982,6 +1912,26 @@ export default {
this.$store.dispatch('refreshDiskUsage'); this.$store.dispatch('refreshDiskUsage');
this.$store.dispatch('refreshRamUsage'); this.$store.dispatch('refreshRamUsage');
}, },
async onRemount(pers) {
if (!pers) { return { 'status': false, 'error': 'no personality - unmount_personality' } }
const obj = {
language: pers.language,
category: pers.category,
folder: pers.folder,
language: pers.lang
}
try {
const res = await axios.post('/unmount_personality', obj);
} catch (error) {
console.log(error.message, 'unmount_personality - settings')
return
}
const res = await axios.post('/mount_personality', obj);
},
async onPersonalitySelected(pers) { async onPersonalitySelected(pers) {
console.log('on pers', pers) console.log('on pers', pers)
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
@ -2567,7 +2517,7 @@ export default {
applyConfiguration() { applyConfiguration() {
this.isLoading = true; this.isLoading = true;
axios.post('/apply_settings').then((res) => { axios.post('/apply_settings', {"config":this.configFile}).then((res) => {
this.isLoading = false; this.isLoading = false;
//console.log('apply-res',res) //console.log('apply-res',res)
if (res.data.status) { if (res.data.status) {
@ -2660,18 +2610,13 @@ export default {
//console.log('asdas',config) //console.log('asdas',config)
// console.log("all_personalities") // console.log("all_personalities")
// console.log(dictionary) // console.log(dictionary)
const langkeys = Object.keys(dictionary); // returns languages folder names const catkeys = Object.keys(dictionary); // returns categories folder names
for (let i = 0; i < langkeys.length; i++) {
const langkey = langkeys[i];
const catdictionary = dictionary[langkey];
const catkeys = Object.keys(catdictionary); // returns categories
for (let j = 0; j < catkeys.length; j++) { for (let j = 0; j < catkeys.length; j++) {
const catkey = catkeys[j]; const catkey = catkeys[j];
const personalitiesArray = catdictionary[catkey]; const personalitiesArray = catdictionary[catkey];
const modPersArr = personalitiesArray.map((item) => { const modPersArr = personalitiesArray.map((item) => {
const isMounted = config.personalities.includes(langkey + '/' + catkey + '/' + item.folder) const isMounted = config.personalities.includes(catkey + '/' + item.folder)
// if (isMounted) { // if (isMounted) {
// console.log(item) // console.log(item)
// } // }
@ -2679,7 +2624,7 @@ export default {
newItem = item newItem = item
newItem.category = catkey // add new props to items newItem.category = catkey // add new props to items
newItem.language = langkey // add new props to items newItem.language = langkey // add new props to items
newItem.full_path = langkey + '/' + catkey + '/' + item.folder // add new props to items newItem.full_path = catkey + '/' + item.folder // add new props to items
newItem.isMounted = isMounted // add new props to items newItem.isMounted = isMounted // add new props to items
return newItem return newItem
}) })
@ -2692,8 +2637,6 @@ export default {
} }
} }
}
this.personalities.sort((a, b) => a.name.localeCompare(b.name)) this.personalities.sort((a, b) => a.name.localeCompare(b.name))
this.personalitiesFiltered = this.personalities.filter((item) => item.category === this.configFile.personality_category) this.personalitiesFiltered = this.personalities.filter((item) => item.category === this.configFile.personality_category)
this.personalitiesFiltered.sort() this.personalitiesFiltered.sort()
@ -2768,7 +2711,8 @@ export default {
const obj = { const obj = {
language: pers.language, language: pers.language,
category: pers.category, category: pers.category,
folder: pers.folder folder: pers.folder,
language: pers.lang
} }
const res = await axios.post('/mount_personality', obj); const res = await axios.post('/mount_personality', obj);