From a4f130ff602b89e1dac571362b34db5b8cb41429 Mon Sep 17 00:00:00 2001 From: slavakurilyak Date: Tue, 4 Apr 2023 19:28:13 -0500 Subject: [PATCH 01/12] Improve security and robustness in browse.py --- scripts/browse.py | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/scripts/browse.py b/scripts/browse.py index 510f9c29d5..d07f269978 100644 --- a/scripts/browse.py +++ b/scripts/browse.py @@ -2,15 +2,44 @@ import requests from bs4 import BeautifulSoup from config import Config from llm_utils import create_chat_completion +from urllib.parse import urlparse, urljoin cfg = Config() -def scrape_text(url): - response = requests.get(url) +# Function to check if the URL is valid +def is_valid_url(url): + try: + result = urlparse(url) + return all([result.scheme, result.netloc]) + except ValueError: + return False - # Check if the response contains an HTTP error - if response.status_code >= 400: - return "Error: HTTP " + str(response.status_code) + " error" +# Function to sanitize the URL +def sanitize_url(url): + return urljoin(url, urlparse(url).path) + +# Function to make a request with a specified timeout and handle exceptions +def make_request(url, timeout=10): + try: + response = requests.get(url, timeout=timeout) + response.raise_for_status() + return response + except requests.exceptions.RequestException as e: + return "Error: " + str(e) + +def scrape_text(url): + # Validate the input URL + if not is_valid_url(url): + return "Error: Invalid URL" + + # Sanitize the input URL + sanitized_url = sanitize_url(url) + + # Make the request with a timeout and handle exceptions + response = make_request(sanitized_url) + + if isinstance(response, str): + return response soup = BeautifulSoup(response.text, "html.parser") From aa786e1b41841604e00a451d7304cdcfc6795e2c Mon Sep 17 00:00:00 2001 From: Chris Cheney Date: Sat, 8 Apr 2023 21:30:36 -0500 Subject: [PATCH 02/12] command_name null check before calling .lower() fixes #534 `AttributeError: 'NoneType' object has no attribute 'lower'` --- scripts/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.py b/scripts/main.py index 17385bf339..4d68b4506d 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -358,7 +358,7 @@ while True: f"COMMAND = {Fore.CYAN}{command_name}{Style.RESET_ALL} ARGUMENTS = {Fore.CYAN}{arguments}{Style.RESET_ALL}") # Execute command - if command_name.lower() == "error": + if command_name is not None and command_name.lower() == "error": result = f"Command {command_name} threw the following error: " + arguments elif command_name == "human_feedback": result = f"Human feedback: {user_input}" From a504f0bdd33b1218488f40a8bfc763984ca6ee47 Mon Sep 17 00:00:00 2001 From: Kari Ahdan Date: Mon, 10 Apr 2023 16:43:06 +0300 Subject: [PATCH 03/12] Add required env parameters for azure usage --- .env.template | 2 ++ README.md | 2 +- scripts/config.py | 2 ++ scripts/llm_utils.py | 2 +- scripts/memory/base.py | 8 ++++++-- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.env.template b/.env.template index 525cd61c5f..cdf8e28c36 100644 --- a/.env.template +++ b/.env.template @@ -10,5 +10,7 @@ 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 +AZURE_CHAT_DEPLOYMENT_ID=deployment-id-for-azure-chat-ai +AZURE_EMBEDDINGS_DEPLOYMENT_ID=deployment-id-for-azure-embeddigs-ai IMAGE_PROVIDER=dalle HUGGINGFACE_API_TOKEN= \ No newline at end of file diff --git a/README.md b/README.md index 118131e463..d93c598ff6 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,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://beta.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 + - 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. Additionally you need separate deployments for both embeddings and chat. Add their ID values to `AZURE_CHAT_DEPLOYMENT_ID` and `AZURE_EMBEDDINGS_DEPLOYMENT_ID` respectively ## 🔧 Usage diff --git a/scripts/config.py b/scripts/config.py index 1eb74b2bc7..7f446cd16c 100644 --- a/scripts/config.py +++ b/scripts/config.py @@ -49,6 +49,8 @@ class Config(metaclass=Singleton): 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") + self.azure_chat_deployment_id = os.getenv("AZURE_CHAT_DEPLOYMENT_ID") + self.azure_embeddigs_deployment_id = os.getenv("AZURE_EMBEDDINGS_DEPLOYMENT_ID") openai.api_type = "azure" openai.api_base = self.openai_api_base openai.api_version = self.openai_api_version diff --git a/scripts/llm_utils.py b/scripts/llm_utils.py index 94ba5f1316..3fb348f07b 100644 --- a/scripts/llm_utils.py +++ b/scripts/llm_utils.py @@ -9,7 +9,7 @@ def create_chat_completion(messages, model=None, temperature=None, max_tokens=No """Create a chat completion using the OpenAI API""" if cfg.use_azure: response = openai.ChatCompletion.create( - deployment_id=cfg.openai_deployment_id, + deployment_id=cfg.azure_chat_deployment_id, model=model, messages=messages, temperature=temperature, diff --git a/scripts/memory/base.py b/scripts/memory/base.py index d7ab7fcf1f..bb22963a8d 100644 --- a/scripts/memory/base.py +++ b/scripts/memory/base.py @@ -1,12 +1,16 @@ """Base class for memory providers.""" import abc -from config import AbstractSingleton +from config import AbstractSingleton, Config 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"] + if cfg.use_azure: + return openai.Embedding.create(input=[text], engine=cfg.azure_embeddigs_deployment_id, model="text-embedding-ada-002")["data"][0]["embedding"] + else: + return openai.Embedding.create(input=[text], model="text-embedding-ada-002")["data"][0]["embedding"] class MemoryProviderSingleton(AbstractSingleton): From 334a1d2632da5fbc4c2a66c4171e361e94b07227 Mon Sep 17 00:00:00 2001 From: keenborder786 <21110290@lums.edu.pk> Date: Tue, 11 Apr 2023 01:23:59 +0500 Subject: [PATCH 04/12] [feat]: Added a argument which allows gpt4 only mode and configure the fast_llm_model accordingly --- scripts/main.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/main.py b/scripts/main.py index 3dfcaa157e..6fc6a03011 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -265,6 +265,7 @@ def parse_arguments(): parser.add_argument('--speak', action='store_true', help='Enable Speak Mode') parser.add_argument('--debug', action='store_true', help='Enable Debug Mode') parser.add_argument('--gpt3only', action='store_true', help='Enable GPT3.5 Only Mode') + parser.add_argument('--gpt4only', action='store_true', help='Enable GPT4 Only Mode') args = parser.parse_args() if args.continuous: @@ -286,6 +287,10 @@ def parse_arguments(): if args.gpt3only: print_to_console("GPT3.5 Only Mode: ", Fore.GREEN, "ENABLED") cfg.set_smart_llm_model(cfg.fast_llm_model) + + if args.gpt4only: + print_to_console("GPT4 Only Mode: ", Fore.GREEN, "ENABLED") + cfg.set_fast_llm_model(cfg.smart_llm_model) if args.debug: print_to_console("Debug Mode: ", Fore.GREEN, "ENABLED") From c0d2df6acc6d6663ed4935f57b7bf63819c1a44f Mon Sep 17 00:00:00 2001 From: blankster Date: Tue, 11 Apr 2023 01:59:43 +0200 Subject: [PATCH 05/12] Update .gitignore Ignoring IntelliJ Project Settings (e.g, Pycharm) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0edd3047d3..854b1401d1 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,5 @@ venv/* outputs/* ai_settings.yaml .vscode +.idea/* auto-gpt.json From d4bb3de91bab4a6bb4a2c7e8124016f31645c20e Mon Sep 17 00:00:00 2001 From: Joseph Bisaillon Date: Mon, 10 Apr 2023 21:02:13 -0400 Subject: [PATCH 06/12] Add OpenAPI Key Link to README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 749c879151..70ee85e1cd 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ Your support is greatly appreciated ## 📋 Requirements - [Python 3.8 or later](https://www.tutorialspoint.com/how-to-install-python-in-windows) -- OpenAI API key +- [OpenAI API key](https://platform.openai.com/account/api-keys) - [PINECONE API key](https://www.pinecone.io/) Optional: From 2b67ede6b36668a7b22cd9f35ce8b9e5c710bc49 Mon Sep 17 00:00:00 2001 From: honeykjoule Date: Tue, 11 Apr 2023 04:31:38 +0000 Subject: [PATCH 07/12] update gitignore venv/* to *venv/* --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2d60380168..287c937fa7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ package-lock.json auto_gpt_workspace/* *.mpeg .env -venv/* +*venv/* outputs/* ai_settings.yaml .vscode From 9725c727da05c1a2a402216013d0564d100c48ec Mon Sep 17 00:00:00 2001 From: JZ Date: Tue, 11 Apr 2023 16:22:26 -0700 Subject: [PATCH 08/12] Changed spelling from "GTP" to "GPT". Also removed the 3 as this can run on GPT4. --- scripts/agent_manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/agent_manager.py b/scripts/agent_manager.py index e6bf3b8632..a0e5f16482 100644 --- a/scripts/agent_manager.py +++ b/scripts/agent_manager.py @@ -13,7 +13,7 @@ def create_agent(task, prompt, model): messages = [{"role": "user", "content": prompt}, ] - # Start GTP3 instance + # Start GPT instance agent_reply = create_chat_completion( model=model, messages=messages, @@ -41,7 +41,7 @@ def message_agent(key, message): # Add user message to message history before sending to agent messages.append({"role": "user", "content": message}) - # Start GTP3 instance + # Start GPT instance agent_reply = create_chat_completion( model=model, messages=messages, From bc6f34d7dc70771273992e2377d890bfe91c6c71 Mon Sep 17 00:00:00 2001 From: vadi Date: Wed, 12 Apr 2023 16:32:13 +1000 Subject: [PATCH 09/12] Fixes #803 - Brings back debug mode - Replaces all calls from cfg.debug to cfg.debug_mode that was updated on 5b2d6010dc59bab1026d13bfcd75b37618e573b9 - Remove unnecessary config instance at main.py --- scripts/chat.py | 6 +++--- scripts/json_parser.py | 2 +- scripts/main.py | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/chat.py b/scripts/chat.py index 23e5b50149..30f7603c76 100644 --- a/scripts/chat.py +++ b/scripts/chat.py @@ -64,14 +64,14 @@ def chat_with_ai( model = cfg.fast_llm_model # TODO: Change model from hardcode to argument # Reserve 1000 tokens for the response - if cfg.debug: + if cfg.debug_mode: print(f"Token limit: {token_limit}") send_token_limit = token_limit - 1000 relevant_memory = permanent_memory.get_relevant(str(full_message_history[-5:]), 10) - if cfg.debug: + if cfg.debug_mode: print('Memory Stats: ', permanent_memory.get_stats()) next_message_to_add_index, current_tokens_used, insertion_index, current_context = generate_context( @@ -110,7 +110,7 @@ def chat_with_ai( # assert tokens_remaining >= 0, "Tokens remaining is negative. This should never happen, please submit a bug report at https://www.github.com/Torantulino/Auto-GPT" # Debug print the current context - if cfg.debug: + if cfg.debug_mode: print(f"Token limit: {token_limit}") print(f"Send Token Count: {current_tokens_used}") print(f"Tokens remaining for response: {tokens_remaining}") diff --git a/scripts/json_parser.py b/scripts/json_parser.py index 8c17dfa252..1d93b10926 100644 --- a/scripts/json_parser.py +++ b/scripts/json_parser.py @@ -91,7 +91,7 @@ def fix_json(json_str: str, schema: str) -> str: result_string = call_ai_function( function_string, args, description_string, model=cfg.fast_llm_model ) - if cfg.debug: + if cfg.debug_mode: print("------------ JSON FIX ATTEMPT ---------------") print(f"Original JSON: {json_str}") print("-----------") diff --git a/scripts/main.py b/scripts/main.py index d84e150850..40cad2b839 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -266,6 +266,7 @@ def prompt_user(): def parse_arguments(): """Parses the arguments passed to the script""" global cfg + cfg.set_debug_mode(False) cfg.set_continuous_mode(False) cfg.set_speak_mode(False) @@ -292,6 +293,9 @@ def parse_arguments(): print_to_console("GPT3.5 Only Mode: ", Fore.GREEN, "ENABLED") cfg.set_smart_llm_model(cfg.fast_llm_model) + if args.debug: + print_to_console("Debug Mode: ", Fore.GREEN, "ENABLED") + cfg.set_debug_mode(True) # TODO: fill in llm values here From 94441ee63bc55390f670483b965d01bbe712a961 Mon Sep 17 00:00:00 2001 From: Manal Arora <42407286+manalarora@users.noreply.github.com> Date: Wed, 12 Apr 2023 14:37:50 +0530 Subject: [PATCH 10/12] correcting the clone command in contributing.md (#927) * correcting the clone command in contributing.md * removing extra newlines added in previous commit removing extra newlines added in previous commit --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 09a604eba9..0529cbd949 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,7 @@ To contribute to this GitHub project, you can follow these steps: 2. Clone the repository to your local machine using the following command: ``` -git clone https://github.com/Torantulino/Auto-GPT +git clone https://github.com//Auto-GPT ``` 3. Create a new branch for your changes using the following command: From 16b37fff1d65a7d998c39aeab9764973d76ea731 Mon Sep 17 00:00:00 2001 From: sarango Date: Mon, 10 Apr 2023 08:07:03 -0500 Subject: [PATCH 11/12] Fix to LocalCache add method, created integration test for it --- scripts/memory/local.py | 2 +- tests/integration/memory_tests.py | 49 +++++++++++++++++++++++++++++++ tests/{ => unit}/json_tests.py | 0 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 tests/integration/memory_tests.py rename tests/{ => unit}/json_tests.py (100%) diff --git a/scripts/memory/local.py b/scripts/memory/local.py index 8dc90021ff..372b59c442 100644 --- a/scripts/memory/local.py +++ b/scripts/memory/local.py @@ -54,8 +54,8 @@ class LocalCache(MemoryProviderSingleton): vector = vector[np.newaxis, :] self.data.embeddings = np.concatenate( [ - vector, self.data.embeddings, + vector, ], axis=0, ) diff --git a/tests/integration/memory_tests.py b/tests/integration/memory_tests.py new file mode 100644 index 0000000000..ed444d9196 --- /dev/null +++ b/tests/integration/memory_tests.py @@ -0,0 +1,49 @@ +import unittest +import random +import string +import sys +from pathlib import Path +# Add the parent directory of the 'scripts' folder to the Python path +sys.path.append(str(Path(__file__).resolve().parent.parent.parent / 'scripts')) +from config import Config +from memory.local import LocalCache + +class TestLocalCache(unittest.TestCase): + + def random_string(self, length): + return ''.join(random.choice(string.ascii_letters) for _ in range(length)) + + def setUp(self): + cfg = cfg = Config() + self.cache = LocalCache(cfg) + self.cache.clear() + + # Add example texts to the cache + self.example_texts = [ + 'The quick brown fox jumps over the lazy dog', + 'I love machine learning and natural language processing', + 'The cake is a lie, but the pie is always true', + 'ChatGPT is an advanced AI model for conversation' + ] + + for text in self.example_texts: + self.cache.add(text) + + # Add some random strings to test noise + for _ in range(5): + self.cache.add(self.random_string(10)) + + def test_get_relevant(self): + query = "I'm interested in artificial intelligence and NLP" + k = 3 + relevant_texts = self.cache.get_relevant(query, k) + + print(f"Top {k} relevant texts for the query '{query}':") + for i, text in enumerate(relevant_texts, start=1): + print(f"{i}. {text}") + + self.assertEqual(len(relevant_texts), k) + self.assertIn(self.example_texts[1], relevant_texts) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/json_tests.py b/tests/unit/json_tests.py similarity index 100% rename from tests/json_tests.py rename to tests/unit/json_tests.py From 434f27fb51f1edd32be46cc2f8d5bae69e311497 Mon Sep 17 00:00:00 2001 From: Samuel Reed Date: Mon, 10 Apr 2023 09:10:26 -0400 Subject: [PATCH 12/12] Fix various JSON input bugs in correction By not having correct_json(json_str) in the try/except, it was still easily possible to throw Invalid JSON errors. When responses were received with no JSON at all, parsing would fail on attempting to locate the braces. --- scripts/json_parser.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/json_parser.py b/scripts/json_parser.py index e96c43f664..5524425559 100644 --- a/scripts/json_parser.py +++ b/scripts/json_parser.py @@ -26,7 +26,7 @@ JSON_SCHEMA = """ """ -def fix_and_parse_json( +def fix_and_parse_json( json_str: str, try_to_fix_with_gpt: bool = True ) -> Union[str, Dict[Any, Any]]: @@ -35,8 +35,8 @@ def fix_and_parse_json( json_str = json_str.replace('\t', '') return json.loads(json_str) except json.JSONDecodeError as _: # noqa: F841 - json_str = correct_json(json_str) try: + json_str = correct_json(json_str) return json.loads(json_str) except json.JSONDecodeError as _: # noqa: F841 pass @@ -53,6 +53,7 @@ def fix_and_parse_json( last_brace_index = json_str.rindex("}") json_str = json_str[:last_brace_index+1] return json.loads(json_str) + # Can throw a ValueError if there is no "{" or "}" in the json_str except (json.JSONDecodeError, ValueError) as e: # noqa: F841 if try_to_fix_with_gpt: print("Warning: Failed to parse AI output, attempting to fix."