diff options
Diffstat (limited to 'autogpt/agent/agent.py')
-rw-r--r-- | autogpt/agent/agent.py | 309 |
1 files changed, 0 insertions, 309 deletions
diff --git a/autogpt/agent/agent.py b/autogpt/agent/agent.py deleted file mode 100644 index 88b3fa809..000000000 --- a/autogpt/agent/agent.py +++ /dev/null @@ -1,309 +0,0 @@ -import json -import signal -import sys -from datetime import datetime -from pathlib import Path - -from colorama import Fore, Style - -from autogpt.config import Config -from autogpt.config.ai_config import AIConfig -from autogpt.json_utils.utilities import extract_json_from_response, validate_json -from autogpt.llm.chat import chat_with_ai -from autogpt.llm.providers.openai import OPEN_AI_CHAT_MODELS -from autogpt.llm.utils import count_string_tokens -from autogpt.logs import ( - FULL_MESSAGE_HISTORY_FILE_NAME, - NEXT_ACTION_FILE_NAME, - USER_INPUT_FILE_NAME, - LogCycleHandler, - logger, - print_assistant_thoughts, - remove_ansi_escape, -) -from autogpt.memory.message_history import MessageHistory -from autogpt.memory.vector import VectorMemory -from autogpt.models.command_registry import CommandRegistry -from autogpt.speech import say_text -from autogpt.spinner import Spinner -from autogpt.utils import clean_input -from autogpt.workspace import Workspace - - -class Agent: - """Agent class for interacting with Auto-GPT. - - Attributes: - ai_name: The name of the agent. - memory: The memory object to use. - next_action_count: The number of actions to execute. - system_prompt: The system prompt is the initial prompt that defines everything - the AI needs to know to achieve its task successfully. - Currently, the dynamic and customizable information in the system prompt are - ai_name, description and goals. - - triggering_prompt: The last sentence the AI will see before answering. - For Auto-GPT, this prompt is: - Determine exactly one command to use, and respond using the format specified - above: - The triggering prompt is not part of the system prompt because between the - system prompt and the triggering - prompt we have contextual information that can distract the AI and make it - forget that its goal is to find the next task to achieve. - SYSTEM PROMPT - CONTEXTUAL INFORMATION (memory, previous conversations, anything relevant) - TRIGGERING PROMPT - - The triggering prompt reminds the AI about its short term meta task - (defining the next task) - """ - - def __init__( - self, - ai_name: str, - memory: VectorMemory, - next_action_count: int, - command_registry: CommandRegistry, - ai_config: AIConfig, - system_prompt: str, - triggering_prompt: str, - workspace_directory: str | Path, - config: Config, - ): - self.ai_name = ai_name - self.memory = memory - self.history = MessageHistory.for_model(config.smart_llm, agent=self) - self.next_action_count = next_action_count - self.command_registry = command_registry - self.config = config - self.ai_config = ai_config - self.system_prompt = system_prompt - self.triggering_prompt = triggering_prompt - self.workspace = Workspace(workspace_directory, config.restrict_to_workspace) - self.created_at = datetime.now().strftime("%Y%m%d_%H%M%S") - self.cycle_count = 0 - self.log_cycle_handler = LogCycleHandler() - self.smart_token_limit = OPEN_AI_CHAT_MODELS.get(config.smart_llm).max_tokens - - def start_interaction_loop(self): - # Avoid circular imports - from autogpt.app import execute_command, extract_command - - # Interaction Loop - self.cycle_count = 0 - command_name = None - arguments = None - user_input = "" - - # Signal handler for interrupting y -N - def signal_handler(signum, frame): - if self.next_action_count == 0: - sys.exit() - else: - print( - Fore.RED - + "Interrupt signal received. Stopping continuous command execution." - + Style.RESET_ALL - ) - self.next_action_count = 0 - - signal.signal(signal.SIGINT, signal_handler) - - while True: - # Discontinue if continuous limit is reached - self.cycle_count += 1 - self.log_cycle_handler.log_count_within_cycle = 0 - self.log_cycle_handler.log_cycle( - self.ai_config.ai_name, - self.created_at, - self.cycle_count, - [m.raw() for m in self.history], - FULL_MESSAGE_HISTORY_FILE_NAME, - ) - if ( - self.config.continuous_mode - and self.config.continuous_limit > 0 - and self.cycle_count > self.config.continuous_limit - ): - logger.typewriter_log( - "Continuous Limit Reached: ", - Fore.YELLOW, - f"{self.config.continuous_limit}", - ) - break - # Send message to AI, get response - with Spinner("Thinking... ", plain_output=self.config.plain_output): - assistant_reply = chat_with_ai( - self.config, - self, - self.system_prompt, - self.triggering_prompt, - self.smart_token_limit, - self.config.smart_llm, - ) - - try: - assistant_reply_json = extract_json_from_response( - assistant_reply.content - ) - validate_json(assistant_reply_json, self.config) - except json.JSONDecodeError as e: - logger.error(f"Exception while validating assistant reply JSON: {e}") - assistant_reply_json = {} - - for plugin in self.config.plugins: - if not plugin.can_handle_post_planning(): - continue - assistant_reply_json = plugin.post_planning(assistant_reply_json) - - # Print Assistant thoughts - if assistant_reply_json != {}: - # Get command name and arguments - try: - print_assistant_thoughts( - self.ai_name, assistant_reply_json, self.config - ) - command_name, arguments = extract_command( - assistant_reply_json, assistant_reply, self.config - ) - if self.config.speak_mode: - say_text(f"I want to execute {command_name}", self.config) - - except Exception as e: - logger.error("Error: \n", str(e)) - self.log_cycle_handler.log_cycle( - self.ai_config.ai_name, - self.created_at, - self.cycle_count, - assistant_reply_json, - NEXT_ACTION_FILE_NAME, - ) - - # First log new-line so user can differentiate sections better in console - logger.typewriter_log("\n") - logger.typewriter_log( - "NEXT ACTION: ", - Fore.CYAN, - f"COMMAND = {Fore.CYAN}{remove_ansi_escape(command_name)}{Style.RESET_ALL} " - f"ARGUMENTS = {Fore.CYAN}{arguments}{Style.RESET_ALL}", - ) - - if not self.config.continuous_mode and self.next_action_count == 0: - # ### GET USER AUTHORIZATION TO EXECUTE COMMAND ### - # Get key press: Prompt the user to press enter to continue or escape - # to exit - self.user_input = "" - logger.info( - f"Enter '{self.config.authorise_key}' to authorise command, " - f"'{self.config.authorise_key} -N' to run N continuous commands, " - f"'{self.config.exit_key}' to exit program, or enter feedback for " - f"{self.ai_name}..." - ) - while True: - if self.config.chat_messages_enabled: - console_input = clean_input( - self.config, "Waiting for your response..." - ) - else: - console_input = clean_input( - self.config, Fore.MAGENTA + "Input:" + Style.RESET_ALL - ) - if console_input.lower().strip() == self.config.authorise_key: - user_input = "GENERATE NEXT COMMAND JSON" - break - elif console_input.lower().strip() == "": - logger.warn("Invalid input format.") - continue - elif console_input.lower().startswith( - f"{self.config.authorise_key} -" - ): - try: - self.next_action_count = abs( - int(console_input.split(" ")[1]) - ) - user_input = "GENERATE NEXT COMMAND JSON" - except ValueError: - logger.warn( - f"Invalid input format. Please enter '{self.config.authorise_key} -n' " - "where n is the number of continuous tasks." - ) - continue - break - elif console_input.lower() == self.config.exit_key: - user_input = "EXIT" - break - else: - user_input = console_input - command_name = "human_feedback" - self.log_cycle_handler.log_cycle( - self.ai_config.ai_name, - self.created_at, - self.cycle_count, - user_input, - USER_INPUT_FILE_NAME, - ) - break - - if user_input == "GENERATE NEXT COMMAND JSON": - logger.typewriter_log( - "-=-=-=-=-=-=-= COMMAND AUTHORISED BY USER -=-=-=-=-=-=-=", - Fore.MAGENTA, - "", - ) - elif user_input == "EXIT": - logger.info("Exiting...") - break - else: - # First log new-line so user can differentiate sections better in console - logger.typewriter_log("\n") - # Print authorized commands left value - logger.typewriter_log( - f"{Fore.CYAN}AUTHORISED COMMANDS LEFT: {Style.RESET_ALL}{self.next_action_count}" - ) - - # Execute command - if command_name is not None and command_name.lower().startswith("error"): - result = f"Could not execute command: {arguments}" - elif command_name == "human_feedback": - result = f"Human feedback: {user_input}" - else: - for plugin in self.config.plugins: - if not plugin.can_handle_pre_command(): - continue - command_name, arguments = plugin.pre_command( - command_name, arguments - ) - command_result = execute_command( - command_name=command_name, - arguments=arguments, - agent=self, - ) - result = f"Command {command_name} returned: " f"{command_result}" - - result_tlength = count_string_tokens( - str(command_result), self.config.smart_llm - ) - memory_tlength = count_string_tokens( - str(self.history.summary_message()), self.config.smart_llm - ) - if result_tlength + memory_tlength + 600 > self.smart_token_limit: - result = f"Failure: command {command_name} returned too much output. \ - Do not execute this command again with the same arguments." - - for plugin in self.config.plugins: - if not plugin.can_handle_post_command(): - continue - result = plugin.post_command(command_name, result) - if self.next_action_count > 0: - self.next_action_count -= 1 - - # Check if there's a result from the command append it to the message - # history - if result is not None: - self.history.add("system", result, "action_result") - logger.typewriter_log("SYSTEM: ", Fore.YELLOW, result) - else: - self.history.add("system", "Unable to execute command", "action_result") - logger.typewriter_log( - "SYSTEM: ", Fore.YELLOW, "Unable to execute command" - ) |