Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swarm: User-defined AfterWork string for agent selection using LLM #368

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e082623
Moved functions and update_agent_state_before_reply parameters and as…
marklysze Dec 30, 2024
dfcc183
Move SwarmAgent functions out or to ConversableAgent
marklysze Dec 30, 2024
5a25727
Move SwarmAgent init to function
marklysze Dec 30, 2024
8882f9c
Merge remote-tracking branch 'origin/main' into swarmagenttoconversable
marklysze Dec 31, 2024
4221ba9
Merge remote-tracking branch 'origin/main' into swarmagenttoconversable
marklysze Dec 31, 2024
5b891ba
Updated agent's string representation
marklysze Dec 31, 2024
b99d9ad
Update swarm tests and add to ConversableAgent tests
marklysze Dec 31, 2024
1453683
Agent string representation, documentation updates for SwarmAgent and…
marklysze Dec 31, 2024
5978eb3
Updated test for agent string representation
marklysze Dec 31, 2024
ab9687c
Removed static method for Python 3.9 support
marklysze Dec 31, 2024
18b018d
Merge remote-tracking branch 'origin/main' into swarmagenttoconversable
marklysze Jan 2, 2025
85b56cc
Update autogen/agentchat/conversable_agent.py
marklysze Jan 2, 2025
c0030c2
Summary from nested chat refactoring, comment fix
marklysze Jan 2, 2025
0c12b99
UPDATE_SYSTEM_MESSAGE, AFTER_WORK, ON_CONDITION to UpdateSystemMessag…
marklysze Jan 2, 2025
0ca8f9d
Merge branch 'swarmagenttoconversable' of https://github.com/ag2ai/ag…
marklysze Jan 2, 2025
0ae67a6
Copyright updates
marklysze Jan 2, 2025
105ae56
add new class UpdateCondition, unit test passed.
linmou Jan 4, 2025
d0ef8e5
Code formatting
linmou Jan 4, 2025
0741ff7
Code formatting
linmou Jan 4, 2025
56aa33c
add document
linmou Jan 6, 2025
faafb64
Added UpdateCondition to init
marklysze Jan 6, 2025
4ef36a8
Documentation layout
marklysze Jan 6, 2025
5ad455a
Merge pull request #349 from ag2ai/swarmOnConditionWithContextV
marklysze Jan 6, 2025
7e3c1b9
Merge remote-tracking branch 'origin/main' into swarmagenttoconversable
marklysze Jan 6, 2025
7292a44
Add next_agent_selection_msg
marklysze Jan 6, 2025
34fbf59
Merge remote-tracking branch 'origin/swarmagenttoconversable' into sw…
marklysze Jan 6, 2025
80e8758
Updated next_agent_selection_msg types, group chat constants
marklysze Jan 6, 2025
a088fa0
Prepare group chat for auto speaker selection
marklysze Jan 6, 2025
cd8840d
Documentation
marklysze Jan 6, 2025
b7bfe70
Add swarm_manager_args
marklysze Jan 7, 2025
c267c65
Updated initiate_swarm_chat in documentation
marklysze Jan 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions autogen/agentchat/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2023 - 2024, Owners of https://github.com/ag2ai
# Copyright (c) 2023 - 2025, Owners of https://github.com/ag2ai
#
# SPDX-License-Identifier: Apache-2.0
#
Expand All @@ -17,14 +17,16 @@
from .contrib.swarm_agent import (
AFTER_WORK,
ON_CONDITION,
UPDATE_SYSTEM_MESSAGE,
AfterWork,
AfterWorkOption,
SwarmAgent,
OnCondition,
SwarmResult,
UpdateCondition,
a_initiate_swarm_chat,
initiate_swarm_chat,
register_hand_off,
)
from .conversable_agent import ConversableAgent, register_function
from .conversable_agent import UPDATE_SYSTEM_MESSAGE, ConversableAgent, UpdateSystemMessage, register_function
from .groupchat import GroupChat, GroupChatManager
from .user_proxy_agent import UserProxyAgent
from .utils import gather_usage_summary
Expand All @@ -42,11 +44,15 @@
"ChatResult",
"initiate_swarm_chat",
"a_initiate_swarm_chat",
"SwarmAgent",
"SwarmResult",
"ON_CONDITION",
"OnCondition",
"UpdateCondition",
"AFTER_WORK",
"AfterWork",
"AfterWorkOption",
"register_hand_off",
"UpdateSystemMessage",
"UPDATE_SYSTEM_MESSAGE",
"ReasoningAgent",
"visualize_tree",
Expand Down
1,034 changes: 463 additions & 571 deletions autogen/agentchat/contrib/swarm_agent.py

Large diffs are not rendered by default.

352 changes: 351 additions & 1 deletion autogen/agentchat/conversable_agent.py

Large diffs are not rendered by default.

20 changes: 12 additions & 8 deletions autogen/agentchat/groupchat.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@

logger = logging.getLogger(__name__)

__SELECT_SPEAKER_MESSAGE_TEMPLATE__ = """You are in a role play game. The following roles are available:
{roles}.
Read the following conversation.
Then select the next role from {agentlist} to play. Only return the role."""

__SELECT_SPEAKER_PROMPT_TEMPLATE__ = (
"Read the above conversation. Then select the next role from {agentlist} to play. Only return the role."
)


@dataclass
class GroupChat:
Expand Down Expand Up @@ -130,13 +139,8 @@ def custom_speaker_selection_func(
speaker_transitions_type: Literal["allowed", "disallowed", None] = None
enable_clear_history: bool = False
send_introductions: bool = False
select_speaker_message_template: str = """You are in a role play game. The following roles are available:
{roles}.
Read the following conversation.
Then select the next role from {agentlist} to play. Only return the role."""
select_speaker_prompt_template: str = (
"Read the above conversation. Then select the next role from {agentlist} to play. Only return the role."
)
select_speaker_message_template: str = __SELECT_SPEAKER_MESSAGE_TEMPLATE__
select_speaker_prompt_template: str = __SELECT_SPEAKER_PROMPT_TEMPLATE__
select_speaker_auto_multiple_template: str = """You provided more than one name in your text, please return just the name of the next speaker. To determine the speaker use these prioritised rules:
1. If the context refers to themselves as a speaker e.g. "As the..." , choose that speaker's name
2. If it refers to the "next" speaker name, choose that name
Expand Down Expand Up @@ -375,7 +379,7 @@ def select_speaker_prompt(self, agents: Optional[list[Agent]] = None) -> str:

agentlist = f"{[agent.name for agent in agents]}"

return_prompt = self.select_speaker_prompt_template.format(agentlist=agentlist)
return_prompt = f"{self.select_speaker_prompt_template}".replace("{agentlist}", agentlist)
return return_prompt

def introductions_msg(self, agents: Optional[list[Agent]] = None) -> str:
Expand Down
13 changes: 6 additions & 7 deletions autogen/agentchat/realtime_agent/realtime_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import anyio
from asyncer import create_task_group, syncify

from ... import SwarmAgent
from ...tools import Tool, get_function_schema
from ..agent import Agent
from ..conversable_agent import ConversableAgent
Expand Down Expand Up @@ -93,8 +92,8 @@ def __init__(
self._answer_event: anyio.Event = anyio.Event()
self._answer: str = ""
self._start_swarm_chat = False
self._initial_agent: Optional[SwarmAgent] = None
self._agents: Optional[list[SwarmAgent]] = None
self._initial_agent: Optional[ConversableAgent] = None
self._agents: Optional[list[ConversableAgent]] = None

@property
def logger(self) -> Logger:
Expand Down Expand Up @@ -122,15 +121,15 @@ def register_observer(self, observer: RealtimeObserver) -> None:
def register_swarm(
self,
*,
initial_agent: SwarmAgent,
agents: list[SwarmAgent],
initial_agent: ConversableAgent,
agents: list[ConversableAgent],
system_message: Optional[str] = None,
) -> None:
"""Register a swarm of agents with the Realtime Agent.

Args:
initial_agent (SwarmAgent): The initial agent.
agents (list[SwarmAgent]): The agents in the swarm.
initial_agent (ConversableAgent): The initial agent.
agents (list[ConversableAgent]): The agents in the swarm.
system_message (str): The system message for the agent.
"""
logger = self.logger
Expand Down
53 changes: 33 additions & 20 deletions notebook/agentchat_realtime_swarm.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@
"In this notebook, we implement OpenAI's [airline customer service example](https://github.com/openai/swarm/tree/main/examples/airline) in AG2 using the RealtimeAgent for enhanced interaction."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"````mdx-code-block\n",
":::note\n",
"This notebook has been updated as swarms can now accommodate any ConversableAgent.\n",
":::\n",
"````"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down Expand Up @@ -270,22 +281,22 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from autogen import ON_CONDITION, SwarmAgent\n",
"from autogen import ConversableAgent, OnCondition, register_hand_off\n",
"\n",
"# Triage Agent\n",
"triage_agent = SwarmAgent(\n",
"triage_agent = ConversableAgent(\n",
" name=\"Triage_Agent\",\n",
" system_message=triage_instructions(context_variables=context_variables),\n",
" llm_config=llm_config,\n",
" functions=[non_flight_enquiry],\n",
")\n",
"\n",
"# Flight Modification Agent\n",
"flight_modification = SwarmAgent(\n",
"flight_modification = ConversableAgent(\n",
" name=\"Flight_Modification_Agent\",\n",
" system_message=\"\"\"You are a Flight Modification Agent for a customer service airline.\n",
" Your task is to determine if the user wants to cancel or change their flight.\n",
Expand All @@ -295,23 +306,23 @@
")\n",
"\n",
"# Flight Cancel Agent\n",
"flight_cancel = SwarmAgent(\n",
"flight_cancel = ConversableAgent(\n",
" name=\"Flight_Cancel_Traversal\",\n",
" system_message=STARTER_PROMPT + FLIGHT_CANCELLATION_POLICY,\n",
" llm_config=llm_config,\n",
" functions=[initiate_refund, initiate_flight_credits, case_resolved, escalate_to_agent],\n",
")\n",
"\n",
"# Flight Change Agent\n",
"flight_change = SwarmAgent(\n",
"flight_change = ConversableAgent(\n",
" name=\"Flight_Change_Traversal\",\n",
" system_message=STARTER_PROMPT + FLIGHT_CHANGE_POLICY,\n",
" llm_config=llm_config,\n",
" functions=[valid_to_change_flight, change_flight, case_resolved, escalate_to_agent],\n",
")\n",
"\n",
"# Lost Baggage Agent\n",
"lost_baggage = SwarmAgent(\n",
"lost_baggage = ConversableAgent(\n",
" name=\"Lost_Baggage_Traversal\",\n",
" system_message=STARTER_PROMPT + LOST_BAGGAGE_POLICY,\n",
" llm_config=llm_config,\n",
Expand All @@ -325,33 +336,35 @@
"source": [
"### Register Handoffs\n",
"\n",
"Now we register the handoffs for the agents. Note that you don't need to define the transfer functions and pass them in. Instead, you can directly register the handoffs using the `ON_CONDITION` class."
"Now we register the handoffs for the agents. Note that you don't need to define the transfer functions and pass them in. Instead, you can directly register the handoffs using the `OnCondition` class."
]
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Register hand-offs\n",
"triage_agent.register_hand_off(\n",
" [\n",
" ON_CONDITION(flight_modification, \"To modify a flight\"),\n",
" ON_CONDITION(lost_baggage, \"To find lost baggage\"),\n",
" ]\n",
"register_hand_off(\n",
" agent=triage_agent,\n",
" hand_to=[\n",
" OnCondition(flight_modification, \"To modify a flight\"),\n",
" OnCondition(lost_baggage, \"To find lost baggage\"),\n",
" ],\n",
")\n",
"\n",
"flight_modification.register_hand_off(\n",
" [\n",
" ON_CONDITION(flight_cancel, \"To cancel a flight\"),\n",
" ON_CONDITION(flight_change, \"To change a flight\"),\n",
" ]\n",
"register_hand_off(\n",
" agent=flight_modification,\n",
" hand_to=[\n",
" OnCondition(flight_cancel, \"To cancel a flight\"),\n",
" OnCondition(flight_change, \"To change a flight\"),\n",
" ],\n",
")\n",
"\n",
"transfer_to_triage_description = \"Call this function when a user needs to be transferred to a different agent and a different policy.\\nFor instance, if a user is asking about a topic that is not handled by the current agent, call this function.\"\n",
"for agent in [flight_modification, flight_cancel, flight_change, lost_baggage]:\n",
" agent.register_hand_off(ON_CONDITION(triage_agent, transfer_to_triage_description))"
" register_hand_off(agent=agent, hand_to=OnCondition(triage_agent, transfer_to_triage_description))"
]
},
{
Expand Down
53 changes: 33 additions & 20 deletions notebook/agentchat_swarm.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@
"In this notebook, we implement OpenAI's [airline customer service example](https://github.com/openai/swarm/tree/main/examples/airline) in AG2."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"````mdx-code-block\n",
":::note\n",
"This notebook has been updated as swarms can now accommodate any ConversableAgent.\n",
":::\n",
"````"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down Expand Up @@ -222,18 +233,18 @@
"metadata": {},
"outputs": [],
"source": [
"from autogen import ON_CONDITION, AfterWorkOption, SwarmAgent, initiate_swarm_chat\n",
"from autogen import AfterWorkOption, ConversableAgent, OnCondition, initiate_swarm_chat, register_hand_off\n",
"\n",
"# Triage Agent\n",
"triage_agent = SwarmAgent(\n",
"triage_agent = ConversableAgent(\n",
" name=\"Triage_Agent\",\n",
" system_message=triage_instructions(context_variables=context_variables),\n",
" llm_config=llm_config,\n",
" functions=[non_flight_enquiry],\n",
")\n",
"\n",
"# Flight Modification Agent\n",
"flight_modification = SwarmAgent(\n",
"flight_modification = ConversableAgent(\n",
" name=\"Flight_Modification_Agent\",\n",
" system_message=\"\"\"You are a Flight Modification Agent for a customer service airline.\n",
" Your task is to determine if the user wants to cancel or change their flight.\n",
Expand All @@ -243,23 +254,23 @@
")\n",
"\n",
"# Flight Cancel Agent\n",
"flight_cancel = SwarmAgent(\n",
"flight_cancel = ConversableAgent(\n",
" name=\"Flight_Cancel_Traversal\",\n",
" system_message=STARTER_PROMPT + FLIGHT_CANCELLATION_POLICY,\n",
" llm_config=llm_config,\n",
" functions=[initiate_refund, initiate_flight_credits, case_resolved, escalate_to_agent],\n",
")\n",
"\n",
"# Flight Change Agent\n",
"flight_change = SwarmAgent(\n",
"flight_change = ConversableAgent(\n",
" name=\"Flight_Change_Traversal\",\n",
" system_message=STARTER_PROMPT + FLIGHT_CHANGE_POLICY,\n",
" llm_config=llm_config,\n",
" functions=[valid_to_change_flight, change_flight, case_resolved, escalate_to_agent],\n",
")\n",
"\n",
"# Lost Baggage Agent\n",
"lost_baggage = SwarmAgent(\n",
"lost_baggage = ConversableAgent(\n",
" name=\"Lost_Baggage_Traversal\",\n",
" system_message=STARTER_PROMPT + LOST_BAGGAGE_POLICY,\n",
" llm_config=llm_config,\n",
Expand All @@ -273,7 +284,7 @@
"source": [
"### Register Handoffs\n",
"\n",
"Now we register the handoffs for the agents. Note that you don't need to define the transfer functions and pass them in. Instead, you can directly register the handoffs using the `ON_CONDITION` class."
"Now we register the handoffs for the agents. Note that you don't need to define the transfer functions and pass them in. Instead, you can directly register the handoffs using the `OnCondition` class."
]
},
{
Expand All @@ -283,23 +294,25 @@
"outputs": [],
"source": [
"# Register hand-offs\n",
"triage_agent.register_hand_off(\n",
" [\n",
" ON_CONDITION(flight_modification, \"To modify a flight\"),\n",
" ON_CONDITION(lost_baggage, \"To find lost baggage\"),\n",
" ]\n",
"register_hand_off(\n",
" agent=triage_agent,\n",
" hand_to=[\n",
" OnCondition(flight_modification, \"To modify a flight\"),\n",
" OnCondition(lost_baggage, \"To find lost baggage\"),\n",
" ],\n",
")\n",
"\n",
"flight_modification.register_hand_off(\n",
" [\n",
" ON_CONDITION(flight_cancel, \"To cancel a flight\"),\n",
" ON_CONDITION(flight_change, \"To change a flight\"),\n",
" ]\n",
"register_hand_off(\n",
" agent=flight_modification,\n",
" hand_to=[\n",
" OnCondition(flight_cancel, \"To cancel a flight\"),\n",
" OnCondition(flight_change, \"To change a flight\"),\n",
" ],\n",
")\n",
"\n",
"transfer_to_triage_description = \"Call this function when a user needs to be transferred to a different agent and a different policy.\\nFor instance, if a user is asking about a topic that is not handled by the current agent, call this function.\"\n",
"for agent in [flight_modification, flight_cancel, flight_change, lost_baggage]:\n",
" agent.register_hand_off(ON_CONDITION(triage_agent, transfer_to_triage_description))"
" register_hand_off(agent=agent, hand_to=OnCondition(triage_agent, transfer_to_triage_description))"
]
},
{
Expand Down Expand Up @@ -373,7 +386,7 @@
"\u001b[33mTool_Execution\u001b[0m (to chat_manager):\n",
"\n",
"\u001b[32m***** Response from calling tool (call_Qgji9KAw1e3ktxykLU8v1wg7) *****\u001b[0m\n",
"SwarmAgent --> Flight_Modification_Agent\n",
"Swarm agent --> Flight_Modification_Agent\n",
"\u001b[32m**********************************************************************\u001b[0m\n",
"\n",
"--------------------------------------------------------------------------------\n",
Expand All @@ -397,7 +410,7 @@
"\u001b[33mTool_Execution\u001b[0m (to chat_manager):\n",
"\n",
"\u001b[32m***** Response from calling tool (call_QYu7uBko1EaEZ7VzxPwx2jNO) *****\u001b[0m\n",
"SwarmAgent --> Flight_Cancel_Traversal\n",
"Swarm agent --> Flight_Cancel_Traversal\n",
"\u001b[32m**********************************************************************\u001b[0m\n",
"\n",
"--------------------------------------------------------------------------------\n",
Expand Down
Loading
Loading