mirror of
https://github.com/microsoft/autogen.git
synced 2026-04-20 03:02:16 -04:00
Support function_call in autogen/agent (#1091)
* update funccall * code format * update to comments * update notebook * remove test for py3.7 * allow funccall to class functions * add test and clean up notebook * revise notebook and test * update * update mathagent * Update flaml/autogen/agent/agent.py Co-authored-by: Chi Wang <wang.chi@microsoft.com> * Update flaml/autogen/agent/user_proxy_agent.py Co-authored-by: Chi Wang <wang.chi@microsoft.com> * revise to comments * revise function call design, notebook and test. add doc * code format * ad message_to_dict function * update mathproxyagent * revise docstr * update * Update flaml/autogen/agent/math_user_proxy_agent.py Co-authored-by: Chi Wang <wang.chi@microsoft.com> * Update flaml/autogen/agent/math_user_proxy_agent.py Co-authored-by: Qingyun Wu <qingyun.wu@psu.edu> * Update flaml/autogen/agent/user_proxy_agent.py Co-authored-by: Qingyun Wu <qingyun.wu@psu.edu> * simply funccall in userproxyagent, rewind auto-gen.md, revise to comments * code format * update * remove notebook for another pr * revise oai_conversation part in agent, revise function exec in user_proxy_agent * update test_funccall * update * update * fix pydantic version * Update test/autogen/test_agent.py Co-authored-by: Chi Wang <wang.chi@microsoft.com> * fix bug * fix bug * update * update is_termination_msg to accept dict --------- Co-authored-by: Chi Wang <wang.chi@microsoft.com> Co-authored-by: Qingyun Wu <qingyun.wu@psu.edu> Co-authored-by: Li Jiang <bnujli@gmail.com>
This commit is contained in:
40
test/autogen/test_agent.py
Normal file
40
test/autogen/test_agent.py
Normal file
@@ -0,0 +1,40 @@
|
||||
def test_agent():
|
||||
from flaml.autogen.agent import Agent
|
||||
|
||||
dummy_agent_1 = Agent(name="dummy_agent_1")
|
||||
dummy_agent_2 = Agent(name="dummy_agent_2")
|
||||
|
||||
dummy_agent_1.receive("hello", dummy_agent_2) # receive a str
|
||||
dummy_agent_1.receive(
|
||||
{
|
||||
"content": "hello",
|
||||
},
|
||||
dummy_agent_2,
|
||||
) # receive a dict
|
||||
|
||||
# receive dict without openai fields to be printed, such as "content", 'function_call'. There should be no error raised.
|
||||
pre_len = len(dummy_agent_1._oai_conversations["dummy_agent_2"])
|
||||
dummy_agent_1.receive({"message": "hello"}, dummy_agent_2)
|
||||
assert pre_len == len(
|
||||
dummy_agent_1._oai_conversations["dummy_agent_2"]
|
||||
), "When the message is not an valid openai message, it should not be appended to the oai conversation."
|
||||
|
||||
dummy_agent_1._send("hello", dummy_agent_2) # send a str
|
||||
dummy_agent_1._send(
|
||||
{
|
||||
"content": "hello",
|
||||
},
|
||||
dummy_agent_2,
|
||||
) # send a dict
|
||||
|
||||
# receive dict with no openai fields
|
||||
pre_len = len(dummy_agent_1._oai_conversations["dummy_agent_2"])
|
||||
dummy_agent_1._send({"message": "hello"}, dummy_agent_2) # send dict with wrong field
|
||||
|
||||
assert pre_len == len(
|
||||
dummy_agent_1._oai_conversations["dummy_agent_2"]
|
||||
), "When the message is not a valid openai message, it should not be appended to the oai conversation."
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_agent()
|
||||
@@ -23,7 +23,7 @@ def test_gpt35(human_input_mode="NEVER", max_consecutive_auto_reply=5):
|
||||
"user",
|
||||
work_dir=f"{here}/test_agent_scripts",
|
||||
human_input_mode=human_input_mode,
|
||||
is_termination_msg=lambda x: x.rstrip().endswith("TERMINATE"),
|
||||
is_termination_msg=lambda x: x.get("content", "").rstrip().endswith("TERMINATE"),
|
||||
max_consecutive_auto_reply=max_consecutive_auto_reply,
|
||||
use_docker="python:3",
|
||||
)
|
||||
@@ -51,7 +51,7 @@ def test_create_execute_script(human_input_mode="NEVER", max_consecutive_auto_re
|
||||
"user",
|
||||
human_input_mode=human_input_mode,
|
||||
max_consecutive_auto_reply=max_consecutive_auto_reply,
|
||||
is_termination_msg=lambda x: x.rstrip().endswith("TERMINATE"),
|
||||
is_termination_msg=lambda x: x.get("content", "").rstrip().endswith("TERMINATE"),
|
||||
)
|
||||
assistant.receive(
|
||||
"""Create and execute a script to plot a rocket without using matplotlib""",
|
||||
|
||||
@@ -60,5 +60,68 @@ def test_eval_math_responses():
|
||||
print(eval_math_responses(**arguments))
|
||||
|
||||
|
||||
def test_json_extraction():
|
||||
from flaml.autogen.agent import UserProxyAgent
|
||||
|
||||
user = UserProxyAgent(name="test", use_docker=False)
|
||||
|
||||
jstr = '{\n"location": "Boston, MA"\n}'
|
||||
assert user._format_json_str(jstr) == '{"location": "Boston, MA"}'
|
||||
|
||||
jstr = '{\n"code": "python",\n"query": "x=3\nprint(x)"}'
|
||||
assert user._format_json_str(jstr) == '{"code": "python","query": "x=3\\nprint(x)"}'
|
||||
|
||||
jstr = '{"code": "a=\\"hello\\""}'
|
||||
assert user._format_json_str(jstr) == '{"code": "a=\\"hello\\""}'
|
||||
|
||||
|
||||
def test_execute_function():
|
||||
from flaml.autogen.agent import UserProxyAgent
|
||||
|
||||
# 1. test calling a simple function
|
||||
def add_num(num_to_be_added):
|
||||
given_num = 10
|
||||
return num_to_be_added + given_num
|
||||
|
||||
user = UserProxyAgent(name="test", function_map={"add_num": add_num})
|
||||
|
||||
# correct execution
|
||||
correct_args = {"name": "add_num", "arguments": '{ "num_to_be_added": 5 }'}
|
||||
assert user._execute_function(func_call=correct_args)[1]["content"] == "15"
|
||||
|
||||
# function name called is wrong or doesn't exist
|
||||
wrong_func_name = {"name": "subtract_num", "arguments": '{ "num_to_be_added": 5 }'}
|
||||
assert "Error: Function" in user._execute_function(func_call=wrong_func_name)[1]["content"]
|
||||
|
||||
# arguments passed is not in correct json format
|
||||
wrong_json_format = {
|
||||
"name": "add_num",
|
||||
"arguments": '{ "num_to_be_added": 5, given_num: 10 }',
|
||||
} # should be "given_num" with quotes
|
||||
assert (
|
||||
"You argument should follow json format." in user._execute_function(func_call=wrong_json_format)[1]["content"]
|
||||
)
|
||||
|
||||
# function execution error with wrong arguments passed
|
||||
wrong_args = {"name": "add_num", "arguments": '{ "num_to_be_added": 5, "given_num": 10 }'}
|
||||
assert "Error: " in user._execute_function(func_call=wrong_args)[1]["content"]
|
||||
|
||||
# 2. test calling a class method
|
||||
class AddNum:
|
||||
def __init__(self, given_num):
|
||||
self.given_num = given_num
|
||||
|
||||
def add(self, num_to_be_added):
|
||||
self.given_num = num_to_be_added + self.given_num
|
||||
return self.given_num
|
||||
|
||||
user = UserProxyAgent(name="test", function_map={"add_num": AddNum(given_num=10).add})
|
||||
func_call = {"name": "add_num", "arguments": '{ "num_to_be_added": 5 }'}
|
||||
assert user._execute_function(func_call=func_call)[1]["content"] == "15"
|
||||
assert user._execute_function(func_call=func_call)[1]["content"] == "20"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_json_extraction()
|
||||
test_execute_function()
|
||||
test_eval_math_responses()
|
||||
|
||||
Reference in New Issue
Block a user