mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2025-02-20 17:22:47 +00:00
enhanced ui
This commit is contained in:
parent
967de53cb2
commit
f2f4b610fe
69
app.py
69
app.py
@ -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)
|
||||
|
||||
|
||||
|
||||
|
@ -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
4
web/dist/index.html
vendored
@ -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>
|
||||
|
@ -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}
|
@ -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: {
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user