From b19eb74874a91b0c8e372ffb37d34e833de07cad Mon Sep 17 00:00:00 2001 From: Alrik Olson <10505065+AlrikOlson@users.noreply.github.com> Date: Tue, 11 Apr 2023 09:09:59 -0700 Subject: [PATCH] Refactor the seed prompt to be generated programmatically This removes the tedium of having to re-number every numbered item in the prompt.txt if you want to add/remove commands. --- scripts/ai_config.py | 3 +- scripts/data.py | 18 ---------- scripts/data/prompt.txt | 63 --------------------------------- scripts/main.py | 3 +- scripts/prompt.py | 51 +++++++++++++++++++++++++++ scripts/promptgenerator.py | 71 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 126 insertions(+), 83 deletions(-) delete mode 100644 scripts/data.py delete mode 100644 scripts/data/prompt.txt create mode 100644 scripts/prompt.py create mode 100644 scripts/promptgenerator.py diff --git a/scripts/ai_config.py b/scripts/ai_config.py index 1d5832c1..332c7f06 100644 --- a/scripts/ai_config.py +++ b/scripts/ai_config.py @@ -1,6 +1,7 @@ import yaml import data import os +from prompt import get_prompt class AIConfig: """ @@ -90,6 +91,6 @@ class AIConfig: for i, goal in enumerate(self.ai_goals): full_prompt += f"{i+1}. {goal}\n" - full_prompt += f"\n\n{data.load_prompt()}" + full_prompt += f"\n\n{get_prompt()}" return full_prompt diff --git a/scripts/data.py b/scripts/data.py deleted file mode 100644 index f80c2875..00000000 --- a/scripts/data.py +++ /dev/null @@ -1,18 +0,0 @@ -import os -from pathlib import Path - -def load_prompt(): - """Load the prompt from data/prompt.txt""" - try: - # get directory of this file: - file_dir = Path(__file__).parent - prompt_file_path = file_dir / "data" / "prompt.txt" - - # Load the prompt from data/prompt.txt - with open(prompt_file_path, "r") as prompt_file: - prompt = prompt_file.read() - - return prompt - except FileNotFoundError: - print("Error: Prompt file not found", flush=True) - return "" diff --git a/scripts/data/prompt.txt b/scripts/data/prompt.txt deleted file mode 100644 index fc68f3ae..00000000 --- a/scripts/data/prompt.txt +++ /dev/null @@ -1,63 +0,0 @@ -CONSTRAINTS: - -1. ~4000 word limit for short term memory. Your short term memory is short, so immediately save important information to files. -2. If you are unsure how you previously did something or want to recall past events, thinking about similar events will help you remember. -3. No user assistance -4. Exclusively use the commands listed in double quotes e.g. "command name" - -COMMANDS: - -1. Google Search: "google", args: "input": "" -5. Browse Website: "browse_website", args: "url": "", "question": "" -6. Start GPT Agent: "start_agent", args: "name": "", "task": "", "prompt": "" -7. Message GPT Agent: "message_agent", args: "key": "", "message": "" -8. List GPT Agents: "list_agents", args: "" -9. Delete GPT Agent: "delete_agent", args: "key": "" -10. Write to file: "write_to_file", args: "file": "", "text": "" -11. Read file: "read_file", args: "file": "" -12. Append to file: "append_to_file", args: "file": "", "text": "" -13. Delete file: "delete_file", args: "file": "" -14. Search Files: "search_files", args: "directory": "" -15. Evaluate Code: "evaluate_code", args: "code": "" -16. Get Improved Code: "improve_code", args: "suggestions": "", "code": "" -17. Write Tests: "write_tests", args: "code": "", "focus": "" -18. Execute Python File: "execute_python_file", args: "file": "" -19. Task Complete (Shutdown): "task_complete", args: "reason": "" -20. Generate Image: "generate_image", args: "prompt": "" -21. Do Nothing: "do_nothing", args: "" - -RESOURCES: - -1. Internet access for searches and information gathering. -2. Long Term memory management. -3. GPT-3.5 powered Agents for delegation of simple tasks. -4. File output. - -PERFORMANCE EVALUATION: - -1. Continuously review and analyze your actions to ensure you are performing to the best of your abilities. -2. Constructively self-criticize your big-picture behavior constantly. -3. Reflect on past decisions and strategies to refine your approach. -4. Every command has a cost, so be smart and efficient. Aim to complete tasks in the least number of steps. - -You should only respond in JSON format as described below - -RESPONSE FORMAT: -{ - "thoughts": - { - "text": "thought", - "reasoning": "reasoning", - "plan": "- short bulleted\n- list that conveys\n- long-term plan", - "criticism": "constructive self-criticism", - "speak": "thoughts summary to say to user" - }, - "command": { - "name": "command name", - "args":{ - "arg name": "value" - } - } -} - -Ensure the response can be parsed by Python json.loads diff --git a/scripts/main.py b/scripts/main.py index 4be0b2aa..a3d4f9df 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -18,6 +18,7 @@ import traceback import yaml import argparse import logging +from prompt import get_prompt cfg = Config() @@ -171,7 +172,7 @@ def load_variables(config_file="config.yaml"): with open(config_file, "w") as file: documents = yaml.dump(config, file) - prompt = data.load_prompt() + prompt = get_prompt() 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/prompt.py b/scripts/prompt.py new file mode 100644 index 00000000..fd2a84a0 --- /dev/null +++ b/scripts/prompt.py @@ -0,0 +1,51 @@ +from promptgenerator import PromptGenerator + +def get_prompt(): + prompt_generator = PromptGenerator() + + # Add constraints + prompt_generator.add_constraint("~4000 word limit for short term memory. Your short term memory is short, so immediately save important information to files.") + prompt_generator.add_constraint("If you are unsure how you previously did something or want to recall past events, thinking about similar events will help you remember.") + prompt_generator.add_constraint("No user assistance") + prompt_generator.add_constraint('Exclusively use the commands listed in double quotes e.g. "command name"') + + # Add commands + commands = [ + ("Google Search", "google", {"input": ""}), + ("Browse Website", "browse_website", {"url": "", "question": ""}), + ("Start GPT Agent", "start_agent", {"name": "", "task": "", "prompt": ""}), + ("Message GPT Agent", "message_agent", {"key": "", "message": ""}), + ("List GPT Agents", "list_agents", {}), + ("Delete GPT Agent", "delete_agent", {"key": ""}), + ("Write to file", "write_to_file", {"file": "", "text": ""}), + ("Read file", "read_file", {"file": ""}), + ("Append to file", "append_to_file", {"file": "", "text": ""}), + ("Delete file", "delete_file", {"file": ""}), + ("Search Files", "search_files", {"directory": ""}), + ("Evaluate Code", "evaluate_code", {"code": ""}), + ("Get Improved Code", "improve_code", {"suggestions": "", "code": ""}), + ("Write Tests", "write_tests", {"code": "", "focus": ""}), + ("Execute Python File", "execute_python_file", {"file": ""}), + ("Task Complete (Shutdown)", "task_complete", {"reason": ""}), + ("Generate Image", "generate_image", {"prompt": ""}), + ("Do Nothing", "do_nothing", {}), + ] + + for command_label, command_name, args in commands: + prompt_generator.add_command(command_label, command_name, args) + + # Add resources + prompt_generator.add_resource("Internet access for searches and information gathering.") + prompt_generator.add_resource("Long Term memory management.") + prompt_generator.add_resource("GPT-3.5 powered Agents for delegation of simple tasks.") + prompt_generator.add_resource("File output.") + + # Add performance evaluation + prompt_generator.add_performance_evaluation("Continuously review and analyze your actions to ensure you are performing to the best of your abilities.") + prompt_generator.add_performance_evaluation("Constructively self-criticize your big-picture behavior constantly.") + prompt_generator.add_performance_evaluation("Reflect on past decisions and strategies to refine your approach.") + prompt_generator.add_performance_evaluation("Every command has a cost, so be smart and efficient. Aim to complete tasks in the least number of steps.") + + # Generate prompt string + prompt_string = prompt_generator.generate_prompt_string() + return prompt_string diff --git a/scripts/promptgenerator.py b/scripts/promptgenerator.py new file mode 100644 index 00000000..1ae43aa7 --- /dev/null +++ b/scripts/promptgenerator.py @@ -0,0 +1,71 @@ +import json + + +class PromptGenerator: + def __init__(self): + self.constraints = [] + self.commands = [] + self.resources = [] + self.performance_evaluation = [] + self.response_format = { + "thoughts": { + "text": "thought", + "reasoning": "reasoning", + "plan": "- short bulleted\n- list that conveys\n- long-term plan", + "criticism": "constructive self-criticism", + "speak": "thoughts summary to say to user" + }, + "command": { + "name": "command name", + "args": { + "arg name": "value" + } + } + } + + def add_constraint(self, constraint): + self.constraints.append(constraint) + + # {CommandLabel}: "{CommandName}", args: "{arg#Name}": "{arg#Prompt}" + def add_command(self, command_label, command_name, args=None): + if args is None: + args = {} + + command_args = {arg_key: arg_value for arg_key, arg_value in args.items()} + + command = { + "label": command_label, + "name": command_name, + "args": command_args, + } + + self.commands.append(command) + + def _generate_command_string(self, command): + args_string = ', '.join(f'"{key}": "{value}"' for key, value in command['args'].items()) + return f'{command["label"]}: "{command["name"]}", args: {args_string}' + + def add_resource(self, resource): + self.resources.append(resource) + + def add_performance_evaluation(self, evaluation): + self.performance_evaluation.append(evaluation) + + + def _generate_numbered_list(self, items, item_type='list'): + if item_type == 'command': + return "\n".join(f"{i+1}. {self._generate_command_string(item)}" for i, item in enumerate(items)) + else: + return "\n".join(f"{i+1}. {item}" for i, item in enumerate(items)) + + def generate_prompt_string(self): + formatted_response_format = json.dumps(self.response_format, indent=4) + prompt_string = ( + f"Constraints:\n{self._generate_numbered_list(self.constraints)}\n\n" + f"Commands:\n{self._generate_numbered_list(self.commands, item_type='command')}\n\n" + f"Resources:\n{self._generate_numbered_list(self.resources)}\n\n" + f"Performance Evaluation:\n{self._generate_numbered_list(self.performance_evaluation)}\n\n" + f"You should only respond in JSON format as described below \nResponse Format: \n{formatted_response_format} \nEnsure the response can be parsed by Python json.loads" + ) + + return prompt_string