diff --git a/src/crewai/agent.py b/src/crewai/agent.py index e7c36d45e..ad9a5bd23 100644 --- a/src/crewai/agent.py +++ b/src/crewai/agent.py @@ -261,7 +261,7 @@ class Agent(BaseModel): self, intermediate_steps: List[Tuple[AgentAction, str]], observation_prefix: str = "Result: ", - llm_prefix: str = "Thought: ", + llm_prefix: str = "", ) -> str: """Construct the scratchpad that lets the agent continue its thought process.""" thoughts = "" diff --git a/src/crewai/agents/executor.py b/src/crewai/agents/executor.py index 8dc35bd9f..7331581e5 100644 --- a/src/crewai/agents/executor.py +++ b/src/crewai/agents/executor.py @@ -3,7 +3,6 @@ from typing import Any, Dict, Iterator, List, Optional, Tuple, Union from langchain.agents import AgentExecutor from langchain.agents.agent import ExceptionTool -from langchain.agents.tools import InvalidTool from langchain.callbacks.manager import CallbackManagerForChainRun from langchain_core.agents import AgentAction, AgentFinish, AgentStep from langchain_core.exceptions import OutputParserException @@ -147,7 +146,7 @@ class CrewAgentExecutor(AgentExecutor): observation = f"\n{str(e.observation)}" text = str(e.llm_output) else: - observation = "Invalid or incomplete response" + observation = "" elif isinstance(self.handle_parsing_errors, str): observation = f"\n{self.handle_parsing_errors}" elif callable(self.handle_parsing_errors): @@ -206,15 +205,8 @@ class CrewAgentExecutor(AgentExecutor): ]: observation = tool_usage.use(tool_calling, agent_action.log) else: - tool_run_kwargs = self.agent.tool_run_logging_kwargs() - observation = InvalidTool().run( - { - "requested_tool_name": tool_calling.tool_name, - "available_tool_names": list(name_to_tool_map.keys()), - }, - verbose=self.verbose, - color=None, - callbacks=run_manager.get_child() if run_manager else None, - **tool_run_kwargs, + observation = self._i18n.errors("wrong_tool_name").format( + tool=tool_calling.tool_name, + tools=", ".join([tool.name for tool in self.tools]), ) yield AgentStep(action=agent_action, observation=observation) diff --git a/src/crewai/agents/parser.py b/src/crewai/agents/parser.py index 118932634..7fba15b5c 100644 --- a/src/crewai/agents/parser.py +++ b/src/crewai/agents/parser.py @@ -8,7 +8,7 @@ from crewai.utilities import I18N TOOL_USAGE_SECTION = "Use Tool:" FINAL_ANSWER_ACTION = "Final Answer:" -FINAL_ANSWER_AND_TOOL_ERROR_MESSAGE = "You are trying to use a tool and give a final answer at the same time, choose only one." +FINAL_ANSWER_AND_TOOL_ERROR_MESSAGE = "I tried to use a tool and give a final answer at the same time, I must choose only one." class CrewAgentParser(ReActSingleInputOutputParser): @@ -50,9 +50,8 @@ class CrewAgentParser(ReActSingleInputOutputParser): {"output": text.split(FINAL_ANSWER_ACTION)[-1].strip()}, text ) - error = self._i18n.errors("unexpected_format") format = self._i18n.slice("format_without_tools") - error = f"{error}\n{format}" + error = f"{format}" raise OutputParserException( error, observation=error, diff --git a/src/crewai/tools/agent_tools.py b/src/crewai/tools/agent_tools.py index c38aa12fc..c2c5737ff 100644 --- a/src/crewai/tools/agent_tools.py +++ b/src/crewai/tools/agent_tools.py @@ -42,11 +42,16 @@ class AgentTools(BaseModel): def _execute(self, agent, task, context): """Execute the command.""" - agent = [ - available_agent - for available_agent in self.agents - if available_agent.role.strip().lower() == agent.strip().lower() - ] + try: + agent = [ + available_agent + for available_agent in self.agents + if available_agent.role.strip().lower() == agent.strip().lower() + ] + except: + return self.i18n.errors("agent_tool_unexsiting_coworker").format( + coworkers="\n".join([f"- {agent.role}" for agent in self.agents]) + ) if not agent: return self.i18n.errors("agent_tool_unexsiting_coworker").format( diff --git a/src/crewai/tools/tool_usage.py b/src/crewai/tools/tool_usage.py index 0835272af..ad62475e8 100644 --- a/src/crewai/tools/tool_usage.py +++ b/src/crewai/tools/tool_usage.py @@ -82,7 +82,7 @@ class ToolUsage: error = getattr(e, "message", str(e)) self._printer.print(content=f"\n\n{error}\n", color="red") return error - return f"{self._use(tool_string=tool_string, tool=tool, calling=calling)}\n{self._i18n.slice('final_answer_format')}" + return f"{self._use(tool_string=tool_string, tool=tool, calling=calling)}\n\n{self._i18n.slice('final_answer_format')}" def _use( self, @@ -121,10 +121,13 @@ class ToolUsage: self._run_attempts += 1 if self._run_attempts > self._max_parsing_attempts: self._telemetry.tool_usage_error(llm=self.llm) + error_message = self._i18n.errors("tool_usage_exception").format( + error=e + ) error = ToolUsageErrorException( - f'{self._i18n.errors("tool_usage_exception").format(error=e)}.\n{self._i18n.slice("format").format(tool_names=self.tools_names)}' + f'\n{error_message}.\nMoving one then. {self._i18n.slice("format").format(tool_names=self.tools_names)}' ).message - self._printer.print(content=f"\n\n{error}\n", color="red") + self._printer.print(content=f"\n\n{error_message}\n", color="red") return error return self.use(calling=calling, tool_string=tool_string) @@ -196,7 +199,7 @@ class ToolUsage: instructor = Instructor( llm=self.llm, model=InstructorToolCalling, - content=f"Tools available:\n\n{self._render()}\n\nReturn a valid schema for the tool, the tool name must be equal one of the options, use this text to inform a valid ouput schema:\n{tool_string}```", + content=f"Tools available:\n###\n{self._render()}\n\nReturn a valid schema for the tool, the tool name must be equal one of the options, use this text to inform a valid ouput schema:\n{tool_string}```", instructions=dedent( """\ The schema should have the following structure, only two keys: @@ -204,7 +207,7 @@ class ToolUsage: - arguments: dict (with all arguments being passed) Example: - {"tool_name": "tool_name", "arguments": {"arg_name1": "value", "arg_name2": 2}} + {"tool_name": "tool name", "arguments": {"arg_name1": "value", "arg_name2": 2}} """ ), ) diff --git a/src/crewai/translations/en.json b/src/crewai/translations/en.json index facc4b7c6..9c2c0feb1 100644 --- a/src/crewai/translations/en.json +++ b/src/crewai/translations/en.json @@ -6,23 +6,24 @@ }, "slices": { "observation": "\nResult", - "task": "Begin! This is VERY important to you, your job depends on it!\n\nCurrent Task: {input}", + "task": "\n\nCurrent Task: {input}\n\n Begin! This is VERY important to you, your job depends on it!\n\n", "memory": "This is the summary of your work so far:\n{chat_history}", "role_playing": "You are {role}.\n{backstory}\n\nYour personal goal is: {goal}", - "tools": "You have access to ONLY the following tools, use one at time:\n\n{tools}\n\nTo use a tool you MUST use the exact following format:\n\n```\nUse Tool: the tool you wanna use, should be one of [{tool_names}] and absolute all relevant input and context for using the tool, you must use only one tool at once.\nResult: [result of the tool]\n```\n\nTo complete the task you MUST follow the format:\n\n```\nFinal Answer: [THE MOST COMPLETE ANSWE WITH ALL CONTEXT, DO NOT LEAVE ANYTHING OUT]\n``` You must use these formats, my life depends on it.", - "no_tools": "To complete the task you MUST follow the format:\n\n```\nFinal Answer: [your most complete final answer goes here]\n``` You must use these formats, my life depends on it.", - "format": "To use a tool you MUST use the exact following format:\n\n```\nUse Tool: the tool you wanna use, should be one of [{tool_names}] and absolute all relevant input and context for using the tool, you must use only one tool at once.\nResult: [result of the tool]\n```\n\nTo complete the task you MUST follow the format:\n\n```\nFinal Answer: [your most complete final answer goes here]\n``` You must use these formats, my life depends on it.", - "final_answer_format": "If you don't need to use any more tools, use the correct format for your final answer:\n\n```Final Answer: [your most complete final answer goes here]```", - "format_without_tools": "To use a tool you MUST use the exact following format:\n\n```\nUse Tool: the tool you wanna use, and absolute all relevant input and context for using the tool, you must use only one tool at once.\nResult: [result of the tool]\n```\n\nTo complete the task you MUST follow the format:\n\n```\nFinal Answer: [your most complete final answer goes here]\n``` You must use these formats, my life depends on it.", + "tools": "You have access to ONLY the following tools, use one at time:\n\n{tools}\n\nTo use a tool you MUST use the exact following format:\n\n```\nUse Tool: the tool you wanna use, should be one of [{tool_names}] and absolute all relevant input and context for using the tool, you must use only one tool at once.\nResult: [result of the tool]\n```\n\nTo give your final answer use the exact following format:\n\n```\nFinal Answer: [THE MOST COMPLETE ANSWE WITH ALL CONTEXT, DO NOT LEAVE ANYTHING OUT]\n```\nI MUST use these formats, my jobs depends on it!", + "no_tools": "To give your final answer use the exact following format:\n\n```\nFinal Answer: [entire content of your most complete final answer goes here]\n```\nI MUST use these formats, my jobs depends on it!", + "format": "You MUST either use a tool (use one at time) OR give your best final answer. To use a tool you MUST use the exact following format:\n\n```\nUse Tool: the tool you wanna use, should be one of [{tool_names}] and absolute all relevant input and context for using the tool, you must use only one tool at once.\nResult: [result of the tool]\n```\n\nTo give your final answer use the exact following format:\n\n```\nFinal Answer: [your most complete final answer goes here]\n```\nI MUST use these formats, my jobs depends on it!", + "final_answer_format": "If you don't need to use any more tools, make sure use the correct format to give your final answer:\n\n```Final Answer: [entire content of your most complete final answer goes here]```\n You MUST use these formats, your jobs depends on it!", + "format_without_tools": "ERROR: I didn't use the right format. I MUST either use a tool (use one at time) OR give my best final answer.\n\n```\nUse Tool: the tool you wanna use, and absolute all relevant input and context for using the tool, you must use only one tool at once.\nResult: [result of the tool]\n```\nOR\n```\nFinal Answer: [entire content of your most complete final answer goes here]\n```", "task_with_context": "{task}\nThis is the context you're working with:\n{context}", "expected_output": "Your final answer must be: {expected_output}" }, "errors": { - "unexpected_format": "You didn't use the expected format, you MUST use a tool or give your best final answer.", - "force_final_answer": "Actually, I used too many tools, so I'll stop now and give you my absolute BEST Final answer NOW, using exaclty the expected format bellow:\n\n```\nFinal Answer: [your most complete final answer goes here]\n``` You must use these formats, my life depends on it.", - "agent_tool_unexsiting_coworker": "\nError executing tool. Co-worker mentioned on the Action Input not found, it must to be one of the following options:\n{coworkers}.\n", - "task_repeated_usage": "I already used the {tool} tool with input {tool_input}. So I already know that and must stop using it with same input. \nI could give my best complete final answer if I'm ready, using exaclty the expected format bellow:\n\n```\nFinal Answer: [your most complete final answer goes here]\n``` You must use these formats, my life depends on it.", + "unexpected_format": "ERROR: I didn't use the expected format, I MUST either use a tool (use one at time) OR give my best final answer.\n", + "force_final_answer": "Actually, I used too many tools, so I'll stop now and give you my absolute BEST Final answer NOW, using exaclty the expected format bellow:\n\n```\nFinal Answer: [your most complete final answer goes here]\n```\nI MUST use these formats, my jobs depends on it!", + "agent_tool_unexsiting_coworker": "\nError executing tool. Co-worker mentioned not found, it must to be one of the following options:\n{coworkers}\n", + "task_repeated_usage": "I already used the {tool} tool with input {tool_input}. So I already know that and must stop using it with same input. \nI could give my best complete final answer if I'm ready, using exaclty the expected format bellow:\n\n```\nFinal Answer: [entire content of your most complete final answer goes here]\n```\nI MUST use these formats, my jobs depends on it!", "tool_usage_error": "It seems we encountered an unexpected error while trying to use the tool.", + "wrong_tool_name": "You tried to use the tool {tool}, but it doesn't exist. You must use one of the following tools, use one at time: {tools}.", "tool_usage_exception": "It seems we encountered an unexpected error while trying to use the tool. This was the error: {error}" }, "tools": { diff --git a/tests/agent_tools/agent_tools_test.py b/tests/agent_tools/agent_tools_test.py index 80a823b2d..160fb797b 100644 --- a/tests/agent_tools/agent_tools_test.py +++ b/tests/agent_tools/agent_tools_test.py @@ -51,7 +51,7 @@ def test_delegate_work_to_wrong_agent(): assert ( result - == "\nError executing tool. Co-worker mentioned on the Action Input not found, it must to be one of the following options:\n- researcher.\n" + == "\nError executing tool. Co-worker mentioned not found, it must to be one of the following options:\n- researcher\n" ) @@ -64,5 +64,5 @@ def test_ask_question_to_wrong_agent(): assert ( result - == "\nError executing tool. Co-worker mentioned on the Action Input not found, it must to be one of the following options:\n- researcher.\n" + == "\nError executing tool. Co-worker mentioned not found, it must to be one of the following options:\n- researcher\n" )