diff --git a/autogpt/autogpt/agent_factory/configurators.py b/autogpt/autogpt/agent_factory/configurators.py index 57e37294843..1e930e8eabc 100644 --- a/autogpt/autogpt/agent_factory/configurators.py +++ b/autogpt/autogpt/agent_factory/configurators.py @@ -12,14 +12,15 @@ def create_agent( agent_id: str, task: str, - ai_profile: AIProfile, app_config: Config, file_storage: FileStorage, llm_provider: MultiProvider, + ai_profile: Optional[AIProfile] = None, directives: Optional[AIDirectives] = None, ) -> Agent: if not task: raise ValueError("No task specified for new agent") + ai_profile = ai_profile or AIProfile() directives = directives or AIDirectives() agent = _configure_agent( diff --git a/autogpt/autogpt/agent_factory/profile_generator.py b/autogpt/autogpt/agent_factory/profile_generator.py index f4406234894..604438fd790 100644 --- a/autogpt/autogpt/agent_factory/profile_generator.py +++ b/autogpt/autogpt/agent_factory/profile_generator.py @@ -21,53 +21,48 @@ class AgentProfileGeneratorConfiguration(SystemConfiguration): model_classification: LanguageModelClassification = UserConfigurable( default=LanguageModelClassification.SMART_MODEL ) - _example_call: object = [ - { - "type": "function", - "function": { - "name": "create_agent", - "arguments": { - "name": "CMOGPT", - "description": ( - "a professional digital marketer AI that assists Solopreneurs " - "in growing their businesses by providing " - "world-class expertise in solving marketing problems " - "for SaaS, content products, agencies, and more." + _example_call: object = { + "name": "create_agent", + "arguments": { + "name": "CMOGPT", + "description": ( + "a professional digital marketer AI that assists Solopreneurs " + "in growing their businesses by providing " + "world-class expertise in solving marketing problems " + "for SaaS, content products, agencies, and more." + ), + "directives": { + "best_practices": [ + ( + "Engage in effective problem-solving, prioritization, " + "planning, and supporting execution to address your " + "marketing needs as your virtual " + "Chief Marketing Officer." ), - "directives": { - "best_practices": [ - ( - "Engage in effective problem-solving, prioritization, " - "planning, and supporting execution to address your " - "marketing needs as your virtual " - "Chief Marketing Officer." - ), - ( - "Provide specific, actionable, and concise advice to " - "help you make informed decisions without the use of " - "platitudes or overly wordy explanations." - ), - ( - "Identify and prioritize quick wins and cost-effective " - "campaigns that maximize results with minimal time and " - "budget investment." - ), - ( - "Proactively take the lead in guiding you and offering " - "suggestions when faced with unclear information or " - "uncertainty to ensure your marketing strategy remains " - "on track." - ), - ], - "constraints": [ - "Do not suggest illegal or unethical plans or strategies.", - "Take reasonable budgetary limits into account.", - ], - }, - }, + ( + "Provide specific, actionable, and concise advice to " + "help you make informed decisions without the use of " + "platitudes or overly wordy explanations." + ), + ( + "Identify and prioritize quick wins and cost-effective " + "campaigns that maximize results with minimal time and " + "budget investment." + ), + ( + "Proactively take the lead in guiding you and offering " + "suggestions when faced with unclear information or " + "uncertainty to ensure your marketing strategy remains " + "on track." + ), + ], + "constraints": [ + "Do not suggest illegal or unethical plans or strategies.", + "Take reasonable budgetary limits into account.", + ], }, - } - ] + }, + } system_prompt: str = UserConfigurable( default=( "Your job is to respond to a user-defined task, given in triple quotes, by " @@ -192,7 +187,6 @@ def parse_response_content( Returns: The parsed response. - """ try: if not response.tool_calls: diff --git a/autogpt/autogpt/agents/agent.py b/autogpt/autogpt/agents/agent.py index a58cedf15eb..457200ed1f6 100644 --- a/autogpt/autogpt/agents/agent.py +++ b/autogpt/autogpt/agents/agent.py @@ -104,8 +104,6 @@ def __init__( super().__init__(settings) self.llm_provider = llm_provider - self.ai_profile = settings.ai_profile - self.directives = settings.directives prompt_config = OneShotAgentPromptStrategy.default_configuration.copy(deep=True) prompt_config.use_functions_api = ( settings.config.use_functions_api @@ -116,7 +114,7 @@ def __init__( self.commands: list[Command] = [] # Components - self.system = SystemComponent(legacy_config, settings.ai_profile) + self.system = SystemComponent() self.history = ActionHistoryComponent( settings.history, self.send_token_limit, diff --git a/autogpt/autogpt/agents/prompt_strategies/one_shot.py b/autogpt/autogpt/agents/prompt_strategies/one_shot.py index cab1286e876..620f39c0846 100644 --- a/autogpt/autogpt/agents/prompt_strategies/one_shot.py +++ b/autogpt/autogpt/agents/prompt_strategies/one_shot.py @@ -160,10 +160,7 @@ def build_system_prompt( + (self._generate_os_info() if include_os_info else []) + [ self.config.body_template.format( - constraints=format_numbered_list( - ai_directives.constraints - + self._generate_budget_constraint(ai_profile.api_budget) - ), + constraints=format_numbered_list(ai_directives.constraints), resources=format_numbered_list(ai_directives.resources), commands=self._generate_commands_list(commands), best_practices=format_numbered_list(ai_directives.best_practices), @@ -237,19 +234,6 @@ def _generate_os_info(self) -> list[str]: ) return [f"The OS you are running on is: {os_info}"] - def _generate_budget_constraint(self, api_budget: float) -> list[str]: - """Generates the budget information part of the prompt. - - Returns: - list[str]: The budget information part of the prompt, or an empty list. - """ - if api_budget > 0.0: - return [ - f"It takes money to let you run. " - f"Your API budget is ${api_budget:.3f}" - ] - return [] - def _generate_commands_list(self, commands: list[CompletionModelFunction]) -> str: """Lists the commands available to the agent. diff --git a/autogpt/autogpt/app/agent_protocol_server.py b/autogpt/autogpt/app/agent_protocol_server.py index 854f2ce2fa1..7544d817b2b 100644 --- a/autogpt/autogpt/app/agent_protocol_server.py +++ b/autogpt/autogpt/app/agent_protocol_server.py @@ -33,8 +33,7 @@ from hypercorn.config import Config as HypercornConfig from sentry_sdk import set_user -from autogpt.agent_factory.configurators import configure_agent_with_state -from autogpt.agent_factory.generators import generate_agent_for_task +from autogpt.agent_factory.configurators import configure_agent_with_state, create_agent from autogpt.agents.agent_manager import AgentManager from autogpt.app.utils import is_port_free @@ -134,8 +133,10 @@ async def create_task(self, task_request: TaskRequestBody) -> Task: input=task_request.input, additional_input=task_request.additional_input, ) - logger.debug(f"Creating agent for task: '{task.input}'") - task_agent = await generate_agent_for_task( + # TODO: re-evaluate performance benefit of task-oriented profiles + # logger.debug(f"Creating agent for task: '{task.input}'") + # task_agent = await generate_agent_for_task( + task_agent = create_agent( agent_id=task_agent_id(task.task_id), task=task.input, app_config=self.app_config, diff --git a/autogpt/autogpt/app/main.py b/autogpt/autogpt/app/main.py index 4fd3487c09a..d1387d10395 100644 --- a/autogpt/autogpt/app/main.py +++ b/autogpt/autogpt/app/main.py @@ -19,6 +19,7 @@ is_docker_available, we_are_running_in_a_docker_container, ) +from forge.config.ai_directives import AIDirectives from forge.config.ai_profile import AIProfile from forge.config.config import Config, ConfigBuilder, assert_config_has_openai_api_key from forge.file_storage import FileStorageBackendName, get_storage @@ -31,7 +32,6 @@ from forge.utils.exceptions import AgentTerminated, InvalidAgentResponseError from autogpt.agent_factory.configurators import configure_agent_with_state, create_agent -from autogpt.agent_factory.profile_generator import generate_agent_profile_for_task from autogpt.agents.agent_manager import AgentManager from autogpt.agents.prompt_strategies.one_shot import AssistantThoughts @@ -260,15 +260,11 @@ async def run_auto_gpt( " with as much detail as possible:", ) - ai_profile, task_oriented_ai_directives = await generate_agent_profile_for_task( - task, - app_config=config, - llm_provider=llm_provider, - ) - ai_directives = task_oriented_ai_directives + ai_profile = AIProfile() + additional_ai_directives = AIDirectives() apply_overrides_to_ai_settings( ai_profile=ai_profile, - directives=ai_directives, + directives=additional_ai_directives, override_name=override_ai_name, override_role=override_ai_role, resources=resources, @@ -288,9 +284,12 @@ async def run_auto_gpt( best_practices, ] ): - ai_profile, ai_directives = await interactively_revise_ai_settings( + ( + ai_profile, + additional_ai_directives, + ) = await interactively_revise_ai_settings( ai_profile=ai_profile, - directives=ai_directives, + directives=additional_ai_directives, app_config=config, ) else: @@ -300,7 +299,7 @@ async def run_auto_gpt( agent_id=agent_manager.generate_id(ai_profile.ai_name), task=task, ai_profile=ai_profile, - directives=ai_directives, + directives=additional_ai_directives, app_config=config, file_storage=file_storage, llm_provider=llm_provider, @@ -316,6 +315,22 @@ async def run_auto_gpt( extra={"preserve_color": True}, ) + # TODO: re-evaluate performance benefit of task-oriented profiles + # # Concurrently generate a custom profile for the agent and apply it once done + # def update_agent_directives( + # task: asyncio.Task[tuple[AIProfile, AIDirectives]] + # ): + # logger.debug(f"Updating AIProfile: {task.result()[0]}") + # logger.debug(f"Adding AIDirectives: {task.result()[1]}") + # agent.state.ai_profile = task.result()[0] + # agent.state.directives = agent.state.directives + task.result()[1] + + # asyncio.create_task( + # generate_agent_profile_for_task( + # task, app_config=config, llm_provider=llm_provider + # ) + # ).add_done_callback(update_agent_directives) + ################# # Run the Agent # ################# @@ -445,7 +460,7 @@ async def run_interaction_loop( """ # These contain both application config and agent config, so grab them here. legacy_config = agent.legacy_config - ai_profile = agent.ai_profile + ai_profile = agent.state.ai_profile logger = logging.getLogger(__name__) cycle_budget = cycles_remaining = _get_cycle_budget( diff --git a/forge/forge/components/system/system.py b/forge/forge/components/system/system.py index e642f286ee5..32a269d9660 100644 --- a/forge/forge/components/system/system.py +++ b/forge/forge/components/system/system.py @@ -4,8 +4,6 @@ from forge.agent.protocols import CommandProvider, DirectiveProvider, MessageProvider from forge.command import Command, command -from forge.config.ai_profile import AIProfile -from forge.config.config import Config from forge.llm.providers import ChatMessage from forge.models.json_schema import JSONSchema from forge.utils.const import FINISH_COMMAND @@ -17,16 +15,7 @@ class SystemComponent(DirectiveProvider, MessageProvider, CommandProvider): """Component for system messages and commands.""" - def __init__(self, config: Config, profile: AIProfile): - self.legacy_config = config - self.profile = profile - def get_constraints(self) -> Iterator[str]: - if self.profile.api_budget > 0.0: - yield ( - f"It takes money to let you run. " - f"Your API budget is ${self.profile.api_budget:.3f}" - ) yield "Exclusively use the commands listed below." yield ( "You can only act proactively, and are unable to start background jobs or " diff --git a/forge/forge/config/ai_profile.py b/forge/forge/config/ai_profile.py index ab8498b0516..a43d0bf4958 100644 --- a/forge/forge/config/ai_profile.py +++ b/forge/forge/config/ai_profile.py @@ -1,5 +1,14 @@ from pydantic import BaseModel, Field +DEFAULT_AI_NAME = "AutoGPT" +DEFAULT_AI_ROLE = ( + "a seasoned digital assistant: " + "capable, intelligent, considerate and assertive. " + "You have extensive research and development skills, and you don't shy " + "away from writing some code to solve a problem. " + "You are pragmatic and make the most out of the tools available to you." +) + class AIProfile(BaseModel): """ @@ -12,7 +21,7 @@ class AIProfile(BaseModel): api_budget (float): The maximum dollar value for API calls (0.0 means infinite) """ - ai_name: str = "" - ai_role: str = "" + ai_name: str = DEFAULT_AI_NAME + ai_role: str = DEFAULT_AI_ROLE + """`ai_role` should fit in the following format: `You are {ai_name}, {ai_role}`""" ai_goals: list[str] = Field(default_factory=list[str]) - api_budget: float = 0.0