diff --git a/autogen/agentchat/contrib/society_of_mind_agent.py b/autogen/agentchat/contrib/society_of_mind_agent.py index a12b228f0..6a6f4aa21 100644 --- a/autogen/agentchat/contrib/society_of_mind_agent.py +++ b/autogen/agentchat/contrib/society_of_mind_agent.py @@ -95,6 +95,26 @@ class SocietyOfMindAgent(ConversableAgent): for message in messages: message = copy.deepcopy(message) message["role"] = "user" + + # Convert tool and function calls to basic messages to avoid an error on the LLM call + if "content" not in message: + message["content"] = "" + + if "tool_calls" in message: + del message["tool_calls"] + if "tool_responses" in message: + del message["tool_responses"] + if "function_call" in message: + if message["content"] == "": + try: + message["content"] = ( + message["function_call"]["name"] + "(" + message["function_call"]["arguments"] + ")" + ) + except KeyError: + pass + del message["function_call"] + + # Add the modified message to the transcript _messages.append(message) _messages.append( diff --git a/test/agentchat/contrib/test_society_of_mind_agent.py b/test/agentchat/contrib/test_society_of_mind_agent.py index acee39a16..c4303f8b4 100644 --- a/test/agentchat/contrib/test_society_of_mind_agent.py +++ b/test/agentchat/contrib/test_society_of_mind_agent.py @@ -2,8 +2,18 @@ import pytest import sys import autogen import os +from typing_extensions import Annotated from autogen.agentchat.contrib.society_of_mind_agent import SocietyOfMindAgent +sys.path.append(os.path.join(os.path.dirname(__file__), "..")) +from test_assistant_agent import KEY_LOC, OAI_CONFIG_LIST # noqa: E402 + +sys.path.append(os.path.join(os.path.dirname(__file__), "../..")) +from conftest import skip_openai # noqa: E402 + +if not skip_openai: + config_list = autogen.config_list_from_json(env_or_file=OAI_CONFIG_LIST, file_location=KEY_LOC) + def test_society_of_mind_agent(): external_agent = autogen.ConversableAgent( @@ -195,6 +205,143 @@ def test_custom_preparer(): assert external_agent.chat_messages[soc][-1]["content"] == "All tests passed." +@pytest.mark.skipif( + skip_openai, + reason="do not run openai tests", +) +def test_function_calling(): + llm_config = {"config_list": config_list} + inner_llm_config = { + "config_list": config_list, + "functions": [ + { + "name": "reverse_print", + "description": "Prints a string in reverse", + "parameters": { + "type": "object", + "properties": { + "str": { + "type": "string", + "description": "The string to reverse-print", + } + }, + }, + "required": ["str"], + } + ], + } + + external_agent = autogen.ConversableAgent( + "external_agent", + max_consecutive_auto_reply=10, + human_input_mode="NEVER", + llm_config=False, + default_auto_reply="This is an external agent speaking.", + ) + + agent1 = autogen.ConversableAgent( + "alice", + max_consecutive_auto_reply=10, + human_input_mode="NEVER", + llm_config=inner_llm_config, + default_auto_reply="This is alice speaking.", + ) + agent2 = autogen.ConversableAgent( + "bob", + max_consecutive_auto_reply=10, + human_input_mode="NEVER", + llm_config=False, + default_auto_reply="This is bob speaking.", + ) + agent3 = autogen.ConversableAgent( + "sam", + max_consecutive_auto_reply=10, + human_input_mode="NEVER", + llm_config=False, + default_auto_reply="TERMINATE", + ) + + agent2.register_function( + function_map={ + "reverse_print": lambda str: str[::-1], + } + ) + + groupchat = autogen.GroupChat( + agents=[agent1, agent2, agent3], messages=[], speaker_selection_method="round_robin", max_round=10 + ) + + group_chat_manager = autogen.GroupChatManager( + groupchat=groupchat, + llm_config=False, + is_termination_msg=lambda x: x.get("content", "").find("TERMINATE") >= 0, + ) + + soc = SocietyOfMindAgent("soc_agent", chat_manager=group_chat_manager, llm_config=llm_config) + external_agent.send( + "Call the reverse_print function with the str 'Hello world.'", soc, request_reply=True, silent=False + ) + + +@pytest.mark.skipif( + skip_openai, + reason="do not run openai tests", +) +def test_tool_use(): + llm_config = {"config_list": config_list} + inner_llm_config = {"config_list": config_list} + + external_agent = autogen.ConversableAgent( + "external_agent", + max_consecutive_auto_reply=10, + human_input_mode="NEVER", + llm_config=False, + default_auto_reply="This is an external agent speaking.", + ) + + agent1 = autogen.ConversableAgent( + "alice", + max_consecutive_auto_reply=10, + human_input_mode="NEVER", + llm_config=inner_llm_config, + default_auto_reply="This is alice speaking.", + ) + agent2 = autogen.ConversableAgent( + "bob", + max_consecutive_auto_reply=10, + human_input_mode="NEVER", + llm_config=False, + default_auto_reply="This is bob speaking.", + ) + agent3 = autogen.ConversableAgent( + "sam", + max_consecutive_auto_reply=10, + human_input_mode="NEVER", + llm_config=False, + default_auto_reply="TERMINATE", + ) + + @agent2.register_for_execution() + @agent1.register_for_llm(name="reverse_print", description="Prints a string in reverse") + def _reverse_print(s: Annotated[str, "The string to reverse-print."]) -> str: + return s[::-1] + + groupchat = autogen.GroupChat( + agents=[agent1, agent2, agent3], messages=[], speaker_selection_method="round_robin", max_round=10 + ) + + group_chat_manager = autogen.GroupChatManager( + groupchat=groupchat, + llm_config=False, + is_termination_msg=lambda x: x.get("content", "").find("TERMINATE") >= 0, + ) + + soc = SocietyOfMindAgent("soc_agent", chat_manager=group_chat_manager, llm_config=llm_config) + external_agent.send("Call reverse_print with the str 'Hello world.'", soc, request_reply=True, silent=False) + + if __name__ == "__main__": - test_society_of_mind_agent() - test_custom_preparer() + # test_society_of_mind_agent() + # test_custom_preparer() + test_function_calling() + test_tool_use()