From af3aeb42f2e96540a986b675ef81fd8398bf63e4 Mon Sep 17 00:00:00 2001 From: Saifeddine ALOUI Date: Fri, 7 Jul 2023 09:59:44 +0200 Subject: [PATCH 1/4] upgraded --- lollms/app.py | 23 +++++++++++------------ lollms/binding.py | 2 +- lollms/console.py | 2 +- lollms/helpers.py | 11 +++++++++++ lollms/personality.py | 2 +- lollms/terminal.py | 2 ++ setup.py | 2 +- 7 files changed, 28 insertions(+), 16 deletions(-) diff --git a/lollms/app.py b/lollms/app.py index 166a52d..ccc8ca7 100644 --- a/lollms/app.py +++ b/lollms/app.py @@ -4,7 +4,7 @@ from lollms.paths import LollmsPaths from lollms.personality import PersonalityBuilder from lollms.binding import LLMBinding, BindingBuilder, ModelBuilder from lollms.config import InstallOption -import traceback +from lollms.helpers import trace_exception from lollms.terminal import MainMenu class LollmsApplication: @@ -29,6 +29,7 @@ class LollmsApplication: self.binding = self.load_binding() except Exception as ex: ASCIIColors.error(f"Failed to load binding.\nReturned exception: {ex}") + trace_exception(ex) if self.binding is not None: ASCIIColors.success(f"Binding {self.config.binding_name} loaded successfully.") @@ -41,6 +42,7 @@ class LollmsApplication: self.model = self.load_model() except Exception as ex: ASCIIColors.error(f"Failed to load model.\nReturned exception: {ex}") + trace_exception(ex) self.model = None else: self.model = None @@ -53,15 +55,6 @@ class LollmsApplication: self.model = None self.mount_personalities() - - def trace_exception(self, ex): - # Catch the exception and get the traceback as a list of strings - traceback_lines = traceback.format_exception(type(ex), ex, ex.__traceback__) - - # Join the traceback lines into a single string - traceback_text = ''.join(traceback_lines) - ASCIIColors.error(traceback_text) - def load_binding(self): try: binding = BindingBuilder().build_binding(self.config, self.lollms_paths) @@ -69,7 +62,12 @@ class LollmsApplication: print(ex) print(f"Couldn't find binding. Please verify your configuration file at {self.configuration_path} or use the next menu to select a valid binding") print(f"Trying to reinstall binding") - binding = BindingBuilder().build_binding(self.config, self.lollms_paths,installation_option=InstallOption.FORCE_INSTALL) + try: + binding = BindingBuilder().build_binding(self.config, self.lollms_paths,installation_option=InstallOption.FORCE_INSTALL) + except Exception as ex: + ASCIIColors.error("Couldn't reinstall model") + trace_exception(ex) + return binding def load_model(self): @@ -81,6 +79,7 @@ class LollmsApplication: except Exception as ex: ASCIIColors.error(f"Couldn't load model. Please verify your configuration file at {self.lollms_paths.personal_configuration_path} or use the next menu to select a valid model") ASCIIColors.error(f"Binding returned this exception : {ex}") + trace_exception(ex) ASCIIColors.error(f"{self.config.get_model_path_infos()}") print("Please select a valid model or install a new one from a url") model = None @@ -102,7 +101,7 @@ class LollmsApplication: except Exception as ex: ASCIIColors.error(f"Couldn't load personality. Please verify your configuration file at {self.lollms_paths.personal_configuration_path} or use the next menu to select a valid personality") ASCIIColors.error(f"Binding returned this exception : {ex}") - self.trace_exception(ex) + trace_exception(ex) ASCIIColors.error(f"{self.config.get_personality_path_infos()}") self.personality = None self.mounted_personalities.append(self.personality) diff --git a/lollms/binding.py b/lollms/binding.py index af71504..7130823 100644 --- a/lollms/binding.py +++ b/lollms/binding.py @@ -22,7 +22,7 @@ import importlib import subprocess from lollms.config import TypedConfig, InstallOption from lollms.main_config import LOLLMSConfig - +import traceback __author__ = "parisneo" __github__ = "https://github.com/ParisNeo/lollms_bindings_zoo" diff --git a/lollms/console.py b/lollms/console.py index f30de2e..d8530da 100644 --- a/lollms/console.py +++ b/lollms/console.py @@ -241,7 +241,7 @@ Participating personalities: antiprompt = self.personality.detect_antiprompt(bot_says) if antiprompt: self.bot_says = self.remove_text_from_string(bot_says,antiprompt) - print("Detected hallucination") + ASCIIColors.warning(f"Detected hallucination with antiprompt {antiprompt}") return False else: self.bot_says = bot_says diff --git a/lollms/helpers.py b/lollms/helpers.py index cd30374..d513fcd 100644 --- a/lollms/helpers.py +++ b/lollms/helpers.py @@ -1,4 +1,15 @@ +import traceback +def trace_exception(ex): + """ + Traces an exception (useful for debug) + """ + # Catch the exception and get the traceback as a list of strings + traceback_lines = traceback.format_exception(type(ex), ex, ex.__traceback__) + + # Join the traceback lines into a single string + traceback_text = ''.join(traceback_lines) + ASCIIColors.error(traceback_text) class ASCIIColors: # Reset diff --git a/lollms/personality.py b/lollms/personality.py index d9951a8..3286a1a 100644 --- a/lollms/personality.py +++ b/lollms/personality.py @@ -982,7 +982,7 @@ class APScript: antiprompt = self.personality.detect_antiprompt(bot_says) if antiprompt: self.bot_says = self.remove_text_from_string(bot_says,antiprompt) - ASCIIColors.warning("Detected hallucination") + ASCIIColors.warning(f"Detected hallucination with antiprompt: {antiprompt}") return False else: self.bot_says = bot_says diff --git a/lollms/terminal.py b/lollms/terminal.py index a1cffc2..a426c2c 100644 --- a/lollms/terminal.py +++ b/lollms/terminal.py @@ -7,6 +7,7 @@ if TYPE_CHECKING: from lollms.binding import BindingBuilder from lollms.config import InstallOption from lollms.personality import PersonalityBuilder +from lollms.helpers import trace_exception from tqdm import tqdm import pkg_resources @@ -277,6 +278,7 @@ class MainMenu: except Exception as ex: 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}") + trace_exception(ex) 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() diff --git a/setup.py b/setup.py index 2ac1bcc..2234769 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ def get_all_files(path): setuptools.setup( name="lollms", - version="2.1.28", + version="2.1.32", author="Saifeddine ALOUI", author_email="aloui.saifeddine@gmail.com", description="A python library for AI personality definition", From b126999ed2683464c2980fb1a3468658be2d475c Mon Sep 17 00:00:00 2001 From: Saifeddine ALOUI Date: Sat, 8 Jul 2023 00:22:52 +0200 Subject: [PATCH 2/4] updated --- examples/chat_forever/console.py | 6 ++++-- examples/simple_story/console.py | 10 ++++++++-- lollms/server.py | 6 +++--- setup.py | 2 +- tests/endoints_unit_tests/python/test_generation.py | 7 +++++-- 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/examples/chat_forever/console.py b/examples/chat_forever/console.py index d9a808d..573f36e 100644 --- a/examples/chat_forever/console.py +++ b/examples/chat_forever/console.py @@ -1,5 +1,5 @@ from lollms.console import Conversation - +import sys class MyConversation(Conversation): def __init__(self, cfg=None): super().__init__(cfg, show_welcome_message=False) @@ -15,7 +15,9 @@ class MyConversation(Conversation): full_discussion += self.personality.user_message_prefix+prompt+self.personality.link_text full_discussion += self.personality.ai_message_prefix def callback(text, type=None): - print(text, end="", flush=True) + print(text, end="") + sys.stdout = sys.__stdout__ + sys.stdout.flush() return True print(self.personality.name+": ",end="",flush=True) output = self.safe_generate(full_discussion, callback=callback) diff --git a/examples/simple_story/console.py b/examples/simple_story/console.py index 389f775..461fdd3 100644 --- a/examples/simple_story/console.py +++ b/examples/simple_story/console.py @@ -1,4 +1,5 @@ from lollms.console import Conversation +import sys class MyConversation(Conversation): def __init__(self, cfg=None): @@ -7,9 +8,14 @@ class MyConversation(Conversation): def start_conversation(self): prompt = "Once apon a time" def callback(text, type=None): - print(text, end="", flush=True) + print(text, end="") + sys.stdout = sys.__stdout__ + sys.stdout.flush() + return True - print(prompt, end="", flush=True) + print(prompt, end="") + sys.stdout = sys.__stdout__ + sys.stdout.flush() output = self.safe_generate(prompt, callback=callback) if __name__ == '__main__': diff --git a/lollms/server.py b/lollms/server.py index fc30300..6001774 100644 --- a/lollms/server.py +++ b/lollms/server.py @@ -462,10 +462,10 @@ class LoLLMsServer(LollmsApplication): fd = personality.model.detokenize(tk[-min(self.config.ctx_size-n_cond_tk-personality.model_n_predicts,n_tokens):]) if personality.processor is not None and personality.processor_cfg["custom_workflow"]: - print("processing...", end="", flush=True) + ASCIIColors.info("processing...") generated_text = personality.processor.run_workflow(prompt, previous_discussion_text=personality.personality_conditioning+fd, callback=callback) else: - ASCIIColors.info("generating...", end="", flush=True) + ASCIIColors.info("generating...") generated_text = personality.model.generate( personality.personality_conditioning+fd, n_predict=personality.model_n_predicts, @@ -475,7 +475,7 @@ class LoLLMsServer(LollmsApplication): generated_text = personality.processor.process_model_output(generated_text) full_discussion_blocks.append(generated_text.strip()) - ASCIIColors.success("\ndone", end="", flush=True) + ASCIIColors.success("\ndone") # Emit the generated text to the client self.socketio.emit('text_generated', {'text': generated_text}, room=client_id) diff --git a/setup.py b/setup.py index 2234769..05940d1 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ def get_all_files(path): setuptools.setup( name="lollms", - version="2.1.32", + version="2.1.33", author="Saifeddine ALOUI", author_email="aloui.saifeddine@gmail.com", description="A python library for AI personality definition", diff --git a/tests/endoints_unit_tests/python/test_generation.py b/tests/endoints_unit_tests/python/test_generation.py index ad770be..bd059f9 100644 --- a/tests/endoints_unit_tests/python/test_generation.py +++ b/tests/endoints_unit_tests/python/test_generation.py @@ -3,7 +3,7 @@ import socketio from pathlib import Path from lollms import MSG_TYPE import time - +import sys # Connect to the Socket.IO server sio = socketio.Client() @@ -35,7 +35,10 @@ def test_generate_text(host, port, text_file): @sio.event def text_chunk(data): - print(data["chunk"],end="",flush=True) + print(data["chunk"],end="") + sys.stdout = sys.__stdout__ + sys.stdout.flush() + @sio.event def text_generated(data): From 16228c496199cff8ce38e0535d1c000d97690fe9 Mon Sep 17 00:00:00 2001 From: Saifeddine ALOUI Date: Sun, 9 Jul 2023 12:50:59 +0200 Subject: [PATCH 3/4] upgraded --- requirements.txt | 3 ++- requirements_dev.txt | 3 ++- setup.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index e6d73bf..d5c4a9e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,5 @@ flask-cors simple-websocket eventlet wget -setuptools \ No newline at end of file +setuptools +requests \ No newline at end of file diff --git a/requirements_dev.txt b/requirements_dev.txt index 92511d3..423b0d1 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -6,4 +6,5 @@ flask_socketio flask-cors simple-websocket wget -setuptools \ No newline at end of file +setuptools +requests \ No newline at end of file diff --git a/setup.py b/setup.py index 05940d1..5b06b92 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ def get_all_files(path): setuptools.setup( name="lollms", - version="2.1.33", + version="2.1.34", author="Saifeddine ALOUI", author_email="aloui.saifeddine@gmail.com", description="A python library for AI personality definition", From c9091fc6407081bcf01ce4ff59dafd345081dff8 Mon Sep 17 00:00:00 2001 From: Saifeddine ALOUI Date: Tue, 11 Jul 2023 01:47:15 +0200 Subject: [PATCH 4/4] added state machine support --- lollms/personality.py | 71 +++++++++++++++++++++++++++++++++++++++++-- setup.py | 2 +- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/lollms/personality.py b/lollms/personality.py index 07b2545..801a04a 100644 --- a/lollms/personality.py +++ b/lollms/personality.py @@ -836,9 +836,73 @@ Date: {{date}} +class StateMachine: + def __init__(self, states_dict): + """ + states structure is the following + [ + { + "name": the state name, + "commands": [ # list of commands + "command": function + ], + "default": default function + } + ] + """ + self.states_dict = states_dict + self.current_state_id = 0 + + def goto_state(self, state): + """ + Transition to the state with the given name or index. + + Args: + state (str or int): The name or index of the state to transition to. + + Raises: + ValueError: If no state is found with the given name or index. + """ + if isinstance(state, str): + for i, state_dict in enumerate(self.states_dict): + if state_dict["name"] == state: + self.current_state_id = i + return + elif isinstance(state, int): + if 0 <= state < len(self.states_dict): + self.current_state_id = state + return + raise ValueError(f"No state found with name or index: {state}") -class APScript: + + def process_state(self, command): + """ + Process the given command based on the current state. + + Args: + command: The command to process. + + Raises: + ValueError: If the current state doesn't have the command and no default function is defined. + """ + current_state = self.states_dict[self.current_state_id] + commands = current_state["commands"] + + for cmd, func in commands: + if cmd == command: + func() + return + + default_func = current_state.get("default") + if default_func is not None: + default_func() + else: + raise ValueError(f"Command '{command}' not found in current state and no default function defined.") + + + +class APScript(StateMachine): """ Template class for implementing personality processor classes in the APScript framework. @@ -848,9 +912,10 @@ class APScript: def __init__( self, personality :AIPersonality, - personality_config :TypedConfig + personality_config :TypedConfig, + states_dict :dict = {} ) -> None: - + super().__init__(states_dict) self.files=[] self.personality = personality self.personality_config = personality_config diff --git a/setup.py b/setup.py index 5b06b92..345e8d5 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ def get_all_files(path): setuptools.setup( name="lollms", - version="2.1.34", + version="2.1.35", author="Saifeddine ALOUI", author_email="aloui.saifeddine@gmail.com", description="A python library for AI personality definition",