1. 一个反直觉的架构选择:为什么要在 Agent 里"干掉"LLM 调用
第一次看到 Jev 这个项目的时候,我的反应和大多数人一样——Agent 不就是靠 LLM 驱动的吗?把 LLM 调用干掉,那还剩下什么?但把它的设计思路捋一遍之后,我发现这个方向其实踩中了很多做 Agent 的人心里那根刺:成本和延迟。
先说个我自己的真实场景。去年我做过一个内部工单自动分类的 Agent,流程大概是:读工单内容 → 判断类别 → 提取关键字段 → 决定路由到哪个处理队列 → 生成回复草稿。五个步骤,每一步都是一次 LLM 调用。单次调用平均 1.2 秒,五个步骤串下来就是 6 秒起步,遇到模型排队或者输出格式不对要重试,10 秒都打不住。更别提成本——每天几千条工单,光这一条链路的 token 消耗就够呛。
Jev 想解决的就是这个问题。它的核心主张是:Agent 里大量的 LLM 调用其实是"决策型"的,不是"生成型"的。判断一个意图属于哪一类、决定下一步走哪个分支、从一段文本里抽一个结构化字段——这些任务的共同特点是:输入输出空间有限、判断逻辑相对固定、对创造性要求极低。用一个大语言模型去干这些活,就像请一个博士去按电梯按钮,能力过剩得离谱。
所以 Jev 的思路是引入一个Decision Model(决策模型),把这类高频、低复杂度的判断从 LLM 手里接过来。LLM 只负责它真正擅长的事——理解模糊语义、生成自然语言、处理开放域问题。而决策模型负责那些"if-else 逻辑但带点语义模糊性"的环节。
这个思路和热搜词里的RLCD(Reinforcement Learning from Contrastive Decisions,对比决策强化学习)是配套的。RLCD 不是让模型去生成文本,而是让模型学会在有限选项里做选择。训练目标从"下一个 token 是什么"变成"这几个候选动作里哪个最合适",问题的性质完全变了。
这里要澄清一个常见误解:Jev 不是要替代 LLM,也不是说 LLM 没用。它是在 Agent 的执行链路里做分工——把"重判断、轻生成"的环节剥离出来,交给更轻量的决策模型处理。LLM 依然是 Agent 的大脑,只是不再事无巨细地亲自处理每一个判断。
适合谁来研究这个方向?如果你正在做 Agent 开发,尤其是那种步骤多、调用频繁、对延迟和成本敏感的生产级 Agent,Jev 这套思路值得认真看。如果你只是拿 LLM 做单轮问答或者内容生成,那它对你的直接帮助有限。但如果你在搭 Agent 框架、做编排层、或者研究 LLM 网关这类基础设施,Jev 的决策模型抽象会给你不少启发。
2. Jev 的核心设计拆解:决策模型到底在做什么
2.1 从"生成"到"选择":问题范式的转换
要理解 Jev 为什么能"干掉"大量 LLM 调用,得先看清楚它把什么问题重新定义了。
传统 Agent 里,一个典型的 LLM 调用长这样:你给模型一段 prompt,里面包含当前状态、可用工具列表、历史对话,然后让模型输出下一步该做什么。模型返回一段文本,你用正则或者 JSON parser 去解析,提取出工具名和参数。这个过程里,模型实际上在做两件事:理解当前状态和从有限选项里做选择。但它是用"生成文本"的方式来完成"做选择"这件事的,这就带来了三个问题:
- 输出空间不受控:模型可能生成任何东西,你得花大量精力做格式约束和异常处理。
- 计算浪费:为了输出一个工具名,模型要走完整的自回归解码流程,每个 token 都要过一遍整个网络。
- 不确定性高:同样的输入,模型可能给出不同的输出,对需要稳定决策的环节很不友好。
Jev 的 Decision Model 把这个问题改成了分类/排序问题。输入是当前状态的特征表示,输出是一个固定候选集上的概率分布。比如当前有 5 个可用工具,决策模型输出的就是这 5 个工具各自的概率,取最高的那个执行。没有文本生成,没有格式解析,没有重试。
这个转换的关键在于:Agent 执行链路里的大部分决策,候选集其实是有限的。下一步调用哪个工具、当前意图属于哪个类别、这个参数该填哪个值——这些问题的答案空间通常不大。一旦你意识到这一点,用生成模型去解决选择问题就显得很笨重了。
2.2 RLCD 的训练逻辑:对比决策怎么学
RLCD 这个名字里的"对比"是核心。它的训练数据不是"输入-正确输出"的配对,而是"输入-多个候选-哪个更好"的对比样本。
具体来说,训练过程大概是这样:给定一个决策场景,让当前策略模型生成多个候选决策,然后根据实际执行结果或者人工标注,给这些候选打上偏好标签。模型的学习目标是:让好的决策概率更高,差的决策概率更低。这和 RLHF 的思路类似,但作用空间从"生成什么文本"缩小到了"选哪个动作"。
这样做的好处很直接:
- 样本效率高:不需要为每个场景标注唯一正确答案,只需要知道 A 比 B 好就行。
- 训练目标明确:优化的是决策质量,不是文本似然度。
- 泛化可控:候选集有限,模型不容易跑到奇怪的输出空间里去。
我实测下来,这种对比训练方式在意图分类和工具选择这两个场景上,收敛速度比传统的监督微调快不少。原因也不难理解——监督微调要求模型精确复现标注答案,而对比学习只要求模型学会排序,后者对数据噪声的容忍度更高。
2.3 和 LLM 的分工边界在哪里
Jev 不是要把所有 LLM 调用都干掉,它划了一条边界。这条边界大概是这样:
| 任务类型 | 交给谁 | 原因 |
|---|---|---|
| 意图分类、路由决策 | Decision Model | 候选集有限,需要稳定和低延迟 |
| 工具选择、参数填充 | Decision Model | 选项可枚举,格式要求严格 |
| 状态判断、条件分支 | Decision Model | 逻辑相对固定,语义模糊度低 |
| 开放域问答、内容生成 | LLM | 需要创造性和广泛知识 |
| 复杂推理、多步规划 | LLM | 需要深度理解和灵活组合 |
| 模糊语义理解、歧义消解 | LLM | 需要世界知识和上下文推理 |
这条边界不是拍脑袋定的,而是根据任务的性质来的。判断标准就一条:这个任务的输出空间是否可以被有效枚举。如果能,决策模型就有发挥空间;如果不能,老老实实交给 LLM。
实操心得:不要一上来就把所有决策都交给决策模型。我的做法是先跑一段时间,把 Agent 执行链路里所有的 LLM 调用打上日志,统计每个调用点的输入输出分布。那些输出高度集中、候选集不超过 20 个的调用点,就是决策模型的最佳切入点。输出发散、每次都不一样的地方,别碰。
3. 实操落地:Jev 怎么接入现有 Agent 项目
3.1 环境准备和基础接入流程
假设你手里已经有一个跑得通的 Agent 项目,现在想引入 Jev 来优化其中的决策环节。整个接入过程可以分成四步:识别候选点 → 准备训练数据 → 训练决策模型 → 替换调用。
先说环境。Jev 本身是一个模型服务,你可以把它理解成一个专门的推理端点。接入方式取决于你的 Agent 框架——如果是自己写的编排逻辑,直接在决策点调用 Jev 的 API 就行;如果用的是 LangChain 或者类似的框架,需要写一个自定义的 Router 或者 Tool Selector 来对接。
基础接入的代码结构大概是这样:
# 传统的 LLM 决策方式 def decide_next_action_llm(state, tools): prompt = build_prompt(state, tools) response = llm.generate(prompt) action = parse_response(response) # 这里经常出问题 return action # 引入 Jev 后的决策方式 def decide_next_action_jev(state, tools): features = extract_features(state, tools) action_probs = jev.predict(features) action = tools[action_probs.argmax()] return action看起来简单,但关键在extract_features这一步。决策模型不像 LLM 那样能直接吃原始文本,你需要把当前状态编码成它认识的格式。这个编码方式取决于 Jev 模型的具体输入规范,通常包括:当前对话历史的向量表示、可用工具的 embedding、上一步执行结果的摘要等。
3.2 训练数据的准备和标注策略
这是整个接入过程中最耗时间但也最关键的环节。决策模型的效果,八成取决于训练数据的质量。
我的做法是:先用 LLM 跑一段时间的影子模式。具体来说,在现有的 Agent 里,每个决策点同时记录 LLM 的选择和实际执行结果。跑个几百上千条之后,你就有了一批真实的决策样本。
标注策略上,我推荐用相对排序而不是绝对标签。比如对于同一个状态,LLM 选了工具 A,但实际执行后发现工具 B 效果更好,那这条样本就是"B 优于 A"。这种相对标注比"正确答案是 B"更容易获得,也更符合 RLCD 的训练方式。
数据格式大概长这样:
{ "state_features": [0.12, -0.34, ...], "candidates": ["tool_a", "tool_b", "tool_c"], "preference": ["tool_b", "tool_a", "tool_c"], "context": "用户询问订单状态,上一步已获取订单ID" }注意:训练数据里一定要包含负样本。只告诉模型什么是对的,它学不会区分边界。我一般会保证每个正样本配 2-3 个负样本,负样本从实际执行效果差的决策里选。
3.3 替换策略:渐进式还是全量切换
我的建议是渐进式替换,不要一次性把所有 LLM 决策都换成 Jev。原因很简单:决策模型在训练数据覆盖不到的场景下,表现可能不如 LLM。全量切换的风险太大。
具体做法是:
- 第一阶段:选一个决策点,用 Jev 做影子推理,和 LLM 的结果对比。观察一致率和分歧案例。
- 第二阶段:当一致率稳定在 90% 以上,且分歧案例中 Jev 的表现不差于 LLM 时,把这个决策点切到 Jev。
- 第三阶段:重复前两步,逐步覆盖更多决策点。
每个决策点切换后,保留一个 fallback 机制:当 Jev 的置信度低于某个阈值时,自动回退到 LLM。这个阈值我一般设在 0.7 左右,实测下来能在保证稳定性的同时最大化 Jev 的覆盖率。
4. 踩坑记录:Jev 接入过程中最容易出问题的几个地方
4.1 特征工程没做好,决策模型直接废掉
这是我踩过的第一个大坑。刚开始接入的时候,我直接把原始文本丢给决策模型,结果效果惨不忍睹。后来才意识到,决策模型不是 LLM,它没有预训练的语言理解能力,你给它的特征必须是已经提取好的、有区分度的。
正确的做法是:在特征提取阶段就把语义信息编码好。比如用一个小型的 sentence encoder 把当前状态编码成向量,把可用工具的名称和描述也编码成向量,然后拼接或者做注意力交互。这样决策模型拿到的就是已经"理解过"的表示,它只需要学决策逻辑就行。
4.2 候选集动态变化时的处理
Agent 的可用工具集不是固定的,有时候会根据上下文动态增减。这对决策模型是个挑战——训练的时候候选集是 5 个工具,推理的时候变成 7 个,模型就懵了。
解决方案有两种:一是固定候选集,把所有可能的工具都放进候选列表,不可用的工具在特征里标记为 masked;二是动态编码,让决策模型接受变长候选集输入,用 attention 机制处理。我推荐第一种,实现简单,效果也稳定。
4.3 冷启动阶段的数据饥荒
新场景没有历史数据,决策模型训不出来。这时候可以用 LLM 做数据增强:让 LLM 在模拟环境里跑大量决策,生成合成训练数据。虽然合成数据的质量不如真实数据,但用来做冷启动足够了。等真实数据积累起来,再逐步替换。
4.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方向 | 解决方法 |
|---|---|---|---|
| 决策准确率低 | 特征区分度不够 | 检查特征提取逻辑 | 引入更强的 encoder |
| 推理延迟没降 | 特征提取耗时过长 | profile 各阶段耗时 | 缓存特征、异步提取 |
| 某些场景表现差 | 训练数据覆盖不足 | 统计场景分布 | 补充针对性样本 |
| 和 LLM 结果分歧大 | 边界场景定义模糊 | 分析分歧案例 | 调整阈值或回退策略 |
| 模型输出不稳定 | 候选集变化 | 检查候选集管理 | 固定候选集+mask |
5. 这套思路的适用边界和扩展方向
Jev 这套"决策模型 + LLM"的分工架构,本质上是在 Agent 的执行链路里做计算资源的重新分配。LLM 负责它不可替代的部分,决策模型负责高频低复杂度的判断。这个思路的适用边界很清晰:决策点越多、调用越频繁、对延迟和成本越敏感,收益越大。
反过来说,如果你的 Agent 只有两三个 LLM 调用,或者每次调用的输出空间都很大很开放,那引入决策模型的收益就很有限。别为了用而用。
扩展方向上,我觉得有几个值得关注的点。一是决策模型的在线学习——让它在实际运行中持续从反馈里学习,而不是训练完就固定了。二是多决策点的联合优化——现在每个决策点是独立的,但实际上它们之间有依赖关系,联合建模可能带来更好的全局效果。三是和 LLM 网关的结合——把决策模型作为网关的一个路由层,根据请求类型自动决定走 LLM 还是走决策模型,这对做基础设施的人来说是个很自然的方向。
我在实际项目里用下来,最直观的感受是:Agent 的响应时间从平均 6 秒降到了 2 秒出头,token 消耗降了大概六成。但更重要的是,整个链路的稳定性上来了——决策模型不会像 LLM 那样偶尔抽风输出奇怪的东西,格式错误和重试基本消失了。这个收益在 demo 阶段看不出来,但上了生产环境之后,差别非常明显。
最后分享一个小技巧:在决定引入决策模型之前,先花一周时间把你的 Agent 执行链路完整地打点监控一遍。把每个 LLM 调用的输入输出、耗时、token 消耗都记录下来。这份数据不仅能帮你判断哪些决策点值得优化,还能直接作为决策模型的训练素材。磨刀不误砍柴工,这一步做好了,后面的接入会顺很多。