From c785352ed2c6f1744bdeac5410ea93199bade937 Mon Sep 17 00:00:00 2001 From: Maiko Bossuyt Date: Wed, 12 Apr 2023 16:23:09 +0200 Subject: [PATCH 01/10] Update main.py clean trailing whitespace --- scripts/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.py b/scripts/main.py index 15af0c381249..3dcedb5fdc70 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -293,7 +293,7 @@ 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) From c986e8713512aad9f06c074b5e7fdfa31ade2df7 Mon Sep 17 00:00:00 2001 From: Maiko Bossuyt Date: Wed, 12 Apr 2023 16:36:27 +0200 Subject: [PATCH 02/10] Edit config Class to manage browse_website command chunk size and summary size I added two new config parameters: - browse_chunk_max_length: define the max_length of a chunk being sent to the memory and to FAST_LLM_MODEL for summarizing - browse_summary_max_token: define the max_token passed to the model use for summary creation. Changing this can help with complex subject, allowing the agent to be more verbose in its attemps to summarize the chunk and the chunks summary. I've also edited the way the user_agent is handle. --- .env.template | 2 ++ scripts/config.py | 14 +++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/.env.template b/.env.template index 6fbc84243b17..0953fac9383c 100644 --- a/.env.template +++ b/.env.template @@ -15,3 +15,5 @@ OPENAI_AZURE_DEPLOYMENT_ID=deployment-id-for-azure IMAGE_PROVIDER=dalle HUGGINGFACE_API_TOKEN= USE_MAC_OS_TTS=False +BROWSE_CHUNK_MAX_LENGTH=4000 +BROWSE_SUMMARY_MAX_TOKEN=300 \ No newline at end of file diff --git a/scripts/config.py b/scripts/config.py index a280e6cc15e9..1eeeb72f3d06 100644 --- a/scripts/config.py +++ b/scripts/config.py @@ -41,6 +41,8 @@ def __init__(self): self.smart_llm_model = os.getenv("SMART_LLM_MODEL", "gpt-4") self.fast_token_limit = int(os.getenv("FAST_TOKEN_LIMIT", 4000)) self.smart_token_limit = int(os.getenv("SMART_TOKEN_LIMIT", 8000)) + self.browse_chunk_max_length = int(os.getenv("BROWSE_CHUNK_MAX_LENGTH", 8000)) + self.browse_summary_max_token = int(os.getenv("BROWSE_SUMMARY_MAX_TOKEN", 300)) self.openai_api_key = os.getenv("OPENAI_API_KEY") self.use_azure = False @@ -71,7 +73,8 @@ 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 = os.getenv("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", "") @@ -80,6 +83,7 @@ def __init__(self): # Note that indexes must be created on db 0 in redis, this is not configurable. self.memory_backend = os.getenv("MEMORY_BACKEND", 'local') + # Initialize the OpenAI API client openai.api_key = self.openai_api_key @@ -107,6 +111,14 @@ def set_smart_token_limit(self, value: int): """Set the smart token limit value.""" self.smart_token_limit = value + def set_browse_chunk_max_length(self, value: int): + """Set the browse_website command chunk max length value.""" + self.browse_chunk_max_length = value + + def set_browse_summary_max_token(self, value: int): + """Set the browse_website command summary max token value.""" + self.browse_summary_max_token = value + def set_openai_api_key(self, value: str): """Set the OpenAI API key value.""" self.openai_api_key = value From b20c0117c5732e73005ee9fc12380078d5ea442c Mon Sep 17 00:00:00 2001 From: Maiko Bossuyt Date: Wed, 12 Apr 2023 16:38:49 +0200 Subject: [PATCH 03/10] Add memory management to browse.py - Change the way User-Agent is handle when calling requests to browse website - Add chunk to memory before and after summary. We do not save the "summary of summaries" as this wasn't performing great and caused noise when the "question" couldn't be answered. - Use the newly added config parameters for max_length and max_token --- scripts/browse.py | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/scripts/browse.py b/scripts/browse.py index b0c745ef420d..5f4aafe67860 100644 --- a/scripts/browse.py +++ b/scripts/browse.py @@ -1,9 +1,14 @@ import requests from bs4 import BeautifulSoup +from memory import get_memory from config import Config from llm_utils import create_chat_completion cfg = Config() +memory = get_memory(cfg) + +session = requests.Session() +session.headers.update({'User-Agent': cfg.user_agent}) # Define and check for local file address prefixes def check_local_file_access(url): @@ -21,7 +26,7 @@ def scrape_text(url): return "Error: Access to local files is restricted" try: - response = requests.get(url, headers=cfg.user_agent_header) + response = session.get(url) except requests.exceptions.RequestException as e: return "Error: " + str(e) @@ -60,7 +65,7 @@ def format_hyperlinks(hyperlinks): def scrape_links(url): """Scrape links from a webpage""" - response = requests.get(url, headers=cfg.user_agent_header) + response = session.get(url) # Check if the response contains an HTTP error if response.status_code >= 400: @@ -76,7 +81,7 @@ def scrape_links(url): return format_hyperlinks(hyperlinks) -def split_text(text, max_length=8192): +def split_text(text, max_length=cfg.browse_chunk_max_length): """Split text into chunks of a maximum length""" paragraphs = text.split("\n") current_length = 0 @@ -102,7 +107,7 @@ def create_message(chunk, question): "content": f"\"\"\"{chunk}\"\"\" Using the above text, please answer the following question: \"{question}\" -- if the question cannot be answered using the text, please summarize the text." } -def summarize_text(text, question): +def summarize_text(url, text, question): """Summarize text using the LLM model""" if not text: return "Error: No text to summarize" @@ -114,15 +119,28 @@ def summarize_text(text, question): chunks = list(split_text(text)) for i, chunk in enumerate(chunks): + print(f"Adding chunk {i + 1} / {len(chunks)} to memory") + + memory_to_add = f"Source: {url}\n" \ + f"Raw content part#{i + 1}: {chunk}" + + memory.add(memory_to_add) + print(f"Summarizing chunk {i + 1} / {len(chunks)}") messages = [create_message(chunk, question)] summary = create_chat_completion( model=cfg.fast_llm_model, messages=messages, - max_tokens=300, + max_tokens=cfg.browse_summary_max_token, ) summaries.append(summary) + print(f"Added chunk {i + 1} summary to memory") + + memory_to_add = f"Source: {url}\n" \ + f"Content summary part#{i + 1}: {summary}" + + memory.add(memory_to_add) print(f"Summarized {len(chunks)} chunks.") @@ -132,7 +150,7 @@ def summarize_text(text, question): final_summary = create_chat_completion( model=cfg.fast_llm_model, messages=messages, - max_tokens=300, + max_tokens=cfg.browse_summary_max_token, ) return final_summary From 5bb551db95fe1eb6765c61fa28bf384d8252cdad Mon Sep 17 00:00:00 2001 From: Maiko Bossuyt Date: Wed, 12 Apr 2023 16:42:14 +0200 Subject: [PATCH 04/10] add the url variable in the get_text_summary function to pass it to the memory By sending the url along when calling browse.summarize_text, we can then add it along the chunk in memory. --- scripts/commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/commands.py b/scripts/commands.py index 92d46ae18ae4..90d7a6f31ea5 100644 --- a/scripts/commands.py +++ b/scripts/commands.py @@ -183,7 +183,7 @@ def browse_website(url, question): def get_text_summary(url, question): """Return the results of a google search""" text = browse.scrape_text(url) - summary = browse.summarize_text(text, question) + summary = browse.summarize_text(url, text, question) return """ "Result" : """ + summary From a615e570616146ba51336b4160c2eff225479769 Mon Sep 17 00:00:00 2001 From: Maiko Bossuyt Date: Wed, 12 Apr 2023 18:00:17 +0200 Subject: [PATCH 05/10] Revert "Update main.py" This reverts commit c785352ed2c6f1744bdeac5410ea93199bade937. --- scripts/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/main.py b/scripts/main.py index 3dcedb5fdc70..15af0c381249 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -293,7 +293,7 @@ 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) From 8baa0769b154f3742cdc75e07404952de02e0669 Mon Sep 17 00:00:00 2001 From: Maiko Bossuyt Date: Wed, 12 Apr 2023 18:03:59 +0200 Subject: [PATCH 06/10] Update config.py --- scripts/config.py | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/config.py b/scripts/config.py index 1eeeb72f3d06..9c4e45727ebc 100644 --- a/scripts/config.py +++ b/scripts/config.py @@ -83,7 +83,6 @@ def __init__(self): # Note that indexes must be created on db 0 in redis, this is not configurable. self.memory_backend = os.getenv("MEMORY_BACKEND", 'local') - # Initialize the OpenAI API client openai.api_key = self.openai_api_key From 1c64a9d24508333d92cfdb26d38a90c4bd543dc6 Mon Sep 17 00:00:00 2001 From: Maiko Bossuyt Date: Wed, 12 Apr 2023 23:33:14 +0200 Subject: [PATCH 07/10] Update .env.template --- .env.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.template b/.env.template index 0aec7b10c5bc..f1e66ea5ec47 100644 --- a/.env.template +++ b/.env.template @@ -19,4 +19,4 @@ HUGGINGFACE_API_TOKEN= USE_MAC_OS_TTS=False BROWSE_CHUNK_MAX_LENGTH=4000 BROWSE_SUMMARY_MAX_TOKEN=300 -MEMORY_BACKEND=local \ No newline at end of file +MEMORY_BACKEND=local From 25509f9d2541a6c92949984da5548b11903fc98b Mon Sep 17 00:00:00 2001 From: Maiko Bossuyt Date: Fri, 14 Apr 2023 00:48:07 +0200 Subject: [PATCH 08/10] Update config.py 8192 is the current default --- scripts/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/config.py b/scripts/config.py index 0150ca42c4a3..a856265a7bc7 100644 --- a/scripts/config.py +++ b/scripts/config.py @@ -43,7 +43,7 @@ def __init__(self): self.smart_llm_model = os.getenv("SMART_LLM_MODEL", "gpt-4") self.fast_token_limit = int(os.getenv("FAST_TOKEN_LIMIT", 4000)) self.smart_token_limit = int(os.getenv("SMART_TOKEN_LIMIT", 8000)) - self.browse_chunk_max_length = int(os.getenv("BROWSE_CHUNK_MAX_LENGTH", 8000)) + self.browse_chunk_max_length = int(os.getenv("BROWSE_CHUNK_MAX_LENGTH", 8192)) self.browse_summary_max_token = int(os.getenv("BROWSE_SUMMARY_MAX_TOKEN", 300)) self.openai_api_key = os.getenv("OPENAI_API_KEY") From e147788c72535779ed094a101c4739aa1e8bdb8c Mon Sep 17 00:00:00 2001 From: Maiko Bossuyt Date: Fri, 14 Apr 2023 10:33:34 +0200 Subject: [PATCH 09/10] Update .env.template BROWSE_CHUNK_MAX_LENGTH default value --- .env.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.template b/.env.template index 7ff03cab8dc3..733597d9119c 100644 --- a/.env.template +++ b/.env.template @@ -4,7 +4,7 @@ # EXECUTE_LOCAL_COMMANDS - Allow local command execution (Example: False) EXECUTE_LOCAL_COMMANDS=False # BROWSE_CHUNK_MAX_LENGTH - When browsing website, define the length of chunk stored in memory -BROWSE_CHUNK_MAX_LENGTH=4000 +BROWSE_CHUNK_MAX_LENGTH=8192 # BROWSE_SUMMARY_MAX_TOKEN - Define the maximum length of the summary generated by GPT agent when browsing website BROWSE_SUMMARY_MAX_TOKEN=300 # USER_AGENT - Define the user-agent used by the requests library to browse website (string) From a67818648ed722e4e50133e01c0c2f189dfec05c Mon Sep 17 00:00:00 2001 From: Maiko Bossuyt Date: Fri, 14 Apr 2023 18:10:42 +0200 Subject: [PATCH 10/10] Update browse.py linting --- scripts/browse.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/browse.py b/scripts/browse.py index a4a417447ba4..ef22de03d021 100644 --- a/scripts/browse.py +++ b/scripts/browse.py @@ -137,6 +137,7 @@ def create_message(chunk, question): "content": f"\"\"\"{chunk}\"\"\" Using the above text, please answer the following question: \"{question}\" -- if the question cannot be answered using the text, please summarize the text." } + def summarize_text(url, text, question): """Summarize text using the LLM model""" if not text: