news 2026/10/1 13:14:09

AutoGen多智能体协作实战:从架构设计到代码自动修复流水线

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AutoGen多智能体协作实战:从架构设计到代码自动修复流水线

1. 从“多智能体”说起:AutoGen到底在解决什么问题

如果你最近在折腾大模型应用,大概率会撞上“多智能体协作”这个词。单次问答已经满足不了复杂任务了——写一份行业调研报告、跑通一个数据分析流程、自动修复一段有Bug的代码,这些事让一个模型从头干到尾,效果往往差强人意。AutoGen就是在这个背景下进入视野的:它把“一个模型干所有事”拆成“多个角色分工协作”,让不同的智能体各司其职,再通过对话把结果拼起来。

我第一次接触AutoGen是在做一个自动化代码审查的小工具。当时的需求很朴素:给一段代码,让它自动找出潜在问题并给出修改建议。用单轮Prompt试了几次,发现模型要么漏掉边界条件,要么改着改着就跑偏了。后来换成两个角色——一个负责“挑刺”,一个负责“验证挑刺是否成立”,效果立刻上了一个台阶。这就是AutoGen的核心思路:用对话驱动协作,用角色约束行为。

AutoGen是微软开源的一个多智能体对话框架,关键词是“对话”和“可编排”。它不绑定某一家模型,OpenAI、Anthropic、本地部署的开源模型都能接;它也不强制你用某种复杂的工作流引擎,核心抽象就是“会说话的智能体”和“它们之间的消息传递”。你可以把它理解成一个“智能体聊天室”,每个成员有自己的系统提示词、自己的工具集、自己的终止条件,主持人决定谁下一个发言。

适合谁来读这篇内容?如果你是大模型应用开发者,正在评估多智能体框架选型;如果你已经用过LangChain这类工具,但觉得链式调用不够灵活;如果你需要让模型自动完成“写代码—跑测试—改代码”这种循环任务,AutoGen值得花时间研究。下面我会从架构设计、核心概念、实操配置、常见坑几个角度,把AutoGen拆开讲清楚。

2. AutoGen的架构骨架:ConversableAgent与GroupChat

2.1 ConversableAgent:一切智能体的基类

AutoGen里最核心的类叫ConversableAgent。顾名思义,它是一个“可以对话的智能体”。这个类封装了几个关键能力:接收消息、生成回复、执行工具、判断是否终止对话。你看到的AssistantAgent、UserProxyAgent、GroupChatManager,全都是它的子类或实例化配置。

理解ConversableAgent的关键在于它的两个方法:generate_reply和execute_function。前者负责“说什么”,后者负责“做什么”。当你给一个智能体配置了llm_config,它就能调用大模型生成回复;当你给它注册了function_map,它就能在对话中触发工具调用。这两个能力组合起来,就构成了一个既能思考又能行动的智能体。

我刚开始用的时候犯过一个错:把所有逻辑都塞进一个AssistantAgent里,结果系统提示词越写越长,模型开始“精神分裂”——一会儿扮演代码专家,一会儿扮演测试工程师。后来才明白,AutoGen的设计哲学是一个智能体只做一件事。代码专家就只管写代码,测试工程师就只管跑测试,两者通过消息传递协作。这样每个角色的提示词可以写得很聚焦,模型的表现也稳定得多。

2.2 UserProxyAgent:不只是“用户代理”

UserProxyAgent这个名字容易让人误解,以为它只是代表人类用户输入。实际上它在AutoGen里扮演两个角色:一是人类输入的代理,二是代码执行的代理。当你设置human_input_mode="NEVER"时,它不会真的等你输入,而是自动根据配置决定下一步;当你设置code_execution_config时,它会在本地执行模型生成的代码,并把执行结果返回给对话。

这个设计非常巧妙。在“写代码—跑代码—改代码”的循环里,AssistantAgent负责生成代码,UserProxyAgent负责执行代码,执行结果(包括报错信息)自动作为下一条消息传回给AssistantAgent。整个过程不需要人类介入,形成了一个自动化的闭环。我实测下来,这个闭环对于修语法错误、补全缺失的import特别有效,模型看到报错信息后通常能在一到两轮内修正。

注意:code_execution_config默认是在Docker容器里执行代码的。如果你本地没有Docker,需要显式设置use_docker=False,但这样代码会直接在宿主机上跑,存在安全风险。建议只在可信环境下关闭Docker,或者干脆保持Docker开启。

2.3 GroupChat与GroupChatManager:多智能体圆桌会议

当两个智能体搞不定的时候,就需要GroupChat出场了。GroupChat是一个消息容器,它维护一个agents列表和一个messages历史。GroupChatManager则是一个特殊的智能体,它的职责是“决定下一个谁发言”。

这个“决定谁发言”的机制是AutoGen多智能体协作的精髓。默认情况下,GroupChatManager会把当前对话历史和所有智能体的描述一起发给大模型,让模型来选下一个发言者。你也可以通过speaker_selection_method参数改成轮询(round_robin)或随机(random)。我做过对比:对于流程固定的任务(比如先写代码再审查再测试),轮询模式更稳定;对于需要动态判断的任务(比如根据用户问题决定找哪个专家),让模型来选更灵活。

GroupChat还有一个容易被忽略的参数叫max_round。它控制整个群聊最多进行多少轮对话。如果不设这个值,遇到两个智能体互相“客气”的情况——一个说“请你先”,另一个说“不,请你先”——对话可能无限循环下去。我一般会把它设在10到20之间,具体取决于任务复杂度。

3. 动手搭一个代码自动修复流水线

3.1 环境准备与依赖安装

先把环境搭起来。AutoGen的安装很简单,但有几个细节需要注意:

pip install pyautogen

如果你要用OpenAI的模型,还需要设置API Key。我习惯用环境变量管理:

export OPENAI_API_KEY="你的key"

如果你用的是兼容OpenAI接口的本地模型服务,可以在llm_config里指定base_url。AutoGen对OpenAI接口的兼容性做得不错,大部分遵循OpenAI协议的服务都能直接接。

提示:AutoGen的版本迭代比较快,不同版本之间API有差异。建议在项目里锁定版本,比如pyautogen==0.2.x,避免因为升级导致代码跑不通。

3.2 定义三个核心角色

我们来搭一个“代码自动修复流水线”,包含三个角色:程序员、审查员、执行器。

import autogen config_list = [{"model": "gpt-4", "api_key": "你的key"}] llm_config = {"config_list": config_list, "timeout": 120} # 角色一:程序员,负责写代码和改代码 programmer = autogen.AssistantAgent( name="Programmer", system_message="你是一名Python程序员。根据需求编写代码,如果收到报错信息,请分析原因并给出修正后的完整代码。代码必须放在```python```代码块中。", llm_config=llm_config, ) # 角色二:审查员,负责检查代码质量 reviewer = autogen.AssistantAgent( name="Reviewer", system_message="你是一名代码审查员。检查程序员提交的代码是否存在逻辑错误、边界条件遗漏、性能问题。如果发现问题,请明确指出并给出修改建议。如果代码没问题,请回复'代码通过审查'。", llm_config=llm_config, ) # 角色三:执行器,负责跑代码 executor = autogen.UserProxyAgent( name="Executor", human_input_mode="NEVER", code_execution_config={ "work_dir": "coding", "use_docker": False, }, is_termination_msg=lambda x: "代码通过审查" in x.get("content", ""), )

这里有几个关键配置值得展开说。is_termination_msg是一个函数,它接收一条消息,返回布尔值,决定对话是否终止。我把它设成“当审查员说代码通过审查时结束”,这样整个流程就有了明确的终点。

code_execution_config里的work_dir指定了代码执行的工作目录。AutoGen会把模型生成的代码写到这个目录下的临时文件里再执行。我建议给每个任务单独设一个目录,避免不同任务的临时文件互相干扰。

3.3 组装GroupChat并启动

三个角色定义好了,现在把它们放进一个群聊:

groupchat = autogen.GroupChat( agents=[programmer, reviewer, executor], messages=[], max_round=15, speaker_selection_method="auto", ) manager = autogen.GroupChatManager( groupchat=groupchat, llm_config=llm_config, ) executor.initiate_chat( manager, message="请写一个Python函数,接收一个整数列表,返回其中所有偶数的平方和。要求处理空列表和None输入。", )

运行这段代码,你会看到三个智能体开始对话。Programmer先写一版代码,Executor执行后发现报错或者结果不对,把信息传回去,Programmer修改,Reviewer再审查。整个过程自动进行,直到Reviewer说“代码通过审查”或者达到max_round上限。

我实测这个流水线处理中等复杂度的函数题,通常3到5轮就能收敛。比单模型一次生成的成功率高不少,尤其是涉及边界条件处理的时候。

4. 工具调用:让智能体真正“动手”

4.1 注册自定义函数

AutoGen的工具调用机制很直接:你定义一个Python函数,把它注册到智能体上,模型在对话中判断需要调用时就会触发。举个例子,我们给Programmer加一个“查询Python文档”的能力:

def query_python_doc(topic: str) -> str: """根据主题返回Python官方文档的链接和摘要。""" docs = { "list": "列表是可变序列,支持索引、切片、append、extend等方法。", "dict": "字典是键值对集合,键必须可哈希,支持get、keys、values、items等方法。", "exception": "异常处理使用try/except/finally结构,可以捕获特定类型的异常。", } return docs.get(topic.lower(), "未找到相关文档。") programmer.register_function( function_map={"query_python_doc": query_python_doc} )

注册之后,当模型在回复中生成类似query_python_doc("list")的调用请求时,AutoGen会自动执行这个函数并把结果返回给模型。模型拿到结果后继续生成回复。

这里有个细节:函数的docstring很重要。AutoGen会把函数名、参数和docstring一起发给模型,模型根据这些信息判断是否调用以及怎么传参。所以docstring要写清楚函数做什么、参数是什么含义。我见过有人写了个函数但docstring只有一行“查询文档”,结果模型根本不知道什么时候该调它。

4.2 工具调用的常见坑

第一个坑是函数返回值必须是字符串。如果你返回一个列表或字典,AutoGen在序列化时可能出错。我一般会在函数内部就把结果转成字符串再返回。

第二个坑是函数执行超时。如果工具函数执行时间过长,整个对话会被卡住。AutoGen的llm_config里有timeout参数,但它管的是模型调用超时,不管工具函数。工具函数的超时需要你自己在函数内部处理,比如用signal.alarm或者把耗时操作放到子进程里。

第三个坑是工具调用和代码执行的冲突。如果你同时给一个智能体注册了工具函数和开启了代码执行,模型有时会分不清该调工具还是该写代码。我的经验是:明确分工。AssistantAgent负责调工具,UserProxyAgent负责跑代码,不要混在一起。

5. 多智能体协作中的“翻车”场景与应对

5.1 无限循环:两个智能体互相“踢皮球”

这是最常见的问题。比如Programmer说“我写好了”,Reviewer说“我觉得有问题”,Programmer说“我改好了”,Reviewer说“还是有问题”……如果问题本身没有明确标准,两个智能体可能永远达不成一致。

应对方法有三个。第一,设置max_round硬性截断。第二,在Reviewer的提示词里加入明确的通过标准,比如“如果代码能正确处理空列表、None输入和正常列表三种情况,就判定通过”。第三,引入一个“裁判”角色,当两个智能体争执超过两轮时,由裁判做最终决定。

我通常会把第一种和第二种结合使用。max_round是兜底,明确的通过标准是治本。

5.2 消息膨胀:上下文越来越长

多智能体对话的消息历史是累积的。三个智能体聊了十轮,消息历史可能就有三十条。每条消息都带着完整的代码块和报错信息,上下文很快就会被撑爆。一旦超出模型的上下文窗口,要么报错,要么模型开始“遗忘”前面的内容。

我的做法是:在GroupChat里设置messages的清理策略。AutoGen本身没有内置的消息摘要功能,但你可以通过自定义GroupChatManager来实现。一个简单的方案是:当消息数量超过阈值时,把最早的一批消息替换成一条摘要,摘要由模型生成,保留关键决策和最终代码。

另一个更轻量的做法是:让每个智能体在回复时只引用必要的上下文,而不是把整段历史都带上。这需要在系统提示词里明确要求,比如“回复时只引用最近一次代码版本,不要重复之前的讨论”。

5.3 角色混淆:智能体“串戏”了

有时候Reviewer会开始写代码,Programmer会开始审查。这是因为模型在多轮对话中逐渐模糊了角色边界。解决办法是在每个智能体的系统提示词里反复强调角色定位,并且在GroupChatManager的speaker_selection_method里限制发言顺序。

我试过一个更“硬”的办法:给每个智能体的消息加上角色标签,比如[Programmer]、[Reviewer],然后在系统提示词里说“你只会看到带有你角色标签的消息,其他消息与你无关”。这个办法效果不错,但实现起来稍微麻烦一点,需要自定义消息处理逻辑。

6. 模型选型与成本控制

6.1 不同角色用不同模型

AutoGen允许每个智能体单独配置llm_config。这意味着你可以让Programmer用GPT-4,让Reviewer用GPT-3.5,让Executor不调用模型(它只执行代码)。这样既能保证关键环节的质量,又能控制成本。

我做过一个粗略的统计:在一个典型的代码修复任务中,Programmer的token消耗占70%,Reviewer占25%,Executor占5%。如果把Reviewer换成更便宜的模型,整体成本能降不少,而审查质量下降有限——因为审查主要是“挑毛病”,不需要太强的生成能力。

6.2 缓存与重试

AutoGen支持cache_seed参数。设置一个固定的种子,相同的请求会命中缓存,不会重复调用模型。这在调试阶段特别有用——你反复运行同一段代码,如果缓存命中,就不会产生额外费用。

重试机制方面,llm_config里的timeout和max_retries可以控制模型调用的超时和重试次数。我一般设timeout=120、max_retries=3。超时太短容易误杀正常请求,太长则会让整个对话卡住。

提示:如果你用的是按token计费的模型服务,建议在开发阶段用便宜模型跑通流程,最后再用贵模型做最终验证。AutoGen的配置切换很方便,改一下config_list就行。

7. 从Demo到生产:还需要补哪些课

AutoGen跑通Demo很容易,但要用在生产环境,还有几件事要做。

日志与可观测性。AutoGen默认把对话历史存在内存里,程序一停就没了。生产环境需要把每条消息、每次工具调用、每次代码执行都记录下来。我通常会在GroupChatManager外面包一层,把消息写入数据库或日志文件。AutoGen也支持自定义logging,但需要自己配置。

错误处理与降级。模型调用可能失败,代码执行可能超时,工具函数可能抛异常。这些异常如果不处理,整个对话就会中断。我的做法是在每个智能体的generate_reply外面加try/except,捕获异常后返回一条“我遇到了错误,请重试”的消息,让对话继续而不是崩溃。

安全边界。代码执行是AutoGen最强大的功能,也是最危险的功能。生产环境必须用Docker隔离,并且限制容器的网络访问和文件系统权限。我见过有人为了图方便直接use_docker=False,结果模型生成的代码把本地文件删了。这种教训一次就够了。

人工介入点。完全自动化的多智能体对话听起来很美好,但实际业务中往往需要在关键节点让人确认一下。AutoGen的human_input_mode支持ALWAYS、TERMINATE、NEVER三种模式。我建议在涉及资金、数据删除、对外发送消息的场景里,至少设成TERMINATE,让人类在终止前确认一次。

8. 我踩过的几个具体坑

第一个坑:is_termination_msg的判断逻辑写错了。我一开始写成lambda x: x.get("content") == "代码通过审查",结果审查员回复“代码通过审查,但建议优化变量命名”,判断就不生效了。后来改成"代码通过审查" in x.get("content", "")才稳定。

第二个坑:work_dir路径不存在。AutoGen不会自动创建这个目录,如果路径不存在,代码执行会直接报错。我现在的习惯是在启动前用os.makedirs(work_dir, exist_ok=True)确保目录存在。

第三个坑:模型生成的代码里有input()调用。在自动执行模式下,input()会阻塞整个流程,因为没有人会去输入。我在系统提示词里明确加了“不要使用input()函数,所有输入通过函数参数传入”,这个问题就再没出现过。

第四个坑:Docker镜像拉取失败。AutoGen默认用的Docker镜像在某些网络环境下拉不下来。如果你遇到这个问题,可以提前手动拉取镜像,或者在code_execution_config里指定一个本地已有的镜像。

9. 和其他Agent框架的对比感受

市面上Agent框架不少,LangChain、LlamaIndex、CrewAI各有侧重。我用下来的感受是:LangChain强在组件丰富、生态庞大,但抽象层次多,调试起来像剥洋葱;CrewAI强在角色定义清晰、上手快,但灵活性稍弱;AutoGen的定位在两者之间——它比LangChain更聚焦于“对话协作”这一件事,比CrewAI更灵活,允许你深入定制消息传递和发言选择逻辑。

如果你要做的是“多个角色围绕一个任务反复讨论、迭代”的场景,AutoGen的抽象最贴合。如果你要做的是“把多个工具串成一条流水线”,LangChain可能更顺手。选型没有绝对的好坏,关键是看你的任务形态和团队的技术栈。

AutoGen的社区活跃度不错,GitHub上的issue响应比较及时。但文档质量参差不齐,有些高级用法需要翻源码或者看示例代码才能搞明白。我的建议是:先把官方Quickstart跑通,然后找一个和你需求接近的示例,在它的基础上改。遇到问题先看issue区,大概率有人已经踩过同样的坑。

最后分享一个我常用的调试技巧:在开发阶段把llm_config里的模型换成gpt-3.5-turbo,把max_round设成5,快速验证流程是否跑通。流程没问题了,再换成更强的模型、放开轮次限制。这样迭代速度最快,成本也最低。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 13:13:42

NS2网络仿真从入门到实践:rar编译、Tcl修改与trace分析指南

简介:NS2(Network Simulator 2)是经典的开源网络模拟器,这份代码示例包面向刚接触NS2的初学者,覆盖从Tcl脚本编写、协议仿真到结果分析的完整入门路径。压缩包共28个文件,约623KB,以tcl脚本为主…

作者头像 李华
网站建设 2026/10/1 13:12:13

基于CNN的农作物病虫害识别系统:数据集、Python源码与部署全流程

简介:这份资源是面向计算机相关专业学生与深度学习入门者的农作物病虫害识别检测系统完整项目,基于卷积神经网络实现图像分类与检测,可作为高分毕业设计、课程设计或期末大作业的实战参考。压缩包共56个文件,约88.3MB,…

作者头像 李华
网站建设 2026/10/1 13:10:43

PC微信小程序wxapkg解密:从加密包到可读源码的完整路径

简介:这份资源是面向PC端微信小程序逆向分析场景的wxapkg解密工具包,主要解决微信小程序加密包无法直接解包查看的问题,适合具备一定Python基础、从事小程序安全研究或爬虫分析的技术人员使用。压缩包共6个文件,以Python脚本为核心…

作者头像 李华
网站建设 2026/10/1 13:10:27

Win7运行Steam失败原因与TLS1.2兼容性修复方案

1. 这不是网络问题,是Win7与Steam现代协议的“代际断层”你点开Steam客户端,看到“下载内容不可用”那行灰字,右下角托盘图标还在转,但游戏列表空荡荡——这感觉我太熟了。2024年还在主力使用Win7跑Steam的人,基本都卡…

作者头像 李华
网站建设 2026/10/1 13:09:35

Manjaro KDE 桌面美化:Plasma 架构深度定制指南

1. 为什么 KDE Plasma 是 Manjaro 桌面美化的“黄金组合”Manjaro 用户点开系统安装完成后的第一个桌面,大概率会看到 KDE Plasma——它不是默认里最轻量的,也不是社区里最常被截图炫耀的“极简风”代表,但它确实是 Linux 桌面生态中唯一一个…

作者头像 李华
网站建设 2026/10/1 13:08:42

基于Next.js与LangGraph.js构建AI简历优化Agent实践

最近我把一个压了很久的想法真正落地了:用 Next.js 做前端和 API 层,用 LangGraph.js 编排 AI Agent,再把这个 Agent 包装成一个能改简历、能按岗位要求重写简历段落的在线工具。它不是那种调一次接口返回一段 Markdown 的玩具,而…

作者头像 李华