TheoLeeCJ/openjev · 上手攻略
- 仓库:TheoLeeCJ/openjev
- 链接:https://github.com/TheoLeeCJ/openjev
- 分类:LLM 应用 · 决策推理
- 作者:Tom
- 更新:2026-09-18
这是什么
OpenJev 是一个开源项目,试图在消费级 GPU(RTX 3090)上复现 TypeSafe 的 Jev 服务——一种语义决策操作符(semantic decision operator)。它的核心思路是:不让模型生成文本,而是直接读取模型在固定 answer token 上的 logits,经过一次 softmax 得到每个选项的概率。
⚠️ 本仓库复现的是 Jev 的接口模式,不是 Jev 使用的闭源模型或训练方法。README 明确注明"This project reproduces that interface pattern with open models; it does not reproduce Jev's undisclosed model or training."
官方提供了浏览器在线 demo(https://openjev.com,无需排队,随时可用),也可以在本地运行。仓库自带完整的测试 fixture、基准脚本和原始结果数据,结果可复现性在开源项目中属于较高水平。
工作原理简述
S[Unstructured state] --> M[4B model]
C[Runtime criteria] --> M
O[Typed options] --> M
M -- native option logits --> P[Probabilities]
Direct 模式下,系统将 state(任意非结构化文本/JSON)、criterion(自然语言问题)和 options(带 ID 和描述的选项列表)一起拼入 prompt,做一次原生前向传播,然后只在预设的固定大写字母 answer token 上读取 logits,应用 softmax 得到各选项概率。整个过程不采样任何 token,解码循环为零。
解决什么问题
在软件系统中嵌入 LLM 做决策,通常要走"生成 → 解析 JSON/文本 → 执行"这条路。三个经典痛点:
- 延迟高:即使答案只有几个字,也要完整跑一个解码循环,21 个二分类问题用传统生成方式中位数 5.3 秒
- 成本高:每次决策都是一次完整 token 生成,GPU 算力消耗大
- 不稳定:生成文本格式可能出错,需要额外的 JSON repair 兜底,甚至要用另一个 LLM 来解析输出
OpenJev 的方案:一次前向传播,直接读 typed option logits,不采样任何 answer token。21 个二分类问题只需约 1 秒(Qwen3.5-4B),输出直接就是概率值,软件可以直接拿来当 if 条件用,无需任何解析层。
在 37 state × 21 criteria 的真实负载下,开启并行 suffix 优化后吞吐量可达 20 decisions/秒,相比从头重新计算提速约 10 倍。
快速安装
环境要求
- Python 3.10+
- CUDA + GPU(能装下 4B BF16 模型,推荐 RTX 3090 或更高)
- 硬盘空间(Q4_K_M 量化版模型约 3 GB,原生 BF16 约 8 GB)
安装步骤
# 克隆仓库
git clone https://github.com/TheoLeeCJ/openjev.git
cd openjev
# 创建虚拟环境
python -m venv .venv
source .venv/bin/activate
# 设置 HuggingFace 模型缓存目录(指向有足够空间的大容量盘)
export HF_HOME=/path/to/large-drive/huggingface
# 安装(含测试依赖)
pip install -e '.[test]'
直接跑官方示例
CUDA_VISIBLE_DEVICES=0 openjev-score \
--mode direct \
--model Qwen/Qwen3.5-4B \
--revision 851bf6e806efd8d0a36b00ddf55e13ccb7b8cd0a \
--input examples/decisions.jsonl \
--output results.jsonl
⚠️ 模型 revision 必须精确指定(
851bf6e...),README 强调要用 exact revision 来保证结果可复现。
输入格式(decisions.jsonl 示例)
{
"id": "route-1",
"state": "Customer cannot access an account after a password reset.",
"question": "Which queue should handle this request?",
"options": [
{"id": "access", "description": "Account access support."},
{"id": "billing", "description": "Billing support."}
]
}
state 可以是任意非空字符串,也可以是结构化 JSON 对象或数组。Direct 模式会保持 JSON 结构原样传给模型。
三种打分模式
# 模式1:每个选项独立前向传播(默认)
openjev-score --mode direct ...
# 模式2:共享 state,prefetch 一次后并行评估多个 criteria(适合 37×21 这类场景)
openjev-score --mode shared ...
# 模式3:reranker 模式(基于 Qwen3-Reranker-4B)
openjev-score --mode reranker ...
三种模式的选择建议:通用决策场景用 direct;单一长文本需要过大量 criteria 时用 shared;检索 ranking 场景用 reranker。
核心用法
Python API
from openjev import score
result = score(
state="Customer cannot access an account after a password reset.",
question="Which queue should handle this request?",
options=[
{"id": "access", "description": "Account access support."},
{"id": "billing", "description": "Billing support."}
],
model="Qwen/Qwen3.5-4B",
revision="851bf6e806efd8d0a36b00ddf55e13ccb7b8cd0a",
mode="direct",
)
# result 包含: probabilities, timing, model_revision, prompt_hash
print(result.probabilities) # {"access": 0.87, "billing": 0.13}
共享 state 批量评估(省显存)
当有一个长 state 要过很多条 criteria 时,用 --mode shared 只 prefetch 一次,然后并行对每个 criterion 做 suffix 计算:
openjev-score \
--mode shared \
--model Qwen/Qwen3.5-4B \
--input multi-criteria.jsonl \
--output results.jsonl
该模式在 shape777(37×21)负载下达到 20 decisions/秒,而 fresh direct 模式只有 2.33 decisions/秒。
基准测试命令
仓库自带了完整的评测 fixture,可以复现报告中的数字:
# shape777 评测(37 state × 21 criteria)
python benchmarks/shape777.py --mode direct
python benchmarks/shape777.py --mode shared
python benchmarks/shape777.py --mode reranker
⚠️ README 提示 fast reuse 路径是实验性的,BF16 执行会改变 5–6/777 个 argmax 结果,涉及关键决策时不要用。
查看完整结果文件
所有原始结果(含 timing、predictions、checksums)都在 results/raw/ 目录下,machine-readable 汇总在 results/phase1-summary.json。
典型适用场景
- 客服工单自动路由:根据工单内容直接输出部门概率分布,不走 API 调用链路,延迟 <1 秒
- 内容安全/合规判断:在数据处理 pipeline 中内嵌实时判断,延迟敏感型场景(1 秒级别),无需生成式解码
- 规则引擎增强:当规则无法覆盖的边界情况出现时,用 semantic decision 兜底,概率直接参与业务决策
- 多指标并行评估:一个 state 同时过几十个评估维度(shared 模式),如贷款审批的多维度评估
- 本地化决策服务:不方便调用外部 API、要求数据留本地的场景,纯本地 GPU 推理
- Agent 动作预筛:在 Agent 执行动作之前,用 OpenJev 快速预判各动作的可行性,减少无效动作执行
质量数据一览
浏览器在线版(量化 GGUF)
| 模型 | 量化格式 | 下载大小 | Authored balanced accuracy | Perturbation balanced accuracy | TypeSafe subset agreement |
|---|---|---|---|---|---|
| Qwen3-0.6B | Q8_0 | 639 MB | 0.440 | 0.528 | 0.407 |
| MiniCPM5-2B | Q4_K_M | 1.56 GB | 0.686 | 0.693 | 0.637 |
| Qwen3.5-4B | Q4_K_M | 3.01 GB | 0.813 | 0.766 | 0.845 |
| Published Jev | 闭源托管 | — | — | — | 0.883 |
⚠️ 以上数据均来自 README。Qwen3.5-4B 量化版(Q4_K_M)与原生 BF16 精度有差距,表格中 BF16 精度值来自官方报告,未经本仓库实测验证。
任务维度横向比较
| 任务类型 | Direct Qwen3.5-4B | Qwen3-Reranker-4B | 说明 |
|---|---|---|---|
| Authored 144 rows 平衡准确率 | 0.813 | 0.625 | 核心工作负载 |
| WANLI 256 rows 平衡准确率 | 0.637 | 0.522 | 自然语言推理外部校验 |
| TypeSafe 子集 102 rows 模态一致率 | 0.845 | 0.560 | 与 Jev 官方结果差 3.8 pp |
| 判断网格 36 rows 准确率 | 0.806 | 0.694 | — |
| 动作防火墙 10 actions 组合准确率 | 0.700 | 0.700 | 两者持平 |
| 代码检索 Recall@1 | 1.000 | 1.000 | 两者均满分 |
| 企业知识 Recall@1 | 0.929 | 0.929 | 两者均相同 |
坑与注意
- 选项顺序影响结果:测试中 option reversal 导致 direct model 出现 10 次 flip/reranker 仅 2 次,说明模型对 position 仍有依赖。重要决策不要依赖单一顺序,应做扰动校验
- 缺失证据时不可信:missing-evidence 测试集上两个系统都有概率 >0.8 却判断"充分"的情况,概率不能当置信度用——这是一个尚未解决的开放问题
- 与 Jev 仍有差距:TypeSafe subset agreement 0.845 vs Jev 0.883,差 3.8 个百分点;且 Jev 结果未经本仓库实测,仅来自公开记录,不是跑出来的
- reranker 不是通用决策基座:在检索排序任务上 reranker 和 direct 差不多(MRR=1.0),但在通用决策上反而更差;reranker 只适合做 retrieval control
- fast reuse 路径是实验性的:BF16 下有 5–6/777 的 argmax 与 fresh scoring 不同,涉及关键决策时不要用
- HuggingFace revision 必须精确:用 exact revision 保证结果可复现,不要用 latest tag
- 需要足够显存:4B BF16 模型至少需要 8 GB 左右显存,量化后 Q4_K_M 约 3 GB
- 概率不等同于置信度:返回的是 conditional probability,不是 calibrated confidence,在低证据场景下会给出虚高的置信度
与同类对比
| 方案 | 是否开源 | 延迟 | 精度(平衡准确率) | 适用场景 |
|---|---|---|---|---|
| OpenJev direct (本仓库) | ✅ 完全开源 | ~1s/21 decisions | 0.813 | 本地/实时/批量决策 |
| OpenJev shared (本仓库) | ✅ 完全开源 | ~20 decisions/s | — | 高吞吐多 criteria 场景 |
| TypeSafe Jev | ❌ 闭源托管 | 未知 | 0.883 | 需要最高精度 |
| 传统 LLM 生成 + JSON 解析 | ✅ 取决于模型 | ~5s/21 decisions | 取决于模型 | 通用但慢 |
| Qwen3-Reranker-4B reranker | ✅ 开源 | 1.86 d/s | 0.625 (通用决策差) | 仅检索排序 |
核心差异:OpenJev 不生成 token,这是它快 5 倍的根本原因。Direct 模式和生成式基线(ordered JSON array)在同一硬件上对比:前者 1.023 秒 0 token,后者 5.332 秒 111 tokens,5.2 倍延迟差距。
一句话推荐
想要本地毫秒级、可复现、软件内嵌的语义决策能力,OpenJev 是目前最干净的开源方案——直接读 logits 不解码,RTX 3090 就能跑,但离 Jev 官方精度仍有 3–4 个百分点的差距,高精度场景建议在目标数据上做对比评估后再上生产。