18
18
from dataclasses import dataclass
19
19
from typing import Any , Callable , Dict , List , Optional , Tuple , Union
20
20
21
+ from rich import box
21
22
from rich .console import Group
22
23
from rich .panel import Panel
23
24
from rich .rule import Rule
24
25
from rich .syntax import Syntax
25
26
from rich .text import Text
26
27
27
- from .default_tools import FinalAnswerTool
28
+ from .default_tools import FinalAnswerTool , TOOL_MAPPING
28
29
from .e2b_executor import E2BExecutor
29
30
from .local_python_executor import (
30
31
BASE_BUILTIN_MODULES ,
49
50
from .tools import (
50
51
DEFAULT_TOOL_DESCRIPTION_TEMPLATE ,
51
52
Tool ,
52
- Toolbox ,
53
53
get_tool_description_with_args ,
54
54
)
55
55
from .types import AgentAudio , AgentImage , handle_agent_output_types
@@ -107,18 +107,27 @@ class SystemPromptStep(AgentStep):
107
107
system_prompt : str
108
108
109
109
110
+ def get_tool_descriptions (
111
+ tools : Dict [str , Tool ], tool_description_template : str
112
+ ) -> str :
113
+ return "\n " .join (
114
+ [
115
+ get_tool_description_with_args (tool , tool_description_template )
116
+ for tool in tools .values ()
117
+ ]
118
+ )
119
+
120
+
110
121
def format_prompt_with_tools (
111
- toolbox : Toolbox , prompt_template : str , tool_description_template : str
122
+ tools : Dict [ str , Tool ] , prompt_template : str , tool_description_template : str
112
123
) -> str :
113
- tool_descriptions = toolbox . show_tool_descriptions ( tool_description_template )
124
+ tool_descriptions = get_tool_descriptions ( tools , tool_description_template )
114
125
prompt = prompt_template .replace ("{{tool_descriptions}}" , tool_descriptions )
115
-
116
126
if "{{tool_names}}" in prompt :
117
127
prompt = prompt .replace (
118
128
"{{tool_names}}" ,
119
- ", " .join ([f"'{ tool_name } '" for tool_name in toolbox . tools .keys ()]),
129
+ ", " .join ([f"'{ tool . name } '" for tool in tools .values ()]),
120
130
)
121
-
122
131
return prompt
123
132
124
133
@@ -163,7 +172,7 @@ class MultiStepAgent:
163
172
164
173
def __init__ (
165
174
self ,
166
- tools : Union [ List [Tool ], Toolbox ],
175
+ tools : List [Tool ],
167
176
model : Callable [[List [Dict [str , str ]]], str ],
168
177
system_prompt : Optional [str ] = None ,
169
178
tool_description_template : Optional [str ] = None ,
@@ -172,7 +181,7 @@ def __init__(
172
181
add_base_tools : bool = False ,
173
182
verbose : bool = False ,
174
183
grammar : Optional [Dict [str , str ]] = None ,
175
- managed_agents : Optional [Dict ] = None ,
184
+ managed_agents : Optional [List ] = None ,
176
185
step_callbacks : Optional [List [Callable ]] = None ,
177
186
planning_interval : Optional [int ] = None ,
178
187
):
@@ -196,17 +205,18 @@ def __init__(
196
205
197
206
self .managed_agents = {}
198
207
if managed_agents is not None :
208
+ print ("NOTNONE" )
199
209
self .managed_agents = {agent .name : agent for agent in managed_agents }
200
210
201
- if isinstance ( tools , Toolbox ):
202
- self . _toolbox = tools
203
- if add_base_tools :
204
- self . _toolbox . add_base_tools (
205
- add_python_interpreter = ( self . __class__ == ToolCallingAgent )
206
- )
207
- else :
208
- self ._toolbox = Toolbox ( tools , add_base_tools = add_base_tools )
209
- self ._toolbox . add_tool ( FinalAnswerTool () )
211
+ self . tools = { tool . name : tool for tool in tools }
212
+ if add_base_tools :
213
+ for tool_name , tool_class in TOOL_MAPPING . items () :
214
+ if (
215
+ tool_name != "python_interpreter"
216
+ or self . __class__ . __name__ == "ToolCallingAgent"
217
+ ) :
218
+ self .tools [ tool_name ] = tool_class ( )
219
+ self .tools [ "final_answer" ] = FinalAnswerTool ()
210
220
211
221
self .system_prompt = self .initialize_system_prompt ()
212
222
self .input_messages = None
@@ -217,14 +227,9 @@ def __init__(
217
227
self .step_callbacks = step_callbacks if step_callbacks is not None else []
218
228
self .step_callbacks .append (self .monitor .update_metrics )
219
229
220
- @property
221
- def toolbox (self ) -> Toolbox :
222
- """Get the toolbox currently available to the agent"""
223
- return self ._toolbox
224
-
225
230
def initialize_system_prompt (self ):
226
231
self .system_prompt = format_prompt_with_tools (
227
- self ._toolbox ,
232
+ self .tools ,
228
233
self .system_prompt_template ,
229
234
self .tool_description_template ,
230
235
)
@@ -384,10 +389,10 @@ def execute_tool_call(
384
389
This method replaces arguments with the actual values from the state if they refer to state variables.
385
390
386
391
Args:
387
- tool_name (`str`): Name of the Tool to execute (should be one from self.toolbox ).
392
+ tool_name (`str`): Name of the Tool to execute (should be one from self.tools ).
388
393
arguments (Dict[str, str]): Arguments passed to the Tool.
389
394
"""
390
- available_tools = {** self .toolbox . tools , ** self .managed_agents }
395
+ available_tools = {** self .tools , ** self .managed_agents }
391
396
if tool_name not in available_tools :
392
397
error_msg = f"Unknown tool { tool_name } , should be instead one of { list (available_tools .keys ())} ."
393
398
raise AgentExecutionError (error_msg )
@@ -415,7 +420,7 @@ def execute_tool_call(
415
420
raise AgentExecutionError (error_msg )
416
421
return observation
417
422
except Exception as e :
418
- if tool_name in self .toolbox . tools :
423
+ if tool_name in self .tools :
419
424
tool_description = get_tool_description_with_args (
420
425
available_tools [tool_name ]
421
426
)
@@ -512,20 +517,26 @@ def stream_run(self, task: str):
512
517
Runs the agent in streaming mode, yielding steps as they are executed: should be launched only in the `run` method.
513
518
"""
514
519
final_answer = None
515
- step_number = 0
516
- while final_answer is None and step_number < self .max_steps :
520
+ self . step_number = 0
521
+ while final_answer is None and self . step_number < self .max_steps :
517
522
step_start_time = time .time ()
518
- step_log = ActionStep (step = step_number , start_time = step_start_time )
523
+ step_log = ActionStep (step = self . step_number , start_time = step_start_time )
519
524
try :
520
525
if (
521
526
self .planning_interval is not None
522
- and step_number % self .planning_interval == 0
527
+ and self . step_number % self .planning_interval == 0
523
528
):
524
529
self .planning_step (
525
- task , is_first_step = (step_number == 0 ), step = step_number
530
+ task ,
531
+ is_first_step = (self .step_number == 0 ),
532
+ step = self .step_number ,
526
533
)
527
534
console .print (
528
- Rule (f"[bold]Step { step_number } " , characters = "━" , style = YELLOW_HEX )
535
+ Rule (
536
+ f"[bold]Step { self .step_number } " ,
537
+ characters = "━" ,
538
+ style = YELLOW_HEX ,
539
+ )
529
540
)
530
541
531
542
# Run one step!
@@ -538,10 +549,10 @@ def stream_run(self, task: str):
538
549
self .logs .append (step_log )
539
550
for callback in self .step_callbacks :
540
551
callback (step_log )
541
- step_number += 1
552
+ self . step_number += 1
542
553
yield step_log
543
554
544
- if final_answer is None and step_number == self .max_steps :
555
+ if final_answer is None and self . step_number == self .max_steps :
545
556
error_message = "Reached max steps."
546
557
final_step_log = ActionStep (error = AgentMaxStepsError (error_message ))
547
558
self .logs .append (final_step_log )
@@ -561,20 +572,26 @@ def direct_run(self, task: str):
561
572
Runs the agent in direct mode, returning outputs only at the end: should be launched only in the `run` method.
562
573
"""
563
574
final_answer = None
564
- step_number = 0
565
- while final_answer is None and step_number < self .max_steps :
575
+ self . step_number = 0
576
+ while final_answer is None and self . step_number < self .max_steps :
566
577
step_start_time = time .time ()
567
- step_log = ActionStep (step = step_number , start_time = step_start_time )
578
+ step_log = ActionStep (step = self . step_number , start_time = step_start_time )
568
579
try :
569
580
if (
570
581
self .planning_interval is not None
571
- and step_number % self .planning_interval == 0
582
+ and self . step_number % self .planning_interval == 0
572
583
):
573
584
self .planning_step (
574
- task , is_first_step = (step_number == 0 ), step = step_number
585
+ task ,
586
+ is_first_step = (self .step_number == 0 ),
587
+ step = self .step_number ,
575
588
)
576
589
console .print (
577
- Rule (f"[bold]Step { step_number } " , characters = "━" , style = YELLOW_HEX )
590
+ Rule (
591
+ f"[bold]Step { self .step_number } " ,
592
+ characters = "━" ,
593
+ style = YELLOW_HEX ,
594
+ )
578
595
)
579
596
580
597
# Run one step!
@@ -589,9 +606,9 @@ def direct_run(self, task: str):
589
606
self .logs .append (step_log )
590
607
for callback in self .step_callbacks :
591
608
callback (step_log )
592
- step_number += 1
609
+ self . step_number += 1
593
610
594
- if final_answer is None and step_number == self .max_steps :
611
+ if final_answer is None and self . step_number == self .max_steps :
595
612
error_message = "Reached max steps."
596
613
final_step_log = ActionStep (error = AgentMaxStepsError (error_message ))
597
614
self .logs .append (final_step_log )
@@ -637,8 +654,8 @@ def planning_step(self, task, is_first_step: bool, step: int):
637
654
"role" : MessageRole .USER ,
638
655
"content" : USER_PROMPT_PLAN .format (
639
656
task = task ,
640
- tool_descriptions = self . _toolbox . show_tool_descriptions (
641
- self .tool_description_template
657
+ tool_descriptions = get_tool_descriptions (
658
+ self .tools , self . tool_description_template
642
659
),
643
660
managed_agents_descriptions = (
644
661
show_agents_descriptions (self .managed_agents )
@@ -692,8 +709,8 @@ def planning_step(self, task, is_first_step: bool, step: int):
692
709
"role" : MessageRole .USER ,
693
710
"content" : USER_PROMPT_PLAN_UPDATE .format (
694
711
task = task ,
695
- tool_descriptions = self . _toolbox . show_tool_descriptions (
696
- self .tool_description_template
712
+ tool_descriptions = get_tool_descriptions (
713
+ self .tools , self . tool_description_template
697
714
),
698
715
managed_agents_descriptions = (
699
716
show_agents_descriptions (self .managed_agents )
@@ -761,7 +778,7 @@ def step(self, log_entry: ActionStep) -> Union[None, Any]:
761
778
try :
762
779
tool_name , tool_arguments , tool_call_id = self .model .get_tool_call (
763
780
self .input_messages ,
764
- available_tools = list (self .toolbox . _tools .values ()),
781
+ available_tools = list (self .tools .values ()),
765
782
stop_sequences = ["Observation:" ],
766
783
)
767
784
except Exception as e :
@@ -856,7 +873,7 @@ def __init__(
856
873
f"You passed both { use_e2b_executor = } and some managed agents. Managed agents is not yet supported with remote code execution."
857
874
)
858
875
859
- all_tools = {** self .toolbox . tools , ** self .managed_agents }
876
+ all_tools = {** self .tools , ** self .managed_agents }
860
877
if use_e2b_executor :
861
878
self .python_executor = E2BExecutor (
862
879
self .additional_authorized_imports , list (all_tools .values ())
@@ -941,10 +958,10 @@ def step(self, log_entry: ActionStep) -> Union[None, Any]:
941
958
lexer = "python" ,
942
959
theme = "monokai" ,
943
960
word_wrap = True ,
944
- line_numbers = True ,
945
961
),
946
962
title = "[bold]Executing this code:" ,
947
963
title_align = "left" ,
964
+ box = box .HORIZONTALS ,
948
965
)
949
966
)
950
967
observation = ""
@@ -1045,5 +1062,4 @@ def __call__(self, request, **kwargs):
1045
1062
"MultiStepAgent" ,
1046
1063
"CodeAgent" ,
1047
1064
"ToolCallingAgent" ,
1048
- "Toolbox" ,
1049
1065
]
0 commit comments