Appearance
第九阶段:AutoGen 多 Agent 团队
本阶段开始项目 3:AutoGen 多 Agent 数据分析。我们让 4 个 Agent 组成一个小团队,协作分析一份销售数据。
一、多 Agent 原理
一个 Agent 既要想思路、又要写代码、还要自查,容易出错。多 Agent 的做法是分工 + 互相检查:
| 角色 | 职责 |
|---|---|
| analyst(分析师) | 拆解任务、提出分析步骤,看到结果后给业务结论 |
| coder(程序员) | 按要求写 pandas 代码 |
| executor(执行器) | 真的运行代码,把输出交回群聊 |
| reviewer(审核员) | 检查结论是否有数字支撑,通过就输出 APPROVE |
RoundRobinGroupChat 让它们轮流发言:analyst → coder → executor → reviewer → analyst …… 所有人共享同一份对话记录。
终止条件:TextMentionTermination("APPROVE") | MaxMessageTermination(20),意思是审核员说出 APPROVE 就结束,或者总消息数超过 20 条强制结束(| 表示“任一满足”),防止无限对话烧钱。
二、安装
bash
pip install autogen-agentchat "autogen-ext[openai]" pandas如果看到 googleapis-common-protos ... requires protobuf<8.0.0,>=6.33.5, but you have protobuf 5.29.6 这类依赖冲突警告,可以忽略:安装已经成功,我们的代码用不到那个包。
三、非 OpenAI 模型要写 model_info
AutoGen 认识 OpenAI 官方的模型名(如 gpt-4o),知道它们能不能调工具、能不能看图。deepseek-flash 它不认识,所以必须用 model_info 告诉它:不支持图像(vision False)、支持函数调用(function_calling True)、支持 JSON 输出等。不写会直接报错。
四、代码
1. 生成示例数据 make_data.py
生成 6 个月 × 3 个产品共 18 行的销售汇总表,保存到 data/sales.csv。
python
import pandas as pd, numpy as np
np.random.seed(0)
df = pd.DataFrame({
"月份": np.repeat([f"2026-{m:02d}" for m in range(1, 7)], 3),
"产品": ["折叠键盘", "鼠标", "耳机"] * 6,
"销量": np.random.randint(50, 300, 18),
"单价": [199, 89, 299] * 6,
})
df["销售额"] = df["销量"] * df["单价"]
df.to_csv("data/sales.csv", index=False, encoding="utf-8-sig")
print(df)2. 多 Agent 团队 09_autogen_team.py
python
import os, asyncio
from dotenv import load_dotenv
from autogen_agentchat.agents import AssistantAgent, CodeExecutorAgent
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.conditions import TextMentionTermination, MaxMessageTermination
from autogen_agentchat.ui import Console
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_ext.code_executors.local import LocalCommandLineCodeExecutor
load_dotenv()
# 模型客户端:非 OpenAI 官方的模型要写 model_info,告诉 AutoGen 这个模型具备哪些能力
model = OpenAIChatCompletionClient(
model=os.getenv("LLM_MODEL"),
base_url=os.getenv("LLM_BASE_URL"),
api_key=os.getenv("LLM_API_KEY"),
model_info={"vision": False, "function_calling": True, "json_output": True,
"family": "unknown", "structured_output": False},
)
# 1. 分析师:拆解任务、提出分析思路
analyst = AssistantAgent("analyst", model_client=model, system_message=
"你是数据分析师。根据任务提出清晰的分析步骤,交给 coder 写代码。看到执行结果后给出业务结论。")
# 2. 程序员:只负责写代码
coder = AssistantAgent("coder", model_client=model, system_message=
"你是 Python 程序员。按分析师的要求写 pandas 代码,放在 ```python 代码块里。"
"数据文件是 data/sales.csv(utf-8-sig 编码)。用 print 输出结果,不要画图。")
# 3. 执行器:真的去运行 coder 写的代码,结果交回群聊
executor = CodeExecutorAgent("executor",
code_executor=LocalCommandLineCodeExecutor(work_dir="."))
# 4. 审核员:检查结论是否有数据支撑
reviewer = AssistantAgent("reviewer", model_client=model, system_message=
"你是审核员。检查分析师的结论是否都有执行结果中的数字支撑。"
"有问题就指出让大家修改;没问题就总结最终报告,并在最后单独写一行 APPROVE。")
# 终止条件:审核员说 APPROVE,或者总共超过 20 条消息(防止无限对话烧钱)
stop = TextMentionTermination("APPROVE") | MaxMessageTermination(20)
# 轮流发言:analyst → coder → executor → reviewer → analyst ...
team = RoundRobinGroupChat([analyst, coder, executor, reviewer], termination_condition=stop)
async def main():
await Console(team.run_stream(task = """分析 data/sales.csv(utf-8-sig 编码)。
表结构:列为 月份(字符串, 如 2026-01)、产品、销量、单价、销售额;共 18 行,是“月份×产品”的汇总表,不是订单明细。
问题:1)哪个产品总销售额最高;2)各产品的月度销量趋势;3)给出一条经营建议。"""))
asyncio.run(main())运行:
bash
python make_data.py
python 09_autogen_team.py五、第一次运行:互相纠错
第一次的 task 里没写表结构。分析师看不到数据,只能盲猜有个 date 列;程序员照着写代码,执行器一跑就报:
KeyError: 'date'审核员对照输出里真实的列名 ['月份','产品','销量','单价','销售额'] 指出问题,判不通过。这正好演示了多 Agent 的价值:一个人犯错,另一个人拦住。
根本原因是分析师在盲猜表结构。两种修法:
- 把表结构写进 task(最简单,本节采用,见上面代码里的 task)。
- 先探查再分析:规定第一轮只看
df.head()和列名,之后再分析。
六、第二次运行:APPROVE
写明表结构后,团队很快拿到正确数字,审核员输出 APPROVE。结论:
- 耳机总销售额最高:338,767(占 55.69%);折叠键盘 191,637;鼠标 77,875。
- 趋势:鼠标销量上升,耳机和折叠键盘首末对比下滑。
七、指标打架:审核员的局限
耳机的首末变化率是 -35.33%,平均月环比却是 +27.22%,方向相反。原因是数据波动大时,个别月份的暴涨会把环比平均值拉高。
审核员却通过了。因为审核员只查提示词让它查的东西(“结论有没有数字支撑”),没要求它检查指标口径是否一致。真实业务里应该把“指标冲突时要说明使用哪个口径”写进审核员的提示词。
八、安全提醒:代码执行器
LocalCommandLineCodeExecutor 会直接在你的电脑上执行 LLM 写的代码。学习时没问题,但生产环境必须换成 Docker 沙箱(如 DockerCommandLineCodeExecutor),否则模型写出删文件之类的代码就会真的执行。
下一阶段预告
第十阶段:给团队加上画图 + 生成报告文件,让分析结果变成图表和可交付的报告。