☰
Agent开发避坑指南:System One Model与LLM职责分离实践
2026/9/29 18:04:28 网站建设 项目流程

1. 从“什么都问大模型”说起:Agent 设计的核心误区

做 Agent 开发的人,几乎都经历过一个阶段:手里有了一个能力还不错的大模型,就恨不得把所有的判断、决策、执行都塞进 prompt 里,让模型一次性搞定。我最早做 Agent 项目的时候也是这样,一个请求进来,先让模型理解意图,再让模型规划步骤,再让模型决定调哪个工具,再让模型解析工具返回结果,最后让模型生成回复。整条链路下来,一次用户交互可能要调用五六次大模型,延迟高得离谱,成本也压不住,而且稳定性极差——模型稍微“发挥”一下,整个流程就崩了。

这个问题的本质,其实不是模型不够强,而是我们把不该交给大模型的事情也交给了它。大模型擅长的是语义理解、模糊匹配、自然语言生成这类“软”任务,但 Agent 系统里还有大量“硬”任务——状态管理、流程控制、条件分支、重试逻辑、参数校验——这些东西用代码写只需要几行,交给模型反而变得不确定。Jev 这个项目给出的新答案,核心思路就是:把 System One Model 和 LLM 的职责分开,让该确定的地方确定,该灵活的地方灵活。

这篇文章适合正在做 Agent 开发、被大模型调用链路折磨过的工程师,也适合刚开始接触 Agent 框架、想搞清楚“到底什么该交给模型、什么不该”的初学者。我会从设计思路、核心机制、实操落地、问题排查几个维度,把 Jev 这套方案拆开讲清楚,尽量让你看完就能在自己的项目里用起来。

2. Agent 架构的核心矛盾:确定性 vs 灵活性

2.1 为什么“全交给大模型”一定会出问题

先说一个我踩过的真实坑。之前做一个客服 Agent,用户输入“帮我查一下上周的订单,如果还没发货就取消”。这个需求拆开看有三步:查订单、判断发货状态、条件取消。我当时的做法是把这三步全部写进 system prompt,让模型自己规划。结果测试的时候发现,模型有时候会跳过“判断发货状态”直接取消,有时候会把“上周”理解成“最近七天”而不是“上一个自然周”,还有时候工具返回了错误码它却当成成功继续往下走。

这些问题的根源在于:大模型的输出是概率性的,而 Agent 的流程控制需要确定性。你让模型做语义理解没问题,它确实比正则表达式强;但你让模型做“如果 A 则 B 否则 C”这种逻辑判断,它每次都可能给你不同的答案。更麻烦的是,当工具调用失败时,模型不一定能正确识别错误并重试,它可能会编一个结果继续往下走。

Jev 的思路很直接:把 Agent 的执行过程拆成两层,一层是确定性的编排层,一层是模型驱动的决策层。编排层用代码写死流程、状态、重试、校验,决策层只在真正需要语义理解的地方调用 LLM。这样既保留了模型的灵活性,又保证了系统的稳定性。

2.2 System One Model 到底解决什么问题

Jev 里提到的 System One Model,名字借用了认知科学里“系统一”的概念——快速、直觉、自动化的思考方式。在 Agent 语境下,它指的是一个轻量级的、专门负责快速决策的模型或规则引擎,用来处理那些不需要深度推理的任务。

举个例子,用户说“帮我订明天去北京的机票”。传统做法是把这句话丢给大模型,让它解析出意图、时间、目的地、动作。但 Jev 的做法是:先用 System One Model 做一层快速匹配——识别出“订机票”这个意图,提取“明天”“北京”这两个槽位,然后直接走预设的订票流程。只有当用户说“帮我安排一下下周的行程,顺便看看有没有合适的航班”这种模糊表达时,才把请求交给 LLM 做深度理解。

这样做的好处很明显:大部分常见请求走快速通道,延迟从几秒降到几百毫秒,成本从几分钱降到几乎为零。只有真正复杂的、模糊的请求才走大模型,整体资源消耗大幅下降。而且因为快速通道是确定性的,不会出现“模型今天心情不好就理解错了”的情况。

2.3 两层架构的职责边界怎么划

划边界的原则其实就一句话:能用规则解决的问题,不要用模型;能用小模型解决的问题,不要用大模型;只有必须用大模型的地方,才用大模型。

具体来说,下面这些任务适合放在 System One Model 层:

  • 意图分类:用户这句话是要查订单、退款、还是咨询
  • 槽位提取:时间、地点、数量、金额这些结构化信息
  • 流程路由:根据意图直接跳转到对应的处理流程
  • 参数校验:检查必填字段是否齐全、格式是否正确
  • 状态管理:当前处于流程的哪一步、下一步该做什么

而下面这些任务才需要交给 LLM:

  • 模糊语义理解:用户表达不完整、有歧义、带隐喻
  • 多轮对话中的上下文推理:用户说“就那个”,需要结合历史判断指代
  • 自然语言生成:把结构化结果转成流畅的回复
  • 复杂规划:需要多步推理、权衡取舍的决策
  • 异常处理:遇到没见过的输入,需要模型兜底

这个边界不是一成不变的,随着你的 System One Model 覆盖的场景越来越多,需要调用 LLM 的比例会越来越低。Jev 的设计里,这个比例是可以动态调整的,这也是它比传统“全 LLM”方案更实用的地方。

3. Jev 的核心机制拆解:怎么做到“该省的省,该花的花”

3.1 快速通道:规则引擎 + 轻量模型

Jev 的快速通道不是简单的 if-else,而是一个可配置的规则引擎加上一个轻量级的分类模型。规则引擎负责处理那些模式固定的请求,比如“查订单”“退款”“改地址”这些高频意图,直接用关键词匹配或者正则就能搞定。轻量模型负责处理规则覆盖不到的边缘情况,比如用户换了一种说法但意思差不多。

我实测下来,一个训练得当的小模型(参数量在百兆级别)在意图分类任务上能做到 95% 以上的准确率,而推理成本只有大模型的几十分之一。Jev 的做法是把这个小模型和规则引擎串起来:先走规则,规则命中就直接返回;规则没命中,走小模型;小模型置信度低于阈值,才升级到大模型。

这个阈值怎么定?我的经验是从 0.8 开始调。阈值太高,大量请求会升级到大模型,省不了钱;阈值太低,小模型误判率上升,用户体验变差。你可以先跑一批真实数据,画出准确率和覆盖率的曲线,找到那个拐点。Jev 的配置里这个阈值是暴露出来的,方便你根据业务场景调整。

3.2 升级机制:什么时候该把请求交给大模型

升级机制是 Jev 里我觉得最巧妙的部分。它不是简单地“小模型搞不定就升级”,而是有一套多级触发条件:

  • 置信度触发:小模型输出的概率低于阈值
  • 规则触发:请求里包含特定关键词,比如“投诉”“紧急”“人工”
  • 轮次触发:多轮对话超过 N 轮还没解决
  • 异常触发:工具调用返回错误、参数校验失败
  • 用户触发:用户明确说“转人工”或者表达不满

这些触发条件可以组合使用,Jev 的配置里用的是一个优先级队列,高优先级的条件先检查。比如用户说“转人工”,不管小模型置信度多高,直接升级。这样做的好处是既保证了效率,又不会在关键时刻掉链子。

我自己的项目里还加了一个“学习触发”:每次大模型处理完一个请求,把输入和输出存下来,定期用来微调小模型。这样小模型的能力会越来越强,升级到大模型的比例会越来越低。Jev 虽然没有内置这个功能,但它的架构留了扩展点,你可以自己接一个数据管道进去。

3.3 状态管理:Agent 的“记忆”不该放在 prompt 里

很多 Agent 项目把对话历史、用户信息、流程状态全部塞进 prompt,导致 prompt 越来越长,成本越来越高,而且模型还容易“忘记”前面的内容。Jev 的做法是把状态管理从 prompt 里抽出来,放到独立的存储层。

具体来说,Jev 用一个状态机来管理流程。每个用户会话对应一个状态实例,记录当前处于哪个节点、已经收集了哪些信息、下一步该做什么。当需要调用 LLM 时,只把当前节点相关的上下文传进去,而不是把整个历史都塞进去。这样 prompt 长度可控,模型注意力集中,输出质量也更稳定。

这个设计的好处我在实际项目里深有体会。之前做一个多轮填单的 Agent,用户要提供姓名、电话、地址、时间四个信息。传统做法是把所有历史对话都传给模型,让它判断还缺什么。结果模型有时候会重复问已经填过的字段,有时候会漏问。改成状态机之后,缺什么字段代码里一清二楚,直接问就行,根本不需要模型判断。只有用户回答的内容需要解析时,才调用模型提取槽位。

3.4 工具调用的确定性编排

工具调用是 Agent 最容易出问题的环节。模型可能调错工具、传错参数、或者对返回结果理解错误。Jev 的方案是把工具调用从模型决策改成编排层决策。

具体怎么做?在流程定义阶段,每个节点就明确指定了“这一步该调哪个工具、参数从哪里来、返回结果怎么处理”。模型只负责在需要的时候提取参数值,不负责决定调哪个工具。比如订机票流程里,“查询航班”这个节点固定调用航班查询接口,参数是出发地、目的地、日期,这些参数从状态机里取,不需要模型决定。

这样做的好处是工具调用的成功率大幅提升。我实测下来,确定性编排的工具调用成功率能到 99% 以上,而模型自主决策的工具调用成功率通常只有 85% 到 90%。别小看这 10 个百分点的差距,在真实业务里意味着每天少几百个失败请求。

当然,有些场景确实需要模型自主选择工具,比如开放式问答或者复杂任务规划。Jev 也支持这种模式,但它建议把自主决策限制在最小范围内,能确定的地方尽量确定。

4. 实操落地:怎么在自己的项目里用这套思路

4.1 从现有 Agent 里识别“不该交给模型”的部分

如果你已经有一个跑着的 Agent 项目,想改成 Jev 这套思路,第一步是做一次调用链路审计。把每次用户请求涉及的大模型调用列出来,逐个问三个问题:

  1. 这次调用是在做语义理解,还是在做逻辑判断?
  2. 这次调用的输出空间是开放的,还是有限的?
  3. 如果这次调用出错,有没有代码层面的兜底?

如果答案是“逻辑判断”“输出有限”“没有兜底”,那这次调用大概率可以改成确定性代码。我自己的项目审计下来,发现大概 60% 的大模型调用是可以去掉的,改成规则或者状态机之后,整体延迟降了 70%,成本降了 80%。

Jev 的文档里给了一个更简单的判断标准:如果你能用一段伪代码描述清楚这个决策的逻辑,那它就不该交给模型。比如“如果用户说的是查订单,就走订单查询流程”这种,用代码写就是一行 if,交给模型反而增加不确定性。

4.2 搭建 System One Model 层的具体步骤

搭建 System One Model 层不需要一开始就上模型,可以分三步走:

第一步,先用纯规则跑通流程。把高频意图和固定模式用关键词、正则、模板匹配覆盖掉。这一步不需要任何模型,纯代码就能做。我建议先覆盖 Top 20 的意图,这些通常能占到 80% 的请求量。

第二步,引入轻量分类模型。当规则覆盖不到的长尾请求多起来之后,训练一个小模型来做意图分类和槽位提取。数据来源就是之前大模型处理过的请求日志,标注好意图和槽位,用几百到几千条数据就能训出一个可用的模型。Jev 支持接入 HuggingFace 上的小模型,也可以用 ONNX 做本地推理,延迟能控制在 50 毫秒以内。

第三步,建立升级机制。给小模型的输出加一个置信度阈值,低于阈值就升级到大模型。同时加上前面说的那些触发条件,保证特殊情况能及时升级。这一步的关键是阈值要可配置、可监控,上线后根据实际数据持续调整。

4.3 状态机的设计与实现要点

状态机是 Jev 架构里的核心组件,设计好坏直接影响系统稳定性。我总结几个实操要点:

状态粒度要适中。太粗会导致一个状态里做太多事,模型调用次数增加;太细会导致状态数量爆炸,维护成本高。我的经验是一个状态对应一个用户可感知的步骤,比如“询问出发地”“询问目的地”“确认订单”各是一个状态。

状态转移条件要明确。每个状态到下一个状态的转移条件必须用代码写清楚,不能依赖模型判断。比如“用户提供了有效日期”这个条件,用正则校验就行,不需要模型。

状态数据要结构化。状态里存的数据用 JSON 或者数据库表,字段明确。不要存自然语言文本,否则后续处理还得再解析一遍。

异常状态要单独处理。每个状态都要考虑“用户不按预期回答”的情况,设置一个兜底转移,比如重试三次后升级到大模型或者转人工。

Jev 的状态机配置用的是 YAML 格式,下面是一个简化示例:

states: ask_departure: prompt: "请问您从哪个城市出发?" extract: field: departure method: city_parser next: ask_destination on_fail: ask_departure_retry max_retry: 3 ask_destination: prompt: "请问您要去哪个城市?" extract: field: destination method: city_parser next: ask_date on_fail: ask_destination_retry max_retry: 3

这种配置方式的好处是流程和代码分离,产品经理也能看懂,改流程不用改代码。

4.4 大模型调用的“最小化”原则

即使到了必须调用大模型的环节,也要遵循最小化原则。具体来说:

只传必要上下文。不要把整个对话历史都塞进去,只传当前状态相关的信息。比如用户在第 5 轮说“就那个”,你只需要传第 4 轮的候选列表,不需要传前 3 轮的内容。

限制输出格式。让模型输出 JSON 而不是自由文本,这样解析更稳定。Jev 的 prompt 模板里会强制要求模型按指定 schema 输出,解析失败就重试。

设置超时和重试上限。大模型调用可能超时,必须设置超时时间和重试次数。我的经验是超时设 10 秒,重试最多 2 次,超过就降级处理。

缓存高频请求。有些请求是重复的,比如“你们几点上班”,这种可以直接缓存答案,不用每次都调模型。Jev 支持在编排层加缓存节点,命中缓存直接返回。

5. 常见问题与排查技巧实录

5.1 小模型误判率太高怎么办

这是最常见的问题。小模型误判通常有三个原因:训练数据不够、类别不平衡、阈值设置不合理。

训练数据不够的话,先别急着标更多数据,试试用大模型做数据增强。把已有的标注数据喂给大模型,让它生成同义变体,能快速扩充数据集。我试过用这个方法把 500 条数据扩到 3000 条,小模型准确率从 82% 提到了 91%。

类别不平衡的话,给少数类别加权重,或者在采样时做 oversampling。Jev 的训练脚本里支持配置 class weight,直接改配置就行。

阈值设置不合理的话,别拍脑袋定,跑一批验证数据画出 PR 曲线,找到 F1 最高的那个点。如果业务上更怕误判,就把阈值调高;更怕漏判,就调低。

5.2 升级到大模型后响应太慢

升级机制本身会增加延迟,因为要先跑小模型再跑大模型。优化思路有两个:

并行化。小模型和大模型可以并行调用,小模型先返回结果,如果置信度够就直接用,不够就用大模型的结果。这样大部分请求的延迟等于小模型延迟,只有少数请求需要等大模型。

预判升级。根据历史数据,某些意图的升级率特别高,比如“投诉”类请求 90% 都会升级。这种可以在请求进来时直接走大模型,跳过小模型。

Jev 的配置里支持给每个意图设置“直连大模型”的标记,我建议把升级率超过 70% 的意图都标记上。

5.3 状态机卡死或者死循环

状态机卡死通常是转移条件写错了,导致某个状态无法跳出。排查方法是在每个状态转移时打日志,记录当前状态、输入、转移目标。跑一遍测试用例,看日志就能定位问题。

死循环的常见原因是重试逻辑没有上限。每个状态的重试次数必须设上限,超过上限要强制转移到一个兜底状态。Jev 的配置里 max_retry 是必填项,就是防止这个问题。

还有一个隐蔽的坑:状态数据被意外修改。比如某个状态里修改了全局变量,导致后续状态判断出错。我的做法是状态数据只读,需要修改时创建新副本,避免副作用。

5.4 工具调用返回结果解析失败

工具返回的结果格式可能和预期不一致,比如接口升级、字段缺失、编码问题。排查步骤:

  1. 先看原始返回,确认是工具的问题还是解析的问题
  2. 如果是工具的问题,加一层适配器,把不同格式统一成内部格式
  3. 如果是解析的问题,检查解析代码的容错性,比如字段缺失时给默认值
  4. 加监控告警,工具调用失败率超过阈值时通知

Jev 的工具调用层支持配置 schema 校验,返回结果不符合 schema 时自动触发重试或者降级。这个功能很实用,建议开启。

5.5 常见问题速查表

问题现象可能原因排查方法解决方案
小模型误判率高训练数据不足看混淆矩阵数据增强或补充标注
升级后延迟高串行调用看调用链路日志并行化或预判升级
状态机卡死转移条件错误打状态转移日志修正条件或加重试上限
工具解析失败返回格式变化看原始返回加适配器或 schema 校验
成本居高不下大模型调用比例高统计升级率优化小模型或调整阈值
多轮对话丢上下文状态未持久化检查状态存储用状态机管理上下文

5.6 几个我踩过的坑

坑一:过度依赖模型的“常识”。有一次做地址解析,我以为模型能自动识别“朝阳区”属于北京,结果用户说“朝阳区”的时候模型有时候当成北京,有时候当成其他城市。后来改成用行政区划表做匹配,准确率直接到 100%。模型没有常识,只有概率,涉及事实性的东西一定要用数据源校验。

坑二:忽略冷启动问题。新业务上线时没有历史数据,小模型训不出来,只能全走大模型。这时候成本会很高,要有心理准备。我的做法是先跑一段时间收集数据,同时用规则兜底,等数据够了再训小模型。

坑三:状态机设计得太复杂。一开始想把所有分支都覆盖,结果状态数量爆炸,维护成本极高。后来简化成“主流程 + 异常处理”两层,主流程只覆盖正常路径,异常统一走兜底,维护成本降了一半。

坑四:忘记处理并发。同一个用户可能同时发起多个请求,如果状态机没有并发控制,会出现状态覆盖的问题。Jev 的状态存储支持加锁,但需要你自己在配置里开启。我建议所有涉及状态修改的操作都加锁,宁可慢一点也不要出错。

6. 这套思路的适用边界与扩展方向

Jev 这套“System One Model + LLM”的架构不是万能的,它有明确的适用边界。如果你的业务场景是高度开放的,比如创意写作、复杂咨询、开放式问答,那大模型的比例本来就该高,强行拆解反而会降低体验。但如果你的业务是流程化的、意图相对固定的,比如客服、订票、填单、查询,那这套架构能带来数量级的效率提升。

我自己的项目从全 LLM 架构改成这套之后,平均响应时间从 4.2 秒降到 0.8 秒,单次对话成本从 0.15 元降到 0.02 元,用户满意度反而上升了,因为响应快了、出错少了。这个投入产出比是值得的。

扩展方向上,我觉得有几个点可以继续挖:一是用小模型做槽位提取,不只是意图分类,这样能进一步减少大模型调用;二是把状态机可视化,让非技术人员也能配置流程;三是接入强化学习,根据用户反馈自动优化升级阈值。Jev 的架构留了这些扩展点,但需要自己实现。

最后分享一个我常用的判断标准:当你发现自己在 prompt 里写“如果……就……”的时候,就该停下来想想,这个逻辑是不是该用代码写。大模型是拿来处理模糊性的,不是拿来替代 if-else 的。把这个边界划清楚,Agent 的稳定性和效率都会有质的提升。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询