From a5048aed56eb1683742aa758b65ad3bd1339ce95 Mon Sep 17 00:00:00 2001 From: ryanmac Date: Mon, 3 Apr 2023 14:20:45 -0500 Subject: [PATCH 01/29] Fix .gitignore to include the correct path to auto_gpt_workspace --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 6b8f00b51..55a21afeb 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ scripts/node_modules/ scripts/__pycache__/keys.cpython-310.pyc package-lock.json *.pyc -scripts/auto_gpt_workspace/* +auto_gpt_workspace/* *.mpeg .env last_run_ai_settings.yaml From 8150f0c813962aaec6b0c070b27c5201e858ef8b Mon Sep 17 00:00:00 2001 From: Pavloh <89773173+ImPavloh@users.noreply.github.com> Date: Tue, 4 Apr 2023 13:24:14 +0200 Subject: [PATCH 02/29] Refactor load_prompt function Simplify the load_prompt function by eliminating redundancy --- scripts/data.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/scripts/data.py b/scripts/data.py index 72a6bbfc6..8d8a7b4ac 100644 --- a/scripts/data.py +++ b/scripts/data.py @@ -1,15 +1,14 @@ import os from pathlib import Path -SRC_DIR = Path(__file__).parent def load_prompt(): try: # get directory of this file: - file_dir = Path(os.path.dirname(os.path.realpath(__file__))) - data_dir = file_dir / "data" - prompt_file = data_dir / "prompt.txt" - # Load the promt from data/prompt.txt - with open(SRC_DIR/ "data/prompt.txt", "r") as prompt_file: + file_dir = Path(__file__).parent + prompt_file_path = file_dir / "data" / "prompt.txt" + + # Load the prompt from data/prompt.txt + with open(prompt_file_path, "r") as prompt_file: prompt = prompt_file.read() return prompt From 624e5b8a181dc276c7856b5d545abe2a36a59759 Mon Sep 17 00:00:00 2001 From: thepok Date: Tue, 4 Apr 2023 15:21:46 +0200 Subject: [PATCH 03/29] More logical Prompt - found by Agusx1211 --- scripts/data/prompt.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/data/prompt.txt b/scripts/data/prompt.txt index a93e783eb..64a4fdba9 100644 --- a/scripts/data/prompt.txt +++ b/scripts/data/prompt.txt @@ -43,12 +43,6 @@ You should only respond in JSON format as described below RESPONSE FORMAT: { - "command": { - "name": "command name", - "args":{ - "arg name": "value" - } - }, "thoughts": { "text": "thought", @@ -56,6 +50,12 @@ RESPONSE FORMAT: "plan": "- short bulleted\n- list that conveys\n- long-term plan", "criticism": "constructive self-criticism", "speak": "thoughts summary to say to user" + }, + "command": { + "name": "command name", + "args":{ + "arg name": "value" + } } } From ed5952782fbdf388f335768d12a958088c611d68 Mon Sep 17 00:00:00 2001 From: slavakurilyak Date: Tue, 4 Apr 2023 15:53:59 -0500 Subject: [PATCH 04/29] Improve key validation and handling in overwrite_memory and message_agent functions --- scripts/commands.py | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/scripts/commands.py b/scripts/commands.py index f8f96fe72..c1d5db9d3 100644 --- a/scripts/commands.py +++ b/scripts/commands.py @@ -16,6 +16,13 @@ from googleapiclient.errors import HttpError cfg = Config() +def is_valid_int(value): + try: + int(value) + return True + except ValueError: + return False + def get_command(response): try: response_json = fix_and_parse_json(response) @@ -194,14 +201,28 @@ def delete_memory(key): def overwrite_memory(key, string): - if int(key) >= 0 and key < len(mem.permanent_memory): - _text = "Overwriting memory with key " + \ - str(key) + " and string " + string - mem.permanent_memory[key] = string + # Check if the key is a valid integer + if is_valid_int(key): + key_int = int(key) + # Check if the integer key is within the range of the permanent_memory list + if 0 <= key_int < len(mem.permanent_memory): + _text = "Overwriting memory with key " + str(key) + " and string " + string + # Overwrite the memory slot with the given integer key and string + mem.permanent_memory[key_int] = string + print(_text) + return _text + else: + print(f"Invalid key '{key}', out of range.") + return None + # Check if the key is a valid string + elif isinstance(key, str): + _text = "Overwriting memory with key " + key + " and string " + string + # Overwrite the memory slot with the given string key and string + mem.string_key_memory[key] = string print(_text) return _text else: - print("Invalid key, cannot overwrite memory.") + print(f"Invalid key '{key}', must be an integer or a string.") return None @@ -235,7 +256,12 @@ def start_agent(name, task, prompt, model=cfg.fast_llm_model): def message_agent(key, message): global cfg - agent_response = agents.message_agent(key, message) + + # Check if the key is a valid integer + if not is_valid_int(key): + return "Invalid key, cannot message agent." + + agent_response = agents.message_agent(int(key), message) # Speak response if cfg.speak_mode: From 1e4732807931f815feb3f6dfab22b5f7c4d0ce15 Mon Sep 17 00:00:00 2001 From: slavakurilyak Date: Tue, 4 Apr 2023 20:32:15 -0500 Subject: [PATCH 05/29] Add search files command --- scripts/commands.py | 4 +++- scripts/data/prompt.txt | 11 ++++++----- scripts/file_operations.py | 13 +++++++++++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/scripts/commands.py b/scripts/commands.py index c1d5db9d3..a6e8f7451 100644 --- a/scripts/commands.py +++ b/scripts/commands.py @@ -6,7 +6,7 @@ import agent_manager as agents import speak from config import Config import ai_functions as ai -from file_operations import read_file, write_to_file, append_to_file, delete_file +from file_operations import read_file, write_to_file, append_to_file, delete_file, search_files from execute_code import execute_python_file from json_parser import fix_and_parse_json from duckduckgo_search import ddg @@ -90,6 +90,8 @@ def execute_command(command_name, arguments): return append_to_file(arguments["file"], arguments["text"]) elif command_name == "delete_file": return delete_file(arguments["file"]) + elif command_name == "search_files": + return search_files(arguments["directory"]) elif command_name == "browse_website": return browse_website(arguments["url"], arguments["question"]) # TODO: Change these to take in a file rather than pasted code, if diff --git a/scripts/data/prompt.txt b/scripts/data/prompt.txt index a93e783eb..75d9312a4 100644 --- a/scripts/data/prompt.txt +++ b/scripts/data/prompt.txt @@ -19,11 +19,12 @@ COMMANDS: 11. Read file: "read_file", args: "file": "" 12. Append to file: "append_to_file", args: "file": "", "text": "" 13. Delete file: "delete_file", args: "file": "" -14. Evaluate Code: "evaluate_code", args: "code": "" -15. Get Improved Code: "improve_code", args: "suggestions": "", "code": "" -16. Write Tests: "write_tests", args: "code": "", "focus": "" -17. Execute Python File: "execute_python_file", args: "file": "" -18. Task Complete (Shutdown): "task_complete", args: "reason": "" +14. Search Files: "search_files", args: "directory": "" +15. Evaluate Code: "evaluate_code", args: "code": "" +16. Get Improved Code: "improve_code", args: "suggestions": "", "code": "" +17. Write Tests: "write_tests", args: "code": "", "focus": "" +18. Execute Python File: "execute_python_file", args: "file": "" +19. Task Complete (Shutdown): "task_complete", args: "reason": "" RESOURCES: diff --git a/scripts/file_operations.py b/scripts/file_operations.py index 81ad47157..f3cd3a458 100644 --- a/scripts/file_operations.py +++ b/scripts/file_operations.py @@ -58,3 +58,16 @@ def delete_file(filename): return "File deleted successfully." except Exception as e: return "Error: " + str(e) + +def search_files(directory): + found_files = [] + search_directory = safe_join(working_directory, directory) + + for root, _, files in os.walk(search_directory): + for file in files: + if file.startswith('.'): + continue + relative_path = os.path.relpath(os.path.join(root, file), working_directory) + found_files.append(relative_path) + + return found_files \ No newline at end of file From b418861d70399eb021c2bec71ff1b7bc7780155f Mon Sep 17 00:00:00 2001 From: slavakurilyak Date: Tue, 4 Apr 2023 20:53:41 -0500 Subject: [PATCH 06/29] Update message_agent function to support string keys --- scripts/commands.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/scripts/commands.py b/scripts/commands.py index c1d5db9d3..2adb84cf5 100644 --- a/scripts/commands.py +++ b/scripts/commands.py @@ -256,18 +256,20 @@ def start_agent(name, task, prompt, model=cfg.fast_llm_model): def message_agent(key, message): global cfg - + # Check if the key is a valid integer - if not is_valid_int(key): - return "Invalid key, cannot message agent." - - agent_response = agents.message_agent(int(key), message) + if is_valid_int(key): + agent_response = agents.message_agent(int(key), message) + # Check if the key is a valid string + elif isinstance(key, str): + agent_response = agents.message_agent(key, message) + else: + return "Invalid key, must be an integer or a string." # Speak response if cfg.speak_mode: - speak.say_text(agent_response, 1) - - return f"Agent {key} responded: {agent_response}" + say.speak(agent_response) + return agent_response def list_agents(): From 98a2b4d9a5453336fc718b3a4ec8fbcc3207251e Mon Sep 17 00:00:00 2001 From: ReadyG <42131870+ReadyG@users.noreply.github.com> Date: Wed, 5 Apr 2023 00:11:19 -0400 Subject: [PATCH 07/29] Update prompt.txt Added double quotes around on line 14. --- scripts/data/prompt.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/data/prompt.txt b/scripts/data/prompt.txt index a93e783eb..ba9a3ec62 100644 --- a/scripts/data/prompt.txt +++ b/scripts/data/prompt.txt @@ -11,7 +11,7 @@ COMMANDS: 3. Memory Delete: "memory_del", args: "key": "" 4. Memory Overwrite: "memory_ovr", args: "key": "", "string": "" 5. Browse Website: "browse_website", args: "url": "", "question": "" -6. Start GPT Agent: "start_agent", args: "name": , "task": "", "prompt": "" +6. Start GPT Agent: "start_agent", args: "name": "", "task": "", "prompt": "" 7. Message GPT Agent: "message_agent", args: "key": "", "message": "" 8. List GPT Agents: "list_agents", args: "" 9. Delete GPT Agent: "delete_agent", args: "key": "" From c1be8a74038bf47aecd77df04b1b08716ab63e82 Mon Sep 17 00:00:00 2001 From: russellocean Date: Wed, 5 Apr 2023 00:56:15 -0400 Subject: [PATCH 08/29] Implement custom continuous task count with 'y -n' --- scripts/main.py | 61 +++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/scripts/main.py b/scripts/main.py index 93124234e..492df20b0 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -277,6 +277,7 @@ prompt = construct_prompt() # Initialize variables full_message_history = [] result = None +next_action_count = 0 # Make a constant: user_input = "Determine which next command to use, and respond using the format specified above:" @@ -291,7 +292,6 @@ while True: mem.permanent_memory, cfg.fast_token_limit) # TODO: This hardcodes the model to use GPT3.5. Make this an argument - # print("assistant reply: "+assistant_reply) # Print Assistant thoughts print_assistant_thoughts(assistant_reply) @@ -301,36 +301,45 @@ while True: except Exception as e: print_to_console("Error: \n", Fore.RED, str(e)) - if not cfg.continuous_mode: + if not cfg.continuous_mode or next_action_count > 0: ### GET USER AUTHORIZATION TO EXECUTE COMMAND ### # Get key press: Prompt the user to press enter to continue or escape # to exit - user_input = "" - print_to_console( - "NEXT ACTION: ", - Fore.CYAN, - f"COMMAND = {Fore.CYAN}{command_name}{Style.RESET_ALL} ARGUMENTS = {Fore.CYAN}{arguments}{Style.RESET_ALL}") - print( - f"Enter 'y' to authorise command or 'n' to exit program, or enter feedback for {ai_name}...", - flush=True) - while True: - console_input = input(Fore.MAGENTA + "Input:" + Style.RESET_ALL) - if console_input.lower() == "y": - user_input = "GENERATE NEXT COMMAND JSON" - break - elif console_input.lower() == "n": - user_input = "EXIT" - break - else: - user_input = console_input - command_name = "human_feedback" - break + if next_action_count == 0: + user_input = "" + print_to_console( + "NEXT ACTION: ", + Fore.CYAN, + f"COMMAND = {Fore.CYAN}{command_name}{Style.RESET_ALL} ARGUMENTS = {Fore.CYAN}{arguments}{Style.RESET_ALL}") + print( + f"Enter 'y' to authorise command, 'y -n' to run n continuous commands, 'n' to exit program, or enter feedback for {ai_name}...", + flush=True) + while True: + console_input = input(Fore.MAGENTA + "Input:" + Style.RESET_ALL) + if console_input.lower() == "y": + user_input = "GENERATE NEXT COMMAND JSON" + break + elif console_input.lower().startswith("y -"): + try: + next_action_count = abs(int(console_input.split(" ")[1])) + user_input = "GENERATE NEXT COMMAND JSON" + except ValueError: + print("Invalid input format. Please enter 'y -n' where n is the number of continuous tasks.") + continue + break + elif console_input.lower() == "n": + user_input = "EXIT" + break + else: + user_input = console_input + command_name = "human_feedback" + break if user_input == "GENERATE NEXT COMMAND JSON": print_to_console( - "-=-=-=-=-=-=-= COMMAND AUTHORISED BY USER -=-=-=-=-=-=-=", - Fore.MAGENTA, - "") + "-=-=-=-=-=-=-= COMMAND AUTHORISED BY USER -=-=-=-=-=-=-=", + Fore.MAGENTA, + "") elif user_input == "EXIT": print("Exiting...", flush=True) break @@ -348,6 +357,8 @@ while True: result = f"Human feedback: {user_input}" else: result = f"Command {command_name} returned: {cmd.execute_command(command_name, arguments)}" + if next_action_count > 0: + next_action_count -= 1 # Check if there's a result from the command append it to the message # history From c8c8f5b11e4f6c1d7297434996dd5159cb313d59 Mon Sep 17 00:00:00 2001 From: russellocean Date: Wed, 5 Apr 2023 10:19:56 -0400 Subject: [PATCH 09/29] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to @Gerqus Co-authored-by: Paweł Pieniacki --- scripts/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/main.py b/scripts/main.py index 492df20b0..f7692757d 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -301,7 +301,7 @@ while True: except Exception as e: print_to_console("Error: \n", Fore.RED, str(e)) - if not cfg.continuous_mode or next_action_count > 0: + if not cfg.continuous_mode and next_action_count === 0: ### GET USER AUTHORIZATION TO EXECUTE COMMAND ### # Get key press: Prompt the user to press enter to continue or escape # to exit @@ -312,7 +312,7 @@ while True: Fore.CYAN, f"COMMAND = {Fore.CYAN}{command_name}{Style.RESET_ALL} ARGUMENTS = {Fore.CYAN}{arguments}{Style.RESET_ALL}") print( - f"Enter 'y' to authorise command, 'y -n' to run n continuous commands, 'n' to exit program, or enter feedback for {ai_name}...", + f"Enter 'y' to authorise command, 'y -N' to run N continuous commands, 'n' to exit program, or enter feedback for {ai_name}...", flush=True) while True: console_input = input(Fore.MAGENTA + "Input:" + Style.RESET_ALL) From c8a927d3ec35cc01feadad470eacb617902b6987 Mon Sep 17 00:00:00 2001 From: russellocean Date: Wed, 5 Apr 2023 10:28:50 -0400 Subject: [PATCH 10/29] Syntax Error, Revert formatting errors, remove 308 --- scripts/main.py | 63 ++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/scripts/main.py b/scripts/main.py index f7692757d..7f1f24b1e 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -301,45 +301,44 @@ while True: except Exception as e: print_to_console("Error: \n", Fore.RED, str(e)) - if not cfg.continuous_mode and next_action_count === 0: + if not cfg.continuous_mode and next_action_count == 0: ### GET USER AUTHORIZATION TO EXECUTE COMMAND ### # Get key press: Prompt the user to press enter to continue or escape # to exit - if next_action_count == 0: - user_input = "" - print_to_console( - "NEXT ACTION: ", - Fore.CYAN, - f"COMMAND = {Fore.CYAN}{command_name}{Style.RESET_ALL} ARGUMENTS = {Fore.CYAN}{arguments}{Style.RESET_ALL}") - print( - f"Enter 'y' to authorise command, 'y -N' to run N continuous commands, 'n' to exit program, or enter feedback for {ai_name}...", - flush=True) - while True: - console_input = input(Fore.MAGENTA + "Input:" + Style.RESET_ALL) - if console_input.lower() == "y": + user_input = "" + print_to_console( + "NEXT ACTION: ", + Fore.CYAN, + f"COMMAND = {Fore.CYAN}{command_name}{Style.RESET_ALL} ARGUMENTS = {Fore.CYAN}{arguments}{Style.RESET_ALL}") + print( + f"Enter 'y' to authorise command, 'y -N' to run N continuous commands, 'n' to exit program, or enter feedback for {ai_name}...", + flush=True) + while True: + console_input = input(Fore.MAGENTA + "Input:" + Style.RESET_ALL) + if console_input.lower() == "y": + user_input = "GENERATE NEXT COMMAND JSON" + break + elif console_input.lower().startswith("y -"): + try: + next_action_count = abs(int(console_input.split(" ")[1])) user_input = "GENERATE NEXT COMMAND JSON" - break - elif console_input.lower().startswith("y -"): - try: - next_action_count = abs(int(console_input.split(" ")[1])) - user_input = "GENERATE NEXT COMMAND JSON" - except ValueError: - print("Invalid input format. Please enter 'y -n' where n is the number of continuous tasks.") - continue - break - elif console_input.lower() == "n": - user_input = "EXIT" - break - else: - user_input = console_input - command_name = "human_feedback" - break + except ValueError: + print("Invalid input format. Please enter 'y -n' where n is the number of continuous tasks.") + continue + break + elif console_input.lower() == "n": + user_input = "EXIT" + break + else: + user_input = console_input + command_name = "human_feedback" + break if user_input == "GENERATE NEXT COMMAND JSON": print_to_console( - "-=-=-=-=-=-=-= COMMAND AUTHORISED BY USER -=-=-=-=-=-=-=", - Fore.MAGENTA, - "") + "-=-=-=-=-=-=-= COMMAND AUTHORISED BY USER -=-=-=-=-=-=-=", + Fore.MAGENTA, + "") elif user_input == "EXIT": print("Exiting...", flush=True) break From b0cd26ac240c884ed817cbec0f8d0aa79b56bf61 Mon Sep 17 00:00:00 2001 From: Mano Bharathi M <88357044+ManoBharathi93@users.noreply.github.com> Date: Wed, 5 Apr 2023 21:30:30 +0530 Subject: [PATCH 11/29] Added Contributing.md file --- CONTRIBUTING.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..73d38d67c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,55 @@ + +To contribute to this GitHub project, you can follow these steps: + +1. Fork the repository you want to contribute to by clicking the "Fork" button on the project page. + +2. Clone the repository to your local machine using the following command: + +``` +git clone https://github.com/Torantulino/Auto-GPT +``` +3. Create a new branch for your changes using the following command: + +``` +git checkout -b "branch-name" +``` +4. Make your changes to the code or documentation. +- Example: Improve User Interface or Add Documentation. + +5. Add the changes to the staging area using the following command: +``` +git add . +``` + +6. Commit the changes with a meaningful commit message using the following command: +``` +git commit -m "your commit message" +``` +7. Push the changes to your forked repository using the following command: +``` +git push origin branch-name +``` +8. Go to the GitHub website and navigate to your forked repository. + +9. Click the "New pull request" button. + +10. Select the branch you just pushed to and the branch you want to merge into on the original repository. + +11. Add a description of your changes and click the "Create pull request" button. + +12. Wait for the project maintainer to review your changes and provide feedback. + +13. Make any necessary changes based on feedback and repeat steps 5-12 until your changes are accepted and merged into the main project. + +14. Once your changes are merged, you can update your forked repository and local copy of the repository with the following commands: + +``` +git fetch upstream +git checkout master +git merge upstream/master +``` +Finally, delete the branch you created with the following command: +``` +git branch -d branch-name +``` +That's it you made it 🐣⭐⭐ From 29a45de2531f014f44501bf815f86f7cd8d7cff9 Mon Sep 17 00:00:00 2001 From: Fabrice Hong Date: Wed, 5 Apr 2023 19:08:53 +0200 Subject: [PATCH 12/29] fix(json-jixer): enclose arguments in a python multi-line string so the fix_json assistant (GPT-3.5) can understand we are providing 2 strings arguments instead of one --- scripts/json_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/json_parser.py b/scripts/json_parser.py index 11ff9ed22..cb05796d4 100644 --- a/scripts/json_parser.py +++ b/scripts/json_parser.py @@ -51,7 +51,7 @@ def fix_and_parse_json(json_str: str, try_to_fix_with_gpt: bool = True): def fix_json(json_str: str, schema: str, debug=False) -> str: # Try to fix the JSON using gpt: function_string = "def fix_json(json_str: str, schema:str=None) -> str:" - args = [json_str, schema] + args = [f"'''{json_str}'''", f"'''{schema}'''"] description_string = """Fixes the provided JSON string to make it parseable and fully complient with the provided schema.\n If an object or field specifed in the schema isn't contained within the correct JSON, it is ommited.\n This function is brilliant at guessing when the format is incorrect.""" # If it doesn't already start with a "`", add one: From a868a39b88a89483bca556f6026e56b3d9c9d991 Mon Sep 17 00:00:00 2001 From: Peter Edwards Date: Wed, 5 Apr 2023 19:44:28 +0200 Subject: [PATCH 13/29] Added functionality to allow the use of GPT on a Microsoft Azure instance --- .env.template | 6 +++++- README.md | 1 + scripts/config.py | 10 ++++++++++ scripts/llm_utils.py | 21 +++++++++++++++------ 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/.env.template b/.env.template index c64d85028..b8e896639 100644 --- a/.env.template +++ b/.env.template @@ -3,4 +3,8 @@ ELEVENLABS_API_KEY=your-elevenlabs-api-key SMART_LLM_MODEL="gpt-4" FAST_LLM_MODEL="gpt-3.5-turbo" GOOGLE_API_KEY= -CUSTOM_SEARCH_ENGINE_ID= \ No newline at end of file +CUSTOM_SEARCH_ENGINE_ID= +USE_AZURE=False +OPENAI_API_BASE=your-base-url-for-azure +OPENAI_API_VERSION=api-version-for-azure +OPENAI_DEPLOYMENT_ID=deployment-id-for-azure \ No newline at end of file diff --git a/README.md b/README.md index d66a60222..6acb0f6c5 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ pip install -r requirements.txt 4. Rename `.env.template` to `.env` and fill in your `OPENAI_API_KEY`. If you plan to use Speech Mode, fill in your `ELEVEN_LABS_API_KEY` as well. - Obtain your OpenAI API key from: https://platform.openai.com/account/api-keys. - Obtain your ElevenLabs API key from: https://elevenlabs.io. You can view your xi-api-key using the "Profile" tab on the website. + - If you want to use GPT on an Azure instance, set `USE_AZURE` to `True` and provide the `OPENAI_API_BASE`, `OPENAI_API_VERSION` and `OPENAI_DEPLOYMENT_ID` values as explained here: https://pypi.org/project/openai/ in the `Microsoft Azure Endpoints` section ## 🔧 Usage diff --git a/scripts/config.py b/scripts/config.py index 766cb94f4..d97ded9ca 100644 --- a/scripts/config.py +++ b/scripts/config.py @@ -34,6 +34,16 @@ class Config(metaclass=Singleton): self.smart_token_limit = int(os.getenv("SMART_TOKEN_LIMIT", 8000)) self.openai_api_key = os.getenv("OPENAI_API_KEY") + self.use_azure = False + self.use_azure = os.getenv("USE_AZURE") + if self.use_azure: + self.openai_api_base = os.getenv("OPENAI_API_BASE") + self.openai_api_version = os.getenv("OPENAI_API_VERSION") + self.openai_deployment_id = os.getenv("OPENAI_DEPLOYMENT_ID") + openai.api_type = "azure" + openai.api_base = self.openai_api_base + openai.api_version = self.openai_api_version + self.elevenlabs_api_key = os.getenv("ELEVENLABS_API_KEY") self.google_api_key = os.getenv("GOOGLE_API_KEY") diff --git a/scripts/llm_utils.py b/scripts/llm_utils.py index 41f396250..5a471ab7a 100644 --- a/scripts/llm_utils.py +++ b/scripts/llm_utils.py @@ -6,11 +6,20 @@ openai.api_key = cfg.openai_api_key # Overly simple abstraction until we create something better def create_chat_completion(messages, model=None, temperature=None, max_tokens=None)->str: - response = openai.ChatCompletion.create( - model=model, - messages=messages, - temperature=temperature, - max_tokens=max_tokens - ) + if cfg.use_azure: + response = openai.ChatCompletion.create( + deployment_id=cfg.openai_deployment_id, + model=model, + messages=messages, + temperature=temperature, + max_tokens=max_tokens + ) + else: + response = openai.ChatCompletion.create( + model=model, + messages=messages, + temperature=temperature, + max_tokens=max_tokens + ) return response.choices[0].message["content"] From ffb95eb0310f67964562853943a512e069432ab1 Mon Sep 17 00:00:00 2001 From: Fabrice Hong Date: Wed, 5 Apr 2023 20:16:28 +0200 Subject: [PATCH 14/29] fix(json_parser): remove the tab character that can be present in the generated json. It makes the json.loads function throw an Invalid JSON error --- scripts/json_parser.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/json_parser.py b/scripts/json_parser.py index 11ff9ed22..f7d607a1b 100644 --- a/scripts/json_parser.py +++ b/scripts/json_parser.py @@ -24,6 +24,7 @@ def fix_and_parse_json(json_str: str, try_to_fix_with_gpt: bool = True): """ try: + json_str = json_str.replace('\t', '') return json.loads(json_str) except Exception as e: # Let's do something manually - sometimes GPT responds with something BEFORE the braces: From 051be4df1007c72d2870f76b47c8ac0856d282cc Mon Sep 17 00:00:00 2001 From: Fabrice Hong Date: Wed, 5 Apr 2023 20:18:06 +0200 Subject: [PATCH 15/29] fix(json_parser): fixing the "TypeError('the JSON object must be str, bytes or bytearray, not dict')" after a json_fix is successful --- scripts/json_parser.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/json_parser.py b/scripts/json_parser.py index 11ff9ed22..763a4789f 100644 --- a/scripts/json_parser.py +++ b/scripts/json_parser.py @@ -67,7 +67,8 @@ def fix_json(json_str: str, schema: str, debug=False) -> str: print(f"Fixed JSON: {result_string}") print("----------- END OF FIX ATTEMPT ----------------") try: - return json.loads(result_string) + json.loads(result_string) # just check the validity + return result_string except: # Get the call stack: # import traceback From 475671d1e846a370a38e2044a73aaa1da417fd9a Mon Sep 17 00:00:00 2001 From: douglas Date: Mon, 3 Apr 2023 20:31:01 -0400 Subject: [PATCH 16/29] Pinecone memory and memory usage tracking --- .env.template | 2 ++ README.md | 29 +++++++++++++++++++ requirements.txt | 3 +- scripts/chat.py | 37 ++++++++++++++++-------- scripts/commands.py | 38 ++----------------------- scripts/config.py | 12 +++++++- scripts/data/prompt.txt | 38 ++++++++++++------------- scripts/main.py | 17 +++++++++-- scripts/memory.py | 62 ++++++++++++++++++++++++++++++++++++++++- 9 files changed, 167 insertions(+), 71 deletions(-) diff --git a/.env.template b/.env.template index c64d85028..9fbffbcd4 100644 --- a/.env.template +++ b/.env.template @@ -1,3 +1,5 @@ +PINECONE_API_KEY=your-pinecone-api-key +PINECONE_ENV=your-pinecone-region OPENAI_API_KEY=your-openai-api-key ELEVENLABS_API_KEY=your-elevenlabs-api-key SMART_LLM_MODEL="gpt-4" diff --git a/README.md b/README.md index d66a60222..3af539c85 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,35 @@ export CUSTOM_SEARCH_ENGINE_ID="YOUR_CUSTOM_SEARCH_ENGINE_ID" ``` +## 🌲 Pinecone API Key Setup + +Pinecone enable a vector based memory so a vast memory can be stored and only relevant memories +are loaded for the agent at any given time. + +1. Go to app.pinecone.io and make an account if you don't already have one. +2. Choose the `Starter` plan to avoid being charged. +3. Find your API key and region under the default project in the left sidebar. + +### Setting up environment variables + For Windows Users: +``` +setx PINECONE_API_KEY "YOUR_GOOGLE_API_KEY" +export PINECONE_ENV="Your region" # something like: us-east4-gcp + +``` +For macOS and Linux users: +``` +export PINECONE_API_KEY="YOUR_GOOGLE_API_KEY" +export PINECONE_ENV="Your region" # something like: us-east4-gcp + +``` + +Or you can set them in the `.env` file. + +## View Memory Usage + +1. View memory usage by using the `--debug` flag :) + ## 💀 Continuous Mode ⚠️ Run the AI **without** user authorisation, 100% automated. Continuous mode is not recommended. diff --git a/requirements.txt b/requirements.txt index 158e93241..2efb371cc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,4 +10,5 @@ tiktoken==0.3.3 gTTS==2.3.1 docker duckduckgo-search -google-api-python-client #(https://developers.google.com/custom-search/v1/overview) +google-api-python-client #(https://developers.google.com/custom-search/v1/overview) +pinecone-client==2.2.1 diff --git a/scripts/chat.py b/scripts/chat.py index 86a70b093..8da074c6b 100644 --- a/scripts/chat.py +++ b/scripts/chat.py @@ -23,6 +23,19 @@ def create_chat_message(role, content): return {"role": role, "content": content} +def generate_context(prompt, relevant_memory, full_message_history, model): + current_context = [ + create_chat_message( + "system", prompt), create_chat_message( + "system", f"Permanent memory: {relevant_memory}")] + + # Add messages from the full message history until we reach the token limit + next_message_to_add_index = len(full_message_history) - 1 + insertion_index = len(current_context) + # Count the currently used tokens + current_tokens_used = token_counter.count_message_tokens(current_context, model) + return next_message_to_add_index, current_tokens_used, insertion_index, current_context + # TODO: Change debug from hardcode to argument def chat_with_ai( @@ -41,7 +54,7 @@ def chat_with_ai( prompt (str): The prompt explaining the rules to the AI. user_input (str): The input from the user. full_message_history (list): The list of all messages sent between the user and the AI. - permanent_memory (list): The list of items in the AI's permanent memory. + permanent_memory (Obj): The memory object containing the permanent memory. token_limit (int): The maximum number of tokens allowed in the API call. Returns: @@ -53,18 +66,20 @@ def chat_with_ai( print(f"Token limit: {token_limit}") send_token_limit = token_limit - 1000 - current_context = [ - create_chat_message( - "system", prompt), create_chat_message( - "system", f"Permanent memory: {permanent_memory}")] + relevant_memory = permanent_memory.get_relevant(str(full_message_history[-5:]), 10) - # Add messages from the full message history until we reach the token limit - next_message_to_add_index = len(full_message_history) - 1 - current_tokens_used = 0 - insertion_index = len(current_context) + if debug: + print('Memory Stats: ', permanent_memory.get_stats()) + + next_message_to_add_index, current_tokens_used, insertion_index, current_context = generate_context( + prompt, relevant_memory, full_message_history, model) + + while current_tokens_used > 2500: + # remove memories until we are under 2500 tokens + relevant_memory = relevant_memory[1:] + next_message_to_add_index, current_tokens_used, insertion_index, current_context = generate_context( + prompt, relevant_memory, full_message_history, model) - # Count the currently used tokens - current_tokens_used = token_counter.count_message_tokens(current_context, model) current_tokens_used += token_counter.count_message_tokens([create_chat_message("user", user_input)], model) # Account for user input (appended later) while next_message_to_add_index >= 0: diff --git a/scripts/commands.py b/scripts/commands.py index f8f96fe72..0a7d27f49 100644 --- a/scripts/commands.py +++ b/scripts/commands.py @@ -1,6 +1,6 @@ import browse import json -import memory as mem +from memory import PineconeMemory import datetime import agent_manager as agents import speak @@ -45,6 +45,7 @@ def get_command(response): def execute_command(command_name, arguments): + memory = PineconeMemory() try: if command_name == "google": @@ -55,11 +56,7 @@ def execute_command(command_name, arguments): else: return google_search(arguments["input"]) elif command_name == "memory_add": - return commit_memory(arguments["string"]) - elif command_name == "memory_del": - return delete_memory(arguments["key"]) - elif command_name == "memory_ovr": - return overwrite_memory(arguments["key"], arguments["string"]) + return memory.add(arguments["string"]) elif command_name == "start_agent": return start_agent( arguments["name"], @@ -176,35 +173,6 @@ def get_hyperlinks(url): return link_list -def commit_memory(string): - _text = f"""Committing memory with string "{string}" """ - mem.permanent_memory.append(string) - return _text - - -def delete_memory(key): - if key >= 0 and key < len(mem.permanent_memory): - _text = "Deleting memory with key " + str(key) - del mem.permanent_memory[key] - print(_text) - return _text - else: - print("Invalid key, cannot delete memory.") - return None - - -def overwrite_memory(key, string): - if int(key) >= 0 and key < len(mem.permanent_memory): - _text = "Overwriting memory with key " + \ - str(key) + " and string " + string - mem.permanent_memory[key] = string - print(_text) - return _text - else: - print("Invalid key, cannot overwrite memory.") - return None - - def shutdown(): print("Shutting down...") quit() diff --git a/scripts/config.py b/scripts/config.py index 766cb94f4..4334f03ac 100644 --- a/scripts/config.py +++ b/scripts/config.py @@ -4,6 +4,7 @@ from dotenv import load_dotenv # Load environment variables from .env file load_dotenv() + class Singleton(type): """ Singleton metaclass for ensuring only one instance of a class. @@ -39,6 +40,9 @@ class Config(metaclass=Singleton): self.google_api_key = os.getenv("GOOGLE_API_KEY") self.custom_search_engine_id = os.getenv("CUSTOM_SEARCH_ENGINE_ID") + self.pinecone_api_key = os.getenv("PINECONE_API_KEY") + self.pinecone_region = os.getenv("PINECONE_ENV") + # Initialize the OpenAI API client openai.api_key = self.openai_api_key @@ -70,4 +74,10 @@ class Config(metaclass=Singleton): self.google_api_key = value def set_custom_search_engine_id(self, value: str): - self.custom_search_engine_id = value \ No newline at end of file + self.custom_search_engine_id = value + + def set_pinecone_api_key(self, value: str): + self.pinecone_api_key = value + + def set_pinecone_region(self, value: str): + self.pinecone_region = value diff --git a/scripts/data/prompt.txt b/scripts/data/prompt.txt index a93e783eb..9f31fad79 100644 --- a/scripts/data/prompt.txt +++ b/scripts/data/prompt.txt @@ -1,29 +1,27 @@ CONSTRAINTS: -1. ~4000 word limit for memory. Your memory is short, so immediately save important information to long term memory and code to files. -2. No user assistance -3. Exclusively use the commands listed in double quotes e.g. "command name" +1. ~4000 word limit for short term memory. Your short term memory is short, so immediately save important information to files. +2. If you are unsure how you previously did something or want to recall past events, thinking about similar events will help you remember. +3. No user assistance +4. Exclusively use the commands listed in double quotes e.g. "command name" COMMANDS: 1. Google Search: "google", args: "input": "" -2. Memory Add: "memory_add", args: "string": "" -3. Memory Delete: "memory_del", args: "key": "" -4. Memory Overwrite: "memory_ovr", args: "key": "", "string": "" -5. Browse Website: "browse_website", args: "url": "", "question": "" -6. Start GPT Agent: "start_agent", args: "name": , "task": "", "prompt": "" -7. Message GPT Agent: "message_agent", args: "key": "", "message": "" -8. List GPT Agents: "list_agents", args: "" -9. Delete GPT Agent: "delete_agent", args: "key": "" -10. Write to file: "write_to_file", args: "file": "", "text": "" -11. Read file: "read_file", args: "file": "" -12. Append to file: "append_to_file", args: "file": "", "text": "" -13. Delete file: "delete_file", args: "file": "" -14. Evaluate Code: "evaluate_code", args: "code": "" -15. Get Improved Code: "improve_code", args: "suggestions": "", "code": "" -16. Write Tests: "write_tests", args: "code": "", "focus": "" -17. Execute Python File: "execute_python_file", args: "file": "" -18. Task Complete (Shutdown): "task_complete", args: "reason": "" +2. Browse Website: "browse_website", args: "url": "", "question": "" +3. Start GPT Agent: "start_agent", args: "name": , "task": "", "prompt": "" +4. Message GPT Agent: "message_agent", args: "key": "", "message": "" +5. List GPT Agents: "list_agents", args: "" +6. Delete GPT Agent: "delete_agent", args: "key": "" +7. Write to file: "write_to_file", args: "file": "", "text": "" +8. Read file: "read_file", args: "file": "" +9. Append to file: "append_to_file", args: "file": "", "text": "" +10. Delete file: "delete_file", args: "file": "" +11. Evaluate Code: "evaluate_code", args: "code": "" +12. Get Improved Code: "improve_code", args: "suggestions": "", "code": "" +13. Write Tests: "write_tests", args: "code": "", "focus": "" +14. Execute Python File: "execute_python_file", args: "file": "" +15. Task Complete (Shutdown): "task_complete", args: "reason": "" RESOURCES: diff --git a/scripts/main.py b/scripts/main.py index 93124234e..2b76842f5 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -1,7 +1,7 @@ import json import random import commands as cmd -import memory as mem +from memory import PineconeMemory import data import chat from colorama import Fore, Style @@ -280,6 +280,13 @@ result = None # Make a constant: user_input = "Determine which next command to use, and respond using the format specified above:" +# Initialize memory and make sure it is empty. +# this is particularly important for indexing and referencing pinecone memory +memory = PineconeMemory() +memory.clear() + +print('Using memory of type: ' + memory.__class__.__name__) + # Interaction Loop while True: # Send message to AI, get response @@ -288,7 +295,7 @@ while True: prompt, user_input, full_message_history, - mem.permanent_memory, + memory, cfg.fast_token_limit) # TODO: This hardcodes the model to use GPT3.5. Make this an argument # print("assistant reply: "+assistant_reply) @@ -349,6 +356,12 @@ while True: else: result = f"Command {command_name} returned: {cmd.execute_command(command_name, arguments)}" + memory_to_add = f"Assistant Reply: {assistant_reply} " \ + f"\nResult: {result} " \ + f"\nHuman Feedback: {user_input} " + + memory.add(memory_to_add) + # Check if there's a result from the command append it to the message # history if result is not None: diff --git a/scripts/memory.py b/scripts/memory.py index 0dc5b7666..0d265a31d 100644 --- a/scripts/memory.py +++ b/scripts/memory.py @@ -1 +1,61 @@ -permanent_memory = [] +from config import Config, Singleton +import pinecone +import openai + +cfg = Config() + + +def get_ada_embedding(text): + text = text.replace("\n", " ") + return openai.Embedding.create(input=[text], model="text-embedding-ada-002")["data"][0]["embedding"] + + +def get_text_from_embedding(embedding): + return openai.Embedding.retrieve(embedding, model="text-embedding-ada-002")["data"][0]["text"] + + +class PineconeMemory(metaclass=Singleton): + def __init__(self): + pinecone_api_key = cfg.pinecone_api_key + pinecone_region = cfg.pinecone_region + pinecone.init(api_key=pinecone_api_key, environment=pinecone_region) + dimension = 1536 + metric = "cosine" + pod_type = "p1" + table_name = "auto-gpt" + # this assumes we don't start with memory. + # for now this works. + # we'll need a more complicated and robust system if we want to start with memory. + self.vec_num = 0 + if table_name not in pinecone.list_indexes(): + pinecone.create_index(table_name, dimension=dimension, metric=metric, pod_type=pod_type) + self.index = pinecone.Index(table_name) + + def add(self, data): + vector = get_ada_embedding(data) + # no metadata here. We may wish to change that long term. + resp = self.index.upsert([(str(self.vec_num), vector, {"raw_text": data})]) + _text = f"Inserting data into memory at index: {self.vec_num}:\n data: {data}" + self.vec_num += 1 + return _text + + def get(self, data): + return self.get_relevant(data, 1) + + def clear(self): + self.index.delete(deleteAll=True) + return "Obliviated" + + def get_relevant(self, data, num_relevant=5): + """ + Returns all the data in the memory that is relevant to the given data. + :param data: The data to compare to. + :param num_relevant: The number of relevant data to return. Defaults to 5 + """ + query_embedding = get_ada_embedding(data) + results = self.index.query(query_embedding, top_k=num_relevant, include_metadata=True) + sorted_results = sorted(results.matches, key=lambda x: x.score) + return [str(item['metadata']["raw_text"]) for item in sorted_results] + + def get_stats(self): + return self.index.describe_index_stats() From 92b6fd9d160b43e962bfba1c2dbc9a6072d4d78b Mon Sep 17 00:00:00 2001 From: David Wurtz Date: Wed, 5 Apr 2023 13:40:09 -0700 Subject: [PATCH 17/29] first draft of github issue templates --- .github/ISSUE_TEMPLATE/1.bug.yml | 39 ++++++++++++++++++++++++++++ .github/ISSUE_TEMPLATE/2.feature.yml | 29 +++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/1.bug.yml create mode 100644 .github/ISSUE_TEMPLATE/2.feature.yml diff --git a/.github/ISSUE_TEMPLATE/1.bug.yml b/.github/ISSUE_TEMPLATE/1.bug.yml new file mode 100644 index 000000000..cf49ab5f8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1.bug.yml @@ -0,0 +1,39 @@ +name: Bug report 🐛 +description: Create a bug report for Auto-GPT. +labels: ['status: needs triage'] +body: + - type: markdown + attributes: + value: | + Please provide a searchable summary of the issue in the title above ⬆️. + + Thanks for contributing by creating an issue! ❤️ + - type: checkboxes + attributes: + label: Duplicates + description: Please [search the history](https://github.com/Torantulino/Auto-GPT/issues) to see if an issue already exists for the same problem. + options: + - label: I have searched the existing issues + required: true + - type: textarea + attributes: + label: Steps to reproduce 🕹 + description: | + **⚠️ Issues that we can't reproduce will be closed.** + - type: textarea + attributes: + label: Current behavior 😯 + description: Describe what happens instead of the expected behavior. + - type: textarea + attributes: + label: Expected behavior 🤔 + description: Describe what should happen. + - type: textarea + attributes: + label: Your prompt 📝 + description: | + Please provide the prompt you are using. You can find your last-used prompt in last_run_ai_settings.yaml. + value: | + ```yaml + # Paste your prompt here + ``` \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/2.feature.yml b/.github/ISSUE_TEMPLATE/2.feature.yml new file mode 100644 index 000000000..0ea882ef6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/2.feature.yml @@ -0,0 +1,29 @@ +name: Feature request 🚀 +description: Suggest a new idea for Auto-GPT. +labels: ['status: needs triage'] +body: + - type: markdown + attributes: + value: | + Please provide a searchable summary of the issue in the title above ⬆️. + + Thanks for contributing by creating an issue! ❤️ + - type: checkboxes + attributes: + label: Duplicates + description: Please [search the history](https://github.com/Torantulino/Auto-GPT/issues) to see if an issue already exists for the same problem. + options: + - label: I have searched the existing issues + required: true + - type: textarea + attributes: + label: Summary 💡 + description: Describe how it should work. + - type: textarea + attributes: + label: Examples 🌈 + description: Provide a link to other implementations, or screenshots of the expected behavior. + - type: textarea + attributes: + label: Motivation 🔦 + description: What are you trying to accomplish? How has the lack of this feature affected you? Providing context helps us come up with a solution that is more useful in the real world. \ No newline at end of file From 62854afe681063d12d915ed6da19ac756af78506 Mon Sep 17 00:00:00 2001 From: Petar Ostojic Date: Wed, 5 Apr 2023 23:44:16 +0200 Subject: [PATCH 18/29] Added fake user-agent headers to browser request. --- scripts/browse.py | 4 ++-- scripts/config.py | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/browse.py b/scripts/browse.py index 510f9c29d..0fda3d7b0 100644 --- a/scripts/browse.py +++ b/scripts/browse.py @@ -6,7 +6,7 @@ from llm_utils import create_chat_completion cfg = Config() def scrape_text(url): - response = requests.get(url) + response = requests.get(url, headers=cfg.user_agent_header) # Check if the response contains an HTTP error if response.status_code >= 400: @@ -40,7 +40,7 @@ def format_hyperlinks(hyperlinks): def scrape_links(url): - response = requests.get(url) + response = requests.get(url, headers=cfg.user_agent_header) # Check if the response contains an HTTP error if response.status_code >= 400: diff --git a/scripts/config.py b/scripts/config.py index 766cb94f4..4a4497694 100644 --- a/scripts/config.py +++ b/scripts/config.py @@ -39,6 +39,11 @@ class Config(metaclass=Singleton): self.google_api_key = os.getenv("GOOGLE_API_KEY") self.custom_search_engine_id = os.getenv("CUSTOM_SEARCH_ENGINE_ID") + # User agent headers to use when browsing web + # Some websites might just completely deny request with an error code if no user agent was found. + self.user_agent_header = {"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36"} + + # Initialize the OpenAI API client openai.api_key = self.openai_api_key From 962fc9a42a8d3e69b3a14f4791cf8a84b67f5504 Mon Sep 17 00:00:00 2001 From: Toran Bruce Richards Date: Thu, 6 Apr 2023 08:07:54 +0100 Subject: [PATCH 19/29] Changes string_key_memory to permanent_memory. Fixes: ```Command memory_ovr returned: Error: module 'memory' has no attribute 'string_key_memory'``` --- scripts/commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/commands.py b/scripts/commands.py index 2adb84cf5..f0e5911e8 100644 --- a/scripts/commands.py +++ b/scripts/commands.py @@ -218,7 +218,7 @@ def overwrite_memory(key, string): elif isinstance(key, str): _text = "Overwriting memory with key " + key + " and string " + string # Overwrite the memory slot with the given string key and string - mem.string_key_memory[key] = string + mem.permanent_memory[key] = string print(_text) return _text else: From 34b6f47f7128c1eb69309beddab6dac65a0d1236 Mon Sep 17 00:00:00 2001 From: Peter Edwards Date: Thu, 6 Apr 2023 09:15:45 +0200 Subject: [PATCH 20/29] Fix for boolean eval from .env --- scripts/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/config.py b/scripts/config.py index d97ded9ca..a2ddd4309 100644 --- a/scripts/config.py +++ b/scripts/config.py @@ -35,7 +35,7 @@ class Config(metaclass=Singleton): self.openai_api_key = os.getenv("OPENAI_API_KEY") self.use_azure = False - self.use_azure = os.getenv("USE_AZURE") + self.use_azure = os.getenv("USE_AZURE") == 'True' if self.use_azure: self.openai_api_base = os.getenv("OPENAI_API_BASE") self.openai_api_version = os.getenv("OPENAI_API_VERSION") From dcc29a5568a9d026648657859a8ece1043430952 Mon Sep 17 00:00:00 2001 From: Toran Bruce Richards Date: Thu, 6 Apr 2023 08:29:28 +0100 Subject: [PATCH 21/29] Fixes broken reference to speak.say_text --- scripts/commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/commands.py b/scripts/commands.py index f0e5911e8..b0b2f3a6d 100644 --- a/scripts/commands.py +++ b/scripts/commands.py @@ -268,7 +268,7 @@ def message_agent(key, message): # Speak response if cfg.speak_mode: - say.speak(agent_response) + speak.say_text(agent_response, 1) return agent_response From a55a64c1c9a8bc1ed6ea72f1bf42dbca375247ee Mon Sep 17 00:00:00 2001 From: Toran Bruce Richards Date: Thu, 6 Apr 2023 08:46:57 +0100 Subject: [PATCH 22/29] Adds voice index back in. Agents now have a different voice again. --- scripts/speak.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/speak.py b/scripts/speak.py index f6242a37d..13517d366 100644 --- a/scripts/speak.py +++ b/scripts/speak.py @@ -42,7 +42,7 @@ def say_text(text, voice_index=0): if not cfg.elevenlabs_api_key: gtts_speech(text) else: - success = eleven_labs_speech(text) + success = eleven_labs_speech(text, voice_index) if not success: gtts_speech(text) From b8f2dd59c8f54ce7efa068b50117212a121b11ac Mon Sep 17 00:00:00 2001 From: Toran Bruce Richards Date: Thu, 6 Apr 2023 09:23:03 +0100 Subject: [PATCH 23/29] Fixes "/" search not working. --- scripts/file_operations.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/file_operations.py b/scripts/file_operations.py index f3cd3a458..90c9a1e4d 100644 --- a/scripts/file_operations.py +++ b/scripts/file_operations.py @@ -61,7 +61,11 @@ def delete_file(filename): def search_files(directory): found_files = [] - search_directory = safe_join(working_directory, directory) + + if directory == "" or directory == "/": + search_directory = working_directory + else: + search_directory = safe_join(working_directory, directory) for root, _, files in os.walk(search_directory): for file in files: From a45ed8c42a86ca15387c6b4ec6575254e194e6a1 Mon Sep 17 00:00:00 2001 From: Toran Bruce Richards Date: Thu, 6 Apr 2023 11:46:13 +0100 Subject: [PATCH 24/29] Moves last_run_ai_settings.yaml to root so it's easier to find and use. --- scripts/ai_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ai_config.py b/scripts/ai_config.py index 945fcfb23..678d3ab99 100644 --- a/scripts/ai_config.py +++ b/scripts/ai_config.py @@ -9,7 +9,7 @@ class AIConfig: self.ai_goals = ai_goals # Soon this will go in a folder where it remembers more stuff about the run(s) - SAVE_FILE = "last_run_ai_settings.yaml" + SAVE_FILE = "../last_run_ai_settings.yaml" @classmethod def load(cls, config_file=SAVE_FILE): From 61685c6f0b04064447125b42732b776e4180cba3 Mon Sep 17 00:00:00 2001 From: Toran Bruce Richards Date: Thu, 6 Apr 2023 11:47:12 +0100 Subject: [PATCH 25/29] Renames last_run_ai_settings to ai_settings. Hopefully this helps people realise they can edit it themselves. --- scripts/ai_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ai_config.py b/scripts/ai_config.py index 678d3ab99..2f4327486 100644 --- a/scripts/ai_config.py +++ b/scripts/ai_config.py @@ -9,7 +9,7 @@ class AIConfig: self.ai_goals = ai_goals # Soon this will go in a folder where it remembers more stuff about the run(s) - SAVE_FILE = "../last_run_ai_settings.yaml" + SAVE_FILE = "../ai_settings.yaml" @classmethod def load(cls, config_file=SAVE_FILE): From a83f148878bb841dcc05f70fc5da6f859688a9c0 Mon Sep 17 00:00:00 2001 From: Toran Bruce Richards Date: Thu, 6 Apr 2023 11:53:47 +0100 Subject: [PATCH 26/29] Adds default ai_settings file. --- ai_settings.yaml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 ai_settings.yaml diff --git a/ai_settings.yaml b/ai_settings.yaml new file mode 100644 index 000000000..1d29bd698 --- /dev/null +++ b/ai_settings.yaml @@ -0,0 +1,7 @@ +ai_goals: +- Increase net worth +- Grow Twitter Account +- Develop and manage multiple businesses autonomously +ai_name: Entrepreneur-GPT +ai_role: an AI designed to autonomously develop and run businesses with the sole goal + of increasing your net worth. From c41acbad4a4679db687d558deb789850e1c754ad Mon Sep 17 00:00:00 2001 From: Toran Bruce Richards Date: Thu, 6 Apr 2023 11:53:58 +0100 Subject: [PATCH 27/29] Tweaks default settings. --- ai_settings.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ai_settings.yaml b/ai_settings.yaml index 1d29bd698..b37ba849f 100644 --- a/ai_settings.yaml +++ b/ai_settings.yaml @@ -1,7 +1,7 @@ ai_goals: -- Increase net worth -- Grow Twitter Account -- Develop and manage multiple businesses autonomously +- Increase net worth. +- Develop and manage multiple businesses autonomously. +- Play to your strengths as a Large Language Model. ai_name: Entrepreneur-GPT ai_role: an AI designed to autonomously develop and run businesses with the sole goal of increasing your net worth. From 89ab8397bf0185a5991cb02209a3fd42e8c4fa20 Mon Sep 17 00:00:00 2001 From: Toran Bruce Richards Date: Thu, 6 Apr 2023 11:56:28 +0100 Subject: [PATCH 28/29] Ignores ai_settings.yaml --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 55a21afeb..7091a8723 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,5 @@ package-lock.json auto_gpt_workspace/* *.mpeg .env -last_run_ai_settings.yaml -outputs/* \ No newline at end of file +outputs/* +ai_settings.yaml \ No newline at end of file From 5987d6297b29988349a9aa05388d9612d58c3016 Mon Sep 17 00:00:00 2001 From: Toran Bruce Richards Date: Thu, 6 Apr 2023 12:20:57 +0100 Subject: [PATCH 29/29] Update CONTRIBUTING.md --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 73d38d67c..001d55470 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,6 +16,7 @@ git checkout -b "branch-name" 4. Make your changes to the code or documentation. - Example: Improve User Interface or Add Documentation. + 5. Add the changes to the staging area using the following command: ``` git add .