Skip to content

Commit 3d8fd5c

Browse files
marklyszeekzhu
andauthored
Added ability to ignore the addition of the select speaker prompt for a group chat (#2726)
Co-authored-by: Eric Zhu <[email protected]>
1 parent 4b5f599 commit 3d8fd5c

File tree

2 files changed

+62
-30
lines changed

2 files changed

+62
-30
lines changed

autogen/agentchat/groupchat.py

+39-9
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class GroupChat:
3939
Then select the next role from {agentlist} to play. Only return the role."
4040
- select_speaker_prompt_template: customize the select speaker prompt (used in "auto" speaker selection), which appears last in the message context and generally includes the list of agents and guidance for the LLM to select the next agent. If the string contains "{agentlist}" it will be replaced with a comma-separated list of agent names in square brackets. The default value is:
4141
"Read the above conversation. Then select the next role from {agentlist} to play. Only return the role."
42+
To ignore this prompt being used, set this to None. If set to None, ensure your instructions for selecting a speaker are in the select_speaker_message_template string.
4243
- select_speaker_auto_multiple_template: customize the follow-up prompt used when selecting a speaker fails with a response that contains multiple agent names. This prompt guides the LLM to return just one agent name. Applies only to "auto" speaker selection method. If the string contains "{agentlist}" it will be replaced with a comma-separated list of agent names in square brackets. The default value is:
4344
"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:
4445
1. If the context refers to themselves as a speaker e.g. "As the..." , choose that speaker's name
@@ -225,8 +226,8 @@ def __post_init__(self):
225226
if self.select_speaker_message_template is None or len(self.select_speaker_message_template) == 0:
226227
raise ValueError("select_speaker_message_template cannot be empty or None.")
227228

228-
if self.select_speaker_prompt_template is None or len(self.select_speaker_prompt_template) == 0:
229-
raise ValueError("select_speaker_prompt_template cannot be empty or None.")
229+
if self.select_speaker_prompt_template is not None and len(self.select_speaker_prompt_template) == 0:
230+
self.select_speaker_prompt_template = None
230231

231232
if self.role_for_select_speaker_messages is None or len(self.role_for_select_speaker_messages) == 0:
232233
raise ValueError("role_for_select_speaker_messages cannot be empty or None.")
@@ -330,7 +331,13 @@ def select_speaker_msg(self, agents: Optional[List[Agent]] = None) -> str:
330331
return return_msg
331332

332333
def select_speaker_prompt(self, agents: Optional[List[Agent]] = None) -> str:
333-
"""Return the floating system prompt selecting the next speaker. This is always the *last* message in the context."""
334+
"""Return the floating system prompt selecting the next speaker.
335+
This is always the *last* message in the context.
336+
Will return None if the select_speaker_prompt_template is None."""
337+
338+
if self.select_speaker_prompt_template is None:
339+
return None
340+
334341
if agents is None:
335342
agents = self.agents
336343

@@ -624,23 +631,35 @@ def validate_speaker_name(recipient, messages, sender, config) -> Tuple[bool, Un
624631
remove_other_reply_funcs=True,
625632
)
626633

634+
# NOTE: Do we have a speaker prompt (select_speaker_prompt_template is not None)? If we don't, we need to feed in the last message to start the nested chat
635+
627636
# Agent for selecting a single agent name from the response
628637
speaker_selection_agent = ConversableAgent(
629638
"speaker_selection_agent",
630639
system_message=self.select_speaker_msg(agents),
631-
chat_messages={checking_agent: messages},
640+
chat_messages=(
641+
{checking_agent: messages}
642+
if self.select_speaker_prompt_template is not None
643+
else {checking_agent: messages[:-1]}
644+
),
632645
llm_config=selector.llm_config,
633646
human_input_mode="NEVER", # Suppresses some extra terminal outputs, outputs will be handled by select_speaker_auto_verbose
634647
)
635648

649+
# Create the starting message
650+
if self.select_speaker_prompt_template is not None:
651+
start_message = {
652+
"content": self.select_speaker_prompt(agents),
653+
"override_role": self.role_for_select_speaker_messages,
654+
}
655+
else:
656+
start_message = messages[-1]
657+
636658
# Run the speaker selection chat
637659
result = checking_agent.initiate_chat(
638660
speaker_selection_agent,
639661
cache=None, # don't use caching for the speaker selection chat
640-
message={
641-
"content": self.select_speaker_prompt(agents),
642-
"override_role": self.role_for_select_speaker_messages,
643-
},
662+
message=start_message,
644663
max_turns=2
645664
* max(1, max_attempts), # Limiting the chat to the number of attempts, including the initial one
646665
clear_history=False,
@@ -711,6 +730,8 @@ def validate_speaker_name(recipient, messages, sender, config) -> Tuple[bool, Un
711730
remove_other_reply_funcs=True,
712731
)
713732

733+
# NOTE: Do we have a speaker prompt (select_speaker_prompt_template is not None)? If we don't, we need to feed in the last message to start the nested chat
734+
714735
# Agent for selecting a single agent name from the response
715736
speaker_selection_agent = ConversableAgent(
716737
"speaker_selection_agent",
@@ -720,11 +741,20 @@ def validate_speaker_name(recipient, messages, sender, config) -> Tuple[bool, Un
720741
human_input_mode="NEVER", # Suppresses some extra terminal outputs, outputs will be handled by select_speaker_auto_verbose
721742
)
722743

744+
# Create the starting message
745+
if self.select_speaker_prompt_template is not None:
746+
start_message = {
747+
"content": self.select_speaker_prompt(agents),
748+
"override_role": self.role_for_select_speaker_messages,
749+
}
750+
else:
751+
start_message = messages[-1]
752+
723753
# Run the speaker selection chat
724754
result = await checking_agent.a_initiate_chat(
725755
speaker_selection_agent,
726756
cache=None, # don't use caching for the speaker selection chat
727-
message=self.select_speaker_prompt(agents),
757+
message=start_message,
728758
max_turns=2
729759
* max(1, max_attempts), # Limiting the chat to the number of attempts, including the initial one
730760
clear_history=False,

test/agentchat/test_groupchat.py

+23-21
Original file line numberDiff line numberDiff line change
@@ -1321,15 +1321,17 @@ def test_select_speaker_message_and_prompt_templates():
13211321
select_speaker_prompt_template="Not empty.",
13221322
)
13231323

1324-
with pytest.raises(ValueError, match="select_speaker_prompt_template cannot be empty or None."):
1325-
groupchat = autogen.GroupChat(
1326-
agents=[agent1, agent2],
1327-
messages=[],
1328-
speaker_selection_method="auto",
1329-
max_round=10,
1330-
select_speaker_message_template="Not empty.",
1331-
select_speaker_prompt_template="",
1332-
)
1324+
# Will not throw an exception, prompt can be empty/None (empty is converted to None)
1325+
groupchat = autogen.GroupChat(
1326+
agents=[agent1, agent2],
1327+
messages=[],
1328+
speaker_selection_method="auto",
1329+
max_round=10,
1330+
select_speaker_message_template="Not empty.",
1331+
select_speaker_prompt_template="",
1332+
)
1333+
1334+
assert groupchat.select_speaker_prompt_template is None
13331335

13341336
# Test with None
13351337
with pytest.raises(ValueError, match="select_speaker_message_template cannot be empty or None."):
@@ -1342,15 +1344,17 @@ def test_select_speaker_message_and_prompt_templates():
13421344
select_speaker_prompt_template="Not empty.",
13431345
)
13441346

1345-
with pytest.raises(ValueError, match="select_speaker_prompt_template cannot be empty or None."):
1346-
groupchat = autogen.GroupChat(
1347-
agents=[agent1, agent2],
1348-
messages=[],
1349-
speaker_selection_method="auto",
1350-
max_round=10,
1351-
select_speaker_message_template="Not empty.",
1352-
select_speaker_prompt_template=None,
1353-
)
1347+
# Will not throw an exception, prompt can be empty/None (empty is converted to None)
1348+
groupchat = autogen.GroupChat(
1349+
agents=[agent1, agent2],
1350+
messages=[],
1351+
speaker_selection_method="auto",
1352+
max_round=10,
1353+
select_speaker_message_template="Not empty.",
1354+
select_speaker_prompt_template=None,
1355+
)
1356+
1357+
assert groupchat.select_speaker_prompt_template is None
13541358

13551359

13561360
def test_speaker_selection_agent_name_match():
@@ -2023,14 +2027,12 @@ def test_manager_resume_messages():
20232027
# test_clear_agents_history()
20242028
# test_custom_speaker_selection_overrides_transition_graph()
20252029
# test_role_for_select_speaker_messages()
2026-
# test_select_speaker_message_and_prompt_templates()
2030+
test_select_speaker_message_and_prompt_templates()
20272031
# test_speaker_selection_agent_name_match()
20282032
# test_role_for_reflection_summary()
20292033
# test_speaker_selection_auto_process_result()
20302034
# test_speaker_selection_validate_speaker_name()
20312035
# test_select_speaker_auto_messages()
2032-
# test_speaker_selection_auto_process_result()
2033-
# test_speaker_selection_validate_speaker_name()
20342036
# test_select_speaker_auto_messages()
20352037
# test_manager_messages_to_string()
20362038
# test_manager_messages_from_string()

0 commit comments

Comments
 (0)