系统一(System one)决策模型会推断,并以校准概率或每个允许的答案作出响应。日常语言模型若用结构化输出(Structured Output)生成 JSON,虽会一次性预填充输入,仍需为每个 token 各跑一遍,例中生成最终输出就要 11 遍。杰夫(Jev)这类决策模型假定有固定选项,可单次传递快速选择;例中把输出限制为 A、B、C、D、E,并掩码词表其他项,使模型只能在其中选择。
正文
"System one" 决策模型是一类会进行推断、并以校准概率或针对每个允许的答案来给出回应的模型。
想想你日常用的语言模型,如果想让它输出带类型的结果(比如 JSON),可以用 Structured Output 把输出约束成必定合法的 JSON。虽然模型会在一次前向里预填充输入,但为了生成合法响应,它仍然需要为每个 token 各做一次传播。
在这个例子里,生成最终输出需要 11 次传播(这里不考虑 speculative decoding 和其他推理优化技术)。在“第 1 步 / 共 11 步”的示意中,提示部分(prefill)对应的 token 序列是 <bos>0 Sky 1·colour 2?3·A)4·red 5·B)6·blue 7·C)8·green 9·D)10·grey 11·E)12·pink 13·Answer 14:15?16,模型正在预测下一个 token,候选里 { 为 93.0%,The 为 3.0%,B 为 2.0%,Sky 等 token 为 1.0%。
Jev 这类决策模型假设存在一组固定选项可供选择,并且只需单次传播就能快速选出。这个例子里,我们把可能的输出约束到 A、B、C、D、E;通过把词表里的其他 token 屏蔽掉,模型只能输出这些 token。选出概率最高的输出,就得到了答案。在“第 1 步 / 共 1 步”中,同样的提示下,输出被约束到固定选项:可选项里 B 为 83.3%,A 为 5.6%,C 为 5.6%,D 为 3.3%,E 为 2.2%;而 The、Blue、Maybe 的概率都是 −∞,因为它们被屏蔽了。
由于输出被限制在一组固定选项里,模型无法选到选项之外的东西。但这并不保证输出正确。在这种场景下,人们也常把输出 token 的概率当作置信度分数;不过如果没有额外训练,这些分数反映的更可能是模型对“下一个 token 是什么”的把握,而不是“答案正确”的真实概率。
自己动手构建
我们可以用 LLM 通过约束输出 token 来模拟这种行为。这里用的是 Qwen/Qwen3-1.7B。脚本会导入 argparse、json、torch 和 transformers,加载分词器与模型(torchdtype="auto"、devicemap="auto"),把选项 A–E 编码为各自的首个 assistant token id;再用 applychattemplate 把问题拼成带 Answer: 的提示(addgenerationprompt=True、enablethinking=False)。接着对输入做 tokenize,取模型输出 logits 的最后一个位置,只在 optiontoken_ids 上做 softmax,得到各选项的约束概率,最后打印概率最大的选项及各选项概率。
用一个简单问题测试,输入是问题“What color is the sky?”,选项 A 到 E 依次是 Red、Blue、Green、Purple、I don't know。输出为 prediction: B,各选项概率是:A 0.0000(Red)、B 0.9988(Blue)、C 0.0000(Green)、D 0.0000(Purple)、E 0.0012(I don't know)。模型理解了输入,并给出了一个合理对应正确答案的预测。
我们可以用公开数据集测试模型准确率。我在 CommonsenseQA 的一个随机留出样本上跑了测试,结果如下:
| 选项 | precision | recall | f1 | support | | --- | --- | --- | --- | --- | | A | 0.5733 | 0.7197 | 0.6382 | 239 | | B | 0.5506 | 0.7686 | 0.6416 | 255 | | C | 0.5372 | 0.6598 | 0.5922 | 241 | | D | 0.7206 | 0.3904 | 0.5065 | 251 | | E | 0.7519 | 0.4255 | 0.5435 | 235 |
accuracy: 725/1221 = 0.5938,macro f1: 0.5844。
对一个 1.7B 的模型来说不算差。在数据集上快速微调后,表现稍好一些:
| 选项 | precision | recall | f1 | support | | --- | --- | --- | --- | --- | | A | 0.6475 | 0.6611 | 0.6542 | 239 | | B | 0.6113 | 0.6784 | 0.6431 | 255 | | C | 0.6234 | 0.5975 | 0.6102 | 241 | | D | 0.6700 | 0.5418 | 0.5991 | 251 | | E | 0.5808 | 0.6426 | 0.6101 | 235 |
accuracy: 762/1221 = 0.6241,macro f1: 0.6234。
校准你的模型
用一个非常模糊的问题测试模型,会暴露一个有意思的现象。问题是“Where would you most likely find a bat?”,选项为 A Cave、B Baseball game、C Attic、D Zoo、E Sporting goods store。输出预测为 A,各选项概率为 A 0.9978(Cave)、B 0.0004(Baseball game)、C 0.0017(Attic)、D 0.0000(Zoo)、E 0.0001(Sporting goods store)。
这里本来不应该有明确答案,但如果把输出概率当成一种伪“置信度”分数,就会看到模型对这个答案极度过度自信。
如果把之前评估里的置信度区间分桶,就能看到模型的置信度和准确率并不匹配,这意味着模型没有经过 calibrated(校准)。分桶结果如下:
| bin | count | confidence | accuracy | | --- | --- | --- | --- | | (0.00, 0.10] | 0 | 0.0000 | 0.0000 | | (0.10, 0.20] | 0 | 0.0000 | 0.0000 | | (0.20, 0.30] | 3 | 0.2834 | 0.0000 | | (0.30, 0.40] | 26 | 0.3761 | 0.2692 | | (0.40, 0.50] | 41 | 0.4538 | 0.2683 | | (0.50, 0.60] | 70 | 0.5490 | 0.3286 | | (0.60, 0.70] | 74 | 0.6476 | 0.3649 | | (0.70, 0.80] | 77 | 0.7495 | 0.4286 | | (0.80, 0.90] | 121 | 0.8555 | 0.4711 | | (0.90, 1.00] | 809 | 0.9855 | 0.7009 |
可以看到,模型在 0.9–1.0 这一档极度过度自信,但只有 70% 的时候是对的;当它以 0.8–0.9 的置信度做预测时,准确率只有约 40%。这说明模型整体上对自己的预测过度自信。
由于我们的目标是让模型输出的分数能反映其准确率,一种校准方法是 temperature scaling(温度缩放)。通过调整 temperature 值,可以把输出概率分布曲线拉平,并将其缩放到接近实际准确率的水平。以温度 T = 2.2 为例,比较 T = 1.0(未校准)和 T = 2.2(校准后)的输出分布:未校准时,A 2.1%、B 94.3%、C 1.7%、D 1.0%、E 0.8%,期望校准误差为 20.1%,在这个置信度下实际正确率为 82%;校准后(T = 2.2),A 11.2%、B 63.2%、C 10.3%、D 8.2%、E 7.1%,期望校准误差降到 2.9%,实际正确率为 61%。
通过曲线拟合把温度参数拟合到模型准确率上,我得到的温度值是 3.797280788421631。校准后的分桶结果如下:
| bin | count | confidence | accuracy | | --- | --- | --- | --- | | (0.00, 0.10] | 0 | 0.0000 | 0.0000 | | (0.10, 0.20] | 0 | 0.0000 | 0.0000 | | (0.20, 0.30] | 82 | 0.2712 | 0.2317 | | (0.30, 0.40] | 217 | 0.3507 | 0.3917 | | (0.40, 0.50] | 199 | 0.4472 | 0.5126 | | (0.50, 0.60] | 166 | 0.5475 | 0.5482 | | (0.60, 0.70] | 139 | 0.6562 | 0.5827 | | (0.70, 0.80] | 140 | 0.7492 | 0.7714 | | (0.80, 0.90] | 169 | 0.8507 | 0.7988 | | (0.90, 1.00] | 109 | 0.9333 | 0.9541 |
这样校准效果就好多了。如果你想试试,我建了一个 GitHub repo,里面有脚本带你走完构建数据集、评估、微调和校准自己模型的全过程。建议拉取下来,在更大的模型上试一试。
评论
多数评论对 Jev 这类决策模型的炒作持怀疑态度,认为其核心能力并不新鲜、估值或宣传被高估,也有人质疑所谓校准只是事后调温的 p-hacking。只有少数人觉得这篇介绍把词元生成和校准思路讲得很清楚、演示直观,并补充了可在 CPU 上运行的轻量替代方案。
认为 Jev 的零样本分类并不新鲜,实际产出与应用撑不起炒作
- 有机器学习工程师表示,零样本分类器确实比传统分类器方便,也有点酷,但通用大模型早就能以很低成本胜任零样本分类;因此对 Jev 引发的兴奋感到难以理解,觉得多年没人关心的分类器突然被追捧很讽刺。也有人直接追问这是否只是在追求固定的 JSON 输出,并反问:既然被吹得这么高,总该有些用 Jev 做出来的好东西吧。(认可度:较多人) > 通用大模型其实早就可以廉价且实用地做零样本分类了,所以围绕 Jev 的热潮让我内心尖叫。(@howunfortunate)
认为校准只是事后调整温度,接近 p-hacking
- 有人质疑,如果所谓校准只是事后修改温度,让模型在某个基准上看起来更准,这本质是在针对基准做优化,有 p-hacking 嫌疑,结果是否真的稳健值得怀疑。(认可度:少数人) > 单纯靠改温度让模型在某个基准上事后显得校准,这算允许吗?感觉像 p-hacking。(@demibabs)
认为 Jev 估值被高估,算法/数据优势撑不起十亿美元级别
- 有人承认这些模型不错,也带出了不少 Jev 克隆项目,近期融资部分归功于其算法和数据;但这类优势能否构成足够大的壁垒、值不值十亿美元以上估值,仍需要观察。(认可度:少数人) > 这些模型是不错,也催生了不少 Jev 克隆,但那套算法/数据的优势能否撑起十亿美元以上的估值,还得观察。(@ford)
认为这篇概述把 Jev 这类决策模型的思路讲得清晰直观
- 少数人觉得演示很酷,尤其是能操作或观察词元生成过程;文章把如何思考这类模型和校准模型讲得很清楚,对理解 Jev 这类决策模型帮助很大,是一篇不错的入门概述。(认可度:少数人) > 能直接操作词元生成很棒,把模型和校准的思路拆开讲,让我很容易就理解了 Jev 这类决策模型。(@ursaguild)
认为 Jeffy 是更轻量且能在 CPU 上运行的同类替代方案
- 有人认同原项目很酷,并补充说如果想要类似思路但更轻量、能在 CPU 上运行和训练的实现,可以试试 Jeffy,并给出了官网和 GitHub。(认可度:少数人) > 如果你想要类似的但更轻量、能在 CPU 上跑和训练的东西,可以试试 Jeffy。(@nico)