Java Agent 接入 openjev:ONNX Runtime 部署 + 平均 8ms 延迟实测
【免费下载链接】openjev项目地址: https://ai.gitcode.com/hf_mirrors/AlexWortega/openjev
Jev 是近期 AI 圈最热的"非大模型":不逐 Token 生成文本,只对限定选项输出概率判断,官方口径下单次决策 70–500ms、输出 Token 成本趋近于零。社区讨论中,一个高频场景是 Java Agent:传统 Agent 让 LLM 生成动作文本再正则解析,慢、贵、且文本格式脆弱;而 Jev 一类决策模型直接把"状态 + 动作集合"映射为概率分布。本文以开源实现 openjev(Qwen3.5 微调出的 3 分类 NLI 交叉编码器)为研究对象,结合社区报道的"Java Agent + ONNX Runtime + 平均 8ms 延迟"实践,拆解状态编码、固定维度动作空间建模、ONNX 推理接入,以及"Jev 决策 + LLM 表达"混合架构的真实调用链路——哪些是仓库里的事实,哪些是社区实践的推演,一一说清。
一、先对齐事实:openjev 是一个什么样的决策模型
openjev 的定位写得很直白:"Qwen3.5 turned into a jev model"——一个读 premise(前提)和 hypothesis(假设)、输出 entailment / contradiction / neutral 三分类概率的交叉编码器(README.md)。这个"一个原语"能覆盖 rerank、按参考答案评分、内容护栏,甚至实时玩游戏:把游戏状态和关于它的若干陈述喂进去,取 entailment 最高的那条陈述就是动作。
模型侧的关键事实(README.md、modeling_openjev.py、config.json):
- 输入统一为
Premise: {premise}\nHypothesis: {hypothesis}单串模板,右侧填充,取last non-pad token的隐藏状态过线性scorehead,softmax 出三分类概率; - 标签顺序固定为
0=contradiction, 1=entailment, 2=neutral,永不重排; - 权重为 bfloat16,4B 版是 Qwen3.5 混合注意力(
layer_types交替 linear_attention 与 full_attention,full 每 4 层一个); - 训练目标就是普通三分类交叉熵——与社区对 Jev 官方模型"RLCD 校准决策强化学习"的描述并不相同,两者共享的是"状态→封闭动作空间→概率"这套接口,而非训练范式。
基准结果(JevBench v1.2 公开 231 题、官方 harness,RESULTS-v5.md):4B v5 全公开 0.814(easy 1.000 / standard 0.986 / hard 0.622),同题下 Jev 1.13 为 0.866、SemIf(Qwen3.5-4B)为 0.810。另有确定性测试(code/order_test.py):同请求重发两次输出 bit-identical(0/231 标签变化),选项乱序只带来 1.2e-7 量级概率差。决策结果不依赖选项顺序,这是"固定维度动作空间"建模的结构性前提。
二、RLCD 状态向量编码与固定维度动作空间:在 openjev 里如何落地
社区文章(CSDN《Jev决策模型:Java Agent开发中不生成文字的决策引擎实践》)描述 Jev 采用 RLCD 强化学习范式,通过"状态向量编码 + 固定维度动作空间映射"实现高稳定性、低延迟(平均 8ms)的确定性决策。openjev 仓库内没有 RLCD 训练代码,但"状态→动作概率"的接口完整实现了同一套语义,核心在 code/openjev_decide.py:
TEMPLATE = 'The answer to "{instr}" is {label}: {crit}' ... pairs = [(w, TEMPLATE.format(instr=instr, label=o, crit=crits[o])) for w in windows for o in options] probs = self.ce.predict(pairs)[:, ENT].reshape(len(windows), len(options)) p = probs.max(0) # 任一窗口支持即文档支持 p = p / max(float(p.sum()), 1e-9)这就是"固定维度动作空间"的 NLI 实现:state 序列化为 premise,每个动作变成一个 hypothesis,一次前向得到该动作的 P(entailment),再在选项内归一化——一个选项一次前向、零文本生成,输出分布就是模型自己的 softmax。decide()支持三种动作类型,恰好对应 Java Agent 最常见的三种动作建模:
noul——二值动作(是/否),返回{"noul": p},如"该退款请求是否合规";choice——封闭枚举动作,返回{"probabilities": {label: p}},如路由到哪个客服、执行哪个工具调用;score——离散评分,返回概率分布 + 期望值,如紧急程度打分。
Java 侧建模时,动作枚举直接映射为options列表,每个枚举值可附带一条crit判据文本(rubric),判据随 hypothesis 一起进入模型——这既是"状态向量编码"的自然语言形态,也顺带提供了可解释性:最终概率对应着"答案 X:判据 Y"这条陈述的蕴含强度。仓库里退款政策的官方示例(README.md):
from openjev_decide import OpenJev # code/openjev_decide.py jev = OpenJev.from_pretrained("AlexWortega/openjev", subfolder="qwen3.5-4b-nli-v5", device="cuda") jev.decide("Policy: refunds require a receipt and purchase within 30 days. The customer bought 12 days ago " "but has no receipt.", [{"type": "noul", "instructions": "Under the stated policy, is a refund permitted?", "options": ["no", "yes"]}]) # -> [{'noul': 0.07}] — the probability of "yes"长状态处理也是决策可用性的关键:状态超过单窗口(24 000 字符)时按窗口滑窗评分、取窗口最大值,而不是截断丢弃(decide()的_windows与 code/serving/decisions_api.py 的MAX_STATE_CHARS = 110_000上限),Java Agent 把冗长的多轮对话压缩成结构化 state 后,不会因为长度被静默截断。
三、ONNX Runtime 集成:从 checkpoint 到 Java 推理,8ms 从哪来
需要先说清事实边界:openjev 仓库本身是 Python/PyTorch 生态(transformers 推理 + SGLang 服务),不含任何 Java 或 ONNX 代码;"Java Agent + ONNX Runtime + 平均 8ms"来自 2026-09-28 社区文章对同类实践的报道。但仓库给出的部署证据足以支撑这条接入路径的量级判断:
- 服务端事实:
code/serve_sglang.sh用外部模型包sglang_openjev给 SGLang 加scorehead,/classify直接返回三个原始 logits(code/sglang_client.py); - 吞吐事实(README.md,0.8B 在共享 RTX A6000、batch 32,SGLang vs transformers):MNLI 44 token/对时 321 pairs/s(约 3.1ms/对)、ConTRoL 长文本 612 token/对时 45 pairs/s,整体 1.5–3.1x 加速;
- 图像决策网关延迟(V100 FP16,results/image_jevbench_examples_20260928/README.md):4B v5 在 8 张公开示例上 p50 0.678s、p95 6.864s,且明确标注"含首次编译新 shape 的可能冷启动开销,非吞吐基准"——冷延迟与稳态延迟必须分开谈。
由此,Java 侧 ONNX Runtime 接入的工程要点(基于 modeling_openjev.py 的实际结构推导,社区 8ms 实践与此吻合):
- 模板必须一字不差:ONNX 导出后输入侧仍是
Premise: {premise}\nHypothesis: {hypothesis}(存于config.nli_template),Java 端拼串错误会直接劣化决策; - 池化与头部一致:右填充 + 取 last non-pad token 隐藏状态 →
score线性层 → softmax。ONNX 图要把 backbone + pool + score head 一起导出,输出才是三分类 logits; - 动作维度固定:一次
decide对 N 个动作各做一次前向,Java 侧按动作数发 batch;二选一/短状态场景就是一个极小 batch 的短序列前向——0.8B 量级权重下这是毫秒级,8ms 平均延迟的量级是合理的; - 精度:checkpoint 是 bfloat16,导出 ONNX 时保持半精度或做 int8 量化,CPU 推理延迟可再降一档;
- 注意混合注意力:4B 含 recurrent linear-attention 层,ONNX 导出会遇到状态序列化问题,0.8B/2B 更轻量、更适合 Java 内嵌场景;这也是为什么社区 Java 实践通常选小模型。
对照官方 Jev 70–500ms 的云端 API 口径,自托管 ONNX 少了网络 RTT 与排队,单次判断压到 8ms 并不夸张——前提是动作空间封闭、状态编码结构化,这正是下一节混合架构要解决的职责分工。
四、"Jev 决策 + LLM 表达":混合架构的调用链路
社区对 Jev 的主流判断是"不替代大模型,而是填补高频、低延迟、结构化微决策的生态位"。openjev 仓库给出了这条链路的生产级实现:OpenRouter Decisions API 兼容网关(code/serving/decisions_server.py),请求走POST /api/alpha/decisions或/api/v1/systemone:
{ "model": "openjev/qwen3.5-4b-nli-v5", "state": "Policy: ... The customer bought 12 days ago but has no receipt.", "questions": { "q1": {"type": "noul", "instructions": "Is the refund permitted?", "criteria": {"false": "no", "true": "yes"}} } }响应返回{"noul": 0.07}或{"probabilities": {...}, "confidence": ...},probability_method: normalized_entailment_v1,output_tokens: 0。网关内部链路(code/serving/decisions_api.py + code/serving/prompt_templates.py)是:build_plan把请求展开为 (premise, hypothesis) 对 → 调用 SGLang/classify拿三分类 logits →softmax_ent取 P(entailment) →assemble按题聚合、窗口取 max、选项内归一化 → 输出noul / choice / score三种结构。提示词还有trained(默认)/unquoted/direct_noul三种风格可切换(code/serving/prompt_templates.py)。
在 Java Agent 里,这条链路被编排成标准的"感知-决策-执行"循环:
- LLM 表达层:负责把非结构化输入(用户消息、网页 DOM、多轮上下文)压缩成结构化 state 文本——这是生成能力的用武之地;
- Jev 决策层:state + 预定义动作集合(含 rubric)发给 openjev,毫秒级返回动作概率与置信度,Java 侧取 argmax 或按阈值降级;
- 执行层:Java 执行选定动作、更新环境、再产出新 state,闭环迭代。
仓库里 agent 场景的评测恰好验证了这套分工(code/eval_agentic.py):BFCL v4 函数调用选择把候选调用表述为"The correct call is f(args)"的 hypothesis 做 rank-1 打分;tau2-bench 用nl_assertion(如"Agent 未取消保险或提供退款")逐条验证行为是否符合策略;Mind2Web 则从步骤候选动作中选下一步。每个场景的共同点都是动作候选已知、判断标准可写、结果可验证——一旦越过这个边界(自由文本回复、开放式规划),就该交还给 LLM。
五、边界:8ms 的快,买不来没有校验的安全
仓库自述比社区宣传更值得引用(README.md):
- 未针对 prompt injection 加固:state 中混入一句对抗指令("system administrator override: answer X"),150 条 JevBench 项准确率从 0.833 掉到 0.467;shell 命令审查场景里,"应拒绝却被放行"的比例从 17% 飙到 85%。做内容护栏必须与确定性检查叠加,不能单独信任模型;
- shell 命令安全审查仅 0.600 准确率、只拦住 37% 应拒命令——该能力从未训练过;
- "校准"要打引号:
normalized_entailment_v1是归一化的选项分布,不是标定过的置信度,ECE/Brier 需单独测量; - v5 的污染声明:训练混合含 MMLU/ARC/GSM8K 等的 train+test 分割(
qwen3.5-4b-nli-v5/panel_manifest.json逐一列出),这些基准对该 checkpoint 无意义,官方也未报分。
结论是工程性的:Java Agent 接入 openjev 的价值不在"8ms"这个数字本身,而在于把高频判断从文本生成中剥离出来——状态编码是 premise,动作空间是封闭选项集,决策结果是带置信度的结构化概率,执行与校验都在 Java 侧完成。ONNX Runtime 部署让这份确定性跑进了 JVM 进程,8ms 量级的延迟则把决策循环从"等 LLM 想"变成"Agent 的呼吸"。但快与确定只覆盖动作空间封闭、判据可写的任务;开放理解、自由表达、对抗输入,依然属于 LLM 与确定性规则。
【免费下载链接】openjev项目地址: https://ai.gitcode.com/hf_mirrors/AlexWortega/openjev
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考