前言
前面学习了 AutoGen 基础,今天通过几个简单的应用场景来理解 MAS 的应用。
Agent 协同方式
上节讲了几个多 Agent 的通讯机制,但具体 AutoGen 内部多个 Agent 之间是怎么协调的?谁先谁后的顺序是由谁决定的?
RoundRobinGroupChat
RoundRobinGroupChat,轮询群聊,是 MAS 系统中最简单的协同调度器。传入一个智能体列表 [A, B, C],系统会严格按照 A→B→C→A→B→C...的顺序循环执行,每个智能体在轮到自己时向全体广播消息。
max_turns:最大轮次termination_condition:终止条件,如关键词触发。作用是防止无限循环。
SelectorGroupChat
SelectorGroupChat,选择器群聊,是基于 LLM 的智能调度器。每轮对话后,系统会将完整的对话历史、各个智能体的角色描述(name, description)提交给一个LLM(即selector),由这个LLM根据当前上下文判断“下一步谁最合适发言”。
allow_repeated_speaker:默认Flase,防止同一智能体霸占对话selector_func:支持自定义选择逻辑,实现类似状态机的复杂流转
Swarm
Swarm,蜂群模式。智能体通过发送特殊的 HandoffMessage来主动将任务“移交”给另一个智能体。系统不依赖中央调度器,而是根据最新的移交信号来决定下一个发言者。去中心化和自主性 设计的典型案例。
GraphFlow
GraphFlow,工作流模式,是一种基于有向图的显式流程编排模式。开发者使用 DiGraphBuilder等API,像画流程图一样,用节点(智能体)和边(执行顺序与条件)来定义精确的工作流。中心化控制和确定性 设计的典型案例。
- 支持顺序、并行、条件分支和循环等复杂逻辑。消息传递路径是预先定义且确定的,控制力极强。
MagenticOneGroupChat
MagenticOneGroupChat,M1编排器群聊,Magentic-One 通用多智能体系统的 “大脑”或“总指挥” 。它是一个高层抽象,将复杂的任务规划、工具调用(如网页浏览、文件操作)逻辑封装了起来。你提供一组智能体,它来负责指挥。
MagenticOne
MagenticOne,M1辅助类。他是 MagenticOneGroupCha t的一个便捷封装。它会自动为你创建并集成一整套预定义的专家智能体,如 MultimodalWebSurfer(网页浏览)、FileSurfer(文件操作)、Coder(代码编写)和 Executor(代码执行)等。M1 相关的设计模式都是模型驱动的智能调度。
- “开箱即用”
该有哪个?
| 协同方式 | 应用场景 |
|---|---|
| RoundRobinGroupChat | 固定流程的流水线作业,如“反思模式”(写手与评论家轮流迭代)。 |
| SelectorGroupChat | 复杂、非固定流程的专家会诊,如根据症状动态选择专科医生。 |
| Swarm | 灵活的客服转接、跨领域问题会诊等需要智能体自主协商移交任务的场景。 |
| GraphFlow | 严格的业务流程、审批流水线、数据处理管道等需要精确编排的确定性工作流。 |
| MagenticOneGroupChat | 解决跨领域的开放式复杂任务,特别是涉及网页搜索、文件处理、代码编写与执行的综合性研究或自动化。 |
| MagenticOne | 快速搭建具备多模态感知和复杂任务执行能力的智能体团队,用于概念验证或快速开发。 |
🌰论文搜集
需求背景
使⽤autoGen通过多agent群聊搜集LLM⽂献实例。从arxiv上找到最新的5篇关于 Agent 的论文,保存到markdown表。并在同目录生成一个md格式的文件,用于存储该表格。
任务拆解
- 编写脚本搜集资料
- 仔细审查搜集资料,判断有效性。并针对性分类
角色定义
- Planner(
AssistantAgent):规划师,负责整个任务规划、管理和分配
# 创建一个计划员assistant
planner = AssistantAgent(
name="Planner",
system_message="""规划师。提出计划。根据管理员和评论员的反馈修改计划,直到管理员批准。
该计划可能涉及会写代码的工程师Engineer和不会写代码的科学家Scientist。
首先解释一下计划。明确哪一步由工程师执行,哪一步由科学家执行。
""",
model_client=model_client,
)
- Admin(
UserProxyAgent):人类管理员,规划师互动,讨论计划。授权其他角色行动
# 创建一个管理员Proxy
user_proxy = UserProxyAgent(
name="Admin",
description="人类管理员. 与规划师互动,讨论计划。计划执行需要得到该管理员的批准。",
)
- Engineer(AssistantAgent):工程师,负责写代码来解决对应问题
# 创建一个工程师assistant
engineer = AssistantAgent(
name="Engineer",
model_client=model_client,
system_message="""工程师。您遵循已批准的计划。您编写 python/shell 代码来解决任务。
将代码包装在指定脚本类型的代码块中。用户无法修改您的代码。因此,不要建议需要其他人修改的不完整代码。
如果代码块不打算由执行器执行,请不要使用它。
不要在一个响应中包含多个代码块。不要要求其他人复制和粘贴结果。检查执行器返回的执行结果。
如果结果表明存在错误,请修复错误并再次输出代码。建议使用完整代码而不是部分代码或代码更改。
如果错误无法修复,或者即使代码成功执行后任务仍未解决,请分析问题,重新审视您的假设,
收集您需要的其他信息,并考虑尝试其他方法。
""",
)
- Critic(AssistantAgent):审核员,检查其他代理商的计划、声明和代码并提供反馈,同时决定是否需要
Admin干预
# 创建一个评论家assistant
critic = AssistantAgent(
name="Critic",
system_message="批评家。仔细检查其他代理商的计划、声明和代码并提供反馈。检查计划是否包括添加可验证信息,例如源 URL。"
"你的工作完成后请以'人类管理员'的称呼明确告知管理员是否需要干预",
model_client=model_client,
)
- Executor(CodeExecutorAgent):代码执行器,执行代码并返回结果。
code_executor = DockerCommandLineCodeExecutor(work_dir="../paper")
await code_executor.start()
# 创建一个执行者Proxy
executor = CodeExecutorAgent(
name="Executor",
description="执行器。执行工程师编写的代码并报告结果。",
model_client= model_client,
code_executor=code_executor
)
- Scientist(CodeExecutorAgent):科学家。可以对论文进行鉴别、分类。以及进一步专业处理。
# 创建一个科学家assistant
scientist = AssistantAgent(
name="Scientist",
model_client=model_client,
system_message="""科学家。你遵循一个已批准的计划。你可以在看到论文摘要后对论文进行分类。你不写代码。""",
)
协作方式
这里是用 RoundRobinGroupChat,还是 SelectorGroupChat 呢?其实从程序执行上都可以,都是可以得出最终结果的。但是前者往往更适合固定流程的 case ,但是本场景中几个角色发言可能是不固定的,所以这里选择 SelectorGroupChat 更好一些。
agent_team = SelectorGroupChat(
[user_proxy, engineer, scientist, planner, executor, critic],
model_client = model_client
)
print("\033[1;31m本程序因为要访问arxiv需要科学上网!请先检查人类管理员检查是否开启了科学上网!\033[0m")
stream = agent_team.run_stream(task="从arxiv上找到最新的5篇关于 Agent 的论文,保存到markdown表。并在同目录生成一个md格式的文件,用于存储该表格。"
"请问人类管理员对该计划是否有调整?如有,请告知我")
await Console(stream)
运行分析
- Selecter(LLM)选择 Engineer 开始写相关查询代码
- Selecter(LLM)选择 Executor 来执行和验证 Engineer 写的代码
- 代码执行报错后,Selecter(LLM)选择 Critic 进行审查,对代码给出了修改建议
-
基于 3 的变动,Admin 询问 人类管理员是否需要干预
-
Executor 继续执行 -> Critic审查 -> 人类干预 循环直到代码完全可靠
- 这里可能执行多轮
- Executor 终于生成了我们要的 md 格式的论文汇总表格
- 最后还给出了一些建议
- paper 目录下是 LLM 不断自我修正中产生的
py中间代码最后一个完整且正确的代码,我们自己执行也会生成对应的 md 表格。
🌰数据分析
使⽤ autoGen 分析数据并绘制对应图标。
Coder
coder = AssistantAgent(
name="Coder",
model_client=model_client,
)
Executor
code_executor = DockerCommandLineCodeExecutor(work_dir="workspace/dataanalysis")
await code_executor.start()
executor = CodeExecutorAgent(
name="Executor",
code_executor=code_executor
)
Critic
critic = AssistantAgent(
name="Critic",
system_message="""
评论家。您是一位乐于助人的助手,能够通过提供 1(差)- 10(好)的分数来评估给定可视化代码的质量,同时提供明确的理由。您必须为每次评估考虑可视化最佳实践。具体来说,您可以从以下维度仔细评估代码
- 错误(bug):是否存在错误、逻辑错误、语法错误或拼写错误?代码编译失败的原因是什么?应该如何修复?如果存在任何错误,错误分数必须小于 5。
- 目标合规性(合规性):代码与指定可视化目标的符合程度如何?
您必须为上述每个维度提供分数。
{bug:0,合规性:0}
不建议代码。
最后,根据上述批评,建议程序员应采取的具体行动清单,以改进代码。
""",
model_client=model_client,
)
测试代码
team = RoundRobinGroupChat([coder, executor, critic], max_turns=20)
stream = team.run_stream(task="从 https://raw.githubusercontent.com/vega/vega/main/docs/data/seattle-weather.csv 下载数据并告诉我每种天气的数量。将图保存到文件中。在可视化数据集之前打印数据集中的字段。接受评论者的反馈以改进代码。")
await Console(stream)
运行
过程就不做过多分析,直接上结果。
🌰查看股价
查看估价信息。
Coder
# 创建助手代理
assistant = AssistantAgent(
name="Coder",
system_message='''你需要编写 python/shell 代码来解决任务。将代码包装在指定脚本类型的代码块中。
用户无法修改您的代码。因此,不要建议需要其他人修改的不完整代码。如果代码块不打算由执行器执行,请不要使用它。
不要在一个响应中包含多个代码块。不要要求其他人复制和粘贴结果。检查执行器返回的执行结果。
如果结果表明存在错误,请修复错误并再次输出代码。建议使用完整代码而不是部分代码或代码更改。
如果错误无法修复,或者即使代码成功执行后任务仍未解决,请分析问题,重新审视您的假设,收集您需要的其他信息,
并考虑尝试其他方法。''',
model_client=model_client
)
Executor
# 创建代码执行器
code_executor = DockerCommandLineCodeExecutor(work_dir="workspace/stockprice")
await code_executor.start()
# 创建执行器代理
executor = CodeExecutorAgent(
name="Executor",
code_executor=code_executor
)
终止条件
max_msg_termination = MaxMessageTermination(max_messages=10)
text_termination = TextMentionTermination("TERMINATE")
combined_termination = max_msg_termination | text_termination
测试代码
# 创建团队聊天
team = RoundRobinGroupChat(
[assistant, executor],
termination_condition=combined_termination
)
# 运行任务
stream = team.run_stream(task="今天是几号,获取美团公司(三快科技)本月至今的股票变化信息,并且用文字对股票变化进行分析。同时获取最近一周美团的股价信息,并绘制成K线图,生成图片保存到当前目录!")
await Console(stream)
🌰数据生成可视化图
Coder
coder = AssistantAgent(
name="Coder",
model_client=model_client,
system_message="务必全程使用中文进行交流和反馈!!!"
)
Executor
code_executor = DockerCommandLineCodeExecutor(work_dir="workspace/visualization")
await code_executor.start()
executor = CodeExecutorAgent(
name="Executor",
code_executor=code_executor,
system_message="务必全程使用中文进行交流和反馈!!!"
)
Critic
critic = AssistantAgent(
name="Critic",
system_message="""
评论家。您是一位乐于助人的助手,能够通过提供 1(差)- 10(好)的分数来评估给定可视化代码的质量,同时提供明确的理由。您必须为每次评估考虑可视化最佳实践。具体来说,您可以从以下维度仔细评估代码
- 错误(bug):是否存在错误、逻辑错误、语法错误或拼写错误?代码编译失败的原因是什么?应该如何修复?如果存在任何错误,错误分数必须小于 5。
- 数据转换(transformation):数据是否针对可视化类型进行了适当的转换?例如,数据集是否根据需要进行了适当的过滤、聚合或分组?如果使用日期字段,是否先将日期字段转换为日期对象等?
- 目标合规性(compliance):代码与指定可视化目标的匹配程度如何?
- 可视化类型 (type):考虑最佳实践,可视化类型是否适合数据和意图?是否有更有效地传达见解的可视化类型?如果其他可视化类型更合适,则分数必须小于 5。
- 数据编码 (encoding):数据是否适合可视化类型编码?
- 美学 (aestics):可视化的美学是否适合可视化类型和数据?
您必须为上述每个维度提供分数。
{错误:0,转换:0,合规性:0,类型:0,编码:0,美观性:0}
不建议代码。
最后,根据上述批评,建议程序员应采取的具体行动清单,以改进代码。
要求:务必全程使用中文进行交流和反馈!!!"
""",
model_client=model_client,
)
测试代码
team = RoundRobinGroupChat(
[coder, executor, critic],
max_turns=20,
)
stream = team.run_stream(task="从 https://raw.githubusercontent.com/uwdata/draco/master/data/cars.csv 下载数据并绘制可视化图,告诉我们重量和马力之间的关系。将图保存到文件中。在可视化之前打印数据集中的字段。")
await Console(stream)