1. 从 Jev 的设计哲学说起为什么 Agent 不能全交给大模型第一次看到 Jev 这个项目的时候我正陷在一个 Agent 项目的泥潭里。当时团队做的是一个自动化运维助手用户丢一句“帮我看看线上服务为什么变慢了”Agent 就要去查日志、看监控、比对配置、给出结论。我们一开始的思路很直接——把所有决策都交给大模型让它自己判断该调什么工具、该看什么数据、该下什么结论。结果跑了两周问题全暴露出来了同一个问题问三遍大模型给出三种不同的排查路径有时候它明明拿到了 CPU 飙高的数据却还在纠结要不要去看磁盘 IO更离谱的是它偶尔会“幻觉”出一个根本不存在的监控指标然后一本正经地分析半天。后来我接触到 Jev 这个项目看到它提出的System One Model概念才意识到我们踩的坑其实是一个架构层面的根本问题。Jev 的核心主张很明确Agent 里不该什么都交给大模型。大模型应该做它擅长的事——理解意图、生成语言、处理模糊输入而那些确定性的、有明确规则的、需要快速响应的决策应该交给一个更轻量、更可控的“系统一”模型来处理。这个思路借鉴了认知心理学里“快思考”和“慢思考”的划分系统一负责直觉、快速、自动化的反应系统二负责理性、慢速、需要注意力集中的分析。在 Agent 架构里大模型就是那个“系统二”而 Jev 想补上的是一个可靠的“系统一”。这篇文章我会从 Jev 的设计思路出发拆解为什么“全交给大模型”的 Agent 会出问题System One Model 到底解决了什么以及在实际开发中怎么落地这套理念。不管你是刚接触 Agent 开发的新手还是已经踩过一些坑的老手应该都能从中找到一些可以直接抄作业的东西。2. 全交给大模型的 Agent 到底出了什么问题2.1 延迟与成本每次决策都调用大模型钱包和用户都受不了我先算一笔账。假设你做一个客服 Agent用户每发一条消息Agent 需要决定是直接回复、还是查知识库、还是转人工、还是追问澄清。如果这个决策也交给大模型那就意味着每轮对话至少多一次 LLM 调用。按 GPT-4 级别的模型算一次调用大概 1-3 秒成本在 0.01-0.03 美元左右。如果一天有 10 万轮对话光决策这一层每天就要多花 1000-3000 美元延迟还平白增加了 1-3 秒。这还只是决策层。如果 Agent 的每一步——解析用户意图、选择工具、生成参数、判断结果是否满意、决定下一步——都走大模型那一次完整的任务处理可能触发 5-10 次 LLM 调用。用户等 10 秒才看到第一个字体验直接崩掉。Jev 的思路是把那些“看一眼就知道该怎么做”的决策交给一个轻量级的 System One Model。这个模型可以是一个小型的分类器、一个规则引擎、甚至是一个微调过的小模型响应时间在毫秒级成本几乎可以忽略。注意这里不是说大模型不重要而是说大模型应该用在“值得”的地方。意图理解、复杂推理、自然语言生成这些是大模型的强项但“用户这句话是问句还是陈述句”“当前是否已经收集齐了必要参数”“这个工具调用返回的是成功还是失败”这些完全可以用更轻量的方式解决。2.2 一致性与可预测性大模型的“创造性”在 Agent 里是毒药大模型有个特点叫“温度”。温度越高输出越多样温度越低输出越确定。但即使把温度调到 0大模型在不同时间、不同上下文下对同一个输入的输出也可能有细微差异。这在聊天场景里是好事显得自然但在 Agent 场景里这是灾难。我举个真实的例子。我们那个运维 Agent用户问“服务为什么变慢了”。第一次跑大模型决定先查 CPU再查内存最后看网络第二次跑它决定先看日志错误率再查数据库连接数第三次跑它直接去查了 CDN 配置。三次路径不同结论自然也不一样。用户会疯掉的——同一个问题你每次给我的答案都不一样我到底信哪个Jev 的 System One Model 在这里的作用是把决策路径固化下来。对于“服务变慢”这个意图System One Model 可以输出一个固定的排查序列先查 CPU 和内存再查磁盘 IO再查网络延迟最后看应用日志。这个序列是预先定义好的、经过验证的、确定性的。大模型只负责在每一步里做它该做的事——比如分析日志内容、生成给用户的解释。这样既保证了一致性又保留了大模型的理解能力。2.3 错误累积与幻觉放大每一步都让大模型自由发挥错误会滚雪球Agent 是一个多步决策的过程。如果每一步都让大模型自由发挥那每一步都有概率出错。假设单步准确率是 95%看起来很高了对吧但一个 10 步的任务整体成功率只有 0.95^10 ≈ 60%。如果单步准确率降到 90%10 步之后只剩 35%。这就是错误累积。更可怕的是幻觉放大。大模型在第一步如果产生了一个错误的理解比如把“查询订单状态”理解成了“修改订单状态”那后续所有步骤都会基于这个错误前提展开。它可能会去调用修改接口然后生成一段“您的订单已修改”的回复。用户收到后一脸懵我只是想查一下啊。Jev 的做法是在关键决策点引入确定性校验。System One Model 不负责理解复杂语义但它可以做一个“守门员”——检查大模型输出的意图标签是否在允许的集合里检查工具调用的参数是否符合 schema检查当前状态是否满足进入下一步的条件。这些检查是确定性的、快速的、不会幻觉的。一旦发现异常就中断流程或者回退到安全状态而不是让错误继续传播。2.4 可观测性与调试全黑盒的大模型决策出了问题你都不知道从哪查做 Agent 开发最痛苦的事情之一就是调试。如果所有决策都在大模型内部完成你只能看到输入和输出中间发生了什么完全不知道。用户说“Agent 回答错了”你去查日志只看到一条“LLM call: input..., output...”。为什么它选了这个工具为什么它跳过了那一步为什么它生成了这个参数全靠猜。Jev 的 System One Model 把决策逻辑外化了。你可以明确地看到当前意图被分类为“查询类”置信度 0.92当前状态是“已收集用户 ID缺少时间范围”System One Model 决定下一步是“追问时间范围”。这些决策点都是可记录、可回放、可单元测试的。大模型只负责它最擅长的部分——比如把“我想看看上个月的账单”解析成{intent: query_bill, time_range: last_month}。这样出了问题你能快速定位是分类错了、状态机跳错了、还是大模型解析错了。3. System One Model 到底是什么Jev 的核心设计拆解3.1 不是另一个大模型而是“快思考”的工程化实现很多人第一次听到 System One Model会以为 Jev 又训练了一个小号的大模型。其实不是。Jev 的 System One Model 更像是一个决策层的抽象它可以由多种技术实现规则引擎、决策树、小型分类模型、有限状态机、甚至是一组 if-else。关键在于它的定位处理高频、确定性、低延迟的决策把大模型从这些琐事里解放出来。我自己的项目里System One Model 是用一个轻量级的意图分类器加上一个状态机实现的。意图分类器用的是微调过的 BERT-small推理时间在 10ms 以内状态机是手写的定义了每个意图下的合法状态转移。大模型只负责两件事把用户原始输入解析成结构化意图如果分类器置信度低以及生成最终的自然语言回复。这样下来平均响应时间从 8 秒降到了 1.5 秒成本降了 70%。3.2 与大模型的分工边界什么交给 System One什么留给 LLM这个边界怎么划是落地时最关键的问题。Jev 给出的原则是确定性决策交给 System One生成式任务留给 LLM。具体来说决策类型交给 System One交给 LLM意图分类封闭集合是否状态转移判断是否工具选择有限选项是否参数校验是否异常检测与回退是否开放域意图理解否是复杂多轮指代消解否是自然语言回复生成否是非结构化信息抽取否是跨领域推理否是这个表不是绝对的但可以作为一个起点。核心判断标准是这个决策是否有明确的、可枚举的正确答案如果有就交给 System One如果没有或者答案空间是开放的就交给 LLM。3.3 状态机 分类器一个最小可用的 System One Model 实现我拿一个实际例子来说明。假设做一个订餐 Agent用户可以说“我想订明天的午餐”“帮我看看有什么川菜”“上次那个宫保鸡丁再来一份”。System One Model 需要处理的是意图分类把用户输入分到{order, query_menu, reorder, cancel, unknown}这几个类别里。状态管理当前处于{idle, collecting_time, collecting_cuisine, collecting_dish, confirming}哪个状态。决策输出根据意图和状态决定下一步动作{ask_time, ask_cuisine, ask_dish, confirm, execute_order, fallback_to_llm}。这个逻辑用代码写出来大概是这样class SystemOneModel: def __init__(self): self.state idle self.context {} self.intent_classifier load_small_classifier() def decide(self, user_input): intent, confidence self.intent_classifier.predict(user_input) if confidence 0.7: return {action: fallback_to_llm, reason: low_confidence} if self.state idle and intent order: self.state collecting_time return {action: ask_time} if self.state collecting_time and intent provide_time: self.context[time] extract_time(user_input) self.state collecting_cuisine return {action: ask_cuisine} # ... 其他状态转移 return {action: fallback_to_llm, reason: unhandled_state}这个实现很粗糙但已经能覆盖 80% 的常见流程。大模型只在fallback_to_llm的时候被调用用来处理那些分类器搞不定的开放域输入。实测下来LLM 调用次数减少了 85%用户平均完成订餐的时间从 45 秒降到了 18 秒。4. 落地实操怎么在你的 Agent 项目里引入 System One Model4.1 第一步梳理你的 Agent 决策点画出决策地图别急着写代码。先拿一张纸把你 Agent 里所有的决策点列出来。什么叫决策点就是“根据某个输入需要选择下一步做什么”的地方。比如用户输入进来了是直接回复还是走工具调用如果要走工具调用选哪个工具工具返回结果了是继续下一步还是结束如果继续下一步是什么如果结束怎么生成回复把这些决策点画成一个流程图。然后对每个决策点问三个问题这个决策的答案空间是封闭的吗这个决策需要理解复杂语义吗这个决策出错的代价大吗如果答案空间封闭、不需要复杂语义理解、出错代价大那就标记为“适合 System One”。反之标记为“留给 LLM”。我自己的经验是一个中等复杂度的 Agent大概有 60-70% 的决策点可以交给 System One。剩下的 30-40% 才是真正需要大模型的地方。4.2 第二步选择 System One 的实现方式别过度工程System One Model 不一定要用机器学习。我见过最稳的实现就是一个规则引擎 状态机。规则引擎用 JSON 配置状态机用代码写死。比如{ rules: [ { when: {intent: order, state: idle}, then: {action: ask_time, next_state: collecting_time} }, { when: {intent: provide_time, state: collecting_time}, then: {action: ask_cuisine, next_state: collecting_cuisine} } ] }这种配置化的方式好处是产品经理也能看懂改起来不用重新训练模型。如果你的意图分类需要一定的泛化能力再考虑上一个小型分类器。但千万别一上来就搞一个复杂的神经网络那是给自己找麻烦。4.3 第三步定义 LLM 的调用契约让大模型做“填空题”而不是“作文题”引入 System One 之后大模型的角色变了。它不再是“全权决策者”而是“特定任务的执行者”。所以你需要给它定义清晰的契约。比如输入用户原始输入 当前状态 需要大模型完成的具体任务如“提取时间信息”输出结构化 JSON字段固定类型固定失败处理如果输出不符合 schemaSystem One 负责重试或回退我习惯用 function calling 或者 JSON mode 来约束大模型的输出。比如让大模型从用户输入里提取时间就给它一个 schema{ name: extract_time, parameters: { type: object, properties: { time_expression: {type: string}, normalized_time: {type: string, format: date-time}, confidence: {type: number} }, required: [time_expression, normalized_time] } }这样大模型输出的东西System One 可以直接消费不需要再做复杂的解析。实测下来这种“填空题”模式比“作文题”模式的准确率高很多而且调试起来容易得多。4.4 第四步建立回退机制System One 搞不定的时候优雅降级System One Model 不是万能的。它处理不了的情况要能优雅地交给 LLM。我的做法是设置一个置信度阈值和异常计数器。当分类器置信度低于阈值或者状态机遇到未定义的状态转移或者连续 N 次工具调用失败就触发回退。回退的时候不是简单地把用户输入丢给 LLM而是把当前上下文一起打包过去。比如def fallback_to_llm(user_input, context, reason): prompt f 用户输入{user_input} 当前状态{context[state]} 已收集信息{context[collected]} 回退原因{reason} 请根据以上信息决定下一步应该做什么。输出 JSON 格式。 return call_llm(prompt)这样 LLM 有足够的上下文来做决策而不是从零开始。回退之后System One 要记录这次回退用于后续优化分类器或补充规则。5. 常见问题与排查技巧实录5.1 System One 和 LLM 的边界怎么定我踩过的三个坑第一个坑是边界划得太死。一开始我把所有意图分类都交给 System One结果用户说“我想吃上次那个”分类器直接懵了——它没见过这种指代。后来我把“指代消解”这个任务划给了 LLMSystem One 只负责在指代消解之后做状态转移。第二个坑是边界划得太松。有一段时间我为了省事把工具选择也交给了 LLM。结果 LLM 经常选错工具或者选了一个不存在的工具。后来我把工具选择收回来用规则引擎根据意图直接映射到工具准确率立刻上去了。第三个坑是没有留回退通道。System One 遇到未知输入时我一开始让它直接返回“我不明白”用户体验很差。后来加了回退到 LLM 的机制未知输入先让 LLM 试着理解如果 LLM 也搞不定再返回“我不明白”。这样用户体验好很多。5.2 分类器置信度低怎么办我的三级处理策略分类器置信度低是常态尤其是用户输入比较模糊的时候。我的处理策略分三级置信度 0.8直接采用分类结果走 System One 决策。0.5 置信度 0.8走 System One但在回复里加一个澄清问句比如“您是想查询账单还是修改账单”让用户确认。置信度 0.5直接回退到 LLM让 LLM 做开放域理解。这个策略的关键是不要追求 100% 的分类准确率。分类器只需要处理那些“一眼就能看出来”的输入模糊的输入交给 LLM 或者让用户澄清整体体验反而更好。5.3 状态机陷入死循环怎么破加超时和最大轮次限制状态机最怕的就是死循环。比如用户一直不提供必要信息状态机一直追问用户烦了直接关掉。我的做法是给每个状态设置一个最大停留轮次。比如collecting_time状态最多停留 3 轮3 轮之后如果还没收集到时间就触发回退或者默认值。MAX_TURNS_PER_STATE 3 if self.state_turns[self.state] MAX_TURNS_PER_STATE: return {action: fallback_to_llm, reason: state_timeout}另外整个对话也要设一个最大轮次限制比如 20 轮。超过之后强制结束避免用户和 Agent 无限拉扯。5.4 大模型返回格式不对怎么处理用 schema 校验 重试即使开了 JSON mode大模型偶尔还是会返回不符合 schema 的内容。我的做法是用 Pydantic 或者 JSON Schema 做校验。如果校验失败把错误信息附在 prompt 里让大模型重新生成。重试最多 2 次还失败就回退到默认值或者报错。from pydantic import BaseModel, ValidationError class TimeExtraction(BaseModel): time_expression: str normalized_time: str confidence: float def extract_time_with_retry(user_input, max_retries2): for i in range(max_retries 1): result call_llm(user_input) try: return TimeExtraction(**result) except ValidationError as e: if i max_retries: raise user_input f{user_input}\n\n上次输出格式错误{e}\n请重新输出。这个模式我用了很多次实测下来 95% 的情况第一次就能通过剩下 5% 重试一次也能解决。5.5 常见问题速查表问题现象可能原因排查方法解决方案Agent 响应慢LLM 调用次数过多统计每轮对话的 LLM 调用次数把确定性决策移到 System One同一问题答案不一致决策路径未固化对比多次运行的决策日志用状态机固定决策路径工具调用参数错误LLM 生成参数不可靠检查工具调用的 schema 校验日志用 System One 做参数校验和补全分类器置信度普遍偏低训练数据不足或类别不平衡看混淆矩阵和置信度分布补充训练数据或降低阈值走回退状态机卡死缺少超时机制检查状态停留轮次加最大轮次限制和超时回退LLM 输出格式错误约束不够强检查 prompt 和 schema用 JSON mode schema 校验 重试6. 我个人的一些实操体会这套 System One LLM 的架构我在三个项目里落地过最大的感受是Agent 的可靠性不是靠大模型变聪明而是靠架构变清晰。大模型再强它也是一个概率模型你没法保证它每次都对。但 System One Model 是确定性的你可以对它做单元测试可以保证它在给定输入下永远输出同样的结果。把这两者结合起来Agent 才能既灵活又可靠。还有一个体会是别追求一步到位。我一开始想设计一个完美的 System One Model把所有决策都覆盖到。结果搞了两周发现根本不可能——用户的输入太多样了。后来我换了个思路先让 System One 处理最常见的 20% 场景剩下的 80% 全部回退给 LLM。然后根据日志逐步把高频场景从 LLM 迁移到 System One。这样迭代了两个月System One 的覆盖率到了 70%LLM 调用次数降了 80%而且整个过程没有影响线上服务。最后分享一个小技巧给 System One 的每个决策点加一个唯一 ID。比如decision_intent_classify、decision_state_transition、decision_tool_select。然后在日志里记录每个决策点的输入、输出、耗时、置信度。这样出了问题你可以直接根据 ID 去查日志快速定位是哪个决策点出了问题。这个习惯让我在排查线上问题时省了至少一半的时间。