ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Agent架构优化:System One Model与LLM分层设计实践

Agent架构优化:System One Model与LLM分层设计实践 1. 从一次线上事故说起为什么“全交给大模型”迟早出事去年冬天我负责的一个客服工单自动分类 Agent 上线第三周出了个不大不小的事故。用户提交了一条“我要退订上个月误扣的会员费”模型给出的分类是“账户咨询”置信度 0.91然后 Agent 直接调用了“发送账户帮助文档”的工具把用户晾在那儿干等了四十分钟。事后复盘问题不在模型本身——它确实读懂了语义问题在于我们把“判断该不该动手”“动手前要不要再确认”“置信度多高才允许执行”这些决策全部塞给了同一个大模型。这就是标题里那个问题的现实版本Agent 里为什么不该什么都交给大模型大模型擅长的是语义理解、意图识别、文本生成但它不擅长的是确定性决策、状态管理、边界控制。你让它既当大脑又当手脚还当裁判它就会在某个你没预料到的输入上用一个“看起来合理”的置信度做出一个“实际很离谱”的动作。Jev 给出的新答案核心思路其实不复杂把 Agent 拆成两层——System One Model 负责快速、确定、低成本的决策LLM 负责慢速、开放、高成本的推理。这个命名借用了认知心理学里“系统一/系统二”的概念System One 是直觉式的、模式化的、几乎不耗能的反应LLM 则是需要调动注意力、逐步推理的“系统二”。下面我把这套思路拆开讲包括它为什么成立、怎么落地、踩过哪些坑。2. 拆解 Jev 的核心主张System One Model 到底在管什么2.1 大模型在 Agent 里的三个“越权”现场先看清楚问题才能理解方案。我在实际项目里观察到的“什么都交给大模型”导致的典型问题集中在三个地方。第一路由决策被大模型接管。用户说了一句话Agent 要先判断这是“查询类”“操作类”还是“闲聊类”然后决定走哪条链路。很多团队的做法是把所有候选意图塞进 prompt让模型输出一个分类标签。问题是当候选意图超过 15 个、且存在语义重叠时模型的分类稳定性会明显下降。我实测过一个 22 类意图的分类任务同一个输入连续跑 10 次有 3 次给出了不同的标签。这种抖动在演示时看不出来上线后就是随机故障。第二工具调用的参数校验被跳过。模型决定调用“退款”工具参数是order_id和amount。它可能从上下文里抽出一个看起来像订单号的字符串但那个字符串其实是用户上一句话里提到的快递单号。如果你不在模型之外做一层确定性校验这个错误会直接打到后端接口。第三终止条件由模型“感觉”决定。Agent 循环什么时候停很多实现是让模型输出一个done标记。但模型有时候会在任务没完成时输出done有时候会在该停的时候继续绕圈。我见过一个 Agent 在“查天气”任务里循环了 7 次每次都重新调用同一个工具因为模型觉得“再确认一下更稳妥”。这三个问题的共同点是它们本质上不是语言问题而是控制流问题。控制流需要的是确定性、可测试、可审计而大模型恰恰在这三点上最弱。2.2 System One Model 的定位不是小模型是“确定性层”这里要先澄清一个常见误解。很多人一听“System One Model”第一反应是“哦就是换个小模型来跑快一点”。不完全是。Jev 这套思路里System One Model 的核心不是“小”而是“确定”。它可以是规则引擎可以是有限状态机可以是一个轻量分类器甚至可以是几个 if-else。关键特征是同样的输入永远给出同样的输出执行成本极低行为完全可预测、可单测。它承担的是 Agent 的“脊髓反射”——不需要思考就能完成的动作。我用一个生活类比来解释这个分工。你开车时看到红灯踩刹车这个动作不需要“思考”是条件反射由脊髓和低位神经完成。但“今天走哪条路能避开拥堵”需要调用导航、比较路况、权衡时间这是大脑皮层的工作。如果你把踩刹车也交给大脑皮层去“推理”反应速度会慢到出事。Agent 也一样高频、确定、边界清晰的决策必须下沉到 System One 层LLM 只处理真正需要语义推理的部分。2.3 两层之间的边界怎么划一个可操作的判断标准边界划在哪里是这套方案成败的关键。我总结了一个在实际项目里反复验证过的判断标准用三个问题来筛判断问题归 System One归 LLM这个决策有唯一正确答案吗有规则明确没有需要语义判断出错成本高吗高必须确定性可容忍一定波动调用频率高吗高每轮都跑低必要时才跑需要理解自然语言吗不需要结构化输入需要原始文本输入举个具体例子。“用户消息是否包含手机号”这个问题有唯一答案正则能判、出错成本高判错会泄露隐私、频率高每条消息都要判、不需要语义理解——四个条件全指向 System One。而“用户这句话表达的深层诉求是什么”这个问题没有唯一答案、需要语义理解归 LLM。注意边界不是一次划定的而是随着你发现新的失败案例不断调整的。我建议每处理一个线上 bad case就问一句“这个决策能不能下沉到 System One”能下沉就下沉。三个月下来LLM 的调用量通常会降 40% 以上稳定性反而提升。3. 落地架构把 Agent 拆成“反射层 推理层”3.1 整体分层设计理解了边界来看整体架构。我实际落地的版本大致分四层从下到上依次是第一层输入规范化层。这一层完全不用模型做的是文本清洗、敏感信息脱敏、格式标准化。比如把全角标点转半角、把连续空格压缩、把手机号和身份证号替换成占位符。这一层用纯代码实现跑得飞快而且保证了后面所有环节拿到的都是干净输入。第二层System One 决策层。这是核心。它接收规范化后的输入输出三类结果之一直接命中某个确定性规则比如“包含退款关键词且订单号格式合法”、需要升级给 LLM 处理、或者直接拒绝比如命中风控规则。这一层用规则引擎加轻量分类器实现我用的组合是正则 关键词加权 一个 3 层的小型文本分类网络。第三层LLM 推理层。只有 System One 层判定“需要升级”的请求才会到这里。LLM 负责的是开放域理解、多轮上下文推理、生成自然语言回复。它的输出不是直接执行而是回到 System One 层做校验。第四层执行与校验层。所有工具调用、状态变更、对外输出都必须经过这一层的确定性校验。校验内容包括参数格式、权限边界、幂等性检查、频率限制。这个架构的关键在于LLM 永远不直接接触执行层。它的输出必须穿过 System One 层的校验才能落地。这就把“模型幻觉导致误操作”的风险挡在了外面。3.2 System One 层的三种实现方式与选型System One 层具体用什么实现取决于你的场景复杂度。我按从简到繁列三种你可以对号入座。方式一纯规则引擎。适合意图数量少于 10 个、边界清晰的场景。用正则、关键词、简单的布尔组合就能覆盖 80% 的请求。优点是零依赖、零延迟、完全可测。缺点是维护成本随规则数量增长而上升规则之间容易冲突。我的经验是规则超过 50 条就该考虑升级到方式二。方式二规则 轻量分类器。这是我目前最推荐的组合。规则处理高确定性的部分比如格式校验、关键词命中分类器处理规则覆盖不到的模糊地带。分类器不需要大我用的是一个基于字符 n-gram 的朴素贝叶斯加一个 3 层全连接网络模型文件不到 2MB单次推理 3 毫秒以内。训练数据从历史 LLM 调用日志里挖标注成本很低。方式三小型预训练模型微调。当你的场景需要一定的语义泛化能力但又不值得动用大模型时可以微调一个 1 亿参数级别的小模型。比如把 BERT-base 微调成意图分类器推理延迟在 20 毫秒左右准确率能到 95% 以上。代价是需要标注数据和训练流程适合有稳定数据积累的团队。选型的核心原则是能用规则就不用分类器能用小分类器就不用微调模型。每往上升一级维护成本和不确定性都增加一个量级。3.3 LLM 层的“最小权限”原则LLM 层要遵守最小权限原则。具体来说我做了三件事。第一LLM 拿不到原始敏感数据。进入 LLM 的文本已经过脱敏手机号变成[PHONE]订单号变成[ORDER_ID]。模型只需要理解语义不需要看到真实值。真实值在 System One 层做参数填充时才注入。第二LLM 的输出被约束在结构化格式里。我不让模型自由输出自然语言然后去解析而是要求它输出 JSON并且用 schema 校验。校验不过的直接打回重试重试两次还不过就降级到兜底回复。这样做的另一个好处是模型输出的每个字段都能被 System One 层逐项校验。第三LLM 没有直接的工具调用权限。它只能“建议”调用某个工具实际调用由 System One 层根据校验结果决定是否执行。这中间加了一层“提议-审批”机制虽然多了一次往返但把误操作率降到了接近零。4. 实操过程从零搭一个两层 Agent4.1 第一步把现有 Agent 的决策点全部列出来不要一上来就写代码。先做审计。把你现有 Agent 里所有“需要做判断”的地方列成一张表。我当时的清单有 23 项包括意图分类、实体抽取、工具选择、参数填充、循环终止判断、回复生成、敏感词过滤、置信度阈值判断等等。列完之后对每一项用 2.3 节的四个问题过一遍标记归 System One 还是 LLM。这一步做完你会发现至少一半的决策点其实不需要大模型。我那 23 项里有 14 项被划到了 System One。4.2 第二步为 System One 层建立可测试的规则集规则集的核心要求是可单测。每一条规则都要有对应的测试用例包括正例、反例、边界例。我用的是 pytest每条规则至少 5 个用例。这样做的好处是当你新增规则时能立刻发现是否和已有规则冲突。规则的组织方式我建议按“决策类型”分组而不是按“业务模块”分组。比如所有“格式校验类”规则放一起所有“权限判断类”规则放一起。因为同一类型的规则往往有相似的边界条件放一起便于统一维护。# 示例System One 层的规则校验骨架 import re class SystemOneGate: def __init__(self): self.phone_pattern re.compile(r1[3-9]\d{9}) self.order_pattern re.compile(rORD\d{12}) def normalize(self, text: str) - str: # 脱敏 格式标准化 text self.phone_pattern.sub([PHONE], text) text self.order_pattern.sub([ORDER_ID], text) return text.strip() def route(self, text: str) - dict: # 返回确定性路由结果 if self._hit_risk_rule(text): return {action: reject, reason: risk} if self._hit_direct_rule(text): return {action: direct, handler: ...} return {action: escalate, reason: need_llm}4.3 第三步设计 LLM 与 System One 的交互协议交互协议要解决三个问题LLM 什么时候被调用、它返回什么、返回后怎么校验。我的做法是定义一个严格的请求-响应契约。请求侧System One 层把脱敏后的文本、当前会话状态摘要、可用工具列表只给名称和参数 schema不给实现打包发给 LLM。响应侧LLM 必须返回一个固定结构的 JSON{ intent: refund_request, confidence: 0.87, suggested_tool: process_refund, tool_params: {order_id: [ORDER_ID], reason: duplicate_charge}, need_clarification: false, reply_text: ... }System One 层拿到这个 JSON 后逐项校验intent 是否在允许列表内、confidence 是否超过阈值、suggested_tool 是否有权限、tool_params 的格式是否合法、order_id 是否真实存在。任何一项不过就走降级流程。提示confidence 阈值不要设死。我最初设 0.8结果大量正常请求被降级。后来改成按 intent 动态设阈值——高风险操作退款、删除设 0.95低风险操作查询、推荐设 0.6。这个调整让降级率从 18% 降到了 4%。4.4 第四步建立降级与兜底链路降级链路是这套架构的安全网。我设计了三层降级第一层LLM 输出校验失败重试一次。重试时在 prompt 里附上上次失败的原因让模型自我修正。实测重试能把 60% 的格式错误救回来。第二层重试仍失败降级到规则兜底。用 System One 层里最保守的规则给出一个安全回复比如“我暂时无法处理这个请求已为您转接人工”。这个回复不追求体验只保证不出错。第三层兜底也异常直接熔断。记录完整上下文返回统一错误码触发告警。这一层是防止系统性故障的最后一道闸。4.5 第五步灰度上线与指标监控不要一次性全量切换。我的做法是先用 5% 流量跑新架构对比新旧两套的指标。核心监控指标有四个任务完成率、误操作率、平均响应延迟、LLM 调用量。前两个看质量后两个看成本。灰度期间我重点关注的是“误操作率”这个指标。因为新架构的核心价值就是把误操作压下去。实测数据是旧架构误操作率 2.3%新架构 0.4%降了将近 6 倍。LLM 调用量降了 52%平均延迟从 1.8 秒降到 0.9 秒。这些数字是我决定全量切换的依据。5. 常见问题与排查技巧实录5.1 System One 层规则冲突了怎么办规则冲突是必然会遇到的。典型场景是一条规则说“包含‘退款’就路由到退款流程”另一条规则说“包含‘查询’就路由到查询流程”而用户说“查询我的退款进度”两条都命中。我的处理原则是优先级 互斥标记。每条规则带一个优先级数字命中多条时取优先级最高的。同时给规则加互斥组标记同一互斥组内只允许一条生效。上面这个例子里“退款进度查询”应该单独定义一条规则优先级高于前两条并且和前两条互斥。排查冲突的工具我推荐做一个规则命中日志每次路由都记录命中了哪些规则、最终选了哪条。出现异常时直接查日志比读代码快得多。5.2 LLM 返回的 JSON 解析失败率高怎么优化解析失败通常有三个原因模型输出了多余的解释文字、JSON 格式不合法、字段缺失。对应三个解法。多余文字在 prompt 里明确要求“只输出 JSON不要任何其他内容”并且在解析前用正则先提取第一个{到最后一个}之间的内容。格式不合法用支持 JSON mode 的模型接口或者在 prompt 里给出严格的 schema 示例。我实测给出完整示例能把格式错误率降低 70%。字段缺失在 schema 校验时对每个必填字段做检查缺失的字段用默认值填充并记录而不是直接失败。这样能把一部分“部分失败”转化成“可用结果”。5.3 怎么判断一个决策该不该下沉到 System One这个问题我在 2.3 节给了判断标准但实操中还有一个更简单的经验法则如果一个决策的失败模式是“可枚举的”就下沉如果是“不可枚举的”就留给 LLM。举个例子。“判断用户是否在骂人”这个决策失败模式是可枚举的漏判、误判而且可以用关键词加分类器覆盖大部分情况适合下沉。“判断用户这句话背后的真实情绪和诉求”这个决策失败模式不可枚举因为情绪和诉求的组合是开放的留给 LLM。5.4 常见问题速查表问题现象可能原因排查方向解决手段同一输入路由结果不稳定决策还在 LLM 层检查路由日志下沉到 System OneLLM 调用量居高不下边界划得太宽统计各决策点调用频次重新审计决策点误操作率没降校验层缺失或太松检查执行前校验逻辑加严参数校验响应延迟反而升高System One 层太重看各层耗时分布精简规则、加缓存降级率过高阈值设置不合理看降级原因分布按 intent 动态调阈值规则维护越来越难规则数量超阈值统计规则条数升级到分类器方案5.5 几个我踩过的坑坑一把 System One 层做成了“小 LLM”。我一开始想省事用一个小模型来做 System One 决策结果发现小模型同样有不确定性问题只是程度轻一点。后来改回规则加分类器才真正做到确定性。教训是System One 层的核心是确定性不是智能。坑二脱敏做在了 LLM 调用之后。有一次排查日志发现真实手机号出现在了 LLM 的请求记录里。原因是脱敏逻辑写在了 LLM 调用之后。这个顺序错误很隐蔽因为功能上没问题但隐私上是大事故。后来我把脱敏强制放在输入规范化的第一步并且加了断言检查。坑三忽略了 System One 层本身的性能。规则多了之后如果每条规则都用正则全量匹配延迟会累积。我的优化是给规则加索引按首字符或关键词先做粗筛只对候选规则做精细匹配。这个优化把 System One 层的耗时从 15 毫秒降到了 3 毫秒。坑四没有给 LLM 的回复做二次校验。LLM 生成的回复文本里可能包含它自己编造的订单号或金额。我后来加了一道校验回复文本里出现的所有数字和 ID必须能在 System One 层的真实数据里找到对应找不到就替换成占位符或走兜底。这道校验拦住过好几次“模型一本正经胡说八道”的情况。6. 这套架构适合谁以及后续可以怎么扩展如果你正在做 Agent 开发且遇到了“模型行为不稳定”“误操作率高”“调用成本压不下来”这几个问题中的任何一个这套两层架构值得试。它不依赖特定的大模型也不要求你换框架本质上是在你的 Agent 和 LLM 之间加一层确定性的“反射层”。后续扩展有几个方向。一是把 System One 层的决策日志积累起来反过来训练更准的分类器形成数据飞轮。二是把校验层做成可配置的策略引擎不同业务线用不同策略不用改代码。三是把降级链路做成可观测的每次降级都记录完整上下文方便持续优化边界。我个人在实际操作中的体会是这套架构最大的价值不是省了多少调用量而是让 Agent 的行为变得可解释、可测试、可回滚。以前出了 bad case只能猜是模型哪根筋搭错了现在能精确定位到是 System One 的哪条规则、还是 LLM 的哪个字段校验没过。这种可观测性比单纯的性能提升重要得多。
返回列表