enhanced ui

This commit is contained in:
Saifeddine ALOUI 2023-10-03 01:13:02 +02:00
parent 967de53cb2
commit f2f4b610fe
8 changed files with 201 additions and 62 deletions

69
app.py
View File

@ -1008,8 +1008,75 @@ class LoLLMsWebUI(LoLLMsAPPI):
print(f"Couldn't load backend card : {f}\n\t{ex}")
return jsonify(bindings)
def list_extensions(self):
return jsonify([])
ASCIIColors.yellow("Listing all extensions")
extensions_folder = self.lollms_paths.extensions_zoo_path
extensions = {}
for category_folder in extensions_folder.iterdir():
cat = category_folder.stem
if category_folder.is_dir() and not category_folder.stem.startswith('.'):
extensions[category_folder.name] = []
for extensions_folder in category_folder.iterdir():
pers = extensions_folder.stem
if extensions_folder.is_dir() and not extensions_folder.stem.startswith('.'):
extension_info = {"folder":extensions_folder.stem}
config_path = extensions_folder / 'card.yaml'
if not config_path.exists():
continue
try:
with open(config_path) as config_file:
config_data = yaml.load(config_file, Loader=yaml.FullLoader)
extension_info['name'] = config_data.get('name',"No Name")
extension_info['author'] = config_data.get('author', 'ParisNeo')
extension_info['description'] = config_data.get('personality_description',"")
extension_info['version'] = config_data.get('version', '1.0.0')
extension_info['installed'] = (self.lollms_paths.personal_configuration_path/f"personality_{extensions_folder.stem}.yaml").exists()
extension_info['help'] = config_data.get('help', '')
real_assets_path = extensions_folder/ 'assets'
assets_path = Path("extensions") / cat / pers / 'assets'
gif_logo_path = assets_path / 'logo.gif'
webp_logo_path = assets_path / 'logo.webp'
png_logo_path = assets_path / 'logo.png'
jpg_logo_path = assets_path / 'logo.jpg'
jpeg_logo_path = assets_path / 'logo.jpeg'
svg_logo_path = assets_path / 'logo.svg'
bmp_logo_path = assets_path / 'logo.bmp'
gif_logo_path_ = real_assets_path / 'logo.gif'
webp_logo_path_ = real_assets_path / 'logo.webp'
png_logo_path_ = real_assets_path / 'logo.png'
jpg_logo_path_ = real_assets_path / 'logo.jpg'
jpeg_logo_path_ = real_assets_path / 'logo.jpeg'
svg_logo_path_ = real_assets_path / 'logo.svg'
bmp_logo_path_ = real_assets_path / 'logo.bmp'
extension_info['has_logo'] = png_logo_path.is_file() or gif_logo_path.is_file()
if gif_logo_path_.exists():
extension_info['avatar'] = str(gif_logo_path).replace("\\","/")
elif webp_logo_path_.exists():
extension_info['avatar'] = str(webp_logo_path).replace("\\","/")
elif png_logo_path_.exists():
extension_info['avatar'] = str(png_logo_path).replace("\\","/")
elif jpg_logo_path_.exists():
extension_info['avatar'] = str(jpg_logo_path).replace("\\","/")
elif jpeg_logo_path_.exists():
extension_info['avatar'] = str(jpeg_logo_path).replace("\\","/")
elif svg_logo_path_.exists():
extension_info['avatar'] = str(svg_logo_path).replace("\\","/")
elif bmp_logo_path_.exists():
extension_info['avatar'] = str(bmp_logo_path).replace("\\","/")
else:
extension_info['avatar'] = ""
extensions[category_folder.name].append(extension_info)
except Exception as ex:
ASCIIColors.warning(f"Couldn't load personality from {extensions_folder} [{ex}]")
trace_exception(ex)
return json.dumps(extensions)

View File

@ -1,5 +1,5 @@
# =================== Lord Of Large Language Models Configuration file ===========================
version: 23
version: 24
binding_name: null
model_name: null
@ -27,6 +27,9 @@ personalities: ["generic/lollms"]
active_personality_id: 0
override_personality_model_parameters: false #if true the personality parameters are overriden by those of the configuration (may affect personality behaviour)
extensions: []
user_name: user
user_description: ""
use_user_name_in_discussions: false

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-9c2f65d2.js"></script>
<link rel="stylesheet" href="/assets/index-0865ea30.css">
<script type="module" crossorigin src="/assets/index-fbad426a.js"></script>
<link rel="stylesheet" href="/assets/index-0c8a7802.css">
</head>
<body>
<div id="app"></div>

View File

@ -39,6 +39,7 @@ export const store = createStore({
ramUsage:null,
vramUsage:null,
extensionsZoo:null,
activeExtensions:null,
}
},
mutations: {
@ -79,6 +80,9 @@ export const store = createStore({
state.vramUsage = vramUsage;
},
setActiveExtensions(state, activeExtensions) {
state.activeExtensions = activeExtensions;
},
setExtensionsZoo(state, extensionsZoo) {
state.extensionsZoo = extensionsZoo;
},
@ -117,6 +121,10 @@ export const store = createStore({
getVramUsage(state) {
return state.vramUsage;
},
getActiveExtensions(state) {
return state.activeExtensions;
},
getExtensionsZoo(state) {
return state.extensionsZoo;
},
@ -203,7 +211,6 @@ export const store = createStore({
let mountedPersArr = []
// console.log('perrs listo',this.state.personalities)
const indicesToRemove = [];
console.log("Personalities", this.state.personalities)
for (let i = 0; i < this.state.config.personalities.length; i++) {
const full_path_item = this.state.config.personalities[i]
const parts = full_path_item.split(':')
@ -235,9 +242,7 @@ export const store = createStore({
this.state.config.active_personality_id -= 1;
}
}
console.log("Personalities", this.state.personalities)
console.log("Mounted personalities : ", mountedPersArr)
commit('setMountedPersArr', mountedPersArr);
this.state.mountedPers = this.state.personalities[this.state.personalities.findIndex(item => item.full_path == this.state.config.personalities[this.state.config.active_personality_id] || item.full_path+':'+item.language ==this.state.config.personalities[this.state.config.active_personality_id])]
@ -260,8 +265,48 @@ export const store = createStore({
commit('setModelsArr',modelsArr)
},
async refreshExtensionsZoo({ commit }) {
let extensionsZoo = await api_get_req("list_extensions")
commit('setExtensionsZoo',extensionsZoo)
let extensions = []
let catdictionary = await api_get_req("list_extensions")
const catkeys = Object.keys(catdictionary); // returns categories
console.log("Extensions recovered:"+this.state.config.extensions)
for (let j = 0; j < catkeys.length; j++) {
const catkey = catkeys[j];
const extensionsArray = catdictionary[catkey];
const modExtArr = extensionsArray.map((item) => {
let isMounted = false;
for(const extension of this.state.config.personalities){
if(extension.includes(catkey + '/' + item.folder)){
isMounted = true;
}
}
// if (isMounted) {
// console.log(item)
// }
let newItem = {}
newItem = item
newItem.category = catkey // 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 (extensions.length == 0) {
extensions = modExtArr
} else {
extensions = extensions.concat(modExtArr)
}
}
extensions.sort((a, b) => a.name.localeCompare(b.name))
commit('setActiveExtensions', this.state.config.extensions);
console.log("Done loading extensions")
commit('setExtensionsZoo',extensions)
},
async refreshDiskUsage({ commit }) {
@ -388,8 +433,27 @@ function logObjectProperties(obj) {
console.log(logString);
}
function flattenObject(obj, parentKey = "") {
let result = [];
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
const newKey = parentKey ? `${parentKey}/${key}` : key;
if (typeof obj[key] === "object") {
const nestedFields = flattenObject(obj[key], newKey);
result = result.concat(nestedFields);
} else {
result.push(newKey);
}
}
}
return result;
}
app.use(router)
app.use(store)
app.mount('#app')
export{logObjectProperties, copyObject}
export{logObjectProperties, copyObject, flattenObject}

View File

@ -1,21 +1,24 @@
<template>
<div>
<div v-if="activeExtensions.length > 0">
<div v-for="extension in activeExtensions" :key="extension.name" @click="showExtensionPage(extension)">
<div :class="{ 'active-tab': extension === activeExtension }">{{ extension.name }}</div>
<div class="container overflow-y-scroll flex flex-col shadow-lg p-10 pt-0 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">
<div v-if="activeExtensions.length > 0">
<div v-for="extension in activeExtensions" :key="extension.name" @click="showExtensionPage(extension)">
<div :class="{ 'active-tab': extension === activeExtension }">{{ extension.name }}</div>
</div>
<div v-if="activeExtension">
<!-- Render the selected extension's page here -->
<iframe :src="activeExtension.page" width="100%" height="500px" frameborder="0"></iframe>
</div>
</div>
<div v-else>
<p>No extension is active. Please install and activate an extension.</p>
</div>
</div>
<div v-if="activeExtension">
<!-- Render the selected extension's page here -->
<iframe :src="activeExtension.page" width="100%" height="500px" frameborder="0"></iframe>
</div>
</div>
<div v-else>
<p>No extension is active. Please install and activate an extension.</p>
</div>
</div>
</template>
<script>
import axios from "axios";
import feather from 'feather-icons'
import {flattenObject} from '../main.js'
export default {
data() {
return {
@ -25,7 +28,9 @@ data() {
computed: {
activeExtensions() {
// Filter the extensions to get only active ones
return this.$store.state.extensionsZoo.filter((extension) => extension.is_active);
console.log(this.$store.state.extensionsZoo)
console.log(flattenObject(this.$store.state.extensionsZoo))
return this.$store.state.extensionsZoo;
},
},
methods: {

View File

@ -1188,7 +1188,7 @@
<input type="search"
class="block w-full p-4 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 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"
placeholder="Search models..." required v-model="searchModel"
@keyup.stop="searchModel_func">
@keyup.enter="searchModel_func">
<button v-if="searchModel" @click.stop="searchModel = ''" type="button"
class="text-white absolute right-2.5 bottom-2.5 bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
Clear search</button>