AutoGen学习笔记系列(九)Advanced - Selector Group Chat
这篇文章瞄的是AutoGen官方教学文档 Advanced 章节中的 Selector Group Chat 篇章,介绍了SelectorGroupChat对象如何从一个Team中选择其中一个Agent与LLM进行对话,并且在得到结果后进行二次规划,同时你也可以自定义选择函数。本质上还是对Team的流程控制。
- 官网链接:https://microsoft.github.io/autogen/stable/user-guide/agentchat-user-guide/selector-group-chat.html# ;
Selector Group Chat
官方展示了一个名为 SelectorGroupChat 的对象,是一个Team对象也就是由多个Agent组成的对象,和我们之前使用的 RoundRobinGroupChat 是同一类型。它的作用在于内部的每一个Agent都会轮流向其他Agent进行广播消息,然后由LLM根据整个Team的上下文环境选择与这个Team中的哪一个Agent进行对话。
SelectorGroupChat 对象的关键特性有以下几点:
- 依靠LLM选择合适的Agent;
- 可以配置参与对象于描述;
- 防止同一个Agent持续性对话(可选);
- 可自定义的prompt;
- 可自定义选择函数
selection function,即你也可以不让LLM进行选择而是根据你的选择函数给LLM一个Agent进行对话;
相当于之前使用的RoundRobinGroupChat是内部Agent自发向LLM进行对话;而SelectorGroupChat是将整个Team的上下文发给LLM,然后让LLM或者你自定义的选择函数使用其中一个Agent与LLM对话。
How Does it Work?
SelectorGroupChat之所以能够实现上面提到的选择功能是依靠在 run() 或者 run_stream() 函数中按照下面的步骤执行:
- Team分析当前对话的上下文,包括历史记录、每一个Agent的
name和description,以此为依据选择下一个与LLM对话的Agent;默认情况下不会选择上一次与LLM对话的Agent,尽量避免只有一个Agent持续与LLM进行对话,除非这个Team中只有一个Agent,但也可以通过参数allow_repeated_speaker=True的方式允许Agent持续与LLM对话;你也可以通过自定义的选择函数来筛选下一次要和LLM对话的Agent; - 被选中的Agent会将自己的prompt和LLM的response都广播给整个Team中的所有其他Agent;
- 只有当终止条件被触发时间才会终止Team,否则整个Team会持续运行下去;
- 当对话结束时会返回一个
TaskResult类型,其中包含了所有的聊天记录;
和RoundRobinGroupChat用法一样,一旦任务结束后Team仍然会保留完整的上下文以便你进行二次激活,并且可以使用 reset() 函数清空上下文。
Example: Web Search/Analysis
官网在这里给出了一个使用 SelectorGroupChat 进行Web内容搜索和数据分析的任务,整个Team的结构如下,设计了三个内部Agent:

- Planning Agent:将一个复杂任务拆解成简单任务并决策由哪个Agent执行,相当于上面提到的选择函数,只不过这个Agent用了LLM进行选择;
- Web Search Agent:网络内容搜索Agent使用
search_web_tool工具进行搜索; - Data Analyst Agent:数据分析Agent使用
percentage_change_tool工具进行计算;
上面提到的两个 search_web_tool 和 percentage_change_tool 定义如下:
# Note: This example uses mock tools instead of real APIs for demonstration purposes
def search_web_tool(query: str) -> str:if "2006-2007" in query:return """Here are the total points scored by Miami Heat players in the 2006-2007 season:Udonis Haslem: 844 pointsDwayne Wade: 1397 pointsJames Posey: 550 points..."""elif "2007-2008" in query:return "The number of total rebounds for Dwayne Wade in the Miami Heat season 2007-2008 is 214."elif "2008-2009" in query:return "The number of total rebounds for Dwayne Wade in the Miami Heat season 2008-2009 is 398."return "No data found."def percentage_change_tool(start: float, end: float) -> float:return ((end - start) / start) * 100
然后就是用 AssistantAgent 来定义上面三个Agent,这里官方提示在定义时最重要的是些明白Agent的 name 和 description,因为这两个信息会变成LLM选择下一个与其对话的依据。
- 定义一个基于
gpt-4o的模型,后面三个Agent都要用这个模型接口:
model_client = OpenAIChatCompletionClient(model="gpt-4o")
- Planning Agent 任务拆解Agent(在这里就是选择对话的Agent):
planning_agent = AssistantAgent("PlanningAgent",description="An agent for planning tasks, this agent should be the first to engage when given a new task.",model_client=model_client,system_message="""You are a planning agent.Your job is to break down complex tasks into smaller, manageable subtasks.Your team members are:WebSearchAgent: Searches for informationDataAnalystAgent: Performs calculationsYou only plan and delegate tasks - you do not execute them yourself.When assigning tasks, use this format:1. <agent> : <task>After all tasks are complete, summarize the findings and end with "TERMINATE".""",
)
- Web Search Agent 内容搜索Agent,调用
search_web_tool工具进行搜索:
web_search_agent = AssistantAgent("WebSearchAgent",description="An agent for searching information on the web.",tools=[search_web_tool],model_client=model_client,system_message="""You are a web search agent.Your only tool is search_tool - use it to find information.You make only one search call at a time.Once you have the results, you never do calculations based on them.""",
)
- Data Analyst Agen 数据分析Agent,调用工具
percentage_change_tool对内容进行分析:
data_analyst_agent = AssistantAgent("DataAnalystAgent",description="An agent for performing calculations.",model_client=model_client,tools=[percentage_change_tool],system_message="""You are a data analyst.Given the tasks you have been assigned, you should analyze the data and provide results using the tools provided.If you have not seen the data, ask for it.""",
)
【Note】:如果你的工具函数返回的不是自然语言格式的字符串,可以在定义Agent的时候使用 reflect_on_tool_use=True 参数让Agent帮你将字符串整理成自然语言,本质还是调用LLM。因为Team内部广播或者沟通的基本单元仍然是一个封装好自然语言的Message。
Workflow
根据官网描述,上面定义的Team运行流程如下:
SelectorGroupChat首先接受到一个Task任务,然后根据Agent的属性name与descriptions信息 自主选择 最适合的一个Agent来启动整个任务,通常情况是 Planning Agent;- Planning Agent将这个Task拆分成子任务,然后按照
<Agent>:<task>的格式分发给对应的Agent; - 根据整个Team中的上线文环境、各个Agent的
descriptions,SelectorGroupChat动态选择下一个与LLM进行对话的Agent; - Web Search Agent执行一次搜索动作,并将LLM返回的结果保存在共享的记录中;
- 如果Data Analyst Agent被选中,那么就使用tools来处理数据;
- 整个Team的终止条件是如果子任务中检测到
TERMINATE或者其他终止条件;
【注意】:在自定义Agent的时候,尽量将descriptions写成 精炼、完备、排他,因为SelectorGroupChat 会根据Team内的所有Agent的描述进行决策下一个与LLM对话的是哪个Agent;
Termination Conditions
官方在这里定义了两个终止条件TextMentionTermination和MaxMessageTermination,这两个终止条件我们在前面已经用了很多次了,分别是文本关键字终止和最大组内沟通信息条数终止;
text_mention_termination = TextMentionTermination("TERMINATE")
max_messages_termination = MaxMessageTermination(max_messages=25)
termination = text_mention_termination | max_messages_termination
Selector Prompt
SelectorGroupChat 基于组内的上下文环境来选择下一个与LLM对话的Agent,因此这里我们自己写一个prompt来告诉SelectorGroupChat 选择Agent的依据是什么:
selector_prompt = """Select an agent to perform task.{roles}Current conversation context:
{history}Read the above conversation, then select an agent from {participants} to perform the next task.
Make sure the planner agent has assigned tasks before other agents start working.
Only select one agent.
"""
官网在如何设置这个prompt时给了以下几个Tips:
- 这个提示词不要写的太长,防止选择器过载;
- 如何判断自己提示词是不是过长了,这个是根据LLM模型规模决定的,如果你使用的模型是GPT-4o的话就可以写稍微长一点,但模型规模较小时就不能太长,官方提供的上面demo就是对于小模型设计的;
- 如果你对每一个Agent都写了多个条件,那么其实最适合的是使用自定义选择函数,由
SelectorGroupChat自主选择的初衷是减少你的工作量;
Running the Team
然后将上面我们提到的Agent、终止条件、自定义选择prompt结合起来形成一个Team:
team = SelectorGroupChat([planning_agent, web_search_agent, data_analyst_agent],model_client=model_client,termination_condition=termination,selector_prompt=selector_prompt,allow_repeated_speaker=True, # Allow an agent to speak multiple turns in a row.
)
然后再定义一个传给Team的任务:
task = "Who was the Miami Heat player with the highest points in the 2006-2007 season, and what was the percentage change in his total rebounds between the 2007-2008 and 2008-2009 seasons?"
那么完整代码如下:
from autogen_agentchat.agents import AssistantAgent
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_agentchat.conditions import TextMentionTermination, MaxMessageTermination
from autogen_agentchat.teams import SelectorGroupChat
from autogen_agentchat.ui import Consoleimport asyncio, osos.environ["OPENAI_API_KEY"] = "你的OpenAI API Key"#-----------------------------------------------------------------------------#
# Part1. 定义两个搜索工具
def search_web_tool(query: str) -> str:if "2006-2007" in query:return """Here are the total points scored by Miami Heat players in the 2006-2007 season:Udonis Haslem: 844 pointsDwayne Wade: 1397 pointsJames Posey: 550 points..."""elif "2007-2008" in query:return "The number of total rebounds for Dwayne Wade in the Miami Heat season 2007-2008 is 214."elif "2008-2009" in query:return "The number of total rebounds for Dwayne Wade in the Miami Heat season 2008-2009 is 398."return "No data found."def percentage_change_tool(start: float, end: float) -> float:return ((end - start) / start) * 100#-----------------------------------------------------------------------------#
# Part2. 定义三个Agent和model
model_client = OpenAIChatCompletionClient(model="gpt-4o")planning_agent = AssistantAgent("PlanningAgent",description="An agent for planning tasks, this agent should be the first to engage when given a new task.",model_client=model_client,system_message="""You are a planning agent.Your job is to break down complex tasks into smaller, manageable subtasks.Your team members are:WebSearchAgent: Searches for informationDataAnalystAgent: Performs calculationsYou only plan and delegate tasks - you do not execute them yourself.When assigning tasks, use this format:1. <agent> : <task>After all tasks are complete, summarize the findings and end with "TERMINATE".""",
)web_search_agent = AssistantAgent("WebSearchAgent",description="An agent for searching information on the web.",tools=[search_web_tool],model_client=model_client,system_message="""You are a web search agent.Your only tool is search_tool - use it to find information.You make only one search call at a time.Once you have the results, you never do calculations based on them.""",
)data_analyst_agent = AssistantAgent("DataAnalystAgent",description="An agent for performing calculations.",model_client=model_client,tools=[percentage_change_tool],system_message="""You are a data analyst.Given the tasks you have been assigned, you should analyze the data and provide results using the tools provided.If you have not seen the data, ask for it.""",
)#-----------------------------------------------------------------------------#
# Part3. 定义Team的终止条件
text_mention_termination = TextMentionTermination("TERMINATE")
max_messages_termination = MaxMessageTermination(max_messages=25)
termination = text_mention_termination | max_messages_terminationselector_prompt = """Select an agent to perform task.{roles}Current conversation context:
{history}Read the above conversation, then select an agent from {participants} to perform the next task.
Make sure the planner agent has assigned tasks before other agents start working.
Only select one agent.
"""#-----------------------------------------------------------------------------#
# Part4. 定义任务Task
task = "Who was the Miami Heat player with the highest points in the 2006-2007 season, and what was the percentage change in his total rebounds between the 2007-2008 and 2008-2009 seasons?"#-----------------------------------------------------------------------------#
# Part5. 将Agent、model、终止条件、prompt组合成一个team
team = SelectorGroupChat([planning_agent, web_search_agent, data_analyst_agent],model_client=model_client,termination_condition=termination,selector_prompt=selector_prompt,allow_repeated_speaker=True, # Allow an agent to speak multiple turns in a row.
)#-----------------------------------------------------------------------------#
# Part6. 运行team
asyncio.run(Console(team.run_stream(task=task))
)
运行结果如下,从输出内容来看除了实际执行的部分,其他都是Team内部上下文同步的过程,感兴趣的可以自己运行看看他们的同步逻辑:
$ python demo.py

Custom Selector Function
上面提到了你也可以自定义选择函数,但如果你自定义的选择函数返回的是 None 对象那么 SelectorGroupChat 仍然会使用基于LLM模型的Agent选择。
这里官方demo中自定义选择函数非常简单,当组内最新的消息不是由PlanningAgent生成时,就直接调用PlanningAgent,否则让LLM来选择,实际上就是每执行一步都让PlanningAgent重新规划一下:
def selector_func(messages: Sequence[AgentEvent | ChatMessage]) -> str | None:if messages[-1].source != planning_agent.name:return planning_agent.namereturn None
然后需要在定义Team的时候就将选择函数设置进去:
team = SelectorGroupChat([planning_agent, web_search_agent, data_analyst_agent],model_client=model_client,termination_condition=termination,selector_prompt=selector_prompt,allow_repeated_speaker=True,selector_func=selector_func,
)
完成代码如下:
from autogen_agentchat.agents import AssistantAgent
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_agentchat.conditions import TextMentionTermination, MaxMessageTermination
from autogen_agentchat.teams import SelectorGroupChat
from autogen_agentchat.ui import Console
from autogen_agentchat.messages import ChatMessage, AgentEvent
from typing import Sequenceimport asyncio, osos.environ["OPENAI_API_KEY"] = "你的OpenAI API Key"def search_web_tool(query: str) -> str:if "2006-2007" in query:return """Here are the total points scored by Miami Heat players in the 2006-2007 season:Udonis Haslem: 844 pointsDwayne Wade: 1397 pointsJames Posey: 550 points..."""elif "2007-2008" in query:return "The number of total rebounds for Dwayne Wade in the Miami Heat season 2007-2008 is 214."elif "2008-2009" in query:return "The number of total rebounds for Dwayne Wade in the Miami Heat season 2008-2009 is 398."return "No data found."def percentage_change_tool(start: float, end: float) -> float:return ((end - start) / start) * 100model_client = OpenAIChatCompletionClient(model="gpt-4o")planning_agent = AssistantAgent("PlanningAgent",description="An agent for planning tasks, this agent should be the first to engage when given a new task.",model_client=model_client,system_message="""You are a planning agent.Your job is to break down complex tasks into smaller, manageable subtasks.Your team members are:WebSearchAgent: Searches for informationDataAnalystAgent: Performs calculationsYou only plan and delegate tasks - you do not execute them yourself.When assigning tasks, use this format:1. <agent> : <task>After all tasks are complete, summarize the findings and end with "TERMINATE".""",
)web_search_agent = AssistantAgent("WebSearchAgent",description="An agent for searching information on the web.",tools=[search_web_tool],model_client=model_client,system_message="""You are a web search agent.Your only tool is search_tool - use it to find information.You make only one search call at a time.Once you have the results, you never do calculations based on them.""",
)data_analyst_agent = AssistantAgent("DataAnalystAgent",description="An agent for performing calculations.",model_client=model_client,tools=[percentage_change_tool],system_message="""You are a data analyst.Given the tasks you have been assigned, you should analyze the data and provide results using the tools provided.If you have not seen the data, ask for it.""",
)text_mention_termination = TextMentionTermination("TERMINATE")
max_messages_termination = MaxMessageTermination(max_messages=25)
termination = text_mention_termination | max_messages_terminationselector_prompt = """Select an agent to perform task.{roles}Current conversation context:
{history}Read the above conversation, then select an agent from {participants} to perform the next task.
Make sure the planner agent has assigned tasks before other agents start working.
Only select one agent.
"""task = "Who was the Miami Heat player with the highest points in the 2006-2007 season, and what was the percentage change in his total rebounds between the 2007-2008 and 2008-2009 seasons?"# 上面部分完全一致
#-----------------------------------------------------------------------------#
# Part1. 定义选择函数
def selector_func(messages: Sequence[AgentEvent | ChatMessage]) -> str | None:if messages[-1].source != planning_agent.name:return planning_agent.namereturn None# Part2. 设置team使用自己的选择函数
team = SelectorGroupChat([planning_agent, web_search_agent, data_analyst_agent],model_client=model_client,termination_condition=termination,selector_prompt=selector_prompt,allow_repeated_speaker=True,selector_func=selector_func,
)# Part3. 运行team
asyncio.run(Console(team.run_stream(task=task))
)
运行结果如下:
$ python demo.py

User Feedback
在之前的文章 AutoGen学习笔记系列(五)Tutorial -Human-in-the-Loop 中提到了 “人在回路” 策略,让人在Team走向的 关键节点 上让人来决策。在这里我们同样可以使用 UserProxyAgent 将人在回路策略引入 SelectorGroupChat 中:
首先定义 UserProxyAgent 和选择函数,在选择函数中使用 Agent 以实现人在回路,这里的逻辑如下:
- 首先第一次使用 PlanningAgent 激活整个Team的Task;
- PlanningAgent通过LLM得到下一个想要执行的Agent名;
- 由人来确认是否使用这个Agent,允许就输入
APPROVE,否则会打回给LLM重新选择一个再来确认;
# 定义 UserProxyAgent
user_proxy_agent = UserProxyAgent("UserProxyAgent", description="A proxy for the user to approve or disapprove tasks.")# 定义使用 UserProxyAgent 的选择函数
def selector_func_with_user_proxy(messages: Sequence[AgentEvent | ChatMessage]) -> str | None:if messages[-1].source != planning_agent.name and messages[-1].source != user_proxy_agent.name:# 必须让PlanningAgent作为第一个被调用的,否则任务无法启动return planning_agent.nameif messages[-1].source == planning_agent.name:if messages[-2].source == user_proxy_agent.name and "APPROVE" in messages[-1].content.upper(): # type: ignore# 如果检测到了人输入的 APPROVE 则确认下一个Agent是被被使用return Nonereturn user_proxy_agent.nameif messages[-1].source == user_proxy_agent.name:# 如果人输入的不是 APPROVE 则让 PlanningAgent重新选择if "APPROVE" not in messages[-1].content.upper(): # type: ignorereturn planning_agent.namereturn None
完整代码如下:
from autogen_agentchat.agents import AssistantAgent, UserProxyAgent
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_agentchat.conditions import TextMentionTermination, MaxMessageTermination
from autogen_agentchat.teams import SelectorGroupChat
from autogen_agentchat.ui import Console
from autogen_agentchat.messages import ChatMessage, AgentEvent
from typing import Sequenceimport asyncio, osos.environ["OPENAI_API_KEY"] = "你的OpenAI API Key"def search_web_tool(query: str) -> str:if "2006-2007" in query:return """Here are the total points scored by Miami Heat players in the 2006-2007 season:Udonis Haslem: 844 pointsDwayne Wade: 1397 pointsJames Posey: 550 points..."""elif "2007-2008" in query:return "The number of total rebounds for Dwayne Wade in the Miami Heat season 2007-2008 is 214."elif "2008-2009" in query:return "The number of total rebounds for Dwayne Wade in the Miami Heat season 2008-2009 is 398."return "No data found."def percentage_change_tool(start: float, end: float) -> float:return ((end - start) / start) * 100model_client = OpenAIChatCompletionClient(model="gpt-4o")planning_agent = AssistantAgent("PlanningAgent",description="An agent for planning tasks, this agent should be the first to engage when given a new task.",model_client=model_client,system_message="""You are a planning agent.Your job is to break down complex tasks into smaller, manageable subtasks.Your team members are:WebSearchAgent: Searches for informationDataAnalystAgent: Performs calculationsYou only plan and delegate tasks - you do not execute them yourself.When assigning tasks, use this format:1. <agent> : <task>After all tasks are complete, summarize the findings and end with "TERMINATE".""",
)web_search_agent = AssistantAgent("WebSearchAgent",description="An agent for searching information on the web.",tools=[search_web_tool],model_client=model_client,system_message="""You are a web search agent.Your only tool is search_tool - use it to find information.You make only one search call at a time.Once you have the results, you never do calculations based on them.""",
)data_analyst_agent = AssistantAgent("DataAnalystAgent",description="An agent for performing calculations.",model_client=model_client,tools=[percentage_change_tool],system_message="""You are a data analyst.Given the tasks you have been assigned, you should analyze the data and provide results using the tools provided.If you have not seen the data, ask for it.""",
)text_mention_termination = TextMentionTermination("TERMINATE")
max_messages_termination = MaxMessageTermination(max_messages=25)
termination = text_mention_termination | max_messages_terminationselector_prompt = """Select an agent to perform task.{roles}Current conversation context:
{history}Read the above conversation, then select an agent from {participants} to perform the next task.
Make sure the planner agent has assigned tasks before other agents start working.
Only select one agent.
"""task = "Who was the Miami Heat player with the highest points in the 2006-2007 season, and what was the percentage change in his total rebounds between the 2007-2008 and 2008-2009 seasons?"# 上面部分完全一致
#-----------------------------------------------------------------------------#
# Part1. 定义 UserProxyAgent
user_proxy_agent = UserProxyAgent("UserProxyAgent", description="A proxy for the user to approve or disapprove tasks.")# Part2. 定义使用 UserProxyAgent 的选择函数
def selector_func_with_user_proxy(messages: Sequence[AgentEvent | ChatMessage]) -> str | None:if messages[-1].source != planning_agent.name and messages[-1].source != user_proxy_agent.name:return planning_agent.nameif messages[-1].source == planning_agent.name:if messages[-2].source == user_proxy_agent.name and "APPROVE" in messages[-1].content.upper(): # type: ignorereturn Nonereturn user_proxy_agent.nameif messages[-1].source == user_proxy_agent.name:if "APPROVE" not in messages[-1].content.upper(): # type: ignorereturn planning_agent.namereturn None# Part2. 设置team使用自己的选择函数
team = SelectorGroupChat([planning_agent, web_search_agent, data_analyst_agent, user_proxy_agent],model_client=model_client,termination_condition=termination,selector_prompt=selector_prompt,selector_func=selector_func_with_user_proxy,allow_repeated_speaker=True,
)# Part3. 运行team
asyncio.run(Console(team.run_stream(task=task))
)
运行结果如下,可以发现每到选择Agent的时候都会等待人进行决策:
$ python demo.py

Using Reasoning Models
上面所有的demo都是基于 gpt-4o 或 Gemini 这种满血大模型,根据上面小节 Selector Prompt 提到的几个 tips 内容,对于像 o3-mini 这种小模型而言还是要尽可能写短描述选择的prompt,而是让模型自行决策,这样可以减小模型本身的压力。官方在下面的示例中使用 o3-mini 作为模型:
from autogen_agentchat.agents import AssistantAgent, UserProxyAgent
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_agentchat.conditions import TextMentionTermination, MaxMessageTermination
from autogen_agentchat.teams import SelectorGroupChat
from autogen_agentchat.ui import Console
from autogen_agentchat.messages import ChatMessage, AgentEvent
from typing import Sequenceimport asyncio, osos.environ["OPENAI_API_KEY"] = "你的OpenAI API Key"def search_web_tool(query: str) -> str:if "2006-2007" in query:return """Here are the total points scored by Miami Heat players in the 2006-2007 season:Udonis Haslem: 844 pointsDwayne Wade: 1397 pointsJames Posey: 550 points..."""elif "2007-2008" in query:return "The number of total rebounds for Dwayne Wade in the Miami Heat season 2007-2008 is 214."elif "2008-2009" in query:return "The number of total rebounds for Dwayne Wade in the Miami Heat season 2008-2009 is 398."return "No data found."def percentage_change_tool(start: float, end: float) -> float:return ((end - start) / start) * 100text_mention_termination = TextMentionTermination("TERMINATE")
max_messages_termination = MaxMessageTermination(max_messages=25)
termination = text_mention_termination | max_messages_terminationtask = "Who was the Miami Heat player with the highest points in the 2006-2007 season, and what was the percentage change in his total rebounds between the 2007-2008 and 2008-2009 seasons?"# 上面部分完全一致
#-----------------------------------------------------------------------------#
model_client = OpenAIChatCompletionClient(model="o3-mini")web_search_agent = AssistantAgent("WebSearchAgent",description="An agent for searching information on the web.",tools=[search_web_tool],model_client=model_client,system_message="""Use web search tool to find information.""",
)data_analyst_agent = AssistantAgent("DataAnalystAgent",description="An agent for performing calculations.",model_client=model_client,tools=[percentage_change_tool],system_message="""Use tool to perform calculation. If you have not seen the data, ask for it.""",
)user_proxy_agent = UserProxyAgent("UserProxyAgent",description="A user to approve or disapprove tasks.",
)selector_prompt = """Select an agent to perform task.
{roles}Current conversation context:
{history}Read the above conversation, then select an agent from {participants} to perform the next task.
When the task is complete, let the user approve or disapprove the task.
"""team = SelectorGroupChat([web_search_agent, data_analyst_agent, user_proxy_agent],model_client=model_client,termination_condition=termination, # Use the same termination condition as before.selector_prompt=selector_prompt,allow_repeated_speaker=True,
)# Part3. 运行team
asyncio.run(Console(team.run_stream(task=task))
)
运行结果如下,如果你运行的话会发现这个过程慢了不少,而且很容易出现一个Agent不停被循环调用的情况,大小模型之间的差异还是很明显的:
$ python demo.py

相关文章:
AutoGen学习笔记系列(九)Advanced - Selector Group Chat
这篇文章瞄的是AutoGen官方教学文档 Advanced 章节中的 Selector Group Chat 篇章,介绍了SelectorGroupChat对象如何从一个Team中选择其中一个Agent与LLM进行对话,并且在得到结果后进行二次规划,同时你也可以自定义选择函数。本质上还是对Tea…...
Stream特性(踩坑):惰性执行、不修改原始数据源
在日常开发中,Stream API 提供了一种高效且易于使用的工具集来处理集合数据。 本文主要讲解 Stream 的两个特性:惰性执行,不修改原始数据源。 为什么说这两个、而不讲下其他的特性呢?主要是因为在开发中如果忽略这两个特性的话&…...
springcloud sentinel教程
QPS(Queries Per Second)即每秒查询率 TPS,每秒处理的事务数目 PV(page view)即页面浏览量 UV 访问数(Unique Visitor)指独立访客访问数 一、初识Sentinel 什么是雪崩问题? 微服务之间相…...
像素的一生 Life of a Pixel - Steve Kobes 2020版
像素的一生 Life of a Pixel - Steve Kobes 2020版 《Life of a Pixel》 作者是Google大佬 Steve Kobes 2020年 介绍Chromium内核完整渲染流程的视频,介绍的非常好,想要学习了解chromium内核渲染必看! 油管视频地址为:https://w…...
系统部署【信创名录】及其查询地址
一、信创类型 (一)服务器: 1.华为云 2.腾讯云 3.阿里云 (二)中央处理器(CPU): 1.海思,鲲鹏920服务器 (三)中间件 1.人大金仓 ࿰…...
VSCode 配置优化指南:打造高效的 uni-app、Vue2/3、JS/TS 开发环境
VSCode 配置优化指南,适用于 uni-app、Vue2、Vue3、JavaScript、TypeScript 开发,包括插件推荐、设置优化、代码片段、调试配置等,确保你的开发体验更加流畅高效。 1. 安装 VSCode 如果你还未安装 VSCode,可前往 VSCode 官网 下载最新版并安装。 2. 安装推荐插件 (1) Vue…...
C++中的析构函数
目录 一、什么是析构函数: 二、析构函数的特性: 一、什么是析构函数: C中的析构函数非常简单,它的功能无非是帮助我们自动归还堆区的空间给操作系统。当我们使用内存开辟函数(如malloc()、realloc())等&a…...
同步,异步,并发,并行
同步: 任务按顺序执行,必须等待前一个任务完成后才能开始下一个任务。 任务之间是强依赖的,通过直接调用或阻塞等待实现。 示例:读取文件时,代码会阻塞直到文件读取完成。 异步: 任务无需等待前一个任务完成即可启…...
种子填充(Floodfill、泛滥填充、洪水填充) 算法c++模板
种子填充(Floodfill) 算法: 从任意 W 开始,不停地把邻接的 W 用 . 代替。1 次 DFS 后与初始 W 连接的所有 W 都被替换成 . 了。 因此,直到图中不存在 W 为止,总共进行 DFS 的次数就是答案了。 问题: 有一个大小为 N x M 的园子,雨后积水。 8 连通的积水被认为是连接在…...
MATLAB控制函数测试要点剖析
一、功能准确性检验 基础功能核验 针对常用控制函数,像用于传递函数建模的 tf 、构建状态空间模型的 ss ,以及开展阶跃响应分析的 step 等,必须确认其能精准执行基础操作。以 tf 函数为例,在输入分子与分母系数后,理…...
【新手指南】pyqt可视化远程部署deepseek7B蒸馏版模型
本地效果:(如果想做这个的本科毕设,建议美化界面。) 总结:MobaXterm远程连接autodl服务器,在MobaXterm上利用X11转发使pyqt可视化页面在自己的电脑上展现出来。 1. 官网下载MobaXterm MobaXterm free Xse…...
大语言模型在患者交互任务中的临床使用评估框架
An evaluation framework for clinical use of large language models in patient interaction tasks An evaluation framework for clinical use of large language models in patient interaction tasks | Nature Medicine 2025.1 收到时间:2023 年 8 月 8 日 …...
DeepSeek-V3 技术报告解读
DeepSeek火了有一段时间了,春节假期因为没时间,所以关于deepseek大模型一系列的技术报告一直没看,新年开工后,抽一点时间把之前的坑补起来,关于DeepSeek-V3技术报告的解读已经有很多了,但我相信不同的人去读…...
suricata安装测试
系统版本为Ubuntu 22.04.4。 # cat /etc/issue Ubuntu 22.04.4 LTS \n \l # # uname -a Linux logging 6.8.0-49-generic #49~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Wed Nov 6 17:42:15 UTC 2 x86_64 x86_64 x86_64 GNU/Linux添加suricata的apt库。 # add-apt-repository pp…...
Java反射简单理解
Java反射是指在运行时(runtime)能够动态地获取类的内部信息,并能直接操作类的属性和方法的一种机制。通过反射,开发者可以在运行时检查类、接口、字段和方法,并且可以调用这些方法和访问这些字段,而无需在编…...
WPS Word中英文混杂空格和行间距不一致调整方案
文章目录 问题1:在两端对齐的情况下,如何删除参考文献(英文)的空格问题2:中英文混杂行间距不一致问题问题3:设置中文为固定字体,设置西文为固定字体参考 问题1:在两端对齐的情况下&a…...
探秘沃尔什-哈达玛变换(WHT)原理
沃尔什-哈达玛变换(WHT)起源 起源与命名(20世纪早期) 数学基础:该变换的理论基础由法国数学家雅克哈达玛(Jacques Hadamard)在1893年提出,其核心是哈达玛矩阵的构造。扩展与命名&…...
优雅拼接字符串:StringJoiner 的完整指南
在Java开发中,字符串拼接是高频操作。无论是日志格式化、构建CSV数据,还是生成动态SQL,开发者常需处理分隔符、前缀和后缀的组合。传统的StringBuilder虽然灵活,但代码冗余且易出错。Java 8推出的StringJoiner类,以简洁…...
AFL++安装
学习fuzzing也几天了,今天记录AFL的安装及使用 一、实验环境 虚拟机:ubuntu20.04 当然也可以uname -a去看自己的版本号 二、AFL安装 1.先更新一下工具 sudo apt update2.安装AFL必要的一些依赖,例如编译工具(如 build-essen…...
开发者社区测试报告(功能测试+性能测试)
功能测试 测试相关用例 开发者社区功能背景 在当今数字化时代,编程已经成为一项核心技能,越来越多的人开始学习编程,以适应快速变化的科技 环境。基于这一需求,我设计开发了一个类似博客的论坛系统,专注于方便程序员…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...
