跳转至

AutoGen

AutoGen 的 Group Chat 与 Two-Agent 对话

image.png

🤖 1. AutoGen 的 Two‑Agent 对话和 Group Chat 各适用于什么场景?

AutoGen 的多智能体对话可以被抽象成两种拓扑:点对点的 Two‑Agent 对话 和 多对多的 Group Chat。前者像两个人之间的专业协作,后者像一个团队讨论会。

image.png

Two‑Agent 对话的适用场景

  • 代码生成与执行:一个 AssistantAgent 写代码,一个 UserProxyAgent 代表用户执行代码并反馈执行结果。这是 AutoGen 最经典的范式。

  • 角色扮演协作:例如“面试官”和“候选人”的模拟面试,或者“老师”和“学生”的问答辅导。

  • 条件明确的回合制任务:你清楚地知道只有两个角色参与,且它们之间的交互模式固定(A 提问 → B 回答 → A 追问)。

Group Chat 的适用场景

  • 多角色共同决策:产品设计评审,需要工程师、设计师、产品经理、测试同时发言并交换意见。

  • 复杂任务拆分与聚合:一个任务需要“研究员”检索资料、“分析师”解读数据、“写手”生成报告,它们之间需要多次来回讨论。

  • 专家会诊:多个不同领域的专家 Agent 共同诊断一个问题,例如“安全专家”+“性能专家”+“法规专家”一起审查一份架构方案。

选型速查:

  • 如果只需要一个助手+一个用户,且交互方式是“助手干活、用户反馈”,直接选 Two‑Agent。

  • 如果需要三个及以上不同角色,或者发言人顺序不能事先固定(需要根据讨论内容动态决定),就用 Group Chat + GroupChatManager。


⚙️ 2. AutoGen Group Chat 中,如何控制发言顺序和避免无限循环对话?

Group Chat 的发言由 GroupChatManager 控制,它内部通过一个 speaker_selection_method 来决定每一轮该谁说话。控制发言顺序和防止死循环,需要从发言规则、终止条件、消息约束三个层面设计。

① 控制发言顺序:指定发言选择策略

默认情况下,Manager 使用 auto 模式,让内部的 LLM 根据对话历史决定下一个发言人。你可以把它改为 round_robin(轮询),或提供一个自定义的选择函数。

from autogen import GroupChat, GroupChatManager

groupchat = GroupChat(
    agents=[agent_a, agent_b, agent_c],
    messages=[],
    max_round=10,
    speaker_selection_method="round_robin"  # 严格按 agents 列表顺序轮流发言
)

如果需要更精细的控制,可以传入一个自定义函数:

def custom_speaker_selection(last_speaker, groupchat):
    # 规则:B 发言后必须由 C 来总结,其他情况随机选 A
    if last_speaker.name == "Agent_B":
        return agent_c
    else:
        return agent_a

groupchat = GroupChat(
    agents=[agent_a, agent_b, agent_c],
    messages=[],
    speaker_selection_method=custom_speaker_selection,
    max_round=10
)

② 设置硬边界:max_round 和终止消息

  • max_round:限制整个群聊的发言轮次上限。到达上限后强制结束,这是最硬的兜底。

  • termination_msg:当某个 Agent 的消息中包含指定关键词(如 "TERMINATE")时,群聊自动终止。你可以在 System Prompt 中教导 Agent 在完成任务后输出该关键词。

agent_a = AssistantAgent(
    name="研究员",
    system_message="完成研究后,请在消息末尾说 'TERMINATE'。"
)

groupchat = GroupChat(
    agents=[...],
    messages=[],
    max_round=20,
    # 不设置 terminate_msg 则默认检查 'TERMINATE'
)

③ 约束发言内容:避免“同意、收到”型循环

LLM 容易陷入礼貌性互聊(“谢谢”、“收到”、“已理解”)。解决办法是在 System Message 中明确禁止无实质内容的发言,并要求每个发言都必须有决策或产出。

system_message = """
你必须只在你拥有新的信息或需要做出决策时才发言。
禁止只为了确认上一条消息而发言,例如不要说“收到”、“了解”。
如果不需要补充任何信息,请直接让给下一个角色,或输出 TERMINATE。
"""

④ 使用 custom_speaker_selection 实现“跳过多余发言”

你可以在选择函数中检查最后几条消息的内容,如果发现某个 Agent 已经连续发言多次且没有进展,就强制切换或直接结束。

def adaptive_selection(last_speaker, groupchat):
    # 如果最近 3 条消息都来自同一个 Agent,强制切换到另一个
    recent_speakers = [msg["name"] for msg in groupchat.messages[-3:]]
    if recent_speakers.count(last_speaker.name) == 3:
        # 找一个其他 Agent 来打破循环
        for agent in groupchat.agents:
            if agent != last_speaker:
                return agent
    # 否则让 LLM 决定
    return "auto"

通过这些手段的组合:轮次上限兜底、TERMINATE 关键词主动结束、发言内容约束、自适应选择函数,你可以把 Group Chat 牢牢控制在一个高效、有限的讨论范围内。


💻 3. AutoGen 中的 UserProxyAgent 和 AssistantAgent 有什么区别?UserProxyAgent 的 code_execution_config 是如何工作的?

3.1 两者的本质区别

查看内嵌表格

最简对比图示:

image.png

AssistantAgent 是系统的“大脑”,它用 LLM 来分析问题、生成代码、提出建议。

UserProxyAgent 是系统的“手脚”,它可以代表用户执行代码,把执行结果返回给 AssistantAgent 以便进一步修正。它还能代表用户直接发起对话或提供人工反馈。

3.2 code_execution_config 的工作原理

code_execution_config 是 UserProxyAgent 独有的配置项,它让 Agent 能够自动执行 AssistantAgent 生成的代码块。

from autogen import UserProxyAgent

user_proxy = UserProxyAgent(
    name="用户代理",
    human_input_mode="NEVER",  # 完全自动,不等待人工
    code_execution_config={
        "work_dir": "workspace",          # 代码执行的工作目录
        "use_docker": False,              # 是否用 Docker 隔离执行
        "timeout": 60,                    # 单次执行超时 (秒)
        "last_n_messages": 3,             # 检查最近多少条消息中的代码块
    }
)

执行流程:

  1. AssistantAgent 生成一条消息,其中包含代码块(标记为 \``python ... ````)。

  2. UserProxyAgent 收到消息后,自动提取代码块。

  3. UserProxyAgent 在 work_dir 下写入临时文件,通过命令行(如 python script.py)执行。

  4. 执行结果(stdout 和 stderr)被捕获,打包成一条新消息,返回给 AssistantAgent。

  5. AssistantAgent 看到执行结果后,如果报错则尝试修正代码,重新发给 UserProxyAgent 执行;如果成功则给出最终答案。

关键配置项说明:

  • use_docker:强烈建议生产环境设为 True,让代码在 Docker 容器中运行,避免恶意代码破坏宿主机。默认为 False 以便开发。

  • timeout:防止无限循环或长时间运行的代码拖死会话。

  • last_n_messages:控制提取代码块的范围。设置为 3 表示只在最近 3 条消息中找代码,避免重复执行旧代码。

  • work_dir:代码文件存放的目录,多个会话可以共享同一个工作目录以便复用文件。

人工介入模式 human_input_mode 的配合:

  • "NEVER":完全自动执行,适合纯自动化流程。

  • "TERMINATE":只有当 Assistant 发出 TERMINATE 信号时才请求人工确认。

  • "ALWAYS":每次需要执行代码或做出决策时都停下来等待人工输入,适合需要人类监督的敏感任务。

一个完整的自动代码执行示例:

from autogen import AssistantAgent, UserProxyAgent

assistant = AssistantAgent(
    name="数据科学家",
    llm_config={"config_list": [{"model": "gpt-4", "api_key": "..."}]},
    system_message="你是一个数据科学家,用 Python 完成任务。将代码放在 ```python ``` 中。"
)

user_proxy = UserProxyAgent(
    name="执行者",
    human_input_mode="NEVER",
    code_execution_config={
        "work_dir": "data_science_workspace",
        "use_docker": False,
        "timeout": 120,
    }
)

user_proxy.initiate_chat(
    assistant,
    message="请编写 Python 代码,读取 sales.csv 并计算每个地区的总销售额,最后输出结果。"
)

收束:

UserProxyAgent 相当于给 AssistantAgent 配了一位忠实的“执行秘书”,它不会自己思考,但能把助手写的代码一丝不苟地跑起来,并把输出原样汇报。这种“脑手分离”的架构是 AutoGen 高效解决实际问题的基础——助手只管想,执行只管做,出错一起改。


4、进阶题:AutoGen 的 Nested Chat(嵌套对话)是什么?它解决了什么问题?和普通 Group Chat 有什么区别?⭐⭐⭐

难度级别:⭐⭐⭐(复杂对话编排、模块化设计)

1️⃣ Common Answer

Nested Chat 就是在对话里面再嵌套一个对话,像函数调用一样。它解决了对话太复杂的问题,可以把一个大任务拆成小任务。和 Group Chat 的区别就是 Nested Chat 是嵌套的,Group Chat 是大家一起聊。

2️⃣ Impressive Answer

  1. Nested Chat 核心概念
  2. 定义:允许一个 Agent 在处理任务时启动一个独立的子对话(Sub-conversation),子对话完成后再将结果返回到主对话。类似函数调用,但对话式执行。
  3. 触发机制:通过 register_nested_chat() 注册,当 Agent 收到特定消息或满足条件时自动触发嵌套对话。
  4. 上下文隔离:嵌套对话拥有独立的对话历史和状态,不会污染主对话上下文,避免历史消息过长影响 LLM 性能。

  5. 解决的核心问题

  6. 复杂任务分解:将"编写完整数据分析报告"拆解为"数据收集→清洗→分析→可视化"四个子任务,每个子任务由专门的嵌套对话处理
  7. 对话历史管理:主对话只保留高层决策和最终结果,子对话处理细节过程,有效控制 token 消耗
  8. 专业化分工:不同嵌套对话可以配置不同的 Agent 组合和 LLM,如代码生成用 GPT-4,文本总结用 GPT-3.5,成本优化

  9. 与 Group Chat 的本质区别

# Nested Chat 示例
def nested_chat_summary(recipient, messages, sender, config):
    # 启动嵌套对话处理子任务
    nested_chat = initiate_chats([
        {
            "sender": assistant,
            "recipient": code_executor,
            "message": "执行数据分析代码"
        }
    ])
    return nested_chat.summary  # 返回摘要而非完整历史

assistant.register_nested_chat(
    nested_chat_summary,
    trigger=lambda msg: "分析数据" in msg["content"]
)

# Group Chat 对比:所有 Agent 共享同一对话历史
group_chat = GroupChat(
    agents=[user_proxy, assistant, code_executor],
    messages=[],  # 所有消息都在这里
    max_round=10
)
  • 上下文可见性:Group Chat 所有 Agent 共享完整历史,Nested Chat 子对话对外部不可见

  • 执行模式:Group Chat 是轮转式(round-robin),Nested Chat 是树状层级式

  • 适用场景:Group Chat 适合协作讨论,Nested Chat 适合任务分解和专业化处理

3️⃣ Key Differences

查看内嵌表格


5、场景题:用 AutoGen 实现一个「自动化数据分析助手」,用户提出分析需求后,系统自动生成代码、执行、可视化并生成报告,如何设计 Agent 角色和对话流程?⭐⭐⭐⭐

难度级别:⭐⭐⭐⭐(系统架构设计、多 Agent 协作)

1️⃣ Common Answer

我会设计三个 Agent:一个 UserProxyAgent 接收用户需求,一个 AssistantAgent 生成代码,一个 UserProxyAgent 执行代码。然后 AssistantAgent 生成报告。对话流程就是用户说需求,Assistant 生成代码,UserProxy 执行,然后生成报告。

2️⃣ Impressive Answer

  1. Agent 角色设计
# 1. 需求理解 Agent(AssistantAgent)
requirement_agent = AssistantAgent(
    name="requirement_analyst",
    system_message="你负责理解用户的数据分析需求,明确分析目标、数据源、指标维度,输出结构化需求文档。",
    llm_config={"model": "gpt-4"}
)

# 2. 代码生成 Agent(AssistantAgent)
code_generator = AssistantAgent(
    name="data_engineer",
    system_message="你负责根据需求文档生成 Python 数据分析代码,使用 pandas、matplotlib 等库,代码需包含错误处理。",
    llm_config={"model": "gpt-4"}
)

# 3. 代码执行 Agent(UserProxyAgent)
code_executor = UserProxyAgent(
    name="executor",
    code_execution_config={
        "work_dir": "data_analysis",
        "use_docker": True,
        "timeout": 120
    },
    human_input_mode="NEVER"
)

# 4. 可视化专家(AssistantAgent)
visualization_agent = AssistantAgent(
    name="visualizer",
    system_message="你负责根据分析结果设计合适的可视化方案,生成 matplotlib/seaborn 绘图代码。",
    llm_config={"model": "gpt-3.5-turbo"}  # 成本优化
)

# 5. 报告生成 Agent(AssistantAgent)
report_generator = AssistantAgent(
    name="report_writer",
    system_message="你负责整合分析结果和图表,生成结构化 Markdown 报告,包含数据洞察和建议。",
    llm_config={"model": "gpt-4"}
)
  1. 对话流程设计(Nested Chat + Group Chat 混合架构)
# 主对话:需求理解 → 报告生成
def main_workflow():
    # 第一步:需求理解
    requirement = requirement_agent.generate_reply(
        messages=[{"role": "user", "content": user_request}]
    )

    # 第二步:启动嵌套对话处理数据分析
    analysis_result = initiate_chats([
        {
            "sender": code_generator,
            "recipient": code_executor,
            "message": f"根据需求生成并执行代码:{requirement}",
            "clear_history": True
        },
        {
            "sender": visualization_agent,
            "recipient": code_executor,
            "message": "根据分析结果生成可视化",
            "clear_history": True
        }
    ])

    # 第三步:生成最终报告
    report = report_generator.generate_reply(
        messages=[{
            "role": "user",
            "content": f"需求:{requirement}\n分析结果:{analysis_result}\n生成报告"
        }]
    )

    return report
  1. 容错和优化机制
  2. 代码执行失败处理:codeexecutor 捕获异常后自动反馈给 codegenerator,触发自我修正循环(最多重试 3 次)
  3. 结果验证:执行完成后自动检查输出文件是否存在、数据格式是否正确
  4. 成本控制:代码生成和报告生成使用 GPT-4,可视化使用 GPT-3.5,降低成本
  5. 人工介入点:在报告生成前设置 human_input_mode="TERMINATE",允许用户确认或调整分析方向

  6. 完整对话示例

User: "帮我分析 2024 年 Q1 的销售数据,找出 Top 10 商品,并展示销售趋势"

Requirement_Agent: "需求已明确:1. 数据源:sales_q1_2024.csv 2. 分析目标:Top 10 商品、销售趋势 3. 输出:排行榜 + 折线图"

[Nested Chat 1 - 数据分析]
Code_Generator → 生成 pandas 聚合代码
Code_Executor → 执行代码,返回 Top 10 商品数据

[Nested Chat 2 - 可视化]
Visualization_Agent → 生成 matplotlib 绘图代码
Code_Executor → 执行代码,生成趋势图

Report_Generator: "## 2024 Q1 销售分析报告\n### Top 10 商品\n[表格]\n### 销售趋势\n[图表]\n### 洞察\n1. 3 月销售额增长 20%..."

3️⃣ Key Differences

查看内嵌表格


AutoGen ConversableAgent 与多 Agent 对话机制

1、基础题:AutoGen 中 ConversableAgent 的作用是什么?

难度级别:⭐(考察要点:ConversableAgent 定义、initiate_chat、终止条件)

ConversableAgent 是 AutoGen 中所有 Agent 类型的基类,封装了消息收发、回复生成(LLM/函数/人工)和终止判断三个核心能力。两个 Agent 通过 initiate_chat 触发对话,轮流发言,直到 is_termination_msg 检测到终止条件(如消息包含 "TERMINATE")为止。


2、进阶题:AutoGen 的 human_input_mode 三种模式有什么区别,GroupChat 的发言权管理如何工作?

难度级别:⭐⭐(考察要点:ALWAYS/NEVER/TERMINATE 模式工程含义、GroupChatManager 发言权策略、speaker_selection_method)

1️⃣ Common Answer

human_input_mode 有三种:ALWAYS 就是每次都要人工输入,NEVER 是全自动不需要人,TERMINATE 是终止时才要人工确认。GroupChat 里有 GroupChatManager 来管理谁发言,可以设置 round_robin 轮流或者 auto 自动选。

2️⃣ Impressive Answer

我会从 3 个角度来回答这个问题:

  1. 首先说 human_input_mode 的工程含义。三种模式对应三种人机协作程度:ALWAYS 是每步都等人,适合完全人工驾驶;NEVER 是全程自动,适合 CI/CD 批处理;TERMINATE 是自动执行、完成后人工确认结果。生产环境里 TERMINATE 是最实用的,既保证效率,又让人在关键节点做最终把关。

  2. 其次说 GroupChatManager 的发言权策略speaker_selection_method 有三种选项:auto 让 LLM 根据上下文选人,最灵活但每轮多耗一次 token;round_robin 轮流发言,省 token 但不智能;工程上最推荐 allowed_or_disallowed_speaker_transitions,预先定义合法的发言顺序(比如 researcher 后只能 coder),兼顾可控性和效率。

  3. 最后说 AutoGen 和 LangGraph 的根本区别。LangGraph 是图驱动,执行路径预先定义;AutoGen 是对话驱动,Agent 用自然语言协调,路径由对话动态决定。前者适合确定性生产流程,后者适合探索性任务。实际项目可以混用:用 LangGraph 定义骨架,在特定节点内嵌 AutoGen 对话。

3️⃣ Key Differences

查看内嵌表格


3、场景题:用 AutoGen 实现代码自动生成与执行时,如何防止 Agent 无限循环调用同一个工具?

难度级别:⭐⭐(考察要点:max_turns 限制、is_termination_msg 设计、UserProxyAgent 代码执行配置)

1️⃣ Common Answer

可以设置 max_turns 来限制最大轮次,防止无限循环。另外 is_termination_msg 可以检测终止条件,比如消息里有 TERMINATE 就停止。

2️⃣ Impressive Answer

防止无限循环要从两个层面入手。

第一,硬限制层面initiate_chat 设置 max_turns=10,作为兜底的轮次上限,不管什么情况都不会超出。

第二,逻辑终止层面:在 is_termination_msg 里检测 TERMINATE 关键词,同时在 assistant 的 system_message 里明确指示:任务成功或者连续两次执行失败后,必须输出 TERMINATE,否则 LLM 可能陷入"执行 → 失败 → 再执行"的死循环。根本原因通常是工具返回的错误信息没有被正确处理,LLM 误判任务尚未完成,这个可以通过 LangSmith Trace 看到 Tool Run 和 LLM Run 的交替次数来验证。

3️⃣ Key Differences

查看内嵌表格