enhancred backend

This commit is contained in:
Saifeddine ALOUI 2024-01-09 01:15:35 +01:00
parent d0368bdb2d
commit 4b016c16e9
13 changed files with 435 additions and 37 deletions

View File

@ -20,6 +20,7 @@ from pathlib import Path
from typing import List
import os
# ----------------------- Defining router and main class ------------------------------
router = APIRouter()
lollmsElfServer = LOLLMSElfServer.get_instance()

View File

@ -18,6 +18,7 @@ from pathlib import Path
from typing import List
import json
# ----------------------------------- Personal files -----------------------------------------
class ReloadBindingParams(BaseModel):
binding_name: str
@ -25,6 +26,7 @@ class BindingInstallParams(BaseModel):
name: str
# ----------------------- Defining router and main class ------------------------------
router = APIRouter()
lollmsElfServer = LOLLMSElfServer.get_instance()
@ -74,11 +76,52 @@ def list_bindings():
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
@router.post("/open_code_in_vs_code")
async def open_code_in_vs_code(request: Request):
"""
Opens code in vs code.
:param request: The HTTP request object.
:return: A JSON response with the status of the operation.
"""
try:
data = (await request.json())
discussion_id = data.get("discussion_id","unknown_discussion")
message_id = data.get("message_id","")
code = data["code"]
discussion_id = data.get("discussion_id","unknown_discussion")
message_id = data.get("message_id","unknown_message")
language = data.get("language","python")
ASCIIColors.info("Opening folder:")
# Create a temporary file.
root_folder = lollmsElfServer.lollms_paths.personal_outputs_path/"discussions"/f"d_{discussion_id}"/f"{message_id}.py"
root_folder.mkdir(parents=True,exist_ok=True)
tmp_file = root_folder/f"ai_code_{message_id}.py"
with open(tmp_file,"w") as f:
f.write(code)
os.system('code ' + str(root_folder))
return {"output": "OK", "execution_time": 0}
except Exception as ex:
trace_exception(ex)
lollmsElfServer.error(ex)
return {"status":False,"error":str(ex)}
@router.post("/reload_binding")
async def reload_binding(request: Request):
"""
Opens code in vs code.
:param request: The HTTP request object.
:return: A JSON response with the status of the operation.
"""
try:
data = (await request.json())
print(f"Roloading binding selected : {data['binding_name']}")
lollmsElfServer.config["binding_name"]=data['binding_name']
if lollmsElfServer.binding:
lollmsElfServer.binding.destroy_model()
lollmsElfServer.binding = None
@ -226,29 +269,44 @@ def get_active_binding_settings():
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}
@router.post("/set_active_binding_settings")
async def set_active_binding_settings(request: Request):
"""
Opens code in vs code.
:param request: The HTTP request object.
:return: A JSON response with the status of the operation.
"""
try:
data = (await request.json())
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}
else:
return {'status':False}
except Exception as ex:
trace_exception(ex)
lollmsElfServer.error(ex)
return {"status":False,"error":str(ex)}

View File

@ -24,6 +24,8 @@ class SettingsInfos(BaseModel):
setting_name:str
setting_value:str
# ----------------------- Defining router and main class ------------------------------
router = APIRouter()
lollmsElfServer = LOLLMSElfServer.get_instance()

View File

@ -28,7 +28,8 @@ class ExtensionMountingInfos(BaseModel):
folder:str
language:str
# --------------------- Route -------------------------------
# ----------------------- Defining router and main class ------------------------------
router = APIRouter()
lollmsElfServer = LOLLMSElfServer.get_instance()

View File

@ -77,18 +77,20 @@ class V1InstructGenerateRequest(BaseModel):
temperature: float
max_tokens: float
# ----------------------- Defining router and main class ------------------------------
router = APIRouter()
elf_server = LOLLMSElfServer.get_instance()
# ----------------------------------- Generation status -----------------------------------------
@router.get("/get_generation_status")
def get_generation_status():
return {"status":elf_server.busy}
# ----------------------------------- Generation -----------------------------------------
@router.post("/generate")
def lollms_generate(request_data: GenerateRequest):
"""

View File

@ -18,6 +18,7 @@ from typing import List
import psutil
import subprocess
# ----------------------- Defining router and main class ------------------------------
router = APIRouter()
lollmsElfServer = LOLLMSElfServer.get_instance()

View File

@ -16,7 +16,7 @@ from pathlib import Path
from typing import List
import psutil
# ----------------------- Defining router and main class ------------------------------
router = APIRouter()
lollmsElfServer = LOLLMSElfServer.get_instance()

View File

@ -22,6 +22,7 @@ class ModelReferenceParams(BaseModel):
path: str
# ----------------------- Defining router and main class ------------------------------
router = APIRouter()
lollmsElfServer = LOLLMSElfServer.get_instance()

View File

@ -32,8 +32,7 @@ class PersonalityMountingInfos(BaseModel):
class PersonalitySelectionInfos(BaseModel):
id:int
# --------------------- Route -------------------------------
# ----------------------- Defining router and main class ------------------------------
router = APIRouter()
lollmsElfServer = LOLLMSElfServer.get_instance()

View File

@ -17,6 +17,7 @@ from pathlib import Path
from typing import List
import shutil
# ----------------------- Defining router and main class ------------------------------
router = APIRouter()
lollmsElfServer = LOLLMSElfServer.get_instance()

View File

@ -22,14 +22,13 @@ from typing import List
import socketio
import os
router = APIRouter()
lollmsElfServer = LOLLMSElfServer.get_instance()
# ----------------------------------- events -----------------------------------------
def add_events(sio:socketio):
@sio.on('cancel_generation')
def cancel_generation(sid, environ):
def cancel_generation(sid):
client_id = sid
lollmsElfServer.cancel_gen = True
#kill thread
@ -40,7 +39,7 @@ def add_events(sio:socketio):
@sio.on('cancel_text_generation')
def cancel_text_generation(sid, environ):
def cancel_text_generation(sid):
client_id = sid
lollmsElfServer.connections[client_id]["requested_stop"]=True
print(f"Client {client_id} requested canceling generation")
@ -51,7 +50,7 @@ def add_events(sio:socketio):
# A copy of the original lollms-server generation code needed for playground
@sio.on('generate_text')
def handle_generate_text(sid, environ, data):
def handle_generate_text(sid, data):
client_id = sid
lollmsElfServer.cancel_gen = False
ASCIIColors.info(f"Text generation requested by client: {client_id}")

View File

@ -0,0 +1,311 @@
"""
project: lollms
file: lollms_binding_files_server.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 serving files
"""
from fastapi import APIRouter, Request
from fastapi import HTTPException
from pydantic import BaseModel
import pkg_resources
from lollms.server.elf_server import LOLLMSElfServer
from fastapi.responses import FileResponse
from lollms.binding import BindingBuilder, InstallOption
from ascii_colors import ASCIIColors
from lollms.personality import MSG_TYPE, AIPersonality
from lollms.utilities import load_config, trace_exception, gc, terminate_thread, run_async
from pathlib import Path
from typing import List
import socketio
from datetime import datetime
from functools import partial
import shutil
import threading
import os
lollmsElfServer = LOLLMSElfServer.get_instance()
# ----------------------------------- events -----------------------------------------
def add_events(sio:socketio):
@sio.on('install_model')
def install_model(sid, data):
room_id = sid
def install_model_():
print("Install model triggered")
model_path = data["path"].replace("\\","/")
if data["type"].lower() in model_path.lower():
model_type:str=data["type"]
else:
mtt = None
for mt in lollmsElfServer.binding.models_dir_names:
if mt.lower() in model_path.lower():
mtt = mt
break
if mtt:
model_type = mtt
else:
model_type:str=lollmsElfServer.binding.models_dir_names[0]
progress = 0
installation_dir = lollmsElfServer.binding.searchModelParentFolder(model_path.split('/')[-1], model_type)
if model_type=="gptq" or model_type=="awq" or model_type=="transformers":
parts = model_path.split("/")
if len(parts)==2:
filename = parts[1]
else:
filename = parts[4]
installation_path = installation_dir / filename
elif model_type=="gpt4all":
filename = data["variant_name"]
model_path = "http://gpt4all.io/models/gguf/"+filename
installation_path = installation_dir / filename
else:
filename = Path(model_path).name
installation_path = installation_dir / filename
print("Model install requested")
print(f"Model path : {model_path}")
model_name = filename
binding_folder = lollmsElfServer.config["binding_name"]
model_url = model_path
signature = f"{model_name}_{binding_folder}_{model_url}"
try:
lollmsElfServer.download_infos[signature]={
"start_time":datetime.now(),
"total_size":lollmsElfServer.binding.get_file_size(model_path),
"downloaded_size":0,
"progress":0,
"speed":0,
"cancel":False
}
if installation_path.exists():
print("Error: Model already exists. please remove it first")
run_async( partial(sio.emit,'install_progress',{
'status': False,
'error': f'model already exists. Please remove it first.\nThe model can be found here:{installation_path}',
'model_name' : model_name,
'binding_folder' : binding_folder,
'model_url' : model_url,
'start_time': lollmsElfServer.download_infos[signature]['start_time'].strftime("%Y-%m-%d %H:%M:%S"),
'total_size': lollmsElfServer.download_infos[signature]['total_size'],
'downloaded_size': lollmsElfServer.download_infos[signature]['downloaded_size'],
'progress': lollmsElfServer.download_infos[signature]['progress'],
'speed': lollmsElfServer.download_infos[signature]['speed'],
}, room=room_id
)
)
return
run_async( partial(sio.emit,'install_progress',{
'status': True,
'progress': progress,
'model_name' : model_name,
'binding_folder' : binding_folder,
'model_url' : model_url,
'start_time': lollmsElfServer.download_infos[signature]['start_time'].strftime("%Y-%m-%d %H:%M:%S"),
'total_size': lollmsElfServer.download_infos[signature]['total_size'],
'downloaded_size': lollmsElfServer.download_infos[signature]['downloaded_size'],
'progress': lollmsElfServer.download_infos[signature]['progress'],
'speed': lollmsElfServer.download_infos[signature]['speed'],
}, room=room_id)
)
def callback(downloaded_size, total_size):
progress = (downloaded_size / total_size) * 100
now = datetime.now()
dt = (now - lollmsElfServer.download_infos[signature]['start_time']).total_seconds()
speed = downloaded_size/dt
lollmsElfServer.download_infos[signature]['downloaded_size'] = downloaded_size
lollmsElfServer.download_infos[signature]['speed'] = speed
if progress - lollmsElfServer.download_infos[signature]['progress']>2:
lollmsElfServer.download_infos[signature]['progress'] = progress
run_async( partial(sio.emit,'install_progress',{
'status': True,
'model_name' : model_name,
'binding_folder' : binding_folder,
'model_url' : model_url,
'start_time': lollmsElfServer.download_infos[signature]['start_time'].strftime("%Y-%m-%d %H:%M:%S"),
'total_size': lollmsElfServer.download_infos[signature]['total_size'],
'downloaded_size': lollmsElfServer.download_infos[signature]['downloaded_size'],
'progress': lollmsElfServer.download_infos[signature]['progress'],
'speed': lollmsElfServer.download_infos[signature]['speed'],
}, room=room_id)
)
if lollmsElfServer.download_infos[signature]["cancel"]:
raise Exception("canceled")
if hasattr(lollmsElfServer.binding, "download_model"):
try:
lollmsElfServer.binding.download_model(model_path, installation_path, callback)
except Exception as ex:
ASCIIColors.warning(str(ex))
trace_exception(ex)
run_async( partial(sio.emit,'install_progress',{
'status': False,
'error': 'canceled',
'model_name' : model_name,
'binding_folder' : binding_folder,
'model_url' : model_url,
'start_time': lollmsElfServer.download_infos[signature]['start_time'].strftime("%Y-%m-%d %H:%M:%S"),
'total_size': lollmsElfServer.download_infos[signature]['total_size'],
'downloaded_size': lollmsElfServer.download_infos[signature]['downloaded_size'],
'progress': lollmsElfServer.download_infos[signature]['progress'],
'speed': lollmsElfServer.download_infos[signature]['speed'],
}, room=room_id
)
)
del lollmsElfServer.download_infos[signature]
try:
if installation_path.is_dir():
shutil.rmtree(installation_path)
else:
installation_path.unlink()
except Exception as ex:
trace_exception(ex)
ASCIIColors.error(f"Couldn't delete file. Please try to remove it manually.\n{installation_path}")
return
else:
try:
lollmsElfServer.download_file(model_path, installation_path, callback)
except Exception as ex:
ASCIIColors.warning(str(ex))
trace_exception(ex)
run_async( partial(sio.emit,'install_progress',{
'status': False,
'error': 'canceled',
'model_name' : model_name,
'binding_folder' : binding_folder,
'model_url' : model_url,
'start_time': lollmsElfServer.download_infos[signature]['start_time'].strftime("%Y-%m-%d %H:%M:%S"),
'total_size': lollmsElfServer.download_infos[signature]['total_size'],
'downloaded_size': lollmsElfServer.download_infos[signature]['downloaded_size'],
'progress': lollmsElfServer.download_infos[signature]['progress'],
'speed': lollmsElfServer.download_infos[signature]['speed'],
}, room=room_id
)
)
del lollmsElfServer.download_infos[signature]
installation_path.unlink()
return
run_async( partial(sio.emit,'install_progress',{
'status': True,
'error': '',
'model_name' : model_name,
'binding_folder' : binding_folder,
'model_url' : model_url,
'start_time': lollmsElfServer.download_infos[signature]['start_time'].strftime("%Y-%m-%d %H:%M:%S"),
'total_size': lollmsElfServer.download_infos[signature]['total_size'],
'downloaded_size': lollmsElfServer.download_infos[signature]['downloaded_size'],
'progress': 100,
'speed': lollmsElfServer.download_infos[signature]['speed'],
}, room=room_id)
)
del lollmsElfServer.download_infos[signature]
except Exception as ex:
trace_exception(ex)
run_async( partial(sio.emit,'install_progress',{
'status': False,
'error': str(ex),
'model_name' : model_name,
'binding_folder' : binding_folder,
'model_url' : model_url,
'start_time': '',
'total_size': 0,
'downloaded_size': 0,
'progress': 0,
'speed': 0,
}, room=room_id
)
)
tpe = threading.Thread(target=install_model_, args=())
tpe.start()
@sio.on('uninstall_model')
def uninstall_model(sid, data):
model_path = data['path']
model_type:str=data.get("type","ggml")
installation_dir = lollmsElfServer.binding.searchModelParentFolder(model_path)
binding_folder = lollmsElfServer.config["binding_name"]
if model_type=="gptq" or model_type=="awq":
filename = model_path.split("/")[4]
installation_path = installation_dir / filename
else:
filename = Path(model_path).name
installation_path = installation_dir / filename
model_name = filename
if not installation_path.exists():
run_async( partial(sio.emit,'uninstall_progress',{
'status': False,
'error': 'The model does not exist',
'model_name' : model_name,
'binding_folder' : binding_folder
}, room=sid)
)
try:
if not installation_path.exists():
# Try to find a version
model_path = installation_path.name.lower().replace("-ggml","").replace("-gguf","")
candidates = [m for m in installation_dir.iterdir() if model_path in m.name]
if len(candidates)>0:
model_path = candidates[0]
installation_path = model_path
if installation_path.is_dir():
shutil.rmtree(installation_path)
else:
installation_path.unlink()
run_async( partial(sio.emit,'uninstall_progress',{
'status': True,
'error': '',
'model_name' : model_name,
'binding_folder' : binding_folder
}, room=sid)
)
except Exception as ex:
trace_exception(ex)
ASCIIColors.error(f"Couldn't delete {installation_path}, please delete it manually and restart the app")
run_async( partial(sio.emit,'uninstall_progress',{
'status': False,
'error': f"Couldn't delete {installation_path}, please delete it manually and restart the app",
'model_name' : model_name,
'binding_folder' : binding_folder
}, room=sid)
)
@sio.on('cancel_install')
def cancel_install(sid,data):
try:
model_name = data["model_name"]
binding_folder = data["binding_folder"]
model_url = data["model_url"]
signature = f"{model_name}_{binding_folder}_{model_url}"
lollmsElfServer.download_infos[signature]["cancel"]=True
run_async( partial(sio.emit,'canceled', {
'status': True
},
room=sid
)
)
except Exception as ex:
trace_exception(ex)
sio.emit('canceled', {
'status': False,
'error':str(ex)
},
room=sid
)

View File

@ -92,6 +92,28 @@ def convert_language_name(language_name):
return language_codes.get(language_name,"en")
# Function to encode the image
def encode_image(image_path, max_image_width=-1):
image = Image.open(image_path)
width, height = image.size
if max_image_width != -1 and width > max_image_width:
ratio = max_image_width / width
new_width = max_image_width
new_height = int(height * ratio)
image = image.resize((new_width, new_height))
# Check and convert image format if needed
if image.format not in ['PNG', 'JPEG', 'GIF', 'WEBP']:
image = image.convert('JPEG')
# Save the image to a BytesIO object
byte_arr = io.BytesIO()
image.save(byte_arr, format=image.format)
byte_arr = byte_arr.getvalue()
return base64.b64encode(byte_arr).decode('utf-8')
def load_config(file_path):
with open(file_path, 'r', encoding='utf-8') as stream:
config = yaml.safe_load(stream)