mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2025-02-22 09:50:53 +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}")
|
print(f"Couldn't load backend card : {f}\n\t{ex}")
|
||||||
return jsonify(bindings)
|
return jsonify(bindings)
|
||||||
|
|
||||||
|
|
||||||
def list_extensions(self):
|
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 ===========================
|
# =================== Lord Of Large Language Models Configuration file ===========================
|
||||||
version: 23
|
version: 24
|
||||||
binding_name: null
|
binding_name: null
|
||||||
model_name: null
|
model_name: null
|
||||||
|
|
||||||
@ -27,6 +27,9 @@ personalities: ["generic/lollms"]
|
|||||||
active_personality_id: 0
|
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)
|
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_name: user
|
||||||
user_description: ""
|
user_description: ""
|
||||||
use_user_name_in_discussions: false
|
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">
|
<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-9c2f65d2.js"></script>
|
<script type="module" crossorigin src="/assets/index-fbad426a.js"></script>
|
||||||
<link rel="stylesheet" href="/assets/index-0865ea30.css">
|
<link rel="stylesheet" href="/assets/index-0c8a7802.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
@ -39,6 +39,7 @@ export const store = createStore({
|
|||||||
ramUsage:null,
|
ramUsage:null,
|
||||||
vramUsage:null,
|
vramUsage:null,
|
||||||
extensionsZoo:null,
|
extensionsZoo:null,
|
||||||
|
activeExtensions:null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
@ -79,6 +80,9 @@ export const store = createStore({
|
|||||||
state.vramUsage = vramUsage;
|
state.vramUsage = vramUsage;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setActiveExtensions(state, activeExtensions) {
|
||||||
|
state.activeExtensions = activeExtensions;
|
||||||
|
},
|
||||||
setExtensionsZoo(state, extensionsZoo) {
|
setExtensionsZoo(state, extensionsZoo) {
|
||||||
state.extensionsZoo = extensionsZoo;
|
state.extensionsZoo = extensionsZoo;
|
||||||
},
|
},
|
||||||
@ -117,6 +121,10 @@ export const store = createStore({
|
|||||||
getVramUsage(state) {
|
getVramUsage(state) {
|
||||||
return state.vramUsage;
|
return state.vramUsage;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getActiveExtensions(state) {
|
||||||
|
return state.activeExtensions;
|
||||||
|
},
|
||||||
getExtensionsZoo(state) {
|
getExtensionsZoo(state) {
|
||||||
return state.extensionsZoo;
|
return state.extensionsZoo;
|
||||||
},
|
},
|
||||||
@ -203,7 +211,6 @@ export const store = createStore({
|
|||||||
let mountedPersArr = []
|
let mountedPersArr = []
|
||||||
// console.log('perrs listo',this.state.personalities)
|
// console.log('perrs listo',this.state.personalities)
|
||||||
const indicesToRemove = [];
|
const indicesToRemove = [];
|
||||||
console.log("Personalities", this.state.personalities)
|
|
||||||
for (let i = 0; i < this.state.config.personalities.length; i++) {
|
for (let i = 0; i < this.state.config.personalities.length; i++) {
|
||||||
const full_path_item = this.state.config.personalities[i]
|
const full_path_item = this.state.config.personalities[i]
|
||||||
const parts = full_path_item.split(':')
|
const parts = full_path_item.split(':')
|
||||||
@ -235,9 +242,7 @@ export const store = createStore({
|
|||||||
this.state.config.active_personality_id -= 1;
|
this.state.config.active_personality_id -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log("Personalities", this.state.personalities)
|
|
||||||
|
|
||||||
console.log("Mounted personalities : ", mountedPersArr)
|
|
||||||
commit('setMountedPersArr', 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])]
|
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)
|
commit('setModelsArr',modelsArr)
|
||||||
},
|
},
|
||||||
async refreshExtensionsZoo({ commit }) {
|
async refreshExtensionsZoo({ commit }) {
|
||||||
let extensionsZoo = await api_get_req("list_extensions")
|
let extensions = []
|
||||||
commit('setExtensionsZoo',extensionsZoo)
|
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 }) {
|
async refreshDiskUsage({ commit }) {
|
||||||
@ -388,8 +433,27 @@ function logObjectProperties(obj) {
|
|||||||
console.log(logString);
|
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(router)
|
||||||
app.use(store)
|
app.use(store)
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|
||||||
export{logObjectProperties, copyObject}
|
export{logObjectProperties, copyObject, flattenObject}
|
@ -1,21 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<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-if="activeExtensions.length > 0">
|
||||||
<div v-for="extension in activeExtensions" :key="extension.name" @click="showExtensionPage(extension)">
|
<div v-for="extension in activeExtensions" :key="extension.name" @click="showExtensionPage(extension)">
|
||||||
<div :class="{ 'active-tab': extension === activeExtension }">{{ extension.name }}</div>
|
<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>
|
||||||
<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>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import axios from "axios";
|
||||||
|
import feather from 'feather-icons'
|
||||||
|
import {flattenObject} from '../main.js'
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -25,7 +28,9 @@ data() {
|
|||||||
computed: {
|
computed: {
|
||||||
activeExtensions() {
|
activeExtensions() {
|
||||||
// Filter the extensions to get only active ones
|
// 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: {
|
methods: {
|
||||||
|
@ -1188,7 +1188,7 @@
|
|||||||
<input type="search"
|
<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"
|
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"
|
placeholder="Search models..." required v-model="searchModel"
|
||||||
@keyup.stop="searchModel_func">
|
@keyup.enter="searchModel_func">
|
||||||
<button v-if="searchModel" @click.stop="searchModel = ''" type="button"
|
<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">
|
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>
|
Clear search</button>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user