Skip to content
This repository was archived by the owner on Apr 14, 2025. It is now read-only.

Commit 19af70a

Browse files
committed
feat(libs): add Functionary adapters
1 parent 4ebe797 commit 19af70a

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

libs/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .functionary import FunctionaryAssistantAgent, FunctionaryUserProxyAgent

libs/functionary.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
"""Functionary API agent classes."""
2+
3+
import re
4+
from typing import Dict, Union
5+
import autogen
6+
7+
8+
class FunctionaryAssistantAgent(autogen.AssistantAgent):
9+
"""`AssistantAgent` class adptation for Functionary API."""
10+
11+
def _process_received_message(
12+
self,
13+
message: str | Union[Dict, str],
14+
sender: autogen.Agent,
15+
silent: bool | None,
16+
):
17+
normalized_message = normalize_message(message)
18+
super()._process_received_message(normalized_message, sender, silent)
19+
20+
21+
class FunctionaryUserProxyAgent(autogen.UserProxyAgent):
22+
"""`UserProxyAgent` class adptation for Functionary API."""
23+
24+
def _process_received_message(
25+
self,
26+
message: str | Union[Dict, str],
27+
sender: autogen.Agent,
28+
silent: bool | None,
29+
):
30+
normalized_message = normalize_message(message)
31+
super()._process_received_message(normalized_message, sender, silent)
32+
33+
34+
def normalize_message(message_as_str: str | Union[Dict, str]) -> Union[Dict, str]:
35+
"""Clean Functionary API message to fit Autogen expectations."""
36+
37+
print(message_as_str)
38+
39+
# pylint: disable=protected-access
40+
message = autogen.ConversableAgent._message_to_dict(message_as_str)
41+
42+
if not isinstance(message, dict):
43+
raise TypeError(
44+
f"Expected `message` to be a dictionary, got {type(message).__name__}."
45+
)
46+
47+
content = message.get("content", "")
48+
if not isinstance(content, str):
49+
raise TypeError(
50+
f"Expected 'content' key to be a string, got {type(content).__name__}."
51+
)
52+
53+
function_call_match = re.match(
54+
r"\s*to=functions\.([a-z_]+)[^\{]+(.*\})[^}]*", content, re.DOTALL
55+
)
56+
if function_call_match:
57+
function_name = function_call_match.group(1)
58+
function_arguments_as_json = function_call_match.group(2)
59+
60+
transformed_message = {
61+
"content": None,
62+
"function_call": {
63+
"name": function_name,
64+
"arguments": function_arguments_as_json,
65+
},
66+
"role": "assistant",
67+
}
68+
else:
69+
# Clean extra characters
70+
content = re.sub(r"^:\n", "", content)
71+
content = re.sub(r"\n user:\n$", "", content)
72+
content = content.strip()
73+
74+
if content == "":
75+
transformed_message = {"content": "TERMINATE"}
76+
else:
77+
transformed_message = {"content": content}
78+
79+
print(transformed_message)
80+
81+
return transformed_message

0 commit comments

Comments
 (0)