lollms-webui/app.py

1542 lines
64 KiB
Python
Raw Normal View History

2023-04-11 10:50:07 +00:00
######
2023-06-08 06:58:02 +00:00
# Project : lollms-webui
2023-04-11 10:50:07 +00:00
# Author : ParisNeo with the help of the community
# Supported by Nomic-AI
2023-05-21 20:46:02 +00:00
# license : Apache 2.0
2023-04-11 10:50:07 +00:00
# Description :
# A front end Flask application for llamacpp models.
# The official GPT4All Web ui
# Made by the community for the community
######
2023-04-20 17:30:03 +00:00
__author__ = "parisneo"
2023-06-08 06:58:02 +00:00
__github__ = "https://github.com/ParisNeo/lollms-webui"
2023-04-20 17:30:03 +00:00
__copyright__ = "Copyright 2023, "
__license__ = "Apache 2.0"
2023-04-27 23:39:57 +00:00
import os
import logging
2023-04-06 19:12:49 +00:00
import argparse
import json
2023-04-06 19:12:49 +00:00
import re
import traceback
2023-04-08 10:25:40 +00:00
import sys
2023-05-11 19:36:52 +00:00
from tqdm import tqdm
import subprocess
import signal
2023-06-21 22:43:59 +00:00
from lollms.config import InstallOption
from lollms.binding import LOLLMSConfig, BindingBuilder, LLMBinding
2023-06-10 13:16:28 +00:00
from lollms.personality import AIPersonality, MSG_TYPE
2023-06-21 11:06:01 +00:00
from lollms.config import BaseConfig
2023-07-07 22:25:04 +00:00
from lollms.helpers import ASCIIColors, trace_exception
2023-06-10 13:16:28 +00:00
from lollms.paths import LollmsPaths
2023-05-24 15:28:22 +00:00
from api.db import DiscussionsDB, Discussion
2023-06-08 06:58:02 +00:00
from api.helpers import compare_lists
from flask import (
Flask,
Response,
jsonify,
render_template,
request,
stream_with_context,
2023-04-08 17:55:33 +00:00
send_from_directory
)
2023-06-26 10:45:46 +00:00
2023-04-27 14:44:22 +00:00
from flask_socketio import SocketIO, emit
2023-04-08 17:55:33 +00:00
from pathlib import Path
2023-05-20 13:50:14 +00:00
import yaml
from geventwebsocket.handler import WebSocketHandler
2023-05-13 22:24:26 +00:00
import logging
2023-05-28 06:47:57 +00:00
import psutil
2023-06-21 11:06:01 +00:00
from lollms.main_config import LOLLMSConfig
2023-06-22 07:46:33 +00:00
from typing import Optional
2023-07-05 00:19:11 +00:00
import gc
2023-05-28 06:47:57 +00:00
2023-07-04 09:26:57 +00:00
import gc
2023-05-13 22:24:26 +00:00
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
app = Flask("GPT4All-WebUI", static_url_path="/static", static_folder="static")
2023-07-06 09:37:12 +00:00
# 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})
2023-05-02 20:53:27 +00:00
2023-04-27 23:39:57 +00:00
app.config['SECRET_KEY'] = 'secret!'
# Set the logging level to WARNING or higher
logging.getLogger('socketio').setLevel(logging.WARNING)
logging.getLogger('engineio').setLevel(logging.WARNING)
2023-05-18 18:00:48 +00:00
logging.getLogger('werkzeug').setLevel(logging.ERROR)
logging.basicConfig(level=logging.WARNING)
import time
2023-05-24 15:28:22 +00:00
from api.config import load_config, save_config
2023-06-04 23:21:12 +00:00
from api import LoLLMsAPPI
2023-04-14 15:11:40 +00:00
import shutil
2023-04-16 21:22:09 +00:00
import markdown
2023-06-25 17:22:16 +00:00
import socket
2023-06-25 17:22:16 +00:00
def get_ip_address():
# Create a socket object
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# Connect to a remote host (doesn't matter which one)
sock.connect(('8.8.8.8', 80))
# Get the local IP address of the socket
ip_address = sock.getsockname()[0]
return ip_address
except socket.error:
return None
finally:
# Close the socket
sock.close()
2023-06-04 23:21:12 +00:00
class LoLLMsWebUI(LoLLMsAPPI):
2023-06-10 13:16:28 +00:00
def __init__(self, _app, _socketio, config:LOLLMSConfig, config_file_path:Path|str, lollms_paths:LollmsPaths) -> None:
2023-07-04 00:19:20 +00:00
if len(config.personalities)==0:
config.personalities.append("english/generic/lollms")
config["active_personality_id"] = 0
config.save_config()
if config["active_personality_id"]>=len(config["personalities"]) or config["active_personality_id"]<0:
config["active_personality_id"] = 0
2023-06-10 13:16:28 +00:00
super().__init__(config, _socketio, config_file_path, lollms_paths)
self.app = _app
self.cancel_gen = False
2023-06-04 23:21:12 +00:00
app.template_folder = "web/dist"
2023-07-04 00:19:20 +00:00
if len(config["personalities"])>0:
self.personality_language= config["personalities"][config["active_personality_id"]].split("/")[0]
self.personality_category= config["personalities"][config["active_personality_id"]].split("/")[1]
self.personality_name= config["personalities"][config["active_personality_id"]].split("/")[2]
else:
self.personality_language = "english"
self.personality_category = "generic"
self.personality_name = "lollms"
# =========================================================================================
# Endpoints
# =========================================================================================
2023-06-10 13:49:41 +00:00
2023-07-13 23:42:29 +00:00
self.add_endpoint("/reload_binding", "reload_binding", self.reload_binding, methods=["POST"])
2023-06-26 10:45:46 +00:00
self.add_endpoint("/install_model_from_path", "install_model_from_path", self.install_model_from_path, methods=["GET"])
2023-06-15 19:19:19 +00:00
self.add_endpoint("/reinstall_binding", "reinstall_binding", self.reinstall_binding, methods=["POST"])
2023-07-05 23:01:17 +00:00
self.add_endpoint("/reinstall_personality", "reinstall_personality", self.reinstall_personality, methods=["POST"])
2023-06-10 13:49:41 +00:00
self.add_endpoint("/switch_personal_path", "switch_personal_path", self.switch_personal_path, methods=["POST"])
2023-06-07 07:39:38 +00:00
self.add_endpoint("/add_reference_to_local_model", "add_reference_to_local_model", self.add_reference_to_local_model, methods=["POST"])
2023-06-06 18:43:38 +00:00
self.add_endpoint("/send_file", "send_file", self.send_file, methods=["POST"])
2023-06-26 14:52:58 +00:00
self.add_endpoint("/upload_model", "upload_model", self.upload_model, methods=["POST"])
2023-06-09 14:49:13 +00:00
self.add_endpoint("/list_mounted_personalities", "list_mounted_personalities", self.list_mounted_personalities, methods=["POST"])
2023-07-04 00:19:20 +00:00
self.add_endpoint("/mount_personality", "mount_personality", self.p_mount_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"])
2023-06-22 08:10:52 +00:00
self.add_endpoint("/get_personality_settings", "get_personality_settings", self.get_personality_settings, methods=["POST"])
2023-06-22 08:20:16 +00:00
self.add_endpoint("/get_active_personality_settings", "get_active_personality_settings", self.get_active_personality_settings, methods=["GET"])
self.add_endpoint("/get_active_binding_settings", "get_active_binding_settings", self.get_active_binding_settings, methods=["GET"])
2023-06-22 09:45:06 +00:00
self.add_endpoint("/set_active_personality_settings", "set_active_personality_settings", self.set_active_personality_settings, methods=["POST"])
self.add_endpoint("/set_active_binding_settings", "set_active_binding_settings", self.set_active_binding_settings, methods=["POST"])
2023-05-28 06:47:57 +00:00
self.add_endpoint(
2023-05-28 06:53:54 +00:00
"/disk_usage", "disk_usage", self.disk_usage, methods=["GET"]
2023-05-28 06:47:57 +00:00
)
2023-06-06 18:23:33 +00:00
self.add_endpoint(
"/ram_usage", "ram_usage", self.ram_usage, methods=["GET"]
)
2023-06-22 07:46:33 +00:00
self.add_endpoint(
"/vram_usage", "vram_usage", self.vram_usage, methods=["GET"]
)
2023-06-06 18:23:33 +00:00
2023-05-28 06:47:57 +00:00
2023-04-20 17:30:03 +00:00
self.add_endpoint(
2023-05-25 21:24:14 +00:00
"/list_bindings", "list_bindings", self.list_bindings, methods=["GET"]
2023-04-20 17:30:03 +00:00
)
2023-04-10 08:27:25 +00:00
self.add_endpoint(
"/list_models", "list_models", self.list_models, methods=["GET"]
)
2023-04-20 17:30:03 +00:00
self.add_endpoint(
"/list_personalities_languages", "list_personalities_languages", self.list_personalities_languages, methods=["GET"]
)
self.add_endpoint(
"/list_personalities_categories", "list_personalities_categories", self.list_personalities_categories, methods=["GET"]
)
2023-04-13 22:47:20 +00:00
self.add_endpoint(
"/list_personalities", "list_personalities", self.list_personalities, methods=["GET"]
)
2023-04-14 00:10:22 +00:00
self.add_endpoint(
"/list_languages", "list_languages", self.list_languages, methods=["GET"]
)
2023-04-10 08:27:25 +00:00
self.add_endpoint(
"/list_discussions", "list_discussions", self.list_discussions, methods=["GET"]
)
2023-04-08 17:55:33 +00:00
2023-05-23 21:12:07 +00:00
self.add_endpoint("/delete_personality", "delete_personality", self.delete_personality, methods=["GET"])
2023-04-20 17:30:03 +00:00
self.add_endpoint("/", "", self.index, methods=["GET"])
2023-05-02 20:53:27 +00:00
self.add_endpoint("/<path:filename>", "serve_static", self.serve_static, methods=["GET"])
2023-05-29 22:37:09 +00:00
self.add_endpoint("/images/<path:filename>", "serve_images", self.serve_images, methods=["GET"])
self.add_endpoint("/bindings/<path:filename>", "serve_bindings", self.serve_bindings, methods=["GET"])
2023-05-05 13:01:38 +00:00
self.add_endpoint("/personalities/<path:filename>", "serve_personalities", self.serve_personalities, methods=["GET"])
2023-05-20 23:10:01 +00:00
self.add_endpoint("/outputs/<path:filename>", "serve_outputs", self.serve_outputs, methods=["GET"])
2023-06-07 07:39:38 +00:00
self.add_endpoint("/data/<path:filename>", "serve_data", self.serve_data, methods=["GET"])
2023-06-10 00:48:19 +00:00
self.add_endpoint("/help/<path:filename>", "serve_help", self.serve_help, methods=["GET"])
2023-06-07 07:39:38 +00:00
self.add_endpoint("/uploads/<path:filename>", "serve_uploads", self.serve_uploads, methods=["GET"])
2023-05-13 22:24:26 +00:00
2023-05-02 20:53:27 +00:00
2023-04-10 08:27:25 +00:00
self.add_endpoint("/export_discussion", "export_discussion", self.export_discussion, methods=["GET"])
self.add_endpoint("/export", "export", self.export, methods=["GET"])
self.add_endpoint(
"/new_discussion", "new_discussion", self.new_discussion, methods=["GET"]
)
2023-04-23 22:19:15 +00:00
self.add_endpoint("/stop_gen", "stop_gen", self.stop_gen, methods=["GET"])
self.add_endpoint("/rename", "rename", self.rename, methods=["POST"])
2023-05-04 14:38:03 +00:00
self.add_endpoint("/edit_title", "edit_title", self.edit_title, methods=["POST"])
self.add_endpoint(
"/load_discussion", "load_discussion", self.load_discussion, methods=["POST"]
)
self.add_endpoint(
"/delete_discussion",
"delete_discussion",
self.delete_discussion,
methods=["POST"],
)
self.add_endpoint(
"/update_message", "update_message", self.update_message, methods=["GET"]
)
self.add_endpoint(
"/message_rank_up", "message_rank_up", self.message_rank_up, methods=["GET"]
)
self.add_endpoint(
"/message_rank_down", "message_rank_down", self.message_rank_down, methods=["GET"]
)
2023-04-13 10:31:48 +00:00
self.add_endpoint(
"/delete_message", "delete_message", self.delete_message, methods=["GET"]
)
self.add_endpoint(
2023-05-25 21:24:14 +00:00
"/set_binding", "set_binding", self.set_binding, methods=["POST"]
)
2023-04-23 19:05:39 +00:00
self.add_endpoint(
"/set_model", "set_model", self.set_model, methods=["POST"]
)
2023-04-07 21:22:17 +00:00
2023-04-08 17:55:33 +00:00
self.add_endpoint(
2023-04-12 20:36:03 +00:00
"/get_config", "get_config", self.get_config, methods=["GET"]
2023-04-08 17:55:33 +00:00
)
2023-06-07 22:54:01 +00:00
self.add_endpoint(
"/get_current_personality_path_infos", "get_current_personality_path_infos", self.get_current_personality_path_infos, methods=["GET"]
)
2023-05-10 21:33:08 +00:00
self.add_endpoint(
"/get_available_models", "get_available_models", self.get_available_models, methods=["GET"]
)
2023-05-11 19:36:52 +00:00
2023-04-11 20:56:15 +00:00
2023-04-11 23:34:50 +00:00
self.add_endpoint(
"/extensions", "extensions", self.extensions, methods=["GET"]
)
self.add_endpoint(
"/training", "training", self.training, methods=["GET"]
)
2023-04-13 10:31:48 +00:00
self.add_endpoint(
"/main", "main", self.main, methods=["GET"]
)
self.add_endpoint(
"/settings", "settings", self.settings, methods=["GET"]
)
2023-04-11 23:34:50 +00:00
2023-04-11 20:56:15 +00:00
self.add_endpoint(
"/help", "help", self.help, methods=["GET"]
)
2023-04-27 14:44:22 +00:00
self.add_endpoint(
"/get_generation_status", "get_generation_status", self.get_generation_status, methods=["GET"]
)
2023-04-27 14:44:22 +00:00
self.add_endpoint(
"/update_setting", "update_setting", self.update_setting, methods=["POST"]
)
2023-05-18 18:00:48 +00:00
self.add_endpoint(
"/apply_settings", "apply_settings", self.apply_settings, methods=["POST"]
)
self.add_endpoint(
"/save_settings", "save_settings", self.save_settings, methods=["POST"]
)
2023-05-06 20:49:56 +00:00
self.add_endpoint(
"/get_current_personality", "get_current_personality", self.get_current_personality, methods=["GET"]
)
2023-04-27 14:44:22 +00:00
2023-05-20 13:50:14 +00:00
self.add_endpoint(
"/get_all_personalities", "get_all_personalities", self.get_all_personalities, methods=["GET"]
)
2023-05-23 21:12:07 +00:00
self.add_endpoint(
"/get_personality", "get_personality", self.get_personality, methods=["GET"]
)
2023-05-20 13:50:14 +00:00
self.add_endpoint(
"/reset", "reset", self.reset, methods=["GET"]
)
2023-05-24 14:08:42 +00:00
self.add_endpoint(
"/export_multiple_discussions", "export_multiple_discussions", self.export_multiple_discussions, methods=["POST"]
)
2023-05-29 18:24:25 +00:00
self.add_endpoint(
"/import_multiple_discussions", "import_multiple_discussions", self.import_multiple_discussions, methods=["POST"]
)
2023-05-24 14:08:42 +00:00
def export_multiple_discussions(self):
data = request.get_json()
discussion_ids = data["discussion_ids"]
2023-05-24 15:41:27 +00:00
discussions = self.db.export_discussions_to_json(discussion_ids)
return jsonify(discussions)
2023-05-24 14:08:42 +00:00
2023-05-29 18:24:25 +00:00
def import_multiple_discussions(self):
2023-05-30 12:11:30 +00:00
discussions = request.get_json()["jArray"]
self.db.import_from_json(discussions)
2023-05-29 18:24:25 +00:00
return jsonify(discussions)
def reset(self):
os.kill(os.getpid(), signal.SIGINT) # Send the interrupt signal to the current process
2023-05-25 06:19:49 +00:00
subprocess.Popen(['python', 'app.py']) # Restart the app using subprocess
return 'App is resetting...'
def save_settings(self):
2023-06-04 23:21:12 +00:00
self.config.save_config(self.config_file_path)
if self.config["debug"]:
print("Configuration saved")
# Tell that the setting was changed
self.socketio.emit('save_settings', {"status":True})
return jsonify({"status":True})
2023-05-06 20:49:56 +00:00
2023-05-06 20:49:56 +00:00
def get_current_personality(self):
2023-05-07 11:46:49 +00:00
return jsonify({"personality":self.personality.as_dict()})
2023-05-06 20:49:56 +00:00
2023-05-20 13:50:14 +00:00
def get_all_personalities(self):
2023-06-10 13:16:28 +00:00
personalities_folder = self.lollms_paths.personalities_zoo_path
2023-05-20 13:50:14 +00:00
personalities = {}
for language_folder in personalities_folder.iterdir():
2023-06-06 18:09:00 +00:00
lang = language_folder.stem
2023-06-23 00:02:37 +00:00
if language_folder.is_dir() and not language_folder.stem.startswith('.'):
2023-05-20 13:50:14 +00:00
personalities[language_folder.name] = {}
2023-05-25 07:23:34 +00:00
for category_folder in language_folder.iterdir():
2023-06-06 18:09:00 +00:00
cat = category_folder.stem
2023-06-23 00:02:37 +00:00
if category_folder.is_dir() and not category_folder.stem.startswith('.'):
2023-05-20 13:50:14 +00:00
personalities[language_folder.name][category_folder.name] = []
for personality_folder in category_folder.iterdir():
2023-06-06 18:09:00 +00:00
pers = personality_folder.stem
2023-06-22 21:23:56 +00:00
if personality_folder.is_dir() and not personality_folder.stem.startswith('.'):
2023-06-20 10:40:04 +00:00
personality_info = {"folder":personality_folder.stem}
config_path = personality_folder / 'config.yaml'
if not config_path.exists():
2023-06-23 00:02:37 +00:00
"""
2023-06-20 10:41:39 +00:00
try:
2023-06-21 15:13:51 +00:00
shutil.rmtree(str(config_path.parent))
2023-06-20 10:41:39 +00:00
ASCIIColors.warning(f"Deleted useless personality: {config_path.parent}")
2023-06-21 15:13:51 +00:00
except Exception as ex:
ASCIIColors.warning(f"Couldn't delete personality ({ex})")
2023-06-23 00:02:37 +00:00
"""
continue
2023-05-25 07:23:34 +00:00
try:
2023-06-23 09:18:43 +00:00
scripts_path = personality_folder / 'scripts'
personality_info['has_scripts'] = scripts_path.is_dir()
2023-05-25 07:23:34 +00:00
with open(config_path) as config_file:
config_data = yaml.load(config_file, Loader=yaml.FullLoader)
personality_info['name'] = config_data.get('name',"No Name")
personality_info['description'] = config_data.get('personality_description',"")
2023-05-30 10:00:51 +00:00
personality_info['author'] = config_data.get('author', 'ParisNeo')
2023-05-25 07:23:34 +00:00
personality_info['version'] = config_data.get('version', '1.0.0')
2023-06-23 09:18:43 +00:00
personality_info['installed'] = (self.lollms_paths.personal_configuration_path/f"personality_{personality_folder.stem}.yaml").exists() or personality_info['has_scripts']
2023-07-09 17:32:25 +00:00
personality_info['help'] = config_data.get('help', '')
personality_info['commands'] = config_data.get('commands', '')
2023-06-06 18:09:00 +00:00
real_assets_path = personality_folder/ 'assets'
assets_path = Path("personalities") / lang / cat / pers / 'assets'
2023-05-25 07:23:34 +00:00
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'
bmp_logo_path = assets_path / 'logo.bmp'
2023-06-06 18:09:00 +00:00
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'
bmp_logo_path_ = real_assets_path / 'logo.bmp'
2023-05-25 07:23:34 +00:00
personality_info['has_logo'] = png_logo_path.is_file() or gif_logo_path.is_file()
2023-06-06 18:09:00 +00:00
if gif_logo_path_.exists():
2023-05-25 07:23:34 +00:00
personality_info['avatar'] = str(gif_logo_path).replace("\\","/")
2023-06-06 18:09:00 +00:00
elif webp_logo_path_.exists():
2023-05-25 07:23:34 +00:00
personality_info['avatar'] = str(webp_logo_path).replace("\\","/")
2023-06-06 18:09:00 +00:00
elif png_logo_path_.exists():
2023-05-25 07:23:34 +00:00
personality_info['avatar'] = str(png_logo_path).replace("\\","/")
2023-06-06 18:09:00 +00:00
elif jpg_logo_path_.exists():
2023-05-25 07:23:34 +00:00
personality_info['avatar'] = str(jpg_logo_path).replace("\\","/")
2023-06-06 18:09:00 +00:00
elif jpeg_logo_path_.exists():
2023-05-25 07:23:34 +00:00
personality_info['avatar'] = str(jpeg_logo_path).replace("\\","/")
2023-06-06 18:09:00 +00:00
elif bmp_logo_path_.exists():
2023-05-25 07:23:34 +00:00
personality_info['avatar'] = str(bmp_logo_path).replace("\\","/")
else:
personality_info['avatar'] = ""
personalities[language_folder.name][category_folder.name].append(personality_info)
2023-05-30 12:11:30 +00:00
except Exception as ex:
print(f"Couldn't load personality from {personality_folder} [{ex}]")
2023-05-20 13:50:14 +00:00
return json.dumps(personalities)
2023-06-22 08:10:52 +00:00
def get_personality(self):
2023-05-23 21:12:07 +00:00
lang = request.args.get('language')
category = request.args.get('category')
name = request.args.get('name')
2023-06-22 08:10:52 +00:00
if category!="personal":
personality_folder = self.lollms_paths.personalities_zoo_path/f"{lang}"/f"{category}"/f"{name}"
else:
personality_folder = self.lollms_paths.personal_personalities_path/f"{lang}"/f"{category}"/f"{name}"
2023-05-23 21:12:07 +00:00
personality_path = personality_folder/f"config.yaml"
personality_info = {}
with open(personality_path) as config_file:
config_data = yaml.load(config_file, Loader=yaml.FullLoader)
personality_info['name'] = config_data.get('name',"unnamed")
personality_info['description'] = config_data.get('personality_description',"")
personality_info['author'] = config_data.get('creator', 'ParisNeo')
personality_info['version'] = config_data.get('version', '1.0.0')
scripts_path = personality_folder / 'scripts'
personality_info['has_scripts'] = scripts_path.is_dir()
assets_path = personality_folder / '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'
bmp_logo_path = assets_path / 'logo.bmp'
personality_info['has_logo'] = png_logo_path.is_file() or gif_logo_path.is_file()
if gif_logo_path.exists():
personality_info['avatar'] = str(gif_logo_path).replace("\\","/")
elif webp_logo_path.exists():
personality_info['avatar'] = str(webp_logo_path).replace("\\","/")
elif png_logo_path.exists():
personality_info['avatar'] = str(png_logo_path).replace("\\","/")
elif jpg_logo_path.exists():
personality_info['avatar'] = str(jpg_logo_path).replace("\\","/")
elif jpeg_logo_path.exists():
personality_info['avatar'] = str(jpeg_logo_path).replace("\\","/")
elif bmp_logo_path.exists():
personality_info['avatar'] = str(bmp_logo_path).replace("\\","/")
else:
personality_info['avatar'] = ""
return json.dumps(personality_info)
# Settings (data: {"setting_name":<the setting name>,"setting_value":<the setting value>})
def update_setting(self):
data = request.get_json()
setting_name = data['setting_name']
if setting_name== "temperature":
self.config["temperature"]=float(data['setting_value'])
elif setting_name== "n_predict":
self.config["n_predict"]=int(data['setting_value'])
elif setting_name== "top_k":
self.config["top_k"]=int(data['setting_value'])
elif setting_name== "top_p":
self.config["top_p"]=float(data['setting_value'])
elif setting_name== "repeat_penalty":
self.config["repeat_penalty"]=float(data['setting_value'])
elif setting_name== "repeat_last_n":
self.config["repeat_last_n"]=int(data['setting_value'])
elif setting_name== "n_threads":
self.config["n_threads"]=int(data['setting_value'])
elif setting_name== "ctx_size":
self.config["ctx_size"]=int(data['setting_value'])
elif setting_name== "language":
self.config["language"]=data['setting_value']
2023-06-04 23:21:12 +00:00
elif setting_name== "personality_folder":
self.personality_name=data['setting_value']
2023-06-09 23:37:50 +00:00
if len(self.config["personalities"])>0:
if self.config["active_personality_id"]<len(self.config["personalities"]):
self.config["personalities"][self.config["active_personality_id"]] = f"{self.personality_language}/{self.personality_category}/{self.personality_name}"
else:
self.config["active_personality_id"] = 0
self.config["personalities"][self.config["active_personality_id"]] = f"{self.personality_language}/{self.personality_category}/{self.personality_name}"
2023-06-15 10:03:05 +00:00
if self.personality_category!="Custom":
personality_fn = self.lollms_paths.personalities_zoo_path/self.config["personalities"][self.config["active_personality_id"]]
else:
personality_fn = self.lollms_paths.personal_personalities_path/self.config["personalities"][self.config["active_personality_id"]].split("/")[-1]
2023-06-09 23:37:50 +00:00
self.personality.load_personality(personality_fn)
else:
self.config["personalities"].append(f"{self.personality_language}/{self.personality_category}/{self.personality_name}")
elif setting_name== "override_personality_model_parameters":
self.config["override_personality_model_parameters"]=bool(data['setting_value'])
2023-06-04 23:21:12 +00:00
elif setting_name== "model_name":
self.config["model_name"]=data['setting_value']
2023-07-03 13:18:35 +00:00
if self.config["model_name"] is not None:
try:
self.model = self.binding.build_model()
except Exception as ex:
# Catch the exception and get the traceback as a list of strings
traceback_lines = traceback.format_exception(type(ex), ex, ex.__traceback__)
# Join the traceback lines into a single string
traceback_text = ''.join(traceback_lines)
ASCIIColors.error(f"Couldn't load model: [{ex}]")
ASCIIColors.error(traceback_text)
return jsonify({ "status":False, 'error':str(ex)})
else:
ASCIIColors.warning("Trying to set a None model. Please select a model for the binding")
2023-06-21 22:43:59 +00:00
print("update_settings : New model selected")
2023-06-04 23:21:12 +00:00
elif setting_name== "binding_name":
if self.config['binding_name']!= data['setting_value']:
2023-05-25 21:24:14 +00:00
print(f"New binding selected : {data['setting_value']}")
2023-06-04 23:21:12 +00:00
self.config["binding_name"]=data['setting_value']
2023-06-23 00:02:37 +00:00
try:
2023-07-14 00:29:58 +00:00
self.binding = None
self.model = None
for per in self.mounted_personalities:
per.model = None
gc.collect()
2023-06-23 00:02:37 +00:00
self.binding = BindingBuilder().build_binding(self.config, self.lollms_paths)
2023-06-24 11:06:06 +00:00
self.model = None
2023-07-14 00:29:58 +00:00
self.config.save_config()
2023-06-23 00:02:37 +00:00
except Exception as ex:
print(f"Couldn't build binding: [{ex}]")
return jsonify({"status":False, 'error':str(ex)})
else:
if self.config["debug"]:
print(f"Configuration {data['setting_name']} set to {data['setting_value']}")
return jsonify({'setting_name': data['setting_name'], "status":True})
2023-04-27 23:39:57 +00:00
else:
if self.config["debug"]:
print(f"Configuration {data['setting_name']} couldn't be set to {data['setting_value']}")
return jsonify({'setting_name': data['setting_name'], "status":False})
2023-04-27 14:44:22 +00:00
if self.config["debug"]:
print(f"Configuration {data['setting_name']} set to {data['setting_value']}")
2023-05-13 22:24:26 +00:00
2023-06-14 08:06:38 +00:00
ASCIIColors.success(f"Configuration {data['setting_name']} updated")
# Tell that the setting was changed
return jsonify({'setting_name': data['setting_name'], "status":True})
2023-04-11 20:56:15 +00:00
2023-05-18 18:00:48 +00:00
2023-06-15 10:03:05 +00:00
2023-05-18 18:00:48 +00:00
def apply_settings(self):
2023-06-21 22:43:59 +00:00
ASCIIColors.success("OK")
self.rebuild_personalities()
return jsonify({"status":True})
2023-06-06 18:25:48 +00:00
2023-06-15 10:03:05 +00:00
2023-06-06 18:23:33 +00:00
def ram_usage(self):
"""
Returns the RAM usage in bytes.
"""
ram = psutil.virtual_memory()
return jsonify({
"total_space":ram.total,
"available_space":ram.free,
"percent_usage":ram.percent,
2023-06-07 18:45:48 +00:00
"ram_usage": ram.used
2023-06-06 18:23:33 +00:00
})
2023-06-22 07:46:33 +00:00
def vram_usage(self) -> Optional[dict]:
try:
2023-07-01 11:42:39 +00:00
output = subprocess.check_output(['nvidia-smi', '--query-gpu=memory.total,memory.used,gpu_name', '--format=csv,nounits,noheader'])
2023-06-22 07:46:33 +00:00
lines = output.decode().strip().split('\n')
vram_info = [line.split(',') for line in lines]
except (subprocess.CalledProcessError, FileNotFoundError):
return {
"nb_gpus": 0
}
ram_usage = {
"nb_gpus": len(vram_info)
}
if vram_info is not None:
for i, gpu in enumerate(vram_info):
2023-06-22 18:16:46 +00:00
ram_usage[f"gpu_{i}_total_vram"] = int(gpu[0])*1024*1024
ram_usage[f"gpu_{i}_used_vram"] = int(gpu[1])*1024*1024
2023-07-01 11:42:39 +00:00
ram_usage[f"gpu_{i}_model"] = gpu[2].strip()
2023-06-22 07:46:33 +00:00
else:
# Set all VRAM-related entries to None
ram_usage["gpu_0_total_vram"] = None
ram_usage["gpu_0_used_vram"] = None
2023-07-01 11:42:39 +00:00
ram_usage["gpu_0_model"] = None
2023-06-22 07:46:33 +00:00
return jsonify(ram_usage)
2023-05-28 06:53:54 +00:00
def disk_usage(self):
2023-05-28 06:47:57 +00:00
current_drive = Path.cwd().anchor
2023-05-28 07:00:50 +00:00
drive_disk_usage = psutil.disk_usage(current_drive)
try:
2023-06-14 11:12:27 +00:00
models_folder_disk_usage = psutil.disk_usage(str(self.lollms_paths.personal_models_path/f'{self.config["binding_name"]}'))
return jsonify( {
2023-05-28 07:00:50 +00:00
"total_space":drive_disk_usage.total,
"available_space":drive_disk_usage.free,
2023-06-14 11:12:27 +00:00
"usage":drive_disk_usage.used,
"percent_usage":drive_disk_usage.percent,
2023-05-28 07:00:50 +00:00
2023-06-14 11:12:27 +00:00
"binding_disk_total_space":models_folder_disk_usage.total,
"binding_disk_available_space":drive_disk_usage.free,
"binding_models_usage": models_folder_disk_usage.used,
"binding_models_percent_usage": models_folder_disk_usage.percent,
2023-05-28 07:00:50 +00:00
})
2023-06-14 11:12:27 +00:00
except Exception as ex:
2023-05-28 07:00:50 +00:00
return jsonify({
"total_space":drive_disk_usage.total,
"available_space":drive_disk_usage.free,
"percent_usage":drive_disk_usage.percent,
2023-06-14 11:12:27 +00:00
"binding_disk_total_space": None,
"binding_disk_available_space": None,
"binding_models_usage": None,
"binding_models_percent_usage": None,
2023-05-28 07:00:50 +00:00
})
2023-05-18 18:00:48 +00:00
2023-05-25 21:24:14 +00:00
def list_bindings(self):
2023-06-10 13:16:28 +00:00
bindings_dir = self.lollms_paths.bindings_zoo_path # replace with the actual path to the models folder
2023-05-27 08:06:52 +00:00
bindings=[]
for f in bindings_dir.iterdir():
card = f/"binding_card.yaml"
if card.exists():
try:
bnd = load_config(card)
bnd["folder"]=f.stem
2023-06-04 23:21:12 +00:00
icon_path = Path(f"bindings/{f.name}/logo.png")
installed = (self.lollms_paths.personal_configuration_path/f"binding_{f.stem}.yaml").exists()
bnd["installed"]=installed
2023-06-10 13:16:28 +00:00
if Path(self.lollms_paths.bindings_zoo_path/f"{f.name}/logo.png").exists():
2023-05-29 22:37:09 +00:00
bnd["icon"]=str(icon_path)
2023-05-27 08:06:52 +00:00
bindings.append(bnd)
except Exception as ex:
print(f"Couldn't load backend card : {f}\n\t{ex}")
2023-05-25 21:24:14 +00:00
return jsonify(bindings)
2023-04-20 17:30:03 +00:00
2023-04-08 17:55:33 +00:00
def list_models(self):
2023-05-25 21:24:14 +00:00
if self.binding is not None:
models = self.binding.list_models(self.config)
2023-07-06 00:27:33 +00:00
ASCIIColors.yellow("Listing models")
2023-05-11 13:09:35 +00:00
return jsonify(models)
else:
return jsonify([])
2023-04-13 22:47:20 +00:00
2023-04-20 17:30:03 +00:00
def list_personalities_languages(self):
2023-06-10 13:16:28 +00:00
personalities_languages_dir = self.lollms_paths.personalities_zoo_path # replace with the actual path to the models folder
2023-07-04 09:26:57 +00:00
personalities_languages = [f.stem for f in personalities_languages_dir.iterdir() if f.is_dir() and not f.name.startswith(".")]
2023-04-20 17:30:03 +00:00
return jsonify(personalities_languages)
def list_personalities_categories(self):
2023-06-10 13:16:28 +00:00
personalities_categories_dir = self.lollms_paths.personalities_zoo_path/f'{self.personality_language}' # replace with the actual path to the models folder
2023-07-04 09:26:57 +00:00
personalities_categories = [f.stem for f in personalities_categories_dir.iterdir() if f.is_dir() and not f.name.startswith(".")]
2023-04-20 17:30:03 +00:00
return jsonify(personalities_categories)
2023-04-13 22:47:20 +00:00
def list_personalities(self):
2023-05-05 20:35:08 +00:00
try:
2023-06-10 13:16:28 +00:00
personalities_dir = self.lollms_paths.personalities_zoo_path/f'{self.personality_language}/{self.personality_category}' # replace with the actual path to the models folder
2023-07-04 09:26:57 +00:00
personalities = [f.stem for f in personalities_dir.iterdir() if f.is_dir() and not f.name.startswith(".")]
except Exception as ex:
2023-05-05 20:35:08 +00:00
personalities=[]
2023-06-12 08:29:41 +00:00
ASCIIColors.error(f"No personalities found. Using default one {ex}")
2023-04-13 22:47:20 +00:00
return jsonify(personalities)
2023-04-07 21:22:17 +00:00
2023-04-14 00:10:22 +00:00
def list_languages(self):
lanuguages= [
{ "value": "en-US", "label": "English" },
{ "value": "fr-FR", "label": "Français" },
{ "value": "ar-AR", "label": "العربية" },
{ "value": "it-IT", "label": "Italiano" },
{ "value": "de-DE", "label": "Deutsch" },
{ "value": "nl-XX", "label": "Dutch" },
{ "value": "zh-CN", "label": "中國人" }
]
return jsonify(lanuguages)
2023-04-10 08:27:25 +00:00
def list_discussions(self):
discussions = self.db.get_discussions()
return jsonify(discussions)
2023-04-10 08:27:25 +00:00
2023-05-23 21:12:07 +00:00
def delete_personality(self):
lang = request.args.get('language')
2023-04-20 17:30:03 +00:00
category = request.args.get('category')
2023-05-23 21:12:07 +00:00
name = request.args.get('name')
path = Path("personalities")/lang/category/name
try:
shutil.rmtree(path)
2023-06-15 14:56:08 +00:00
return jsonify({'status':True})
2023-05-23 21:12:07 +00:00
except Exception as ex:
2023-06-15 14:56:08 +00:00
return jsonify({'status':False,'error':str(ex)})
2023-04-20 17:30:03 +00:00
def add_endpoint(
self,
endpoint=None,
endpoint_name=None,
handler=None,
methods=["GET"],
*args,
**kwargs,
):
self.app.add_url_rule(
endpoint, endpoint_name, handler, methods=methods, *args, **kwargs
)
2023-04-06 19:12:49 +00:00
def index(self):
2023-04-17 15:59:36 +00:00
return render_template("index.html")
2023-05-02 20:53:27 +00:00
def serve_static(self, filename):
root_dir = os.getcwd()
2023-06-04 23:21:12 +00:00
path = os.path.join(root_dir, 'web/dist/')+"/".join(filename.split("/")[:-1])
2023-05-02 20:53:27 +00:00
fn = filename.split("/")[-1]
return send_from_directory(path, fn)
2023-05-29 22:37:09 +00:00
def serve_images(self, filename):
root_dir = os.getcwd()
path = os.path.join(root_dir, 'images/')+"/".join(filename.split("/")[:-1])
fn = filename.split("/")[-1]
return send_from_directory(path, fn)
def serve_bindings(self, filename):
2023-06-10 13:16:28 +00:00
path = str(self.lollms_paths.bindings_zoo_path/("/".join(filename.split("/")[:-1])))
2023-05-29 22:37:09 +00:00
fn = filename.split("/")[-1]
return send_from_directory(path, fn)
2023-05-05 13:01:38 +00:00
def serve_personalities(self, filename):
2023-06-10 13:16:28 +00:00
path = str(self.lollms_paths.personalities_zoo_path/("/".join(filename.split("/")[:-1])))
2023-05-05 13:01:38 +00:00
fn = filename.split("/")[-1]
return send_from_directory(path, fn)
2023-05-20 23:10:01 +00:00
def serve_outputs(self, filename):
2023-06-10 13:16:28 +00:00
root_dir = self.lollms_paths.personal_path / "outputs"
2023-06-09 23:37:50 +00:00
root_dir.mkdir(exist_ok=True, parents=True)
path = str(root_dir/"/".join(filename.split("/")[:-1]))
2023-05-20 23:10:01 +00:00
fn = filename.split("/")[-1]
return send_from_directory(path, fn)
2023-06-10 00:48:19 +00:00
def serve_help(self, filename):
root_dir = Path(__file__).parent/f"help"
root_dir.mkdir(exist_ok=True, parents=True)
path = str(root_dir/"/".join(filename.split("/")[:-1]))
fn = filename.split("/")[-1]
return send_from_directory(path, fn)
2023-06-07 07:39:38 +00:00
def serve_data(self, filename):
2023-06-10 13:16:28 +00:00
root_dir = self.lollms_paths.personal_path / "data"
2023-06-09 23:37:50 +00:00
root_dir.mkdir(exist_ok=True, parents=True)
path = str(root_dir/"/".join(filename.split("/")[:-1]))
2023-06-07 07:39:38 +00:00
fn = filename.split("/")[-1]
return send_from_directory(path, fn)
def serve_uploads(self, filename):
2023-06-10 13:16:28 +00:00
root_dir = self.lollms_paths.personal_path / "uploads"
2023-06-09 23:37:50 +00:00
root_dir.mkdir(exist_ok=True, parents=True)
path = str(root_dir+"/".join(filename.split("/")[:-1]))
2023-06-07 07:39:38 +00:00
fn = filename.split("/")[-1]
return send_from_directory(path, fn)
2023-05-20 23:10:01 +00:00
2023-04-06 19:12:49 +00:00
def export(self):
2023-04-10 08:27:25 +00:00
return jsonify(self.db.export_to_json())
2023-04-06 19:12:49 +00:00
2023-04-10 08:27:25 +00:00
def export_discussion(self):
2023-04-17 22:23:31 +00:00
return jsonify({"discussion_text":self.get_discussion_to()})
2023-04-10 08:27:25 +00:00
2023-05-13 22:24:26 +00:00
def get_generation_status(self):
2023-06-21 22:43:59 +00:00
return jsonify({"status":not self.is_ready})
2023-04-23 22:19:15 +00:00
def stop_gen(self):
self.cancel_gen = True
2023-06-07 07:39:38 +00:00
return jsonify({"status": True})
2023-06-10 13:49:41 +00:00
def switch_personal_path(self):
data = request.get_json()
path = data["path"]
global_paths_cfg = Path("./global_paths_cfg.yaml")
if global_paths_cfg.exists():
try:
cfg = BaseConfig()
cfg.load_config(global_paths_cfg)
cfg.lollms_personal_path = path
cfg.save_config(global_paths_cfg)
return jsonify({"status": True})
except Exception as ex:
print(ex)
return jsonify({"status": False, 'error':f"Couldn't switch path: {ex}"})
2023-06-07 07:39:38 +00:00
def add_reference_to_local_model(self):
data = request.get_json()
path = data["path"]
if path.exists():
self.conversation.config.reference_model(path)
return jsonify({"status": True})
else:
return jsonify({"status": True})
2023-05-13 22:24:26 +00:00
2023-06-09 14:49:13 +00:00
def list_mounted_personalities(self):
print("- Listing mounted personalities")
return jsonify({"status": True,
"personalities":self.config["personalities"],
"active_personality_id":self.config["active_personality_id"]
})
2023-06-26 10:45:46 +00:00
def install_model_from_path(self):
2023-07-12 07:36:45 +00:00
from tkinter import Tk
from tkinter.filedialog import askopenfilename
2023-06-26 10:45:46 +00:00
ASCIIColors.info(f"- Selecting model ...")
# Define the file types
filetypes = [
("Model file", self.binding.file_extension),
]
# Create the Tkinter root window
root = Tk()
# Hide the root window
root.withdraw()
# Open the file dialog
file_path = askopenfilename(filetypes=filetypes)
file_path = Path(file_path)
#
with open(str(self.lollms_paths.personal_models_path/self.config.binding_name/(file_path.stem+".reference")),"w") as f:
f.write(file_path)
return jsonify({
"status": True
})
2023-07-05 23:01:17 +00:00
def reinstall_personality(self):
try:
data = request.get_json()
# Further processing of the data
except Exception as e:
print(f"Error occurred while parsing JSON: {e}")
return jsonify({"status":False, 'error':str(e)})
2023-06-26 10:45:46 +00:00
2023-07-05 23:01:17 +00:00
ASCIIColors.info(f"- Reinstalling personality {data['name']}...")
try:
ASCIIColors.info("Unmounting personality")
except Exception as e:
return jsonify({"status":False, 'error':str(e)})
2023-06-15 19:19:19 +00:00
def reinstall_binding(self):
try:
data = request.get_json()
# Further processing of the data
except Exception as e:
print(f"Error occurred while parsing JSON: {e}")
2023-07-05 23:01:17 +00:00
return jsonify({"status":False, 'error':str(e)})
2023-06-21 22:43:59 +00:00
ASCIIColors.info(f"- Reinstalling binding {data['name']}...")
2023-06-15 19:19:19 +00:00
try:
2023-07-04 09:26:57 +00:00
ASCIIColors.info("Unmounting binding and model")
self.binding = None
self.model = None
2023-07-14 00:29:58 +00:00
for per in self.mounted_personalities:
per.model = None
2023-07-04 09:26:57 +00:00
gc.collect()
ASCIIColors.info("Reinstalling binding")
2023-06-21 22:43:59 +00:00
self.binding = BindingBuilder().build_binding(self.config, self.lollms_paths, InstallOption.FORCE_INSTALL)
2023-07-05 00:19:11 +00:00
ASCIIColors.info("Binding reinstalled successfully")
2023-06-25 17:43:50 +00:00
try:
2023-07-05 00:19:11 +00:00
ASCIIColors.info("Reloading model")
2023-06-25 17:43:50 +00:00
self.model = self.binding.build_model()
2023-07-05 00:19:11 +00:00
ASCIIColors.info("Model reloaded successfully")
2023-06-25 17:43:50 +00:00
except Exception as ex:
print(f"Couldn't build model: [{ex}]")
2023-07-07 22:25:04 +00:00
trace_exception(ex)
2023-06-25 17:43:50 +00:00
try:
self.rebuild_personalities()
except Exception as ex:
print(f"Couldn't reload personalities: [{ex}]")
2023-06-15 19:19:19 +00:00
return jsonify({"status": True})
except Exception as ex:
print(f"Couldn't build binding: [{ex}]")
return jsonify({"status":False, 'error':str(ex)})
2023-07-13 23:42:29 +00:00
def reload_binding(self):
try:
data = request.get_json()
# Further processing of the data
except Exception as e:
print(f"Error occurred while parsing JSON: {e}")
return jsonify({"status":False, 'error':str(e)})
ASCIIColors.info(f"- Reloading binding {data['name']}...")
try:
ASCIIColors.info("Unmounting binding and model")
self.binding = None
self.model = None
for personality in self.mounted_personalities:
personality.model = None
gc.collect()
ASCIIColors.info("Reloading binding")
self.binding = BindingBuilder().build_binding(self.config, self.lollms_paths)
ASCIIColors.info("Binding loaded successfully")
try:
ASCIIColors.info("Reloading model")
self.model = self.binding.build_model()
ASCIIColors.info("Model reloaded successfully")
except Exception as ex:
print(f"Couldn't build model: [{ex}]")
trace_exception(ex)
try:
self.rebuild_personalities()
except Exception as ex:
print(f"Couldn't reload personalities: [{ex}]")
return jsonify({"status": True})
except Exception as ex:
print(f"Couldn't build binding: [{ex}]")
return jsonify({"status":False, 'error':str(ex)})
2023-06-15 19:19:19 +00:00
2023-07-04 00:19:20 +00:00
def p_mount_personality(self):
2023-07-03 13:18:35 +00:00
print("- Mounting personality")
2023-06-09 11:55:45 +00:00
try:
data = request.get_json()
# Further processing of the data
except Exception as e:
print(f"Error occurred while parsing JSON: {e}")
return
2023-06-09 11:42:08 +00:00
language = data['language']
category = data['category']
2023-06-14 08:27:02 +00:00
name = data['folder']
2023-06-08 06:58:02 +00:00
package_path = f"{language}/{category}/{name}"
2023-06-10 13:56:12 +00:00
package_full_path = self.lollms_paths.personalities_zoo_path/package_path
2023-06-08 06:58:02 +00:00
config_file = package_full_path / "config.yaml"
2023-06-09 12:24:24 +00:00
if config_file.exists():
self.config["personalities"].append(package_path)
2023-06-21 22:43:59 +00:00
self.mounted_personalities = self.rebuild_personalities()
2023-06-10 00:22:49 +00:00
self.personality = self.mounted_personalities[self.config["active_personality_id"]]
2023-06-08 06:58:02 +00:00
self.apply_settings()
2023-06-14 08:06:38 +00:00
ASCIIColors.success("ok")
2023-06-24 14:25:39 +00:00
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"]
})
2023-06-08 06:58:02 +00:00
else:
2023-06-09 12:24:24 +00:00
pth = str(config_file).replace('\\','/')
2023-06-14 08:06:38 +00:00
ASCIIColors.error(f"nok : Personality not found @ {pth}")
2023-06-09 12:24:24 +00:00
return jsonify({"status": False, "error":f"Personality not found @ {pth}"})
2023-06-08 06:58:02 +00:00
2023-07-04 00:19:20 +00:00
def p_unmount_personality(self):
2023-07-03 13:18:35 +00:00
print("- Unmounting personality ...")
2023-06-09 14:49:13 +00:00
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']
2023-06-14 10:54:55 +00:00
name = data['folder']
2023-06-08 06:58:02 +00:00
try:
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
2023-06-09 14:51:27 +00:00
if len(self.config["personalities"])>0:
2023-06-21 22:43:59 +00:00
self.mounted_personalities = self.rebuild_personalities()
2023-06-10 00:22:49 +00:00
self.personality = self.mounted_personalities[self.config["active_personality_id"]]
2023-06-09 14:51:27 +00:00
else:
self.personalities = ["english/generic/lollms"]
2023-06-21 22:43:59 +00:00
self.mounted_personalities = self.rebuild_personalities()
self.personality = self.mounted_personalities[self.config["active_personality_id"]]
2023-06-08 06:58:02 +00:00
self.apply_settings()
2023-06-14 08:06:38 +00:00
ASCIIColors.success("ok")
2023-06-09 14:49:13 +00:00
return jsonify({
"status": True,
"personalities":self.config["personalities"],
"active_personality_id":self.config["active_personality_id"]
})
2023-06-08 06:58:02 +00:00
except:
ASCIIColors.error(f"nok : Personality not found @ {language}/{category}/{name}")
2023-06-08 06:58:02 +00:00
return jsonify({"status": False, "error":"Couldn't unmount personality"})
2023-06-22 08:10:52 +00:00
2023-06-22 08:20:16 +00:00
def get_active_personality_settings(self):
print("- Retreiving personality settings")
if self.personality.processor is not None:
if hasattr(self.personality.processor,"personality_config"):
return jsonify(self.personality.processor.personality_config.config_template.template)
else:
return jsonify({})
else:
return jsonify({})
def get_active_binding_settings(self):
print("- Retreiving binding settings")
if self.binding is not None:
if hasattr(self.binding,"binding_config"):
return jsonify(self.binding.binding_config.config_template.template)
else:
return jsonify({})
else:
return jsonify({})
2023-06-22 09:42:23 +00:00
def set_active_personality_settings(self):
print("- Setting personality settings")
try:
data = request.get_json()
# Further processing of the data
except Exception as e:
print(f"Error occurred while parsing JSON: {e}")
return
if self.personality.processor is not None:
if hasattr(self.personality.processor,"personality_config"):
self.personality.processor.personality_config.update_template(data)
2023-06-29 21:43:55 +00:00
self.personality.processor.personality_config.config.save_config()
2023-06-22 09:45:06 +00:00
return jsonify({'status':True})
2023-06-22 09:42:23 +00:00
else:
return jsonify({'status':False})
else:
2023-06-22 09:45:06 +00:00
return jsonify({'status':False})
2023-06-22 09:42:23 +00:00
2023-06-22 09:45:06 +00:00
def set_active_binding_settings(self):
print("- Setting binding settings")
try:
data = request.get_json()
# Further processing of the data
except Exception as e:
print(f"Error occurred while parsing JSON: {e}")
return
2023-06-22 09:42:23 +00:00
2023-06-22 09:45:06 +00:00
if self.binding is not None:
if hasattr(self.binding,"binding_config"):
2023-07-02 22:17:01 +00:00
for entry in data:
if entry["type"]=="list" and type(entry["value"])==str:
try:
v = json.loads(entry["value"])
except:
v= ""
if type(v)==list:
entry["value"] = v
else:
entry["value"] = [entry["value"]]
2023-06-22 09:45:06 +00:00
self.binding.binding_config.update_template(data)
2023-06-29 23:23:10 +00:00
self.binding.binding_config.config.save_config()
2023-07-14 00:29:58 +00:00
self.binding = None
self.model = None
for per in self.mounted_personalities:
per.model = None
gc.collect()
2023-06-29 23:23:10 +00:00
self.binding= BindingBuilder().build_binding(self.config, self.lollms_paths)
self.model = self.binding.build_model()
2023-06-22 09:45:06 +00:00
return jsonify({'status':True})
else:
return jsonify({'status':False})
else:
return jsonify({'status':False})
2023-06-22 08:20:16 +00:00
2023-06-22 08:10:52 +00:00
def get_personality_settings(self):
print("- Retreiving personality settings")
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']
if category.startswith("personal"):
personality_folder = self.lollms_paths.personal_personalities_path/f"{language}"/f"{category}"/f"{name}"
else:
personality_folder = self.lollms_paths.personalities_zoo_path/f"{language}"/f"{category}"/f"{name}"
personality = AIPersonality(personality_folder,
self.lollms_paths,
self.config,
model=self.model,
run_scripts=True)
if personality.processor is not None:
if hasattr(personality.processor,"personality_config"):
return jsonify(personality.processor.personality_config.config_template.template)
else:
return jsonify({})
else:
return jsonify({})
2023-06-22 08:20:16 +00:00
2023-07-04 00:19:20 +00:00
def p_select_personality(self):
2023-06-14 08:06:38 +00:00
2023-06-10 14:04:12 +00:00
data = request.get_json()
id = data['id']
print(f"- Selecting active personality {id} ...",end="")
2023-06-08 06:58:02 +00:00
if id<len(self.config["personalities"]):
self.config["active_personality_id"]=id
2023-06-10 00:22:49 +00:00
self.personality = self.mounted_personalities[self.config["active_personality_id"]]
2023-06-08 06:58:02 +00:00
self.apply_settings()
2023-06-14 08:06:38 +00:00
ASCIIColors.success("ok")
2023-06-15 19:19:19 +00:00
print(f"Mounted {self.personality.name}")
2023-06-10 14:04:12 +00:00
return jsonify({
"status": True,
"personalities":self.config["personalities"],
"active_personality_id":self.config["active_personality_id"]
})
2023-06-08 06:58:02 +00:00
else:
2023-06-14 08:27:02 +00:00
ASCIIColors.error(f"nok : personality id out of bounds @ {id} >= {len(self.config['personalities'])}")
2023-06-08 06:58:02 +00:00
return jsonify({"status": False, "error":"Invalid ID"})
2023-06-06 18:43:38 +00:00
def send_file(self):
2023-07-14 12:02:53 +00:00
try:
file = request.files['file']
file.save(self.lollms_paths.personal_uploads_path / file.filename)
if self.personality.processor:
self.personality.processor.add_file(self.lollms_paths.personal_uploads_path / file.filename)
return jsonify({"status": True})
except Exception as ex:
ASCIIColors.error(ex)
trace_exception(ex)
return jsonify({"status": False})
2023-06-26 14:52:58 +00:00
def upload_model(self):
file = request.files['file']
file.save(self.lollms_paths.personal_models_path/self.config.binding_name/file.filename)
return jsonify({"status": True})
2023-06-06 18:43:38 +00:00
2023-04-06 19:12:49 +00:00
def rename(self):
data = request.get_json()
title = data["title"]
2023-04-10 14:15:12 +00:00
self.current_discussion.rename(title)
2023-04-06 19:12:49 +00:00
return "renamed successfully"
2023-05-04 14:38:03 +00:00
def edit_title(self):
data = request.get_json()
title = data["title"]
discussion_id = data["id"]
self.current_discussion = Discussion(discussion_id, self.db)
self.current_discussion.rename(title)
return "title renamed successfully"
def load_discussion(self):
2023-04-07 21:22:17 +00:00
data = request.get_json()
if "id" in data:
discussion_id = data["id"]
2023-04-13 19:40:46 +00:00
self.current_discussion = Discussion(discussion_id, self.db)
else:
if self.current_discussion is not None:
discussion_id = self.current_discussion.discussion_id
2023-04-13 19:40:46 +00:00
self.current_discussion = Discussion(discussion_id, self.db)
else:
2023-04-13 19:40:46 +00:00
self.current_discussion = self.db.create_discussion()
2023-04-07 21:22:17 +00:00
messages = self.current_discussion.get_messages()
2023-05-20 13:50:14 +00:00
2023-04-07 21:22:17 +00:00
2023-04-20 17:30:03 +00:00
return jsonify(messages), {'Content-Type': 'application/json; charset=utf-8'}
2023-04-06 19:12:49 +00:00
def delete_discussion(self):
data = request.get_json()
discussion_id = data["id"]
2023-04-10 09:14:10 +00:00
self.current_discussion = Discussion(discussion_id, self.db)
2023-04-06 19:12:49 +00:00
self.current_discussion.delete_discussion()
self.current_discussion = None
return jsonify({})
2023-04-06 19:12:49 +00:00
def update_message(self):
discussion_id = request.args.get("id")
new_message = request.args.get("message")
2023-05-20 17:48:38 +00:00
try:
self.current_discussion.update_message(discussion_id, new_message)
2023-06-07 07:39:38 +00:00
return jsonify({"status": True})
2023-05-20 17:48:38 +00:00
except Exception as ex:
2023-06-07 07:39:38 +00:00
return jsonify({"status": False, "error":str(ex)})
2023-05-20 17:48:38 +00:00
def message_rank_up(self):
discussion_id = request.args.get("id")
2023-05-20 17:48:38 +00:00
try:
new_rank = self.current_discussion.message_rank_up(discussion_id)
2023-06-07 07:39:38 +00:00
return jsonify({"status": True, "new_rank": new_rank})
2023-05-20 17:48:38 +00:00
except Exception as ex:
2023-06-07 07:39:38 +00:00
return jsonify({"status": False, "error":str(ex)})
def message_rank_down(self):
discussion_id = request.args.get("id")
2023-05-20 17:48:38 +00:00
try:
new_rank = self.current_discussion.message_rank_down(discussion_id)
2023-06-07 07:39:38 +00:00
return jsonify({"status": True, "new_rank": new_rank})
2023-05-20 17:48:38 +00:00
except Exception as ex:
2023-06-07 07:39:38 +00:00
return jsonify({"status": False, "error":str(ex)})
2023-04-06 19:12:49 +00:00
2023-04-13 10:31:48 +00:00
def delete_message(self):
discussion_id = request.args.get("id")
2023-04-27 23:39:57 +00:00
if self.current_discussion is None:
return jsonify({"status": False,"message":"No discussion is selected"})
else:
new_rank = self.current_discussion.delete_message(discussion_id)
2023-07-06 17:19:48 +00:00
ASCIIColors.yellow("Message deleted")
2023-04-27 23:39:57 +00:00
return jsonify({"status":True,"new_rank": new_rank})
2023-04-13 10:31:48 +00:00
2023-04-06 19:12:49 +00:00
def new_discussion(self):
title = request.args.get("title")
timestamp = self.create_new_discussion(title)
2023-04-24 21:11:32 +00:00
2023-04-06 19:12:49 +00:00
# Return a success response
2023-04-30 20:40:19 +00:00
return json.dumps({"id": self.current_discussion.discussion_id, "time": timestamp, "welcome_message":self.personality.welcome_message, "sender":self.personality.name})
2023-05-25 21:24:14 +00:00
def set_binding(self):
data = request.get_json()
2023-05-25 21:24:14 +00:00
binding = str(data["binding"])
2023-06-04 23:21:12 +00:00
if self.config['binding_name']!= binding:
2023-05-25 21:24:14 +00:00
print("New binding selected")
2023-06-04 23:21:12 +00:00
self.config['binding_name'] = binding
2023-05-24 14:41:38 +00:00
try:
2023-06-04 23:21:12 +00:00
binding_ =self.process.load_binding(config["binding_name"],True)
2023-05-25 21:24:14 +00:00
models = binding_.list_models(self.config)
2023-05-24 14:41:38 +00:00
if len(models)>0:
2023-05-25 21:24:14 +00:00
self.binding = binding_
2023-06-04 23:21:12 +00:00
self.config['model_name'] = models[0]
2023-05-24 14:41:38 +00:00
# Build chatbot
return jsonify(self.process.set_config(self.config))
else:
return jsonify({"status": "no_models_found"})
except :
return jsonify({"status": "failed"})
2023-04-23 14:59:00 +00:00
return jsonify({"status": "error"})
2023-04-23 19:05:39 +00:00
def set_model(self):
data = request.get_json()
2023-06-04 23:21:12 +00:00
model = str(data["model_name"])
if self.config['model_name']!= model:
2023-05-13 22:24:26 +00:00
print("set_model: New model selected")
2023-06-04 23:21:12 +00:00
self.config['model_name'] = model
2023-05-24 14:08:42 +00:00
# Build chatbot
return jsonify(self.process.set_config(self.config))
2023-04-23 19:05:39 +00:00
return jsonify({"status": "succeeded"})
2023-04-23 14:59:00 +00:00
2023-04-08 17:55:33 +00:00
2023-05-10 21:33:08 +00:00
def get_available_models(self):
2023-05-13 12:19:56 +00:00
"""Get the available models
Returns:
_type_: _description_
"""
2023-05-25 21:24:14 +00:00
if self.binding is None:
2023-05-18 18:00:48 +00:00
return jsonify([])
2023-05-25 21:24:14 +00:00
model_list = self.binding.get_available_models()
2023-05-10 21:33:08 +00:00
models = []
2023-07-07 16:25:18 +00:00
ASCIIColors.yellow("Recovering available models")
2023-05-10 21:33:08 +00:00
for model in model_list:
2023-05-14 08:32:55 +00:00
try:
2023-05-18 18:00:48 +00:00
filename = model.get('filename',"")
server = model.get('server',"")
2023-05-25 14:40:28 +00:00
image_url = model.get("icon", '/images/default_model.png')
2023-05-21 20:46:02 +00:00
license = model.get("license", 'unknown')
owner = model.get("owner", 'unknown')
owner_link = model.get("owner_link", 'https://github.com/ParisNeo')
2023-05-18 18:00:48 +00:00
filesize = int(model.get('filesize',0))
description = model.get('description',"")
2023-05-29 22:37:09 +00:00
model_type = model.get("model_type","")
2023-05-14 08:32:55 +00:00
if server.endswith("/"):
path = f'{server}{filename}'
else:
path = f'{server}/{filename}'
2023-06-10 13:16:28 +00:00
local_path = lollms_paths.personal_models_path/f'{self.config["binding_name"]}/{filename}'
2023-05-29 22:37:09 +00:00
is_installed = local_path.exists() or model_type.lower()=="api"
2023-05-14 08:32:55 +00:00
models.append({
2023-05-18 18:00:48 +00:00
'title': filename,
'icon': image_url, # Replace with the path to the model icon
2023-05-21 20:46:02 +00:00
'license': license,
'owner': owner,
'owner_link': owner_link,
2023-05-18 18:00:48 +00:00
'description': description,
2023-05-14 08:32:55 +00:00
'isInstalled': is_installed,
'path': path,
'filesize': filesize,
2023-05-29 22:37:09 +00:00
'model_type': model_type
2023-05-14 08:32:55 +00:00
})
2023-05-18 18:00:48 +00:00
except Exception as ex:
print("#################################")
print(ex)
print("#################################")
2023-05-14 08:32:55 +00:00
print(f"Problem with model : {model}")
2023-05-10 21:33:08 +00:00
return jsonify(models)
2023-06-06 20:20:29 +00:00
def train(self):
form_data = request.form
# Create and populate the config file
config = {
'model_name': form_data['model_name'],
'tokenizer_name': form_data['tokenizer_name'],
'dataset_path': form_data['dataset_path'],
'max_length': form_data['max_length'],
'batch_size': form_data['batch_size'],
'lr': form_data['lr'],
'num_epochs': form_data['num_epochs'],
'output_dir': form_data['output_dir'],
}
with open('train/configs/train/local_cfg.yaml', 'w') as f:
yaml.dump(config, f)
# Trigger the train.py script
# Place your code here to run the train.py script with the created config file
# accelerate launch --dynamo_backend=inductor --num_processes=8 --num_machines=1 --machine_rank=0 --deepspeed_multinode_launcher standard --mixed_precision=bf16 --use_deepspeed --deepspeed_config_file=configs/deepspeed/ds_config_gptj.json train.py --config configs/train/finetune_gptj.yaml
subprocess.check_call(["accelerate","launch", "--dynamo_backend=inductor", "--num_processes=8", "--num_machines=1", "--machine_rank=0", "--deepspeed_multinode_launcher standard", "--mixed_precision=bf16", "--use_deepspeed", "--deepspeed_config_file=train/configs/deepspeed/ds_config_gptj.json", "train/train.py", "--config", "train/configs/train/local_cfg.yaml"])
return jsonify({'message': 'Training started'})
2023-05-10 21:33:08 +00:00
2023-04-12 20:36:03 +00:00
def get_config(self):
2023-06-04 23:21:12 +00:00
return jsonify(self.config.to_dict())
2023-06-07 22:54:01 +00:00
def get_current_personality_path_infos(self):
2023-07-04 00:19:20 +00:00
if self.personality is None:
return jsonify({
"personality_language":"",
"personality_category":"",
"personality_name":""
})
else:
return jsonify({
"personality_language":self.personality_language,
"personality_category":self.personality_category,
"personality_name":self.personality_name
})
2023-04-08 17:55:33 +00:00
2023-04-13 10:31:48 +00:00
def main(self):
return render_template("main.html")
def settings(self):
return render_template("settings.html")
2023-04-11 20:56:15 +00:00
def help(self):
return render_template("help.html")
2023-04-11 23:34:50 +00:00
def training(self):
return render_template("training.html")
def extensions(self):
return render_template("extensions.html")
2023-05-26 10:10:16 +00:00
def sync_cfg(default_config, config):
"""Syncs a configuration with the default configuration
Args:
default_config (_type_): _description_
config (_type_): _description_
Returns:
_type_: _description_
"""
added_entries = []
removed_entries = []
# Ensure all fields from default_config exist in config
for key, value in default_config.items():
if key not in config:
config[key] = value
added_entries.append(key)
# Remove fields from config that don't exist in default_config
2023-06-07 07:39:38 +00:00
for key in list(config.config.keys()):
2023-05-26 10:10:16 +00:00
if key not in default_config:
2023-06-07 07:39:38 +00:00
del config.config[key]
2023-05-26 10:10:16 +00:00
removed_entries.append(key)
2023-06-10 20:49:03 +00:00
config["version"]=default_config["version"]
2023-04-11 23:34:50 +00:00
2023-05-26 10:10:16 +00:00
return config, added_entries, removed_entries
if __name__ == "__main__":
2023-06-12 14:25:24 +00:00
lollms_paths = LollmsPaths.find_paths(force_local=True, custom_default_cfg_path="configs/config.yaml")
2023-06-10 13:49:41 +00:00
db_folder = lollms_paths.personal_path/"databases"
db_folder.mkdir(parents=True, exist_ok=True)
parser = argparse.ArgumentParser(description="Start the chatbot Flask app.")
parser.add_argument(
2023-06-07 07:39:38 +00:00
"-c", "--config", type=str, default="local_config", help="Sets the configuration file to be used."
)
parser.add_argument(
"-p", "--personality", type=str, default=None, help="Selects the personality to be using."
)
parser.add_argument(
2023-04-13 13:27:50 +00:00
"-s", "--seed", type=int, default=None, help="Force using a specific seed value."
)
parser.add_argument(
2023-04-12 20:36:03 +00:00
"-m", "--model", type=str, default=None, help="Force using a specific model."
)
parser.add_argument(
2023-04-12 20:36:03 +00:00
"--temp", type=float, default=None, help="Temperature parameter for the model."
)
parser.add_argument(
"--n_predict",
type=int,
2023-04-12 20:36:03 +00:00
default=None,
help="Number of tokens to predict at each step.",
)
2023-04-16 19:33:34 +00:00
parser.add_argument(
"--n_threads",
type=int,
default=None,
help="Number of threads to use.",
)
parser.add_argument(
2023-04-12 20:36:03 +00:00
"--top_k", type=int, default=None, help="Value for the top-k sampling."
)
parser.add_argument(
2023-04-12 20:36:03 +00:00
"--top_p", type=float, default=None, help="Value for the top-p sampling."
)
parser.add_argument(
2023-04-12 20:36:03 +00:00
"--repeat_penalty", type=float, default=None, help="Penalty for repeated tokens."
)
parser.add_argument(
"--repeat_last_n",
type=int,
2023-04-12 20:36:03 +00:00
default=None,
help="Number of previous tokens to consider for the repeat penalty.",
)
parser.add_argument(
"--ctx_size",
type=int,
2023-04-12 20:36:03 +00:00
default=None,#2048,
help="Size of the context window for the model.",
)
parser.add_argument(
"--debug",
dest="debug",
action="store_true",
default=None,
help="launch Flask server in debug mode",
)
parser.add_argument(
2023-04-13 10:31:48 +00:00
"--host", type=str, default=None, help="the hostname to listen on"
)
2023-04-12 20:36:03 +00:00
parser.add_argument("--port", type=int, default=None, help="the port to listen on")
parser.add_argument(
2023-04-12 20:36:03 +00:00
"--db_path", type=str, default=None, help="Database path"
)
2023-04-06 19:12:49 +00:00
args = parser.parse_args()
2023-06-12 13:45:59 +00:00
# Configuration loading part
config = LOLLMSConfig.autoload(lollms_paths)
2023-06-15 10:03:05 +00:00
2023-04-12 20:36:03 +00:00
# Override values in config with command-line arguments
for arg_name, arg_value in vars(args).items():
if arg_value is not None:
config[arg_name] = arg_value
2023-04-06 19:12:49 +00:00
# executor = ThreadPoolExecutor(max_workers=1)
# app.config['executor'] = executor
2023-06-12 13:45:59 +00:00
bot = LoLLMsWebUI(app, socketio, config, config.file_path, lollms_paths)
2023-04-06 19:12:49 +00:00
# chong Define custom WebSocketHandler with error handling
class CustomWebSocketHandler(WebSocketHandler):
def handle_error(self, environ, start_response, e):
# Handle the error here
print("WebSocket error:", e)
super().handle_error(environ, start_response, e)
2023-06-21 22:43:59 +00:00
# chong -add socket server
app.config['debug'] = config["debug"]
if config["debug"]:
2023-06-21 22:43:59 +00:00
ASCIIColors.info("debug mode:true")
else:
2023-06-21 22:43:59 +00:00
ASCIIColors.info("debug mode:false")
2023-06-25 17:22:16 +00:00
2023-06-21 22:43:59 +00:00
url = f'http://{config["host"]}:{config["port"]}'
2023-06-25 22:17:14 +00:00
if config["host"]!="localhost":
2023-06-25 17:22:16 +00:00
print(f'Please open your browser and go to http://localhost:{config["port"]} to view the ui')
ASCIIColors.success(f'This server is visible from a remote PC. use this address http://{get_ip_address()}:{config["port"]}')
else:
print(f"Please open your browser and go to {url} to view the ui")
2023-05-31 23:57:46 +00:00
socketio.run(app, host=config["host"], port=config["port"])
# http_server = WSGIServer((config["host"], config["port"]), app, handler_class=WebSocketHandler)
# http_server.serve_forever()