Add config as attribute to Agent, rename old config to ai_config (#4638)

* Add config as attribute to Agent, rename old config to ai_config

* Code review: Pass ai_config

---------

Co-authored-by: Nicholas Tindle <nick@ntindle.com>
Co-authored-by: merwanehamadi <merwanehamadi@gmail.com>
pull/4640/head^2
Erik Peterson 2023-06-10 14:47:26 -07:00 committed by GitHub
parent 15c6b0c1c3
commit 6b9e3b21d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 81 additions and 59 deletions

View File

@ -65,29 +65,31 @@ class Agent:
memory: VectorMemory, memory: VectorMemory,
next_action_count: int, next_action_count: int,
command_registry: CommandRegistry, command_registry: CommandRegistry,
config: AIConfig, ai_config: AIConfig,
system_prompt: str, system_prompt: str,
triggering_prompt: str, triggering_prompt: str,
workspace_directory: str, workspace_directory: str,
config: Config,
): ):
cfg = Config()
self.ai_name = ai_name self.ai_name = ai_name
self.memory = memory self.memory = memory
self.history = MessageHistory(self) self.history = MessageHistory(self)
self.next_action_count = next_action_count self.next_action_count = next_action_count
self.command_registry = command_registry self.command_registry = command_registry
self.config = config self.config = config
self.ai_config = ai_config
self.system_prompt = system_prompt self.system_prompt = system_prompt
self.triggering_prompt = triggering_prompt self.triggering_prompt = triggering_prompt
self.workspace = Workspace(workspace_directory, cfg.restrict_to_workspace) self.workspace = Workspace(workspace_directory, config.restrict_to_workspace)
self.created_at = datetime.now().strftime("%Y%m%d_%H%M%S") self.created_at = datetime.now().strftime("%Y%m%d_%H%M%S")
self.cycle_count = 0 self.cycle_count = 0
self.log_cycle_handler = LogCycleHandler() self.log_cycle_handler = LogCycleHandler()
self.fast_token_limit = OPEN_AI_CHAT_MODELS.get(cfg.fast_llm_model).max_tokens self.fast_token_limit = OPEN_AI_CHAT_MODELS.get(
config.fast_llm_model
).max_tokens
def start_interaction_loop(self): def start_interaction_loop(self):
# Interaction Loop # Interaction Loop
cfg = Config()
self.cycle_count = 0 self.cycle_count = 0
command_name = None command_name = None
arguments = None arguments = None
@ -112,34 +114,36 @@ class Agent:
self.cycle_count += 1 self.cycle_count += 1
self.log_cycle_handler.log_count_within_cycle = 0 self.log_cycle_handler.log_count_within_cycle = 0
self.log_cycle_handler.log_cycle( self.log_cycle_handler.log_cycle(
self.config.ai_name, self.ai_config.ai_name,
self.created_at, self.created_at,
self.cycle_count, self.cycle_count,
[m.raw() for m in self.history], [m.raw() for m in self.history],
FULL_MESSAGE_HISTORY_FILE_NAME, FULL_MESSAGE_HISTORY_FILE_NAME,
) )
if ( if (
cfg.continuous_mode self.config.continuous_mode
and cfg.continuous_limit > 0 and self.config.continuous_limit > 0
and self.cycle_count > cfg.continuous_limit and self.cycle_count > self.config.continuous_limit
): ):
logger.typewriter_log( logger.typewriter_log(
"Continuous Limit Reached: ", Fore.YELLOW, f"{cfg.continuous_limit}" "Continuous Limit Reached: ",
Fore.YELLOW,
f"{self.config.continuous_limit}",
) )
break break
# Send message to AI, get response # Send message to AI, get response
with Spinner("Thinking... ", plain_output=cfg.plain_output): with Spinner("Thinking... ", plain_output=self.config.plain_output):
assistant_reply = chat_with_ai( assistant_reply = chat_with_ai(
cfg, self.config,
self, self,
self.system_prompt, self.system_prompt,
self.triggering_prompt, self.triggering_prompt,
self.fast_token_limit, self.fast_token_limit,
cfg.fast_llm_model, self.config.fast_llm_model,
) )
assistant_reply_json = fix_json_using_multiple_techniques(assistant_reply) assistant_reply_json = fix_json_using_multiple_techniques(assistant_reply)
for plugin in cfg.plugins: for plugin in self.config.plugins:
if not plugin.can_handle_post_planning(): if not plugin.can_handle_post_planning():
continue continue
assistant_reply_json = plugin.post_planning(assistant_reply_json) assistant_reply_json = plugin.post_planning(assistant_reply_json)
@ -150,10 +154,10 @@ class Agent:
# Get command name and arguments # Get command name and arguments
try: try:
print_assistant_thoughts( print_assistant_thoughts(
self.ai_name, assistant_reply_json, cfg.speak_mode self.ai_name, assistant_reply_json, self.config.speak_mode
) )
command_name, arguments = get_command(assistant_reply_json) command_name, arguments = get_command(assistant_reply_json)
if cfg.speak_mode: if self.config.speak_mode:
say_text(f"I want to execute {command_name}") say_text(f"I want to execute {command_name}")
arguments = self._resolve_pathlike_command_args(arguments) arguments = self._resolve_pathlike_command_args(arguments)
@ -161,7 +165,7 @@ class Agent:
except Exception as e: except Exception as e:
logger.error("Error: \n", str(e)) logger.error("Error: \n", str(e))
self.log_cycle_handler.log_cycle( self.log_cycle_handler.log_cycle(
self.config.ai_name, self.ai_config.ai_name,
self.created_at, self.created_at,
self.cycle_count, self.cycle_count,
assistant_reply_json, assistant_reply_json,
@ -177,7 +181,7 @@ class Agent:
f"ARGUMENTS = {Fore.CYAN}{arguments}{Style.RESET_ALL}", f"ARGUMENTS = {Fore.CYAN}{arguments}{Style.RESET_ALL}",
) )
if not cfg.continuous_mode and self.next_action_count == 0: if not self.config.continuous_mode and self.next_action_count == 0:
# ### GET USER AUTHORIZATION TO EXECUTE COMMAND ### # ### GET USER AUTHORIZATION TO EXECUTE COMMAND ###
# Get key press: Prompt the user to press enter to continue or escape # Get key press: Prompt the user to press enter to continue or escape
# to exit # to exit
@ -188,13 +192,13 @@ class Agent:
f"{self.ai_name}..." f"{self.ai_name}..."
) )
while True: while True:
if cfg.chat_messages_enabled: if self.config.chat_messages_enabled:
console_input = clean_input("Waiting for your response...") console_input = clean_input("Waiting for your response...")
else: else:
console_input = clean_input( console_input = clean_input(
Fore.MAGENTA + "Input:" + Style.RESET_ALL Fore.MAGENTA + "Input:" + Style.RESET_ALL
) )
if console_input.lower().strip() == cfg.authorise_key: if console_input.lower().strip() == self.config.authorise_key:
user_input = "GENERATE NEXT COMMAND JSON" user_input = "GENERATE NEXT COMMAND JSON"
break break
elif console_input.lower().strip() == "s": elif console_input.lower().strip() == "s":
@ -205,7 +209,7 @@ class Agent:
) )
thoughts = assistant_reply_json.get("thoughts", {}) thoughts = assistant_reply_json.get("thoughts", {})
self_feedback_resp = self.get_self_feedback( self_feedback_resp = self.get_self_feedback(
thoughts, cfg.fast_llm_model thoughts, self.config.fast_llm_model
) )
logger.typewriter_log( logger.typewriter_log(
f"SELF FEEDBACK: {self_feedback_resp}", f"SELF FEEDBACK: {self_feedback_resp}",
@ -218,7 +222,9 @@ class Agent:
elif console_input.lower().strip() == "": elif console_input.lower().strip() == "":
logger.warn("Invalid input format.") logger.warn("Invalid input format.")
continue continue
elif console_input.lower().startswith(f"{cfg.authorise_key} -"): elif console_input.lower().startswith(
f"{self.config.authorise_key} -"
):
try: try:
self.next_action_count = abs( self.next_action_count = abs(
int(console_input.split(" ")[1]) int(console_input.split(" ")[1])
@ -231,14 +237,14 @@ class Agent:
) )
continue continue
break break
elif console_input.lower() == cfg.exit_key: elif console_input.lower() == self.config.exit_key:
user_input = "EXIT" user_input = "EXIT"
break break
else: else:
user_input = console_input user_input = console_input
command_name = "human_feedback" command_name = "human_feedback"
self.log_cycle_handler.log_cycle( self.log_cycle_handler.log_cycle(
self.config.ai_name, self.ai_config.ai_name,
self.created_at, self.created_at,
self.cycle_count, self.cycle_count,
user_input, user_input,
@ -271,7 +277,7 @@ class Agent:
elif command_name == "self_feedback": elif command_name == "self_feedback":
result = f"Self feedback: {user_input}" result = f"Self feedback: {user_input}"
else: else:
for plugin in cfg.plugins: for plugin in self.config.plugins:
if not plugin.can_handle_pre_command(): if not plugin.can_handle_pre_command():
continue continue
command_name, arguments = plugin.pre_command( command_name, arguments = plugin.pre_command(
@ -281,22 +287,22 @@ class Agent:
self.command_registry, self.command_registry,
command_name, command_name,
arguments, arguments,
self.config.prompt_generator, self.ai_config.prompt_generator,
config=cfg, config=self.config,
) )
result = f"Command {command_name} returned: " f"{command_result}" result = f"Command {command_name} returned: " f"{command_result}"
result_tlength = count_string_tokens( result_tlength = count_string_tokens(
str(command_result), cfg.fast_llm_model str(command_result), self.config.fast_llm_model
) )
memory_tlength = count_string_tokens( memory_tlength = count_string_tokens(
str(self.history.summary_message()), cfg.fast_llm_model str(self.history.summary_message()), self.config.fast_llm_model
) )
if result_tlength + memory_tlength + 600 > self.fast_token_limit: if result_tlength + memory_tlength + 600 > self.fast_token_limit:
result = f"Failure: command {command_name} returned too much output. \ result = f"Failure: command {command_name} returned too much output. \
Do not execute this command again with the same arguments." Do not execute this command again with the same arguments."
for plugin in cfg.plugins: for plugin in self.config.plugins:
if not plugin.can_handle_post_command(): if not plugin.can_handle_post_command():
continue continue
result = plugin.post_command(command_name, result) result = plugin.post_command(command_name, result)
@ -337,7 +343,7 @@ class Agent:
Returns: Returns:
str: A feedback response generated using the provided thoughts dictionary. str: A feedback response generated using the provided thoughts dictionary.
""" """
ai_role = self.config.ai_role ai_role = self.ai_config.ai_role
feedback_prompt = f"Below is a message from me, an AI Agent, assuming the role of {ai_role}. whilst keeping knowledge of my slight limitations as an AI Agent Please evaluate my thought process, reasoning, and plan, and provide a concise paragraph outlining potential improvements. Consider adding or removing ideas that do not align with my role and explaining why, prioritizing thoughts based on their significance, or simply refining my overall thought process." feedback_prompt = f"Below is a message from me, an AI Agent, assuming the role of {ai_role}. whilst keeping knowledge of my slight limitations as an AI Agent Please evaluate my thought process, reasoning, and plan, and provide a concise paragraph outlining potential improvements. Consider adding or removing ideas that do not align with my role and explaining why, prioritizing thoughts based on their significance, or simply refining my overall thought process."
reasoning = thoughts.get("reasoning", "") reasoning = thoughts.get("reasoning", "")
@ -349,7 +355,7 @@ class Agent:
prompt.add("user", feedback_prompt + feedback_thoughts) prompt.add("user", feedback_prompt + feedback_thoughts)
self.log_cycle_handler.log_cycle( self.log_cycle_handler.log_cycle(
self.config.ai_name, self.ai_config.ai_name,
self.created_at, self.created_at,
self.cycle_count, self.cycle_count,
prompt.raw(), prompt.raw(),
@ -359,7 +365,7 @@ class Agent:
feedback = create_chat_completion(prompt) feedback = create_chat_completion(prompt)
self.log_cycle_handler.log_cycle( self.log_cycle_handler.log_cycle(
self.config.ai_name, self.ai_config.ai_name,
self.created_at, self.created_at,
self.cycle_count, self.cycle_count,
feedback, feedback,

View File

@ -150,7 +150,7 @@ def chat_with_ai(
if not plugin.can_handle_on_planning(): if not plugin.can_handle_on_planning():
continue continue
plugin_response = plugin.on_planning( plugin_response = plugin.on_planning(
agent.config.prompt_generator, message_sequence.raw() agent.ai_config.prompt_generator, message_sequence.raw()
) )
if not plugin_response or plugin_response == "": if not plugin_response or plugin_response == "":
continue continue
@ -181,7 +181,7 @@ def chat_with_ai(
logger.debug("") logger.debug("")
logger.debug("----------- END OF CONTEXT ----------------") logger.debug("----------- END OF CONTEXT ----------------")
agent.log_cycle_handler.log_cycle( agent.log_cycle_handler.log_cycle(
agent.config.ai_name, agent.ai_config.ai_name,
agent.created_at, agent.created_at,
agent.cycle_count, agent.cycle_count,
message_sequence.raw(), message_sequence.raw(),

View File

@ -189,9 +189,10 @@ def run_auto_gpt(
memory=memory, memory=memory,
next_action_count=next_action_count, next_action_count=next_action_count,
command_registry=command_registry, command_registry=command_registry,
config=ai_config,
system_prompt=system_prompt, system_prompt=system_prompt,
triggering_prompt=DEFAULT_TRIGGERING_PROMPT, triggering_prompt=DEFAULT_TRIGGERING_PROMPT,
workspace_directory=workspace_directory, workspace_directory=workspace_directory,
ai_config=ai_config,
config=cfg,
) )
agent.start_interaction_loop() agent.start_interaction_loop()

View File

@ -184,7 +184,7 @@ Latest Development:
prompt = ChatSequence.for_model(cfg.fast_llm_model, [Message("user", prompt)]) prompt = ChatSequence.for_model(cfg.fast_llm_model, [Message("user", prompt)])
self.agent.log_cycle_handler.log_cycle( self.agent.log_cycle_handler.log_cycle(
self.agent.config.ai_name, self.agent.ai_config.ai_name,
self.agent.created_at, self.agent.created_at,
self.agent.cycle_count, self.agent.cycle_count,
prompt.raw(), prompt.raw(),
@ -194,7 +194,7 @@ Latest Development:
self.summary = create_chat_completion(prompt) self.summary = create_chat_completion(prompt)
self.agent.log_cycle_handler.log_cycle( self.agent.log_cycle_handler.log_cycle(
self.agent.config.ai_name, self.agent.ai_config.ai_name,
self.agent.created_at, self.agent.created_at,
self.agent.cycle_count, self.agent.cycle_count,
self.summary, self.summary,

View File

@ -59,7 +59,8 @@ def browser_agent(agent_test_config, memory_none: NoMemory, workspace: Workspace
ai_name="", ai_name="",
memory=memory_none, memory=memory_none,
command_registry=command_registry, command_registry=command_registry,
config=ai_config, ai_config=ai_config,
config=agent_test_config,
next_action_count=0, next_action_count=0,
system_prompt=system_prompt, system_prompt=system_prompt,
triggering_prompt=DEFAULT_TRIGGERING_PROMPT, triggering_prompt=DEFAULT_TRIGGERING_PROMPT,
@ -95,7 +96,8 @@ def file_system_agents(
ai_name="Information Retrieval Agent", ai_name="Information Retrieval Agent",
memory=memory_json_file, memory=memory_json_file,
command_registry=command_registry, command_registry=command_registry,
config=ai_config, ai_config=ai_config,
config=agent_test_config,
next_action_count=0, next_action_count=0,
system_prompt=system_prompt, system_prompt=system_prompt,
triggering_prompt=DEFAULT_TRIGGERING_PROMPT, triggering_prompt=DEFAULT_TRIGGERING_PROMPT,
@ -125,7 +127,8 @@ def memory_management_agent(agent_test_config, memory_json_file, workspace: Work
ai_name="Follow-Instructions-GPT", ai_name="Follow-Instructions-GPT",
memory=memory_json_file, memory=memory_json_file,
command_registry=command_registry, command_registry=command_registry,
config=ai_config, ai_config=ai_config,
config=agent_test_config,
next_action_count=0, next_action_count=0,
system_prompt=system_prompt, system_prompt=system_prompt,
triggering_prompt=DEFAULT_TRIGGERING_PROMPT, triggering_prompt=DEFAULT_TRIGGERING_PROMPT,
@ -161,7 +164,8 @@ def information_retrieval_agents(
ai_name="Information Retrieval Agent", ai_name="Information Retrieval Agent",
memory=memory_json_file, memory=memory_json_file,
command_registry=command_registry, command_registry=command_registry,
config=ai_config, ai_config=ai_config,
config=agent_test_config,
next_action_count=0, next_action_count=0,
system_prompt=system_prompt, system_prompt=system_prompt,
triggering_prompt=DEFAULT_TRIGGERING_PROMPT, triggering_prompt=DEFAULT_TRIGGERING_PROMPT,
@ -172,7 +176,9 @@ def information_retrieval_agents(
@pytest.fixture @pytest.fixture
def kubernetes_agent(memory_json_file, workspace: Workspace): def kubernetes_agent(
agent_test_config: Config, memory_json_file: NoMemory, workspace: Workspace
) -> Agent:
command_registry = CommandRegistry() command_registry = CommandRegistry()
command_registry.import_commands("autogpt.commands.file_operations") command_registry.import_commands("autogpt.commands.file_operations")
command_registry.import_commands("autogpt.app") command_registry.import_commands("autogpt.app")
@ -193,7 +199,8 @@ def kubernetes_agent(memory_json_file, workspace: Workspace):
ai_name="Kubernetes-Demo", ai_name="Kubernetes-Demo",
memory=memory_json_file, memory=memory_json_file,
command_registry=command_registry, command_registry=command_registry,
config=ai_config, ai_config=ai_config,
config=agent_test_config,
next_action_count=0, next_action_count=0,
system_prompt=system_prompt, system_prompt=system_prompt,
triggering_prompt=DEFAULT_TRIGGERING_PROMPT, triggering_prompt=DEFAULT_TRIGGERING_PROMPT,
@ -226,7 +233,8 @@ def get_nobel_prize_agent(agent_test_config, memory_json_file, workspace: Worksp
ai_name="Get-PhysicsNobelPrize", ai_name="Get-PhysicsNobelPrize",
memory=memory_json_file, memory=memory_json_file,
command_registry=command_registry, command_registry=command_registry,
config=ai_config, ai_config=ai_config,
config=agent_test_config,
next_action_count=0, next_action_count=0,
system_prompt=system_prompt, system_prompt=system_prompt,
triggering_prompt=DEFAULT_TRIGGERING_PROMPT, triggering_prompt=DEFAULT_TRIGGERING_PROMPT,
@ -270,7 +278,8 @@ def debug_code_agents(agent_test_config, memory_json_file, workspace: Workspace)
ai_name="Debug Code Agent", ai_name="Debug Code Agent",
memory=memory_json_file, memory=memory_json_file,
command_registry=command_registry, command_registry=command_registry,
config=ai_config, ai_config=ai_config,
config=agent_test_config,
next_action_count=0, next_action_count=0,
system_prompt=system_prompt, system_prompt=system_prompt,
triggering_prompt=DEFAULT_TRIGGERING_PROMPT, triggering_prompt=DEFAULT_TRIGGERING_PROMPT,

View File

@ -4,28 +4,30 @@ import pytest
from autogpt.agent import Agent from autogpt.agent import Agent
from autogpt.config import AIConfig from autogpt.config import AIConfig
from autogpt.config.config import Config
@pytest.fixture @pytest.fixture
def agent(): def agent(config: Config):
ai_name = "Test AI" ai_name = "Test AI"
memory = MagicMock() memory = MagicMock()
next_action_count = 0 next_action_count = 0
command_registry = MagicMock() command_registry = MagicMock()
config = AIConfig() ai_config = AIConfig(ai_name=ai_name)
system_prompt = "System prompt" system_prompt = "System prompt"
triggering_prompt = "Triggering prompt" triggering_prompt = "Triggering prompt"
workspace_directory = "workspace_directory" workspace_directory = "workspace_directory"
agent = Agent( agent = Agent(
ai_name, ai_name=ai_name,
memory, memory=memory,
next_action_count, next_action_count=next_action_count,
command_registry, command_registry=command_registry,
config, ai_config=ai_config,
system_prompt, config=config,
triggering_prompt, system_prompt=system_prompt,
workspace_directory, triggering_prompt=triggering_prompt,
workspace_directory=workspace_directory,
) )
return agent return agent
@ -36,7 +38,7 @@ def test_agent_initialization(agent: Agent):
assert agent.history.messages == [] assert agent.history.messages == []
assert agent.next_action_count == 0 assert agent.next_action_count == 0
assert agent.command_registry == agent.command_registry assert agent.command_registry == agent.command_registry
assert agent.config == agent.config assert agent.ai_config == agent.ai_config
assert agent.system_prompt == "System prompt" assert agent.system_prompt == "System prompt"
assert agent.triggering_prompt == "Triggering prompt" assert agent.triggering_prompt == "Triggering prompt"

View File

@ -1,12 +1,15 @@
from datetime import datetime from datetime import datetime
from pytest_mock import MockerFixture
from autogpt.agent.agent import Agent from autogpt.agent.agent import Agent
from autogpt.config import AIConfig from autogpt.config import AIConfig
from autogpt.config.config import Config
from autogpt.llm.chat import create_chat_completion from autogpt.llm.chat import create_chat_completion
from autogpt.log_cycle.log_cycle import LogCycleHandler from autogpt.log_cycle.log_cycle import LogCycleHandler
def test_get_self_feedback(mocker): def test_get_self_feedback(config: Config, mocker: MockerFixture):
# Define a sample thoughts dictionary # Define a sample thoughts dictionary
thoughts = { thoughts = {
"reasoning": "Sample reasoning.", "reasoning": "Sample reasoning.",
@ -32,7 +35,8 @@ def test_get_self_feedback(mocker):
agent_mock = mocker.MagicMock(spec=Agent) agent_mock = mocker.MagicMock(spec=Agent)
# Mock the config attribute of the Agent instance # Mock the config attribute of the Agent instance
agent_mock.config = AIConfig() agent_mock.config = config
agent_mock.ai_config = AIConfig()
# Mock the log_cycle_handler attribute of the Agent instance # Mock the log_cycle_handler attribute of the Agent instance
agent_mock.log_cycle_handler = LogCycleHandler() agent_mock.log_cycle_handler = LogCycleHandler()