From c932087997456bdbb4c07661aaa648dd861263f1 Mon Sep 17 00:00:00 2001 From: Gull Man Date: Wed, 12 Apr 2023 12:13:18 +0200 Subject: [PATCH 01/16] add encoding to open file --- scripts/file_operations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/file_operations.py b/scripts/file_operations.py index c6066ef93029..59b3a0d054ab 100644 --- a/scripts/file_operations.py +++ b/scripts/file_operations.py @@ -38,7 +38,7 @@ def write_to_file(filename, text): directory = os.path.dirname(filepath) if not os.path.exists(directory): os.makedirs(directory) - with open(filepath, "w") as f: + with open(filepath, "w", encoding='utf-8') as f: f.write(text) return "File written to successfully." except Exception as e: From db9f8a2749e5f44585b2ad7514f346e7a5a9a26b Mon Sep 17 00:00:00 2001 From: Kory Becker Date: Wed, 12 Apr 2023 22:14:51 -0400 Subject: [PATCH 02/16] Added config option for OPENAI_API_TYPE=azure_ad --- scripts/config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/config.py b/scripts/config.py index 255587d76fc0..4f8961264dee 100644 --- a/scripts/config.py +++ b/scripts/config.py @@ -51,7 +51,8 @@ def __init__(self): self.openai_deployment_id = os.getenv("OPENAI_AZURE_DEPLOYMENT_ID") self.azure_chat_deployment_id = os.getenv("OPENAI_AZURE_CHAT_DEPLOYMENT_ID") self.azure_embeddigs_deployment_id = os.getenv("OPENAI_AZURE_EMBEDDINGS_DEPLOYMENT_ID") - openai.api_type = "azure" + openai.api_type = os.getenv("OPENAI_API_TYPE", "azure") + openai.api_base = self.openai_api_base openai.api_version = self.openai_api_version From 1546c244419e1531d72cb3b558e48e9eda6b5aa0 Mon Sep 17 00:00:00 2001 From: Ishwor Panta <31570025+ishworpanta10@users.noreply.github.com> Date: Thu, 13 Apr 2023 10:52:35 +0545 Subject: [PATCH 03/16] Update serial in Installation step updated serial in Installation step from 1 rather than from 0. --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c9ef9d5c5955..4bdc97c6e610 100644 --- a/README.md +++ b/README.md @@ -70,32 +70,32 @@ Optional: To install Auto-GPT, follow these steps: -0. Make sure you have all the **requirements** above, if not, install/get them. +1. Make sure you have all the **requirements** above, if not, install/get them. _The following commands should be executed in a CMD, Bash or Powershell window. To do this, go to a folder on your computer, click in the folder path at the top and type CMD, then press enter._ -1. Clone the repository: +2. Clone the repository: For this step you need Git installed, but you can just download the zip file instead by clicking the button at the top of this page ☝️ ``` git clone https://github.com/Torantulino/Auto-GPT.git ``` -2. Navigate to the project directory: +3. Navigate to the project directory: _(Type this into your CMD window, you're aiming to navigate the CMD window to the repository you just downloaded)_ ``` cd 'Auto-GPT' ``` -3. Install the required dependencies: +4. Install the required dependencies: _(Again, type this into your CMD window)_ ``` 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. +5. 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. @@ -344,4 +344,4 @@ flake8 scripts/ tests/ # Or, if you want to run flake8 with the same configuration as the CI: flake8 scripts/ tests/ --select E303,W293,W291,W292,E305 -``` \ No newline at end of file +``` From 947d27a9edcc1ab6116cf8eed1f5e50a0d416dbf Mon Sep 17 00:00:00 2001 From: Drikus Roor Date: Wed, 12 Apr 2023 22:42:15 +0200 Subject: [PATCH 04/16] docs: Update README.md with the flake8 command used in the CI --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 87b5d1be6fc7..b5d9ac4ec580 100644 --- a/README.md +++ b/README.md @@ -342,7 +342,9 @@ coverage run -m unittest discover tests ## Run linter -This project uses [flake8](https://flake8.pycqa.org/en/latest/) for linting. To run the linter, run the following command: +This project uses [flake8](https://flake8.pycqa.org/en/latest/) for linting. We currently use the following rules: `E303,W293,W291,W292,E305`. See the [flake8 rules](https://www.flake8rules.com/) for more information. + +To run the linter, run the following command: ``` flake8 scripts/ tests/ From 8ff36bb8ba5663aa7ee12f365fc89fd101d9aee6 Mon Sep 17 00:00:00 2001 From: Drikus Roor Date: Wed, 12 Apr 2023 22:55:20 +0200 Subject: [PATCH 05/16] lint: Add rule E231 to the flake8 linting job --- .github/workflows/ci.yml | 2 +- README.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 070df794b94a..de2140057684 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: - name: Lint with flake8 continue-on-error: false - run: flake8 scripts/ tests/ --select E303,W293,W291,W292,E305 + run: flake8 scripts/ tests/ --select E303,W293,W291,W292,E305,E231 - name: Run unittest tests with coverage run: | diff --git a/README.md b/README.md index b5d9ac4ec580..82d489b13e9e 100644 --- a/README.md +++ b/README.md @@ -342,7 +342,7 @@ coverage run -m unittest discover tests ## Run linter -This project uses [flake8](https://flake8.pycqa.org/en/latest/) for linting. We currently use the following rules: `E303,W293,W291,W292,E305`. See the [flake8 rules](https://www.flake8rules.com/) for more information. +This project uses [flake8](https://flake8.pycqa.org/en/latest/) for linting. We currently use the following rules: `E303,W293,W291,W292,E305,E231`. See the [flake8 rules](https://www.flake8rules.com/) for more information. To run the linter, run the following command: @@ -350,5 +350,5 @@ To run the linter, run the following command: flake8 scripts/ tests/ # Or, if you want to run flake8 with the same configuration as the CI: -flake8 scripts/ tests/ --select E303,W293,W291,W292,E305 -``` +flake8 scripts/ tests/ --select E303,W293,W291,W292,E305,E231 +``` \ No newline at end of file From 4afd0a3714e3fdc22a0dc16920869f3df8fa1d5e Mon Sep 17 00:00:00 2001 From: Drikus Roor Date: Wed, 12 Apr 2023 22:55:42 +0200 Subject: [PATCH 06/16] lint: Fix E231 flake8 linting errors --- scripts/config.py | 2 +- tests/test_json_parser.py | 4 ++-- tests/unit/json_tests.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/config.py b/scripts/config.py index ebf1b08b22f7..01505b22dd84 100644 --- a/scripts/config.py +++ b/scripts/config.py @@ -73,7 +73,7 @@ def __init__(self): # 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"} + 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"} self.redis_host = os.getenv("REDIS_HOST", "localhost") self.redis_port = os.getenv("REDIS_PORT", "6379") self.redis_password = os.getenv("REDIS_PASSWORD", "") diff --git a/tests/test_json_parser.py b/tests/test_json_parser.py index b8cb2680d40f..0f2c6488c626 100644 --- a/tests/test_json_parser.py +++ b/tests/test_json_parser.py @@ -50,7 +50,7 @@ def test_invalid_json_leading_sentence_with_gpt(self): good_obj = { "command": { "name": "browse_website", - "args":{ + "args": { "url": "https://github.com/Torantulino/Auto-GPT" } }, @@ -89,7 +89,7 @@ def test_invalid_json_leading_sentence_with_gpt(self): good_obj = { "command": { "name": "browse_website", - "args":{ + "args": { "url": "https://github.com/Torantulino/Auto-GPT" } }, diff --git a/tests/unit/json_tests.py b/tests/unit/json_tests.py index 1edbaeaf3652..3320ad5e9ab5 100644 --- a/tests/unit/json_tests.py +++ b/tests/unit/json_tests.py @@ -52,7 +52,7 @@ def test_invalid_json_leading_sentence_with_gpt(self): good_obj = { "command": { "name": "browse_website", - "args":{ + "args": { "url": "https://github.com/Torantulino/Auto-GPT" } }, @@ -91,7 +91,7 @@ def test_invalid_json_leading_sentence_with_gpt(self): good_obj = { "command": { "name": "browse_website", - "args":{ + "args": { "url": "https://github.com/Torantulino/Auto-GPT" } }, From 04dc0f7149d29ea284e55ff19b0178db2b706a40 Mon Sep 17 00:00:00 2001 From: Drikus Roor Date: Wed, 12 Apr 2023 23:04:59 +0200 Subject: [PATCH 07/16] lint: Add flake8 rule E302 to the flake8 workflow job --- .github/workflows/ci.yml | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de2140057684..0b90b55d34fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: - name: Lint with flake8 continue-on-error: false - run: flake8 scripts/ tests/ --select E303,W293,W291,W292,E305,E231 + run: flake8 scripts/ tests/ --select E303,W293,W291,W292,E305,E231,E302 - name: Run unittest tests with coverage run: | diff --git a/README.md b/README.md index 82d489b13e9e..51649bd66a9d 100644 --- a/README.md +++ b/README.md @@ -342,7 +342,7 @@ coverage run -m unittest discover tests ## Run linter -This project uses [flake8](https://flake8.pycqa.org/en/latest/) for linting. We currently use the following rules: `E303,W293,W291,W292,E305,E231`. See the [flake8 rules](https://www.flake8rules.com/) for more information. +This project uses [flake8](https://flake8.pycqa.org/en/latest/) for linting. We currently use the following rules: `E303,W293,W291,W292,E305,E231,E302`. See the [flake8 rules](https://www.flake8rules.com/) for more information. To run the linter, run the following command: @@ -350,5 +350,5 @@ To run the linter, run the following command: flake8 scripts/ tests/ # Or, if you want to run flake8 with the same configuration as the CI: -flake8 scripts/ tests/ --select E303,W293,W291,W292,E305,E231 +flake8 scripts/ tests/ --select E303,W293,W291,W292,E305,E231,E302 ``` \ No newline at end of file From d1ea6cf002fb9b7747221666ba5593108cd48984 Mon Sep 17 00:00:00 2001 From: Drikus Roor Date: Wed, 12 Apr 2023 23:05:14 +0200 Subject: [PATCH 08/16] lint: Fix all E302 linting errors --- scripts/agent_manager.py | 1 + scripts/ai_config.py | 1 + scripts/browse.py | 16 ++++++++++++++++ scripts/call_ai_function.py | 2 ++ scripts/chat.py | 1 + scripts/commands.py | 3 +++ scripts/data.py | 1 + scripts/file_operations.py | 1 + scripts/image_gen.py | 1 + scripts/llm_utils.py | 1 + scripts/logger.py | 1 + scripts/main.py | 4 ++++ scripts/memory/__init__.py | 2 ++ scripts/speak.py | 4 ++++ scripts/token_counter.py | 2 ++ tests/integration/memory_tests.py | 1 + tests/local_cache_test.py | 2 ++ tests/test_config.py | 1 + tests/test_json_parser.py | 1 + tests/unit/json_tests.py | 1 + 20 files changed, 47 insertions(+) diff --git a/scripts/agent_manager.py b/scripts/agent_manager.py index a0e5f1648213..191ab838a342 100644 --- a/scripts/agent_manager.py +++ b/scripts/agent_manager.py @@ -6,6 +6,7 @@ # Create new GPT agent # TODO: Centralise use of create_chat_completion() to globally enforce token limit + def create_agent(task, prompt, model): """Create a new agent and return its key""" global next_key diff --git a/scripts/ai_config.py b/scripts/ai_config.py index bd373944fca1..ee4b1fda2336 100644 --- a/scripts/ai_config.py +++ b/scripts/ai_config.py @@ -2,6 +2,7 @@ import data import os + class AIConfig: """ A class object that contains the configuration information for the AI diff --git a/scripts/browse.py b/scripts/browse.py index 9e93c55a338b..a5b167c92860 100644 --- a/scripts/browse.py +++ b/scripts/browse.py @@ -21,12 +21,28 @@ 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, headers=cfg.user_agent_header, timeout=timeout) + response.raise_for_status() + return response + except requests.exceptions.RequestException as e: + return "Error: " + str(e) + + # Define and check for local file address prefixes def check_local_file_access(url): local_prefixes = ['file:///', 'file://localhost', 'http://localhost', 'https://localhost'] return any(url.startswith(prefix) for prefix in local_prefixes) +def scrape_text(url): + """Scrape text from a webpage""" + # Basic check if the URL is valid + if not url.startswith('http'): + return "Error: Invalid URL" + def get_response(url, headers=cfg.user_agent_header, timeout=10): try: # Restrict access to local files diff --git a/scripts/call_ai_function.py b/scripts/call_ai_function.py index f8238658695a..6f1d6ceee8b3 100644 --- a/scripts/call_ai_function.py +++ b/scripts/call_ai_function.py @@ -3,6 +3,8 @@ cfg = Config() from llm_utils import create_chat_completion + + # This is a magic function that can do anything with no-code. See # https://github.com/Torantulino/AI-Functions for more info. def call_ai_function(function, args, description, model=None): diff --git a/scripts/chat.py b/scripts/chat.py index e16cee383785..2b7c34b5c400 100644 --- a/scripts/chat.py +++ b/scripts/chat.py @@ -9,6 +9,7 @@ cfg = Config() + def create_chat_message(role, content): """ Create a chat message with the given role and content. diff --git a/scripts/commands.py b/scripts/commands.py index 3966e86ab85c..fe6f6c30e9f5 100644 --- a/scripts/commands.py +++ b/scripts/commands.py @@ -24,6 +24,7 @@ def is_valid_int(value): except ValueError: return False + def get_command(response): """Parse the response and return the command name and arguments""" try: @@ -135,6 +136,7 @@ def google_search(query, num_results=8): return json.dumps(search_results, ensure_ascii=False, indent=4) + def google_official_search(query, num_results=8): """Return the results of a google search using the official Google API""" from googleapiclient.discovery import build @@ -171,6 +173,7 @@ def google_official_search(query, num_results=8): # Return the list of search result URLs return search_results_links + def browse_website(url, question): """Browse a website and return the summary and links""" summary = get_text_summary(url, question) diff --git a/scripts/data.py b/scripts/data.py index f80c2875d8ef..088fd51ce1c0 100644 --- a/scripts/data.py +++ b/scripts/data.py @@ -1,6 +1,7 @@ import os from pathlib import Path + def load_prompt(): """Load the prompt from data/prompt.txt""" try: diff --git a/scripts/file_operations.py b/scripts/file_operations.py index 7b48c1348728..2999bc24f1bf 100644 --- a/scripts/file_operations.py +++ b/scripts/file_operations.py @@ -65,6 +65,7 @@ def delete_file(filename): except Exception as e: return "Error: " + str(e) + def search_files(directory): found_files = [] diff --git a/scripts/image_gen.py b/scripts/image_gen.py index 4481696ffa21..6c27df3f352b 100644 --- a/scripts/image_gen.py +++ b/scripts/image_gen.py @@ -11,6 +11,7 @@ working_directory = "auto_gpt_workspace" + def generate_image(prompt): filename = str(uuid.uuid4()) + ".jpg" diff --git a/scripts/llm_utils.py b/scripts/llm_utils.py index 35cc5ce040c6..16739dddf001 100644 --- a/scripts/llm_utils.py +++ b/scripts/llm_utils.py @@ -4,6 +4,7 @@ openai.api_key = cfg.openai_api_key + # Overly simple abstraction until we create something better def create_chat_completion(messages, model=None, temperature=cfg.temperature, max_tokens=None)->str: """Create a chat completion using the OpenAI API""" diff --git a/scripts/logger.py b/scripts/logger.py index 85dde8133135..42a4387851e2 100644 --- a/scripts/logger.py +++ b/scripts/logger.py @@ -151,6 +151,7 @@ def emit(self, record): except Exception: self.handleError(record) + class ConsoleHandler(logging.StreamHandler): def emit(self, record): msg = self.format(record) diff --git a/scripts/main.py b/scripts/main.py index 81f560b21664..4a89e8e127f1 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -20,6 +20,7 @@ cfg = Config() + def check_openai_api_key(): """Check if the OpenAI API key is set in config.py or as an environment variable.""" if not cfg.openai_api_key: @@ -30,6 +31,7 @@ def check_openai_api_key(): print("You can get your key from https://beta.openai.com/account/api-keys") exit(1) + def attempt_to_fix_json_by_finding_outermost_brackets(json_string): if cfg.speak_mode and cfg.debug_mode: speak.say_text("I have received an invalid JSON response from the OpenAI API. Trying to fix it now.") @@ -58,6 +60,7 @@ def attempt_to_fix_json_by_finding_outermost_brackets(json_string): return json_string + def print_assistant_thoughts(assistant_reply): """Prints the assistant's thoughts to the console""" global ai_name @@ -262,6 +265,7 @@ def prompt_user(): config = AIConfig(ai_name, ai_role, ai_goals) return config + def parse_arguments(): """Parses the arguments passed to the script""" global cfg diff --git a/scripts/memory/__init__.py b/scripts/memory/__init__.py index a07f9fd88df3..7eee1b3da1a6 100644 --- a/scripts/memory/__init__.py +++ b/scripts/memory/__init__.py @@ -18,6 +18,7 @@ print("Pinecone not installed. Skipping import.") PineconeMemory = None + def get_memory(cfg, init=False): memory = None if cfg.memory_backend == "pinecone": @@ -41,6 +42,7 @@ def get_memory(cfg, init=False): memory.clear() return memory + def get_supported_memory_backends(): return supported_memory diff --git a/scripts/speak.py b/scripts/speak.py index 64054e3c5843..7a17873c5ec3 100644 --- a/scripts/speak.py +++ b/scripts/speak.py @@ -31,6 +31,7 @@ mutex_lock = Lock() # Ensure only one sound is played at a time queue_semaphore = Semaphore(1) # The amount of sounds to queue before blocking the main thread + def eleven_labs_speech(text, voice_index=0): """Speak text using elevenlabs.io's API""" tts_url = "https://api.elevenlabs.io/v1/text-to-speech/{voice_id}".format( @@ -51,6 +52,7 @@ def eleven_labs_speech(text, voice_index=0): print("Response content:", response.content) return False + def gtts_speech(text): tts = gtts.gTTS(text) with mutex_lock: @@ -58,6 +60,7 @@ def gtts_speech(text): playsound("speech.mp3", True) os.remove("speech.mp3") + def macos_tts_speech(text, voice_index=0): if voice_index == 0: os.system(f'say "{text}"') @@ -67,6 +70,7 @@ def macos_tts_speech(text, voice_index=0): else: os.system(f'say -v Samantha "{text}"') + def say_text(text, voice_index=0): def speak(): diff --git a/scripts/token_counter.py b/scripts/token_counter.py index 635d3286385f..8aecf1681be5 100644 --- a/scripts/token_counter.py +++ b/scripts/token_counter.py @@ -1,6 +1,7 @@ import tiktoken from typing import List, Dict + def count_message_tokens(messages : List[Dict[str, str]], model : str = "gpt-3.5-turbo-0301") -> int: """ Returns the number of tokens used by a list of messages. @@ -41,6 +42,7 @@ def count_message_tokens(messages : List[Dict[str, str]], model : str = "gpt-3.5 num_tokens += 3 # every reply is primed with <|start|>assistant<|message|> return num_tokens + def count_string_tokens(string: str, model_name: str) -> int: """ Returns the number of tokens in a text string. diff --git a/tests/integration/memory_tests.py b/tests/integration/memory_tests.py index 5f1611be96f9..d0c309628041 100644 --- a/tests/integration/memory_tests.py +++ b/tests/integration/memory_tests.py @@ -8,6 +8,7 @@ from config import Config from memory.local import LocalCache + class TestLocalCache(unittest.TestCase): def random_string(self, length): diff --git a/tests/local_cache_test.py b/tests/local_cache_test.py index d1f1ef084370..0352624ea26b 100644 --- a/tests/local_cache_test.py +++ b/tests/local_cache_test.py @@ -4,6 +4,7 @@ sys.path.append(os.path.abspath('../scripts')) from memory.local import LocalCache + def MockConfig(): return type('MockConfig', (object,), { 'debug_mode': False, @@ -12,6 +13,7 @@ def MockConfig(): 'memory_index': 'auto-gpt', }) + class TestLocalCache(unittest.TestCase): def setUp(self): diff --git a/tests/test_config.py b/tests/test_config.py index c1310b709893..ba8381e1e73a 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,6 +1,7 @@ import unittest from scripts.config import Config + class TestConfig(unittest.TestCase): def test_singleton(self): diff --git a/tests/test_json_parser.py b/tests/test_json_parser.py index 0f2c6488c626..438e047b448b 100644 --- a/tests/test_json_parser.py +++ b/tests/test_json_parser.py @@ -3,6 +3,7 @@ from scripts.json_parser import fix_and_parse_json + class TestParseJson(unittest.TestCase): def test_valid_json(self): # Test that a valid JSON string is parsed correctly diff --git a/tests/unit/json_tests.py b/tests/unit/json_tests.py index 3320ad5e9ab5..4f3267217a36 100644 --- a/tests/unit/json_tests.py +++ b/tests/unit/json_tests.py @@ -5,6 +5,7 @@ sys.path.append(os.path.abspath('../scripts')) from json_parser import fix_and_parse_json + class TestParseJson(unittest.TestCase): def test_valid_json(self): # Test that a valid JSON string is parsed correctly From 62edc148a8b43dfe4b30c5ca9de3c462cd366a46 Mon Sep 17 00:00:00 2001 From: Drikus Roor Date: Thu, 13 Apr 2023 10:56:02 +0200 Subject: [PATCH 09/16] chore: Remove functions that had been removed on the master branch recently --- scripts/browse.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/scripts/browse.py b/scripts/browse.py index a5b167c92860..9e93c55a338b 100644 --- a/scripts/browse.py +++ b/scripts/browse.py @@ -21,28 +21,12 @@ 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, headers=cfg.user_agent_header, timeout=timeout) - response.raise_for_status() - return response - except requests.exceptions.RequestException as e: - return "Error: " + str(e) - - # Define and check for local file address prefixes def check_local_file_access(url): local_prefixes = ['file:///', 'file://localhost', 'http://localhost', 'https://localhost'] return any(url.startswith(prefix) for prefix in local_prefixes) -def scrape_text(url): - """Scrape text from a webpage""" - # Basic check if the URL is valid - if not url.startswith('http'): - return "Error: Invalid URL" - def get_response(url, headers=cfg.user_agent_header, timeout=10): try: # Restrict access to local files From abe01ab81e0428b6b9cc1844df8e2130c9ffe3f6 Mon Sep 17 00:00:00 2001 From: Drikus Roor Date: Thu, 13 Apr 2023 11:05:36 +0200 Subject: [PATCH 10/16] fix: Fix flake8 linting errors --- scripts/execute_code.py | 1 + scripts/logger.py | 8 ++++---- scripts/memory/base.py | 1 - 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/execute_code.py b/scripts/execute_code.py index 2c92903cf4b4..dbd62c226591 100644 --- a/scripts/execute_code.py +++ b/scripts/execute_code.py @@ -67,6 +67,7 @@ def execute_python_file(file): except Exception as e: return f"Error: {str(e)}" + def execute_shell(command_line): current_dir = os.getcwd() diff --git a/scripts/logger.py b/scripts/logger.py index 42a4387851e2..f5e94687b03c 100644 --- a/scripts/logger.py +++ b/scripts/logger.py @@ -161,11 +161,11 @@ def emit(self, record): self.handleError(record) -''' -Allows to handle custom placeholders 'title_color' and 'message_no_color'. -To use this formatter, make sure to pass 'color', 'title' as log extras. -''' class AutoGptFormatter(logging.Formatter): + """ + Allows to handle custom placeholders 'title_color' and 'message_no_color'. + To use this formatter, make sure to pass 'color', 'title' as log extras. + """ def format(self, record: LogRecord) -> str: if (hasattr(record, 'color')): record.title_color = getattr(record, 'color') + getattr(record, 'title') + " " + Style.RESET_ALL diff --git a/scripts/memory/base.py b/scripts/memory/base.py index 1be7b3ddcbeb..96cf3df13534 100644 --- a/scripts/memory/base.py +++ b/scripts/memory/base.py @@ -4,7 +4,6 @@ import openai cfg = Config() -cfg = Config() def get_ada_embedding(text): text = text.replace("\n", " ") From dd15900804ea502fdca76077ea7bc30ebfaaa476 Mon Sep 17 00:00:00 2001 From: Yossi Marouani Date: Thu, 13 Apr 2023 17:19:02 +0300 Subject: [PATCH 11/16] temperature should not be an Int. it can be any value between 0-1 --- scripts/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/config.py b/scripts/config.py index ebf1b08b22f7..8cbc67fc5a7a 100644 --- a/scripts/config.py +++ b/scripts/config.py @@ -44,7 +44,7 @@ def __init__(self): self.smart_token_limit = int(os.getenv("SMART_TOKEN_LIMIT", 8000)) self.openai_api_key = os.getenv("OPENAI_API_KEY") - self.temperature = int(os.getenv("TEMPERATURE", "1")) + self.temperature = float(os.getenv("TEMPERATURE", "1")) self.use_azure = False self.use_azure = os.getenv("USE_AZURE") == 'True' self.execute_local_commands = os.getenv('EXECUTE_LOCAL_COMMANDS', 'False') == 'True' From b112f5ebfafe2d488e2819dcf02b767e416f3919 Mon Sep 17 00:00:00 2001 From: Merwane Hamadi Date: Thu, 13 Apr 2023 05:57:21 -0700 Subject: [PATCH 12/16] put loop in in if main --- scripts/main.py | 229 +++++++++++++++++++++++++----------------------- 1 file changed, 117 insertions(+), 112 deletions(-) diff --git a/scripts/main.py b/scripts/main.py index 81f560b21664..4f1b23eacd62 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -316,118 +316,123 @@ def parse_arguments(): cfg.memory_backend = chosen -# TODO: fill in llm values here -check_openai_api_key() -parse_arguments() -logger.set_level(logging.DEBUG if cfg.debug_mode else logging.INFO) -ai_name = "" -prompt = construct_prompt() -# print(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:" - -# Initialize memory and make sure it is empty. -# this is particularly important for indexing and referencing pinecone memory -memory = get_memory(cfg, init=True) -print('Using memory of type: ' + memory.__class__.__name__) - -# Interaction Loop -while True: - # Send message to AI, get response - with Spinner("Thinking... "): - assistant_reply = chat.chat_with_ai( - prompt, - user_input, - full_message_history, - memory, - cfg.fast_token_limit) # TODO: This hardcodes the model to use GPT3.5. Make this an argument - - # Print Assistant thoughts - print_assistant_thoughts(assistant_reply) - - # Get command name and arguments - try: - command_name, arguments = cmd.get_command(attempt_to_fix_json_by_finding_outermost_brackets(assistant_reply)) - if cfg.speak_mode: - speak.say_text(f"I want to execute {command_name}") - except Exception as e: - logger.error("Error: \n", str(e)) - - 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 - user_input = "" - logger.typewriter_log( - "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 = utils.clean_input(Fore.MAGENTA + "Input:" + Style.RESET_ALL) - if console_input.lower().rstrip() == "y": - user_input = "GENERATE NEXT COMMAND JSON" - break - elif console_input.lower().startswith("y -"): - try: - next_action_count = abs(int(console_input.split(" ")[1])) +def main(): + global ai_name, memory + # TODO: fill in llm values here + check_openai_api_key() + parse_arguments() + logger.set_level(logging.DEBUG if cfg.debug_mode else logging.INFO) + ai_name = "" + prompt = construct_prompt() + # print(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:" + # Initialize memory and make sure it is empty. + # this is particularly important for indexing and referencing pinecone memory + memory = get_memory(cfg, init=True) + print('Using memory of type: ' + memory.__class__.__name__) + # Interaction Loop + while True: + # Send message to AI, get response + with Spinner("Thinking... "): + assistant_reply = chat.chat_with_ai( + prompt, + user_input, + full_message_history, + memory, + cfg.fast_token_limit) # TODO: This hardcodes the model to use GPT3.5. Make this an argument + + # Print Assistant thoughts + print_assistant_thoughts(assistant_reply) + + # Get command name and arguments + try: + command_name, arguments = cmd.get_command( + attempt_to_fix_json_by_finding_outermost_brackets(assistant_reply)) + if cfg.speak_mode: + speak.say_text(f"I want to execute {command_name}") + except Exception as e: + logger.error("Error: \n", str(e)) + + 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 + user_input = "" + logger.typewriter_log( + "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 = utils.clean_input(Fore.MAGENTA + "Input:" + Style.RESET_ALL) + if console_input.lower().rstrip() == "y": 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 + 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": + logger.typewriter_log( + "-=-=-=-=-=-=-= COMMAND AUTHORISED BY USER -=-=-=-=-=-=-=", + Fore.MAGENTA, + "") + elif user_input == "EXIT": + print("Exiting...", flush=True) break - - if user_input == "GENERATE NEXT COMMAND JSON": + else: + # Print command logger.typewriter_log( - "-=-=-=-=-=-=-= COMMAND AUTHORISED BY USER -=-=-=-=-=-=-=", - Fore.MAGENTA, - "") - elif user_input == "EXIT": - print("Exiting...", flush=True) - break - else: - # Print command - logger.typewriter_log( - "NEXT ACTION: ", - Fore.CYAN, - f"COMMAND = {Fore.CYAN}{command_name}{Style.RESET_ALL} ARGUMENTS = {Fore.CYAN}{arguments}{Style.RESET_ALL}") - - # Execute command - if command_name is not None and command_name.lower().startswith( "error" ): - result = f"Command {command_name} threw the following error: " + arguments - elif command_name == "human_feedback": - 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 - - 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: - full_message_history.append(chat.create_chat_message("system", result)) - logger.typewriter_log("SYSTEM: ", Fore.YELLOW, result) - else: - full_message_history.append( - chat.create_chat_message( - "system", "Unable to execute command")) - logger.typewriter_log("SYSTEM: ", Fore.YELLOW, "Unable to execute command") + "NEXT ACTION: ", + Fore.CYAN, + f"COMMAND = {Fore.CYAN}{command_name}{Style.RESET_ALL} ARGUMENTS = {Fore.CYAN}{arguments}{Style.RESET_ALL}") + + # Execute command + if command_name is not None and command_name.lower().startswith("error"): + result = f"Command {command_name} threw the following error: " + arguments + elif command_name == "human_feedback": + 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 + + 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: + full_message_history.append(chat.create_chat_message("system", result)) + logger.typewriter_log("SYSTEM: ", Fore.YELLOW, result) + else: + full_message_history.append( + chat.create_chat_message( + "system", "Unable to execute command")) + logger.typewriter_log("SYSTEM: ", Fore.YELLOW, "Unable to execute command") + + +if __name__ == "__main__": + main() From da247ca600dd0961d2ba8d3ea69819121f589468 Mon Sep 17 00:00:00 2001 From: Kory Becker Date: Thu, 13 Apr 2023 12:47:16 -0400 Subject: [PATCH 13/16] merge fix --- azure.yaml.template | 1 + scripts/config.py | 13 ++++--------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/azure.yaml.template b/azure.yaml.template index 852645ca0d47..74ca797b2d54 100644 --- a/azure.yaml.template +++ b/azure.yaml.template @@ -1,3 +1,4 @@ +azure_api_type: azure_ad azure_api_base: your-base-url-for-azure azure_api_version: api-version-for-azure azure_model_map: diff --git a/scripts/config.py b/scripts/config.py index 0270dbec0e42..03d48dd430ef 100644 --- a/scripts/config.py +++ b/scripts/config.py @@ -45,18 +45,12 @@ def __init__(self): self.openai_api_key = os.getenv("OPENAI_API_KEY") self.temperature = int(os.getenv("TEMPERATURE", "1")) - self.use_azure = False self.use_azure = os.getenv("USE_AZURE") == 'True' self.execute_local_commands = os.getenv('EXECUTE_LOCAL_COMMANDS', 'False') == 'True' if self.use_azure: - self.openai_api_base = os.getenv("OPENAI_AZURE_API_BASE") - self.openai_api_version = os.getenv("OPENAI_AZURE_API_VERSION") - self.openai_deployment_id = os.getenv("OPENAI_AZURE_DEPLOYMENT_ID") - self.azure_chat_deployment_id = os.getenv("OPENAI_AZURE_CHAT_DEPLOYMENT_ID") - self.azure_embeddigs_deployment_id = os.getenv("OPENAI_AZURE_EMBEDDINGS_DEPLOYMENT_ID") self.load_azure_config() - openai.api_type = os.getenv("OPENAI_API_TYPE", "azure") + openai.api_type = self.openai_api_type openai.api_base = self.openai_api_base openai.api_version = self.openai_api_version @@ -126,8 +120,9 @@ def load_azure_config(self, config_file: str=AZURE_CONFIG_FILE) -> None: config_params = yaml.load(file, Loader=yaml.FullLoader) except FileNotFoundError: config_params = {} - self.openai_api_base = config_params.get("azure_api_base", "") - self.openai_api_version = config_params.get("azure_api_version", "") + self.openai_api_type = os.getenv("OPENAI_API_TYPE", config_params.get("azure_api_type", "azure")) + self.openai_api_base = os.getenv("OPENAI_AZURE_API_BASE", config_params.get("azure_api_base", "")) + self.openai_api_version = os.getenv("OPENAI_AZURE_API_VERSION", config_params.get("azure_api_version", "")) self.azure_model_to_deployment_id_map = config_params.get("azure_model_map", []) def set_continuous_mode(self, value: bool): From 53c00b4199d047cfcbf44146447c18ed0919795d Mon Sep 17 00:00:00 2001 From: Richard Beales Date: Thu, 13 Apr 2023 18:01:12 +0100 Subject: [PATCH 14/16] Hotfix - re-add missing cfg variable to memory/base --- scripts/memory/base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/memory/base.py b/scripts/memory/base.py index 1d908531c82c..1bb4e89f5ba4 100644 --- a/scripts/memory/base.py +++ b/scripts/memory/base.py @@ -3,6 +3,7 @@ from config import AbstractSingleton, Config import openai +cfg = Config() def get_ada_embedding(text): text = text.replace("\n", " ") From 1da9dbe671fb6d876b7e8883c5ec06a88225adb5 Mon Sep 17 00:00:00 2001 From: "fabi.s" Date: Thu, 13 Apr 2023 19:05:23 +0200 Subject: [PATCH 15/16] remove output to set OpenAI API key in config.py --- scripts/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.py b/scripts/main.py index 68f9d10c3152..c08ba1b2924d 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -26,7 +26,7 @@ def check_openai_api_key(): if not cfg.openai_api_key: print( Fore.RED + - "Please set your OpenAI API key in config.py or as an environment variable." + "Please set your OpenAI API key in .env or as an environment variable." ) print("You can get your key from https://beta.openai.com/account/api-keys") exit(1) From 6bb4ca0bff34cfdf22b1e6bdb1b6b08d81c62e73 Mon Sep 17 00:00:00 2001 From: Andy Melnikov Date: Thu, 13 Apr 2023 19:32:35 +0200 Subject: [PATCH 16/16] Fix flake8 E302 --- scripts/memory/no_memory.py | 1 + scripts/memory/pinecone.py | 1 + 2 files changed, 2 insertions(+) diff --git a/scripts/memory/no_memory.py b/scripts/memory/no_memory.py index 45dbd7349bb9..830982f9c42b 100644 --- a/scripts/memory/no_memory.py +++ b/scripts/memory/no_memory.py @@ -2,6 +2,7 @@ from memory.base import MemoryProviderSingleton + class NoMemory(MemoryProviderSingleton): def __init__(self, cfg): """ diff --git a/scripts/memory/pinecone.py b/scripts/memory/pinecone.py index fa21124b5c7c..20a905b32c00 100644 --- a/scripts/memory/pinecone.py +++ b/scripts/memory/pinecone.py @@ -5,6 +5,7 @@ from logger import logger from colorama import Fore, Style + class PineconeMemory(MemoryProviderSingleton): def __init__(self, cfg): pinecone_api_key = cfg.pinecone_api_key