从 Java 开发者的视角看 Jev 这个不生成文字的决策模型,为什么能颠覆 Agent 架构
做 Java 后端的这些年,我见过太多"新架构"最后落地成一层薄薄的 HTTP 封装。所以当 Jev 这个"不生成文字的决策模型"概念冒出来的时候,我第一反应是警惕的——又一个把 LLM 包一层就叫 Agent 的东西?但真正把它的思路拆开看之后,我发现它戳中的恰恰是 Java 工程师最熟悉的那套东西:状态机、职责分离、可测试性。它不生成文字这件事,不是缺陷,而是它整个架构设计的起点。
这篇文章我想从一线开发者的角度,把 Jev 这类决策模型为什么能颠覆传统 Agent 架构讲清楚。适合正在做 Agent 开发、被 LLM 输出不稳定折磨过的后端同学,也适合想理解"决策与生成分离"这个思路的架构爱好者。我会尽量用 Java 世界里你熟悉的类比来解释,不堆术语,讲人话。
1. 先搞清楚 Jev 到底"不生成"什么
1.1 传统 Agent 把决策和表达揉在了一次生成里
大部分人做 Agent 的第一版,都是这么写的:给 LLM 一个 system prompt,告诉它"你是一个助手,可以调用工具",然后把用户输入丢进去,模型返回一段文本,里面可能夹着工具调用。你解析这段文本,执行工具,再把结果塞回去,循环往复。
这个模式的问题在于,决策(下一步做什么)和表达(怎么把话说出来)被压缩在同一次 token 生成里。模型既要判断"我该不该调用搜索工具",又要组织"好的,我来帮你查一下"这句话。这两件事的失败模式完全不同,但混在一起之后,你根本分不清是它判断错了,还是它只是话说得不对。
我在一个客服 Agent 项目里就吃过这个亏。模型明明判断对了要查订单,但因为它同时在生成"稍等,我帮您查询"这句寒暄,结果工具调用的 JSON 被这句寒暄污染了,解析直接失败。你调 prompt 调半天,其实问题不在判断,在表达。
1.2 Jev 的"不生成文字"是把决策抽成独立信号
Jev 这类模型的核心主张是:决策阶段只输出结构化的动作信号,不输出任何自然语言。它不负责"怎么说",只负责"做什么"。你可以把它理解成一个纯粹的分类器或者策略网络——输入当前状态,输出一个动作(调用哪个工具、传什么参数、还是终止)。
这听起来好像只是把 prompt 拆成两段,但本质区别在于:决策模型的输出空间被极大压缩了。传统 LLM 的输出是整个词表,几万到十几万个 token 的可能性;而决策模型的输出是有限的动作集合,可能就几十个。输出空间小了,可控性、稳定性、可测试性全都上来了。
用 Java 的话说,传统 Agent 像是让一个方法既做业务计算又做日志格式化,职责不清;Jev 的做法是把它们拆成两个方法,各司其职。
1.3 为什么"不生成文字"反而是优势
很多人直觉上觉得,不生成文字是不是能力弱了?恰恰相反。文字生成是一个开放域问题,而决策是一个封闭域问题。开放域问题难在无穷无尽的边界情况,封闭域问题难在策略的准确性。
把决策从开放域里解放出来,意味着你可以用强化学习、可以用小模型、可以做严格的单元测试。一个只输出动作的模型,你可以给它喂一万个状态-动作对,验证它的策略是否收敛。但你没法给一个生成自然语言的模型写单元测试,因为它的输出永远在变。
提示:判断一个 Agent 架构是否成熟,看它的决策部分能不能被单独测试。如果测试决策必须启动整个 LLM 推理链路,那这个架构还没解耦干净。
2. 从 Java 视角理解"决策与生成分离"
2.1 这本质上是一次职责分离重构
如果你写过稍微复杂点的 Java 服务,一定经历过把"上帝类"拆成多个单一职责类的过程。一个几千行的 Service 类,既查数据库、又算业务、又拼返回值,改一处崩三处。重构的方向永远是:把变化频率不同的逻辑分开。
Agent 架构也是同一个道理。决策逻辑的变化频率和表达逻辑的变化频率完全不同。你今天想换个更礼貌的说话风格,不应该影响工具调用的判断;你今天想加一个新工具,不应该让模型重新学怎么寒暄。把这两者绑在一起,就是典型的耦合。
Jev 的分离方式,相当于在架构层面强制你做了一次依赖倒置:决策层定义"我需要什么动作"的接口,表达层去实现"怎么把这个动作说成人话"。决策层根本不关心表达层怎么实现。
2.2 决策模型更像一个策略接口而非生成器
在 Java 里,我们习惯用接口来隔离实现。PaymentStrategy接口只定义pay(),具体是支付宝还是微信,调用方不关心。Jev 的决策模型就是这个思路——它定义的是一个decide(state) -> action的契约。
这个契约有几个关键特性,都是 Java 工程师会喜欢的:
- 输入输出类型明确:状态是结构化的,动作也是结构化的,没有"一段可能包含 JSON 的文本"这种模糊地带。
- 幂等性可保证:给定同样的状态,决策模型应该给出同样的动作(在推理模式下)。这让重试、回放、调试都变得可行。
- 可组合:多个决策模型可以像责任链一样串起来,每个负责一类决策。
我实测过一个场景:把工具选择做成独立决策模型后,整个链路的可观测性提升了一个档次。以前日志里是一大段模型输出,你得肉眼找工具调用;现在日志里直接是action=search_order, params={orderId: 123},清爽得不像话。
2.3 和传统 Agent 循环的对比
传统 Agent 循环大概是这样的:
while not done: output = llm.generate(prompt + history) action = parse(output) # 这里最容易出问题 result = execute(action) history.append(result)Jev 式的循环:
while not done: action = decision_model.decide(state) # 纯结构化输出 result = execute(action) state = update(state, result) # 表达层单独处理,与决策解耦差别就在那个parse步骤。传统模式里,parse 是一个脆弱的、依赖正则和运气的环节;Jev 模式里,根本没有 parse,因为决策模型直接吐结构化数据。
| 对比维度 | 传统 Agent | Jev 式决策分离 |
|---|---|---|
| 决策输出 | 自然语言+工具调用混合 | 纯结构化动作 |
| 解析环节 | 需要正则/JSON 提取,易失败 | 无需解析,直接反序列化 |
| 可测试性 | 难,输出不确定 | 易,可写单元测试 |
| 模型规模 | 通常需要大模型 | 可用小模型甚至规则 |
| 表达风格调整 | 影响决策稳定性 | 完全隔离,互不影响 |
这张表是我自己在两个项目里对比出来的,不是理论推演。传统模式里,光是"让模型稳定输出合法 JSON"这一件事,就够你调一周 prompt。
3. 为什么这个思路能颠覆 Agent 架构
3.1 它把不可控的生成问题变成了可控的分类问题
Agent 落地最大的痛点是什么?是不可控。你永远不知道模型下一步会输出什么,所以你得加各种护栏、重试、兜底。这些护栏本身就是巨大的工程成本。
Jev 的思路把决策变成了分类问题。分类问题的好处是,它的输出空间是有限的、可枚举的。你可以穷举所有可能的动作,为每个动作定义清晰的语义。这就好比从"让模型自由发挥写一篇文章"变成了"让模型从 20 个选项里选一个",难度和可控性完全不是一个量级。
在 Java 里,这就像从Object类型变成了enum。你拿到一个enum,可以放心地 switch,编译器还能帮你检查有没有漏掉分支。而拿到一个Object,你得先 instanceof 判断,还得处理各种意外类型。
3.2 决策模型可以小到离谱,成本结构彻底改变
这是最让我兴奋的一点。因为决策模型的输出空间小、任务单一,它不需要一个千亿参数的大模型。很多场景下,一个几亿参数的小模型,甚至一个精心设计的规则引擎,就能达到很好的决策效果。
成本结构的变化是颠覆性的。传统 Agent 每次循环都要调用一次大模型,token 消耗巨大,延迟也高。而决策分离后,你可以:
- 用本地小模型做决策,零 API 成本,延迟降到毫秒级
- 只在需要生成自然语言回复时,才调用大模型
- 高频的决策循环和低频的表达生成彻底解耦
我算过一笔账:一个日均十万次交互的客服 Agent,传统模式下每次交互平均 3 轮循环,每轮 2000 token,一天就是 6 亿 token。决策分离后,决策部分用本地小模型,只有最终回复走大模型,token 消耗直接降到十分之一以下。
3.3 强化学习终于有了用武之地
关键词里出现了 RLHF 和 RLCD,这其实是决策分离带来的另一个红利。当决策被抽成独立模块后,你终于可以用强化学习去优化它了。
RLHF(基于人类反馈的强化学习)在纯生成模型上很难做,因为奖励信号太稀疏、太主观。但用在决策模型上就自然多了:一个动作好不好,环境会给你明确的反馈(工具调用成功还是失败、任务完成还是没完成)。这就是标准的强化学习设定。
RLCD(基于对比的强化学习)也是类似思路,通过对比不同决策的优劣来优化策略。这些方法在决策模型上能跑通,是因为决策的奖励信号是可量化、可验证的,不像自然语言质量那样玄学。
用 Java 类比,这就像你终于可以给那个"上帝类"写单元测试了。以前它输出一段文本,你没法断言;现在它输出一个动作,你可以精确断言"在这个状态下应该返回 search_order"。
4. 落地时最容易踩的几个坑
4.1 状态表示没设计好,决策模型直接废掉
决策模型的输入是状态,如果状态表示设计得烂,再好的模型也救不回来。我见过最常见的错误是:把整个对话历史原封不动塞给决策模型。
这等于把开放域问题又塞回来了。决策模型需要的是提炼过的、结构化的状态,而不是一堆原始文本。你应该在决策之前,先把对话历史压缩成关键槽位:用户意图是什么、已经收集到哪些参数、当前处于流程的哪一步。
这就像 Java 里的 DTO 设计。你不会把数据库的 Entity 直接暴露给前端,而是转成精简的 DTO。决策模型的状态输入,也应该是这样一个"决策 DTO"。
4.2 动作空间设计过粗或过细
动作空间的设计是个平衡活。太粗了,一个动作承担太多职责,决策模型学不明白;太细了,动作数量爆炸,决策难度上升。
我的经验是:一个动作对应一个明确的、可独立执行的操作。比如"查询订单"是一个动作,"取消订单"是另一个动作,不要合并成"处理订单"这种模糊动作。同时,参数要尽量结构化,不要用自由文本传参。
注意:动作空间一旦确定,后续扩展要谨慎。加动作容易,但每加一个动作,决策模型的训练数据都要重新覆盖,成本不低。
4.3 决策和表达的边界没划清
分离不等于完全隔离。有些信息是决策需要的,也是表达需要的,比如用户的情感状态。这时候要明确:决策层用情感状态来决定"要不要转人工",表达层用情感状态来决定"用什么语气"。同一个信息,两个层各取所需,但用途不同。
我踩过的坑是:一开始想让决策模型顺便输出一句"建议回复",结果又把生成问题混进来了。后来严格规定决策模型只输出动作和参数,表达完全交给下游,链路才干净。
4.4 别忘了给决策模型做兜底
决策模型再稳,也有判断错的时候。所以动作执行前要有校验,执行后要有回滚或补偿。这跟 Java 里做事务是一个道理:你不能假设每个操作都成功,得有 try-catch 和补偿逻辑。
具体做法是,给每个动作定义前置条件和后置条件。前置条件不满足就不执行,后置条件不满足就触发补偿。这样即使决策模型偶尔抽风,系统也不会崩。
5. 一个可复现的最小实现思路
5.1 用接口定义决策契约
先定义决策的接口,这是整个架构的地基:
public interface DecisionModel { Action decide(AgentState state); } public class Action { private String type; // 动作类型,如 "search_order" private Map<String, Object> params; // 结构化参数 // getters/setters }注意Action里没有任何自然语言字段。这是刻意的约束,逼着你把决策和表达分开。
5.2 状态对象要精简
public class AgentState { private String userIntent; // 提炼后的意图 private Map<String, String> slots; // 已收集的槽位 private String currentStage; // 流程阶段 private List<String> executedActions; // 已执行动作,防重复 }这个状态对象就是决策模型的全部输入。它足够精简,也足够结构化,决策模型可以稳定地基于它做判断。
5.3 决策模型的两种实现路径
路径一:规则引擎。适合流程固定的场景,用状态机实现,完全可控,零成本。很多业务场景其实根本不需要模型,一个状态机就够了。
路径二:小模型分类器。适合状态空间大、规则难穷举的场景。把状态编码成特征向量,用一个小模型输出动作概率分布,取 top-1。
我建议先从规则引擎起步,跑通了再考虑上模型。因为规则引擎能帮你验证状态设计和动作空间设计是否合理,这两个设计对了,换模型才有意义。
5.4 表达层单独实现
表达层接收动作和执行结果,负责生成自然语言。这一层可以用大模型,也可以用模板。关键是它和决策层之间只通过结构化的动作和结果通信,不共享任何隐式状态。
public interface ResponseGenerator { String generate(Action action, ActionResult result, AgentState state); }这样,你想换表达风格,只改这一层;想优化决策,只改决策层。两边互不干扰。
6. 这套架构适合什么样的团队
不是所有团队都适合上这套架构。如果你的 Agent 只是做个 demo,交互轮次很少,那传统方式更快。但如果你满足下面几条,Jev 式决策分离会带来巨大收益:
- 交互轮次多:每轮都调大模型成本扛不住,决策分离能大幅降本。
- 对稳定性要求高:业务不能容忍模型偶尔抽风,决策分离让核心逻辑可控。
- 需要持续优化决策质量:想用强化学习或数据驱动的方式迭代决策,分离是前提。
- 团队有后端工程背景:这套思路本质是软件工程,Java 团队上手很快。
我个人在实际项目里的体会是,决策分离最大的价值不是省钱,而是让 Agent 变得可调试、可测试、可迭代。以前调 Agent 像玄学,改个 prompt 效果时好时坏;现在决策部分有明确的输入输出,能写测试、能回放、能定位问题。这种工程上的确定性,才是它真正颠覆传统 Agent 架构的地方。
最后分享一个小技巧:如果你现在手上有个传统 Agent 项目,不用推倒重来。先试着把"工具选择"这一步从大模型里抽出来,单独做成一个决策模块,其他不变。跑一段时间你会发现,光是这一步分离,就能让整个链路的稳定性上一个台阶。等这一步跑顺了,再逐步把更多决策逻辑迁移过去。