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

Update speaker selector in GroupChat and update some notebooks #688

Merged
merged 27 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b6f528a
Add speaker selection methods
thinkall Nov 15, 2023
c558e68
Update groupchat RAG
thinkall Nov 15, 2023
8953173
Update seed to cache_seed
thinkall Nov 15, 2023
8cae4f4
Update RetrieveChat notebook
thinkall Nov 15, 2023
37a6f74
Update parameter name
thinkall Nov 15, 2023
9008d91
Add test
thinkall Nov 15, 2023
a660718
Add more tests
thinkall Nov 15, 2023
de073c8
Add mock to test
thinkall Nov 15, 2023
91d50ca
Add mock to test
thinkall Nov 15, 2023
5f24a0e
Merge branch 'main' into update_selector
thinkall Nov 16, 2023
da7c932
Fix typo speaking
thinkall Nov 16, 2023
4872cff
Add gracefully exit manual input
thinkall Nov 16, 2023
07e4fdb
Update round_robin docstring
thinkall Nov 16, 2023
28b1711
Add method checking
thinkall Nov 16, 2023
10255de
Merge main
thinkall Nov 17, 2023
7966c27
Remove participant roles
thinkall Nov 17, 2023
16f1681
Fix versions in notebooks
thinkall Nov 17, 2023
3dbbd33
Minimize installation overhead
thinkall Nov 17, 2023
9955a60
Fix missing lower()
thinkall Nov 17, 2023
e7c3cc3
Add comments for try_count 3
thinkall Nov 17, 2023
38cb8ae
Update warning for n_agents < 3
thinkall Nov 17, 2023
8c9cb59
Update warning for n_agents < 3
thinkall Nov 17, 2023
7449ca5
Add test_n_agents_less_than_3
thinkall Nov 17, 2023
8817302
Add a function for manual select
thinkall Nov 17, 2023
68164e8
Merge main
thinkall Nov 17, 2023
f28eca5
Update version in notebooks
thinkall Nov 17, 2023
0e230b6
Fixed bugs that allow speakers to go twice in a row even when allow_r…
afourney Nov 17, 2023
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
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
python -m pip install --upgrade pip wheel
pip install -e .
python -c "import autogen"
pip install -e. pytest
pip install -e.[test]
thinkall marked this conversation as resolved.
Show resolved Hide resolved
pip uninstall -y openai
- name: Install unstructured if not windows
if: matrix.os != 'windows-2019'
Expand Down
68 changes: 60 additions & 8 deletions autogen/agentchat/groupchat.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from dataclasses import dataclass
import sys
import random
from typing import Dict, List, Optional, Union
from .agent import Agent
from .conversable_agent import ConversableAgent
Expand All @@ -20,13 +21,24 @@ class GroupChat:
When set to True and when a message is a function call suggestion,
the next speaker will be chosen from an agent which contains the corresponding function name
in its `function_map`.
- speaker_selection_method: the method for selecting the next speaker. Default is "auto".
Could be any of the following (case insensitive), will raise ValueError if not recognized:
- "auto": the next speaker is selected automatically by LLM.
- "manual": the next speaker is selected manually by user input.
- "random": the next speaker is selected randomly.
- "round_robin": the next speaker is selected in a round robin fashion, i.e., iterating in the same order as provided in `agents`.
- allow_repeat_speaker: whether to allow the same speaker to speak consecutively. Default is True.
"""

agents: List[Agent]
messages: List[Dict]
max_round: int = 10
admin_name: str = "Admin"
func_call_filter: bool = True
speaker_selection_method: str = "auto"
allow_repeat_speaker: bool = True

_VALID_SPEAKER_SELECTION_METHODS = ["auto", "manual", "random", "round_robin"]

@property
def agent_names(self) -> List[str]:
Expand Down Expand Up @@ -61,6 +73,20 @@ def select_speaker_msg(self, agents: List[Agent]):

def select_speaker(self, last_speaker: Agent, selector: ConversableAgent):
"""Select the next speaker."""
if self.speaker_selection_method.lower() not in self._VALID_SPEAKER_SELECTION_METHODS:
raise ValueError(
f"GroupChat speaker_selection_method is set to '{self.speaker_selection_method}'. "
f"It should be one of {self._VALID_SPEAKER_SELECTION_METHODS} (case insensitive). "
thinkall marked this conversation as resolved.
Show resolved Hide resolved
)

agents = self.agents
# Warn if GroupChat is underpopulated
n_agents = len(agents)
if n_agents < 3:
sonichi marked this conversation as resolved.
Show resolved Hide resolved
logger.warning(
f"GroupChat is underpopulated with {n_agents} agents. Direct communication would be more efficient."
)

if self.func_call_filter and self.messages and "function_call" in self.messages[-1]:
# find agents with the right function_map which contains the function name
agents = [
Expand All @@ -79,14 +105,40 @@ def select_speaker(self, last_speaker: Agent, selector: ConversableAgent):
f"No agent can execute the function {self.messages[-1]['name']}. "
"Please check the function_map of the agents."
)

# remove the last speaker from the list to avoid selecting the same speaker if allow_repeat_speaker is False
agents = agents if self.allow_repeat_speaker else [agent for agent in agents if agent != last_speaker]

if self.speaker_selection_method == "manual":
print("Please select the next speaker from the following list:")
_n_agents = len(agents)
for i in range(_n_agents):
print(f"{i+1}: {agents[i].name}")
try_count = 0
while try_count <= 3:
thinkall marked this conversation as resolved.
Show resolved Hide resolved
try_count += 1
if try_count >= 3:
print(f"You have tried {try_count} times. The next speaker will be selected automatically.")
break
try:
i = input("Enter the number of the next speaker (enter nothing or `q` to use auto selection): ")
if i == "" or i == "q":
break
i = int(i)
if i > 0 and i <= _n_agents:
return agents[i - 1]
else:
raise ValueError
except ValueError:
print(f"Invalid input. Please enter a number between 1 and {_n_agents}.")
thinkall marked this conversation as resolved.
Show resolved Hide resolved
elif self.speaker_selection_method == "round_robin":
return self.next_agent(last_speaker, agents)
elif self.speaker_selection_method == "random":
return random.choice(agents)
else:
thinkall marked this conversation as resolved.
Show resolved Hide resolved
agents = self.agents
# Warn if GroupChat is underpopulated
n_agents = len(agents)
if n_agents < 3:
logger.warning(
f"GroupChat is underpopulated with {n_agents} agents. Direct communication would be more efficient."
)
pass
thinkall marked this conversation as resolved.
Show resolved Hide resolved
afourney marked this conversation as resolved.
Show resolved Hide resolved

# auto speaker selection
selector.update_system_message(self.select_speaker_msg(agents))
final, name = selector.generate_oai_reply(
self.messages
Expand All @@ -98,7 +150,7 @@ def select_speaker(self, last_speaker: Agent, selector: ConversableAgent):
]
)
if not final:
# i = self._random.randint(0, len(self._agent_names) - 1) # randomly pick an id
# the LLM client is None, thus no reply is generated. Use round robin instead.
return self.next_agent(last_speaker, agents)
try:
return self.agent_by_name(name)
Expand Down
Loading
Loading