From 13590372aec390cd374a3b899dabbd6fa985b17b Mon Sep 17 00:00:00 2001 From: Nathan Hoos <128712250+unaidedelf8777@users.noreply.github.com> Date: Mon, 25 Sep 2023 21:59:04 -0500 Subject: [PATCH] merge rebased branch to main. (#2) * fix: stop overwriting boolean config values Without the default set to None, any boolean CLI flag that isn't passed reverts to its default state even if it is configured in the config.yaml file. * The Generator Update (English docs) * Improved --conversations, --config --------- Co-authored-by: Eric allen Co-authored-by: killian <63927363+KillianLucas@users.noreply.github.com> --- interpreter/cli/cli.py | 3 ++- interpreter/core/core.py | 19 ++++++++++++---- interpreter/core/respond.py | 10 --------- .../conversation_navigator.py | 22 ++++++++++++++----- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/interpreter/cli/cli.py b/interpreter/cli/cli.py index 0b6ce7ad1f..9d52e26fcd 100644 --- a/interpreter/cli/cli.py +++ b/interpreter/cli/cli.py @@ -88,7 +88,7 @@ def cli(interpreter): # Add arguments for arg in arguments: if arg["type"] == bool: - parser.add_argument(f'-{arg["nickname"]}', f'--{arg["name"]}', dest=arg["name"], help=arg["help_text"], action='store_true') + parser.add_argument(f'-{arg["nickname"]}', f'--{arg["name"]}', dest=arg["name"], help=arg["help_text"], action='store_true', default=None) else: parser.add_argument(f'-{arg["nickname"]}', f'--{arg["name"]}', dest=arg["name"], help=arg["help_text"], type=arg["type"]) @@ -117,6 +117,7 @@ def cli(interpreter): except FileNotFoundError: # Fallback to using 'open' on macOS if 'xdg-open' is not available subprocess.call(['open', config_path]) + return # TODO Implement model explorer """ diff --git a/interpreter/core/core.py b/interpreter/core/core.py index d03efc5c6f..c82a9dcc3c 100644 --- a/interpreter/core/core.py +++ b/interpreter/core/core.py @@ -11,8 +11,8 @@ from ..terminal_interface.validate_llm_settings import validate_llm_settings import appdirs import os -import json from datetime import datetime +import json from ..utils.check_for_update import check_for_update from ..utils.display_markdown_message import display_markdown_message @@ -33,7 +33,7 @@ def __init__(self): # Conversation history self.conversation_history = True - self.conversation_name = datetime.now().strftime("%B_%d_%Y_%H-%M-%S") + self.conversation_filename = None self.conversation_history_path = os.path.join(appdirs.user_data_dir("Open Interpreter"), "conversations") # LLM settings @@ -97,11 +97,22 @@ def _streaming_chat(self, message=None, display=True): # Save conversation if self.conversation_history: + + # If it's the first message, set the conversation name + if len([m for m in self.messages if m["role"] == "user"]) == 1: + + first_few_words = "_".join(self.messages[0]["message"][:25].split(" ")[:-1]) + for char in "<>:\"/\\|?*!": # Invalid characters for filenames + first_few_words = first_few_words.replace(char, "") + + date = datetime.now().strftime("%B_%d_%Y_%H-%M-%S") + self.conversation_filename = "__".join([first_few_words, date]) + ".json" + # Check if the directory exists, if not, create it if not os.path.exists(self.conversation_history_path): os.makedirs(self.conversation_history_path) # Write or overwrite the file - with open(os.path.join(self.conversation_history_path, self.conversation_name + '.json'), 'w') as f: + with open(os.path.join(self.conversation_history_path, self.conversation_filename), 'w') as f: json.dump(self.messages, f) return @@ -113,7 +124,7 @@ def _respond(self): def reset(self): self.messages = [] - self.conversation_name = datetime.now().strftime("%B %d, %Y") + self.conversation_filename = None for code_interpreter in self._code_interpreters.values(): code_interpreter.terminate() self._code_interpreters = {} \ No newline at end of file diff --git a/interpreter/core/respond.py b/interpreter/core/respond.py index 8d9b692aa8..2de25c315a 100644 --- a/interpreter/core/respond.py +++ b/interpreter/core/respond.py @@ -115,16 +115,11 @@ def respond(interpreter): # We need to tell python what we (the generator) should do if they exit break - # Track if you've sent_output. - # If you never do, we'll send an empty string (to indicate that code has been run) - sent_output = False - # Yield each line, also append it to last messages' output interpreter.messages[-1]["output"] = "" for line in code_interpreter.run(code): yield line if "output" in line: - sent_output = True output = interpreter.messages[-1]["output"] output += "\n" + line["output"] @@ -133,11 +128,6 @@ def respond(interpreter): interpreter.messages[-1]["output"] = output.strip() - if sent_output == False: - # Indicate that the code has been run by sending an empty string - # I think we can remove this now that we send "executing".. right? - yield {"output": ""} - except: output = traceback.format_exc() yield {"output": output.strip()} diff --git a/interpreter/terminal_interface/conversation_navigator.py b/interpreter/terminal_interface/conversation_navigator.py index 6b3e68975c..a2a1c624ca 100644 --- a/interpreter/terminal_interface/conversation_navigator.py +++ b/interpreter/terminal_interface/conversation_navigator.py @@ -28,24 +28,34 @@ def conversation_navigator(interpreter): # Get list of all JSON files in the directory json_files = [f for f in os.listdir(conversations_dir) if f.endswith('.json')] - json_files.append("> Open folder") # Add the option to open the folder + + # Make a dict that maps reformatted "First few words... (September 23rd)" -> "First_few_words__September_23rd.json" (original file name) + readable_names_and_filenames = {} + for filename in json_files: + name = filename.replace(".json", "").replace(".JSON", "").replace("__", "... (").replace("_", " ") + ")" + readable_names_and_filenames[name] = filename + + # Add the option to open the folder. This doesn't map to a filename, we'll catch it + readable_names_and_filenames["> Open folder"] = None # Use inquirer to let the user select a file questions = [ - inquirer.List('file', + inquirer.List('name', message="", - choices=json_files, + choices=readable_names_and_filenames.keys(), ), ] answers = inquirer.prompt(questions) # If the user selected to open the folder, do so and return - if answers['file'] == "> Open folder": + if answers['name'] == "> Open folder": open_folder(conversations_dir) return + selected_filename = readable_names_and_filenames[answers['name']] + # Open the selected file and load the JSON data - with open(os.path.join(conversations_dir, answers['file']), 'r') as f: + with open(os.path.join(conversations_dir, selected_filename), 'r') as f: messages = json.load(f) # Pass the data into render_past_conversation @@ -53,7 +63,7 @@ def conversation_navigator(interpreter): # Set the interpreter's settings to the loaded messages interpreter.messages = messages - interpreter.conversation_name = answers['file'].replace(".json", "") + interpreter.conversation_filename = selected_filename # Start the chat interpreter.chat()