3
3
Callable ,
4
4
Optional
5
5
)
6
- import json
6
+
7
7
import yaml
8
+ import json
8
9
from rich .panel import Panel
9
10
from rich .text import Text
10
11
21
22
from src .memory import (ActionStep ,
22
23
ToolCall ,
23
24
AgentMemory )
24
- from src .logger import (
25
- LogLevel ,
26
- YELLOW_HEX ,
27
- logger # AsyncMultiStepAgent creates its own self.logger
28
- )
25
+ from src .logger import (LogLevel ,
26
+ YELLOW_HEX ,
27
+ logger )
29
28
from src .models import Model , parse_json_if_needed , ChatMessage
30
29
from src .utils .agent_types import (
31
30
AgentAudio ,
@@ -94,7 +93,6 @@ def __init__(
94
93
system_prompt = self .system_prompt ,
95
94
user_prompt = self .user_prompt ,
96
95
)
97
- # self.logger is inherited from AsyncMultiStepAgent and uses agent_name_to_use
98
96
99
97
def initialize_system_prompt (self ) -> str :
100
98
"""Initialize the system prompt for the agent."""
@@ -115,7 +113,6 @@ def initialize_user_prompt(self) -> str:
115
113
116
114
def initialize_task_instruction (self ) -> str :
117
115
"""Initialize the task instruction for the agent."""
118
- # self.task is set by the __call__ method of AsyncMultiStepAgent at runtime
119
116
task_instruction = populate_template (
120
117
self .prompt_templates ["task_instruction" ],
121
118
variables = {"task" : self .task },
@@ -220,42 +217,20 @@ async def step(self, memory_step: ActionStep) -> None | Any:
220
217
title = "Output message of the LLM:" ,
221
218
level = LogLevel .DEBUG ,
222
219
)
220
+
223
221
memory_step .model_output_message .content = model_output
224
222
memory_step .model_output = model_output
225
223
except Exception as e :
226
224
raise AgentGenerationError (f"Error while generating output:\n { e } " , self .logger ) from e
227
225
228
226
if chat_message .tool_calls is None or len (chat_message .tool_calls ) == 0 :
229
227
try :
230
- # Attempt to parse tool calls if they were not automatically populated
231
228
chat_message = self .model .parse_tool_calls (chat_message )
232
229
except Exception as e :
233
- # If parsing failed and there is model_output, it can be considered a direct answer
234
- if model_output :
235
- self .logger .log (
236
- Text (f"Tool call not detected. Processing model output as final answer: { model_output } " , style = f"bold { YELLOW_HEX } " ),
237
- level = LogLevel .INFO ,
238
- )
239
- memory_step .action_output = model_output
240
- return model_output
241
230
raise AgentParsingError (f"Error while parsing tool call from model output: { e } " , self .logger )
242
-
243
- # If there are still no tool calls after attempting to parse
244
- if not chat_message .tool_calls :
245
- if model_output :
246
- self .logger .log (
247
- Text (f"Tool call not detected after parsing. Processing model output as final answer: { model_output } " , style = f"bold { YELLOW_HEX } " ),
248
- level = LogLevel .INFO ,
249
- )
250
- memory_step .action_output = model_output
251
- return model_output
252
- else :
253
- # If there are no tool calls and no content, it's an error
254
- raise AgentParsingError ("Tool call not found, and there is no content in the model output." , self .logger )
255
-
256
- # Continue if there are tool calls
257
- for tool_call in chat_message .tool_calls :
258
- tool_call .function .arguments = parse_json_if_needed (tool_call .function .arguments )
231
+ else :
232
+ for tool_call in chat_message .tool_calls :
233
+ tool_call .function .arguments = parse_json_if_needed (tool_call .function .arguments )
259
234
260
235
tool_call = chat_message .tool_calls [0 ]
261
236
tool_name , tool_call_id = tool_call .function .name , tool_call .id
@@ -270,7 +245,10 @@ async def step(self, memory_step: ActionStep) -> None | Any:
270
245
)
271
246
if tool_name == "final_answer" :
272
247
if isinstance (tool_arguments , dict ):
273
- result = tool_arguments .get ("result" , tool_arguments )
248
+ if "result" in tool_arguments :
249
+ result = tool_arguments ["result" ]
250
+ else :
251
+ result = tool_arguments
274
252
else :
275
253
result = tool_arguments
276
254
if (
@@ -291,19 +269,21 @@ async def step(self, memory_step: ActionStep) -> None | Any:
291
269
memory_step .action_output = final_result
292
270
return final_result
293
271
else :
294
- tool_args_to_pass = tool_arguments if tool_arguments is not None else {}
295
- observation = await self .execute_tool_call (tool_name , tool_args_to_pass )
272
+ if tool_arguments is None :
273
+ tool_arguments = {}
274
+ observation = await self .execute_tool_call (tool_name , tool_arguments )
296
275
observation_type = type (observation )
297
-
298
276
if observation_type in [AgentImage , AgentAudio ]:
299
- observation_name = "image.png" if observation_type == AgentImage else "audio.mp3"
277
+ if observation_type == AgentImage :
278
+ observation_name = "image.png"
279
+ elif observation_type == AgentAudio :
280
+ observation_name = "audio.mp3"
300
281
# TODO: observation naming could allow for different names of same type
301
282
302
283
self .state [observation_name ] = observation
303
284
updated_information = f"Stored '{ observation_name } ' in memory."
304
285
else :
305
286
updated_information = str (observation ).strip ()
306
-
307
287
self .logger .log (
308
288
f"Observations: { updated_information .replace ('[' , '|' )} " , # escape potential rich-tag-like components
309
289
level = LogLevel .INFO ,
0 commit comments