mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2025-02-20 09:16:15 +00:00
enhanced version
This commit is contained in:
parent
c69adacf68
commit
5c4078c63a
@ -113,7 +113,7 @@ class LoLLMsAPPI(LollmsApplication):
|
||||
def __init__(self, config:LOLLMSConfig, socketio, config_file_path:str, lollms_paths: LollmsPaths) -> None:
|
||||
|
||||
super().__init__("Lollms_webui",config, lollms_paths, callback=self.process_chunk)
|
||||
self.is_ready = True
|
||||
self.buzy = False
|
||||
|
||||
|
||||
self.socketio = socketio
|
||||
@ -516,7 +516,7 @@ class LoLLMsAPPI(LollmsApplication):
|
||||
self.notify("Model not selected. Please select a model", False, client_id)
|
||||
return
|
||||
|
||||
if self.is_ready:
|
||||
if not self.buzy:
|
||||
if self.connections[client_id]["current_discussion"] is None:
|
||||
if self.db.does_last_discussion_have_messages():
|
||||
self.connections[client_id]["current_discussion"] = self.db.create_discussion()
|
||||
@ -540,6 +540,7 @@ class LoLLMsAPPI(LollmsApplication):
|
||||
|
||||
self.socketio.sleep(0.01)
|
||||
ASCIIColors.info("Started generation task")
|
||||
self.buzy=True
|
||||
#tpe = threading.Thread(target=self.start_message_generation, args=(message, message_id, client_id))
|
||||
#tpe.start()
|
||||
else:
|
||||
@ -761,7 +762,7 @@ class LoLLMsAPPI(LollmsApplication):
|
||||
|
||||
if self.config["debug"]:
|
||||
ASCIIColors.yellow(discussion_messages)
|
||||
ASCIIColors.yellow(f"prompt size:{len(tokens)} tokens")
|
||||
ASCIIColors.info(f"prompt size:{tokens.shape} tokens")
|
||||
|
||||
return discussion_messages, message.content, tokens
|
||||
|
||||
@ -887,9 +888,7 @@ class LoLLMsAPPI(LollmsApplication):
|
||||
)
|
||||
def process_chunk(self, chunk, message_type:MSG_TYPE, metadata:dict={}, client_id:int=0):
|
||||
"""
|
||||
0 : a regular message
|
||||
1 : a notification message
|
||||
2 : A hidden message
|
||||
Processes a chunk of generated text
|
||||
"""
|
||||
|
||||
if message_type == MSG_TYPE.MSG_TYPE_STEP:
|
||||
@ -945,7 +944,7 @@ class LoLLMsAPPI(LollmsApplication):
|
||||
self.connections[client_id]["generated_text"] = chunk
|
||||
self.nb_received_tokens += 1
|
||||
ASCIIColors.green(f"Received {self.nb_received_tokens} tokens",end="\r",flush=True)
|
||||
self.update_message(client_id, chunk, metadata)
|
||||
self.update_message(client_id, chunk, metadata, msg_type=message_type)
|
||||
return True
|
||||
# Stream the generated text to the frontend
|
||||
else:
|
||||
@ -1055,6 +1054,8 @@ class LoLLMsAPPI(LollmsApplication):
|
||||
ASCIIColors.success(f" ╔══════════════════════════════════════════════════╗ ")
|
||||
ASCIIColors.success(f" ║ Done ║ ")
|
||||
ASCIIColors.success(f" ╚══════════════════════════════════════════════════╝ ")
|
||||
self.buzy=False
|
||||
|
||||
else:
|
||||
ump = self.config.discussion_prompt_separator +self.config.user_name+": " if self.config.use_user_name_in_discussions else self.personality.user_message_prefix
|
||||
|
||||
@ -1065,5 +1066,6 @@ class LoLLMsAPPI(LollmsApplication):
|
||||
self.notify("No discussion selected!!!",False, client_id)
|
||||
|
||||
print()
|
||||
self.buzy=False
|
||||
return ""
|
||||
|
64
app.py
64
app.py
@ -99,6 +99,7 @@ log = logging.getLogger('werkzeug')
|
||||
log.setLevel(logging.ERROR)
|
||||
|
||||
app = Flask("Lollms-WebUI", static_url_path="/static", static_folder="static")
|
||||
|
||||
# async_mode='gevent', ping_timeout=1200, ping_interval=120,
|
||||
socketio = SocketIO(app, cors_allowed_origins="*", async_mode='threading',engineio_options={'websocket_compression': False, 'websocket_ping_interval': 20, 'websocket_ping_timeout': 120, 'websocket_max_queue': 100})
|
||||
|
||||
@ -236,6 +237,8 @@ class LoLLMsWebUI(LoLLMsAPPI):
|
||||
self.add_endpoint("/list_mounted_personalities", "list_mounted_personalities", self.list_mounted_personalities, methods=["POST"])
|
||||
|
||||
self.add_endpoint("/mount_personality", "mount_personality", self.p_mount_personality, methods=["POST"])
|
||||
self.add_endpoint("/remount_personality", "remount_personality", self.p_remount_personality, methods=["POST"])
|
||||
|
||||
self.add_endpoint("/unmount_personality", "unmount_personality", self.p_unmount_personality, methods=["POST"])
|
||||
self.add_endpoint("/select_personality", "select_personality", self.p_select_personality, methods=["POST"])
|
||||
|
||||
@ -288,9 +291,10 @@ class LoLLMsWebUI(LoLLMsAPPI):
|
||||
)
|
||||
|
||||
self.add_endpoint("/delete_personality", "delete_personality", self.delete_personality, methods=["GET"])
|
||||
|
||||
|
||||
|
||||
self.add_endpoint("/", "", self.index, methods=["GET"])
|
||||
self.add_endpoint("/settings/", "", self.index, methods=["GET"])
|
||||
|
||||
self.add_endpoint("/<path:filename>", "serve_static", self.serve_static, methods=["GET"])
|
||||
self.add_endpoint("/user_infos/<path:filename>", "serve_user_infos", self.serve_user_infos, methods=["GET"])
|
||||
|
||||
@ -932,7 +936,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
|
||||
|
||||
|
||||
def get_generation_status(self):
|
||||
return jsonify({"status":not self.is_ready})
|
||||
return jsonify({"status":self.buzy})
|
||||
|
||||
def stop_gen(self):
|
||||
self.cancel_gen = True
|
||||
@ -1244,6 +1248,60 @@ class LoLLMsWebUI(LoLLMsAPPI):
|
||||
ASCIIColors.error(f"nok : Personality not found @ {pth}")
|
||||
return jsonify({"status": False, "error":f"Personality not found @ {pth}"})
|
||||
|
||||
def p_remount_personality(self):
|
||||
print("- Remounting personality")
|
||||
try:
|
||||
data = request.get_json()
|
||||
# Further processing of the data
|
||||
except Exception as e:
|
||||
print(f"Error occurred while parsing JSON: {e}")
|
||||
return
|
||||
language = data['language']
|
||||
category = data['category']
|
||||
name = data['folder']
|
||||
|
||||
|
||||
|
||||
|
||||
package_path = f"{language}/{category}/{name}"
|
||||
package_full_path = self.lollms_paths.personalities_zoo_path/package_path
|
||||
config_file = package_full_path / "config.yaml"
|
||||
if config_file.exists():
|
||||
ASCIIColors.info(f"Unmounting personality {package_path}")
|
||||
index = self.config["personalities"].index(f"{language}/{category}/{name}")
|
||||
self.config["personalities"].remove(f"{language}/{category}/{name}")
|
||||
if self.config["active_personality_id"]>=index:
|
||||
self.config["active_personality_id"]=0
|
||||
if len(self.config["personalities"])>0:
|
||||
self.mounted_personalities = self.rebuild_personalities()
|
||||
self.personality = self.mounted_personalities[self.config["active_personality_id"]]
|
||||
else:
|
||||
self.personalities = ["english/generic/lollms"]
|
||||
self.mounted_personalities = self.rebuild_personalities()
|
||||
self.personality = self.mounted_personalities[self.config["active_personality_id"]]
|
||||
|
||||
|
||||
ASCIIColors.info(f"Mounting personality {package_path}")
|
||||
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,
|
||||
"personalities":self.config["personalities"],
|
||||
"active_personality_id":self.config["active_personality_id"]
|
||||
})
|
||||
else:
|
||||
return jsonify({"status": True,
|
||||
"personalities":self.config["personalities"],
|
||||
"active_personality_id":self.config["active_personality_id"]
|
||||
})
|
||||
else:
|
||||
pth = str(config_file).replace('\\','/')
|
||||
ASCIIColors.error(f"nok : Personality not found @ {pth}")
|
||||
return jsonify({"status": False, "error":f"Personality not found @ {pth}"})
|
||||
|
||||
def p_unmount_personality(self):
|
||||
print("- Unmounting personality ...")
|
||||
try:
|
||||
|
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-c75baf49.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-9c82748a.css">
|
||||
<script type="module" crossorigin src="/assets/index-16e1e498.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-498e6c2a.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
@ -111,6 +111,7 @@
|
||||
<MountedPersonalitiesList ref="mountedPersList"
|
||||
:onShowPersList="onShowPersListFun"
|
||||
:on-mount-unmount="onMountUnmountFun"
|
||||
:on-remount="onRemount"
|
||||
:on-talk="handleOnTalk"
|
||||
:discussionPersonalities="allDiscussionPersonalities" />
|
||||
</div>
|
||||
@ -338,6 +339,10 @@ export default {
|
||||
console.log('Mounting/unmounting chat')
|
||||
this.$refs.mountedPers.constructor()
|
||||
},
|
||||
onRemount(comp){
|
||||
console.log('Remounting chat')
|
||||
this.$refs.mountedPers.constructor()
|
||||
},
|
||||
computedFileSize(size) {
|
||||
nextTick(() => {
|
||||
feather.replace()
|
||||
|
@ -38,7 +38,7 @@
|
||||
<personality-entry ref="personalitiesZoo" v-for="(pers, index) in this.$store.state.mountedPersArr"
|
||||
:key="'index-' + index + '-' + pers.name" :personality="pers" :full_path="pers.full_path"
|
||||
:selected="configFile.personalities[configFile.active_personality_id] === pers.full_path"
|
||||
:on-selected="onPersonalitySelected" :on-mounted="onPersonalityMounted"
|
||||
:on-selected="onPersonalitySelected" :on-mounted="onPersonalityMounted" :on-remount="onPersonalityRemount"
|
||||
:on-settings="onSettingsPersonality" :on-reinstall="onPersonalityReinstall"
|
||||
:on-talk="handleOnTalk"
|
||||
/>
|
||||
@ -91,6 +91,7 @@ export default {
|
||||
props: {
|
||||
onTalk:Function,
|
||||
onMountUnmount: Function,
|
||||
onRemount: Function,
|
||||
discussionPersonalities: Array,
|
||||
onShowPersList: Function,
|
||||
|
||||
@ -221,6 +222,9 @@ export default {
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
onPersonalityRemount(persItem){
|
||||
this.reMountPersonality(persItem)
|
||||
},
|
||||
async handleOnTalk(pers){
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
@ -346,6 +350,28 @@ export default {
|
||||
}
|
||||
|
||||
},
|
||||
async remount_personality(pers) {
|
||||
if (!pers) { return { 'status': false, 'error': 'no personality - mount_personality' } }
|
||||
|
||||
try {
|
||||
const obj = {
|
||||
language: pers.language,
|
||||
category: pers.category,
|
||||
folder: pers.folder
|
||||
}
|
||||
const res = await axios.post('/remount_personality', obj);
|
||||
|
||||
if (res) {
|
||||
|
||||
return res.data
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error.message, 'remount_personality - settings')
|
||||
return
|
||||
}
|
||||
|
||||
},
|
||||
async unmount_personality(pers) {
|
||||
if (!pers) { return { 'status': false, 'error': 'no personality - unmount_personality' } }
|
||||
|
||||
@ -432,6 +458,37 @@ export default {
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
async reMountPersonality(pers) {
|
||||
|
||||
console.log('remount pers', pers)
|
||||
if (!pers) { return }
|
||||
|
||||
if (!this.configFile.personalities.includes(pers.personality.full_path)) {
|
||||
this.$refs.toast.showToast("Personality not mounted", 4, false)
|
||||
return
|
||||
}
|
||||
|
||||
const res = await this.remount_personality(pers.personality)
|
||||
console.log('remount_personality res', res)
|
||||
|
||||
if (res.status) {
|
||||
this.configFile.personalities = res.personalities
|
||||
this.$refs.toast.showToast("Personality remounted", 4, true)
|
||||
pers.isMounted = true
|
||||
this.toggleMountUnmount()
|
||||
const res2 = await this.select_personality(pers.personality)
|
||||
if (res2.status) {
|
||||
this.$refs.toast.showToast("Selected personality:\n" + pers.personality.name, 4, true)
|
||||
|
||||
}
|
||||
this.getMountedPersonalities()
|
||||
} else {
|
||||
pers.isMounted = false
|
||||
this.$refs.toast.showToast("Could not mount personality\nError: " + res.error, 4, false)
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
async unmountPersonality(pers) {
|
||||
|
||||
|
@ -3,32 +3,32 @@
|
||||
<div class="w-full">
|
||||
<ul class="flex flex-row font-medium">
|
||||
<li>
|
||||
<RouterLink :to="{ name: 'discussions' }" class="link-item">
|
||||
<RouterLink :to="{ name: 'discussions' }" class="link-item dark:link-item-dark">
|
||||
Discussions
|
||||
</RouterLink>
|
||||
</li>
|
||||
<li>
|
||||
<RouterLink :to="{ name: 'settings' }" class="link-item">
|
||||
<RouterLink :to="{ name: 'settings' }" class="link-item dark:link-item-dark">
|
||||
Settings
|
||||
</RouterLink>
|
||||
</li>
|
||||
<li>
|
||||
<RouterLink :to="{ name: 'extensions' }" class="link-item">
|
||||
<RouterLink :to="{ name: 'extensions' }" class="link-item dark:link-item-dark">
|
||||
Extensions
|
||||
</RouterLink>
|
||||
</li>
|
||||
<li>
|
||||
<RouterLink :to="{ name: 'training' }" class="link-item">
|
||||
<RouterLink :to="{ name: 'training' }" class="link-item dark:link-item-dark">
|
||||
Training
|
||||
</RouterLink>
|
||||
</li>
|
||||
<li>
|
||||
<RouterLink :to="{ name: 'quantizing' }" class="link-item">
|
||||
<RouterLink :to="{ name: 'quantizing' }" class="link-item dark:link-item-dark">
|
||||
Quantizing
|
||||
</RouterLink>
|
||||
</li>
|
||||
<li>
|
||||
<RouterLink :to="{ name: 'help' }" class="link-item">
|
||||
<RouterLink :to="{ name: 'help' }" class="link-item dark:link-item-dark">
|
||||
Help
|
||||
</RouterLink>
|
||||
</li>
|
||||
@ -63,7 +63,7 @@
|
||||
font-weight: bold; /* Optional: Add font-weight for emphasis */
|
||||
|
||||
/* Use different colors for dark and light modes */
|
||||
background-color: #b9d2f7; /* Use your theme's 'bg-light-tone' color for light mode */
|
||||
background-color: #82a1d4; /* Use your theme's 'bg-light-tone' color for light mode */
|
||||
color: #000; /* Use your theme's 'primary' color for light mode */
|
||||
|
||||
|
||||
@ -81,9 +81,45 @@
|
||||
|
||||
/* Optional: Change the color when the link is active */
|
||||
.link-item.router-link-active {
|
||||
background-color: #82a1d4; /* Use your theme's 'bg-dark-tone' color for active link in dark mode */
|
||||
background-color: #b9d2f7; /* Use your theme's 'bg-dark-tone' color for active link in dark mode */
|
||||
}
|
||||
|
||||
|
||||
|
||||
.link-item-dark {
|
||||
/* Thin out the links */
|
||||
padding: 0px 20px;
|
||||
margin-bottom: -5px; /* Removes the gap between li elements */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid transparent; /* Ensure all links have the same height */
|
||||
border-radius: 5px 5px 0 0; /* Rounded corners on the top */
|
||||
font-weight: bold; /* Optional: Add font-weight for emphasis */
|
||||
|
||||
/* Use different colors for dark and light modes */
|
||||
background-color: #132e59; /* Use your theme's 'bg-light-tone' color for light mode */
|
||||
color: #000; /* Use your theme's 'primary' color for light mode */
|
||||
|
||||
|
||||
/* Animate the links when hovered */
|
||||
transition: duration-300 ease-in-out transform;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.link-item-dark:hover {
|
||||
background-color: #0cc96a; /* Use your theme's 'primary-light' color for the hover effect */
|
||||
animation-timing-function: ease-in-out;
|
||||
|
||||
}
|
||||
|
||||
/* Optional: Change the color when the link is active */
|
||||
.link-item-dark.router-link-active {
|
||||
background-color: #25477d; /* Use your theme's 'bg-dark-tone' color for active link in dark mode */
|
||||
}
|
||||
|
||||
|
||||
/* Ensure each li extends to the bottom of its container */
|
||||
ul {
|
||||
display: flex;
|
||||
|
@ -48,7 +48,12 @@
|
||||
|
||||
<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="">
|
||||
@ -99,6 +104,7 @@ export default {
|
||||
onTalk:Function,
|
||||
onSelected: Function,
|
||||
onMounted: Function,
|
||||
onRemount: Function,
|
||||
onReinstall: Function,
|
||||
onSettings: Function
|
||||
},
|
||||
@ -136,6 +142,9 @@ selected_computed(){
|
||||
toggleSelected() {
|
||||
this.onSelected(this)
|
||||
},
|
||||
reMount(){
|
||||
this.onRemount(this)
|
||||
},
|
||||
toggleMounted() {
|
||||
this.onMounted(this)
|
||||
},
|
||||
|
@ -1256,6 +1256,7 @@ export default {
|
||||
console.log("--------------------")
|
||||
console.log(msgId);
|
||||
if (!res.data.status) {
|
||||
console.log('generate_msg_from');
|
||||
socket.emit('generate_msg_from', { prompt: msg, id: msgId });
|
||||
}
|
||||
else {
|
||||
|
@ -932,7 +932,6 @@
|
||||
<!-- SEARCH BAR -->
|
||||
<div class="mx-2 mb-4">
|
||||
|
||||
<form>
|
||||
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
|
||||
@ -973,7 +972,6 @@
|
||||
<!-- @input="filterPersonalities()" -->
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<div v-if="searchModel">
|
||||
@ -1250,8 +1248,6 @@
|
||||
<div :class="{ 'hidden': pzc_collapsed }" class="flex flex-col mb-2 px-3 pb-0">
|
||||
<!-- SEARCH BAR -->
|
||||
<div class="mx-2 mb-4">
|
||||
|
||||
<form>
|
||||
<label for="personality-search"
|
||||
class="mb-2 text-sm font-medium text-gray-900 sr-only dark:text-white">Search</label>
|
||||
<div class="relative">
|
||||
@ -1293,7 +1289,6 @@
|
||||
<!-- @input="filterPersonalities()" -->
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<div class="mx-2 mb-4" v-if="!searchPersonality">
|
||||
@ -3010,6 +3005,7 @@ export default {
|
||||
event.target.src = defaultPersonalityImgPlaceholder
|
||||
},
|
||||
searchPersonality_func() {
|
||||
|
||||
clearTimeout(this.searchPersonalityTimer)
|
||||
if (this.searchPersonality) {
|
||||
this.searchPersonalityInProgress = true
|
||||
@ -3030,6 +3026,7 @@ export default {
|
||||
console.log("Getting voices")
|
||||
this.getVoices();
|
||||
},
|
||||
|
||||
activated() {
|
||||
if (this.isMounted) {
|
||||
this.constructor()
|
||||
|
Loading…
x
Reference in New Issue
Block a user