2024-01-01 03:18:49 +00:00
"""
File : lollms_web_ui . py
Author : ParisNeo
Description : Singleton class for the LoLLMS web UI .
This class provides a singleton instance of the LoLLMS web UI , allowing access to its functionality and data across multiple endpoints .
"""
2024-01-04 02:57:42 +00:00
from lollms . server . elf_server import LOLLMSElfServer
2024-01-01 03:18:49 +00:00
from lollms . main_config import LOLLMSConfig
2024-01-05 02:40:55 +00:00
from lollms . helpers import trace_exception
2024-01-01 03:18:49 +00:00
from lollms . paths import LollmsPaths
2024-01-05 02:40:55 +00:00
from ascii_colors import ASCIIColors
from datetime import datetime
from api . db import DiscussionsDB , Discussion
from pathlib import Path
2024-01-06 01:05:07 +00:00
import os , sys
# The current version of the webui
lollms_webui_version = " 9.0 (alpha) "
import git
2024-01-05 02:40:55 +00:00
try :
from lollms . media import WebcamImageSender , AudioRecorder
Media_on = True
except :
ASCIIColors . warning ( " Couldn ' t load media library. \n You will not be able to perform any of the media linked operations. please verify the logs and install any required installations " )
Media_on = False
2024-01-01 03:18:49 +00:00
2024-01-04 02:57:42 +00:00
class LOLLMSWebUI ( LOLLMSElfServer ) :
2024-01-05 02:40:55 +00:00
__instance = None
@staticmethod
def build_instance (
config : LOLLMSConfig ,
lollms_paths : LollmsPaths ,
load_binding = True ,
load_model = True ,
load_voice_service = True ,
load_sd_service = True ,
try_select_binding = False ,
try_select_model = False ,
callback = None ,
socketio = None
) :
if LOLLMSWebUI . __instance is None :
LOLLMSWebUI (
config ,
lollms_paths ,
load_binding = load_binding ,
load_model = load_model ,
load_sd_service = load_sd_service ,
load_voice_service = load_voice_service ,
try_select_binding = try_select_binding ,
try_select_model = try_select_model ,
callback = callback ,
socketio = socketio
)
return LOLLMSWebUI . __instance
2024-01-01 03:18:49 +00:00
def __init__ (
self ,
config : LOLLMSConfig ,
lollms_paths : LollmsPaths ,
load_binding = True ,
load_model = True ,
2024-01-04 02:57:42 +00:00
load_voice_service = True ,
load_sd_service = True ,
2024-01-01 03:18:49 +00:00
try_select_binding = False ,
try_select_model = False ,
callback = None ,
socketio = None
) - > None :
super ( ) . __init__ (
config ,
lollms_paths ,
load_binding = load_binding ,
load_model = load_model ,
2024-01-04 02:57:42 +00:00
load_sd_service = load_sd_service ,
load_voice_service = load_voice_service ,
2024-01-01 03:18:49 +00:00
try_select_binding = try_select_binding ,
try_select_model = try_select_model ,
callback = callback ,
socketio = socketio
)
2024-01-04 02:57:42 +00:00
self . app_name = " LOLLMSWebUI "
2024-01-06 01:05:07 +00:00
self . version = lollms_webui_version
2024-01-01 03:18:49 +00:00
2024-01-05 02:40:55 +00:00
self . busy = False
self . nb_received_tokens = 0
self . config_file_path = config . file_path
self . cancel_gen = False
# Keeping track of current discussion and message
self . _current_user_message_id = 0
self . _current_ai_message_id = 0
self . _message_id = 0
self . db_path = config [ " 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_databases_path / self . db_path )
# If the database is empty, populate it with tables
ASCIIColors . info ( " Checking discussions database... " , end = " " )
self . db . create_tables ( )
self . db . add_missing_columns ( )
ASCIIColors . success ( " ok " )
# prepare vectorization
if self . config . data_vectorization_activate and self . config . use_discussions_history :
try :
ASCIIColors . yellow ( " Loading long term memory " )
folder = self . lollms_paths . personal_databases_path / " vectorized_dbs "
folder . mkdir ( parents = True , exist_ok = True )
self . build_long_term_skills_memory ( )
ASCIIColors . yellow ( " Ready " )
except Exception as ex :
trace_exception ( ex )
self . long_term_memory = None
else :
self . long_term_memory = None
# This is used to keep track of messages
self . download_infos = { }
self . connections = {
0 : {
" current_discussion " : None ,
" generated_text " : " " ,
" cancel_generation " : False ,
" generation_thread " : None ,
" processing " : False ,
" schedule_for_deletion " : False ,
" continuing " : False ,
" first_chunk " : True ,
}
}
if Media_on :
try :
self . webcam = WebcamImageSender ( socketio , lollmsCom = self )
except :
self . webcam = None
try :
self . rec_output_folder = lollms_paths . personal_outputs_path / " audio_rec "
self . rec_output_folder . mkdir ( exist_ok = True , parents = True )
self . summoned = False
self . audio_cap = AudioRecorder ( socketio , self . rec_output_folder / " rt.wav " , callback = self . audio_callback , lollmsCom = self )
except :
self . audio_cap = None
self . rec_output_folder = None
else :
self . webcam = None
self . rec_output_folder = None
2024-01-06 01:05:07 +00:00
2024-01-01 03:18:49 +00:00
# Other methods and properties of the LoLLMSWebUI singleton class
2024-01-06 01:05:07 +00:00
def check_module_update_ ( self , repo_path , branch_name = " main " ) :
try :
# Open the repository
ASCIIColors . yellow ( f " Checking for updates from { repo_path } " )
repo = git . Repo ( repo_path )
# Fetch updates from the remote for the specified branch
repo . remotes . origin . fetch ( refspec = f " refs/heads/ { branch_name } :refs/remotes/origin/ { branch_name } " )
# Compare the local and remote commit IDs for the specified branch
local_commit = repo . head . commit
remote_commit = repo . remotes . origin . refs [ branch_name ] . commit
# Check if the local branch is behind the remote branch
is_behind = repo . is_ancestor ( local_commit , remote_commit ) and local_commit != remote_commit
ASCIIColors . yellow ( f " update availability: { is_behind } " )
# Return True if the local branch is behind the remote branch
return is_behind
except Exception as e :
# Handle any errors that may occur during the fetch process
# trace_exception(e)
return False
def check_update_ ( self , branch_name = " main " ) :
try :
# Open the repository
repo_path = str ( Path ( __file__ ) . parent )
if self . check_module_update_ ( repo_path , branch_name ) :
return True
repo_path = str ( Path ( __file__ ) . parent / " lollms_core " )
if self . check_module_update_ ( repo_path , branch_name ) :
return True
repo_path = str ( Path ( __file__ ) . parent / " utilities/safe_store " )
if self . check_module_update_ ( repo_path , branch_name ) :
return True
return False
except Exception as e :
# Handle any errors that may occur during the fetch process
# trace_exception(e)
return False
def run_update_script ( self , args = None ) :
update_script = Path ( __file__ ) . parent / " update_script.py "
# Convert Namespace object to a dictionary
if args :
args_dict = vars ( args )
else :
args_dict = { }
# Filter out any key-value pairs where the value is None
valid_args = { key : value for key , value in args_dict . items ( ) if value is not None }
# Save the arguments to a temporary file
temp_file = Path ( __file__ ) . parent / " temp_args.txt "
with open ( temp_file , " w " ) as file :
# Convert the valid_args dictionary to a string in the format "key1 value1 key2 value2 ..."
arg_string = " " . join ( [ f " -- { key } { value } " for key , value in valid_args . items ( ) ] )
file . write ( arg_string )
os . system ( f " python { update_script } " )
sys . exit ( 0 )