我花了 $0.72 测出 Jev 不该被问什么
8,000+ 次调用、17,156,453 输入 token、合计 $0.72 。评分基准不是我的主观判断,而是指令流和字节级布局这类硬真值。 本文是完整实测记录的中文导读。结论里对 Jev 不利的部分,我一条都没删。
先说为什么要测"它不行"
Jev 的中文介绍现在基本都停留在"很快、很便宜、给概率"。这些都对,但对真正要把它放进生产管线的人没用------你需要知道的是它在哪儿会塌,以及塌的时候你能不能发现。
我做的第一件事不是写应用,是找真值。因为用"人标的数据"去评估一个决策模型,最后得到的只是"它和我意见一致吗";一旦不一致,你没法判断谁读对了。
所以我把目标选在一份已编译的商业软件上,因为它有大量不依赖意见的真值:
| 真值来源 | 规模 |
|---|---|
| IL 指令流(每个数值字段被谁消费) | 3,959 个方法体 / 82,765 条指令,分支目标 3322/3322 全部解析成功 |
| 字节级布局(字段尺寸) | 尺寸预测 1381/1381 = 100% 命中 |
| 对象引用还原 | 16,606 个 PPtr |
有了这些,"Jev 答得对不对"就是可计算的,不是投票。
三个结论
① 它的优势主要来自读标识符命名,不是读语义(遮名消融)
做法: 同一批 27 个字段 × 4 条语义轴,三种条件------保留真名 / 遮成 Class_NN.field_NN / 贴上反类的假名 。 成本: 351 次调用 / 617,392 token / $0.0259。
结果:
| 语义轴 | 留名 gap | 遮名 | 贴错名 |
|---|---|---|---|
designer_constant |
+0.67 | +0.24 | −0.12 |
player_visible |
+0.79 | +0.27 | −0.44 |
normalized_ratio |
+0.79 | +0.58 | −0.43 |
persistent_progress |
+0.85 | +0.80 | +0.72 |
只有 persistent_progress 在遮名、贴错名之后几乎不动------那一条是真行为接地。其余三条掉的量,就是"它在读名字"的量。
规模更大的一次复测(1,470 次请求 / $0.05082): 同一个角色五分类任务,保留真名准确率 0.588 ,遮名后 0.302 ------低于"永远答多数类"的 0.42 。也就是说,+0.286 完全来自命名约定;拿掉名字,它比一个常数预测器还差。
能直接用的一条: 同样 245 个标签,确定性探针 8 秒、0 次调用 就能拿到。"这个数在代码里干什么"这件事有真值表,所以它不该问模型。
② 置信度防噪声,不防偏置(那个 $0.18 的教训)
一个九选项的路由任务(把 158 个剧情文件分派到 8 个引用槽位),真值同样来自代码还原的引用关系,不是人标的。
| 方案 | 准确率 | 成本 |
|---|---|---|
| Jev 零样本 | 0.000(158/158 全押同一个诱饵槽位) | $0.18112 |
| Jev + 8 个范例 | 0.907 | 同上 |
| 确定性 1-NN(knot 集合 Jaccard,同样 8 个范例) | 0.987 | 0 |
零样本那一臂:158 次调用全部投给同一个"声明了但从未被引用"的槽位 ,置信度 0.65--0.84 ,一致率 1.000,准确率 0.000。
关键在这里:覆盖率截断在任何一档都救不回来 ------准确率在所有覆盖率下都是 0.00。也就是说,当一个选项集合里存在"听起来最通用"的诱饵时,选择性预测(只看高置信的)完全无效,因为它会稳定地、自信地全押那个诱饵。
能直接用的一条: 任何"给几个范例让它选"的任务,先跑一个确定性最近邻基线。这个项目里查表 0.987、0 调用、还比模型准 8 个点。
③ 剪枝候选集反而让它变差(这条和官方建议反着"感觉")
做法: 同一个问题,20 个候选 vs 用谓词缩到 3 个。
- 20 个候选 → 选对,conf 0.54
- 缩到 3 个 →
none0.37 / 看全部 0.31 / 正确项 0.31 ,最后答了none
整体首问命中率 62.5% → 37.5% 。而且在有谓词那一侧,多出一个本来没有的错选。
直觉是"选项少了更容易选",实测是"概率被推给了退出项"。 这条独立验证了官方文档里"给全量列表而不是 shortlist"的建议。样本只有 8 个案例、单次运行,所以是方向性证据不是结论------但方向和官方建议一致。
中文场景:一条只有你能测出来的东西
同一批素材、同一组英文问题,只把 state 的语言从英文换成中文:
| 结果 | |
|---|---|
| 英文 | 3/3 判对 |
| 中文 | 1/3 判对 |
| 两个错答的置信度 | 0.31 / 0.53 |
| 三个答对的置信度 | 全部 ≥ 0.82 |
模型的准确率掉了一半以上,但它的置信度正好落在 0.6 以下。
所以:
- 判别用的字段保留一份英文镜像。 原文仍然是画面/文案的权威,但送进判别的那份用英文。
- 按置信度分档处置: 高 → 自动执行;中 → 执行但标记复核;低 → 不执行,转人工。
这不需要改模型,只需要一个阈值。 注意:用中文写"问题"没测过(只测了中文 state),别假设可行。
顺手测到的工程数字
- 延迟: p50 383 ms / p90 806 ms ;同一个小状态单问,另一台机器上 p50 769ms / p90 1380ms。官方宣传的"real-time 150ms"在这两台机器上都没拿到,实测大约差 5 倍。
- 价格口径: 输入 42/Btok(=0.042/Mtok),输出不计费 。所以成本主要由 state 决定------"先把 state 检索过滤再问"既是准确率优化也是成本优化。
- 选项上限是真正的瓶颈: 抽样 24 个页面,0% 先撞字符上限,100% 先撞 255 选项上限;4.2% 的页面某层选项数 >255(最多 528)。
- 一次请求可以问几十到上百个问题,共享同一份 state。官方测过 13 问合 1 次:便宜 11.5 倍、快 9.6 倍、答案不变。
沉淀下来的 7 条(可直接搬走)
- 能从字节/表/文件确证的,一律用代码。 只把"没有真值表"的判断交给模型。
- 每条新语义轴过三关: 正例 → 正负例差距 → 遮名消融。三关全过才发布。
- 概率当回归基线,argmax 标签不当。 两次运行标签变了,不代表"理解变了"。
- 任何"给范例"的判断先跑确定性最近邻基线。 本项目里查表 0.987 > 0.907,而且 0 成本。
- 阈值一律作为参数公布,给敏感性区间;别宣称"发现了 N 个模块"。
- 弃权是产物。 conf 0.00 + 能定位到具体哪一问 = 下一张调查清单。
- 模型版本钉死。
jev-latest是会漂移的别名,升级模型按编译器升级对待(全量重跑 + diff)。
完整的 16 条在 docs/FINDINGS.md。
怎么复现
仓库里两个应用完全不需要密钥,可以直接跑:
bash
git clone https://github.com/scd13150/jev-field-notes
cd jev-field-notes
# 52 个测试 + 确定性双脑台账(全程无网络)
cd applications/stick-figure-fighter
npm test
node scripts/spar.mjs --mock --games 64 --seconds 45
# 解析与几何断言(纯标准库,无需 pip install)
cd ../svg-line-partition
python -m src.selftest
要重跑 Jev 那部分需要自己的 TYPESAFE_API_KEY。
仓库里还有什么: 一个实时格斗游戏(Jev 每次请求给 6 个并行判断,代码按帧执行)、一条情感语音管线(8 维情绪向量驱动 IndexTTS 2.5,含 A/B 试听)、一个故意设计成会失败的 SVG 探针(坐标置换后准确率 0.857→0.048,而置信度只动 0.026)。
一句总结
置信度衡量的是"这份 state 里有没有可依据的线索",不是"线索是不是真的"。
所以边界应该这么划:上游数据的正确性由代码保证,模型只负责判断; 而判断的结果必须接上一个动作(执行 / 标记 / 弃权),否则那个概率就白给了。
本文数据来自公开 API 实测,模型版本钉死 jev-1.13.0。被分析作品的身份与内部标识符已做脱敏处理。