3
3
import re
4
4
import sys
5
5
from dataclasses import dataclass
6
- from typing import Dict , List , Optional , Union
6
+ from typing import Dict , List , Optional , Union , Tuple
7
7
8
8
from ..code_utils import content_str
9
9
from .agent import Agent
@@ -118,8 +118,7 @@ def manual_select_speaker(self, agents: List[Agent]) -> Union[Agent, None]:
118
118
print (f"Invalid input. Please enter a number between 1 and { _n_agents } ." )
119
119
return None
120
120
121
- def select_speaker (self , last_speaker : Agent , selector : ConversableAgent ):
122
- """Select the next speaker."""
121
+ def _prepare_and_select_agents (self , last_speaker : Agent ) -> Tuple [Optional [Agent ], List [Agent ]]:
123
122
if self .speaker_selection_method .lower () not in self ._VALID_SPEAKER_SELECTION_METHODS :
124
123
raise ValueError (
125
124
f"GroupChat speaker_selection_method is set to '{ self .speaker_selection_method } '. "
@@ -148,30 +147,35 @@ def select_speaker(self, last_speaker: Agent, selector: ConversableAgent):
148
147
]
149
148
if len (agents ) == 1 :
150
149
# only one agent can execute the function
151
- return agents [0 ]
150
+ return agents [0 ], agents
152
151
elif not agents :
153
152
# find all the agents with function_map
154
153
agents = [agent for agent in self .agents if agent .function_map ]
155
154
if len (agents ) == 1 :
156
- return agents [0 ]
155
+ return agents [0 ], agents
157
156
elif not agents :
158
157
raise ValueError (
159
158
f"No agent can execute the function { self .messages [- 1 ]['name' ]} . "
160
159
"Please check the function_map of the agents."
161
160
)
162
-
163
161
# remove the last speaker from the list to avoid selecting the same speaker if allow_repeat_speaker is False
164
162
agents = agents if self .allow_repeat_speaker else [agent for agent in agents if agent != last_speaker ]
165
163
166
164
if self .speaker_selection_method .lower () == "manual" :
167
165
selected_agent = self .manual_select_speaker (agents )
168
- if selected_agent :
169
- return selected_agent
170
166
elif self .speaker_selection_method .lower () == "round_robin" :
171
- return self .next_agent (last_speaker , agents )
167
+ selected_agent = self .next_agent (last_speaker , agents )
172
168
elif self .speaker_selection_method .lower () == "random" :
173
- return random .choice (agents )
169
+ selected_agent = random .choice (agents )
170
+ else :
171
+ selected_agent = None
172
+ return selected_agent , agents
174
173
174
+ def select_speaker (self , last_speaker : Agent , selector : ConversableAgent ):
175
+ """Select the next speaker."""
176
+ selected_agent , agents = self ._prepare_and_select_agents (last_speaker )
177
+ if selected_agent :
178
+ return selected_agent
175
179
# auto speaker selection
176
180
selector .update_system_message (self .select_speaker_msg (agents ))
177
181
context = self .messages + [{"role" : "system" , "content" : self .select_speaker_prompt (agents )}]
@@ -196,6 +200,41 @@ def select_speaker(self, last_speaker: Agent, selector: ConversableAgent):
196
200
except ValueError :
197
201
return self .next_agent (last_speaker , agents )
198
202
203
+ async def a_select_speaker (self , last_speaker : Agent , selector : ConversableAgent ):
204
+ """Select the next speaker."""
205
+ selected_agent , agents = self ._prepare_and_select_agents (last_speaker )
206
+ if selected_agent :
207
+ return selected_agent
208
+ # auto speaker selection
209
+ selector .update_system_message (self .select_speaker_msg (agents ))
210
+ final , name = await selector .a_generate_oai_reply (
211
+ self .messages
212
+ + [
213
+ {
214
+ "role" : "system" ,
215
+ "content" : f"Read the above conversation. Then select the next role from { [agent .name for agent in agents ]} to play. Only return the role." ,
216
+ }
217
+ ]
218
+ )
219
+ if not final :
220
+ # the LLM client is None, thus no reply is generated. Use round robin instead.
221
+ return self .next_agent (last_speaker , agents )
222
+
223
+ # If exactly one agent is mentioned, use it. Otherwise, leave the OAI response unmodified
224
+ mentions = self ._mentioned_agents (name , agents )
225
+ if len (mentions ) == 1 :
226
+ name = next (iter (mentions ))
227
+ else :
228
+ logger .warning (
229
+ f"GroupChat select_speaker failed to resolve the next speaker's name. This is because the speaker selection OAI call returned:\n { name } "
230
+ )
231
+
232
+ # Return the result
233
+ try :
234
+ return self .agent_by_name (name )
235
+ except ValueError :
236
+ return self .next_agent (last_speaker , agents )
237
+
199
238
def _participant_roles (self , agents : List [Agent ] = None ) -> str :
200
239
# Default to all agents registered
201
240
if agents is None :
@@ -342,7 +381,7 @@ async def a_run_chat(
342
381
break
343
382
try :
344
383
# select the next speaker
345
- speaker = groupchat .select_speaker (speaker , self )
384
+ speaker = await groupchat .a_select_speaker (speaker , self )
346
385
# let the speaker speak
347
386
reply = await speaker .a_generate_reply (sender = self )
348
387
except KeyboardInterrupt :
0 commit comments