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=[]
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=[]
ASCIIColors.success(f" ╔══════════════════════════════════════════════════╗ ")
ASCIIColors.success(f" ║ Building mounted Personalities ║ ")
@ -848,12 +848,13 @@ class LoLLMsAPPI(LollmsApplication):
if personality in loaded_names:
mounted_personalities.append(loaded[loaded_names.index(personality)])
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:
personality = AIPersonality(personality_path,
self.lollms_paths,
self.config,
model=self.model,
selected_language=personality.split(":")[1] if ":" in personality else None,
run_scripts=True)
mounted_personalities.append(personality)
except Exception as ex:
@ -868,6 +869,7 @@ class LoLLMsAPPI(LollmsApplication):
self.config,
self.model,
run_scripts=True,
selected_language=personality.split(":")[1] if ":" in personality else None,
installation_option=InstallOption.FORCE_INSTALL)
mounted_personalities.append(personality)
except Exception as ex:
@ -875,7 +877,8 @@ class LoLLMsAPPI(LollmsApplication):
trace_exception(ex)
ASCIIColors.info(f"Unmounting personality")
to_remove.append(i)
personality = AIPersonality(None, self.lollms_paths,
personality = AIPersonality(None,
self.lollms_paths,
self.config,
self.model,
run_scripts=True,

27
app.py
View File

@ -495,7 +495,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
presets = []
for filename in presets_folder.glob('*.yaml'):
print(filename)
with open(filename, 'r') as file:
with open(filename, 'r', encoding='utf-8') as file:
preset = yaml.safe_load(file)
if preset is not None:
presets.append(preset)
@ -510,7 +510,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
self.copy_files("presets",presets_folder)
fn = preset_data.name.lower().replace(" ","_")
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)
return jsonify({"status": True})
@ -813,10 +813,15 @@ class LoLLMsWebUI(LoLLMsAPPI):
def apply_settings(self):
ASCIIColors.success("OK")
self.rebuild_personalities()
return jsonify({"status":True})
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")
self.rebuild_personalities()
return jsonify({"status":True})
except Exception as ex:
return jsonify({"status":False,"error":str(ex)})
def ram_usage(self):
@ -1106,7 +1111,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
ASCIIColors.info(f"- Selecting model ...")
# Define the file types
filetypes = [
("Model file", self.binding.file_extension),
("Model file", self.binding.supported_file_extensions),
]
# Create the Tkinter root window
root = Tk()
@ -1345,14 +1350,17 @@ class LoLLMsWebUI(LoLLMsAPPI):
category = data['category']
name = data['folder']
language = data.get('language', None)
package_path = f"{category}/{name}"
package_full_path = self.lollms_paths.personalities_zoo_path/package_path
config_file = package_full_path / "config.yaml"
if config_file.exists():
if language:
package_path += ":" + language
self.config["personalities"].append(package_path)
self.mounted_personalities = self.rebuild_personalities()
self.personality = self.mounted_personalities[self.config["active_personality_id"]]
self.apply_settings()
ASCIIColors.success("ok")
if self.config["active_personality_id"]<0:
return jsonify({"status": False,
@ -1405,7 +1413,6 @@ class LoLLMsWebUI(LoLLMsAPPI):
self.config["personalities"].append(package_path)
self.mounted_personalities = self.rebuild_personalities()
self.personality = self.mounted_personalities[self.config["active_personality_id"]]
self.apply_settings()
ASCIIColors.success("ok")
if self.config["active_personality_id"]<0:
return jsonify({"status": False,
@ -1444,7 +1451,6 @@ class LoLLMsWebUI(LoLLMsAPPI):
self.personalities = ["generic/lollms"]
self.mounted_personalities = self.rebuild_personalities()
self.personality = self.mounted_personalities[self.config["active_personality_id"]]
self.apply_settings()
ASCIIColors.success("ok")
return jsonify({
"status": True,
@ -1571,7 +1577,6 @@ class LoLLMsWebUI(LoLLMsAPPI):
if id<len(self.mounted_personalities):
self.config["active_personality_id"]=id
self.personality = self.mounted_personalities[self.config["active_personality_id"]]
self.apply_settings()
ASCIIColors.success("ok")
print(f"Mounted {self.personality.name}")
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">
<title>LoLLMS WebUI - Welcome</title>
<script type="module" crossorigin src="/assets/index-7262b344.js"></script>
<link rel="stylesheet" href="/assets/index-d072d96d.css">
<script type="module" crossorigin src="/assets/index-76ec0c11.js"></script>
<link rel="stylesheet" href="/assets/index-5b957acd.css">
</head>
<body>
<div id="app"></div>

View File

@ -13,7 +13,7 @@
:style="{ cursor:!this.disableFocus ? 'pointer' : ''}"
>
<!-- 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">
<!-- Card Content -->
@ -25,7 +25,7 @@
<slot></slot>
</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>
</template>
@ -33,6 +33,10 @@
<script>
export default {
props: {
is_subcard:{
type:Boolean,
default:false
},
is_shrunk: {
type:Boolean,
default:false

View File

@ -1,160 +1,168 @@
<template>
<div class="menu-container">
<button @click.prevent="toggleMenu" class="menu-button bg-blue-500 text-white dark:bg-blue-200 dark:text-gray-800 rounded-full flex items-center justify-center w-6 h-6 border-none cursor-pointer hover:bg-blue-400 w-8 h-8 rounded-full object-fill text-red-700 border-2 active:scale-90 hover:z-20 hover:-translate-y-2 duration-150 border-gray-300 border-secondary cursor-pointer" ref="menuButton">
<i data-feather="command" class="w-5 h-5"></i>
</button>
<transition name="slide">
<div v-if="isMenuOpen" class="menu-list flex-grow" :style="menuPosition" ref="menu">
<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 ">
<img v-if="command.icon && !command.is_file" :src="command.icon" :alt="command.name" class="menu-icon">
<span v-else class="menu-icon"></span>
<span>{{ command.name }}</span>
</li>
</ul>
</div>
</transition>
</div>
</template>
<script>
export default {
props: {
commands: {
type: Array,
required: true
},
execute_cmd: {
type: Function, // The execute_cmd property should be a function
required: false
}
},
data() {
return {
isMenuOpen: false,
menuPosition: {
bottom: 'auto',
top: 'calc(100% + 10px)' // Initial position: below the button
}
};
},
methods: {
handleClickOutside(event) {
// Close the menu if the click occurs outside the menu container
const menuContainer = this.$refs.menu;
const menuButton = this.$refs.menuButton;
if (menuContainer && !menuContainer.contains(event.target) && !menuButton.contains(event.target)) {
this.isMenuOpen = false;
window.removeEventListener('click', this.handleClickOutside);
}
},
toggleMenu() {
this.positionMenu();
this.isMenuOpen = !this.isMenuOpen;
if (this.isMenuOpen) {
// Attach the click event listener when the menu opens
window.addEventListener('click', this.handleClickOutside);
} else {
// Remove the click event listener when the menu closes
window.removeEventListener('click', this.handleClickOutside);
}
},
executeCommand(command) {
if (typeof this[command.value] === 'function') {
this[command.value]();
}
this.isMenuOpen = false;
if (this.execute_cmd) {
this.execute_cmd(command); // Call the execute_cmd property with the current command
}
},
positionMenu() {
if (this.$refs.menuButton!=undefined){
const buttonRect = this.$refs.menuButton.getBoundingClientRect();
//const menuRect = this.$refs.menu.getBoundingClientRect();
const windowHeight = window.innerHeight;
const isMenuAboveButton = buttonRect.bottom > windowHeight / 2;
this.menuPosition.top = isMenuAboveButton ? 'auto' : 'calc(100% + 10px)';
this.menuPosition.bottom = isMenuAboveButton ? '100%' : 'auto';
}
}
},
mounted() {
// Listen to window resize to reposition the menu if needed
window.addEventListener('resize', this.positionMenu);
this.positionMenu(); // Initial positioning
},
beforeDestroy() {
// Cleanup the event listener
window.removeEventListener('resize', this.positionMenu);
},
watch: {
isMenuOpen: 'positionMenu'
}
};
</script>
<style>
.menu-container {
position: relative;
display: inline-block;
}
.menu-button {
background-color: #007bff;
color: white;
padding: 10px;
border: none;
cursor: pointer;
border-radius: 4px;
}
.menu-list {
position: absolute;
background-color: white;
color: black;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
padding: 10px;
max-width: 500px;
z-index: 1000;
}
.slide-enter-active,
.slide-leave-active {
transition: transform 0.2s;
}
.slide-enter-to,
.slide-leave-from {
transform: translateY(-10px);
}
.menu-ul {
list-style: none;
padding: 0;
margin: 0;
}
.menu-li {
cursor: pointer;
display: flex;
align-items: center;
padding: 5px;
}
.menu-icon {
width: 20px;
height: 20px;
margin-right: 8px;
}
<div class="menu-container">
<button @click.prevent="toggleMenu" class="menu-button bg-blue-500 text-white dark:bg-blue-200 dark:text-gray-800 rounded-full flex items-center justify-center w-6 h-6 border-none cursor-pointer hover:bg-blue-400 w-8 h-8 rounded-full object-fill text-red-700 border-2 active:scale-90 hover:z-20 hover:-translate-y-2 duration-150 border-gray-300 border-secondary cursor-pointer" ref="menuButton">
<i data-feather="command" class="w-5 h-5"></i>
</button>
<transition name="slide">
<div v-if="isMenuOpen" class="menu-list flex-grow" :style="menuPosition" ref="menu">
<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 ">
<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>{{ command.name }}</span>
</li>
</ul>
</div>
</transition>
</div>
</template>
.menu-command{
min-width: 200px;
text-align: left;
<script>
import { nextTick } from 'vue'
import feather from 'feather-icons'
export default {
props: {
commands: {
type: Array,
required: true
},
execute_cmd: {
type: Function, // The execute_cmd property should be a function
required: false
}
},
data() {
return {
isMenuOpen: false,
menuPosition: {
bottom: 'auto',
top: 'calc(100% + 10px)' // Initial position: below the button
}
};
},
methods: {
handleClickOutside(event) {
// Close the menu if the click occurs outside the menu container
const menuContainer = this.$refs.menu;
const menuButton = this.$refs.menuButton;
if (menuContainer && !menuContainer.contains(event.target) && !menuButton.contains(event.target)) {
this.isMenuOpen = false;
window.removeEventListener('click', this.handleClickOutside);
}
},
toggleMenu() {
this.positionMenu();
this.isMenuOpen = !this.isMenuOpen;
if (this.isMenuOpen) {
// Attach the click event listener when the menu opens
window.addEventListener('click', this.handleClickOutside);
} else {
// Remove the click event listener when the menu closes
window.removeEventListener('click', this.handleClickOutside);
}
nextTick(() => {
feather.replace()
})
},
executeCommand(command) {
if (typeof this[command.value] === 'function') {
this[command.value]();
}
this.isMenuOpen = false;
if (this.execute_cmd) {
this.execute_cmd(command); // Call the execute_cmd property with the current command
}
},
positionMenu() {
if (this.$refs.menuButton!=undefined){
const buttonRect = this.$refs.menuButton.getBoundingClientRect();
//const menuRect = this.$refs.menu.getBoundingClientRect();
const windowHeight = window.innerHeight;
const isMenuAboveButton = buttonRect.bottom > windowHeight / 2;
this.menuPosition.top = isMenuAboveButton ? 'auto' : 'calc(100% + 10px)';
this.menuPosition.bottom = isMenuAboveButton ? '100%' : 'auto';
}
}
},
mounted() {
// Listen to window resize to reposition the menu if needed
window.addEventListener('resize', this.positionMenu);
this.positionMenu(); // Initial positioning
nextTick(() => {
feather.replace()
})
},
beforeDestroy() {
// Cleanup the event listener
window.removeEventListener('resize', this.positionMenu);
},
watch: {
isMenuOpen: 'positionMenu'
}
</style>
};
</script>
<style>
.menu-container {
position: relative;
display: inline-block;
}
.menu-button {
background-color: #007bff;
color: white;
padding: 10px;
border: none;
cursor: pointer;
border-radius: 4px;
}
.menu-list {
position: absolute;
background-color: white;
color: black;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
padding: 10px;
max-width: 500px;
z-index: 1000;
}
.slide-enter-active,
.slide-leave-active {
transition: transform 0.2s;
}
.slide-enter-to,
.slide-leave-from {
transform: translateY(-10px);
}
.menu-ul {
list-style: none;
padding: 0;
margin: 0;
}
.menu-li {
cursor: pointer;
display: flex;
align-items: center;
padding: 5px;
}
.menu-icon {
width: 20px;
height: 20px;
margin-right: 8px;
}
.menu-command{
min-width: 200px;
text-align: left;
}
</style>

View File

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

View File

@ -1,7 +1,7 @@
<template>
<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"
@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' : ''">
<div :class="!personality.installed ? 'opacity-50' : ''">
@ -19,42 +19,11 @@
<i data-feather="send" class="w-5"></i>
<span class="sr-only">Talk</span>
</button>
<InteractiveMenu :commands="commandsList">
</InteractiveMenu>
</div>
<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 class="">
<div class="">
@ -64,6 +33,21 @@
{{ personality.author }}
</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">
<i data-feather="bookmark" class="w-5 m-1"></i>
<b>Category:&nbsp;</b>
@ -89,6 +73,8 @@ import { nextTick } from 'vue'
import feather from 'feather-icons'
import botImgPlaceholder from "../assets/logo.svg"
import userImgPlaceholder from "../assets/default_user.svg"
import InteractiveMenu from "@/components/InteractiveMenu.vue"
const bUrl = import.meta.env.VITE_LOLLMS_API_BASEURL
export default {
props: {
@ -102,12 +88,30 @@ export default {
onReinstall: Function,
onSettings: Function
},
components:{
InteractiveMenu
},
data() {
return {
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() {
this.isMounted = this.personality.isMounted
@ -118,11 +122,6 @@ export default {
})
},
computed: {
selected_computed(){
return this.selected
}
},
methods: {
getImgUrl() {
return bUrl + this.personality.avatar
@ -134,7 +133,9 @@ selected_computed(){
this.onTalk(this)
},
toggleSelected() {
this.onSelected(this)
if(this.isMounted){
this.onSelected(this)
}
},
reMount(){
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")
configFile.personality_category = personality_path_infos[0]
configFile.personality_folder = personality_path_infos[1]
console.log("Recovered config")
console.log(configFile)
commit('setConfig', configFile);
} catch (error) {
console.log(error.message, 'refreshConfig');
@ -131,12 +132,12 @@ export const store = createStore({
let personalities = []
const catdictionary = await api_get_req("get_all_personalities")
const catkeys = Object.keys(catdictionary); // returns categories
console.log("Personalities recovered:"+this.state.config.personalities)
for (let j = 0; j < catkeys.length; j++) {
const catkey = catkeys[j];
const personalitiesArray = catdictionary[catkey];
const modPersArr = personalitiesArray.map((item) => {
const isMounted = this.state.config.personalities.includes(catkey + '/' + item.folder)
// if (isMounted) {
// console.log(item)
@ -175,7 +176,7 @@ export const store = createStore({
mountedPersArr.push(pers)
}
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)

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'}">
Render
</div>
</div>
<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>
</div>
<div v-else>
@ -48,8 +50,8 @@
</div>
</div>
</div>
<Card title="settings" class="slider-container ml-0 mr-0" :isHorizontal="false" :disableHoverAnimation="true" :disableFocus="true">
<Card title="Model" 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" :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">
<option v-for="model in models" :key="model" :value="model">
{{ model }}
@ -72,8 +74,8 @@
</div>
</Card>
<Card title="Presets" class="slider-container ml-0 mr-0" :isHorizontal="false" :disableHoverAnimation="true" :disableFocus="true">
<select v-model="selectedPreset" class="m-0 border-2 rounded-md shadow-sm w-full">
<Card title="Presets" class="slider-container ml-0 mr-0" :is_subcard="true" :isHorizontal="false" :disableHoverAnimation="true" :disableFocus="true">
<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">
{{ preset.name }}
</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>
</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">
<h3 class="text-gray-600">Temperature</h3>
@ -322,24 +324,6 @@ export default {
Card
},
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 => {
console.log("List models "+response.data)
this.models=response.data
@ -444,6 +428,27 @@ export default {
},
},
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(){
this.selecting_model=true
axios.post("/update_setting", {
@ -452,8 +457,10 @@ export default {
}).then((response) => {
console.log(response);
this.$refs.toast.showToast(`Model changed to this.selectedModel`,4,true)
this.selecting_model=false
}).catch(err=>{
this.$refs.toast.showToast(`Error ${err}`,4,true)
this.selecting_model=false
});
},

View File

@ -29,9 +29,33 @@
<i data-feather="list"></i>
</button>
</div>
<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 v-if="settingsChanged" class="flex gap-3 items-center">
Apply changes:
@ -543,18 +567,11 @@
type="text"
id="db_path"
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"
>
</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>
<td style="min-width: 200px;">
@ -565,18 +582,11 @@
type="checkbox"
id="enable_gpu"
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"
>
</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>
<td style="min-width: 200px;">
@ -587,18 +597,11 @@
type="checkbox"
id="auto_update"
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"
>
</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>
</table>
</div>
@ -614,18 +617,11 @@
type="text"
id="user_name"
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"
>
</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>
<!-- Row 3 -->
<tr>
@ -634,18 +630,10 @@
</td>
<td style="width: 100%;">
<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>
<input type="file" id="avatar-upload" style="display: none" @change="uploadAvatar">
</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>
<!-- Row 4 -->
<tr>
@ -657,18 +645,11 @@
type="checkbox"
id="use_user_name_in_discussions"
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"
>
</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>
</table>
</div>
@ -684,25 +665,19 @@
type="checkbox"
id="auto_speak"
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"
>
</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>
<td style="min-width: 200px;">
<label for="audio_pitch" class="text-sm font-bold" style="margin-right: 1rem;">audio pitch:</label>
</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"
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"
>{{ audio_pitch }}</p>
</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>
@ -728,7 +695,8 @@
<!-- Select element for choosing the input audio language -->
<select
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"
>
<!-- Options with language codes and corresponding language names -->
@ -737,14 +705,6 @@
</option>
</select>
</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>
<td style="min-width: 200px;">
@ -754,7 +714,8 @@
<!-- Select element for choosing the output audio voice -->
<select
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"
>
<!-- Options with available voices in the browser -->
@ -763,14 +724,6 @@
</option>
</select>
</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>
@ -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"
:key="'index-' + index + '-' + pers.name" :personality="pers"
:full_path="pers.full_path"
:on-remount="onRemount"
:selected="configFile.active_personality_id == configFile.personalities.findIndex(item => item === pers.full_path)"
:on-selected="onPersonalitySelected" :on-mounted="onPersonalityMounted" :on-reinstall="onPersonalityReinstall"
:on-settings="onSettingsPersonality" />
@ -1815,6 +1744,7 @@ export default {
},
async constructor() {
console.log("Constructing")
this.isLoading = true
nextTick(() => {
feather.replace()
@ -1982,6 +1912,26 @@ export default {
this.$store.dispatch('refreshDiskUsage');
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) {
console.log('on pers', pers)
// eslint-disable-next-line no-unused-vars
@ -2567,7 +2517,7 @@ export default {
applyConfiguration() {
this.isLoading = true;
axios.post('/apply_settings').then((res) => {
axios.post('/apply_settings', {"config":this.configFile}).then((res) => {
this.isLoading = false;
//console.log('apply-res',res)
if (res.data.status) {
@ -2660,38 +2610,31 @@ export default {
//console.log('asdas',config)
// console.log("all_personalities")
// console.log(dictionary)
const langkeys = Object.keys(dictionary); // returns languages 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
const catkeys = Object.keys(dictionary); // returns categories folder names
for (let j = 0; j < catkeys.length; j++) {
const catkey = catkeys[j];
const personalitiesArray = catdictionary[catkey];
const modPersArr = personalitiesArray.map((item) => {
for (let j = 0; j < catkeys.length; j++) {
const catkey = catkeys[j];
const personalitiesArray = catdictionary[catkey];
const modPersArr = personalitiesArray.map((item) => {
const isMounted = config.personalities.includes(langkey + '/' + catkey + '/' + item.folder)
// if (isMounted) {
// console.log(item)
// }
let newItem = {}
newItem = item
newItem.category = catkey // 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.isMounted = isMounted // add new props to items
return newItem
})
const isMounted = config.personalities.includes(catkey + '/' + item.folder)
// if (isMounted) {
// console.log(item)
// }
let newItem = {}
newItem = item
newItem.category = catkey // add new props to items
newItem.language = langkey // add new props to items
newItem.full_path = catkey + '/' + item.folder // add new props to items
newItem.isMounted = isMounted // add new props to items
return newItem
})
if (this.personalities.length == 0) {
this.personalities = modPersArr
} else {
this.personalities = this.personalities.concat(modPersArr)
}
if (this.personalities.length == 0) {
this.personalities = modPersArr
} else {
this.personalities = this.personalities.concat(modPersArr)
}
}
this.personalities.sort((a, b) => a.name.localeCompare(b.name))
@ -2768,7 +2711,8 @@ export default {
const obj = {
language: pers.language,
category: pers.category,
folder: pers.folder
folder: pers.folder,
language: pers.lang
}
const res = await axios.post('/mount_personality', obj);