From eac5c1f6e6be1c068e74fd6b153e5fc86456b5a7 Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Sun, 2 Apr 2023 19:03:37 +0200 Subject: [PATCH 01/26] Add documentation --- scripts/agent_manager.py | 4 ++++ scripts/ai_functions.py | 5 ++++- scripts/browse.py | 6 ++++++ scripts/chat.py | 1 + scripts/commands.py | 15 +++++++++++++++ scripts/config.py | 4 ++++ scripts/data.py | 1 + scripts/execute_code.py | 1 + scripts/file_operations.py | 5 +++++ scripts/keys.py | 1 + scripts/main.py | 5 +++++ scripts/speak.py | 1 + scripts/spinner.py | 5 +++++ 13 files changed, 53 insertions(+), 1 deletion(-) diff --git a/scripts/agent_manager.py b/scripts/agent_manager.py index 9939332b..b829b219 100644 --- a/scripts/agent_manager.py +++ b/scripts/agent_manager.py @@ -7,6 +7,7 @@ agents = {} # key, (task, full_message_history, model) def create_agent(task, prompt, model): + """Create a new agent and return its key""" global next_key global agents @@ -34,6 +35,7 @@ def create_agent(task, prompt, model): def message_agent(key, message): + """Send a message to an agent and return its response""" global agents task, messages, model = agents[int(key)] @@ -57,6 +59,7 @@ def message_agent(key, message): def list_agents(): + """Return a list of all agents""" global agents # Return a list of agent keys and their tasks @@ -64,6 +67,7 @@ def list_agents(): def delete_agent(key): + """Delete an agent and return True if successful, False otherwise""" global agents try: diff --git a/scripts/ai_functions.py b/scripts/ai_functions.py index b79c4dbc..6659bb5f 100644 --- a/scripts/ai_functions.py +++ b/scripts/ai_functions.py @@ -6,7 +6,7 @@ import openai # 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="gpt-4"): - # parse args to comma seperated string + """Calls an AI function and returns the result.""" args = ", ".join(args) messages = [ { @@ -27,6 +27,7 @@ def call_ai_function(function, args, description, model="gpt-4"): def evaluate_code(code: str) -> List[str]: + """Evaluates the given code and returns a list of suggestions for improvements.""" function_string = "def analyze_code(code: str) -> List[str]:" args = [code] description_string = """Analyzes the given code and returns a list of suggestions for improvements.""" @@ -39,6 +40,7 @@ def evaluate_code(code: str) -> List[str]: def improve_code(suggestions: List[str], code: str) -> str: + """Improves the provided code based on the suggestions provided, making no other changes.""" function_string = ( "def generate_improved_code(suggestions: List[str], code: str) -> str:" ) @@ -53,6 +55,7 @@ def improve_code(suggestions: List[str], code: str) -> str: def write_tests(code: str, focus: List[str]) -> str: + """Generates test cases for the existing code, focusing on specific areas if required.""" function_string = ( "def create_test_cases(code: str, focus: Optional[str] = None) -> str:" ) diff --git a/scripts/browse.py b/scripts/browse.py index af7ce576..74d01b80 100644 --- a/scripts/browse.py +++ b/scripts/browse.py @@ -6,6 +6,7 @@ import openai def scrape_text(url): + """Scrape text from a webpage""" response = requests.get(url) # Check if the response contains an HTTP error @@ -26,6 +27,7 @@ def scrape_text(url): def extract_hyperlinks(soup): + """Extract hyperlinks from a BeautifulSoup object""" hyperlinks = [] for link in soup.find_all('a', href=True): hyperlinks.append((link.text, link['href'])) @@ -33,6 +35,7 @@ def extract_hyperlinks(soup): def format_hyperlinks(hyperlinks): + """Format hyperlinks into a list of strings""" formatted_links = [] for link_text, link_url in hyperlinks: formatted_links.append(f"{link_text} ({link_url})") @@ -40,6 +43,7 @@ def format_hyperlinks(hyperlinks): def scrape_links(url): + """Scrape hyperlinks from a webpage""" response = requests.get(url) # Check if the response contains an HTTP error @@ -57,6 +61,7 @@ def scrape_links(url): def split_text(text, max_length=8192): + """Split text into chunks of a maximum length""" paragraphs = text.split("\n") current_length = 0 current_chunk = [] @@ -75,6 +80,7 @@ def split_text(text, max_length=8192): def summarize_text(text, is_website=True): + """Summarize text using GPT-3""" if text == "": return "Error: No text to summarize" diff --git a/scripts/chat.py b/scripts/chat.py index a406812d..56f98240 100644 --- a/scripts/chat.py +++ b/scripts/chat.py @@ -27,6 +27,7 @@ def chat_with_ai( permanent_memory, token_limit, debug=False): + """Interact with the OpenAI API, sending the prompt, user input, message history, and permanent memory.""" while True: try: """ diff --git a/scripts/commands.py b/scripts/commands.py index 61085632..dbfe36c7 100644 --- a/scripts/commands.py +++ b/scripts/commands.py @@ -12,6 +12,7 @@ cfg = Config() def get_command(response): + """Parse the response and return the command name and arguments""" try: response_json = json.loads(response) command = response_json["command"] @@ -30,6 +31,7 @@ def get_command(response): def execute_command(command_name, arguments): + """Execute the command and return the response""" try: if command_name == "google": return google_search(arguments["input"]) @@ -93,11 +95,13 @@ def execute_command(command_name, arguments): def get_datetime(): + """Return the current date and time""" return "Current date and time: " + \ datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") def google_search(query, num_results=8): + """Return the results of a google search""" search_results = [] for j in browse.search(query, num_results=num_results): search_results.append(j) @@ -106,6 +110,7 @@ def google_search(query, num_results=8): def browse_website(url): + """Return the results of a google search""" summary = get_text_summary(url) links = get_hyperlinks(url) @@ -119,23 +124,27 @@ def browse_website(url): def get_text_summary(url): + """Return the results of a google search""" text = browse.scrape_text(url) summary = browse.summarize_text(text) return """ "Result" : """ + summary def get_hyperlinks(url): + """Return the results of a google search""" link_list = browse.scrape_links(url) return link_list def commit_memory(string): + """Commit a string to memory""" _text = f"""Committing memory with string "{string}" """ mem.permanent_memory.append(string) return _text def delete_memory(key): + """Delete a memory with a given key""" if key >= 0 and key < len(mem.permanent_memory): _text = "Deleting memory with key " + str(key) del mem.permanent_memory[key] @@ -147,6 +156,7 @@ def delete_memory(key): def overwrite_memory(key, string): + """Overwrite a memory with a given key""" if key >= 0 and key < len(mem.permanent_memory): _text = "Overwriting memory with key " + \ str(key) + " and string " + string @@ -159,11 +169,13 @@ def overwrite_memory(key, string): def shutdown(): + """Shut down the program""" print("Shutting down...") quit() def start_agent(name, task, prompt, model="gpt-3.5-turbo"): + """Start an agent with a given name, task, and prompt""" global cfg # Remove underscores from name @@ -187,6 +199,7 @@ def start_agent(name, task, prompt, model="gpt-3.5-turbo"): def message_agent(key, message): + """Message an agent with a given key and message""" global cfg agent_response = agents.message_agent(key, message) @@ -198,10 +211,12 @@ def message_agent(key, message): def list_agents(): + """List all agents""" return agents.list_agents() def delete_agent(key): + """Delete an agent with a given key""" result = agents.delete_agent(key) if not result: return f"Agent {key} does not exist." diff --git a/scripts/config.py b/scripts/config.py index bc7ebf71..ac145657 100644 --- a/scripts/config.py +++ b/scripts/config.py @@ -6,6 +6,7 @@ class Singleton(type): _instances = {} def __call__(cls, *args, **kwargs): + """Call method for the singleton metaclass.""" if cls not in cls._instances: cls._instances[cls] = super( Singleton, cls).__call__( @@ -19,11 +20,14 @@ class Config(metaclass=Singleton): """ def __init__(self): + """Initialize the configuration class.""" self.continuous_mode = False self.speak_mode = False def set_continuous_mode(self, value: bool): + """Set the continuous mode value.""" self.continuous_mode = value def set_speak_mode(self, value: bool): + """Set the speak mode value.""" self.speak_mode = value diff --git a/scripts/data.py b/scripts/data.py index 19473557..b1faec87 100644 --- a/scripts/data.py +++ b/scripts/data.py @@ -1,4 +1,5 @@ def load_prompt(): + """Load the prompt from data/prompt.txt""" try: # Load the promt from data/prompt.txt with open("data/prompt.txt", "r") as prompt_file: diff --git a/scripts/execute_code.py b/scripts/execute_code.py index cfd818d4..01b454a0 100644 --- a/scripts/execute_code.py +++ b/scripts/execute_code.py @@ -3,6 +3,7 @@ import os def execute_python_file(file): + """Execute a Python file in a Docker container and return the output""" workspace_folder = "auto_gpt_workspace" if not file.endswith(".py"): diff --git a/scripts/file_operations.py b/scripts/file_operations.py index 62b3dc4b..d92709fb 100644 --- a/scripts/file_operations.py +++ b/scripts/file_operations.py @@ -9,6 +9,7 @@ if not os.path.exists(working_directory): def safe_join(base, *paths): + """Join one or more path components intelligently.""" new_path = os.path.join(base, *paths) norm_new_path = os.path.normpath(new_path) @@ -19,6 +20,7 @@ def safe_join(base, *paths): def read_file(filename): + """Read a file and return the contents""" try: filepath = safe_join(working_directory, filename) with open(filepath, "r") as f: @@ -29,6 +31,7 @@ def read_file(filename): def write_to_file(filename, text): + """Write text to a file""" try: filepath = safe_join(working_directory, filename) with open(filepath, "w") as f: @@ -39,6 +42,7 @@ def write_to_file(filename, text): def append_to_file(filename, text): + """Append text to a file""" try: filepath = safe_join(working_directory, filename) with open(filepath, "a") as f: @@ -49,6 +53,7 @@ def append_to_file(filename, text): def delete_file(filename): + """Delete a file""" try: filepath = safe_join(working_directory, filename) os.remove(filepath) diff --git a/scripts/keys.py b/scripts/keys.py index 1cd439cd..dbb3b91a 100644 --- a/scripts/keys.py +++ b/scripts/keys.py @@ -1,3 +1,4 @@ +# This file contains the API keys for the various APIs used in the project. # Get yours from: https://beta.openai.com/account/api-keys OPENAI_API_KEY = "YOUR-OPENAI-KEY" # To access your ElevenLabs API key, head to https://elevenlabs.io, you diff --git a/scripts/main.py b/scripts/main.py index d51ad0fc..298fa95c 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -14,6 +14,7 @@ from config import Config class Argument(Enum): + """This class is used to define the different arguments that can be passed""" CONTINUOUS_MODE = "continuous-mode" SPEAK_MODE = "speak-mode" @@ -25,6 +26,7 @@ def print_to_console( speak_text=False, min_typing_speed=0.05, max_typing_speed=0.01): + """Prints text to the console with a typing effect""" global cfg if speak_text and cfg.speak_mode: speak.say_text(f"{title}. {content}") @@ -44,6 +46,7 @@ def print_to_console( def print_assistant_thoughts(assistant_reply): + """Prints the assistant's thoughts to the console""" global ai_name global cfg try: @@ -102,6 +105,7 @@ def print_assistant_thoughts(assistant_reply): def construct_prompt(): + """Constructs the prompt for the AI""" global ai_name # Construct the prompt print_to_console( @@ -165,6 +169,7 @@ def construct_prompt(): def parse_arguments(): + """Parses the arguments passed to the script""" global cfg cfg.set_continuous_mode(False) cfg.set_speak_mode(False) diff --git a/scripts/speak.py b/scripts/speak.py index 13ceb8d9..db05a024 100644 --- a/scripts/speak.py +++ b/scripts/speak.py @@ -12,6 +12,7 @@ tts_headers = { def say_text(text, voice_index=0): + """Say text using ElevenLabs API""" tts_url = "https://api.elevenlabs.io/v1/text-to-speech/{voice_id}".format( voice_id=voices[voice_index]) diff --git a/scripts/spinner.py b/scripts/spinner.py index 2a48dfec..df39dbbd 100644 --- a/scripts/spinner.py +++ b/scripts/spinner.py @@ -5,7 +5,9 @@ import time class Spinner: + """A simple spinner class""" def __init__(self, message="Loading...", delay=0.1): + """Initialize the spinner class""" self.spinner = itertools.cycle(['-', '/', '|', '\\']) self.delay = delay self.message = message @@ -13,6 +15,7 @@ class Spinner: self.spinner_thread = None def spin(self): + """Spin the spinner""" while self.running: sys.stdout.write(next(self.spinner) + " " + self.message + "\r") sys.stdout.flush() @@ -20,11 +23,13 @@ class Spinner: sys.stdout.write('\b' * (len(self.message) + 2)) def __enter__(self): + """Start the spinner""" self.running = True self.spinner_thread = threading.Thread(target=self.spin) self.spinner_thread.start() def __exit__(self, exc_type, exc_value, exc_traceback): + """Stop the spinner""" self.running = False self.spinner_thread.join() sys.stdout.write('\r' + ' ' * (len(self.message) + 2) + '\r') From 5c02bfa4de5b2ef4aa3bac2a10a3b1d10f0fca9f Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Mon, 3 Apr 2023 13:38:56 +0200 Subject: [PATCH 02/26] Update .gitignore Ignore venv folder --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4d084445..d47b8396 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ scripts/__pycache__/keys.cpython-310.pyc package-lock.json *.pyc scripts/auto_gpt_workspace/* -*.mpeg \ No newline at end of file +*.mpeg +venv/* \ No newline at end of file From 765210f0cd7a40cac8d82be55b4543fa1b17e388 Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Mon, 3 Apr 2023 14:10:02 +0200 Subject: [PATCH 03/26] Add extra documentation --- scripts/ai_config.py | 6 +++++- scripts/call_ai_function.py | 1 + scripts/config.py | 6 ++++++ scripts/file_operations.py | 2 +- scripts/json_parser.py | 2 ++ scripts/llm_utils.py | 1 + scripts/main.py | 3 ++- 7 files changed, 18 insertions(+), 3 deletions(-) diff --git a/scripts/ai_config.py b/scripts/ai_config.py index 945fcfb2..42d227d0 100644 --- a/scripts/ai_config.py +++ b/scripts/ai_config.py @@ -3,7 +3,9 @@ import data class AIConfig: + """Class to store the AI's name, role, and goals.""" def __init__(self, ai_name="", ai_role="", ai_goals=[]): + """Initialize the AIConfig class""" self.ai_name = ai_name self.ai_role = ai_role self.ai_goals = ai_goals @@ -13,7 +15,7 @@ class AIConfig: @classmethod def load(cls, config_file=SAVE_FILE): - # Load variables from yaml file if it exists + """Load variables from yaml file if it exists, otherwise use defaults.""" try: with open(config_file) as file: config_params = yaml.load(file, Loader=yaml.FullLoader) @@ -27,11 +29,13 @@ class AIConfig: return cls(ai_name, ai_role, ai_goals) def save(self, config_file=SAVE_FILE): + """Save variables to yaml file.""" config = {"ai_name": self.ai_name, "ai_role": self.ai_role, "ai_goals": self.ai_goals} with open(config_file, "w") as file: yaml.dump(config, file) def construct_full_prompt(self): + """Construct the full prompt for the AI to use.""" prompt_start = """Your decisions must always be made independently without seeking user assistance. Play to your strengths as an LLM and pursue simple strategies with no legal complications.""" # Construct full prompt diff --git a/scripts/call_ai_function.py b/scripts/call_ai_function.py index 0c864b49..83c87687 100644 --- a/scripts/call_ai_function.py +++ b/scripts/call_ai_function.py @@ -6,6 +6,7 @@ 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=cfg.smart_llm_model): + """Call an AI function with the given args and description.""" # For each arg, if any are None, convert to "None": args = [str(arg) if arg is not None else "None" for arg in args] # parse args to comma seperated string diff --git a/scripts/config.py b/scripts/config.py index fa3bf7cc..d98cb698 100644 --- a/scripts/config.py +++ b/scripts/config.py @@ -51,21 +51,27 @@ class Config(metaclass=Singleton): self.speak_mode = value def set_fast_llm_model(self, value: str): + """Set the fast LLM model value.""" self.fast_llm_model = value def set_smart_llm_model(self, value: str): + """Set the smart LLM model value.""" self.smart_llm_model = value def set_fast_token_limit(self, value: int): + """Set the fast token limit value.""" self.fast_token_limit = value def set_smart_token_limit(self, value: int): + """Set the smart token limit value.""" self.smart_token_limit = value def set_openai_api_key(self, value: str): + """Set the OpenAI API key value.""" self.apiopenai_api_key_key = value def set_elevenlabs_api_key(self, value: str): + """Set the ElevenLabs API key value.""" self.elevenlabs_api_key = value diff --git a/scripts/file_operations.py b/scripts/file_operations.py index d92709fb..f58d2cbc 100644 --- a/scripts/file_operations.py +++ b/scripts/file_operations.py @@ -3,7 +3,7 @@ import os.path # Set a dedicated folder for file I/O working_directory = "auto_gpt_workspace" - +# Create the directory if it doesn't exist if not os.path.exists(working_directory): os.makedirs(working_directory) diff --git a/scripts/json_parser.py b/scripts/json_parser.py index 8154b584..edd67305 100644 --- a/scripts/json_parser.py +++ b/scripts/json_parser.py @@ -4,6 +4,7 @@ from config import Config cfg = Config() def fix_and_parse_json(json_str: str, try_to_fix_with_gpt: bool = True): + """Fix and parse the given JSON string.""" json_schema = """ { "command": { @@ -50,6 +51,7 @@ def fix_and_parse_json(json_str: str, try_to_fix_with_gpt: bool = True): # TODO: Make debug a global config var def fix_json(json_str: str, schema: str, debug=False) -> str: + """Fix the given JSON string to make it parseable and fully complient with the provided schema.""" # Try to fix the JSON using gpt: function_string = "def fix_json(json_str: str, schema:str=None) -> str:" args = [json_str, schema] diff --git a/scripts/llm_utils.py b/scripts/llm_utils.py index 41f39625..c512e997 100644 --- a/scripts/llm_utils.py +++ b/scripts/llm_utils.py @@ -6,6 +6,7 @@ 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: + """Create a chat completion using the OpenAI API.""" response = openai.ChatCompletion.create( model=model, messages=messages, diff --git a/scripts/main.py b/scripts/main.py index b4236c52..b0aef178 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -117,7 +117,7 @@ def print_assistant_thoughts(assistant_reply): print_to_console("Error: \n", Fore.RED, call_stack) def load_variables(config_file="config.yaml"): - # Load variables from yaml file if it exists + """Load variables from yaml file if it exists, otherwise prompt the user for input""" try: with open(config_file) as file: config = yaml.load(file, Loader=yaml.FullLoader) @@ -200,6 +200,7 @@ Continue (y/n): """) def prompt_user(): + """Prompt the user for input""" ai_name = "" # Construct the prompt print_to_console( From 5ced5cae3aad0e2a399e24e2671cc12e0f18a6c8 Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Mon, 3 Apr 2023 14:10:15 +0200 Subject: [PATCH 04/26] Update Dockerfile The requirements file wasn't on the file system. --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c67291c8..d2a127c7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM python:3.11 WORKDIR /app COPY scripts/ /app - +COPY requirements.txt /app/requirements.txt RUN pip install -r requirements.txt CMD ["python", "main.py"] From b6344b98e241eb2d9607a54d9a4d9efc09f7bb8f Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 10:46:02 +0200 Subject: [PATCH 05/26] Update main.py Add separation between code blocks. --- scripts/main.py | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/scripts/main.py b/scripts/main.py index 0ec8978f..8f0400ae 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -27,17 +27,24 @@ def print_to_console( max_typing_speed=0.01): """Prints text to the console with a typing effect""" global cfg + if speak_text and cfg.speak_mode: speak.say_text(f"{title}. {content}") + print(title_color + title + " " + Style.RESET_ALL, end="") + if content: + if isinstance(content, list): content = " ".join(content) words = content.split() + for i, word in enumerate(words): print(word, end="", flush=True) + if i < len(words) - 1: print(" ", end="", flush=True) + typing_speed = random.uniform(min_typing_speed, max_typing_speed) time.sleep(typing_speed) # type faster after each word @@ -73,6 +80,7 @@ def print_assistant_thoughts(assistant_reply): if assistant_thoughts_plan: print_to_console("PLAN:", Fore.YELLOW, "") # If it's a list, join it into a string + if isinstance(assistant_thoughts_plan, list): assistant_thoughts_plan = "\n".join(assistant_thoughts_plan) elif isinstance(assistant_thoughts_plan, dict): @@ -80,6 +88,7 @@ def print_assistant_thoughts(assistant_reply): # Split the input_string using the newline character and dashes lines = assistant_thoughts_plan.split('\n') + for line in lines: line = line.lstrip("- ") print_to_console("- ", Fore.GREEN, line.strip()) @@ -114,11 +123,13 @@ def load_variables(config_file="config.yaml"): # Prompt the user for input if config file is missing or empty values if not ai_name: ai_name = input("Name your AI: ") + if ai_name == "": ai_name = "Entrepreneur-GPT" if not ai_role: ai_role = input(f"{ai_name} is: ") + if ai_role == "": ai_role = "an AI designed to autonomously develop and run businesses with the sole goal of increasing your net worth." @@ -127,16 +138,20 @@ def load_variables(config_file="config.yaml"): print("For example: \nIncrease net worth, Grow Twitter Account, Develop and manage multiple businesses autonomously'") print("Enter nothing to load defaults, enter nothing when finished.") ai_goals = [] + for i in range(5): ai_goal = input(f"Goal {i+1}: ") + if ai_goal == "": break ai_goals.append(ai_goal) + if len(ai_goals) == 0: ai_goals = ["Increase net worth", "Grow Twitter Account", "Develop and manage multiple businesses autonomously"] # Save variables to yaml file config = {"ai_name": ai_name, "ai_role": ai_role, "ai_goals": ai_goals} + with open(config_file, "w") as file: documents = yaml.dump(config, file) @@ -145,6 +160,7 @@ def load_variables(config_file="config.yaml"): # Construct full prompt full_prompt = f"You are {ai_name}, {ai_role}\n{prompt_start}\n\nGOALS:\n\n" + for i, goal in enumerate(ai_goals): full_prompt += f"{i+1}. {goal}\n" @@ -155,6 +171,7 @@ def load_variables(config_file="config.yaml"): def construct_prompt(): """Construct the prompt for the AI to respond to""" config = AIConfig.load() + if config.ai_name: print_to_console( f"Welcome back! ", @@ -162,10 +179,11 @@ def construct_prompt(): f"Would you like me to return to being {config.ai_name}?", speak_text=True) should_continue = input(f"""Continue with the last settings? -Name: {config.ai_name} -Role: {config.ai_role} -Goals: {config.ai_goals} -Continue (y/n): """) + Name: {config.ai_name} + Role: {config.ai_role} + Goals: {config.ai_goals} + Continue (y/n): """) + if should_continue.lower() == "n": config = AIConfig() @@ -196,7 +214,9 @@ def prompt_user(): "Name your AI: ", Fore.GREEN, "For example, 'Entrepreneur-GPT'") + ai_name = input("AI Name: ") + if ai_name == "": ai_name = "Entrepreneur-GPT" @@ -212,6 +232,7 @@ def prompt_user(): Fore.GREEN, "For example, 'an AI designed to autonomously develop and run businesses with the sole goal of increasing your net worth.'") ai_role = input(f"{ai_name} is: ") + if ai_role == "": ai_role = "an AI designed to autonomously develop and run businesses with the sole goal of increasing your net worth." @@ -220,13 +241,18 @@ def prompt_user(): "Enter up to 5 goals for your AI: ", Fore.GREEN, "For example: \nIncrease net worth, Grow Twitter Account, Develop and manage multiple businesses autonomously'") + print("Enter nothing to load defaults, enter nothing when finished.", flush=True) ai_goals = [] + for i in range(5): ai_goal = input(f"{Fore.LIGHTBLUE_EX}Goal{Style.RESET_ALL} {i+1}: ") + if ai_goal == "": break + ai_goals.append(ai_goal) + if len(ai_goals) == 0: ai_goals = ["Increase net worth", "Grow Twitter Account", "Develop and manage multiple businesses autonomously"] @@ -234,6 +260,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 @@ -307,11 +334,11 @@ while True: "NEXT ACTION: ", Fore.CYAN, f"COMMAND = {Fore.CYAN}{command_name}{Style.RESET_ALL} ARGUMENTS = {Fore.CYAN}{arguments}{Style.RESET_ALL}") - print( - "Enter 'y' to authorise command or 'n' to exit program...", - flush=True) + print("Enter 'y' to authorise command or 'n' to exit program...", 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 From cd164648ba8a9368bde00d5812a96ed569ea0d76 Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 10:47:04 +0200 Subject: [PATCH 06/26] Update ai_config.py Add separation between code blocks. --- scripts/ai_config.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/ai_config.py b/scripts/ai_config.py index 42d227d0..0b521b7d 100644 --- a/scripts/ai_config.py +++ b/scripts/ai_config.py @@ -13,6 +13,7 @@ class AIConfig: # Soon this will go in a folder where it remembers more stuff about the run(s) SAVE_FILE = "last_run_ai_settings.yaml" + @classmethod def load(cls, config_file=SAVE_FILE): """Load variables from yaml file if it exists, otherwise use defaults.""" @@ -28,18 +29,21 @@ class AIConfig: return cls(ai_name, ai_role, ai_goals) + def save(self, config_file=SAVE_FILE): """Save variables to yaml file.""" config = {"ai_name": self.ai_name, "ai_role": self.ai_role, "ai_goals": self.ai_goals} with open(config_file, "w") as file: yaml.dump(config, file) + def construct_full_prompt(self): """Construct the full prompt for the AI to use.""" prompt_start = """Your decisions must always be made independently without seeking user assistance. Play to your strengths as an LLM and pursue simple strategies with no legal complications.""" # Construct full prompt full_prompt = f"You are {self.ai_name}, {self.ai_role}\n{prompt_start}\n\nGOALS:\n\n" + for i, goal in enumerate(self.ai_goals): full_prompt += f"{i+1}. {goal}\n" From 27bf7c47e98a3c8fbb660b6fa00f6d61771863d4 Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 10:48:19 +0200 Subject: [PATCH 07/26] Update ai_functions.py Unnecessary spaces --- scripts/ai_functions.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/scripts/ai_functions.py b/scripts/ai_functions.py index eb524b9b..f93d7ea6 100644 --- a/scripts/ai_functions.py +++ b/scripts/ai_functions.py @@ -6,7 +6,6 @@ from json_parser import fix_and_parse_json cfg = Config() # Evaluating code - def evaluate_code(code: str) -> List[str]: """Evaluates the given code and returns a list of suggestions for improvements.""" function_string = "def analyze_code(code: str) -> List[str]:" @@ -19,7 +18,6 @@ def evaluate_code(code: str) -> List[str]: # Improving code - def improve_code(suggestions: List[str], code: str) -> str: """Improves the provided code based on the suggestions provided, making no other changes.""" function_string = ( @@ -33,8 +31,6 @@ def improve_code(suggestions: List[str], code: str) -> str: # Writing tests - - def write_tests(code: str, focus: List[str]) -> str: """Generates test cases for the existing code, focusing on specific areas if required.""" function_string = ( From 1b4a5301d0d4406732b8e903af1bfda8e7552a6d Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 10:49:28 +0200 Subject: [PATCH 08/26] Update ai_functions.py Just import dumps from JSON library. --- scripts/ai_functions.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/ai_functions.py b/scripts/ai_functions.py index f93d7ea6..eb6dbd93 100644 --- a/scripts/ai_functions.py +++ b/scripts/ai_functions.py @@ -1,5 +1,5 @@ from typing import List, Optional -import json +from json import dumps from config import Config from call_ai_function import call_ai_function from json_parser import fix_and_parse_json @@ -23,7 +23,7 @@ def improve_code(suggestions: List[str], code: str) -> str: function_string = ( "def generate_improved_code(suggestions: List[str], code: str) -> str:" ) - args = [json.dumps(suggestions), code] + args = [dumps(suggestions), code] description_string = """Improves the provided code based on the suggestions provided, making no other changes.""" result_string = call_ai_function(function_string, args, description_string) @@ -36,7 +36,7 @@ def write_tests(code: str, focus: List[str]) -> str: function_string = ( "def create_test_cases(code: str, focus: Optional[str] = None) -> str:" ) - args = [code, json.dumps(focus)] + args = [code, dumps(focus)] description_string = """Generates test cases for the existing code, focusing on specific areas if required.""" result_string = call_ai_function(function_string, args, description_string) From 39f758ba5ceaac927c50f3bacb94e4b24c5f0706 Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 10:53:47 +0200 Subject: [PATCH 09/26] Update browse.py Add separation between code blocks and standardize dictionary definition. --- scripts/browse.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/scripts/browse.py b/scripts/browse.py index 8a10ddd6..85f7bc6c 100644 --- a/scripts/browse.py +++ b/scripts/browse.py @@ -5,6 +5,7 @@ from llm_utils import create_chat_completion cfg = Config() + def scrape_text(url): """Scrape text from a webpage""" response = requests.get(url) @@ -29,16 +30,20 @@ def scrape_text(url): def extract_hyperlinks(soup): """Extract hyperlinks from a BeautifulSoup object""" hyperlinks = [] + for link in soup.find_all('a', href=True): hyperlinks.append((link.text, link['href'])) + return hyperlinks def format_hyperlinks(hyperlinks): """Format hyperlinks into a list of strings""" formatted_links = [] + for link_text, link_url in hyperlinks: formatted_links.append(f"{link_text} ({link_url})") + return formatted_links @@ -67,6 +72,7 @@ def split_text(text, max_length=8192): current_chunk = [] for paragraph in paragraphs: + if current_length + len(paragraph) + 1 <= max_length: current_chunk.append(paragraph) current_length += len(paragraph) + 1 @@ -90,19 +96,22 @@ def summarize_text(text, is_website=True): for i, chunk in enumerate(chunks): print("Summarizing chunk " + str(i + 1) + " / " + str(len(chunks))) + if is_website: messages = [ { "role": "user", "content": "Please summarize the following website text, do not describe the general website, but instead concisely extract the specific information this subpage contains.: " + - chunk}, + chunk + } ] else: messages = [ { "role": "user", "content": "Please summarize the following text, focusing on extracting concise and specific information: " + - chunk}, + chunk + } ] summary = create_chat_completion( @@ -121,14 +130,16 @@ def summarize_text(text, is_website=True): { "role": "user", "content": "Please summarize the following website text, do not describe the general website, but instead concisely extract the specific information this subpage contains.: " + - combined_summary}, + combined_summary + } ] else: messages = [ { "role": "user", "content": "Please summarize the following text, focusing on extracting concise and specific infomation: " + - combined_summary}, + combined_summary + } ] final_summary = create_chat_completion( From 772d4beb218e66b38347a265640d15dc8bc304b6 Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 10:54:52 +0200 Subject: [PATCH 10/26] Update browse.py Just import GET from requests library. --- scripts/browse.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/browse.py b/scripts/browse.py index 85f7bc6c..20ffc035 100644 --- a/scripts/browse.py +++ b/scripts/browse.py @@ -1,4 +1,4 @@ -import requests +from requests import get from bs4 import BeautifulSoup from config import Config from llm_utils import create_chat_completion @@ -8,7 +8,7 @@ cfg = Config() def scrape_text(url): """Scrape text from a webpage""" - response = requests.get(url) + response = get(url) # Check if the response contains an HTTP error if response.status_code >= 400: @@ -49,7 +49,7 @@ def format_hyperlinks(hyperlinks): def scrape_links(url): """Scrape hyperlinks from a webpage""" - response = requests.get(url) + response = get(url) # Check if the response contains an HTTP error if response.status_code >= 400: From 1b7b367ce9e0455caf7ec2efbb0b5f4701bd2a51 Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 10:56:56 +0200 Subject: [PATCH 11/26] Update call_ai_function.py Standardize importation of libraries to top. --- scripts/call_ai_function.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/call_ai_function.py b/scripts/call_ai_function.py index 83c87687..44f9fd8c 100644 --- a/scripts/call_ai_function.py +++ b/scripts/call_ai_function.py @@ -1,7 +1,7 @@ from config import Config +from llm_utils import create_chat_completion 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. From 238824553ae8626af1e8e27218d947a859a220ac Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 10:58:38 +0200 Subject: [PATCH 12/26] Update chat.py Standardize importation of libraries to top. --- scripts/chat.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/chat.py b/scripts/chat.py index c526be15..819e0881 100644 --- a/scripts/chat.py +++ b/scripts/chat.py @@ -3,10 +3,8 @@ import openai from dotenv import load_dotenv from config import Config import token_counter - -cfg = Config() - from llm_utils import create_chat_completion +cfg = Config() def create_chat_message(role, content): @@ -50,8 +48,10 @@ def chat_with_ai( """ model = cfg.fast_llm_model # TODO: Change model from hardcode to argument # Reserve 1000 tokens for the response + if debug: print(f"Token limit: {token_limit}") + send_token_limit = token_limit - 1000 current_context = [ From 500b2b48367566708829a9f5ce4eb4c4d9c4acde Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 11:02:01 +0200 Subject: [PATCH 13/26] Update chat.py Adds code separation between code blocks. --- scripts/chat.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/chat.py b/scripts/chat.py index 819e0881..dd52e784 100644 --- a/scripts/chat.py +++ b/scripts/chat.py @@ -73,6 +73,7 @@ def chat_with_ai( message_to_add = full_message_history[next_message_to_add_index] tokens_to_add = token_counter.count_message_tokens([message_to_add], model) + if current_tokens_used + tokens_to_add > send_token_limit: break @@ -98,13 +99,16 @@ def chat_with_ai( print(f"Send Token Count: {current_tokens_used}") print(f"Tokens remaining for response: {tokens_remaining}") print("------------ CONTEXT SENT TO AI ---------------") + for message in current_context: # Skip printing the prompt + if message["role"] == "system" and message["content"] == prompt: continue print( f"{message['role'].capitalize()}: {message['content']}") print() + print("----------- END OF CONTEXT ----------------") # TODO: use a model defined elsewhere, so that model can contain temperature and other settings we care about From 9699a1ca78a18188c45ba09bc6b07f69624bd8bc Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 11:03:09 +0200 Subject: [PATCH 14/26] Update chat.py Just import sleep from time library. --- scripts/chat.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/chat.py b/scripts/chat.py index dd52e784..17e36879 100644 --- a/scripts/chat.py +++ b/scripts/chat.py @@ -1,4 +1,4 @@ -import time +from time import sleep import openai from dotenv import load_dotenv from config import Config @@ -130,4 +130,4 @@ def chat_with_ai( except openai.error.RateLimitError: # TODO: WHen we switch to langchain, this is built in print("Error: ", "API Rate Limit Reached. Waiting 10 seconds...") - time.sleep(10) + sleep(10) From 632d87c195ed52da45d4150c8d6eb64bbc96f243 Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 11:28:15 +0200 Subject: [PATCH 15/26] Update commands.py Just import datetime from datetime library. --- scripts/commands.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/commands.py b/scripts/commands.py index 42fe1ebb..7873c048 100644 --- a/scripts/commands.py +++ b/scripts/commands.py @@ -1,7 +1,7 @@ import browse import json import memory as mem -import datetime +from datetime import datetime import agent_manager as agents import speak from config import Config @@ -110,7 +110,7 @@ def execute_command(command_name, arguments): def get_datetime(): """Return the current date and time""" return "Current date and time: " + \ - datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + datetime.now().strftime("%Y-%m-%d %H:%M:%S") def google_search(query, num_results=8): @@ -122,6 +122,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 from googleapiclient.errors import HttpError import json From 8053ecd5c6f7c2ce7a3363acdb31063b8d91f5af Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 11:29:02 +0200 Subject: [PATCH 16/26] Update config.py Introduce spaces between code blocks. --- scripts/config.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/scripts/config.py b/scripts/config.py index c7d04bf8..0650535f 100644 --- a/scripts/config.py +++ b/scripts/config.py @@ -44,42 +44,52 @@ class Config(metaclass=Singleton): # Initialize the OpenAI API client openai.api_key = self.openai_api_key + def set_continuous_mode(self, value: bool): """Set the continuous mode value.""" self.continuous_mode = value + def set_speak_mode(self, value: bool): """Set the speak mode value.""" self.speak_mode = value + def set_fast_llm_model(self, value: str): """Set the fast LLM model value.""" self.fast_llm_model = value + def set_smart_llm_model(self, value: str): """Set the smart LLM model value.""" self.smart_llm_model = value + def set_fast_token_limit(self, value: int): """Set the fast token limit value.""" self.fast_token_limit = value + def set_smart_token_limit(self, value: int): """Set the smart token limit value.""" self.smart_token_limit = value + def set_openai_api_key(self, value: str): """Set the OpenAI API key value.""" self.openai_api_key = value - + + def set_elevenlabs_api_key(self, value: str): """Set the ElevenLabs API key value.""" self.elevenlabs_api_key = value - + + def set_google_api_key(self, value: str): """Set the Google API key value.""" self.google_api_key = value - + + def set_custom_search_engine_id(self, value: str): """Set the custom search engine ID value.""" - self.custom_search_engine_id = value \ No newline at end of file + self.custom_search_engine_id = value From 1632f7ebf6332642ceedd97587dad6f76bc46740 Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 11:30:20 +0200 Subject: [PATCH 17/26] Update data.py Just import path from OS library. --- scripts/data.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/data.py b/scripts/data.py index 22393844..bb8936c1 100644 --- a/scripts/data.py +++ b/scripts/data.py @@ -1,4 +1,4 @@ -import os +from os import path from pathlib import Path @@ -6,7 +6,7 @@ def load_prompt(): """Load the prompt from data/prompt.txt""" try: # get directory of this file: - file_dir = Path(os.path.dirname(os.path.realpath(__file__))) + file_dir = Path(path.dirname(path.realpath(__file__))) data_dir = file_dir / "data" prompt_file = data_dir / "prompt.txt" # Load the promt from data/prompt.txt From d450ac3a0b489bf820d2c3794b08955054d1f543 Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 11:31:20 +0200 Subject: [PATCH 18/26] Update execute_code.py Just import path from OS library. --- scripts/execute_code.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/execute_code.py b/scripts/execute_code.py index f34469dd..22ae1047 100644 --- a/scripts/execute_code.py +++ b/scripts/execute_code.py @@ -1,5 +1,5 @@ import docker -import os +from os import path def execute_python_file(file): @@ -11,9 +11,9 @@ def execute_python_file(file): if not file.endswith(".py"): return "Error: Invalid file type. Only .py files are allowed." - file_path = os.path.join(workspace_folder, file) + file_path = path.join(workspace_folder, file) - if not os.path.isfile(file_path): + if not path.isfile(file_path): return f"Error: File '{file}' does not exist." try: From 1d10236a63e4535a7a16aa01f500d9932760f651 Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 11:32:55 +0200 Subject: [PATCH 19/26] Update file_operations.py Introduces spaces between code blocks. --- scripts/file_operations.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/file_operations.py b/scripts/file_operations.py index 65664e60..cb054616 100644 --- a/scripts/file_operations.py +++ b/scripts/file_operations.py @@ -3,6 +3,7 @@ import os.path # Set a dedicated folder for file I/O working_directory = "auto_gpt_workspace" + # Create the directory if it doesn't exist if not os.path.exists(working_directory): os.makedirs(working_directory) @@ -35,8 +36,10 @@ def write_to_file(filename, text): try: filepath = safe_join(working_directory, filename) directory = os.path.dirname(filepath) + if not os.path.exists(directory): os.makedirs(directory) + with open(filepath, "w") as f: f.write(text) return "File written to successfully." From 621f18eba79f8a31aed2da88bc9b26007c21f1ec Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 11:34:28 +0200 Subject: [PATCH 20/26] Update json_parser.py Introduces spaces between code blocks. --- scripts/json_parser.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/json_parser.py b/scripts/json_parser.py index 5153f71b..e827b753 100644 --- a/scripts/json_parser.py +++ b/scripts/json_parser.py @@ -1,6 +1,7 @@ import json from call_ai_function import call_ai_function from config import Config + cfg = Config() def fix_and_parse_json(json_str: str, try_to_fix_with_gpt: bool = True): @@ -37,15 +38,18 @@ def fix_and_parse_json(json_str: str, try_to_fix_with_gpt: bool = True): json_str = json_str[:last_brace_index+1] return json.loads(json_str) except Exception as e: + if try_to_fix_with_gpt: print(f"Warning: Failed to parse AI output, attempting to fix.\n If you see this warning frequently, it's likely that your prompt is confusing the AI. Try changing it up slightly.") # Now try to fix this up using the ai_functions ai_fixed_json = fix_json(json_str, json_schema, False) + if ai_fixed_json != "failed": return json.loads(ai_fixed_json) else: print(f"Failed to fix ai output, telling the AI.") # This allows the AI to react to the error message, which usually results in it correcting its ways. return json_str + else: raise e @@ -59,15 +63,18 @@ def fix_json(json_str: str, schema: str, debug=False) -> str: # If it doesn't already start with a "`", add one: if not json_str.startswith("`"): json_str = "```json\n" + json_str + "\n```" + result_string = call_ai_function( function_string, args, description_string, model=cfg.fast_llm_model ) + if debug: print("------------ JSON FIX ATTEMPT ---------------") print(f"Original JSON: {json_str}") print("-----------") print(f"Fixed JSON: {result_string}") print("----------- END OF FIX ATTEMPT ----------------") + try: return json.loads(result_string) except: From 62615cacc9532bcae1fe94d4ef27e10610edd758 Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Tue, 4 Apr 2023 11:36:50 +0200 Subject: [PATCH 21/26] Adds necessary spaces Introduces spaces between code blocks. --- scripts/llm_utils.py | 1 + scripts/speak.py | 4 ++-- scripts/spinner.py | 3 +++ scripts/token_counter.py | 6 ++++++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/scripts/llm_utils.py b/scripts/llm_utils.py index c512e997..2981c8a0 100644 --- a/scripts/llm_utils.py +++ b/scripts/llm_utils.py @@ -1,5 +1,6 @@ import openai from config import Config + cfg = Config() openai.api_key = cfg.openai_api_key diff --git a/scripts/speak.py b/scripts/speak.py index 1e0eb408..5a0728a2 100644 --- a/scripts/speak.py +++ b/scripts/speak.py @@ -2,6 +2,7 @@ import os from playsound import playsound import requests from config import Config + cfg = Config() # TODO: Nicer names for these ids @@ -18,8 +19,7 @@ def say_text(text, voice_index=0): voice_id=voices[voice_index]) formatted_message = {"text": text} - response = requests.post( - tts_url, headers=tts_headers, json=formatted_message) + response = requests.post(tts_url, headers=tts_headers, json=formatted_message) if response.status_code == 200: with open("speech.mpeg", "wb") as f: diff --git a/scripts/spinner.py b/scripts/spinner.py index df39dbbd..2b79ae26 100644 --- a/scripts/spinner.py +++ b/scripts/spinner.py @@ -14,6 +14,7 @@ class Spinner: self.running = False self.spinner_thread = None + def spin(self): """Spin the spinner""" while self.running: @@ -22,12 +23,14 @@ class Spinner: time.sleep(self.delay) sys.stdout.write('\b' * (len(self.message) + 2)) + def __enter__(self): """Start the spinner""" self.running = True self.spinner_thread = threading.Thread(target=self.spin) self.spinner_thread.start() + def __exit__(self, exc_type, exc_value, exc_traceback): """Stop the spinner""" self.running = False diff --git a/scripts/token_counter.py b/scripts/token_counter.py index a28a9868..fc5b9c51 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. @@ -17,6 +18,7 @@ def count_message_tokens(messages : List[Dict[str, str]], model : str = "gpt-3.5 except KeyError: print("Warning: model not found. Using cl100k_base encoding.") encoding = tiktoken.get_encoding("cl100k_base") + if model == "gpt-3.5-turbo": # !Node: gpt-3.5-turbo may change over time. Returning num tokens assuming gpt-3.5-turbo-0301.") return count_message_tokens(messages, model="gpt-3.5-turbo-0301") @@ -32,15 +34,19 @@ def count_message_tokens(messages : List[Dict[str, str]], model : str = "gpt-3.5 else: raise NotImplementedError(f"""num_tokens_from_messages() is not implemented for model {model}. See https://github.com/openai/openai-python/blob/main/chatml.md for information on how messages are converted to tokens.""") num_tokens = 0 + for message in messages: num_tokens += tokens_per_message + for key, value in message.items(): num_tokens += len(encoding.encode(value)) + if key == "name": num_tokens += tokens_per_name 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. From 011699e6a1df18254d08f6ec0b0d6b482e02e690 Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Sun, 9 Apr 2023 15:39:11 +0200 Subject: [PATCH 22/26] Code review changes --- .gitignore | 2 +- Dockerfile | 2 +- scripts/ai_config.py | 2 -- scripts/ai_functions.py | 6 +++--- scripts/browse.py | 12 +++--------- scripts/call_ai_function.py | 4 ++-- scripts/chat.py | 14 ++++---------- scripts/commands.py | 4 ++-- scripts/config.py | 12 +----------- scripts/data.py | 4 ++-- scripts/execute_code.py | 6 +++--- scripts/file_operations.py | 2 -- scripts/json_parser.py | 6 ------ scripts/llm_utils.py | 1 - scripts/main.py | 36 ++++-------------------------------- scripts/speak.py | 4 ++-- scripts/spinner.py | 3 --- scripts/token_counter.py | 6 ------ 18 files changed, 28 insertions(+), 98 deletions(-) diff --git a/.gitignore b/.gitignore index fc20dfd2..6b8f00b5 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,4 @@ scripts/auto_gpt_workspace/* *.mpeg .env last_run_ai_settings.yaml -outputs/* +outputs/* \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index d2a127c7..c67291c8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM python:3.11 WORKDIR /app COPY scripts/ /app -COPY requirements.txt /app/requirements.txt + RUN pip install -r requirements.txt CMD ["python", "main.py"] diff --git a/scripts/ai_config.py b/scripts/ai_config.py index 0b521b7d..de214463 100644 --- a/scripts/ai_config.py +++ b/scripts/ai_config.py @@ -13,7 +13,6 @@ class AIConfig: # Soon this will go in a folder where it remembers more stuff about the run(s) SAVE_FILE = "last_run_ai_settings.yaml" - @classmethod def load(cls, config_file=SAVE_FILE): """Load variables from yaml file if it exists, otherwise use defaults.""" @@ -29,7 +28,6 @@ class AIConfig: return cls(ai_name, ai_role, ai_goals) - def save(self, config_file=SAVE_FILE): """Save variables to yaml file.""" config = {"ai_name": self.ai_name, "ai_role": self.ai_role, "ai_goals": self.ai_goals} diff --git a/scripts/ai_functions.py b/scripts/ai_functions.py index eb6dbd93..f93d7ea6 100644 --- a/scripts/ai_functions.py +++ b/scripts/ai_functions.py @@ -1,5 +1,5 @@ from typing import List, Optional -from json import dumps +import json from config import Config from call_ai_function import call_ai_function from json_parser import fix_and_parse_json @@ -23,7 +23,7 @@ def improve_code(suggestions: List[str], code: str) -> str: function_string = ( "def generate_improved_code(suggestions: List[str], code: str) -> str:" ) - args = [dumps(suggestions), code] + args = [json.dumps(suggestions), code] description_string = """Improves the provided code based on the suggestions provided, making no other changes.""" result_string = call_ai_function(function_string, args, description_string) @@ -36,7 +36,7 @@ def write_tests(code: str, focus: List[str]) -> str: function_string = ( "def create_test_cases(code: str, focus: Optional[str] = None) -> str:" ) - args = [code, dumps(focus)] + args = [code, json.dumps(focus)] description_string = """Generates test cases for the existing code, focusing on specific areas if required.""" result_string = call_ai_function(function_string, args, description_string) diff --git a/scripts/browse.py b/scripts/browse.py index 3fde8d25..89e41af4 100644 --- a/scripts/browse.py +++ b/scripts/browse.py @@ -1,14 +1,13 @@ -from requests import get +import requests from bs4 import BeautifulSoup from config import Config from llm_utils import create_chat_completion cfg = Config() - def scrape_text(url): """Scrape text from a webpage""" - response = get(url) + response = requests.get(url) # Check if the response contains an HTTP error if response.status_code >= 400: @@ -30,26 +29,22 @@ def scrape_text(url): def extract_hyperlinks(soup): """Extract hyperlinks from a BeautifulSoup object""" hyperlinks = [] - for link in soup.find_all('a', href=True): hyperlinks.append((link.text, link['href'])) - return hyperlinks def format_hyperlinks(hyperlinks): """Format hyperlinks into a list of strings""" formatted_links = [] - for link_text, link_url in hyperlinks: formatted_links.append(f"{link_text} ({link_url})") - return formatted_links def scrape_links(url): """Scrape hyperlinks from a webpage""" - response = get(url) + response = requests.get(url) # Check if the response contains an HTTP error if response.status_code >= 400: @@ -72,7 +67,6 @@ def split_text(text, max_length=8192): current_chunk = [] for paragraph in paragraphs: - if current_length + len(paragraph) + 1 <= max_length: current_chunk.append(paragraph) current_length += len(paragraph) + 1 diff --git a/scripts/call_ai_function.py b/scripts/call_ai_function.py index 44f9fd8c..82cf1a76 100644 --- a/scripts/call_ai_function.py +++ b/scripts/call_ai_function.py @@ -1,8 +1,8 @@ from config import Config -from llm_utils import create_chat_completion + 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=cfg.smart_llm_model): diff --git a/scripts/chat.py b/scripts/chat.py index 17e36879..89a03509 100644 --- a/scripts/chat.py +++ b/scripts/chat.py @@ -1,11 +1,11 @@ -from time import sleep +import time import openai from dotenv import load_dotenv from config import Config import token_counter from llm_utils import create_chat_completion -cfg = Config() +cfg = Config() def create_chat_message(role, content): """ @@ -48,10 +48,8 @@ def chat_with_ai( """ model = cfg.fast_llm_model # TODO: Change model from hardcode to argument # Reserve 1000 tokens for the response - if debug: - print(f"Token limit: {token_limit}") - + print(f"Token limit: {token_limit}") send_token_limit = token_limit - 1000 current_context = [ @@ -73,7 +71,6 @@ def chat_with_ai( message_to_add = full_message_history[next_message_to_add_index] tokens_to_add = token_counter.count_message_tokens([message_to_add], model) - if current_tokens_used + tokens_to_add > send_token_limit: break @@ -99,16 +96,13 @@ def chat_with_ai( print(f"Send Token Count: {current_tokens_used}") print(f"Tokens remaining for response: {tokens_remaining}") print("------------ CONTEXT SENT TO AI ---------------") - for message in current_context: # Skip printing the prompt - if message["role"] == "system" and message["content"] == prompt: continue print( f"{message['role'].capitalize()}: {message['content']}") print() - print("----------- END OF CONTEXT ----------------") # TODO: use a model defined elsewhere, so that model can contain temperature and other settings we care about @@ -130,4 +124,4 @@ def chat_with_ai( except openai.error.RateLimitError: # TODO: WHen we switch to langchain, this is built in print("Error: ", "API Rate Limit Reached. Waiting 10 seconds...") - sleep(10) + time.sleep(10) diff --git a/scripts/commands.py b/scripts/commands.py index 134b3fd8..38912b48 100644 --- a/scripts/commands.py +++ b/scripts/commands.py @@ -1,7 +1,7 @@ import browse import json import memory as mem -from datetime import datetime +import datetime import agent_manager as agents import speak from config import Config @@ -110,7 +110,7 @@ def execute_command(command_name, arguments): def get_datetime(): """Return the current date and time""" return "Current date and time: " + \ - datetime.now().strftime("%Y-%m-%d %H:%M:%S") + datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") def google_search(query, num_results=8): diff --git a/scripts/config.py b/scripts/config.py index 0650535f..cf8fe7e7 100644 --- a/scripts/config.py +++ b/scripts/config.py @@ -44,52 +44,42 @@ class Config(metaclass=Singleton): # Initialize the OpenAI API client openai.api_key = self.openai_api_key - def set_continuous_mode(self, value: bool): """Set the continuous mode value.""" self.continuous_mode = value - def set_speak_mode(self, value: bool): """Set the speak mode value.""" self.speak_mode = value - def set_fast_llm_model(self, value: str): """Set the fast LLM model value.""" self.fast_llm_model = value - def set_smart_llm_model(self, value: str): """Set the smart LLM model value.""" self.smart_llm_model = value - def set_fast_token_limit(self, value: int): """Set the fast token limit value.""" self.fast_token_limit = value - def set_smart_token_limit(self, value: int): """Set the smart token limit value.""" self.smart_token_limit = value - def set_openai_api_key(self, value: str): """Set the OpenAI API key value.""" self.openai_api_key = value - def set_elevenlabs_api_key(self, value: str): """Set the ElevenLabs API key value.""" self.elevenlabs_api_key = value - def set_google_api_key(self, value: str): """Set the Google API key value.""" self.google_api_key = value - def set_custom_search_engine_id(self, value: str): """Set the custom search engine ID value.""" - self.custom_search_engine_id = value + self.custom_search_engine_id = value \ No newline at end of file diff --git a/scripts/data.py b/scripts/data.py index 7694329a..e0840dd9 100644 --- a/scripts/data.py +++ b/scripts/data.py @@ -1,4 +1,4 @@ -from os import path +import os from pathlib import Path SRC_DIR = Path(__file__).parent @@ -6,7 +6,7 @@ def load_prompt(): """Load the prompt from data/prompt.txt""" try: # get directory of this file: - file_dir = Path(path.dirname(path.realpath(__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 diff --git a/scripts/execute_code.py b/scripts/execute_code.py index 22ae1047..f34469dd 100644 --- a/scripts/execute_code.py +++ b/scripts/execute_code.py @@ -1,5 +1,5 @@ import docker -from os import path +import os def execute_python_file(file): @@ -11,9 +11,9 @@ def execute_python_file(file): if not file.endswith(".py"): return "Error: Invalid file type. Only .py files are allowed." - file_path = path.join(workspace_folder, file) + file_path = os.path.join(workspace_folder, file) - if not path.isfile(file_path): + if not os.path.isfile(file_path): return f"Error: File '{file}' does not exist." try: diff --git a/scripts/file_operations.py b/scripts/file_operations.py index cb054616..d7596c91 100644 --- a/scripts/file_operations.py +++ b/scripts/file_operations.py @@ -36,10 +36,8 @@ def write_to_file(filename, text): try: filepath = safe_join(working_directory, filename) directory = os.path.dirname(filepath) - if not os.path.exists(directory): os.makedirs(directory) - with open(filepath, "w") as f: f.write(text) return "File written to successfully." diff --git a/scripts/json_parser.py b/scripts/json_parser.py index e827b753..e46161ac 100644 --- a/scripts/json_parser.py +++ b/scripts/json_parser.py @@ -1,7 +1,6 @@ import json from call_ai_function import call_ai_function from config import Config - cfg = Config() def fix_and_parse_json(json_str: str, try_to_fix_with_gpt: bool = True): @@ -38,18 +37,15 @@ def fix_and_parse_json(json_str: str, try_to_fix_with_gpt: bool = True): json_str = json_str[:last_brace_index+1] return json.loads(json_str) except Exception as e: - if try_to_fix_with_gpt: print(f"Warning: Failed to parse AI output, attempting to fix.\n If you see this warning frequently, it's likely that your prompt is confusing the AI. Try changing it up slightly.") # Now try to fix this up using the ai_functions ai_fixed_json = fix_json(json_str, json_schema, False) - if ai_fixed_json != "failed": return json.loads(ai_fixed_json) else: print(f"Failed to fix ai output, telling the AI.") # This allows the AI to react to the error message, which usually results in it correcting its ways. return json_str - else: raise e @@ -63,11 +59,9 @@ def fix_json(json_str: str, schema: str, debug=False) -> str: # If it doesn't already start with a "`", add one: if not json_str.startswith("`"): json_str = "```json\n" + json_str + "\n```" - result_string = call_ai_function( function_string, args, description_string, model=cfg.fast_llm_model ) - if debug: print("------------ JSON FIX ATTEMPT ---------------") print(f"Original JSON: {json_str}") diff --git a/scripts/llm_utils.py b/scripts/llm_utils.py index 2981c8a0..c512e997 100644 --- a/scripts/llm_utils.py +++ b/scripts/llm_utils.py @@ -1,6 +1,5 @@ import openai from config import Config - cfg = Config() openai.api_key = cfg.openai_api_key diff --git a/scripts/main.py b/scripts/main.py index e89e57dc..9b938559 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -27,24 +27,17 @@ def print_to_console( max_typing_speed=0.01): """Prints text to the console with a typing effect""" global cfg - if speak_text and cfg.speak_mode: speak.say_text(f"{title}. {content}") - print(title_color + title + " " + Style.RESET_ALL, end="") - if content: - if isinstance(content, list): content = " ".join(content) words = content.split() - for i, word in enumerate(words): print(word, end="", flush=True) - if i < len(words) - 1: print(" ", end="", flush=True) - typing_speed = random.uniform(min_typing_speed, max_typing_speed) time.sleep(typing_speed) # type faster after each word @@ -88,7 +81,6 @@ def print_assistant_thoughts(assistant_reply): if assistant_thoughts_plan: print_to_console("PLAN:", Fore.YELLOW, "") # If it's a list, join it into a string - if isinstance(assistant_thoughts_plan, list): assistant_thoughts_plan = "\n".join(assistant_thoughts_plan) elif isinstance(assistant_thoughts_plan, dict): @@ -96,7 +88,6 @@ def print_assistant_thoughts(assistant_reply): # Split the input_string using the newline character and dashes lines = assistant_thoughts_plan.split('\n') - for line in lines: line = line.lstrip("- ") print_to_console("- ", Fore.GREEN, line.strip()) @@ -131,13 +122,11 @@ def load_variables(config_file="config.yaml"): # Prompt the user for input if config file is missing or empty values if not ai_name: ai_name = input("Name your AI: ") - if ai_name == "": ai_name = "Entrepreneur-GPT" if not ai_role: ai_role = input(f"{ai_name} is: ") - if ai_role == "": ai_role = "an AI designed to autonomously develop and run businesses with the sole goal of increasing your net worth." @@ -146,20 +135,16 @@ def load_variables(config_file="config.yaml"): print("For example: \nIncrease net worth, Grow Twitter Account, Develop and manage multiple businesses autonomously'") print("Enter nothing to load defaults, enter nothing when finished.") ai_goals = [] - for i in range(5): ai_goal = input(f"Goal {i+1}: ") - if ai_goal == "": break ai_goals.append(ai_goal) - if len(ai_goals) == 0: ai_goals = ["Increase net worth", "Grow Twitter Account", "Develop and manage multiple businesses autonomously"] # Save variables to yaml file config = {"ai_name": ai_name, "ai_role": ai_role, "ai_goals": ai_goals} - with open(config_file, "w") as file: documents = yaml.dump(config, file) @@ -168,7 +153,6 @@ def load_variables(config_file="config.yaml"): # Construct full prompt full_prompt = f"You are {ai_name}, {ai_role}\n{prompt_start}\n\nGOALS:\n\n" - for i, goal in enumerate(ai_goals): full_prompt += f"{i+1}. {goal}\n" @@ -179,7 +163,6 @@ def load_variables(config_file="config.yaml"): def construct_prompt(): """Construct the prompt for the AI to respond to""" config = AIConfig.load() - if config.ai_name: print_to_console( f"Welcome back! ", @@ -190,8 +173,7 @@ def construct_prompt(): Name: {config.ai_name} Role: {config.ai_role} Goals: {config.ai_goals} - Continue (y/n): """) - + Continue (y/n): """) if should_continue.lower() == "n": config = AIConfig() @@ -221,10 +203,8 @@ def prompt_user(): print_to_console( "Name your AI: ", Fore.GREEN, - "For example, 'Entrepreneur-GPT'") - + "For example, 'Entrepreneur-GPT'") ai_name = input("AI Name: ") - if ai_name == "": ai_name = "Entrepreneur-GPT" @@ -240,7 +220,6 @@ def prompt_user(): Fore.GREEN, "For example, 'an AI designed to autonomously develop and run businesses with the sole goal of increasing your net worth.'") ai_role = input(f"{ai_name} is: ") - if ai_role == "": ai_role = "an AI designed to autonomously develop and run businesses with the sole goal of increasing your net worth." @@ -248,19 +227,14 @@ def prompt_user(): print_to_console( "Enter up to 5 goals for your AI: ", Fore.GREEN, - "For example: \nIncrease net worth, Grow Twitter Account, Develop and manage multiple businesses autonomously'") - + "For example: \nIncrease net worth, Grow Twitter Account, Develop and manage multiple businesses autonomously'") print("Enter nothing to load defaults, enter nothing when finished.", flush=True) ai_goals = [] - for i in range(5): ai_goal = input(f"{Fore.LIGHTBLUE_EX}Goal{Style.RESET_ALL} {i+1}: ") - if ai_goal == "": break - ai_goals.append(ai_goal) - if len(ai_goals) == 0: ai_goals = ["Increase net worth", "Grow Twitter Account", "Develop and manage multiple businesses autonomously"] @@ -268,7 +242,6 @@ 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 @@ -346,8 +319,7 @@ while True: 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) - + console_input = input(Fore.MAGENTA + "Input:" + Style.RESET_ALL) if console_input.lower() == "y": user_input = "GENERATE NEXT COMMAND JSON" break diff --git a/scripts/speak.py b/scripts/speak.py index 9f32fac2..398eaf59 100644 --- a/scripts/speak.py +++ b/scripts/speak.py @@ -2,7 +2,6 @@ import os from playsound import playsound import requests from config import Config - cfg = Config() import gtts @@ -20,7 +19,8 @@ def eleven_labs_speech(text, voice_index=0): tts_url = "https://api.elevenlabs.io/v1/text-to-speech/{voice_id}".format( voice_id=voices[voice_index]) formatted_message = {"text": text} - response = requests.post(tts_url, headers=tts_headers, json=formatted_message) + response = requests.post( + tts_url, headers=tts_headers, json=formatted_message) if response.status_code == 200: with open("speech.mpeg", "wb") as f: diff --git a/scripts/spinner.py b/scripts/spinner.py index 2b79ae26..df39dbbd 100644 --- a/scripts/spinner.py +++ b/scripts/spinner.py @@ -14,7 +14,6 @@ class Spinner: self.running = False self.spinner_thread = None - def spin(self): """Spin the spinner""" while self.running: @@ -23,14 +22,12 @@ class Spinner: time.sleep(self.delay) sys.stdout.write('\b' * (len(self.message) + 2)) - def __enter__(self): """Start the spinner""" self.running = True self.spinner_thread = threading.Thread(target=self.spin) self.spinner_thread.start() - def __exit__(self, exc_type, exc_value, exc_traceback): """Stop the spinner""" self.running = False diff --git a/scripts/token_counter.py b/scripts/token_counter.py index fc5b9c51..a28a9868 100644 --- a/scripts/token_counter.py +++ b/scripts/token_counter.py @@ -1,7 +1,6 @@ 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. @@ -18,7 +17,6 @@ def count_message_tokens(messages : List[Dict[str, str]], model : str = "gpt-3.5 except KeyError: print("Warning: model not found. Using cl100k_base encoding.") encoding = tiktoken.get_encoding("cl100k_base") - if model == "gpt-3.5-turbo": # !Node: gpt-3.5-turbo may change over time. Returning num tokens assuming gpt-3.5-turbo-0301.") return count_message_tokens(messages, model="gpt-3.5-turbo-0301") @@ -34,19 +32,15 @@ def count_message_tokens(messages : List[Dict[str, str]], model : str = "gpt-3.5 else: raise NotImplementedError(f"""num_tokens_from_messages() is not implemented for model {model}. See https://github.com/openai/openai-python/blob/main/chatml.md for information on how messages are converted to tokens.""") num_tokens = 0 - for message in messages: num_tokens += tokens_per_message - for key, value in message.items(): num_tokens += len(encoding.encode(value)) - if key == "name": num_tokens += tokens_per_name 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. From d05146c6c5766a17d7b40b932d3de4056e142123 Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Sun, 9 Apr 2023 15:48:17 +0200 Subject: [PATCH 23/26] Delete unrelated changes with PR --- scripts/ai_config.py | 3 +-- scripts/main.py | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/scripts/ai_config.py b/scripts/ai_config.py index 14b45887..43d88ec3 100644 --- a/scripts/ai_config.py +++ b/scripts/ai_config.py @@ -40,8 +40,7 @@ class AIConfig: prompt_start = """Your decisions must always be made independently without seeking user assistance. Play to your strengths as an LLM and pursue simple strategies with no legal complications.""" # Construct full prompt - full_prompt = f"You are {self.ai_name}, {self.ai_role}\n{prompt_start}\n\nGOALS:\n\n" - + full_prompt = f"You are {self.ai_name}, {self.ai_role}\n{prompt_start}\n\nGOALS:\n\n" for i, goal in enumerate(self.ai_goals): full_prompt += f"{i+1}. {goal}\n" diff --git a/scripts/main.py b/scripts/main.py index 0c2a94e0..0a2d2447 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -170,10 +170,10 @@ def construct_prompt(): f"Would you like me to return to being {config.ai_name}?", speak_text=True) should_continue = input(f"""Continue with the last settings? - Name: {config.ai_name} - Role: {config.ai_role} - Goals: {config.ai_goals} - Continue (y/n): """) +Name: {config.ai_name} +Role: {config.ai_role} +Goals: {config.ai_goals} +Continue (y/n): """) if should_continue.lower() == "n": config = AIConfig() From 9105a9c7f862c1dc6901ea12b1fff10e70bb4aad Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Sun, 9 Apr 2023 16:31:04 +0200 Subject: [PATCH 24/26] Remove whitespaces --- scripts/ai_config.py | 2 +- scripts/main.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/ai_config.py b/scripts/ai_config.py index 43d88ec3..59c75201 100644 --- a/scripts/ai_config.py +++ b/scripts/ai_config.py @@ -40,7 +40,7 @@ class AIConfig: prompt_start = """Your decisions must always be made independently without seeking user assistance. Play to your strengths as an LLM and pursue simple strategies with no legal complications.""" # Construct full prompt - full_prompt = f"You are {self.ai_name}, {self.ai_role}\n{prompt_start}\n\nGOALS:\n\n" + full_prompt = f"You are {self.ai_name}, {self.ai_role}\n{prompt_start}\n\nGOALS:\n\n" for i, goal in enumerate(self.ai_goals): full_prompt += f"{i+1}. {goal}\n" diff --git a/scripts/main.py b/scripts/main.py index 0a2d2447..851108a7 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -173,7 +173,7 @@ def construct_prompt(): Name: {config.ai_name} Role: {config.ai_role} Goals: {config.ai_goals} -Continue (y/n): """) +Continue (y/n): """) if should_continue.lower() == "n": config = AIConfig() From c4ab35275a2acc585533c044e9d1f168a54d78b3 Mon Sep 17 00:00:00 2001 From: Andres Caicedo Date: Sun, 9 Apr 2023 16:34:36 +0200 Subject: [PATCH 25/26] Remove whitespaces --- scripts/main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/main.py b/scripts/main.py index 851108a7..6115cffe 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -203,7 +203,7 @@ def prompt_user(): print_to_console( "Name your AI: ", Fore.GREEN, - "For example, 'Entrepreneur-GPT'") + "For example, 'Entrepreneur-GPT'") ai_name = input("AI Name: ") if ai_name == "": ai_name = "Entrepreneur-GPT" @@ -227,7 +227,7 @@ def prompt_user(): print_to_console( "Enter up to 5 goals for your AI: ", Fore.GREEN, - "For example: \nIncrease net worth, Grow Twitter Account, Develop and manage multiple businesses autonomously'") + "For example: \nIncrease net worth, Grow Twitter Account, Develop and manage multiple businesses autonomously'") print("Enter nothing to load defaults, enter nothing when finished.", flush=True) ai_goals = [] for i in range(5): @@ -328,7 +328,7 @@ while True: 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) + console_input = input(Fore.MAGENTA + "Input:" + Style.RESET_ALL) if console_input.lower() == "y": user_input = "GENERATE NEXT COMMAND JSON" break From 1f0209bba70c28717888cfa0c2f9f9e633264a7f Mon Sep 17 00:00:00 2001 From: Toran Bruce Richards Date: Mon, 10 Apr 2023 12:07:16 +0100 Subject: [PATCH 26/26] Fixe incorrect Docstring --- scripts/speak.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/speak.py b/scripts/speak.py index 8a3a64df..10dd7c07 100644 --- a/scripts/speak.py +++ b/scripts/speak.py @@ -15,7 +15,7 @@ tts_headers = { } def eleven_labs_speech(text, voice_index=0): - """Return the results of a google search""" + """Speak text using elevenlabs.io's API""" tts_url = "https://api.elevenlabs.io/v1/text-to-speech/{voice_id}".format( voice_id=voices[voice_index]) formatted_message = {"text": text}