当前位置: 首页 > news >正文

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() 函数中按照下面的步骤执行:

  1. Team分析当前对话的上下文,包括历史记录、每一个Agent的namedescription,以此为依据选择下一个与LLM对话的Agent;默认情况下不会选择上一次与LLM对话的Agent,尽量避免只有一个Agent持续与LLM进行对话,除非这个Team中只有一个Agent,但也可以通过参数 allow_repeated_speaker=True 的方式允许Agent持续与LLM对话;你也可以通过自定义的选择函数来筛选下一次要和LLM对话的Agent;
  2. 被选中的Agent会将自己的prompt和LLM的response都广播给整个Team中的所有其他Agent;
  3. 只有当终止条件被触发时间才会终止Team,否则整个Team会持续运行下去;
  4. 当对话结束时会返回一个 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_toolpercentage_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 points
        Dwayne Wade: 1397 points
        James 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的 namedescription,因为这两个信息会变成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 information
        DataAnalystAgent: Performs calculations

    You 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运行流程如下:

  1. SelectorGroupChat 首先接受到一个Task任务,然后根据Agent的属性namedescriptions信息 自主选择 最适合的一个Agent来启动整个任务,通常情况是 Planning Agent;
  2. Planning Agent将这个Task拆分成子任务,然后按照 <Agent>:<task> 的格式分发给对应的Agent;
  3. 根据整个Team中的上线文环境、各个Agent的descriptionsSelectorGroupChat 动态选择下一个与LLM进行对话的Agent;
  4. Web Search Agent执行一次搜索动作,并将LLM返回的结果保存在共享的记录中;
  5. 如果Data Analyst Agent被选中,那么就使用tools来处理数据;
  6. 整个Team的终止条件是如果子任务中检测到TERMINATE 或者其他终止条件;

【注意】:在自定义Agent的时候,尽量将descriptions写成 精炼完备排他,因为SelectorGroupChat 会根据Team内的所有Agent的描述进行决策下一个与LLM对话的是哪个Agent;


Termination Conditions

官方在这里定义了两个终止条件TextMentionTerminationMaxMessageTermination,这两个终止条件我们在前面已经用了很多次了,分别是文本关键字终止和最大组内沟通信息条数终止;

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:

  1. 这个提示词不要写的太长,防止选择器过载;
  2. 如何判断自己提示词是不是过长了,这个是根据LLM模型规模决定的,如果你使用的模型是GPT-4o的话就可以写稍微长一点,但模型规模较小时就不能太长,官方提供的上面demo就是对于小模型设计的;
  3. 如果你对每一个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 Console

import asyncio, os

os.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 points
        Dwayne Wade: 1397 points
        James 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 information
        DataAnalystAgent: Performs calculations

    You 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_termination

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.
"""

#-----------------------------------------------------------------------------#
# 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.name
    return 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 Sequence

import asyncio, os

os.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 points
        Dwayne Wade: 1397 points
        James 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

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 information
        DataAnalystAgent: Performs calculations

    You 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_termination

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.
"""

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.name
    return 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 以实现人在回路,这里的逻辑如下:

  1. 首先第一次使用 PlanningAgent 激活整个Team的Task;
  2. PlanningAgent通过LLM得到下一个想要执行的Agent名;
  3. 由人来确认是否使用这个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.name
    if 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 None
        return user_proxy_agent.name
    if messages[-1].source == user_proxy_agent.name:
        # 如果人输入的不是 APPROVE 则让 PlanningAgent重新选择
        if "APPROVE" not in messages[-1].content.upper():  # type: ignore
            return planning_agent.name
    return 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 Sequence

import asyncio, os

os.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 points
        Dwayne Wade: 1397 points
        James 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

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 information
        DataAnalystAgent: Performs calculations

    You 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_termination

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.
"""

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.name
    if messages[-1].source == planning_agent.name:
        if messages[-2].source == user_proxy_agent.name and "APPROVE" in messages[-1].content.upper():  # type: ignore
            return None
        return user_proxy_agent.name
    if messages[-1].source == user_proxy_agent.name:
        if "APPROVE" not in messages[-1].content.upper():  # type: ignore
            return planning_agent.name
    return 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-4oGemini 这种满血大模型,根据上面小节 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 Sequence

import asyncio, os

os.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 points
        Dwayne Wade: 1397 points
        James 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

text_mention_termination = TextMentionTermination("TERMINATE")
max_messages_termination = MaxMessageTermination(max_messages=25)
termination = text_mention_termination | max_messages_termination

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?"

# 上面部分完全一致
#-----------------------------------------------------------------------------#
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

在这里插入图片描述

相关文章:

  • PawSQL for MSSQL:PawSQL 支持 SQL Server 的SQL优化、SQL审核、性能巡检
  • 【redis】type命令和定时器的两种实现方式(优先级队列、时间轮)
  • elasticsearch是哪家的
  • 每天五分钟深度学习pytorch:基于Pytorch搭建ResNet模型的残差块
  • 分布式ETCD面试题及参考答案
  • 2025 年 AI 网络安全预测
  • 使用 Java 在后端 为 PDF 添加水印
  • 电脑中本地部署阉割版DeepSeek或其他大模型的方法
  • ES-分词器安装与使用详解
  • MWC 2025 | 移远通信推出AI智能无人零售解决方案,以“动态视觉+边缘计算”引领智能零售新潮流
  • Hive的架构
  • Python 相对路径写法
  • 掌握MiniQMT:程序化下单与撤单的高效实现
  • 【vLLM 教程】使用 TPU 安装
  • 《Natural Actor-Critic》译读笔记
  • DMR协议空中接口部分
  • Vulnhub-election靶机
  • shell编程——运算符和运算命令
  • 硬件基础(4):(1)AD采集电路设计
  • <论文>MiniCPM:利用可扩展训练策略揭示小型语言模型的潜力
  • 经济日报:将法律红利转化为民营经济发展动力
  • “千馆万员讲家风”活动举办,小讲解员登台讲述家风故事
  • 美官员鼓动他国“退出WHO”遭冷遇,鲁比奥辩称美国没“退群”
  • 浙江台州女厅官林虹被决定逮捕,曾因直播带货广受关注
  • 文化破冰,土耳其亚美尼亚合拍摄影大师阿拉·古勒传记片
  • 人民日报:不能层层加码,要层层负责