Merge pull request #265 from ParisNeo/lollms

Lollms
This commit is contained in:
Saifeddine ALOUI 2023-06-10 15:53:34 +02:00 committed by GitHub
commit f8c685ff18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 82 additions and 52 deletions

View File

@ -12,9 +12,9 @@ from api.db import DiscussionsDB
from api.helpers import compare_lists
from pathlib import Path
import importlib
from lollms import AIPersonality, MSG_TYPE
from lollms.binding import BindingConfig
from lollms.paths import lollms_path, lollms_personal_configuration_path, lollms_personal_path, lollms_personal_models_path, lollms_bindings_zoo_path, lollms_personalities_zoo_path, lollms_default_cfg_path
from lollms.personality import AIPersonality, MSG_TYPE
from lollms.binding import LOLLMSConfig
from lollms.paths import LollmsPaths
import multiprocessing as mp
import threading
import time
@ -83,8 +83,9 @@ def parse_requirements_file(requirements_path):
class ModelProcess:
def __init__(self, config:BindingConfig=None):
def __init__(self, lollms_paths:LollmsPaths, config:LOLLMSConfig=None):
self.config = config
self.lollms_paths = lollms_paths
self.generate_queue = mp.Queue()
self.generation_queue = mp.Queue()
self.cancel_queue = mp.Queue(maxsize=1)
@ -92,8 +93,6 @@ class ModelProcess:
self.set_config_queue = mp.Queue(maxsize=1)
self.set_config_result_queue = mp.Queue(maxsize=1)
self.models_path = lollms_personal_models_path
self.process = None
# Create synchronization objects
self.start_signal = mp.Event()
@ -139,7 +138,7 @@ class ModelProcess:
print(f"Loading binding {binding_name} install ON")
else:
print(f"Loading binding : {binding_name} install is off")
binding_path = lollms_path/"bindings_zoo"/binding_name
binding_path = self.lollms_paths.bindings_zoo_path/binding_name
if install:
# first find out if there is a requirements.txt file
install_file_name="install.py"
@ -223,7 +222,7 @@ class ModelProcess:
self.binding = self.load_binding(self.config["binding_name"], install=True)
print("Binding loaded successfully")
try:
model_file = self.config.models_path/self.config["binding_name"]/self.config["model_name"]
model_file = self.lollms_paths.personal_models_path/self.config["binding_name"]/self.config["model_name"]
print(f"Loading model : {model_file}")
self.model = self.binding(self.config)
self.model_ready.value = 1
@ -253,14 +252,15 @@ class ModelProcess:
for personality in self.config['personalities']:
try:
print(f" {personality}")
personality_path = lollms_personalities_zoo_path/f"{personality}"
personality = AIPersonality(personality_path, run_scripts=False)
personality_path = self.lollms_paths.personalities_zoo_path/f"{personality}"
print(f"Loading from {personality_path}")
personality = AIPersonality(self.lollms_paths, personality_path, run_scripts=False)
mounted_personalities.append(personality)
except Exception as ex:
print(f"Personality file not found or is corrupted ({personality_path}).\nPlease verify that the personality you have selected exists or select another personality. Some updates may lead to change in personality name or category, so check the personality selection in settings to be sure.")
if self.config["debug"]:
print(ex)
personality = AIPersonality()
personality = AIPersonality(self.lollms_paths)
print(f" ************ Personalities mounted (Main process) ***************************")
@ -274,14 +274,14 @@ class ModelProcess:
for personality in self.config['personalities']:
try:
print(f" {personality}")
personality_path = lollms_path/f"personalities_zoo/{personality}"
personality = AIPersonality(personality_path, run_scripts=True)
personality_path = self.lollms_paths.personalities_zoo_path/f"{personality}"
personality = AIPersonality(self.lollms_paths, personality_path, run_scripts=True)
self.mounted_personalities.append(personality)
except Exception as ex:
print(f"Personality file not found or is corrupted ({personality_path}).\nPlease verify that the personality you have selected exists or select another personality. Some updates may lead to change in personality name or category, so check the personality selection in settings to be sure.")
if self.config["debug"]:
print(ex)
personality = AIPersonality()
personality = AIPersonality(self.lollms_paths)
failed_personalities.append(personality_path)
self._set_config_result['errors'].append(f"couldn't build personalities:{ex}")
@ -462,10 +462,12 @@ class ModelProcess:
class LoLLMsAPPI():
def __init__(self, config:BindingConfig, socketio, config_file_path:str) -> None:
def __init__(self, config:LOLLMSConfig, socketio, config_file_path:str, lollms_paths: LollmsPaths) -> None:
self.lollms_paths = lollms_paths
self.socketio = socketio
#Create and launch the process
self.process = ModelProcess(config)
self.process = ModelProcess(self.lollms_paths, config)
self.config = config
self.binding = self.process.rebuild_binding(self.config)
self.mounted_personalities = self.process.rebuild_personalities()
@ -482,9 +484,12 @@ class LoLLMsAPPI():
self._message_id = 0
self.db_path = config["db_path"]
# Create database object
self.db = DiscussionsDB(self.db_path)
if Path(self.db_path).is_absolute():
# Create database object
self.db = DiscussionsDB(self.db_path)
else:
# Create database object
self.db = DiscussionsDB(self.lollms_paths.personal_path/"databases"/self.db_path)
# If the database is empty, populate it with tables
self.db.populate()

View File

@ -1,6 +1,6 @@
import sqlite3
from pathlib import Path
__author__ = "parisneo"
__github__ = "https://github.com/ParisNeo/lollms-webui"
__copyright__ = "Copyright 2023, "
@ -13,7 +13,8 @@ class DiscussionsDB:
MSG_TYPE_CONDITIONNING = 1
def __init__(self, db_path="database.db"):
self.db_path = db_path
self.db_path = Path(db_path)
self.db_path .parent.mkdir(exist_ok=True, parents= True)
def populate(self):
"""

78
app.py
View File

@ -24,9 +24,9 @@ import sys
from tqdm import tqdm
import subprocess
import signal
from lollms import AIPersonality, lollms_path, MSG_TYPE
from lollms.console import ASCIIColors
from lollms.paths import lollms_default_cfg_path, lollms_bindings_zoo_path, lollms_personalities_zoo_path, lollms_personal_path, lollms_personal_configuration_path, lollms_personal_models_path
from lollms.personality import AIPersonality, MSG_TYPE
from lollms.helpers import ASCIIColors, BaseConfig
from lollms.paths import LollmsPaths
from api.db import DiscussionsDB, Discussion
from api.helpers import compare_lists
from flask import (
@ -48,7 +48,7 @@ import requests
from concurrent.futures import ThreadPoolExecutor, as_completed
import logging
import psutil
from lollms.binding import BindingConfig
from lollms.binding import LOLLMSConfig
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
@ -71,8 +71,8 @@ import markdown
class LoLLMsWebUI(LoLLMsAPPI):
def __init__(self, _app, _socketio, config:BindingConfig, config_file_path) -> None:
super().__init__(config, _socketio, config_file_path)
def __init__(self, _app, _socketio, config:LOLLMSConfig, config_file_path:Path|str, lollms_paths:LollmsPaths) -> None:
super().__init__(config, _socketio, config_file_path, lollms_paths)
self.app = _app
self.cancel_gen = False
@ -87,6 +87,12 @@ class LoLLMsWebUI(LoLLMsAPPI):
# =========================================================================================
# Endpoints
# =========================================================================================
self.add_endpoint("/switch_personal_path", "switch_personal_path", self.switch_personal_path, methods=["POST"])
self.add_endpoint("/add_reference_to_local_model", "add_reference_to_local_model", self.add_reference_to_local_model, methods=["POST"])
self.add_endpoint("/send_file", "send_file", self.send_file, methods=["POST"])
@ -295,7 +301,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
return jsonify({"personality":self.personality.as_dict()})
def get_all_personalities(self):
personalities_folder = lollms_personalities_zoo_path
personalities_folder = self.lollms_paths.personalities_zoo_path
personalities = {}
for language_folder in personalities_folder.iterdir():
lang = language_folder.stem
@ -438,7 +444,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
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}"
personality_fn = lollms_personalities_zoo_path/self.config["personalities"][self.config["active_personality_id"]]
personality_fn = self.lollms_paths.personalities_zoo_path/self.config["personalities"][self.config["active_personality_id"]]
self.personality.load_personality(personality_fn)
else:
self.config["personalities"].append(f"{self.personality_language}/{self.personality_category}/{self.personality_name}")
@ -503,7 +509,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
current_drive = Path.cwd().anchor
drive_disk_usage = psutil.disk_usage(current_drive)
try:
models_folder_disk_usage = psutil.disk_usage(lollms_personal_models_path/f'{self.config["binding_name"]}')
models_folder_disk_usage = psutil.disk_usage(self.lollms_paths.personal_models_path/f'{self.config["binding_name"]}')
return jsonify({
"total_space":drive_disk_usage.total,
"available_space":drive_disk_usage.free,
@ -521,7 +527,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
})
def list_bindings(self):
bindings_dir = lollms_bindings_zoo_path # replace with the actual path to the models folder
bindings_dir = self.lollms_paths.bindings_zoo_path # replace with the actual path to the models folder
bindings=[]
for f in bindings_dir.iterdir():
card = f/"binding_card.yaml"
@ -530,7 +536,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
bnd = load_config(card)
bnd["folder"]=f.stem
icon_path = Path(f"bindings/{f.name}/logo.png")
if Path(lollms_bindings_zoo_path/f"{f.name}/logo.png").exists():
if Path(self.lollms_paths.bindings_zoo_path/f"{f.name}/logo.png").exists():
bnd["icon"]=str(icon_path)
bindings.append(bnd)
@ -548,18 +554,18 @@ class LoLLMsWebUI(LoLLMsAPPI):
def list_personalities_languages(self):
personalities_languages_dir = lollms_personalities_zoo_path # replace with the actual path to the models folder
personalities_languages_dir = self.lollms_paths.personalities_zoo_path # replace with the actual path to the models folder
personalities_languages = [f.stem for f in personalities_languages_dir.iterdir() if f.is_dir()]
return jsonify(personalities_languages)
def list_personalities_categories(self):
personalities_categories_dir = lollms_personalities_zoo_path/f'{self.personality_language}' # replace with the actual path to the models folder
personalities_categories_dir = self.lollms_paths.personalities_zoo_path/f'{self.personality_language}' # replace with the actual path to the models folder
personalities_categories = [f.stem for f in personalities_categories_dir.iterdir() if f.is_dir()]
return jsonify(personalities_categories)
def list_personalities(self):
try:
personalities_dir = lollms_personalities_zoo_path/f'{self.personality_language}/{self.personality_category}' # replace with the actual path to the models folder
personalities_dir = self.lollms_paths.personalities_zoo_path/f'{self.personality_language}/{self.personality_category}' # replace with the actual path to the models folder
personalities = [f.stem for f in personalities_dir.iterdir() if f.is_dir()]
except Exception as ex:
personalities=[]
@ -627,19 +633,19 @@ class LoLLMsWebUI(LoLLMsAPPI):
return send_from_directory(path, fn)
def serve_bindings(self, filename):
path = str(lollms_bindings_zoo_path/("/".join(filename.split("/")[:-1])))
path = str(self.lollms_paths.bindings_zoo_path/("/".join(filename.split("/")[:-1])))
fn = filename.split("/")[-1]
return send_from_directory(path, fn)
def serve_personalities(self, filename):
path = str(lollms_personalities_zoo_path/("/".join(filename.split("/")[:-1])))
path = str(self.lollms_paths.personalities_zoo_path/("/".join(filename.split("/")[:-1])))
fn = filename.split("/")[-1]
return send_from_directory(path, fn)
def serve_outputs(self, filename):
root_dir = lollms_personal_path / "outputs"
root_dir = self.lollms_paths.personal_path / "outputs"
root_dir.mkdir(exist_ok=True, parents=True)
path = str(root_dir/"/".join(filename.split("/")[:-1]))
@ -655,7 +661,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
return send_from_directory(path, fn)
def serve_data(self, filename):
root_dir = lollms_personal_path / "data"
root_dir = self.lollms_paths.personal_path / "data"
root_dir.mkdir(exist_ok=True, parents=True)
path = str(root_dir/"/".join(filename.split("/")[:-1]))
@ -663,7 +669,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
return send_from_directory(path, fn)
def serve_uploads(self, filename):
root_dir = lollms_personal_path / "uploads"
root_dir = self.lollms_paths.personal_path / "uploads"
root_dir.mkdir(exist_ok=True, parents=True)
path = str(root_dir+"/".join(filename.split("/")[:-1]))
@ -689,6 +695,22 @@ class LoLLMsWebUI(LoLLMsAPPI):
self.process.cancel_generation()
return jsonify({"status": True})
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}"})
def add_reference_to_local_model(self):
data = request.get_json()
path = data["path"]
@ -719,7 +741,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
name = data['name']
package_path = f"{language}/{category}/{name}"
package_full_path = lollms_path/"personalities_zoo"/package_path
package_full_path = self.lollms_paths.lollms_path/"personalities_zoo"/package_path
config_file = package_full_path / "config.yaml"
if config_file.exists():
self.config["personalities"].append(package_path)
@ -984,7 +1006,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
path = f'{server}{filename}'
else:
path = f'{server}/{filename}'
local_path = lollms_personal_models_path/f'{self.config["binding_name"]}/{filename}'
local_path = lollms_paths.personal_models_path/f'{self.config["binding_name"]}/{filename}'
is_installed = local_path.exists() or model_type.lower()=="api"
models.append({
'title': filename,
@ -1085,6 +1107,10 @@ def sync_cfg(default_config, config):
return config, added_entries, removed_entries
if __name__ == "__main__":
lollms_paths = LollmsPaths.find_paths(force_local=True)
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(
"-c", "--config", type=str, default="local_config", help="Sets the configuration file to be used."
@ -1159,12 +1185,12 @@ if __name__ == "__main__":
if args.config!="local_config":
args.config = "local_config"
if not lollms_personal_configuration_path/f"local_config.yaml".exists():
if not lollms_paths.personal_configuration_path/f"local_config.yaml".exists():
print("No local configuration file found. Building from scratch")
shutil.copy(default_config, lollms_personal_configuration_path/f"local_config.yaml")
shutil.copy(default_config, lollms_paths.personal_configuration_path/f"local_config.yaml")
config_file_path = lollms_personal_configuration_path/f"local_config.yaml"
config = BindingConfig(config_file_path)
config_file_path = lollms_paths.personal_configuration_path/f"local_config.yaml"
config = LOLLMSConfig(config_file_path)
if "version" not in config or int(config["version"])<int(default_config["version"]):
@ -1181,7 +1207,7 @@ if __name__ == "__main__":
# executor = ThreadPoolExecutor(max_workers=1)
# app.config['executor'] = executor
bot = LoLLMsWebUI(app, socketio, config, config_file_path)
bot = LoLLMsWebUI(app, socketio, config, config_file_path, lollms_paths)
# chong Define custom WebSocketHandler with error handling
class CustomWebSocketHandler(WebSocketHandler):

View File

@ -28,4 +28,4 @@ user_name: user
# UI parameters
debug: False
db_path: databases/database.db
db_path: database.db

2
global_paths_cfg.yaml Normal file
View File

@ -0,0 +1,2 @@
lollms_path: c:\Users\aloui\Documents\ai\GPT4ALL-ui\GPT4All\env\lib\site-packages\lollms
lollms_personal_path: C:\Users\aloui\Documents\lollms

View File

View File

@ -1,4 +0,0 @@
Here you can drop your models depending on the selected binding
Currently, supported bindings are:
- llamacpp
- gpt-j