diff --git a/src/transformers/agents/agents.py b/src/transformers/agents/agents.py index 81e473d08669de..e09c3da344fe42 100644 --- a/src/transformers/agents/agents.py +++ b/src/transformers/agents/agents.py @@ -598,7 +598,6 @@ def __init__( if "final_answer" not in self._toolbox.tools: self._toolbox.add_tool(FinalAnswerTool()) - def provide_final_answer(self, task) -> str: """ This method provides a final answer to the task, based on the logs of the agent's interactions. @@ -621,7 +620,6 @@ def provide_final_answer(self, task) -> str: except Exception as e: return f"Error in generating final llm output: {e}." - def run(self, task: str, stream: bool = False, **kwargs): """ Runs the agent for the given task. @@ -644,7 +642,6 @@ def run(self, task: str, stream: bool = False, **kwargs): else: return self.direct_run(task, **kwargs) - def stream_run(self, task: str, **kwargs): self.initialize_for_run(task, **kwargs) @@ -653,8 +650,8 @@ def stream_run(self, task: str, **kwargs): while final_answer is None and iteration < self.max_iterations: try: step_logs = self.step() - if 'final_answer' in step_logs: - final_answer = step_logs['final_answer'] + if "final_answer" in step_logs: + final_answer = step_logs["final_answer"] except AgentError as e: self.logger.error(e, exc_info=1) self.logs[-1]["error"] = e @@ -664,17 +661,14 @@ def stream_run(self, task: str, **kwargs): if final_answer is None and iteration == self.max_iterations: error_message = "Reached max iterations." - final_step_log = { - "error": AgentMaxIterationsError(error_message) - } + final_step_log = {"error": AgentMaxIterationsError(error_message)} self.logs.append(final_step_log) self.logger.error(error_message, exc_info=1) final_answer = self.provide_final_answer(task) final_step_log["final_answer"] = final_answer yield final_step_log - return final_answer - + yield final_answer def direct_run(self, task: str, **kwargs): self.initialize_for_run(task, **kwargs) @@ -684,8 +678,8 @@ def direct_run(self, task: str, **kwargs): while final_answer is None and iteration < self.max_iterations: try: step_logs = self.step() - if 'final_answer' in step_logs: - final_answer = step_logs['final_answer'] + if "final_answer" in step_logs: + final_answer = step_logs["final_answer"] except AgentError as e: self.logger.error(e, exc_info=1) self.logs[-1]["error"] = e @@ -694,9 +688,7 @@ def direct_run(self, task: str, **kwargs): if final_answer is None and iteration == self.max_iterations: error_message = "Reached max iterations." - final_step_log = { - "error": AgentMaxIterationsError(error_message) - } + final_step_log = {"error": AgentMaxIterationsError(error_message)} self.logs.append(final_step_log) self.logger.error(error_message, exc_info=1) final_answer = self.provide_final_answer(task) diff --git a/src/transformers/agents/prompts.py b/src/transformers/agents/prompts.py index a3e7873e4c8234..f76734b09fa88f 100644 --- a/src/transformers/agents/prompts.py +++ b/src/transformers/agents/prompts.py @@ -145,10 +145,6 @@ def download_prompt(prompt_or_repo_id, agent_name, mode="run"): Make sure to have the $INPUT as a dictionnary in the right format for the tool you are using, and do not put variable names as input if you can find the right values. -You will be given: - -Task: the task you are given. - You should ALWAYS use the following format: Thought: you should always think about one action to take. Then use the action as follows: @@ -266,10 +262,10 @@ def download_prompt(prompt_or_repo_id, agent_name, mode="run"): DEFAULT_REACT_CODE_SYSTEM_PROMPT = """You will be given a task to solve as best you can. -To do so, you have been given access to tools that are basically Python functions which you can call with code. +To do so, you have been given access to *tools*: these tools are basically Python functions which you can call with code. To solve the task, you must plan forward to proceed in a series of steps, in a cycle of 'Thought:', 'Code:', and 'Observation:' sequences. -At each step, in the 'Thought:' sequence, you should first explain your reasoning towards solving the task, then the tools that you want to use. +At each step, in the 'Thought:' sequence, you should first explain your reasoning towards solving the task and the tools that you want to use. Then in the 'Code:' sequence, you should write the code in simple Python. The code sequence must end with '' sequence. During each intermediate step, you can use 'print()' to save whatever important information you will then need. These print outputs will then appear in the 'Observation:' field, which will be available as input for the next step. @@ -307,7 +303,7 @@ def download_prompt(prompt_or_repo_id, agent_name, mode="run"): ``` --- -Task: "Which city has the highest population , Guangzhou or Shanghai?" +Task: "Which city has the highest population: Guangzhou or Shanghai?" Thought: I need to get the populations for both cities and compare them: I will use the tool `search` to get the population of both cities. Code: @@ -350,14 +346,13 @@ def download_prompt(prompt_or_repo_id, agent_name, mode="run"): <> -You also can perform computations in the python code that you generate. +You also can perform computations in the Python code that you generate. Here are the rules you should always follow to solve your task: 1. Always provide a 'Thought:' sequence, and a 'Code:\n```py' sequence ending with '```' sequence, else you will fail. -2. Use only variables that you defined! +2. Use only variables that you have defined! 3. Always use the right arguments for the tools. DO NOT pass the arguments as a dict as in 'answer = ask_search_agent({'query': "What is the place where James Bond lives?"})', but use the arguments directly as in 'answer = ask_search_agent(query="What is the place where James Bond lives?")'. -4. In the code you generate, you can do several tool calls in parallel, but do not perform too many tool calls sequentially in a single block, especialy when the output of one tool call is in an unpredictable format: in that case rather split the task into intermediate code blocks, then use print() to save the intermediate result. Finally, use final_answer() to return the final result. -For instance if you need to call search for three independant topics, you can do three calls in the same code block. But if you're waiting for the ouput of one search call to generate an image, rather print the search output, then generate the image in the next step. +4. Take care to not chain too many sequential tool calls in the same code block, especially when the output format is unpredictable. For instance, a call to search has an unpredictable return format, so do not have another tool call that depends on its output in the same block: rather output results with print() to use them in the next block. 5. Call a tool only when needed, and never re-do a tool call that you previously did with the exact same parameters. 6. Don't name any new variable with the same name as a tool: for instance don't name a variable 'final_answer'. diff --git a/src/transformers/agents/python_interpreter.py b/src/transformers/agents/python_interpreter.py index b64f8760208ccf..0a2d535ca5bbe0 100644 --- a/src/transformers/agents/python_interpreter.py +++ b/src/transformers/agents/python_interpreter.py @@ -29,7 +29,19 @@ class InterpretorError(ValueError): pass -LIST_SAFE_MODULES = ["random", "collections", "requests", "math", "time", "queue", "itertools", "re", "stat", "statistics", "unicodedata"] +LIST_SAFE_MODULES = [ + "random", + "collections", + "requests", + "math", + "time", + "queue", + "itertools", + "re", + "stat", + "statistics", + "unicodedata", +] class BreakException(Exception):