mirror of
https://github.com/ParisNeo/lollms.git
synced 2025-02-22 02:06:37 +00:00
Moved to the new configuration system
This commit is contained in:
parent
2ed99531eb
commit
f7348b0084
@ -6,18 +6,13 @@ __copyright__ = "Copyright 2023, "
|
||||
__license__ = "Apache 2.0"
|
||||
|
||||
|
||||
from lollms.binding import LLMBinding, LOLLMSConfig
|
||||
from lollms.binding import LLMBinding, LOLLMSConfig
|
||||
from lollms.personality import AIPersonality, MSG_TYPE
|
||||
from lollms.helpers import ASCIIColors
|
||||
from lollms.paths import LollmsPaths
|
||||
from lollms.helpers import ASCIIColors
|
||||
from lollms.paths import LollmsPaths
|
||||
#from lollms.binding import LLMBinding
|
||||
import importlib
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def reset_all_installs():
|
||||
@ -33,20 +28,9 @@ def reset_all_installs():
|
||||
|
||||
|
||||
|
||||
|
||||
class BindingBuilder:
|
||||
def build_binding(self, bindings_path: Path, cfg: LOLLMSConfig, force_reinstall=False)->LLMBinding:
|
||||
binding_path = Path(bindings_path) / cfg["binding_name"]
|
||||
# first find out if there is a requirements.txt file
|
||||
install_file_name = "install.py"
|
||||
install_script_path = binding_path / install_file_name
|
||||
if install_script_path.exists():
|
||||
module_name = install_file_name[:-3] # Remove the ".py" extension
|
||||
module_spec = importlib.util.spec_from_file_location(module_name, str(install_script_path))
|
||||
module = importlib.util.module_from_spec(module_spec)
|
||||
module_spec.loader.exec_module(module)
|
||||
if hasattr(module, "Install"):
|
||||
module.Install(cfg, force_reinstall=force_reinstall)
|
||||
# define the full absolute path to the module
|
||||
absolute_path = binding_path.resolve()
|
||||
# infer the module name from the file path
|
||||
|
@ -9,17 +9,15 @@
|
||||
######
|
||||
from pathlib import Path
|
||||
from typing import Callable
|
||||
from lollms.helpers import BaseConfig, ASCIIColors
|
||||
from lollms.paths import LollmsPaths
|
||||
from lollms.helpers import ASCIIColors
|
||||
|
||||
import inspect
|
||||
import yaml
|
||||
import sys
|
||||
from tqdm import tqdm
|
||||
import urllib.request
|
||||
import importlib
|
||||
import shutil
|
||||
import subprocess
|
||||
from lollms.config import TypedConfig
|
||||
from lollms.main_config import LOLLMSConfig
|
||||
|
||||
|
||||
__author__ = "parisneo"
|
||||
@ -30,174 +28,6 @@ __license__ = "Apache 2.0"
|
||||
|
||||
import yaml
|
||||
|
||||
DEFAULT_CONFIG = {
|
||||
# =================== Lord Of Large Language Models Configuration file ===========================
|
||||
"version": 5,
|
||||
"binding_name": "llama_cpp_official",
|
||||
"model_name": "Wizard-Vicuna-7B-Uncensored.ggmlv3.q4_0.bin",
|
||||
|
||||
# Host information
|
||||
"host": "localhost",
|
||||
"port": 9600,
|
||||
|
||||
# Genreration parameters
|
||||
"seed": -1,
|
||||
"n_predict": 1024,
|
||||
"ctx_size": 2048,
|
||||
"temperature": 0.9,
|
||||
"top_k": 50,
|
||||
"top_p": 0.95,
|
||||
"repeat_last_n": 40,
|
||||
"repeat_penalty": 1.2,
|
||||
|
||||
"n_threads": 8,
|
||||
|
||||
#Personality parameters
|
||||
"personalities": ["english/generic/lollms"],
|
||||
"active_personality_id": 0,
|
||||
"override_personality_model_parameters": False, #if true the personality parameters are overriden by those of the configuration (may affect personality behaviour)
|
||||
|
||||
"user_name": "user",
|
||||
|
||||
}
|
||||
|
||||
|
||||
class LOLLMSConfig(BaseConfig):
|
||||
def __init__(self, file_path=None, lollms_paths:LollmsPaths = None):
|
||||
super().__init__(["file_path", "config", "lollms_paths"])
|
||||
|
||||
if file_path:
|
||||
self.file_path = Path(file_path)
|
||||
else:
|
||||
self.file_path = None
|
||||
|
||||
if file_path is not None:
|
||||
self.load_config(file_path)
|
||||
else:
|
||||
self.config = DEFAULT_CONFIG.copy()
|
||||
|
||||
if lollms_paths is None:
|
||||
self.lollms_paths = LollmsPaths()
|
||||
else:
|
||||
self.lollms_paths = lollms_paths
|
||||
|
||||
|
||||
@staticmethod
|
||||
def autoload(lollms_paths, config_path:str=None):
|
||||
# Configuration loading part
|
||||
original_cfg_path = lollms_paths.default_cfg_path
|
||||
if config_path is None:
|
||||
local = lollms_paths.personal_configuration_path / "local_config.yaml"
|
||||
if not local.exists():
|
||||
shutil.copy(original_cfg_path, local)
|
||||
cfg_path = local
|
||||
else:
|
||||
cfg_path = config_path
|
||||
|
||||
if cfg_path.exists():
|
||||
original_config = LOLLMSConfig(original_cfg_path, lollms_paths)
|
||||
config = LOLLMSConfig(cfg_path, lollms_paths)
|
||||
if "version" not in config or int(config["version"])<int(original_config["version"]):
|
||||
#Upgrade old configuration files to new format
|
||||
ASCIIColors.error("Configuration file is very old.\nReplacing with default configuration")
|
||||
_, added, removed = config.sync_cfg(original_config)
|
||||
print(f"Added entries : {added}, removed entries:{removed}")
|
||||
config.save_config(cfg_path)
|
||||
else:
|
||||
config = LOLLMSConfig(lollms_paths=lollms_paths)
|
||||
|
||||
return config
|
||||
|
||||
def sync_cfg(self, default_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.config.items():
|
||||
if key not in self:
|
||||
self[key] = value
|
||||
added_entries.append(key)
|
||||
|
||||
# Remove fields from config that don't exist in default_config
|
||||
for key in list(self.config.keys()):
|
||||
if key not in default_config.config:
|
||||
del self.config[key]
|
||||
removed_entries.append(key)
|
||||
|
||||
self["version"]=default_config["version"]
|
||||
|
||||
return self, added_entries, removed_entries
|
||||
|
||||
def get_model_path_infos(self):
|
||||
return f"personal_models_path: {self.lollms_paths.personal_models_path}\nBinding name:{self.binding_name}\nModel name:{self.model_name}"
|
||||
|
||||
def get_personality_path_infos(self):
|
||||
return f"personalities_zoo_path: {self.lollms_paths.personalities_zoo_path}\nPersonalities:{self.personalities}\nActive personality id:{self.active_personality_id}"
|
||||
|
||||
def get_model_full_path(self):
|
||||
try:
|
||||
return self.lollms_paths.personal_models_path/self.binding_name/self.model_name
|
||||
except:
|
||||
return None
|
||||
def check_model_existance(self):
|
||||
try:
|
||||
model_path = self.lollms_paths.personal_models_path/self.binding_name/self.model_name
|
||||
return model_path.exists()
|
||||
except Exception as ex:
|
||||
print(f"Exception in checking model existance: {ex}")
|
||||
return False
|
||||
|
||||
def download_model(self, url, binding, callback = None):
|
||||
folder_path = self.lollms_paths.personal_models_path/self.binding_name
|
||||
model_name = url.split("/")[-1]
|
||||
model_full_path = (folder_path / model_name)
|
||||
if binding is not None and hasattr(binding,'download_model'):
|
||||
binding.download_model(url, model_full_path, callback)
|
||||
else:
|
||||
|
||||
# Check if file already exists in folder
|
||||
if model_full_path.exists():
|
||||
print("File already exists in folder")
|
||||
else:
|
||||
# Create folder if it doesn't exist
|
||||
folder_path.mkdir(parents=True, exist_ok=True)
|
||||
progress_bar = tqdm(total=None, unit="B", unit_scale=True, desc=f"Downloading {url.split('/')[-1]}")
|
||||
# Define callback function for urlretrieve
|
||||
def report_progress(block_num, block_size, total_size):
|
||||
progress_bar.total=total_size
|
||||
progress_bar.update(block_size)
|
||||
# Download file from URL to folder
|
||||
try:
|
||||
urllib.request.urlretrieve(url, folder_path / url.split("/")[-1], reporthook=report_progress if callback is None else callback)
|
||||
print("File downloaded successfully!")
|
||||
except Exception as e:
|
||||
print("Error downloading file:", e)
|
||||
sys.exit(1)
|
||||
|
||||
def reference_model(self, path):
|
||||
path = str(path).replace("\\","/")
|
||||
folder_path = self.lollms_paths.personal_models_path/self.binding_name
|
||||
model_name = path.split("/")[-1]+".reference"
|
||||
model_full_path = (folder_path / model_name)
|
||||
|
||||
# Check if file already exists in folder
|
||||
if model_full_path.exists():
|
||||
print("File already exists in folder")
|
||||
else:
|
||||
# Create folder if it doesn't exist
|
||||
folder_path.mkdir(parents=True, exist_ok=True)
|
||||
with open(model_full_path,"w") as f:
|
||||
f.write(path)
|
||||
print("Reference created, please make sure you don't delete the file or you will have broken link")
|
||||
|
||||
|
||||
class BindingInstaller:
|
||||
@ -219,11 +49,62 @@ class LLMBinding:
|
||||
|
||||
file_extension='*.bin'
|
||||
binding_path = Path(__file__).parent
|
||||
def __init__(self, config:LOLLMSConfig, inline:bool) -> None:
|
||||
self.config = config
|
||||
self.inline = inline
|
||||
def __init__(
|
||||
self,
|
||||
binding_dir:Path,
|
||||
lollms_paths:LollmsPaths,
|
||||
config:LOLLMSConfig,
|
||||
binding_config:TypedConfig,
|
||||
force_install:bool=False
|
||||
) -> None:
|
||||
self.binding_dir = binding_dir
|
||||
self.binding_folder_name = binding_dir.stem
|
||||
self.lollms_paths = lollms_paths
|
||||
self.config = config
|
||||
self.binding_config = binding_config
|
||||
|
||||
def load_config_file(self, path):
|
||||
self.configuration_file_path = lollms_paths.personal_configuration_path/f"binding_{self.binding_folder_name}.yaml"
|
||||
self.binding_config.config.file_path = self.configuration_file_path
|
||||
if not self.configuration_file_path.exists() or force_install:
|
||||
self.install()
|
||||
self.binding_config.config.save_config()
|
||||
else:
|
||||
self.load_binding_config()
|
||||
|
||||
self.models_folder = config.lollms_paths.personal_models_path / self.binding_folder_name
|
||||
self.models_folder.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
|
||||
def install(self):
|
||||
"""
|
||||
Installation procedure (to be implemented)
|
||||
"""
|
||||
ASCIIColors.blue("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*")
|
||||
ASCIIColors.red(f"Installing {self.binding_folder_name}")
|
||||
ASCIIColors.blue("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*")
|
||||
|
||||
|
||||
def get_model_path(self):
|
||||
"""
|
||||
Retrieves the path of the model based on the configuration.
|
||||
|
||||
If the model name ends with ".reference", it reads the model path from a file.
|
||||
Otherwise, it constructs the model path based on the configuration.
|
||||
|
||||
Returns:
|
||||
str: The path of the model.
|
||||
"""
|
||||
if self.config.model_name.endswith(".reference"):
|
||||
with open(str(self.lollms_paths.personal_models_path / f"{self.binding_folder_name}/{self.config.model_name}"), 'r') as f:
|
||||
model_path = Path(f.read())
|
||||
else:
|
||||
model_path = Path(self.lollms_paths.personal_models_path / f"{self.binding_folder_name}/{self.config.model_name}")
|
||||
return model_path
|
||||
|
||||
|
||||
|
||||
def load_binding_config(self):
|
||||
"""
|
||||
Load the content of local_config.yaml file.
|
||||
|
||||
@ -235,9 +116,24 @@ class LLMBinding:
|
||||
Returns:
|
||||
dict: A dictionary containing the loaded data from the local_config.yaml file.
|
||||
"""
|
||||
with open(path, 'r') as file:
|
||||
data = yaml.safe_load(file)
|
||||
return data
|
||||
self.binding_config.config.load_config()
|
||||
self.binding_config.sync()
|
||||
|
||||
def save_config_file(self, path):
|
||||
"""
|
||||
Load the content of local_config.yaml file.
|
||||
|
||||
The function reads the content of the local_config.yaml file and returns it as a Python dictionary.
|
||||
|
||||
Args:
|
||||
None
|
||||
|
||||
Returns:
|
||||
dict: A dictionary containing the loaded data from the local_config.yaml file.
|
||||
"""
|
||||
self.binding_config.config.save_config(self.configuration_file_path)
|
||||
|
||||
|
||||
|
||||
|
||||
def generate(self,
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit fb0b73a12f02ba033c6860f7bb8f1cc7c4fba083
|
||||
Subproject commit 854400ff86978e212dbb768d5ff575a4521f2272
|
466
lollms/config.py
Normal file
466
lollms/config.py
Normal file
@ -0,0 +1,466 @@
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
class BaseConfig:
|
||||
"""
|
||||
A base class for managing configuration data.
|
||||
|
||||
The `BaseConfig` class provides basic functionality to load, save, and access configuration data.
|
||||
|
||||
Attributes:
|
||||
exceptional_keys (list): A list of exceptional keys that can be accessed directly as attributes.
|
||||
config (dict): The configuration data stored as a dictionary.
|
||||
|
||||
Methods:
|
||||
to_dict():
|
||||
Returns the configuration data as a dictionary.
|
||||
__getitem__(key):
|
||||
Retrieves the configuration value associated with the specified key.
|
||||
__getattr__(key):
|
||||
Retrieves the configuration value associated with the specified key as an attribute.
|
||||
__setattr__(key, value):
|
||||
Sets the value of the configuration key.
|
||||
__setitem__(key, value):
|
||||
Sets the value of the configuration key.
|
||||
__contains__(item):
|
||||
Checks if the configuration contains the specified key.
|
||||
load_config(file_path):
|
||||
Loads the configuration from a YAML file.
|
||||
save_config(file_path):
|
||||
Saves the configuration to a YAML file.
|
||||
"""
|
||||
|
||||
def __init__(self, exceptional_keys: list = [], config: dict = None, file_path:Path|str=None):
|
||||
"""
|
||||
Initializes a new instance of the `BaseConfig` class.
|
||||
|
||||
Args:
|
||||
exceptional_keys (list, optional): A list of exceptional keys that can be accessed directly as attributes.
|
||||
Defaults to an empty list.
|
||||
config (dict, optional): The configuration data stored as a dictionary. Defaults to None.
|
||||
"""
|
||||
self.exceptional_keys = exceptional_keys
|
||||
self.config = config
|
||||
self.file_path = file_path
|
||||
|
||||
def to_dict(self):
|
||||
"""
|
||||
Returns the configuration data as a dictionary.
|
||||
|
||||
Returns:
|
||||
dict: The configuration data as a dictionary.
|
||||
"""
|
||||
return self.config
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""
|
||||
Retrieves the configuration value associated with the specified key.
|
||||
|
||||
Args:
|
||||
key (Any): The key to retrieve the configuration value.
|
||||
|
||||
Returns:
|
||||
Any: The configuration value associated with the key.
|
||||
|
||||
Raises:
|
||||
ValueError: If no configuration is loaded.
|
||||
KeyError: If the specified key is not found in the configuration.
|
||||
"""
|
||||
if self.config is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
return self.config[key]
|
||||
|
||||
def __getattr__(self, key):
|
||||
"""
|
||||
Retrieves the configuration value associated with the specified key as an attribute.
|
||||
|
||||
Args:
|
||||
key (str): The key to retrieve the configuration value.
|
||||
|
||||
Returns:
|
||||
Any: The configuration value associated with the key.
|
||||
|
||||
Raises:
|
||||
ValueError: If no configuration is loaded.
|
||||
AttributeError: If the specified key is not found in the configuration.
|
||||
"""
|
||||
if key == "exceptional_keys":
|
||||
return super().__getattribute__(key)
|
||||
if key in self.exceptional_keys + ["config","file_path"] or key.startswith("__"):
|
||||
return super().__getattribute__(key)
|
||||
else:
|
||||
if self.config is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
return self.config[key]
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
"""
|
||||
Sets the value of the configuration key.
|
||||
|
||||
Args:
|
||||
key (str): The key of the configuration.
|
||||
value (Any): The new value for the configuration key.
|
||||
|
||||
Raises:
|
||||
ValueError: If no configuration is loaded.
|
||||
"""
|
||||
if key == "exceptional_keys":
|
||||
return super().__setattr__(key, value)
|
||||
if key in self.exceptional_keys + ["config","file_path"] or key.startswith("__"):
|
||||
super().__setattr__(key, value)
|
||||
else:
|
||||
if self.config is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
self.config[key] = value
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
"""
|
||||
Sets the value of the configuration key.
|
||||
|
||||
Args:
|
||||
key (str): The key of the configuration.
|
||||
value (Any): The new value for the configuration key.
|
||||
|
||||
Raises:
|
||||
ValueError: If no configuration is loaded.
|
||||
"""
|
||||
if self.config is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
self.config[key] = value
|
||||
|
||||
def __contains__(self, item):
|
||||
"""
|
||||
Checks if the configuration contains the specified key.
|
||||
|
||||
Args:
|
||||
item (str): The key to check.
|
||||
|
||||
Returns:
|
||||
bool: True if the key is present in the configuration, False otherwise.
|
||||
|
||||
Raises:
|
||||
ValueError: If no configuration is loaded.
|
||||
"""
|
||||
if self.config is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
return item in self.config
|
||||
|
||||
def load_config(self, file_path: Path | str = None):
|
||||
"""
|
||||
Loads the configuration from a YAML file.
|
||||
|
||||
Args:
|
||||
file_path (str or Path, optional): The path to the YAML file. If not provided, uses the previously set file path.
|
||||
|
||||
Raises:
|
||||
ValueError: If no configuration file path is specified.
|
||||
FileNotFoundError: If the specified file path does not exist.
|
||||
yaml.YAMLError: If there is an error parsing the YAML file.
|
||||
"""
|
||||
if file_path is None:
|
||||
if self.file_path is None:
|
||||
raise ValueError("No configuration file path specified.")
|
||||
file_path = self.file_path
|
||||
|
||||
file_path = Path(file_path)
|
||||
if not file_path.exists():
|
||||
raise FileNotFoundError(f"Configuration file not found: {file_path}")
|
||||
|
||||
with open(file_path, 'r', encoding='utf-8') as stream:
|
||||
self.config = yaml.safe_load(stream)
|
||||
|
||||
def save_config(self, file_path=None):
|
||||
"""
|
||||
Saves the configuration to a YAML file.
|
||||
|
||||
Args:
|
||||
file_path (str or Path, optional): The path to the YAML file. If not provided, uses the previously set file path.
|
||||
|
||||
Raises:
|
||||
ValueError: If no configuration is loaded.
|
||||
ValueError: If no configuration file path is specified.
|
||||
PermissionError: If the user does not have permission to write to the specified file path.
|
||||
yaml.YAMLError: If there is an error serializing the configuration to YAML.
|
||||
"""
|
||||
if file_path is None:
|
||||
if self.file_path is None:
|
||||
raise ValueError("No configuration file path specified.")
|
||||
file_path = self.file_path
|
||||
|
||||
if self.config is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
|
||||
file_path = Path(file_path)
|
||||
with open(file_path, "w") as f:
|
||||
yaml.dump(self.config, f)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ConfigTemplate:
|
||||
"""
|
||||
A class representing a configuration template.
|
||||
|
||||
The `ConfigTemplate` class provides functionality to define and manage configuration entries in the form of a template.
|
||||
|
||||
Attributes:
|
||||
template (list): A list of dictionaries representing configuration entries.
|
||||
|
||||
Methods:
|
||||
add_entry(entry_name, entry_value, entry_type, entry_min=None, entry_max=None):
|
||||
Adds a new entry to the configuration template.
|
||||
__getitem__(key):
|
||||
Retrieves the configuration entry with the specified key.
|
||||
__getattr__(key):
|
||||
Retrieves the configuration entry with the specified key as an attribute.
|
||||
__setattr__(key, value):
|
||||
Sets the value of the configuration entry with the specified key.
|
||||
__setitem__(key, value):
|
||||
Sets the value of the configuration entry with the specified key.
|
||||
__contains__(item):
|
||||
Checks if a configuration entry with the specified name exists in the template.
|
||||
"""
|
||||
|
||||
def __init__(self, template: list = None) -> None:
|
||||
"""
|
||||
Initializes a new instance of the `ConfigTemplate` class.
|
||||
|
||||
Args:
|
||||
template (list, optional): A list of dictionaries representing configuration entries. Defaults to an empty list.
|
||||
|
||||
Raises:
|
||||
ValueError: If the `template` parameter is not a list of dictionaries or if any entry is missing required fields.
|
||||
"""
|
||||
if template is None:
|
||||
template = []
|
||||
elif not isinstance(template, list):
|
||||
raise ValueError("Template must be a list of dictionaries.")
|
||||
else:
|
||||
for entry in template:
|
||||
if not isinstance(entry, dict):
|
||||
raise ValueError("Each entry in the template must be a dictionary.")
|
||||
required_fields = ["name", "value", "type"]
|
||||
missing_fields = [field for field in required_fields if field not in entry]
|
||||
if missing_fields:
|
||||
raise ValueError(f"Missing fields {', '.join(missing_fields)} in template entry.")
|
||||
self.template = template
|
||||
|
||||
def add_entry(self, entry_name, entry_value, entry_type, entry_min=None, entry_max=None, entry_help=""):
|
||||
"""
|
||||
Adds a new entry to the configuration template.
|
||||
|
||||
Args:
|
||||
entry_name (str): The name of the configuration entry.
|
||||
entry_value (Any): The value of the configuration entry.
|
||||
entry_type (str): The type of the configuration entry.
|
||||
entry_min (Any, optional): The minimum allowed value for the configuration entry. Defaults to None.
|
||||
entry_max (Any, optional): The maximum allowed value for the configuration entry. Defaults to None.
|
||||
entry_help (str, optional): the help string to describe the entry
|
||||
"""
|
||||
self.template.append({
|
||||
"name": entry_name,
|
||||
"value": entry_value,
|
||||
"type": entry_type,
|
||||
"min": entry_min,
|
||||
"max": entry_max,
|
||||
"help": entry_help
|
||||
})
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""
|
||||
Retrieves the configuration entry with the specified key.
|
||||
|
||||
Args:
|
||||
key (str): The name of the configuration entry.
|
||||
|
||||
Returns:
|
||||
dict: The configuration entry with the specified key, or None if not found.
|
||||
|
||||
Raises:
|
||||
ValueError: If no configuration is loaded.
|
||||
"""
|
||||
if self.template is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
for entry in self.template:
|
||||
if entry["name"] == key:
|
||||
return entry
|
||||
return None
|
||||
|
||||
def __getattr__(self, key):
|
||||
"""
|
||||
Retrieves the configuration entry with the specified key as an attribute.
|
||||
|
||||
Args:
|
||||
key (str): The name of the configuration entry.
|
||||
|
||||
Returns:
|
||||
dict: The configuration entry with the specified key, or None if not found.
|
||||
|
||||
Raises:
|
||||
ValueError: If no configuration is loaded.
|
||||
"""
|
||||
if key == "exceptional_keys":
|
||||
return super().__getattribute__(key)
|
||||
if key in ["template"] or key.startswith("__"):
|
||||
return super().__getattribute__(key)
|
||||
else:
|
||||
if self.template is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
for entry in self.template:
|
||||
if entry["name"] == key:
|
||||
return entry
|
||||
return None
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
"""
|
||||
Sets the value of the configuration entry with the specified key.
|
||||
|
||||
Args:
|
||||
key (str): The name of the configuration entry.
|
||||
value (Any): The new value for the configuration entry.
|
||||
|
||||
Raises:
|
||||
ValueError: If no configuration is loaded or if the specified key is not found.
|
||||
"""
|
||||
if key == "exceptional_keys":
|
||||
return super().__setattr__(key, value)
|
||||
if key in ["template"] or key.startswith("__"):
|
||||
super().__setattr__(key, value)
|
||||
else:
|
||||
if self.template is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
for entry in self.template:
|
||||
if entry["name"] == key:
|
||||
entry["value"] = value
|
||||
return
|
||||
raise ValueError(f"Configuration entry '{key}' not found.")
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
"""
|
||||
Sets the value of the configuration entry with the specified key.
|
||||
|
||||
Args:
|
||||
key (str): The name of the configuration entry.
|
||||
value (Any): The new value for the configuration entry.
|
||||
|
||||
Raises:
|
||||
ValueError: If no configuration is loaded or if the specified key is not found.
|
||||
"""
|
||||
if self.template is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
for entry in self.template:
|
||||
if entry["name"] == key:
|
||||
entry["value"] = value
|
||||
return
|
||||
raise ValueError(f"Configuration entry '{key}' not found.")
|
||||
|
||||
def __contains__(self, item):
|
||||
"""
|
||||
Checks if a configuration entry with the specified name exists in the template.
|
||||
|
||||
Args:
|
||||
item (str): The name of the configuration entry.
|
||||
|
||||
Returns:
|
||||
bool: True if the configuration entry exists, False otherwise.
|
||||
|
||||
Raises:
|
||||
ValueError: If no configuration is loaded.
|
||||
"""
|
||||
if self.template is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
for entry in self.template:
|
||||
if entry["name"] == item:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class TypedConfig:
|
||||
"""
|
||||
This type of configuration contains a template of descriptions for the fields of the configuration.
|
||||
Field types: int, float, str.
|
||||
"""
|
||||
|
||||
def __init__(self, config_template: ConfigTemplate, config: BaseConfig):
|
||||
"""
|
||||
Initializes a new instance of the `TypedConfig` class.
|
||||
|
||||
Args:
|
||||
config_template (ConfigTemplate): The template of descriptions for the fields of the configuration.
|
||||
config (BaseConfig): The base configuration object containing the configuration values.
|
||||
"""
|
||||
self.config = config
|
||||
self.config_template = config_template
|
||||
|
||||
# Fill the template values from the config values
|
||||
self.sync()
|
||||
|
||||
def sync(self):
|
||||
"""
|
||||
Fills the template values from the config values.
|
||||
"""
|
||||
if self.config_template is None:
|
||||
raise ValueError("No configuration template loaded.")
|
||||
if self.config is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
|
||||
for entry in self.config_template.template:
|
||||
entry_name = entry["name"]
|
||||
if entry_name in self.config:
|
||||
entry_value = self.config[entry_name]
|
||||
entry_type = entry["type"]
|
||||
|
||||
# Validate and convert the entry value based on its type
|
||||
if entry_type == "int":
|
||||
entry_value = int(entry_value)
|
||||
elif entry_type == "float":
|
||||
entry_value = float(entry_value)
|
||||
elif entry_type == "str":
|
||||
entry_value = str(entry_value)
|
||||
elif entry_type == "bool":
|
||||
entry_value = bool(entry_value)
|
||||
elif entry_type == "list":
|
||||
entry_value = list(entry_value)
|
||||
else:
|
||||
raise ValueError(f"Invalid field type '{entry_type}' for entry '{entry_name}'.")
|
||||
|
||||
# Skip checking min and max if the entry type is not numeric
|
||||
if entry_type == "int" or entry_type == "float":
|
||||
entry_min = entry.get("min")
|
||||
entry_max = entry.get("max")
|
||||
|
||||
# Check if the value is within the allowed range (if specified)
|
||||
if entry_min is not None and entry_max is not None:
|
||||
if entry_value < entry_min:
|
||||
entry_value = entry_min
|
||||
elif entry_value > entry_max:
|
||||
entry_value = entry_max
|
||||
elif entry_min is not None:
|
||||
if entry_value < entry_min:
|
||||
entry_value = entry_min
|
||||
elif entry_max is not None:
|
||||
if entry_value > entry_max:
|
||||
entry_value = entry_max
|
||||
|
||||
# Update the template entry with the converted value
|
||||
entry["value"] = entry_value
|
||||
else:
|
||||
self.config[entry_name] = entry["value"]
|
||||
|
||||
def set_config(self, config: BaseConfig):
|
||||
"""
|
||||
Sets the configuration and updates the values of the template.
|
||||
|
||||
Args:
|
||||
config (BaseConfig): The base configuration object containing the configuration values.
|
||||
"""
|
||||
self.config = config
|
||||
self.sync()
|
||||
|
||||
|
||||
def to_dict(self, use_template=False):
|
||||
if not use_template:
|
||||
return self.config
|
||||
else:
|
||||
return self.config_template
|
@ -1,9 +1,8 @@
|
||||
from lollms.personality import AIPersonality, MSG_TYPE
|
||||
from lollms.binding import LOLLMSConfig, LLMBinding
|
||||
from lollms.personality import MSG_TYPE
|
||||
from lollms.main_config import LOLLMSConfig
|
||||
from lollms.helpers import ASCIIColors
|
||||
from lollms.paths import LollmsPaths
|
||||
from lollms import reset_all_installs
|
||||
import shutil
|
||||
import yaml
|
||||
from pathlib import Path
|
||||
import sys
|
||||
@ -14,9 +13,9 @@ from lollms import BindingBuilder, ModelBuilder, PersonalityBuilder
|
||||
|
||||
|
||||
class MainMenu:
|
||||
def __init__(self, conversation):
|
||||
def __init__(self, lollms_app):
|
||||
self.binding_infs = []
|
||||
self.conversation = conversation
|
||||
self.lollms_app = lollms_app
|
||||
|
||||
def show_logo(self):
|
||||
print(f"{ASCIIColors.color_bright_yellow}")
|
||||
@ -53,9 +52,9 @@ class MainMenu:
|
||||
print(f" {ASCIIColors.color_red}├{ASCIIColors.color_reset} send_file: uploads a file to the AI")
|
||||
print(f" {ASCIIColors.color_red}└{ASCIIColors.color_reset} exit: exists the console")
|
||||
|
||||
if self.conversation.personality.help !="":
|
||||
if self.lollms_app.personality.help !="":
|
||||
print(f"Personality help:")
|
||||
print(f"{self.conversation.personality.help}")
|
||||
print(f"{self.lollms_app.personality.help}")
|
||||
|
||||
|
||||
|
||||
@ -69,28 +68,31 @@ class MainMenu:
|
||||
def select_binding(self):
|
||||
bindings_list = []
|
||||
print()
|
||||
print(f"{ASCIIColors.color_green}Current binding: {ASCIIColors.color_reset}{self.conversation.config['binding_name']}")
|
||||
for p in self.conversation.lollms_paths.bindings_zoo_path.iterdir():
|
||||
print(f"{ASCIIColors.color_green}Current binding: {ASCIIColors.color_reset}{self.lollms_app.config['binding_name']}")
|
||||
for p in self.lollms_app.lollms_paths.bindings_zoo_path.iterdir():
|
||||
if p.is_dir():
|
||||
with open(p/"binding_card.yaml", "r") as f:
|
||||
card = yaml.safe_load(f)
|
||||
with open(p/"models.yaml", "r") as f:
|
||||
models = yaml.safe_load(f)
|
||||
entry=f"{card['name']} (by {card['author']})"
|
||||
is_installed = (self.lollms_app.lollms_paths.personal_configuration_path/f"binding_{p.name}.yaml").exists()
|
||||
entry=f"{ASCIIColors.color_green if is_installed else ''}{card['name']} (by {card['author']})"
|
||||
bindings_list.append(entry)
|
||||
entry={
|
||||
"name":p.name,
|
||||
"card":card,
|
||||
"models":models
|
||||
"models":models,
|
||||
"installed": is_installed
|
||||
}
|
||||
self.binding_infs.append(entry)
|
||||
bindings_list += ["Back"]
|
||||
choice = self.show_menu(bindings_list)
|
||||
if 1 <= choice <= len(bindings_list)-1:
|
||||
print(f"You selected binding: {ASCIIColors.color_green}{self.binding_infs[choice - 1]['name']}{ASCIIColors.color_reset}")
|
||||
self.conversation.config['binding_name']=self.binding_infs[choice - 1]['name']
|
||||
self.conversation.load_binding()
|
||||
self.conversation.config.save_config()
|
||||
self.lollms_app.config['binding_name']=self.binding_infs[choice - 1]['name']
|
||||
self.lollms_app.load_binding()
|
||||
self.lollms_app.config['model_name']=None
|
||||
self.lollms_app.config.save_config()
|
||||
elif choice <= len(bindings_list):
|
||||
return
|
||||
else:
|
||||
@ -98,16 +100,19 @@ class MainMenu:
|
||||
|
||||
def select_model(self):
|
||||
print()
|
||||
print(f"{ASCIIColors.color_green}Current model: {ASCIIColors.color_reset}{self.conversation.config['model_name']}")
|
||||
models_dir:Path = (self.conversation.lollms_paths.personal_models_path/self.conversation.config['binding_name'])
|
||||
print(f"{ASCIIColors.color_green}Current model: {ASCIIColors.color_reset}{self.lollms_app.config['model_name']}")
|
||||
models_dir:Path = (self.lollms_app.lollms_paths.personal_models_path/self.lollms_app.config['binding_name'])
|
||||
models_dir.mkdir(parents=True, exist_ok=True)
|
||||
models_list = [m.name for m in models_dir.iterdir() if m.name.lower() not in [".ds_dtore","thumb.db"]] + ["Install model", "Change binding", "Back"]
|
||||
if hasattr(self.lollms_app,"binding") and hasattr(self.lollms_app.binding,"list_models"):
|
||||
models_list = [f'{v["filename"]} (by {v["owner"]})' for v in self.lollms_app.binding.list_models(self.lollms_app.config)] + ["Install model", "Change binding", "Back"]
|
||||
else:
|
||||
models_list = [m.name for m in models_dir.iterdir() if m.name.lower() not in [".ds_dtore","thumb.db"]] + ["Install model", "Change binding", "Back"]
|
||||
choice = self.show_menu(models_list)
|
||||
if 1 <= choice <= len(models_list)-3:
|
||||
print(f"You selected model: {ASCIIColors.color_green}{models_list[choice - 1]}{ASCIIColors.color_reset}")
|
||||
self.conversation.config['model_name']=models_list[choice - 1]
|
||||
self.conversation.config.save_config()
|
||||
self.conversation.load_model()
|
||||
self.lollms_app.config['model_name']=models_list[choice - 1]
|
||||
self.lollms_app.config.save_config()
|
||||
self.lollms_app.load_model()
|
||||
elif choice <= len(models_list)-2:
|
||||
self.install_model()
|
||||
elif choice <= len(models_list)-1:
|
||||
@ -129,12 +134,12 @@ class MainMenu:
|
||||
|
||||
# Usage example
|
||||
with tqdm(total=100, unit="%", desc="Download Progress", ncols=80) as tqdm_bar:
|
||||
self.conversation.config.download_model(url,self.conversation.binding, progress_callback)
|
||||
self.lollms_app.config.download_model(url,self.lollms_app.binding, progress_callback)
|
||||
self.select_model()
|
||||
elif choice <= len(models_list)-1:
|
||||
path = Path(input("Give a path to the model to be used on your PC:"))
|
||||
if path.exists():
|
||||
self.conversation.config.reference_model(path)
|
||||
self.lollms_app.config.reference_model(path)
|
||||
self.select_model()
|
||||
elif choice <= len(models_list):
|
||||
return
|
||||
@ -143,31 +148,31 @@ class MainMenu:
|
||||
|
||||
def select_personality(self):
|
||||
print()
|
||||
print(f"{ASCIIColors.color_green}Current personality: {ASCIIColors.color_reset}{self.conversation.config['personalities'][self.conversation.config['active_personality_id']]}")
|
||||
personality_languages = [p.stem for p in self.conversation.lollms_paths.personalities_zoo_path.iterdir() if p.is_dir()] + ["Back"]
|
||||
print(f"{ASCIIColors.color_green}Current personality: {ASCIIColors.color_reset}{self.lollms_app.config['personalities'][self.lollms_app.config['active_personality_id']]}")
|
||||
personality_languages = [p.stem for p in self.lollms_app.lollms_paths.personalities_zoo_path.iterdir() if p.is_dir()] + ["Back"]
|
||||
print("Select language")
|
||||
choice = self.show_menu(personality_languages)
|
||||
if 1 <= choice <= len(personality_languages)-1:
|
||||
language = personality_languages[choice - 1]
|
||||
print(f"You selected language: {ASCIIColors.color_green}{language}{ASCIIColors.color_reset}")
|
||||
personality_categories = [p.stem for p in (self.conversation.lollms_paths.personalities_zoo_path/language).iterdir() if p.is_dir()]+["Custom","Back"]
|
||||
personality_categories = [p.stem for p in (self.lollms_app.lollms_paths.personalities_zoo_path/language).iterdir() if p.is_dir()]+["Custom","Back"]
|
||||
print("Select category")
|
||||
choice = self.show_menu(personality_categories)
|
||||
if 1 <= choice <= len(personality_categories)-1:
|
||||
category = personality_categories[choice - 1]
|
||||
print(f"You selected category: {ASCIIColors.color_green}{category}{ASCIIColors.color_reset}")
|
||||
if category=="Custom":
|
||||
personality_names = [p.stem for p in self.conversation.lollms_paths.personal_personalities_path.iterdir() if p.is_dir()]+["Back"]
|
||||
personality_names = [p.stem for p in self.lollms_app.lollms_paths.personal_personalities_path.iterdir() if p.is_dir()]+["Back"]
|
||||
else:
|
||||
personality_names = [p.stem for p in (self.conversation.lollms_paths.personalities_zoo_path/language/category).iterdir() if p.is_dir()]+["Back"]
|
||||
personality_names = [p.stem for p in (self.lollms_app.lollms_paths.personalities_zoo_path/language/category).iterdir() if p.is_dir()]+["Back"]
|
||||
print("Select personality")
|
||||
choice = self.show_menu(personality_names)
|
||||
if 1 <= choice <= len(personality_names)-1:
|
||||
name = personality_names[choice - 1]
|
||||
print(f"You selected personality: {ASCIIColors.color_green}{name}{ASCIIColors.color_reset}")
|
||||
self.conversation.config["personalities"]=[f"{language}/{category}/{name}"]
|
||||
self.conversation.load_personality()
|
||||
self.conversation.config.save_config()
|
||||
self.lollms_app.config["personalities"]=[f"{language}/{category}/{name}"]
|
||||
self.lollms_app.load_personality()
|
||||
self.lollms_app.config.save_config()
|
||||
print("Personality saved successfully!")
|
||||
elif 1 <= choice <= len(personality_names):
|
||||
return
|
||||
@ -183,22 +188,22 @@ class MainMenu:
|
||||
print("Invalid choice!")
|
||||
|
||||
def reinstall_binding(self):
|
||||
conversation = self.conversation
|
||||
lollms_app = self.lollms_app
|
||||
try:
|
||||
conversation.binding = BindingBuilder().build_binding(conversation.lollms_paths.bindings_zoo_path, conversation.config, force_reinstall=True)
|
||||
lollms_app.binding = BindingBuilder().build_binding(lollms_app.lollms_paths.bindings_zoo_path, lollms_app.config, force_reinstall=True)
|
||||
except Exception as ex:
|
||||
print(ex)
|
||||
print(f"Couldn't find binding. Please verify your configuration file at {conversation.config.file_path} or use the next menu to select a valid binding")
|
||||
print(f"Couldn't find binding. Please verify your configuration file at {lollms_app.config.file_path} or use the next menu to select a valid binding")
|
||||
self.select_binding()
|
||||
|
||||
def reinstall_personality(self):
|
||||
conversation = self.conversation
|
||||
lollms_app = self.lollms_app
|
||||
try:
|
||||
conversation.personality = PersonalityBuilder(conversation.lollms_paths, conversation.config, conversation.model).build_personality(force_reinstall=True)
|
||||
lollms_app.personality = PersonalityBuilder(lollms_app.lollms_paths, lollms_app.config, lollms_app.model).build_personality(force_reinstall=True)
|
||||
except Exception as ex:
|
||||
ASCIIColors.error(f"Couldn't load personality. Please verify your configuration file at {conversation.configuration_path} or use the next menu to select a valid personality")
|
||||
ASCIIColors.error(f"Couldn't load personality. Please verify your configuration file at {lollms_app.configuration_path} or use the next menu to select a valid personality")
|
||||
ASCIIColors.error(f"Binding returned this exception : {ex}")
|
||||
ASCIIColors.error(f"{conversation.config.get_personality_path_infos()}")
|
||||
ASCIIColors.error(f"{lollms_app.config.get_personality_path_infos()}")
|
||||
print("Please select a valid model or install a new one from a url")
|
||||
self.select_model()
|
||||
|
||||
@ -595,8 +600,8 @@ def main():
|
||||
|
||||
configuration_path = args.configuration_path
|
||||
|
||||
conversation = Conversation(configuration_path=configuration_path, show_commands_list=True)
|
||||
conversation.start_conversation()
|
||||
lollms_app = Conversation(configuration_path=configuration_path, show_commands_list=True)
|
||||
lollms_app.start_conversation()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -1,6 +1,3 @@
|
||||
from pathlib import Path
|
||||
import yaml
|
||||
|
||||
|
||||
|
||||
class ASCIIColors:
|
||||
@ -74,61 +71,3 @@ class ASCIIColors:
|
||||
|
||||
|
||||
|
||||
class BaseConfig():
|
||||
def __init__(self, exceptional_keys=[], config = None):
|
||||
self.exceptional_keys = exceptional_keys
|
||||
self.config = config
|
||||
|
||||
|
||||
def to_dict(self):
|
||||
return self.config
|
||||
|
||||
def __getitem__(self, key):
|
||||
if self.config is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
return self.config[key]
|
||||
|
||||
def __getattr__(self, key):
|
||||
if key == "exceptional_keys":
|
||||
return super().__getattribute__(key)
|
||||
if key in self.exceptional_keys+ ["config"] or key.startswith("__"):
|
||||
return super().__getattribute__(key)
|
||||
else:
|
||||
if self.config is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
return self.config[key]
|
||||
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
if key == "exceptional_keys":
|
||||
return super().__setattr__(key, value)
|
||||
if key in self.exceptional_keys+ ["config"] or key.startswith("__"):
|
||||
super().__setattr__(key, value)
|
||||
else:
|
||||
if self.config is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
self.config[key] = value
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if self.config is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
self.config[key] = value
|
||||
|
||||
def __contains__(self, item):
|
||||
if self.config is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
return item in self.config
|
||||
|
||||
def load_config(self, file_path:Path=None):
|
||||
if file_path is None:
|
||||
file_path = self.file_path
|
||||
with open(file_path, 'r', encoding='utf-8') as stream:
|
||||
self.config = yaml.safe_load(stream)
|
||||
|
||||
def save_config(self, file_path:Path=None):
|
||||
if file_path is None:
|
||||
file_path = self.file_path
|
||||
if self.config is None:
|
||||
raise ValueError("No configuration loaded.")
|
||||
with open(file_path, "w") as f:
|
||||
yaml.dump(self.config, f)
|
||||
|
184
lollms/main_config.py
Normal file
184
lollms/main_config.py
Normal file
@ -0,0 +1,184 @@
|
||||
__author__ = "ParisNeo"
|
||||
__github__ = "https://github.com/ParisNeo/lollms"
|
||||
__copyright__ = "Copyright 2023, "
|
||||
__license__ = "Apache 2.0"
|
||||
|
||||
from lollms.helpers import ASCIIColors
|
||||
from lollms.paths import LollmsPaths
|
||||
from lollms.config import BaseConfig
|
||||
#from lollms.binding import LLMBinding
|
||||
import shutil
|
||||
import urllib
|
||||
from tqdm import tqdm
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
import sys
|
||||
DEFAULT_CONFIG = {
|
||||
# =================== Lord Of Large Language Models Configuration file ===========================
|
||||
"version": 5,
|
||||
"binding_name": "llama_cpp_official",
|
||||
"model_name": "Wizard-Vicuna-7B-Uncensored.ggmlv3.q4_0.bin",
|
||||
|
||||
# Host information
|
||||
"host": "localhost",
|
||||
"port": 9600,
|
||||
|
||||
# Genreration parameters
|
||||
"seed": -1,
|
||||
"n_predict": 1024,
|
||||
"ctx_size": 2048,
|
||||
"temperature": 0.9,
|
||||
"top_k": 50,
|
||||
"top_p": 0.95,
|
||||
"repeat_last_n": 40,
|
||||
"repeat_penalty": 1.2,
|
||||
|
||||
"n_threads": 8,
|
||||
|
||||
#Personality parameters
|
||||
"personalities": ["english/generic/lollms"],
|
||||
"active_personality_id": 0,
|
||||
"override_personality_model_parameters": False, #if true the personality parameters are overriden by those of the configuration (may affect personality behaviour)
|
||||
|
||||
"user_name": "user",
|
||||
|
||||
}
|
||||
|
||||
class LOLLMSConfig(BaseConfig):
|
||||
def __init__(self, file_path=None, lollms_paths:LollmsPaths = None):
|
||||
super().__init__(["file_path", "config", "lollms_paths"])
|
||||
|
||||
if file_path:
|
||||
self.file_path = Path(file_path)
|
||||
else:
|
||||
self.file_path = None
|
||||
|
||||
if file_path is not None:
|
||||
self.load_config(file_path)
|
||||
else:
|
||||
self.config = DEFAULT_CONFIG.copy()
|
||||
|
||||
if lollms_paths is None:
|
||||
self.lollms_paths = LollmsPaths()
|
||||
else:
|
||||
self.lollms_paths = lollms_paths
|
||||
|
||||
|
||||
@staticmethod
|
||||
def autoload(lollms_paths, config_path:str=None):
|
||||
# Configuration loading part
|
||||
original_cfg_path = lollms_paths.default_cfg_path
|
||||
if config_path is None:
|
||||
local = lollms_paths.personal_configuration_path / "local_config.yaml"
|
||||
if not local.exists():
|
||||
shutil.copy(original_cfg_path, local)
|
||||
cfg_path = local
|
||||
else:
|
||||
cfg_path = config_path
|
||||
|
||||
if cfg_path.exists():
|
||||
original_config = LOLLMSConfig(original_cfg_path, lollms_paths)
|
||||
config = LOLLMSConfig(cfg_path, lollms_paths)
|
||||
if "version" not in config or int(config["version"])<int(original_config["version"]):
|
||||
#Upgrade old configuration files to new format
|
||||
ASCIIColors.error("Configuration file is very old.\nReplacing with default configuration")
|
||||
_, added, removed = config.sync_cfg(original_config)
|
||||
print(f"Added entries : {added}, removed entries:{removed}")
|
||||
config.save_config(cfg_path)
|
||||
else:
|
||||
config = LOLLMSConfig(lollms_paths=lollms_paths)
|
||||
|
||||
return config
|
||||
|
||||
def sync_cfg(self, default_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.config.items():
|
||||
if key not in self:
|
||||
self[key] = value
|
||||
added_entries.append(key)
|
||||
|
||||
# Remove fields from config that don't exist in default_config
|
||||
for key in list(self.config.keys()):
|
||||
if key not in default_config.config:
|
||||
del self.config[key]
|
||||
removed_entries.append(key)
|
||||
|
||||
self["version"]=default_config["version"]
|
||||
|
||||
return self, added_entries, removed_entries
|
||||
|
||||
def get_model_path_infos(self):
|
||||
return f"personal_models_path: {self.lollms_paths.personal_models_path}\nBinding name:{self.binding_name}\nModel name:{self.model_name}"
|
||||
|
||||
def get_personality_path_infos(self):
|
||||
return f"personalities_zoo_path: {self.lollms_paths.personalities_zoo_path}\nPersonalities:{self.personalities}\nActive personality id:{self.active_personality_id}"
|
||||
|
||||
def get_model_full_path(self):
|
||||
try:
|
||||
return self.lollms_paths.personal_models_path/self.binding_name/self.model_name
|
||||
except:
|
||||
return None
|
||||
def check_model_existance(self):
|
||||
try:
|
||||
model_path = self.lollms_paths.personal_models_path/self.binding_name/self.model_name
|
||||
return model_path.exists()
|
||||
except Exception as ex:
|
||||
print(f"Exception in checking model existance: {ex}")
|
||||
return False
|
||||
|
||||
def download_model(self, url, binding, callback = None):
|
||||
folder_path = self.lollms_paths.personal_models_path/self.binding_name
|
||||
model_name = url.split("/")[-1]
|
||||
model_full_path = (folder_path / model_name)
|
||||
if binding is not None and hasattr(binding,'download_model'):
|
||||
binding.download_model(url, model_full_path, callback)
|
||||
else:
|
||||
|
||||
# Check if file already exists in folder
|
||||
if model_full_path.exists():
|
||||
print("File already exists in folder")
|
||||
else:
|
||||
# Create folder if it doesn't exist
|
||||
folder_path.mkdir(parents=True, exist_ok=True)
|
||||
progress_bar = tqdm(total=None, unit="B", unit_scale=True, desc=f"Downloading {url.split('/')[-1]}")
|
||||
# Define callback function for urlretrieve
|
||||
def report_progress(block_num, block_size, total_size):
|
||||
progress_bar.total=total_size
|
||||
progress_bar.update(block_size)
|
||||
# Download file from URL to folder
|
||||
try:
|
||||
urllib.request.urlretrieve(url, folder_path / url.split("/")[-1], reporthook=report_progress if callback is None else callback)
|
||||
print("File downloaded successfully!")
|
||||
except Exception as e:
|
||||
print("Error downloading file:", e)
|
||||
sys.exit(1)
|
||||
|
||||
def reference_model(self, path):
|
||||
path = str(path).replace("\\","/")
|
||||
folder_path = self.lollms_paths.personal_models_path/self.binding_name
|
||||
model_name = path.split("/")[-1]+".reference"
|
||||
model_full_path = (folder_path / model_name)
|
||||
|
||||
# Check if file already exists in folder
|
||||
if model_full_path.exists():
|
||||
print("File already exists in folder")
|
||||
else:
|
||||
# Create folder if it doesn't exist
|
||||
folder_path.mkdir(parents=True, exist_ok=True)
|
||||
with open(model_full_path,"w") as f:
|
||||
f.write(path)
|
||||
print("Reference created, please make sure you don't delete the file or you will have broken link")
|
||||
|
@ -1,7 +1,7 @@
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
from lollms.helpers import ASCIIColors
|
||||
from lollms.helpers import BaseConfig
|
||||
from lollms.config import BaseConfig
|
||||
|
||||
lollms_path = Path(__file__).parent
|
||||
lollms_default_cfg_path = lollms_path / "configs/config.yaml"
|
||||
@ -81,15 +81,14 @@ class LollmsPaths:
|
||||
# if the app is not forcing a specific path, then try to find out if the default installed library has specified a default path
|
||||
global_paths_cfg = lollms_path/"global_paths_cfg.yaml"
|
||||
if global_paths_cfg.exists():
|
||||
cfg = BaseConfig()
|
||||
cfg.load_config(global_paths_cfg)
|
||||
try:
|
||||
cfg = BaseConfig()
|
||||
cfg.load_config(global_paths_cfg)
|
||||
lollms_path = cfg.lollms_path
|
||||
lollms_personal_path = cfg.lollms_personal_path
|
||||
return LollmsPaths(lollms_path, lollms_personal_path, custom_default_cfg_path=custom_default_cfg_path)
|
||||
except Exception as ex:
|
||||
print(f"{ASCIIColors.color_red}Global paths configuration file found but seems to be corrupted{ASCIIColors.color_reset}")
|
||||
print("Couldn't find your personal data path!")
|
||||
cfg.lollms_path = Path(__file__).parent
|
||||
cfg.lollms_personal_path = input("Please specify the folder where your configuration files, your models and your custom personalities need to be stored:")
|
||||
cfg.save_config(global_paths_cfg)
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 02543f5b23ad31cd587dffd4b8b8f2623a7ea3a2
|
||||
Subproject commit cc16d94f2ebaee7736891cf507ca5cc0026d58d6
|
@ -1,8 +1,9 @@
|
||||
from flask import Flask, render_template, request
|
||||
from flask import Flask, request
|
||||
from flask_socketio import SocketIO, emit
|
||||
from flask_cors import CORS
|
||||
from lollms.personality import AIPersonality, MSG_TYPE
|
||||
from lollms.binding import LOLLMSConfig, LLMBinding
|
||||
from lollms.main_config import LOLLMSConfig
|
||||
from lollms.binding import LLMBinding
|
||||
from lollms.helpers import ASCIIColors
|
||||
from lollms.console import MainMenu
|
||||
from lollms.paths import LollmsPaths
|
||||
@ -14,10 +15,8 @@ import importlib
|
||||
from pathlib import Path
|
||||
import argparse
|
||||
import logging
|
||||
import shutil
|
||||
import yaml
|
||||
import copy
|
||||
from threading import Thread
|
||||
|
||||
class LoLLMsServer:
|
||||
def __init__(self):
|
||||
@ -112,7 +111,7 @@ class LoLLMsServer:
|
||||
|
||||
self.menu.show_logo()
|
||||
|
||||
self.app = Flask("LoLLMsServer_Server")
|
||||
self.app = Flask("LoLLMsServer")
|
||||
#self.app.config['SECRET_KEY'] = 'lollmssecret'
|
||||
CORS(self.app) # Enable CORS for all routes
|
||||
|
||||
@ -547,16 +546,6 @@ class LoLLMsServer:
|
||||
|
||||
def build_binding(self, bindings_path: Path, cfg: LOLLMSConfig)->LLMBinding:
|
||||
binding_path = Path(bindings_path) / cfg["binding_name"]
|
||||
# first find out if there is a requirements.txt file
|
||||
install_file_name = "install.py"
|
||||
install_script_path = binding_path / install_file_name
|
||||
if install_script_path.exists():
|
||||
module_name = install_file_name[:-3] # Remove the ".py" extension
|
||||
module_spec = importlib.util.spec_from_file_location(module_name, str(install_script_path))
|
||||
module = importlib.util.module_from_spec(module_spec)
|
||||
module_spec.loader.exec_module(module)
|
||||
if hasattr(module, "Install"):
|
||||
module.Install(self.config)
|
||||
# define the full absolute path to the module
|
||||
absolute_path = binding_path.resolve()
|
||||
# infer the module name from the file path
|
||||
|
@ -1,14 +1,10 @@
|
||||
from lollms.personality import AIPersonality, MSG_TYPE
|
||||
from lollms.binding import LOLLMSConfig, LLMBinding
|
||||
|
||||
from lollms.main_config import LOLLMSConfig
|
||||
from lollms.helpers import ASCIIColors
|
||||
from lollms.paths import LollmsPaths
|
||||
from lollms import reset_all_installs
|
||||
import shutil
|
||||
import yaml
|
||||
import importlib
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import pkg_resources
|
||||
import argparse
|
||||
from tqdm import tqdm
|
||||
from lollms import BindingBuilder, ModelBuilder, PersonalityBuilder
|
||||
|
Loading…
x
Reference in New Issue
Block a user