reorganized endpoints for the new lollms-elf-server

This commit is contained in:
Saifeddine ALOUI 2024-01-06 02:04:28 +01:00
parent de5e73c90f
commit e42ec2c799
11 changed files with 1092 additions and 3 deletions

View File

@ -9,6 +9,7 @@ This class provides a singleton instance of the LoLLMS web UI, allowing access t
from lollms.app import LollmsApplication
from lollms.main_config import LOLLMSConfig
from lollms.paths import LollmsPaths
from pathlib import Path
class LOLLMSElfServer(LollmsApplication):
__instance = None
@ -76,3 +77,9 @@ class LOLLMSElfServer(LollmsApplication):
LOLLMSElfServer.__instance = self
# Other methods and properties of the LoLLMSWebUI singleton class
def find_extension(self, path:Path, filename:str, exts:list)->Path:
for ext in exts:
full_path = path/(filename+ext)
if full_path.exists():
return full_path
return None

View File

@ -0,0 +1,250 @@
"""
project: lollms
file: lollms_binding_infos.py
author: ParisNeo
description:
This module contains a set of FastAPI routes that provide information about the Lord of Large Language and Multimodal Systems (LoLLMs) Web UI
application. These routes are specific to bindings
"""
from fastapi import APIRouter, Request
from pydantic import BaseModel
import pkg_resources
from lollms.server.elf_server import LOLLMSElfServer
from lollms.binding import BindingBuilder, InstallOption
from ascii_colors import ASCIIColors
from lollms.utilities import load_config, trace_exception, gc
from pathlib import Path
from typing import List
import json
class ReloadBindingParams(BaseModel):
binding_name: str
class BindingInstallParams(BaseModel):
name: str
router = APIRouter()
lollmsElfServer = LOLLMSElfServer.get_instance()
# ----------------------------------- Listing -----------------------------------------
@router.get("/list_bindings")
def list_bindings():
"""
List all available bindings in the Lollms server.
Returns:
List[str]: A list of binding names.
"""
bindings_dir = lollmsElfServer.lollms_paths.bindings_zoo_path # replace with the actual path to the models folder
bindings=[]
for f in bindings_dir.iterdir():
if f.stem!="binding_template":
card = f/"binding_card.yaml"
if card.exists():
try:
bnd = load_config(card)
bnd["folder"]=f.stem
installed = (lollmsElfServer.lollms_paths.personal_configuration_path/"bindings"/f.stem/f"config.yaml").exists()
bnd["installed"]=installed
ui_file_path = f/"ui.html"
if ui_file_path.exists():
with ui_file_path.open("r") as file:
text_content = file.read()
bnd["ui"]=text_content
else:
bnd["ui"]=None
disclaimer_file_path = f/"disclaimer.md"
if disclaimer_file_path.exists():
with disclaimer_file_path.open("r") as file:
text_content = file.read()
bnd["disclaimer"]=text_content
else:
bnd["disclaimer"]=None
icon_file = lollmsElfServer.find_extension(lollmsElfServer.lollms_paths.bindings_zoo_path/f"{f.name}", "logo", [".svg",".gif",".png"])
if icon_file is not None:
icon_path = Path(f"bindings/{f.name}/logo{icon_file.suffix}")
bnd["icon"]=str(icon_path)
bindings.append(bnd)
except Exception as ex:
print(f"Couldn't load backend card : {f}\n\t{ex}")
return bindings
# ----------------------------------- Reloading ----------------------------------------
@router.post("/reload_binding")
def reload_binding( params: ReloadBindingParams):
print(f"Roloading binding selected : {params.binding_name}")
lollmsElfServer.config["binding_name"]=params.binding_name
try:
if lollmsElfServer.binding:
lollmsElfServer.binding.destroy_model()
lollmsElfServer.binding = None
lollmsElfServer.model = None
for per in lollmsElfServer.mounted_personalities:
per.model = None
gc.collect()
lollmsElfServer.binding = BindingBuilder().build_binding(lollmsElfServer.config, lollmsElfServer.lollms_paths, InstallOption.INSTALL_IF_NECESSARY, lollmsCom=lollmsElfServer)
lollmsElfServer.model = None
lollmsElfServer.config.save_config()
ASCIIColors.green("Binding loaded successfully")
except Exception as ex:
ASCIIColors.error(f"Couldn't build binding: [{ex}]")
trace_exception(ex)
return {"status":False, 'error':str(ex)}
# ----------------------------------- Installation/Uninstallation/Reinstallation ----------------------------------------
@router.post("/install_binding")
def install_binding(data:BindingInstallParams):
"""Install a new binding on the server.
Args:
data (BindingInstallParams): Parameters required for installation.
format:
name: str : the name of the binding
Returns:
dict: Status of operation.
"""
ASCIIColors.info(f"- Reinstalling binding {data.name}...")
try:
lollmsElfServer.info("Unmounting binding and model")
lollmsElfServer.info("Reinstalling binding")
old_bn = lollmsElfServer.config.binding_name
lollmsElfServer.config.binding_name = data.name
lollmsElfServer.binding = BindingBuilder().build_binding(lollmsElfServer.config, lollmsElfServer.lollms_paths, InstallOption.FORCE_INSTALL, lollmsCom=lollmsElfServer)
lollmsElfServer.success("Binding installed successfully")
del lollmsElfServer.binding
lollmsElfServer.binding = None
lollmsElfServer.config.binding_name = old_bn
if old_bn is not None:
lollmsElfServer.binding = BindingBuilder().build_binding(lollmsElfServer.config, lollmsElfServer.lollms_paths, lollmsCom=lollmsElfServer)
lollmsElfServer.model = lollmsElfServer.binding.build_model()
for per in lollmsElfServer.mounted_personalities:
per.model = lollmsElfServer.model
return {"status": True}
except Exception as ex:
lollmsElfServer.error(f"Couldn't build binding: [{ex}]")
trace_exception(ex)
return {"status":False, 'error':str(ex)}
@router.post("/reinstall_binding")
def reinstall_binding(data:BindingInstallParams):
"""Reinstall an already installed binding on the server.
Args:
data (BindingInstallParams): Parameters required for reinstallation.
format:
name: str : the name of the binding
Returns:
dict: Status of operation.
"""
ASCIIColors.info(f"- Reinstalling binding {data.name}...")
try:
ASCIIColors.info("Unmounting binding and model")
del lollmsElfServer.binding
lollmsElfServer.binding = None
gc.collect()
ASCIIColors.info("Reinstalling binding")
old_bn = lollmsElfServer.config.binding_name
lollmsElfServer.config.binding_name = data.name
lollmsElfServer.binding = BindingBuilder().build_binding(lollmsElfServer.config, lollmsElfServer.lollms_paths, InstallOption.FORCE_INSTALL, lollmsCom=lollmsElfServer)
lollmsElfServer.success("Binding reinstalled successfully")
lollmsElfServer.config.binding_name = old_bn
lollmsElfServer.binding = BindingBuilder().build_binding(lollmsElfServer.config, lollmsElfServer.lollms_paths, lollmsCom=lollmsElfServer)
lollmsElfServer.model = lollmsElfServer.binding.build_model()
for per in lollmsElfServer.mounted_personalities:
per.model = lollmsElfServer.model
return {"status": True}
except Exception as ex:
ASCIIColors.error(f"Couldn't build binding: [{ex}]")
trace_exception(ex)
return {"status":False, 'error':str(ex)}
@router.post("/unInstall_binding")
def unInstall_binding(data:BindingInstallParams):
"""Uninstall an installed binding from the server.
Args:
data (BindingInstallParams): Parameters required for uninstallation.
format:
name: str : the name of the binding
Returns:
dict: Status of operation.
"""
ASCIIColors.info(f"- Reinstalling binding {data.name}...")
try:
ASCIIColors.info("Unmounting binding and model")
if lollmsElfServer.binding is not None:
del lollmsElfServer.binding
lollmsElfServer.binding = None
gc.collect()
ASCIIColors.info("Uninstalling binding")
old_bn = lollmsElfServer.config.binding_name
lollmsElfServer.config.binding_name = data.name
lollmsElfServer.binding = BindingBuilder().build_binding(lollmsElfServer.config, lollmsElfServer.lollms_paths, InstallOption.NEVER_INSTALL, lollmsCom=lollmsElfServer)
lollmsElfServer.binding.uninstall()
ASCIIColors.green("Uninstalled successful")
if old_bn!=lollmsElfServer.config.binding_name:
lollmsElfServer.config.binding_name = old_bn
lollmsElfServer.binding = BindingBuilder().build_binding(lollmsElfServer.config, lollmsElfServer.lollms_paths, lollmsCom=lollmsElfServer)
lollmsElfServer.model = lollmsElfServer.binding.build_model()
for per in lollmsElfServer.mounted_personalities:
per.model = lollmsElfServer.model
else:
lollmsElfServer.config.binding_name = None
if lollmsElfServer.config.auto_save:
ASCIIColors.info("Saving configuration")
lollmsElfServer.config.save_config()
return {"status": True}
except Exception as ex:
ASCIIColors.error(f"Couldn't build binding: [{ex}]")
trace_exception(ex)
return {"status":False, 'error':str(ex)}
# ----------------------------------- Bet binding settings ----------------------------------------
@router.get("/get_active_binding_settings")
def get_active_binding_settings():
print("- Retreiving binding settings")
if lollmsElfServer.binding is not None:
if hasattr(lollmsElfServer.binding,"binding_config"):
return lollmsElfServer.binding.binding_config.config_template.template
else:
return {}
else:
return {}
def set_active_binding_settings(data):
print("- Setting binding settings")
if lollmsElfServer.binding is not None:
if hasattr(lollmsElfServer.binding,"binding_config"):
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"]]
lollmsElfServer.binding.binding_config.update_template(data)
lollmsElfServer.binding.binding_config.config.save_config()
lollmsElfServer.binding.settings_updated()
if lollmsElfServer.config.auto_save:
ASCIIColors.info("Saving configuration")
lollmsElfServer.config.save_config()
return {'status':True}
else:
return {'status':False}
else:
return {'status':False}

View File

@ -0,0 +1,25 @@
"""
project: lollms
file: lollms_extensions_infos.py
author: ParisNeo
description:
This module contains a set of FastAPI routes that provide information about the Lord of Large Language and Multimodal Systems (LoLLMs) Web UI
application. These routes are specific to handling extensions related operations.
"""
from fastapi import APIRouter, Request
from pydantic import BaseModel
import pkg_resources
from lollms.server.elf_server import LOLLMSElfServer
from ascii_colors import ASCIIColors
from lollms.utilities import load_config, trace_exception
from pathlib import Path
from typing import List
import psutil
import yaml
router = APIRouter()
lollmsElfServer = LOLLMSElfServer.get_instance()
# --------------------- Listing -------------------------------

View File

@ -1,3 +1,13 @@
"""
project: lollms
file: lollms_generator.py
author: ParisNeo
description:
This module contains a set of FastAPI routes that provide information about the Lord of Large Language and Multimodal Systems (LoLLMs) Web UI
application. These routes are specific to the generation process
"""
from fastapi import APIRouter
from lollms.server.elf_server import LOLLMSElfServer
from pydantic import BaseModel

View File

@ -0,0 +1,93 @@
"""
project: lollms
file: lollms_hardware_infos.py
author: ParisNeo
description:
This module contains a set of FastAPI routes that provide information about the Lord of Large Language and Multimodal Systems (LoLLMs) Web UI
application. These routes are specific to handling hardware information
"""
from fastapi import APIRouter, Request
import pkg_resources
from lollms.server.elf_server import LOLLMSElfServer
from ascii_colors import ASCIIColors
from lollms.utilities import load_config
from pathlib import Path
from typing import List
import psutil
import subprocess
router = APIRouter()
lollmsElfServer = LOLLMSElfServer.get_instance()
@router.get("/disk_usage")
def disk_usage():
current_drive = Path.cwd().anchor
drive_disk_usage = psutil.disk_usage(current_drive)
try:
models_folder_disk_usage = psutil.disk_usage(str(lollmsElfServer.lollms_paths.personal_models_path/f'{lollmsElfServer.config["binding_name"]}'))
return {
"total_space":drive_disk_usage.total,
"available_space":drive_disk_usage.free,
"usage":drive_disk_usage.used,
"percent_usage":drive_disk_usage.percent,
"binding_disk_total_space":models_folder_disk_usage.total,
"binding_disk_available_space":models_folder_disk_usage.free,
"binding_models_usage": models_folder_disk_usage.used,
"binding_models_percent_usage": models_folder_disk_usage.percent,
}
except Exception as ex:
return {
"total_space":drive_disk_usage.total,
"available_space":drive_disk_usage.free,
"percent_usage":drive_disk_usage.percent,
"binding_disk_total_space": None,
"binding_disk_available_space": None,
"binding_models_usage": None,
"binding_models_percent_usage": None,
}
@router.get("/ram_usage")
def ram_usage():
"""
Returns the RAM usage in bytes.
"""
ram = psutil.virtual_memory()
return {
"total_space":ram.total,
"available_space":ram.free,
"percent_usage":ram.percent,
"ram_usage": ram.used
}
@router.get("/vram_usage")
def vram_usage():
try:
output = subprocess.check_output(['nvidia-smi', '--query-gpu=memory.total,memory.used,gpu_name', '--format=csv,nounits,noheader'])
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):
ram_usage[f"gpu_{i}_total_vram"] = int(gpu[0])*1024*1024
ram_usage[f"gpu_{i}_used_vram"] = int(gpu[1])*1024*1024
ram_usage[f"gpu_{i}_model"] = gpu[2].strip()
else:
# Set all VRAM-related entries to None
ram_usage["gpu_0_total_vram"] = None
ram_usage["gpu_0_used_vram"] = None
ram_usage["gpu_0_model"] = None
return ram_usage

View File

@ -1,11 +1,26 @@
from fastapi import APIRouter
"""
project: lollms
file: lollms_infos.py
author: ParisNeo
description:
This module contains a set of FastAPI routes that provide information about the Lord of Large Language and Multimodal Systems (LoLLMs) Web UI
application. These routes are specific to handling lollms information like version and configuration
"""
from fastapi import APIRouter, Request
import pkg_resources
from lollms.server.elf_server import LOLLMSElfServer
from ascii_colors import ASCIIColors
from lollms.utilities import load_config
from pathlib import Path
from typing import List
import psutil
router = APIRouter()
lollmsWebUI = LOLLMSElfServer.get_instance()
lollmsElfServer = LOLLMSElfServer.get_instance()
@router.get("/get_lollms_version")
@router.get("/version")
def get_version():
"""
@ -17,3 +32,32 @@ def get_version():
version = pkg_resources.get_distribution('lollms').version
ASCIIColors.yellow("Lollms version: " + version)
return {"version": version}
@router.get("/get_config")
def get_config():
"""
Get the configuration of the Lollms server.
Returns:
Config: The configuration object as a Pydantic model.
"""
return lollmsElfServer.config.to_dict()
@router.get("/get_server_address")
def get_server_address(request:Request):
"""
Get the server address for the current request.
Returns:
str: The server address without the endpoint path.
"""
server_address = request.url_for("get_server_address")
srv_addr = "/".join(str(server_address).split("/")[:-1])
ASCIIColors.yellow(server_address)
return srv_addr

View File

@ -0,0 +1,96 @@
"""
project: lollms
file: lollms_models_infos.py
author: ParisNeo
description:
This module contains a set of FastAPI routes that provide information about the Lord of Large Language and Multimodal Systems (LoLLMs) Web UI
application. These routes are specific to handling models related operations.
"""
from fastapi import APIRouter, Request
from pydantic import BaseModel
import pkg_resources
from lollms.server.elf_server import LOLLMSElfServer
from ascii_colors import ASCIIColors
from lollms.utilities import load_config
from pathlib import Path
from typing import List
import psutil
class ModelReferenceParams(BaseModel):
path: str
router = APIRouter()
lollmsElfServer = LOLLMSElfServer.get_instance()
@router.get("/list_models")
async def list_models():
"""
List all available models for the specified binding.
Parameters:
- binding (str): Name of the binding to retrieve models from.
Returns:
List[str]: A list of model names.
"""
if lollmsElfServer.binding is not None:
ASCIIColors.yellow("Listing models")
models = lollmsElfServer.binding.list_models()
ASCIIColors.green("ok")
return models
else:
return []
@router.get("/get_available_models")
async def get_available_models():
"""
Retrieve a list of available models for the currently selected binding.
Returns:
List[str]: A list of model names.
"""
if lollmsElfServer.binding is None:
return []
try:
model_list = lollmsElfServer.binding.get_available_models(lollmsElfServer)
except Exception as ex:
lollmsElfServer.error("Coudln't list models. Please reinstall the binding or notify ParisNeo on the discord server")
return []
return model_list
@router.get("/get_active_model")
def get_active_model():
if lollmsElfServer.binding is not None:
try:
ASCIIColors.yellow("Getting active model")
models = lollmsElfServer.binding.list_models()
index = models.index(lollmsElfServer.config.model_name)
ASCIIColors.green("ok")
return {"status":True,"model":models[index],"index":index}
except Exception as ex:
return {"status":False}
else:
return {"status":False}
@router.get("/get_model_status")
def get_model_status():
return {"status":lollmsElfServer.model is not None}
@router.post("/add_reference_to_local_model")
def add_reference_to_local_model(data:ModelReferenceParams):
if data.path=="":
return {"status": False, "error":"Empty model path"}
path = Path(data.path)
if path.exists():
lollmsElfServer.config.reference_model(path)
return {"status": True}
else:
return {"status": False, "error":"Model not found"}

View File

@ -0,0 +1,476 @@
"""
project: lollms
file: lollms_personalities_infos.py
author: ParisNeo
description:
This module contains a set of FastAPI routes that provide information about the Lord of Large Language and Multimodal Systems (LoLLMs) Web UI
application. These routes are specific to handling personalities related operations.
"""
from fastapi import APIRouter, Request
from pydantic import BaseModel
import pkg_resources
from lollms.server.elf_server import LOLLMSElfServer
from lollms.personality import AIPersonality, InstallOption
from ascii_colors import ASCIIColors
from lollms.utilities import load_config, trace_exception, gc
from pathlib import Path
from typing import List
import psutil
import yaml
# --------------------- Parameter Classes -------------------------------
class PersonalityListingInfos(BaseModel):
category:str
class PersonalityInstallInfos(BaseModel):
name:str
class PersonalityMountingInfos(BaseModel):
category:str
folder:str
language:str
class PersonalitySelectionInfos(BaseModel):
id:int
# --------------------- Route -------------------------------
router = APIRouter()
lollmsElfServer = LOLLMSElfServer.get_instance()
# --------------------- Listing -------------------------------
@router.get("/list_personalities_categories")
def list_personalities_categories():
personalities_categories_dir = lollmsElfServer.lollms_paths.personalities_zoo_path # replace with the actual path to the models folder
personalities_categories = ["custom_personalities"]+[f.stem for f in personalities_categories_dir.iterdir() if f.is_dir() and not f.name.startswith(".")]
return personalities_categories
@router.get("/list_personalities")
def list_personalities(category:PersonalityListingInfos):
if not category:
return []
try:
if category=="custom_personalities":
personalities_dir = lollmsElfServer.lollms_paths.custom_personalities_path # replace with the actual path to the models folder
else:
personalities_dir = lollmsElfServer.lollms_paths.personalities_zoo_path/f'{category}' # replace with the actual path to the models folder
personalities = [f.stem for f in personalities_dir.iterdir() if f.is_dir() and not f.name.startswith(".")]
except Exception as ex:
personalities=[]
ASCIIColors.error(f"No personalities found. Using default one {ex}")
return personalities
@router.get("/get_all_personalities")
def get_all_personalities():
ASCIIColors.yellow("Listing all personalities")
personalities_folder = lollmsElfServer.lollms_paths.personalities_zoo_path
personalities = {}
for category_folder in [lollmsElfServer.lollms_paths.custom_personalities_path] + list(personalities_folder.iterdir()):
cat = category_folder.stem
if category_folder.is_dir() and not category_folder.stem.startswith('.'):
personalities[cat if category_folder!=lollmsElfServer.lollms_paths.custom_personalities_path else "custom_personalities"] = []
for personality_folder in category_folder.iterdir():
pers = personality_folder.stem
if personality_folder.is_dir() and not personality_folder.stem.startswith('.'):
personality_info = {"folder":personality_folder.stem}
config_path = personality_folder / 'config.yaml'
if not config_path.exists():
"""
try:
shutil.rmtree(str(config_path.parent))
ASCIIColors.warning(f"Deleted useless personality: {config_path.parent}")
except Exception as ex:
ASCIIColors.warning(f"Couldn't delete personality ({ex})")
"""
continue
try:
scripts_path = personality_folder / 'scripts'
personality_info['has_scripts'] = scripts_path.exists()
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',"")
personality_info['disclaimer'] = config_data.get('disclaimer',"")
personality_info['author'] = config_data.get('author', 'ParisNeo')
personality_info['version'] = config_data.get('version', '1.0.0')
personality_info['installed'] = (lollmsElfServer.lollms_paths.personal_configuration_path/f"personality_{personality_folder.stem}.yaml").exists() or personality_info['has_scripts']
personality_info['help'] = config_data.get('help', '')
personality_info['commands'] = config_data.get('commands', '')
languages_path = personality_folder/ 'languages'
real_assets_path = personality_folder/ 'assets'
assets_path = Path("personalities") / cat / pers / 'assets'
gif_logo_path = assets_path / 'logo.gif'
webp_logo_path = assets_path / 'logo.webp'
png_logo_path = assets_path / 'logo.png'
jpg_logo_path = assets_path / 'logo.jpg'
jpeg_logo_path = assets_path / 'logo.jpeg'
svg_logo_path = assets_path / 'logo.svg'
bmp_logo_path = assets_path / 'logo.bmp'
gif_logo_path_ = real_assets_path / 'logo.gif'
webp_logo_path_ = real_assets_path / 'logo.webp'
png_logo_path_ = real_assets_path / 'logo.png'
jpg_logo_path_ = real_assets_path / 'logo.jpg'
jpeg_logo_path_ = real_assets_path / 'logo.jpeg'
svg_logo_path_ = real_assets_path / 'logo.svg'
bmp_logo_path_ = real_assets_path / 'logo.bmp'
if languages_path.exists():
personality_info['languages']= [""]+[f.stem for f in languages_path.iterdir() if f.suffix==".yaml"]
else:
personality_info['languages']=None
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 svg_logo_path_.exists():
personality_info['avatar'] = str(svg_logo_path).replace("\\","/")
elif bmp_logo_path_.exists():
personality_info['avatar'] = str(bmp_logo_path).replace("\\","/")
else:
personality_info['avatar'] = ""
personalities[cat if category_folder!=lollmsElfServer.lollms_paths.custom_personalities_path else "custom_personalities"].append(personality_info)
except Exception as ex:
ASCIIColors.warning(f"Couldn't load personality from {personality_folder} [{ex}]")
trace_exception(ex)
ASCIIColors.green("OK")
return personalities
@router.get("/list_mounted_personalities")
def list_mounted_personalities(lollmsElfServer):
ASCIIColors.yellow("- Listing mounted personalities")
return {"status": True,
"personalities":lollmsElfServer.config["personalities"],
"active_personality_id":lollmsElfServer.config["active_personality_id"]
}
# ----------------------------------- Installation/Uninstallation/Reinstallation ----------------------------------------
@router.post("/reinstall_personality")
def reinstall_personality(data: PersonalityInstallInfos):
if not 'name' in data:
data['name']=lollmsElfServer.config.personalities[lollmsElfServer.config["active_personality_id"]]
try:
personality_path = lollmsElfServer.lollms_paths.personalities_zoo_path / data['name']
ASCIIColors.info(f"- Reinstalling personality {data['name']}...")
ASCIIColors.info("Unmounting personality")
idx = lollmsElfServer.config.personalities.index(data['name'])
print(f"index = {idx}")
lollmsElfServer.mounted_personalities[idx] = None
gc.collect()
try:
lollmsElfServer.mounted_personalities[idx] = AIPersonality(personality_path,
lollmsElfServer.lollms_paths,
lollmsElfServer.config,
model=lollmsElfServer.model,
app=lollmsElfServer,
run_scripts=True,installation_option=InstallOption.FORCE_INSTALL)
return {"status":True}
except Exception as ex:
ASCIIColors.error(f"Personality file not found or is corrupted ({data['name']}).\nReturned the following exception:{ex}\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.")
ASCIIColors.info("Trying to force reinstall")
return {"status":False, 'error':str(e)}
except Exception as e:
return {"status":False, 'error':str(e)}
# ------------------------------------------- Files manipulation -----------------------------------------------------
@router.get("/get_current_personality_files_list")
def get_current_personality_files_list():
if lollmsElfServer.personality is None:
return {"state":False, "error":"No personality selected"}
return {"state":True, "files":[{"name":Path(f).name, "size":Path(f).stat().st_size} for f in lollmsElfServer.personality.text_files]+[{"name":Path(f).name, "size":Path(f).stat().st_size} for f in lollmsElfServer.personality.image_files]}
@router.get("/clear_personality_files_list")
def clear_personality_files_list():
if lollmsElfServer.personality is None:
return {"state":False, "error":"No personality selected"}
lollmsElfServer.personality.remove_all_files()
return {"state":True}
# ------------------------------------------- Mounting/Unmounting/Remounting ------------------------------------------------
@router.post("/mount_personality")
def mount_personality(data:PersonalityMountingInfos):
print("- Mounting personality")
category = data.category
name = data.folder
language = data.language #.get('language', None)
package_path = f"{category}/{name}"
if category=="custom_personalities":
package_full_path = lollmsElfServer.lollms_paths.custom_personalities_path/f"{name}"
else:
package_full_path = lollmsElfServer.lollms_paths.personalities_zoo_path/package_path
config_file = package_full_path / "config.yaml"
if config_file.exists():
if language:
package_path += ":" + language
"""
if package_path in lollmsElfServer.config["personalities"]:
ASCIIColors.error("Can't mount exact same personality twice")
return jsonify({"status": False,
"error":"Can't mount exact same personality twice",
"personalities":lollmsElfServer.config["personalities"],
"active_personality_id":lollmsElfServer.config["active_personality_id"]
})
"""
lollmsElfServer.config["personalities"].append(package_path)
lollmsElfServer.mounted_personalities = lollmsElfServer.rebuild_personalities()
lollmsElfServer.config["active_personality_id"]= len(lollmsElfServer.config["personalities"])-1
lollmsElfServer.personality = lollmsElfServer.mounted_personalities[lollmsElfServer.config["active_personality_id"]]
ASCIIColors.success("ok")
if lollmsElfServer.config["active_personality_id"]<0:
ASCIIColors.error("error:active_personality_id<0")
return {"status": False,
"error":"active_personality_id<0",
"personalities":lollmsElfServer.config["personalities"],
"active_personality_id":lollmsElfServer.config["active_personality_id"]
}
else:
if lollmsElfServer.config.auto_save:
ASCIIColors.info("Saving configuration")
lollmsElfServer.config.save_config()
ASCIIColors.success(f"Personality {name} mounted successfully")
return {"status": True,
"personalities":lollmsElfServer.config["personalities"],
"active_personality_id":lollmsElfServer.config["active_personality_id"]
}
else:
pth = str(config_file).replace('\\','/')
ASCIIColors.error(f"nok : Personality not found @ {pth}")
ASCIIColors.yellow(f"Available personalities: {[p.name for p in lollmsElfServer.mounted_personalities]}")
return {"status": False, "error":f"Personality not found @ {pth}"}
@router.post("/remount_personality")
def remount_personality(data:PersonalityMountingInfos):
category = data.category
name = data.folder
language = data.language #.get('language', None)
package_path = f"{category}/{name}"
if category=="custom_personalities":
package_full_path = lollmsElfServer.lollms_paths.custom_personalities_path/f"{name}"
else:
package_full_path = lollmsElfServer.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 = lollmsElfServer.config["personalities"].index(f"{category}/{name}")
lollmsElfServer.config["personalities"].remove(f"{category}/{name}")
if lollmsElfServer.config["active_personality_id"]>=index:
lollmsElfServer.config["active_personality_id"]=0
if len(lollmsElfServer.config["personalities"])>0:
lollmsElfServer.mounted_personalities = lollmsElfServer.rebuild_personalities()
lollmsElfServer.personality = lollmsElfServer.mounted_personalities[lollmsElfServer.config["active_personality_id"]]
else:
lollmsElfServer.personalities = ["generic/lollms"]
lollmsElfServer.mounted_personalities = lollmsElfServer.rebuild_personalities()
lollmsElfServer.personality = lollmsElfServer.mounted_personalities[lollmsElfServer.config["active_personality_id"]]
ASCIIColors.info(f"Mounting personality {package_path}")
lollmsElfServer.config["personalities"].append(package_path)
lollmsElfServer.config["active_personality_id"]= len(lollmsElfServer.config["personalities"])-1
lollmsElfServer.mounted_personalities = lollmsElfServer.rebuild_personalities()
lollmsElfServer.personality = lollmsElfServer.mounted_personalities[lollmsElfServer.config["active_personality_id"]]
ASCIIColors.success("ok")
if lollmsElfServer.config["active_personality_id"]<0:
return {"status": False,
"personalities":lollmsElfServer.config["personalities"],
"active_personality_id":lollmsElfServer.config["active_personality_id"]
}
else:
return {"status": True,
"personalities":lollmsElfServer.config["personalities"],
"active_personality_id":lollmsElfServer.config["active_personality_id"]
}
else:
pth = str(config_file).replace('\\','/')
ASCIIColors.error(f"nok : Personality not found @ {pth}")
ASCIIColors.yellow(f"Available personalities: {[p.name for p in lollmsElfServer.mounted_personalities]}")
return {"status": False, "error":f"Personality not found @ {pth}"}
@router.post("/remount_personality")
def unmount_personality(data:PersonalityMountingInfos):
print("- Unmounting personality ...")
category = data.category
name = data.folder
language = data.language #.get('language', None)
try:
personality_id = f"{category}/{name}" if language is None or language=="" else f"{category}/{name}:{language}"
index = lollmsElfServer.config["personalities"].index(personality_id)
lollmsElfServer.config["personalities"].remove(personality_id)
if lollmsElfServer.config["active_personality_id"]>=index:
lollmsElfServer.config["active_personality_id"]=0
if len(lollmsElfServer.config["personalities"])>0:
lollmsElfServer.mounted_personalities = lollmsElfServer.rebuild_personalities()
lollmsElfServer.personality = lollmsElfServer.mounted_personalities[lollmsElfServer.config["active_personality_id"]]
else:
lollmsElfServer.personalities = ["generic/lollms"]
lollmsElfServer.mounted_personalities = lollmsElfServer.rebuild_personalities()
if lollmsElfServer.config["active_personality_id"]<len(lollmsElfServer.mounted_personalities):
lollmsElfServer.personality = lollmsElfServer.mounted_personalities[lollmsElfServer.config["active_personality_id"]]
else:
lollmsElfServer.config["active_personality_id"] = -1
ASCIIColors.success("ok")
if lollmsElfServer.config.auto_save:
ASCIIColors.info("Saving configuration")
lollmsElfServer.config.save_config()
return {
"status": True,
"personalities":lollmsElfServer.config["personalities"],
"active_personality_id":lollmsElfServer.config["active_personality_id"]
}
except Exception as ex:
trace_exception(ex)
if language:
ASCIIColors.error(f"nok : Personality not found @ {category}/{name}:{language}")
else:
ASCIIColors.error(f"nok : Personality not found @ {category}/{name}")
ASCIIColors.yellow(f"Available personalities: {[p.name for p in lollmsElfServer.mounted_personalities]}")
return {"status": False, "error":"Couldn't unmount personality"}
@router.post("/unmount_all_personalities")
def unmount_all_personalities():
lollmsElfServer.config.personalities=["generic/lollms"]
lollmsElfServer.mounted_personalities=[]
lollmsElfServer.personality=None
lollmsElfServer.mount_personality(0)
lollmsElfServer.config.save_config()
return {"status":True}
# ------------------------------------------- Selecting personality ------------------------------------------------
@router.post("/select_personality")
def select_personality(data:PersonalitySelectionInfos):
ASCIIColors.info("Selecting personality")
id = data.id
print(f"- Selecting active personality {id} ...",end="")
if id<len(lollmsElfServer.mounted_personalities):
lollmsElfServer.config["active_personality_id"]=id
lollmsElfServer.personality:AIPersonality = lollmsElfServer.mounted_personalities[lollmsElfServer.config["active_personality_id"]]
if lollmsElfServer.personality.processor:
lollmsElfServer.personality.processor.selected()
ASCIIColors.success("ok")
print(f"Selected {lollmsElfServer.personality.name}")
if lollmsElfServer.config.auto_save:
ASCIIColors.info("Saving configuration")
lollmsElfServer.config.save_config()
return {
"status": True,
"personalities":lollmsElfServer.config["personalities"],
"active_personality_id":lollmsElfServer.config["active_personality_id"]
}
else:
ASCIIColors.error(f"nok : personality id out of bounds @ {id} >= {len(lollmsElfServer.mounted_personalities)}")
return {"status": False, "error":"Invalid ID"}
# ------------------------------------------- Personality settings------------------------------------------------
@router.post("/get_personality_settings")
def get_personality_settings(data:PersonalityMountingInfos):
print("- Retreiving personality settings")
category = data.category
name = data.folder
if category.startswith("personal"):
personality_folder = lollmsElfServer.lollms_paths.personal_personalities_path/f"{category}"/f"{name}"
else:
personality_folder = lollmsElfServer.lollms_paths.personalities_zoo_path/f"{category}"/f"{name}"
personality = AIPersonality(personality_folder,
lollmsElfServer.lollms_paths,
lollmsElfServer.config,
model=lollmsElfServer.model,
app=lollmsElfServer,
run_scripts=True)
if personality.processor is not None:
if hasattr(personality.processor,"personality_config"):
return personality.processor.personality_config.config_template.template
else:
return {}
else:
return {}
@router.get("/get_active_personality_settings")
def get_active_personality_settings():
print("- Retreiving personality settings")
if lollmsElfServer.personality.processor is not None:
if hasattr(lollmsElfServer.personality.processor,"personality_config"):
return lollmsElfServer.personality.processor.personality_config.config_template.template
else:
return {}
else:
return {}
@router.post("/get_active_personality_settings")
def set_active_personality_settings(data):
print("- Setting personality settings")
if lollmsElfServer.personality.processor is not None:
if hasattr(lollmsElfServer.personality.processor,"personality_config"):
lollmsElfServer.personality.processor.personality_config.update_template(data)
lollmsElfServer.personality.processor.personality_config.config.save_config()
if lollmsElfServer.config.auto_save:
ASCIIColors.info("Saving configuration")
lollmsElfServer.config.save_config()
return {'status':True}
else:
return {'status':False}
else:
return {'status':False}
# ------------------------------------------- Interaction with personas ------------------------------------------------
@router.get("/post_to_personality")
def post_to_personality(data):
"""Post data to a personality"""
if hasattr(lollmsElfServer.personality.processor,'handle_request'):
return lollmsElfServer.personality.processor.handle_request(data)
else:
return {}

View File

@ -0,0 +1,59 @@
"""
project: lollms
file: lollms_uploads_infos.py
author: ParisNeo
description:
This module contains a set of FastAPI routes that provide information about the Lord of Large Language and Multimodal Systems (LoLLMs) Web UI
application. These routes are specific to uploaded files. They include functionality to remove all uploaded files from the server.
"""
from fastapi import APIRouter, Request
from pydantic import BaseModel
import pkg_resources
from lollms.server.elf_server import LOLLMSElfServer
from lollms.binding import BindingBuilder, InstallOption
from ascii_colors import ASCIIColors
from lollms.utilities import load_config, trace_exception, gc
from pathlib import Path
from typing import List
import shutil
router = APIRouter()
lollmsElfServer = LOLLMSElfServer.get_instance()
@router.get("/clear_uploads")
def clear_uploads():
"""
Clears all uploads from the specified path.
Parameters:
None
Returns:
status (bool): Whether the operation was successful or not.
error (Optional[str]): An optional error message if the operation failed.
"""
ASCIIColors.info("")
ASCIIColors.info("")
ASCIIColors.info("")
ASCIIColors.info(" ╔══════════════════════════════════════════════════╗")
ASCIIColors.info(" ║ Removing all uploads ║")
ASCIIColors.info(" ╚══════════════════════════════════════════════════╝")
ASCIIColors.info("")
ASCIIColors.info("")
ASCIIColors.info("")
try:
folder_path = lollmsElfServer.lollms_paths.personal_uploads_path
# Iterate over all files and directories in the folder
for entry in folder_path.iterdir():
if entry.is_file():
# Remove file
entry.unlink()
elif entry.is_dir():
# Remove directory (recursively)
shutil.rmtree(entry)
print(f"All files and directories inside '{folder_path}' have been removed successfully.")
return {"status": True}
except OSError as e:
ASCIIColors.error(f"Couldn't clear the upload folder.\nMaybe some files are opened somewhere else.\Try doing it manually")
return {"status": False, 'error': "Couldn't clear the upload folder.\nMaybe some files are opened somewhere else.\Try doing it manually"}

View File

@ -45,9 +45,24 @@ if __name__ == "__main__":
LOLLMSElfServer.build_instance(config=config, lollms_paths=lollms_paths, socketio=sio)
from lollms.server.endpoints.lollms_infos import router as lollms_infos_router
from lollms.server.endpoints.lollms_hardware_infos import router as lollms_hardware_infos_router
from lollms.server.endpoints.lollms_binding_infos import router as lollms_binding_infos_router
from lollms.server.endpoints.lollms_models_infos import router as lollms_models_infos_router
from lollms.server.endpoints.lollms_personalities_infos import router as lollms_personalities_infos_router
from lollms.server.endpoints.lollms_extensions_infos import router as lollms_extensions_infos_router
from lollms.server.endpoints.lollms_generator import router as lollms_generator_router
app.include_router(lollms_infos_router)
app.include_router(lollms_hardware_infos_router)
app.include_router(lollms_binding_infos_router)
app.include_router(lollms_models_infos_router)
app.include_router(lollms_personalities_infos_router)
app.include_router(lollms_extensions_infos_router)
app.include_router(lollms_generator_router)
uvicorn.run(app, host=config.host, port=config.port)

View File

@ -24,6 +24,7 @@ import requests
from io import BytesIO
import base64
import importlib
import yaml
def convert_language_name(language_name):
@ -45,6 +46,19 @@ def convert_language_name(language_name):
# Return the corresponding language code if found, or None otherwise
return language_codes.get(language_name,"en")
def load_config(file_path):
with open(file_path, 'r', encoding='utf-8') as stream:
config = yaml.safe_load(stream)
return config
def save_config(config, filepath):
with open(filepath, "w") as f:
yaml.dump(config, f)
def load_image(image_file):
s_image_file = str(image_file)
if s_image_file.startswith('http://') or s_image_file.startswith('https://'):