-
Notifications
You must be signed in to change notification settings - Fork 28.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Agents planning #31702
Agents planning #31702
Conversation
Fix infinite loops in python interpreter
1dce68f
to
75d1129
Compare
75d1129
to
8efac17
Compare
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
e00836b
to
50cad81
Compare
6dabac6
to
cbba80d
Compare
**BASE_PYTHON_TOOLS.copy(), | ||
**self.toolbox.tools, | ||
}, | ||
custom_tools=self.custom_tools, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is made because I needed to separate two sets of tools:
- user-defined tools that are static (at least they do not change within one call to
run
) but can be changed in-betweenrun
calls - agent-defined tools that will have to change within one run (thus the different handling in python interpreter)
@@ -365,7 +365,118 @@ def download_prompt(prompt_or_repo_id, agent_name, mode="run"): | |||
6. Don't name any new variable with the same name as a tool: for instance don't name a variable 'final_answer'. | |||
7. Never create any notional variables in our code, as having these in your logs might derail you from the true variables. | |||
8. You can use imports in your code, but only from the following list of modules: <<authorized_imports>> | |||
9. Don't give up! You're in charge of solving the task, not providing directions to solve it. | |||
9. The state persists between code executions: so if in one step you've created variables or imported modules, these will all persist. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This precision helps e.g. with matplotlib plots that persist between code snippets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super nice prompt!
@@ -75,8 +85,8 @@ def get_iterable(obj): | |||
raise InterpreterError("Object is not iterable") | |||
|
|||
|
|||
def evaluate_unaryop(expression, state, tools): | |||
operand = evaluate_ast(expression.operand, state, tools) | |||
def evaluate_unaryop(expression, state, static_tools, custom_tools): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We add the distinction between static_tools
and custom_tools
everywhere: static_tools
are the ones that the interpreter is not allowed to overwrite or create new ones (like base Python functions or user-defined tools), whereas custom_tools
are the ones it can modify or extend.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, understood! Can you clarify that in the methods' docstrings?
ops = [type(op) for op in condition.ops] | ||
|
||
result = True | ||
current_left = left | ||
|
||
for op, comparator in zip(ops, comparators): | ||
if op == ast.Eq: | ||
result = result and (current_left == comparator) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change allows to support pandas "==" statement between a Series and an int for instance
ef0c543
to
7263052
Compare
f""" | ||
The code blob you used is invalid: due to the following error: {e} | ||
This means that the regex pattern {pattern} was not respected: make sure to include code with the correct pattern, for instance: | ||
Thoughts: Your thoughts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We remind the correct pattern to guide the LLM towards correct formatting.
@@ -655,7 +687,7 @@ 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): | |||
def run(self, task: str, stream: bool = False, reset: bool = True, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This reset option is provisory, it will be refined later to help multi-turn conversation with an user.
src/transformers/agents/agents.py
Outdated
@@ -726,6 +764,91 @@ def direct_run(self, task: str, **kwargs): | |||
|
|||
return final_answer | |||
|
|||
def planning_step(self, task, is_first_step=False, iteration: int = None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We tried to keep this planning step as simple as possible for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem for me to merge this!
As the agents framework grows, it would be nice to complete the docstrings to hve each method be understood better; for example the methods planning_step
, provide_final_answer
, direct_run
, stream_run
, etc, are they supposed to be run by the user or by the Agent?
Clarifying this via their docstring would help a lot regarding the accessibility of the framework
@@ -75,8 +85,8 @@ def get_iterable(obj): | |||
raise InterpreterError("Object is not iterable") | |||
|
|||
|
|||
def evaluate_unaryop(expression, state, tools): | |||
operand = evaluate_ast(expression.operand, state, tools) | |||
def evaluate_unaryop(expression, state, static_tools, custom_tools): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, understood! Can you clarify that in the methods' docstrings?
@@ -365,7 +365,118 @@ def download_prompt(prompt_or_repo_id, agent_name, mode="run"): | |||
6. Don't name any new variable with the same name as a tool: for instance don't name a variable 'final_answer'. | |||
7. Never create any notional variables in our code, as having these in your logs might derail you from the true variables. | |||
8. You can use imports in your code, but only from the following list of modules: <<authorized_imports>> | |||
9. Don't give up! You're in charge of solving the task, not providing directions to solve it. | |||
9. The state persists between code executions: so if in one step you've created variables or imported modules, these will all persist. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super nice prompt!
What does this PR do?
This adds an optional planning steps to agents, to let them insert steps of higher-level planning to their workflow.
It also:
AgentType
behavior where int and floats or other outputs would be converted toAgentType
, which made them less accessible.