diff --git a/interpreter/core/computer/clipboard/clipboard.py b/interpreter/core/computer/clipboard/clipboard.py index 27c712b8d..71bb351a5 100644 --- a/interpreter/core/computer/clipboard/clipboard.py +++ b/interpreter/core/computer/clipboard/clipboard.py @@ -1,8 +1,10 @@ import os + from ...utils.lazy_import import lazy_import # Lazy import of optional packages -pyperclip = lazy_import('pyperclip') +pyperclip = lazy_import("pyperclip") + class Clipboard: def __init__(self, computer): diff --git a/interpreter/core/computer/contacts/contacts.py b/interpreter/core/computer/contacts/contacts.py index 890c0dc95..a4060d1e6 100644 --- a/interpreter/core/computer/contacts/contacts.py +++ b/interpreter/core/computer/contacts/contacts.py @@ -1,73 +1,72 @@ import platform + from ..utils.run_applescript import run_applescript_capture + class Contacts: def __init__(self, computer): self.computer = computer - def get_phone_number(self, contact_name): """ Returns the phone number of a contact by name. """ - if platform.system() != 'Darwin': + if platform.system() != "Darwin": return "This method is only supported on MacOS" - - script = f''' + + script = f""" tell application "Contacts" set thePerson to first person whose name is "{contact_name}" set theNumber to value of first phone of thePerson return theNumber end tell - ''' + """ stout, stderr = run_applescript_capture(script) # If the person is not found, we will try to find similar contacts if "Can’t get person" in stderr: - names= self.get_full_names_from_first_name(contact_name) + names = self.get_full_names_from_first_name(contact_name) if names == "No contacts found": return "No contacts found" else: # Language model friendly error message return f"A contact for '{contact_name}' was not found, perhaps one of these similar contacts might be what you are looking for? {names} \n Please try again and provide a more specific contact name." else: - return stout.replace('\n', '') - + return stout.replace("\n", "") def get_email_address(self, contact_name): """ Returns the email address of a contact by name. """ - if platform.system() != 'Darwin': + if platform.system() != "Darwin": return "This method is only supported on MacOS" - - script = f''' + + script = f""" tell application "Contacts" set thePerson to first person whose name is "{contact_name}" set theEmail to value of first email of thePerson return theEmail end tell - ''' + """ stout, stderr = run_applescript_capture(script) # If the person is not found, we will try to find similar contacts if "Can’t get person" in stderr: - names= self.get_full_names_from_first_name(contact_name) + names = self.get_full_names_from_first_name(contact_name) if names == "No contacts found": return "No contacts found" else: # Language model friendly error message return f"A contact for '{contact_name}' was not found, perhaps one of these similar contacts might be what you are looking for? {names} \n Please try again and provide a more specific contact name." else: - return stout.replace('\n', '') - + return stout.replace("\n", "") def get_full_names_from_first_name(self, first_name): """ Returns a list of full names of contacts that contain the first name provided. """ - if platform.system() != 'Darwin': + if platform.system() != "Darwin": return "This method is only supported on MacOS" - - script = f''' + + script = f""" tell application "Contacts" set matchingPeople to every person whose name contains "{first_name}" set namesList to {{}} @@ -76,10 +75,9 @@ def get_full_names_from_first_name(self, first_name): end repeat return namesList end tell - ''' + """ names, _ = run_applescript_capture(script) if names: return names else: return "No contacts found." - \ No newline at end of file diff --git a/interpreter/core/computer/docs/docs.py b/interpreter/core/computer/docs/docs.py index c83585097..7265ec7b4 100644 --- a/interpreter/core/computer/docs/docs.py +++ b/interpreter/core/computer/docs/docs.py @@ -4,7 +4,8 @@ from ...utils.lazy_import import lazy_import # Lazy import of aifs, imported when needed to speed up start time -aifs = lazy_import('aifs') +aifs = lazy_import("aifs") + class Docs: def __init__(self, computer): diff --git a/interpreter/core/computer/files/files.py b/interpreter/core/computer/files/files.py index 4c559b3ab..74a825b61 100644 --- a/interpreter/core/computer/files/files.py +++ b/interpreter/core/computer/files/files.py @@ -3,7 +3,8 @@ from ...utils.lazy_import import lazy_import # Lazy import of aifs, imported when needed -aifs = lazy_import('aifs') +aifs = lazy_import("aifs") + class Files: def __init__(self, computer): diff --git a/interpreter/core/computer/keyboard/keyboard.py b/interpreter/core/computer/keyboard/keyboard.py index 5cf34fd80..11d3e8ff8 100644 --- a/interpreter/core/computer/keyboard/keyboard.py +++ b/interpreter/core/computer/keyboard/keyboard.py @@ -1,10 +1,12 @@ import os import platform import time + from ...utils.lazy_import import lazy_import # Lazy import of pyautogui -pyautogui = lazy_import('pyautogui') +pyautogui = lazy_import("pyautogui") + class Keyboard: """A class to simulate keyboard inputs""" @@ -14,7 +16,7 @@ def __init__(self, computer): def write(self, text, interval=None, **kwargs): """ - Type out a string of characters. + Type out a string of characters. """ time.sleep(0.15) diff --git a/interpreter/core/computer/sms/sms.py b/interpreter/core/computer/sms/sms.py index 4a811c3e0..13da58595 100644 --- a/interpreter/core/computer/sms/sms.py +++ b/interpreter/core/computer/sms/sms.py @@ -1,5 +1,6 @@ -import subprocess import platform +import subprocess + from ..utils.run_applescript import run_applescript @@ -8,16 +9,14 @@ def __init__(self, computer): self.computer = computer self.messages_app = "Messages" - - def send(self, to, message): """ Sends an SMS message to the specified recipient using the Messages app. """ # Check if the operating system is MacOS, as this functionality is MacOS-specific. - if platform.system() != 'Darwin': + if platform.system() != "Darwin": return "This method is only supported on MacOS" - + # Remove any newline characters from the recipient number. to = to.replace("\n", "") # Escape double quotes in the message and recipient variables to prevent script errors. diff --git a/interpreter/core/respond.py b/interpreter/core/respond.py index 224d08a63..8b4f48411 100644 --- a/interpreter/core/respond.py +++ b/interpreter/core/respond.py @@ -112,10 +112,7 @@ def respond(interpreter): ) elif interpreter.offline and not interpreter.os: print(traceback.format_exc()) - raise Exception( - "Error occurred. " - + str(e) - ) + raise Exception("Error occurred. " + str(e)) else: raise diff --git a/interpreter/core/utils/lazy_import.py b/interpreter/core/utils/lazy_import.py index 4d4204663..b43020db2 100644 --- a/interpreter/core/utils/lazy_import.py +++ b/interpreter/core/utils/lazy_import.py @@ -1,6 +1,7 @@ import importlib.util import sys + def lazy_import(name, optional=True): """Lazily import a module, specified by the name. Useful for optional packages, to speed up startup times.""" # Check if module is already imported diff --git a/interpreter/terminal_interface/magic_commands.py b/interpreter/terminal_interface/magic_commands.py index 8a02a966a..1d200c012 100644 --- a/interpreter/terminal_interface/magic_commands.py +++ b/interpreter/terminal_interface/magic_commands.py @@ -1,10 +1,10 @@ import json import os import subprocess -import time import sys - +import time from datetime import datetime + from ..core.utils.system_debug_info import system_info from .utils.count_tokens import count_messages_tokens from .utils.display_markdown_message import display_markdown_message @@ -175,15 +175,17 @@ def handle_count_tokens(self, prompt): display_markdown_message("\n".join(outputs)) + def get_downloads_path(): - if os.name == 'nt': + if os.name == "nt": # For Windows - downloads = os.path.join(os.environ['USERPROFILE'], 'Downloads') + downloads = os.path.join(os.environ["USERPROFILE"], "Downloads") else: # For MacOS and Linux - downloads = os.path.join(os.path.expanduser('~'), 'Downloads') + downloads = os.path.join(os.path.expanduser("~"), "Downloads") return downloads + def install_and_import(package): try: module = __import__(package) @@ -193,29 +195,32 @@ def install_and_import(package): print("") print(f"Installing {package}...") print("") - subprocess.check_call([sys.executable, "-m", "pip", "install", package], - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL - ) + subprocess.check_call( + [sys.executable, "-m", "pip", "install", package], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) module = __import__(package) except subprocess.CalledProcessError: # If pip fails, try pip3 try: - subprocess.check_call([sys.executable, "-m", "pip3", "install", package], + subprocess.check_call( + [sys.executable, "-m", "pip3", "install", package], stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL + stderr=subprocess.DEVNULL, ) except subprocess.CalledProcessError: print(f"Failed to install package {package}.") return finally: globals()[package] = module - return module + return module + def jupyter(self, arguments): # Dynamically install nbformat if not already installed - nbformat = install_and_import('nbformat') - from nbformat.v4 import new_notebook, new_code_cell, new_markdown_cell + nbformat = install_and_import("nbformat") + from nbformat.v4 import new_code_cell, new_markdown_cell, new_notebook downloads = get_downloads_path() current_time = datetime.now() @@ -224,31 +229,33 @@ def jupyter(self, arguments): notebook_path = os.path.join(downloads, filename) nb = new_notebook() cells = [] - + for msg in self.messages: - if msg['role'] == 'user' and msg['type'] == 'message': - # Prefix user messages with '>' to render them as block quotes, so they stand out - content = f"> {msg['content']}" - cells.append(new_markdown_cell(content)) - elif msg['role'] == 'assistant' and msg['type'] == 'message': - cells.append(new_markdown_cell(msg['content'])) - elif msg['type'] == 'code': - # Handle the language of the code cell - if 'format' in msg and msg['format']: - language = msg['format'] - else: - language = 'python' # Default to Python if no format specified - code_cell = new_code_cell(msg['content']) - code_cell.metadata.update({"language": language}) - cells.append(code_cell) - - nb['cells'] = cells - - with open(notebook_path, 'w', encoding='utf-8') as f: + if msg["role"] == "user" and msg["type"] == "message": + # Prefix user messages with '>' to render them as block quotes, so they stand out + content = f"> {msg['content']}" + cells.append(new_markdown_cell(content)) + elif msg["role"] == "assistant" and msg["type"] == "message": + cells.append(new_markdown_cell(msg["content"])) + elif msg["type"] == "code": + # Handle the language of the code cell + if "format" in msg and msg["format"]: + language = msg["format"] + else: + language = "python" # Default to Python if no format specified + code_cell = new_code_cell(msg["content"]) + code_cell.metadata.update({"language": language}) + cells.append(code_cell) + + nb["cells"] = cells + + with open(notebook_path, "w", encoding="utf-8") as f: nbformat.write(nb, f) - + print("") - display_markdown_message(f"Jupyter notebook file exported to {os.path.abspath(notebook_path)}") + display_markdown_message( + f"Jupyter notebook file exported to {os.path.abspath(notebook_path)}" + ) def handle_magic_command(self, user_input): diff --git a/interpreter/terminal_interface/profiles/defaults/local.py b/interpreter/terminal_interface/profiles/defaults/local.py index 3f72e57a8..d6ee0d01d 100644 --- a/interpreter/terminal_interface/profiles/defaults/local.py +++ b/interpreter/terminal_interface/profiles/defaults/local.py @@ -1,150 +1,177 @@ -import sys import os import platform import subprocess +import sys import time + import inquirer from interpreter import interpreter + def download_model(models_dir, models, interpreter): # For some reason, these imports need to be inside the function import inquirer - import wget import psutil + import wget # Get RAM and disk information - total_ram = psutil.virtual_memory().total / (1024 * 1024 * 1024) # Convert bytes to GB - free_disk_space = psutil.disk_usage('/').free / (1024 * 1024 * 1024) # Convert bytes to GB - + total_ram = psutil.virtual_memory().total / ( + 1024 * 1024 * 1024 + ) # Convert bytes to GB + free_disk_space = psutil.disk_usage("/").free / ( + 1024 * 1024 * 1024 + ) # Convert bytes to GB + time.sleep(1) - + # Display the users hardware specs - interpreter.display_message(f"Your machine has `{total_ram:.2f}GB` of RAM, and `{free_disk_space:.2f}GB` of free storage space.") - + interpreter.display_message( + f"Your machine has `{total_ram:.2f}GB` of RAM, and `{free_disk_space:.2f}GB` of free storage space." + ) + time.sleep(2) - + if total_ram < 10: - interpreter.display_message(f"\nYour computer realistically can only run smaller models less than 4GB, Phi-2 might be the best model for your computer.\n") + interpreter.display_message( + f"\nYour computer realistically can only run smaller models less than 4GB, Phi-2 might be the best model for your computer.\n" + ) elif 10 <= total_ram < 30: - interpreter.display_message(f"\nYour computer could handle a mid-sized model (4-10GB), Mistral-7B might be the best model for your computer.\n") + interpreter.display_message( + f"\nYour computer could handle a mid-sized model (4-10GB), Mistral-7B might be the best model for your computer.\n" + ) else: - interpreter.display_message(f"\nYour computer should have enough RAM to run any model below.\n") - - + interpreter.display_message( + f"\nYour computer should have enough RAM to run any model below.\n" + ) + time.sleep(1) - - interpreter.display_message(f"In general, the larger the model, the better the performance, but choose a model that best fits your computer's hardware. \nOnly models you have the storage space to download are shown:\n") - + + interpreter.display_message( + f"In general, the larger the model, the better the performance, but choose a model that best fits your computer's hardware. \nOnly models you have the storage space to download are shown:\n" + ) + time.sleep(1) - + try: model_list = [ { "name": "TinyLlama-1.1B", "file_name": "TinyLlama-1.1B-Chat-v1.0.Q5_K_M.llamafile", "size": 0.76, - "url": "https://huggingface.co/jartine/TinyLlama-1.1B-Chat-v1.0-GGUF/resolve/main/TinyLlama-1.1B-Chat-v1.0.Q5_K_M.llamafile?download=true" + "url": "https://huggingface.co/jartine/TinyLlama-1.1B-Chat-v1.0-GGUF/resolve/main/TinyLlama-1.1B-Chat-v1.0.Q5_K_M.llamafile?download=true", }, { "name": "Rocket-3B", "file_name": "rocket-3b.Q5_K_M.llamafile", "size": 1.89, - "url": "https://huggingface.co/jartine/rocket-3B-llamafile/resolve/main/rocket-3b.Q5_K_M.llamafile?download=true" + "url": "https://huggingface.co/jartine/rocket-3B-llamafile/resolve/main/rocket-3b.Q5_K_M.llamafile?download=true", }, { "name": "Phi-2", "file_name": "phi-2.Q5_K_M.llamafile", "size": 1.96, - "url": "https://huggingface.co/jartine/phi-2-llamafile/resolve/main/phi-2.Q5_K_M.llamafile?download=true" + "url": "https://huggingface.co/jartine/phi-2-llamafile/resolve/main/phi-2.Q5_K_M.llamafile?download=true", }, { "name": "LLaVA 1.5", "file_name": "llava-v1.5-7b-q4.llamafile", "size": 3.97, - "url": "https://huggingface.co/jartine/llava-v1.5-7B-GGUF/resolve/main/llava-v1.5-7b-q4.llamafile?download=true" + "url": "https://huggingface.co/jartine/llava-v1.5-7B-GGUF/resolve/main/llava-v1.5-7b-q4.llamafile?download=true", }, { "name": "Mistral-7B-Instruct", "file_name": "mistral-7b-instruct-v0.2.Q5_K_M.llamafile", "size": 5.15, - "url": "https://huggingface.co/jartine/Mistral-7B-Instruct-v0.2-llamafile/resolve/main/mistral-7b-instruct-v0.2.Q5_K_M.llamafile?download=true" + "url": "https://huggingface.co/jartine/Mistral-7B-Instruct-v0.2-llamafile/resolve/main/mistral-7b-instruct-v0.2.Q5_K_M.llamafile?download=true", }, { "name": "WizardCoder-Python-13B", "file_name": "wizardcoder-python-13b.llamafile", "size": 7.33, - "url": "https://huggingface.co/jartine/wizardcoder-13b-python/resolve/main/wizardcoder-python-13b.llamafile?download=true" + "url": "https://huggingface.co/jartine/wizardcoder-13b-python/resolve/main/wizardcoder-python-13b.llamafile?download=true", }, { "name": "WizardCoder-Python-34B", "file_name": "wizardcoder-python-34b-v1.0.Q5_K_M.llamafile", "size": 22.23, - "url": "https://huggingface.co/jartine/WizardCoder-Python-34B-V1.0-llamafile/resolve/main/wizardcoder-python-34b-v1.0.Q5_K_M.llamafile?download=true" + "url": "https://huggingface.co/jartine/WizardCoder-Python-34B-V1.0-llamafile/resolve/main/wizardcoder-python-34b-v1.0.Q5_K_M.llamafile?download=true", }, { "name": "Mixtral-8x7B-Instruct", "file_name": "mixtral-8x7b-instruct-v0.1.Q5_K_M.llamafile", "size": 30.03, - "url": "https://huggingface.co/jartine/Mixtral-8x7B-Instruct-v0.1-llamafile/resolve/main/mixtral-8x7b-instruct-v0.1.Q5_K_M.llamafile?download=true" - } + "url": "https://huggingface.co/jartine/Mixtral-8x7B-Instruct-v0.1-llamafile/resolve/main/mixtral-8x7b-instruct-v0.1.Q5_K_M.llamafile?download=true", + }, ] - + # Filter models based on available disk space and RAM - filtered_models = [model for model in model_list if model["size"] <= free_disk_space and model["file_name"] not in models] + filtered_models = [ + model + for model in model_list + if model["size"] <= free_disk_space and model["file_name"] not in models + ] if filtered_models: - time.sleep(1) - + # Prompt the user to select a model model_choices = [ - f"{model['name']} ({model['size']:.2f}GB)" - for model in filtered_models + f"{model['name']} ({model['size']:.2f}GB)" for model in filtered_models ] questions = [ inquirer.List( "model", message="Select a model to download:", - choices=model_choices + choices=model_choices, ) ] answers = inquirer.prompt(questions) - + # Get the selected model - selected_model = next(model for model in filtered_models if f"{model['name']} ({model['size']}GB)" == answers["model"]) - + selected_model = next( + model + for model in filtered_models + if f"{model['name']} ({model['size']}GB)" == answers["model"] + ) + # Download the selected model model_url = selected_model["url"] # Extract the basename and remove query parameters - filename = os.path.basename(model_url).split('?')[0] + filename = os.path.basename(model_url).split("?")[0] model_path = os.path.join(models_dir, filename) - + time.sleep(1) print(f"\nDownloading {selected_model['name']}...\n") wget.download(model_url, model_path) - + # Make the model executable if not on Windows if platform.system() != "Windows": subprocess.run(["chmod", "+x", model_path], check=True) - + print(f"\nModel '{selected_model['name']}' downloaded successfully.\n") - - interpreter.display_message("To view or delete downloaded local models, run `interpreter --local_models`\n\n") - + + interpreter.display_message( + "To view or delete downloaded local models, run `interpreter --local_models`\n\n" + ) + return model_path else: - print("\nYour computer does not have enough storage to download any local LLMs.\n") + print( + "\nYour computer does not have enough storage to download any local LLMs.\n" + ) return None except Exception as e: print(e) - print("\nAn error occurred while trying to download the model. Please try again or use a different local model provider.\n") + print( + "\nAn error occurred while trying to download the model. Please try again or use a different local model provider.\n" + ) return None - - # START OF LOCAL MODEL PROVIDER LOGIC -interpreter.display_message("> Open Interpreter is compatible with several local model providers.\n") +interpreter.display_message( + "> Open Interpreter is compatible with several local model providers.\n" +) # Define the choices for local models choices = [ @@ -183,7 +210,7 @@ def download_model(models_dir, models, interpreter): """ ) - + interpreter.llm.api_base = "http://localhost:1234/v1" interpreter.llm.max_tokens = 1000 interpreter.llm.context_window = 3000 @@ -191,47 +218,58 @@ def download_model(models_dir, models, interpreter): elif selected_model == "Ollama": try: - # List out all downloaded ollama models. Will fail if ollama isn't installed - result = subprocess.run(["ollama", "list"], capture_output=True, text=True, check=True) - lines = result.stdout.split('\n') - names = [line.split()[0].replace(":latest", "") for line in lines[1:] if line.strip()] # Extract names, trim out ":latest", skip header - + result = subprocess.run( + ["ollama", "list"], capture_output=True, text=True, check=True + ) + lines = result.stdout.split("\n") + names = [ + line.split()[0].replace(":latest", "") for line in lines[1:] if line.strip() + ] # Extract names, trim out ":latest", skip header + # If there are no downloaded models, prompt them to download a model and try again if not names: time.sleep(1) - - interpreter.display_message(f"\nYou don't have any Ollama models downloaded. To download a new model, run `ollama run `, then start a new interpreter session. \n\n For a full list of downloadable models, check out [https://ollama.com/library](https://ollama.com/library) \n") - + + interpreter.display_message( + f"\nYou don't have any Ollama models downloaded. To download a new model, run `ollama run `, then start a new interpreter session. \n\n For a full list of downloadable models, check out [https://ollama.com/library](https://ollama.com/library) \n" + ) + print("Please download a model then try again\n") time.sleep(2) sys.exit(1) - + # If there are models, prompt them to select one else: time.sleep(1) - interpreter.display_message(f"**{len(names)} Ollama model{'s' if len(names) != 1 else ''} found.** To download a new model, run `ollama run `, then start a new interpreter session. \n\n For a full list of downloadable models, check out [https://ollama.com/library](https://ollama.com/library) \n") + interpreter.display_message( + f"**{len(names)} Ollama model{'s' if len(names) != 1 else ''} found.** To download a new model, run `ollama run `, then start a new interpreter session. \n\n For a full list of downloadable models, check out [https://ollama.com/library](https://ollama.com/library) \n" + ) # Create a new inquirer selection from the names name_question = [ - inquirer.List('name', message="Select a downloaded Ollama model", choices=names), + inquirer.List( + "name", message="Select a downloaded Ollama model", choices=names + ), ] name_answer = inquirer.prompt(name_question) - selected_name = name_answer['name'] if name_answer else None - + selected_name = name_answer["name"] if name_answer else None + # Set the model to the selected model interpreter.llm.model = f"ollama/{selected_name}" interpreter.display_message(f"\nUsing Ollama model: `{selected_name}` \n") time.sleep(1) - + # If Ollama is not installed or not recognized as a command, prompt the user to download Ollama and try again except (subprocess.CalledProcessError, FileNotFoundError) as e: print("Ollama is not installed or not recognized as a command.") time.sleep(1) - interpreter.display_message(f"\nPlease visit [https://ollama.com/](https://ollama.com/) to download Ollama and try again\n") + interpreter.display_message( + f"\nPlease visit [https://ollama.com/](https://ollama.com/) to download Ollama and try again\n" + ) time.sleep(2) sys.exit(1) - + elif selected_model == "Jan": interpreter.display_message( """ @@ -251,21 +289,22 @@ def download_model(models_dir, models, interpreter): interpreter.llm.max_tokens = 1000 interpreter.llm.context_window = 3000 time.sleep(1) - + # Prompt the user to enter the name of the model running on Jan model_name_question = [ - inquirer.Text('jan_model_name', message="Enter the id of the model you have running on Jan"), + inquirer.Text( + "jan_model_name", + message="Enter the id of the model you have running on Jan", + ), ] model_name_answer = inquirer.prompt(model_name_question) - jan_model_name = model_name_answer['jan_model_name'] if model_name_answer else None + jan_model_name = model_name_answer["jan_model_name"] if model_name_answer else None interpreter.llm.model = f"jan/{jan_model_name}" interpreter.display_message(f"\nUsing Jan model: `{jan_model_name}` \n") time.sleep(1) - - -elif selected_model == "Llamafile": +elif selected_model == "Llamafile": if platform.system() == "Darwin": # Check if the system is MacOS result = subprocess.run( ["xcode-select", "-p"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT @@ -275,7 +314,9 @@ def download_model(models_dir, models, interpreter): "To use Llamafile, Open Interpreter requires Mac users to have Xcode installed. You can install Xcode from https://developer.apple.com/xcode/ .\n\nAlternatively, you can use `LM Studio`, `Jan.ai`, or `Ollama` to manage local language models. Learn more at https://docs.openinterpreter.com/guides/running-locally ." ) time.sleep(3) - raise Exception("Xcode is not installed. Please install Xcode and try again.") + raise Exception( + "Xcode is not installed. Please install Xcode and try again." + ) # Define the path to the models directory models_dir = os.path.join(interpreter.get_oi_dir(), "models") @@ -289,7 +330,7 @@ def download_model(models_dir, models, interpreter): if not models: print("\nThere are no models currently downloaded. Let's download a new one.\n") - model_path = download_model(models_dir, models, interpreter) + model_path = download_model(models_dir, models, interpreter) else: # Prompt the user to select a downloaded model or download a new one model_choices = models + [" ↓ Download new model"] @@ -297,21 +338,27 @@ def download_model(models_dir, models, interpreter): inquirer.List( "model", message="Select a Llamafile model to run or download a new one:", - choices=model_choices + choices=model_choices, ) ] answers = inquirer.prompt(questions) - + if answers["model"] == " ↓ Download new model": model_path = download_model(models_dir, models, interpreter) else: model_path = os.path.join(models_dir, answers["model"]) - + if model_path: try: # Run the selected model and hide its output - process = subprocess.Popen(f'"{model_path}" ' + " ".join(["--nobrowser", "-ngl", "9999"]), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) - + process = subprocess.Popen( + f'"{model_path}" ' + " ".join(["--nobrowser", "-ngl", "9999"]), + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + ) + print("Waiting for the model to load...") for line in process.stdout: if "llama server listening at http://127.0.0.1:8080" in line: @@ -335,6 +382,3 @@ def download_model(models_dir, models, interpreter): interpreter.system_message = "You are Open Interpreter, a world-class programmer that can execute code on the user's machine." # Set offline for all local models interpreter.offline = True - - - diff --git a/interpreter/terminal_interface/profiles/profiles.py b/interpreter/terminal_interface/profiles/profiles.py index 89f4f1d74..e7457a445 100644 --- a/interpreter/terminal_interface/profiles/profiles.py +++ b/interpreter/terminal_interface/profiles/profiles.py @@ -549,7 +549,7 @@ def apply_profile_to_object(obj, profile): def open_storage_dir(directory): dir = os.path.join(oi_dir, directory) - + print(f"Opening {directory} directory ({dir})...") if platform.system() == "Windows": @@ -563,6 +563,7 @@ def open_storage_dir(directory): subprocess.call(["open", dir]) return + def reset_profile(specific_default_profile=None): if ( specific_default_profile diff --git a/interpreter/terminal_interface/terminal_interface.py b/interpreter/terminal_interface/terminal_interface.py index b4bc652b9..d7580ec64 100644 --- a/interpreter/terminal_interface/terminal_interface.py +++ b/interpreter/terminal_interface/terminal_interface.py @@ -22,10 +22,10 @@ from .components.message_block import MessageBlock from .magic_commands import handle_magic_command from .utils.check_for_package import check_for_package +from .utils.cli_input import cli_input from .utils.display_markdown_message import display_markdown_message from .utils.display_output import display_output from .utils.find_image_path import find_image_path -from .utils.cli_input import cli_input # Add examples to the readline history examples = [ @@ -76,7 +76,11 @@ def terminal_interface(interpreter, message): try: if interactive: ### This is the primary input for Open Interpreter. - message = cli_input("> ").strip() if interpreter.multi_line else input("> ").strip() + message = ( + cli_input("> ").strip() + if interpreter.multi_line + else input("> ").strip() + ) try: # This lets users hit the up arrow key for past messages diff --git a/interpreter/terminal_interface/validate_llm_settings.py b/interpreter/terminal_interface/validate_llm_settings.py index ea490bc24..0b72c6763 100644 --- a/interpreter/terminal_interface/validate_llm_settings.py +++ b/interpreter/terminal_interface/validate_llm_settings.py @@ -29,7 +29,11 @@ def validate_llm_settings(interpreter): # OpenAI if interpreter.llm.model in litellm.open_ai_chat_completion_models: - if not os.environ.get("OPENAI_API_KEY") and not interpreter.llm.api_key and not interpreter.llm.api_base: + if ( + not os.environ.get("OPENAI_API_KEY") + and not interpreter.llm.api_key + and not interpreter.llm.api_base + ): display_welcome_message_once() display_markdown_message(