AgentOccam/Agent_E/ae/utils/autogen_sequential_function_call.py
2025-01-22 11:32:35 -08:00

86 lines
3.6 KiB
Python

import asyncio
import inspect
from typing import Any
from autogen import Agent # type: ignore
from autogen import UserProxyAgent # type: ignore
class UserProxyAgent_SequentialFunctionExecution(UserProxyAgent):
def __init__(self, *args, **kwargs): # type: ignore
super().__init__(*args, **kwargs) # type: ignore
#position = 2 allows termination check to be called earlier, this helps detect loops.
self.register_reply(Agent, UserProxyAgent_SequentialFunctionExecution.sequential_generate_tool_calls_reply, position=2) # type: ignore
def sequential_generate_tool_calls_reply( # type: ignore
self,
messages: list[dict] | None = None, # type: ignore
sender: Agent | None = None,
config: Any | None = None,
) -> tuple[bool, dict[str, Any] | None]:
"""Generate a reply using tool call."""
if config is None:
config = self
if messages is None:
messages = self._oai_messages[sender] # type: ignore
message = messages[-1] # type: ignore
tool_returns = []
skip_flag:bool = False
for tool_call in message.get("tool_calls", []): # type: ignore
function_call = tool_call.get("function", {}) # type: ignore
func = self._function_map.get(function_call.get("name", None), None) # type: ignore
func_return = None
if inspect.iscoroutinefunction(func): # type: ignore
try:
# get the running loop if it was already created
loop = asyncio.get_running_loop()
close_loop = False
except RuntimeError:
# create a loop if there is no running loop
loop = asyncio.new_event_loop()
close_loop = True
if (not skip_flag):
_, func_return = loop.run_until_complete(self.a_execute_function(function_call)) # type: ignore
if close_loop:
loop.close()
else:
if (not skip_flag):
_, func_return = self.execute_function(function_call) # type: ignore
if func_return is None: # type: ignore
if skip_flag:
content = "VERY IMPORTANT: This function could not be executed since previous function resulted in a Webpage change. You must get all_fields DOM and repeat the function if needed."
else:
content = ""
else:
content = func_return.get("content", "") # type: ignore
if content is None:
content = ""
if ("as a consequence of this action" in content.lower()): # type: ignore
skip_flag = True
tool_call_id = tool_call.get("id", None) # type: ignore
if tool_call_id is not None:
tool_call_response = { # type: ignore
"tool_call_id": tool_call_id,
"role": "tool",
"content": content,
}
else:
tool_call_response = { # type: ignore
"role": "tool",
"content": content,
}
tool_returns.append(tool_call_response) # type: ignore
if tool_returns:
return True, {
"role": "tool",
"tool_responses": tool_returns,
"content": "\n\n".join([self._str_for_tool_response(tool_return) for tool_return in tool_returns]), # type: ignore
}
return False, None