资讯动态

Agent运行模式对比与源码拆解:从单轮到多Agent协作

发布时间:2026/9/2 13:19:39 来源:尧图企业网站定制
简介面向AI智能体设计与软件开发者的源码资源包聚焦ReAct推理-行动与Plan-and-Execute规划-执行两种主流运行模式系统梳理了二者的核心思想、工作流程、优劣势及适用场景。资源通过简洁的HTML演示页面直观展示ReAct边推理边行动、可即时调整的特点以及Plan-and-Execute先规划后执行、全局清晰的优势帮助读者快速识别动态任务与结构化任务之间的选型差异。包内共3个文件包含HTML演示源码、inscode配置及gitignore辅助文件整体仅10KB轻量易读适合作为学习模板或二次开发基础。读者还可以借助源码中的示例进一步理解两种模式结合使用以提升策略灵活性的思路并参考其中关于按任务动态变化或步骤明确程度选择模式的建议。目前已有53人学习下载对于正在调研智能体架构、对比模式差异或快速搭建演示原型的开发者是一份省时高效的入门资料。 把Agent的Prompt调好只是迈过了第一道门槛。真正决定它能不能稳定跑在业务里的是运行模式。我最近整理了一版Agent运行模式的对比笔记把每种模式的核心逻辑抽成了可复现的源码片段今天拿出来聊一聊。文章默认你已经有LLM调用和工具调用的基础但不要求用过任何特定框架。我会按单轮直答、ReAct、Plan-and-Execute、反射、多Agent协作几种常见模式依次拆解穿插源码和踩坑记录最后给一张选型对照表。想自己写Agent而不是只会调框架的话这篇应该能省不少时间。1. Agent运行模式到底在对比什么1.1 为什么“跑通”不等于“跑好”很多人第一次跑通Agent时特别兴奋但放到真实场景里问题会一个接一个冒出来同样一个任务有时结果正确有时完全跑偏工具被莫名其妙调用几十次上下文越来越长最终超限。这些问题十有八九不是模型能力不行而是运行模式没选对。运行模式本质上决定三件事模型在一个任务里被调用几次、调用之间如何传递信息、流程控制权在模型手里还是在你写的代码手里。单轮直答模式把决策权完全交给模型一次生成最终答案ReAct模式把控制权分散到每一轮思考和动作之间Plan-and-Execute模式把“拆任务”和“执行子任务”分开用流程框住模型。这三者在代码层面的差异很小行为差异却极大。我自己的经验是任何Agent项目的第一个版本都应该先用最简单的模式跑通再观察失败案例集中在哪逐步升级。直接上多Agent协作看起来很酷但排查问题时会很痛苦。模式选对了平庸的模型也能交出稳定结果选错了再强的模型也救不回来。1.2 从输入输出看模式的本质差异对比运行模式有一个很实用的视角看每次调用LLM时messages列表里到底放了什么。单轮模式通常只有一条user消息加一条assistant消息ReAct的messages里会交替出现thought、action、observation每轮都要把之前所有步骤重新发给模型Plan-and-Execute一开始就把完整计划放进上下文执行过程中再逐步追加每步结果反射模式把上一轮答案和评价一起发给模型让它修正。所以“运行模式”和“上下文管理策略”几乎是同一个概念。选模式之前先想清楚三个问题任务需要几步每一步是否依赖外部工具的结果能不能容忍模型犯错并自己纠正这三个问题想清楚了模式自然就出来了。举个例子要做“根据用户问题查询订单状态”的客服Agent单轮模式只能让模型生成一段看起来合理的SQL它不会真的去查换成ReAct模型会先调用查订单工具再把真实结果组织成回答。单轮只能“说”ReAct才能“做”但代价是每次工具调用都要把历史重新发给模型Token成本成倍上涨。2. 三种主流运行模式的源码级拆解2.1 单轮直答模式最简单也最容易低估单轮直答模式的源码短到有点不好意思def run_single_round(prompt: str, llm_func) - str: messages [{role: user, content: prompt}] response llm_func(messages) return response[-1][content]严格来说这不算Agent但它是所有Agent模式的地基适用范围远比想象中广。文本分类、信息抽取、格式转换、翻译、简单问答单轮模式完全够用延迟低、成本低、结果可预期出了问题也最好排查。这里有个容易被忽略的点单轮模式也能调用工具只是调用逻辑写在你的业务代码里。比如先调一个模型判断意图再根据意图走不同业务分支这是一种“外部编排的单轮模式”。LLM只负责其中一小段流程控制交给硬编码。这种方案可靠且简单适合大部分生产场景。很多开发者一上来就上ReAct觉得Agent就得让模型自主决策但我见过太多项目因为ReAct不可控又改回硬编码路由。我的建议是能硬编码的路由就不要让模型自由发挥。2.2 ReAct模式边想边做用源码看推理循环ReActReasoning and Acting的思路是让模型在推理和行动之间交替后来成了各类Agent框架的主流。核心代码可以浓缩成一个while循环def run_react(task, llm_func, tools, max_steps10): messages [{role: user, content: task}] action_map {t.name: t for t in tools} for step in range(max_steps): response llm_func(messages) messages.append({role: assistant, content: response}) action parse_action(response) if action[type] finish: return action[answer] tool action_map.get(action[name]) if tool is None: observation fError: unknown tool {action[name]} else: try: observation tool.run(**action[args]) except Exception as e: observation fError: {e} messages.append({role: user, content: fObservation: {observation}}) return {error: max_steps exceeded, messages: messages}这段代码有四处细节决定它能不能真跑。第一parse_action要容错。模型输出的Action经常不规整可能带Markdown代码块可能把参数写成JSON数组。我一般让模型严格按“Action: 工具名\nAction Input: JSON”的格式输出同时写一个parse函数兼容常见格式错误。第二Observation必须短。工具可能返回几千行日志直接丢给模型会让下一轮上下文爆炸。我会在工具层截断到500字并注明这是截断结果。第三max_steps不能省。模型很可能陷入“调用工具-拿到结果-再调用同样工具”的死循环没有上限Token会烧到你怀疑人生。第四未知工具和异常也要作为Observation返回让模型自己修正这比外部校验更自然。ReAct最适合“任务步骤不明确必须根据中间结果动态决定下一步”的场景比如“查这个仓库里最近更新的Python文件”模型需要先列目录、再看文件、再读内容每一步都依赖上一步输出。这种任务用单轮完全做不了用Plan-and-Execute又因为步骤不确定而计划不准。代价是Token消耗随时间线性增长优化手段是定期把早期Thought和Observation压缩成摘要只保留最近几步的完整内容。2.3 Plan-and-Execute模式先计划再执行Plan-and-Execute和ReAct最大的区别是先让模型生成完整执行计划再逐条执行。核心代码def run_plan_execute(task, planner, executor, max_steps10): plan planner(task) current_plan plan[:max_steps] executed [] for i, step in enumerate(current_plan): result executor(step, planplan, executedexecuted) if result.status need_replan: new_plan planner(task, feedbackresult.error, planplan, executedexecuted) current_plan[i:] new_plan plan current_plan if result.status done: executed.append(result.output) return synthesize(executed)planner和executor一般复用同一个LLM但system prompt完全不同。planner只负责输出步骤列表不执行executor只按步骤执行不能跳步。这个模式的优势是可预测出了问题可以直接定位到某一步也方便并行执行无依赖的子任务。我经常用它做“数据清洗-分析-生成报告”这类多阶段任务。但计划本身可能出错这是它最大的坑。任务需求有歧义时planner生成的计划可能完全跑偏。解决办法是executor执行出错时触发replan而不是直接抛异常。另一种技巧是让planner给每个步骤加“验收条件”executor执行完先自查不满足就反馈给planner调整。用一句话区分任务像“做菜”且菜谱清晰就用Plan-and-Execute连菜谱都不知道得边看食材边摸索就用ReAct。3. 进阶模式记忆、反射与多智能体协作3.1 带记忆的对话模式状态从哪来Agent跑起来就会产生状态如果全部堆在messages里上下文窗口迟早被撑爆。我常用的方案是“向量检索摘要改写”。任务开始前根据当前输入检索相关历史拼进context任务结束后把这轮关键信息压缩成结构化记录再写入记忆库def agent_with_memory(task, memory_store, llm_func, top_k3): records memory_store.search(task, top_k) memory_text \n.join(f[{r.time}] {r.summary} for r in records) messages [{ role: user, content: fRelated history:\n{memory_text}\n\nCurrent task: {task} }] answer llm_func(messages) memory_store.add(summarycompact_summary(task, answer, llm_func)) return answer这个模式的关键不是向量库选型而是什么时候写、怎么写。把原始对话直接塞进向量库检索出来多半是噪音。我让LLM在每次任务结束后把“用户目标、最终结果、关键限制条件”压缩成三行摘要再入库检索更干净。top_k也别设太大对话任务里最相关的历史通常只有两三条top_k超过10反而让模型分不清主次。我一般设3到5同时给每条记忆加时间戳。3.2 反射与自我修正模式让Agent学会复盘反射模式是在Agent给出答案后再让模型或校验工具对答案做审查发现问题就重新生成。最常见的实现def run_reflective(task, llm_func, rounds2): answer llm_func(task) for _ in range(rounds): critique llm_func(f审查以下答案的问题\n{answer}) answer llm_func(f根据审查意见改写答案\n{critique}) return answer但直接这么用模型往往看不出自己问题critique经常是“内容完整”这种空话。我把反射分成两类基于规则的反射让模型按明确清单检查本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价