refactor agent class to streamline tool call handling and improve task reference management; enhance logging for API response parsing in base tool

pull/938/head
harshalmore31 3 weeks ago
parent 5029e7644b
commit 840dce779b

@ -581,8 +581,6 @@ class Agent:
# subsequent requests / summaries. # subsequent requests / summaries.
self.expecting_tool_call: bool = False self.expecting_tool_call: bool = False
self.tool_call_completed: bool = False self.tool_call_completed: bool = False
self.original_streaming_state: bool = self.streaming_on
self.should_stream_after_tools: bool = False
# self.short_memory = self.short_memory_init() # self.short_memory = self.short_memory_init()
@ -1006,6 +1004,9 @@ class Agent:
agent(task="What is the capital of France?", img="path/to/image.jpg", is_last=True) agent(task="What is the capital of France?", img="path/to/image.jpg", is_last=True)
""" """
try: try:
# Preserve the original user task so that tool summaries can reference it
if task is not None:
self.run_task = str(task)
self.check_if_no_prompt_then_autogenerate(task) self.check_if_no_prompt_then_autogenerate(task)
@ -1071,7 +1072,6 @@ class Agent:
if self.streaming_on and exists(self.tools) and not self.tool_call_completed: if self.streaming_on and exists(self.tools) and not self.tool_call_completed:
# Disable streaming for this request so we can reliably parse JSON # Disable streaming for this request so we can reliably parse JSON
self.expecting_tool_call = True self.expecting_tool_call = True
self.should_stream_after_tools = True
else: else:
self.expecting_tool_call = False self.expecting_tool_call = False
@ -1367,37 +1367,6 @@ class Agent:
) )
return self.run(task=improved_prompt, *args, **kwargs) return self.run(task=improved_prompt, *args, **kwargs)
# def parse_and_execute_tools(self, response: str, *args, **kwargs):
# max_retries = 3 # Maximum number of retries
# retries = 0
# while retries < max_retries:
# try:
# logger.info("Executing tool...")
# # try to Execute the tool and return a string
# out = parse_and_execute_json(
# functions=self.tools,
# json_string=response,
# parse_md=True,
# *args,
# **kwargs,
# )
# logger.info(f"Tool Output: {out}")
# # Add the output to the memory
# # self.short_memory.add(
# # role="Tool Executor",
# # content=out,
# # )
# return out
# except Exception as error:
# retries += 1
# logger.error(
# f"Attempt {retries}: Error executing tool: {error}"
# )
# if retries == max_retries:
# raise error
# time.sleep(1) # Wait for a bit before retrying
def add_memory(self, message: str): def add_memory(self, message: str):
"""Add a memory to the agent """Add a memory to the agent
@ -3003,15 +2972,18 @@ class Agent:
raise e raise e
def temp_llm_instance_for_tool_summary(self): def temp_llm_instance_for_tool_summary(self):
# Enable streaming for tool summary if original streaming was enabled and we should stream after tools """Create a temporary LiteLLM instance for the post-tool summary.
should_stream = getattr(self, 'should_stream_after_tools', False) and getattr(self, 'original_streaming_state', False)
If the agent was configured with `streaming_on=True`, the summary
request will also stream; otherwise it will be a normal synchronous
call. No extra coordination flags are required.
"""
return LiteLLM( return LiteLLM(
model_name=self.model_name, model_name=self.model_name,
temperature=self.temperature, temperature=self.temperature,
max_tokens=self.max_tokens, max_tokens=self.max_tokens,
system_prompt=self.system_prompt, system_prompt=self.system_prompt,
stream=should_stream, # Enable streaming for tool summaries if conditions are met stream=self.streaming_on,
tools_list_dictionary=None, tools_list_dictionary=None,
parallel_tool_calls=False, parallel_tool_calls=False,
base_url=self.llm_base_url, base_url=self.llm_base_url,
@ -3061,16 +3033,14 @@ class Agent:
tool_prompt = f""" tool_prompt = f"""
Please analyze and summarize the following tool execution output in a clear and concise way. Please analyze and summarize the following tool execution output in a clear and concise way.
Focus on the key information and insights that would be most relevant to the user's original request. Focus on the key information and insights that would be most relevant to the user's original request.
{self.run_task}
If there are any errors or issues, highlight them prominently. If there are any errors or issues, highlight them prominently.
Tool Output: Tool Output:
{output} {output}
""" """
# Check if we should stream the tool summary # Stream the tool summary only if the agent is configured for streaming
should_stream = getattr(self, 'should_stream_after_tools', False) and getattr(self, 'original_streaming_state', False) if self.streaming_on and self.print_on:
if should_stream and self.print_on:
# Handle streaming response with streaming panel # Handle streaming response with streaming panel
streaming_response = temp_llm.run(tool_prompt) streaming_response = temp_llm.run(tool_prompt)

@ -2262,15 +2262,16 @@ class BaseTool(BaseModel):
api_response = json.loads(api_response) api_response = json.loads(api_response)
except json.JSONDecodeError as e: except json.JSONDecodeError as e:
self._log_if_verbose( self._log_if_verbose(
"error", "debug",
f"Failed to parse JSON from API response: {e}. Response: '{api_response[:100]}...'", f"API response is not JSON format: {e}. This is normal for plain text responses. Response: '{api_response[:100]}...'",
) )
# If it's not JSON, it might be plain text without function calls
return [] return []
if not isinstance(api_response, dict): if not isinstance(api_response, dict):
self._log_if_verbose( self._log_if_verbose(
"warning", "debug",
f"API response is not a dictionary (type: {type(api_response)}), returning empty list", f"API response is not a dictionary (type: {type(api_response)}), no function calls detected",
) )
return [] return []

Loading…
Cancel
Save