1. 从单次调用到多步编排:Agent工作流架构到底解决什么问题
这两年做大模型应用,我最深的体感是:很多人一开始把Agent想得太"玄",觉得只要把Prompt写好、模型够强,什么都能干。真到了生产环境才发现,单次调用根本撑不起复杂的业务——模型输出不稳定、上下文塞不下、工具调用容易断、用户一句话里藏着好几个意图,靠一次"请完成以下任务"的提示词,结果必然是碰运气。
Agent工作流架构解决的正是这个问题:它不是让模型"一把梭",而是把一个大任务拆成多个小步骤,每一步各司其职,再用明确的编排方式串联起来。目前项目里用得最多的三条路线,就是标题里说的增强型(Augmented)、**链式(Chain)和路由式(Routing)**架构。
用大白话理解这三者的区别:
- 增强型:还是"问一句答一句"的结构,但给单次调用配上了外部检索、工具调用、记忆等增强能力,相当于给一个人配了计算器、词典和笔记本。
- 链式:把任务分解成多个依次执行的节点,前一个节点的输出是后一个节点的输入,相当于一条流水线。
- 路由式:先判断问题属于哪一类,再分发到不同的处理流程,相当于前台分诊,再决定挂哪个科室。
这三者不是互斥的,实际项目里经常混合使用。但要混合得好,前提是先把每一种架构的工作原理、优缺点、适合场景吃透。我用一个模拟项目(一个内部知识库问答助手)贯穿全文,走一遍三种架构的选型和演进过程。这个项目的真实需求很典型:员工提问,系统要从多份文档里找答案,还要区分"政策咨询""技术故障""闲聊寒暄"等不同场景,并给出不同格式的回复。
2. 增强型架构:模型还是那个模型,但每一步都被"配齐装备"
2.1 增强型架构的核心组成
增强型架构是所有Agent工作流的"地基"。它不改变"模型接收输入、生成输出"这个基本链路,而是围绕单次调用增加三样东西:检索增强、工具增强、记忆增强。
关于这三种增强方式,可以看一张简单的对照表:
| 增强方式 | 解决什么问题 | 典型实现 | 类比 |
|---|---|---|---|
| 检索增强(RAG) | 模型不知道你的私有知识 | 向量检索 + 文档切片 + 重排 | 考试时允许翻书 |
| 工具增强 | 模型只能生成文字,不能操作外部世界 | 函数调用(Function Calling) | 给分析师配了计算器和电话 |
| 记忆增强 | 模型不记得上一次对话 | 外部存储 + 上下文压缩 | 给小助理配了笔记本 |
这三者可以单独用,也可以叠加。我的经验是:RAG 永远是增强型的第一个选择,因为它解决的是最痛的问题——模型训练时的知识截止日期和私有数据隔离。比如员工问"年假制度是什么",直接问模型大概率得到一段通用答案,但企业内部的年假规则往往是特殊的,必须从公司文档里检索。
2.2 项目里的实测:用一个RAG节点给模型装上"外挂"
我在模拟项目X里做的第一步,就是给单次调用加上检索增强。技术选型如下:
- 文档处理:PDF和Word统一转为纯文本,按标题层级做结构化解构,切片大小为512字符,相邻切片重叠64字符。
- 向量化模型:中文场景下优先选择支持768维向量输出的模型,我用了开源的中文向量模型;向量数据库是常用的轻量方案。
- 检索策略:先做向量召回top 50,再用重排模型精排取top 5。
这里有一个值得展开的操作细节:检索并不是"把文档塞进向量库"就完事。切片方式直接决定召回质量。一开始我按固定字符数硬切,结果很多问题的答案被拦腰截断。后来改成按语义段落切,每段控制在300到600字,效果立刻改善。原因是LLM对上下文的理解依赖完整语义块,硬切会把"制度条款+解释说明"这对完整语义拆散。
这个增强节点的实际调用流程:
def augmented_query(question: str, top_k: int = 5) -> str: # 1. 问题向量化 question_emb = embed(question) # 2. 向量召回 + 重排,得到候选文档块 candidates = vector_db.search(question_emb, top_k=50) ranked = rerank(question, [c.text for c in candidates])[:top_k] # 3. 拼接上下文,生成提示词 context = "\n\n---\n\n".join([c.text for c in ranked]) prompt = build_prompt(question, context) # 4. 单次调用大模型 return llm_chat(prompt)关键点在第三步:上下文拼装时,要显式告诉模型哪些内容来自检索结果,哪些内容是用户问题。因为检索出的文档块里可能含有矛盾信息,如果不在提示词里做隔离,模型会更倾向于信任最后看到的文本。
2.3 为什么说增强型架构是"另一个问题"的解题思路
增强型架构最大的价值,是在不改变模型和任务结构的前提下,把"不知道"变成"知道"。但它有明显的天花板:它仍然是一次性的单向对话。模型接收输入生成输出,无论生成质量多高,它都没有"先做完一步、根据结果再去规划下一步"的能力。
比如员工问"帮我对比不同部门的调休政策并给出建议",这个问题本身至少包含三个子任务:检索政策、对比差异、生成建议。增强型架构只能一次性把所有文档塞进上下文,模型要在一次输出里完成全部推理。结果是输出结构不稳定,时好时坏。
所以增强型架构适合的场景是:问题边界清晰、答案主要依赖外部知识、不需要多轮工具操作的问答。一旦任务在逻辑上需要"分步走",就得往链式架构演进。
3. 链式架构:把一个复杂任务拆成一串有依赖关系的节点
3.1 为什么要把Prompt流程化
链式架构是Agent工作流里最直观、也最容易被低估的一种模式。它的思路非常朴素:把任务拆成多个步骤,每个步骤由一个(或多个)模型调用/工具调用完成,上个步骤的输出作为下个步骤的输入。就像工厂里的流水线——每道工序只做一件事,但整条线可以完成单个工人做不了的产品。
我用模拟项目X验证过一条完整的链:意图识别 → 信息提取 → 策略匹配 → 草稿生成 → 格式检查 → 输出。单看每一步都很简单,但串联起来后,模型做每一步时都只需要关注一个子目标,输出质量明显提升。模型不需要"一口气想清楚所有事情",而是把"想清楚"拆到每一个节点里。
链式架构还有一个容易被忽视的好处:可观测性。单体Prompt调用,输入输出只有一黑盒;链式架构里,每个节点都可以单独记录输入输出、耗时、成功失败。一旦出问题,就能定位到具体是哪一步,而不是对着一个巨大的调用栈猜。
3.2 一个多步链的完整结构
我用一个"技术故障工单自动流转"的例子说明。这个场景是:员工提交故障描述,系统需要判断故障类型、分配优先级、生成处理建议、并输出一份工单摘要。
链的第一版结构如下:
节点1: 问题分类(模型调用,输出结构化JSON) 节点2: 紧急程度判断(代码逻辑 + 模型辅助) 节点3: 解决方案检索(RAG检索) 节点4: 工单内容生成(模型调用) 节点5: 格式与合规校验(规则引擎 + 模型校验)每个节点需要明确三个东西:输入Schema、处理逻辑、输出Schema。我踩过的坑是,一开始没有强制所有节点都输出结构化数据,导致下游节点拿到一堆非结构化文本,解析困难,错误率很高。后来统一约定:每个节点输出必须是JSON,且带有版本号字段,下游节点根据版本号做兼容解析。这一步让整条链的错误率降了一个数量级。
3.3 链式架构的依赖设计
链子不是随便串的,节点之间的依赖关系是架构设计的核心。常见的依赖形态有三种:
- 顺序依赖:后节点必须等前节点,比如先生成草稿再检查格式。
- 条件依赖:只有满足某些条件才走到下一节点,比如分类结果是"网络故障"才检索网络相关解决方案。
- 并行依赖:多个节点互不依赖,可以并行执行,最后再汇总,比如同时检索政策文档和员工请假记录。
顺序依赖实现最简单,但容易在链条过长时拖慢响应。条件依赖相当于在链中埋了分支逻辑。并行依赖能显著降低延迟,但对架构的编排能力要求更高。
我在模拟项目X里做了一次性能对比。同样是20个测试问题,纯顺序链的平均响应时间约7.2秒,加入并行节点后降到4.1秒,其中时间主要省在了同时检索三个不同数据源这一步。需要注意加权:并行不是银弹,如果单个数据源检索特别慢,并行反而会拖累整体。
3.4 链式架构的适用边界
链式架构对"任务结构清晰"的问题是神器。它的两大前提是:节点职责能分清楚,以及节点之间的数据契约能定义出来。
一旦任务本身没法提前拆解,或者拆解方案要依赖模型的输出动态调整,链式架构就会显得僵化。比如用户抛出一个开放性问题:"帮我想个团建方案",你很难预先定义"第一步做什么、第二步做什么",因为不同的用户需求可能走向完全不同的流程。这时候就需要引入路由式架构,让系统能动态决定走哪条子链路。
4. 路由式架构:让系统自己决定走哪条处理路径
4.1 路由的本质:把"判断"独立出来
路由式架构的核心思想,是把"走哪条流程"这件事从业务代码和Prompt里拿出来,变成一个独立的决策节点,由模型或规则来做出判断。它解决的问题很明确:当我们同时维护了多条流程链路时,系统怎么知道当前这个请求该进哪条链。
如果不用路由,常见的做法是把所有可能性都塞进一个大Prompt里,让模型"自己看着办"。结果是模型经常在其他类别的指令里迷失,而且每新增一类就要改动主Prompt,成本很高。有了路由节点,主流程变成了:
请求进入 -> 路由节点判断类别 -> 分发到对应子流程 -> 返回结果我做过的一个真实对比:单独一个大Prompt同时处理"政策问答""故障处理""闲聊"三类请求,分类准确率约78%。引入独立路由节点后,每个子流程的Prompt可以专注于自己的任务,整体准确率升到92%。差距来自两类,一是大Prompt内部不同任务的指令互相干扰,二是路由本身就是更明确的子任务。
4.2 路由判断的三种实现方式
路由节点本身可以三种方式实现,各有用武之地:
| 实现方式 | 原理 | 场景 | 优点 | 缺点 |
|---|---|---|---|---|
| 基于规则 | 关键词、正则、代码逻辑 | 意图明确、边界固定 | 快且稳定 | 覆盖面窄,不可泛化 |
| 基于模型分类 | 用小型模型做分类 | 意图范围可控 | 成本低、速度尚可 | 极端类目容易混淆 |
| 基于大模型判断 | 把问题和可选路径描述给大模型 | 类目多、开放性高 | 泛化能力强 | 成本高,延迟高 |
我的建议是先规则、后模型、再大模型。简单场景用规则,复杂场景先用一个嵌入模型分类,再升级到大模型判断。不要在第一步就上大模型,否则任何请求都会白白增加一次——有时候是几次——昂贵的大模型调用。
4.3 我在模拟项目X中的路由实现
模拟项目X做了一版路由式架构,解决的问题:员工可能问政策、问技术故障、也可能随口闲聊。我实现了一个两级路由结构:
def route_request(user_input: str) -> str: # 第一级:规则快速过滤 if "年假" in user_input or "请假" in user_input or "报销" in user_input: return "policy" if "崩溃" in user_input or "连接不上" in user_input or "报错" in user_input: return "tech_support" # 第二级:模型分类兜底 category = classify_with_nlu(user_input) return category这里有个很重要的细节:规则和模型是互补关系,不是替代关系。规则负责拦截高置信度场景,命中率高的同时不费钱;模型负责处理规则覆盖不到的长尾。两级路由在这个项目里的准确率达到96%,而且平均路由耗时不到200毫秒(规则命中时几乎是0延迟)。
路由式架构真正难的不是路由节点本身,而是子流程的编排。每一个路由目标后面,可能挂着不同的链式架构、不同的工具集合。这意味着路由式架构往往和链式架构嵌套使用:路由决定走哪条链,链负责具体的处理。
4.4 路由式架构的难点与陷阱
路由模型如果分错类,整个流程就跑偏,所以路由结果必须有兜底机制。我在项目中加了三重保险:
- 路由节点的输出除了类别,还要带置信度分数,低于阈值就进入"人工确认"流程。
- 当一个子流程连续两次失败时,自动回退到通用流程。
- 所有路由结果都缓存下来,同一问题的重复命中率提高后,后续直接走快捷路径。
路由式架构还有一个容易忽略的点:类目不是越多越好。类目越多,模型分类越容易混淆,且每个类目都需要足够的样例来训练或构建Prompt。我建议路由类目控制在5到8个以内,超过就需要考虑加一层子路由,分而治之。
5. 三种架构的选型判断与混合实践
5.1 三种架构的横向对比
用模拟项目X跑下来的数据,做了一张对比表:
| 维度 | 增强型 | 链式 | 路由式 |
|---|---|---|---|
| 设计思路 | 给单次调用增强能力 | 多节点串行的任务分解 | 动态路径分发 |
| 适用任务 | 知识问答、直接回复 | 结构清晰的多步骤任务 | 多类目请求混合 |
| 复杂度 | 低 | 中 | 中高 |
| 可观测性 | 弱 | 强 | 中 |
| 延迟影响 | 中 | 高(链越长越慢) | 中(路由本身有开销) |
| 维护成本 | 低 | 中 | 高(需维护子流程) |
| 典型失败模式 | 信息不足导致答非所问 | 链节点错误累积 | 路由分错类 |
切勿死记这张表。因为实际生产系统里,它们几乎总是以组合形态出现。关键是理解每一种形态在什么环节提供什么价值。
5.2 最常见的混合套路:RAG + 链式 + 路由
我在模拟项目X最终落地的架构,是一个典型的混合结构:
入口请求 -> 路由节点(规则 + NLU) -> 政策问答子流程:增强型(RAG节点 + 模型生成) -> 技术故障子流程:链式(分类 -> 检索 -> 方案生成 -> 工单输出) -> 闲聊子流程:增强型(轻量记忆 + 模型直答)这个结构的好处是:每种架构都只出现在它最擅长的地方。路由负责"分流",RAG负责"知识供给",链式负责"多步处理"。三个组成部分各司其职,而不是把所有逻辑揉成一团。
5.3 架构选型的三个判断顺序
面对一个新需求,我建议按以下顺序问三个问题:
- 这个请求是单一意图还是多意图?单一意图走增强型,多意图或意图不明走路由式。
- 这个任务能预定义步骤吗?能预定义就拆成链式,每个步骤独立优化、独立观测。
- 知识扮演什么角色?只要答案依赖私有知识,就一定要加RAG节点,不管最终用哪种架构。
这三个问题问完,90%的场景都能找到明确的架构方向。剩下的10%,多靠实际数据迭代。
6. 落地时踩过的那些坑,以及现在我会怎么做
6.1 假设模型"一定"遵循输出格式
这是链式架构初期最典型的坑。我曾经在一个节点上要求模型输出严格JSON,并写了很详细的说明,但实际跑下来,大约有6%的输出带了多余的前缀文字或者注释符号,导致下游解析报错。后来我做了三件事:把提示词里的格式约束收敛成一行精确表述;增加一个轻量级的格式修复节点,当解析失败时自动让模型二次修正;同时把关键字段用正则做校验,校验不过就该节点重试一次。这一套下来,格式相关错误率降到了0.5%以下。
6.2 链子太长导致的错误累积
链式架构最大的风险不是单点失败,而是错误沿着链路逐级放大。第一个节点一个字段提取偏了,到了最后生成的工单内容就完全没法看。解决办法是:链长超过5个节点时,拆分出多个子链,中间插入校验和审计节点;其次,尽可能减少模型调用的次数,能用规则和代码解决的步骤就绝不交给模型。模型每次生成都是一次"概率性事件",把概率事件的数量降到最低,整条链的稳定性才会上去。
6.3 路由的误判往往出在最像的类别上
路由分类在"政策问答"和"技术故障"之间容易混淆,因为两类问题都可能出现"权限""系统"这些词。后来我在路由节点上加了一层关键词加权:对高区分度的词(比如"报错"、"崩溃")给更高权重,对高频干扰词(比如"系统"、"登录")给低权重甚至负权重。效果提升明显。这说明路由不能完全依赖模型语义判断,规则特征依然非常重要。
6.4 别忽略成本与延迟的精细化控制
有些架构在生产环境跑不起来,不是设计不对,而是成本和延迟没有控制好。我见过一个失败的例子:某个团队为了让回答更有"深度",在主流程前加了一个"分析用户意图"的大模型节点,结果每个请求多花2到3元成本、增加2秒延迟,实际收益却很小。后来去掉这个节点,直接把原始输入喂给下游,效果几乎不变。现在我会遵守一条原则:每一步都要问自己,这个节点是"必须"还是"锦上添花"。锦上添花的节点默认不建,除非有数据证明它的价值。
我之前某个项目配置了很多辅助功能,包括计划任务、消息队列、定时提醒、自动重试等,后来梳理的时候发现其中一部分的功能早就被主流程吞掉了,留着反而是负担。
6.5 关于架构演进,我现在的实际体会
把这个模拟项目从零搭到上线,最大的体会是:架构不是一开始就设计出来的,而是被需求和数据推着长出来的。第一个版本可能就是一个RAG增强节点,能回答问题就上了线;接着数据反馈说分类不准确,加了路由;再后来发现故障处理流程需要多步协作,慢慢长出了链式结构。这个演进路径在绝大多数Agent项目里都是相似的。
所以如果你现在也正面临Agent工作流的设计,我的建议是:不要试图第一步就把增强型、链式、路由式全都铺好。先跑通一个最简单的增强型闭环,把数据采集起来,让真实业务需求来告诉你下一步该加链式还是路由。架构是为业务服务的,不是用来展示技术审美的。把每一步的输入、输出、错误、耗时都记录好,等数据积累到一定程度,架构的演进方向会变得非常清晰。