diff --git a/crewai/agent.py b/crewai/agent.py index aab00a884..6d73306b7 100644 --- a/crewai/agent.py +++ b/crewai/agent.py @@ -8,9 +8,10 @@ from langchain.agents import AgentExecutor from langchain.chat_models import ChatOpenAI as OpenAI from langchain.tools.render import render_text_description from langchain.agents.format_scratchpad import format_log_to_str -from langchain.agents.output_parsers import ReActSingleInputOutputParser +from langchain.agents.output_parsers import ReActSingleInputOutputParser, PydanticOutputParser from .prompts import Prompts +from .agent.agent_vote import AgentVote class Agent(BaseModel): """Generic agent implementation.""" @@ -34,7 +35,26 @@ class Agent(BaseModel): ) ) - def execute(self, task: str) -> str: + def vote_agent_for_task(self, task: str) -> AgentVote: + """ + Execute a task with the agent. + Parameters: + task (str): Task to execute + Returns: + output (AgentVote): The agent voted to execute the task + """ + parser = PydanticOutputParser(pydantic_object=AgentVote) + prompt = Prompts.AGENT_EXECUTION_PROMPT.partial( + tools=render_text_description(self.tools), + tool_names=self.__tools_names(), + backstory=self.backstory, + role=self.role, + goal=self.goal, + format_instructions=parser.get_format_instructions() + ) + return self.__function_calling(task, prompt, parser) + + def execute_task(self, task: str) -> str: """ Execute a task with the agent. Parameters: @@ -49,16 +69,32 @@ class Agent(BaseModel): role=self.role, goal=self.goal, ) - return self.__run(task, prompt, self.tools) + return self.__execute_task(task, prompt) - def __run(self, input: str, prompt: str, tools: List[Tool]) -> str: + def __function_calling(self, input: str, prompt: str, parser: str) -> str: + inner_agent = { + "input": lambda x: x["input"], + "agent_scratchpad": lambda x: format_log_to_str(x['intermediate_steps']) + } | prompt | parser + + return self.__execute(inner_agent, input) + + def __execute_task(self, input: str, prompt: str) -> str: chat_with_bind = self.llm.bind(stop=["\nObservation"]) - agent = { + inner_agent = { "input": lambda x: x["input"], "agent_scratchpad": lambda x: format_log_to_str(x['intermediate_steps']) } | prompt | chat_with_bind | ReActSingleInputOutputParser() - agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, handle_parsing_errors=True) + return self.__execute(inner_agent, input) + + def __execute(self, inner_agent, input): + agent_executor = AgentExecutor( + agent=inner_agent, + tools=self.tools, + verbose=True, + handle_parsing_errors=True + ) return agent_executor.invoke({"input": input})['output'] def __tools_names(self) -> str: diff --git a/crewai/agent/agent_vote.py b/crewai/agent/agent_vote.py new file mode 100644 index 000000000..250c5c609 --- /dev/null +++ b/crewai/agent/agent_vote.py @@ -0,0 +1,5 @@ +from pydantic import BaseModel, Field + +class AgentVote(BaseModel): + task: str = Field(description="Task to be executed by the agent") + agent_vote: str = Field(description="Agent that will execute the task")