Jev 决策层实验室
TypeSafe AI 在 2026 年 9 月发布了 Jev。你打不开它的权重,多半也没有 API key,但官方自己公布的那些数字,从校准误差到级联成本,都能在这页里现场算一遍。二十章走完,你手上会多一套能拿去审计任何一个「决策模型」宣称的工具,不只是 Jev。
第0章 二十分钟把地基补齐
你大概率见过一句「七成把握」,点开过某个网页背后那次看不见的请求,也在某处瞥过一坨大括号套小括号的文字——这一章不教新东西,只是把这几件散落的常识收到一处,焊死几个后面几十节里天天要用到的说法。
学完这一章你应该能做到
- 看到一个百分数,说出它在大量重复之后的含义,而不是这一次会怎样
- 分清「分类」和「写一段话」这两类任务的根本区别
- 读懂一段 JSON,指出哪里是键、哪里是值
- 不把「百分点」「百分比」「倍数」这三个说法混着用
- 给一个有输有赢的赌局,算出它「平均下来」的结果
- 说清一张图什么时候该用对数坐标,什么时候不该用
一句「七成把握」到底在说什么
扔一枚硬币一次,正面朝上还是反面朝上,你没法预测。但扔一千次,正面大约占一半——这个「大约一半」就是概率。写成 P(正面)=0.5,这句话跟这一次会翻出哪一面无关,它说的是重复很多次之后,正面出现的比例会落在哪。概率永远落在 0 到 1 之间:0 表示这件事从没发生过,1 表示每次都发生。如果一件事只有两种互斥又穷尽的结果——不是正面就是反面,没有第三种——两种结果的概率加起来正好是 1。这条看起来理所当然的算术,第1章会让你亲眼看着它失效。
天气预报说「明天下雨的概率是 30%」。如果只看明天这一天下没下雨,能不能用来判断这句话说得对不对?
如果连续几年里,被预报「30% 概率下雨」的那些日子,实际下雨的比例是 65%,这说明了什么?
「分类」这个词,到底在说哪种任务
给一段文字挑标签、给一封邮件选部门、判断一条评论是好评还是差评——这些都是分类:输入可以是任意的,但输出必须从一个提前列好的、有限的集合里选一个。这和「写一首诗」「总结一段话」不是同一类任务:诗和摘要的输出可以是无穷多种不同的句子,没有一张预先列好的合法答案清单。分类任务的输出空间是封闭的,这一点会在第2、3章反复出现——它正是后面那个「只回答类型化问题」的模型能够成立的前提。
「把这句话翻译成英文」和「判断这句话是不是在抱怨物流慢」,哪一个是分类任务?
「给这次咨询的满意度打 1 到 5 分」算不算分类任务,和「是否抱怨物流慢」这种分类有什么不一样?
点一下「发送」之后,网络那头发生了什么
你的代码把一段文字和几个问题打包成一份请求,发到一个固定的网址——这个网址叫端点——后面跟着一段用来证明「这是你在发请求」的密钥。服务器收到之后处理,把结果打包成另一份文字发回来,这一来一回就是一次 API 请求。本站后面反复出现的就是这样一次请求:发到 api.typesafe.ai/v1/systemone,带着一段客户留言和几个问题;服务器几百毫秒后回一份写着判断结果的响应。你不需要知道服务器内部在算什么,只需要认得请求长什么样、响应长什么样。
「发一次 API 请求」和「打一次电话」最像的地方是什么?
如果同一个网址,你不带密钥直接发请求,服务器最可能怎么回应?
大括号和方括号里装的都是什么
JSON 是一种用文字表示结构化数据的写法:大括号 {} 装一组「键: 值」,键必须是带引号的文字,值可以是文字、数字、真假、空值,也可以是另一层大括号或者方括号 [](一串并列的值)。比如 {"noul": 0.999} 这一段,键是 noul,值是数字 0.999;["billing","technical","sales"] 是一串三个文字。键值之间的冒号、成员之间的逗号一个都不能少——这也是本站后面判断「一次请求写对了没有」最基本的一道检查。
在 {"choice": "billing", "confidence": 0.596} 这段里,confidence 是键还是值?它对应的值是多少?
confidence 在冒号左边,是键;冒号右边的 0.596 是它对应的值,一个键对应一个值,成对出现。choice 在冒号左边是键,冒号右边的 billing 是它对应的值。这段 JSON 其实是两对「键: 值」,中间用逗号隔开。confidence 是键,0.596 是它对应的值。整段 JSON 装着两对「键: 值」:choice 对应 billing,confidence 对应 0.596,两对之间用逗号隔开。键必须带引号(写成 "confidence",不能写成 confidence),值如果是数字就不带引号(0.596 两边没有引号)——少一个冒号或逗号,这段 JSON 就读不出来了。如果要往这段 JSON 里再加一条「department 的值是 billing」,应该写成什么样、加在哪个符号后面?
「快了 60%」和「快了 60 个百分点」是一回事吗
百分比是把一个比例乘以 100、后面跟一个百分号。百分点是两个百分比直接相减的差:正确率从 60% 提到 65%,这是「提高了 5 个百分点」;但如果按相对提升算,(65−60)/60 约等于 8.3%,这是「提高了约 8.3%」——同一组数字,两种说法说的不是同一件事。倍数是两个量相除,「A 是 B 的 3 倍」意味着 A=3B,而且倍数永远需要一个明确的参照对象:不说清楚是「比谁快」,「快了 3 倍」这句话就没有意义。这三个词本站后面几乎每一章都会用到,混着用会直接算错。
某班正确率从 60% 提高到 65%。这是提高了「5 个百分点」还是「5%」?如果说「提高了约 8.3%」,这个 8.3% 又是怎么算出来的?
如果说「B 是 A 的 3 倍」,B 比 A 多出了百分之多少?
一场有输有赢的赌局,「平均下来」该怎么算
一个赌局:抛一枚硬币,正面赢 10 元,反面输 6 元。你没法预测下一次是正面还是反面,但可以算出「平均下来每玩一次」的结果:把每种结果乘以它出现的概率,再加起来,0.5×10+0.5×(−6)=2,平均每玩一次赚 2 元。这个数叫期望值,写成 E(X)=p₁x₁+p₂x₂+…,算的是重复很多次之后,总收益除以次数会落在哪,不针对某一次的结果——后面第8章判断「要不要多花一次钱去问更贵的模型」,用的就是这套算法。
一个赌局:60% 的概率赢 5 元,40% 的概率输 10 元。这个赌局「平均下来」每玩一次是赚是亏,赚亏多少?
如果概率变成 70% 赢 5 元、30% 输 10 元,这个赌局值不值得玩?
四门课的总评,是「一门一票」还是「按学分算」
等权平均是把几项数字直接加起来除以项数,每一项同等重要。加权平均是给每一项配一个权重——比如学分、样本量——按权重折算之后再加总,权重大的项对结果的影响也大。同一组数字,两种算法能给出完全不同的答案。本站后面会出现一个由四项能力合成的「总分」,那四项不管各自内容多寡,在总分里都各占四分之一,用的是等权平均而不是按各项规模折算的加权平均——这不是唯一合理的算法,只是其中一种,第11章会回来细看这个选择本身会带来什么后果。
四次测验成绩分别是 90、90、90、40 分。等权平均是多少?如果第四次测验的题量是前三次的 3 倍,按「权重与题量成正比」算出的加权平均,结果会和等权平均一样吗?
四项权重分别是多少时,加权平均和等权平均一定会算出同一个数?
为什么有的图,格子之间是「乘」不是「加」
如果几个数据点从 0.0001 一路跨到 1,放在一条普通的直线坐标轴上,前面那几个会全部挤在贴着 0 的地方,肉眼分不出 0.0001 和 0.001 差了 10 倍。对数坐标把「乘以 10」变成「往右挪固定的一格」:不管你在标尺的哪个位置,挪同样的距离代表的都是同样的倍数,这样跨越好几个数量级的数据才能同时看清楚。代价是加法在这种坐标上不再直观——两个点之间的距离说的是它们相差几倍,不是相差多少。
在一条对数坐标轴上,0.01 和 0.1 之间的距离,和 1 和 10 之间的距离,哪一段更长?
如果一张图上,0.001 到 0.01 这一段目测比 0.01 到 1 那一段短很多,这条轴还是对数坐标吗?
模型公司嘴里的「token」,按什么收费
token 是模型处理文字的基本单位,不完全等于一个字或一个词,中英文的切法也不一样,大致是几个字符换一个 token。本站后面反复出现的 Jev,定价是每百万输入 token 0.042 美元,输出不计费。官方给过一次真实请求的用量:输入 312 个 token、输出 48 个。按输入单价算,这次输入大约花掉 0.042÷1,000,000×312,约 0.0000131 美元,不到千分之一美分;而那 48 个输出 token,不管用了多少个,都不算进账单。
一次请求用了 312 个输入 token,按每百万输入 token 0.042 美元计价,这次输入大概花了多少钱?
如果这次响应还带回 48 个输出 token,而输出不计费,这 48 个 token 会不会让总花费增加?
某次改动让输入 token 数从 312 个变成 468 个,输出仍然免费。按每百万 token 0.042 美元的单价,这次改动让输入花费该说「涨了 50%」,还是「涨了 50 个百分点」?如果之后又有人说「现在的输入花费是以前的 1.5 倍」,这句话和「涨了 50%」说的是同一件事吗?
如果输入 token 数从 468 降回 312,花费的降幅也该说成「降了 50%」吗?
留给你的问题
一个模型说「有九成五的把握,这是垃圾邮件」,另一次独立的判断又说「有一成的把握,这不是垃圾邮件」。这两个数字能不能像普通百分比一样直接相加减,你凭什么这么想?
不看材料,说出这九个说法分别在讲什么
概率的频率含义 · 分类任务封闭的输出空间 · API 请求的一来一回 · JSON 的键值结构 · 百分比 / 百分点 / 倍数的区别 · 期望值 · 加权平均与等权平均 · 对数坐标为什么等距代表等倍数 · token 怎么计价。挑三个你说不清楚的,回头翻那一小节。
第1章 一个卖家自己写下的 1.19
把两个数字念出来:0.72,加 0.47,等于 1.19——这不是哪个博主拿放大镜挑出来的错处,是卖家自己写在文档里、给自己家模型列毛病的那一页上的原话。
学完这一章你应该能做到
- 看到两个概率数字加起来超过 1,说清这到底违反了什么、又没违反什么
- 判断「归一化」什么时候是在修正误差,什么时候只是在掩盖一个没被检验过的假设
- 给任意一条关于 Jev 的说法,判断它该放进五档证据里的哪一档
- 读懂接下来十九级台阶之间,谁靠着谁才站得住
这一章要给审计仪装上第一个部件:一个能读进一组「命题→概率」、报出哪些组合违反了概率公理的检查器。之前什么都没有,是因为在此之前我们连一个真实模型自己写下的违规案例都没见过。
两个「是不是」的问题,答案能加成 1.19 吗
一段真实工单写着:「I was charged twice for the same order. Can someone look into this?」有人把这条工单分别问了两次:第一次问「顾客是不是在要求退款」,模型答概率 0.72;第二次问「顾客是不是不在要求退款」,模型答概率 0.47。这两个数,你觉得会怎样?
答完再看
官方给出的实测原文就是 0.72+0.47=1.19,写在 jev-1.13 的官方局限说明页里,不是外部人挖出来的。选「一定等于 1」的人,依据的是硬币那种「两种结果互斥又穷尽」的直觉——第0章那条「加起来是1」的算术,这次被这家公司自己的文档打破了。选「小于1」的人的依据也说得通,只是这次没有对上:官方给的另一个例子里,同一张工单换个问法,一个数还比另一个数低了 22 倍,方向并不固定。
最省事的解释是模型算错了——两个本该互补的数字,加起来却超出了 1,这不就是加法出了故障吗?这个解释在这里站不住。官方给出的说明里没有「抱歉,这是个 bug」这类致歉,说明的核心是指出这两次问法问的根本不是同一件事。Choice 是相对的:在几个选项之间分配一份总概率,几个数字生来就被同一次归一化捆在一起,加起来必须是 1。Noul 是绝对的:每次只回答一个孤立的是非题,给出的是这句陈述单独成立的可能性,没有任何机制要求它记得自己刚问过的另一句话。「顾客在要求退款」和「顾客不在要求退款」是两次分开发出的请求,背后各自跑了一次独立的推断,没有人告诉后一次推断,前一次给出的答案是多少。
同一张工单,两次分开发的 Noul
问 refund 给 0.72,问 not_refund 给 0.47,加起来 1.19——两次都是「绝对」判断,却在加法上撞在了一起。
另一张工单,同一个问题问成两种题型
「I'm not happy with the fit. What are my options here?」问「顾客是否要退款」:做成 Noul 给 0.22;做成 yes/no 的 Choice,yes 只有 0.01、no 是 0.99、confidence 0.97——两种问法相差 22 倍。
差别在出问题的方式不一样:前者是两次「绝对」判断互相不设防地违反了加法直觉;后者是「绝对」(Noul)和「相对」(Choice)两种度量本来就不该放在同一把尺子上比,一比就差了 22 倍。
两次问诊,不是一次问诊拆成两半
想象你拿着同一张体检单先后挂了两个号。第一个医生看完说「像流感的可能性大概七成」;你换了个窗口,把同一张单子给第二个医生,问「不像流感的可能性有多大」,对方说「四成七」。两个百分比来自两次独立的问诊,没有人把第一个医生的判断转告给第二个,你没有理由要求 70% 加 47% 卡在 100% 以内,不管这两个医生实际有多熟练。
类比在哪失效:两个医生毕竟是两个不同的人,你本来就不指望他们的判断精确吻合;但 Jev 面对这两个问题时是同一个模型,直觉上会觉得它总该记得自己刚才怎么判断的——这恰恰是官方要澄清的地方:同一个模型的每次请求都不携带上一次请求的记忆,哪怕问的是同一张工单。
答辩:如果我是审稿人
官方那句「Choice 是相对的、Noul 是绝对的」解释了为什么同一个问题问成 Noul 和 Choice 会给出天差地别的数(0.22 对 0.01,差 22 倍),但它解释了 0.72+0.47 为什么会超出 1 吗?两次问的明明都是 Noul,都是「绝对」的,凭什么就不能相加?
参考防守(先自己组织语言再看)
问题恰恰出在「绝对」这个词上。「绝对」的意思是每次评估各自成立、不依赖其他选项瓜分概率,而不是「跟其他判断互相校验过」。两个 Noul 都是绝对的,这保证了它们各自作为孤立判断是自洽的,但没有保证两次孤立判断合在一起满足任何算术关系。官方在这一条上给出的已经是能给的最诚实的结论:不要指望不同问题之间存在算术恒等关系——这句话没有在回避——它承认这里没有更深的机制性解释,只能确认现象、给出规避办法。
如果 TypeSafe 把「退款/不退款」做成一个只有两个选项的 Choice 问题,而不是两个分开的 Noul,两个选项的概率还可能加起来超过 1 吗?
如果这个 Choice 问题有三个选项,三个选项的概率加起来会不会也保证是 1?
把 1.19 除回 1,问题就消失了吗
如果把 0.72 和 0.47 都除以两者之和 1.19,0.72 会变成约 0.605,两个数重新加起来正好是 1。这样处理之后,0.605 是不是就变成了一个更可信的数字?
答完再看
0.72÷1.19≈0.605,算术上没有问题,除法本身不引入任何「计算误差」。但除以 1.19 这一步,悄悄借用了硬币那种「两种结果互斥又穷尽」的结构——只有当「退款」和「不退款」真的共用同一套概率、真的穷尽了全部可能,归一化才是在恢复一个本该存在的分布,而不是在编造一个从没存在过的分布。
归一化要成立,需要一个前提:这两个数字原本就该来自同一个概率分布,只是被除法之外的什么原因搞乱了比例。可这个前提从没被检验过。「顾客在要求退款」和「顾客不在要求退款」是两次分开发出的请求,背后是两次独立的推断过程——没有任何机制保证这两次推断用的是同一套内部信念,更没有人在发请求之前替它们规定「你们俩合起来必须穷尽全部可能」。除以 1.19 确实能让两个数字重新加起来等于 1,这只是数学上抹平了那道 0.19 的缝,不能反过来证明「互斥又穷尽」这个前提本来就成立。
自己推一遍:归一化那一步,到底假设了什么
抛一枚硬币,「正面」和「反面」是唯一的两种结果。P(正面)+P(反面) 为什么必然等于 1?
想好了再看
因为「正面或反面」这句话本身已经穷尽了所有可能,而且两者互斥——把所有可能结果的概率加起来,定义上就是 1。这个 1 不是算出来的,是「所有可能结果」这句话自带的。
如果只知道 P(正面)=0.6,能不能直接推出 P(反面)=0.4?
想好了再看
能,但依据的是上一步那个前提已经成立:正面反面是同一枚硬币、同一次抛掷的两个互斥又穷尽的结果。这个前提在硬币的例子里明摆着,不需要单独验证。
现在把硬币换成两次分开发出的请求——一次问「是退款」给 0.72,另一次问「是不退款」给 0.47。上一步那个「明摆着」的前提,在这里是被保证的,还是被假设的?
想好了再看
是被假设的,而且此前没有人检查过。这是模型两次独立的推断,没有共享状态,没有谁告诉它「这两个问题合起来必须穷尽所有可能」。归一化能算出一个新数字,但算得出数字,不等于那个前提是真的。
同一个 Choice 问题里的选项概率
billing 0.84、technical 0.159、sales 0.001——三个数字来自同一次请求、同一次归一化,API 的契约保证它们的和恒为 1,这不是巧合,是 schema 本身的约束。
两个分开发出的 Noul
refund 0.72、not_refund 0.47——各自是一次独立评估的结果,谁都没有被要求跟对方加起来等于 1,两者之间不存在任何强制的归一化关系。
差别在于有没有一个共享的、强制归一化的概率分布作为两者共同的来源:Choice 有,分开问的 Noul 没有。
举一个例子:两个分开发出的 Noul 问题,答案加起来明显小于 1,而不是像 0.72+0.47 那样大于 1。这说明「跨问题概率不可加」这件事,是不是只往「偏大」这一个方向出错?
如果两个 Noul 问题问的是完全无关的两件事(比如「这条留言提到价格」和「这条留言用了感叹号」),它们的概率加起来会不会更没有理由等于 1?
0.72 归一化之后变成约 0.605。这两个数之间相差多少「百分点」?如果说 0.72 是 0.605 的多少「倍」,又该怎么算?
如果有人说「归一化让这个概率缩水了 16%」,这句话说的是百分点差还是相对变化?
一条断言,该往哪个档位放
0.72 加 0.47 等于 1.19 这件事,你之所以能一路跟到这里还站得住脚,原因是它符合几个具体条件:有原始工单文本,有确切数字,官方自己的解释可以复核,发表在专门列自己毛病的页面上,不是挂在营销页面上——单靠「来自官方」这个身份,撑不起这份可信。把这几条拆开,就是本站接下来十八章都在用的一套打分办法。
证据分级Evidence Grading:同一句「Jev 很准」或者「Jev 有缺陷」,出自不同地方,可信度天差地别——证据分级就是先问这句话是谁说的、怎么测出来的,再决定要不要信,以及信到什么程度。
| 档位 | 含义 | 正文里的语气 |
|---|---|---|
| 一手·官方 | 文档 / 博客 / 评测站 / 定价页——卖家自己说的 | 可以当产品事实用,不能当性能证据用 |
| 一手·官方自承的局限 | 卖家自己承认的问题,比如这一章的 1.19 | 语气可以最硬——连卖家自己都这么写 |
| 第三方·有早期访问 | 拿了厂商早期访问权限的外部测评 | 独立性打折,要写明这层关系 |
| 第三方·自费独立 | 无厂商关系、自己掏钱测的 | 证据等级最高的一档 |
| 本站可算 | 由公开数字经算术或决策论推出 | 必须把算式写出来,读者能自己复算 |
某个不具名的论坛帖子说「我自己测了几十条,Jev 的判断和另一个模型几乎一模一样,准确率不相上下」。这条说法该放进哪一档,为什么够不上「第三方·自费独立」?
如果同样的内容,换成一篇署名博客,公布了完整的测试代码和原始数据,证据档位会不会变,变成哪一档?
还有第六种情况要单独处理:到今天为止一条数据都没有的断言,写「查不到」,不用先验去补——第17章会专门回来清点这份清单。
出声示范一遍怎么用这张表:「0.72 加 0.47 等于 1.19」这条,出自官方自己列自己毛病的那个页面,带着工单原文和确切数字,还能用本节学到的算术复核——这是「一手·官方自承的局限」,语气可以最硬。「官网首页写着比 sonnet 5 快 193.6 倍」呢?这条也来自官方,但它出现在推广页面而不是自曝局限的页面上,厂商自己承认过这类数字大概率偏向了更好看的那一端——同一个「一手·官方」的门槛,却只能当产品事实用,不能直接当性能证据用。两条都来自 TypeSafe,可信的分量却不一样,差别不在是不是官方说的,而在官方说这句话时,有没有动机把它说得比实际更好看。
假设你在某处看到一张对比表,把「官方 workflow 测出的 67.8% 一致率——与两个参照模型给出的共识答案相符的比例,不是人工核对过的正确率」和「某个不具名论坛说 Jev 判断几乎一模一样」放在同一行比较,还顺手写了一句「两者加起来足以说明 Jev 靠谱,误差不超过百分之几」。用这一章学到的两件事——证据要分档、跨问题的数字不能想当然地做算术——各挑一句话,说说这张表错在哪。
如果把表里的「匿名论坛」换成「一篇公布了完整测试代码和原始数据的独立博客」,这张表还有同样的问题吗?
答辩:如果我是审稿人
官方自己开一个页面列自己模型的毛病,会不会只是更高级的公关——承认几个无伤大雅的小问题,反而让读者对其他没提到的地方更放心?
参考防守(先自己组织语言再看)
这个怀疑没法被证实,也没法被证伪,材料给不出「TypeSafe 内部到底怎么想」的证据。能确认的只是这条证据本身的几个具体特征:带着可核对的工单原文和确切数字、发表在专门列局限的页面而不是营销页面上、指向的正是官方自己反复强调的核心卖点——概率可信。这些特征让它比空口的营销话术更值得较真地对待,但不能因此排除「承认局限本身也是一种公关姿态」这个可能性。两件事可以同时为真:这条证据比大多数说法更可信,公司选择公开它也可能有自己的算计。
真未解confidence 这个数到底是怎么算出来的
官方明说 confidence 是「从概率分布里算出来的一个统计量」,但没有给出公式,只说会在未来专门写一篇说明,并且明确表示不希望开发者把这个默认定义当成唯一答案。与此同时,在官方公开的全部文档里检索 ECE、Brier、可靠性图这些校准领域的标准指标,一次都没检到。没有第三方公开逆向出这个公式,包括本站在内。这意味着没人知道这个统计量有没有把「跨问题不满足可加性」这种情况算进去,也不知道它对 0.72、0.47 这类会撞上 1.19 的数字,会不会有额外的惩罚。
先做这一步:官方公开过一组完整的例子——一次 Choice 请求给出概率 billing 0.84、technical 0.159、sales 0.001,官方标注的 confidence 是 0.596;同一次请求里还有一个 Score,概率加权算出 score 1.035,confidence 是 0.842。拿这两组数字,自己试几种候选公式(比如最高概率减次高概率、或者用这组概率算信息熵再换算),看哪种能同时对上这两个 confidence,哪种对不上。
接下来这十九级台阶,先走哪一段
这一章立住脚的,是「校准」这个词第一次被认真拆开——一个概率数字什么时候可信、什么时候不可信,取决于它有没有共享同一个归一化的来源。后面十八级台阶里,「校准」还会被反复搬出来:第4到第9章连续六章围着它转,第10、11、16章会再回来对照它。下面这张图标出了每一章分别用到第0、1章里哪一条道理——箭头指向「用到了」,不是「要等讲完才能碰」。
如果你在第9章卡住了,回头该先查第几章的哪个道理?
如果你只想看「便宜的模型能不能省钱」这件事,不想从第4章的校准学起,材料的结构允许你跳过第5到第7章直接看第8章吗?
这一层要加什么:给审计仪加一个越界检查器
为什么现在才加它:在这之前我们连一个真实模型自己写下的违规案例都没见过,不知道该检查什么样的违规,也不知道「违规」具体是什么意思。
难点:检查器不能看见任意两个数字就去比较它们的和——那样的话,随便塞两个互不相干的 Noul 概率进去,也会被当成「违规」。它只能在输入明确声明了逻辑关系(比如这条是那条的否定)的时候才去检查;没有声明关系的两个数字,压根不该被拿来做加减法,这条边界本身才是这一层真正的难点,不是加法本身。
输入 [{id:"refund",p:0.72},{id:"not_refund",p:0.47,complementOf:"refund"}] → 应报「refund+not_refund = 1.190,偏离 1 达 0.190」;输入 [{id:"refund",p:0.6},{id:"not_refund",p:0.4,complementOf:"refund"}] → 不应报任何问题;输入 [{id:"a",p:1.3}] → 应报「a: p=1.3 越出 [0,1]」。
留给你的问题
如果官方下一次发布,把 confidence 的计算公式也公开了,你会用这一章学到的哪一步,去检验这个公式老不老实?
不看材料,写下这一章的三堵墙
「模型算错了」撞在官方自己给出的、站得住脚的解释上;「除以 1.19 归一化」撞在「这两个问题凭什么构成一个完备事件组」这个没人验证过的前提上;「官方自曝短处」这件事本身,撞在「会不会是更高级的公关」这层怀疑上——而材料能确认的,只是这条证据对官方核心卖点不利,承认和利用承认可以同时为真。
第2章 为什么会有一个不肯说话的模型
一万封邮件堆在队列里,每一封都要决定转给 billing、technical 还是 sales——你手上只有一个会聊天的大模型,没有别的。
学完这一章你应该能做到
- 说清「直接问、要 JSON、约束解码、自评置信度」这四种办法各自撞在哪一步
- 区分「输出格式合法」和「判断本身可信」这两件事
- 解释 System One / System Two 这对说法在描述什么,以及类比在哪里失效
- 设计一份能同时装下三种问法的决策请求数据结构
这一章要给审计仪加上一份决策请求的数据结构——判断的对象、判断的类型、可能的答案范围、一个可以核对的概率,缺一样都装不下三种真实的问法。之前没有这份结构,是因为在四堵墙撞完之前,我们都不知道一个「合格的决策请求」必须包含哪几样东西。
让它回「billing / technical / sales」,它会乖乖照做吗
你写了一句 prompt:「请判断这封邮件该转给哪个部门,只回答 billing、technical 或 sales 这三个词之一,不要说别的」,发给一个聊天大模型,再把返回的文字直接交给下游代码做 if 判断。你觉得会怎样?
答完再看
聊天模型是被训练来「对话」的,即使要求写得再清楚,它也倾向于把答案包在一句完整的话里——比如「根据您提供的信息,我认为应该转给账务部门,因为提到了扣款异常」。多数时候意思是对的,但代码要拿到能直接用的东西,还得先在这句话里把「账务部门」或者对应的 billing 摘出来。
从「回一个词」到「回一句解释」,中间隔着的不是模型犯错,是它本来的训练目标——聊天模型的整套调教,奖励的是那些读起来像一个人在回答问题的输出,不是只吐出枚举值的接口。可以在解析这一侧想办法补救:找关键词、掐头去尾、写一堆正则表达式去应付「账务部门」「billing team」「这属于 billing」这些不同的措辞。这些办法能把一万封邮件里的大多数处理掉,但只要模型某一次把话说得更绕一点,正则就会漏判,而且没法穷举模型可能说出的所有句式。
解析层parsing layer:在模型的自然语言输出和代码之间,专门负责「从一句话里摘出想要的那个词」的那一层——它的规则永远追不上模型能说出的句式变化。
如果模型对同一个问题,这次回「这属于 billing」,下次回「我认为是 billing 相关的问题」,写好的正则表达式要怎么应付这种变化?
如果要处理的邮件从纯英文变成中英文混杂,解析层的规则数量会怎么变化?
那就明说要 JSON,这总该行了吗
如果把 prompt 改成「请用 JSON 格式回答,比如 {department: billing}」,再发给模型,你觉得代码能不能稳定地从返回结果里直接解析出 department 字段?
答完再看
给模型一个 JSON 格式的示例,确实比「只回一个词」管用得多,大多数请求都能拿到合法的 JSON。但「大多数」不是「全部」——不同模型、不同厂商,输出格式坏掉的比例差很多,下面用一张第三方托管平台上的实测表格给出来。
格式坏掉可能是缺一个右括号,可能是在 JSON 前后又加了一句「好的,这是结果:」,也可能是字符串的引号写漏了。代码这边要么加一层容错重新解析,要么整条请求作废重发。第三方托管平台 OpenRouter 测过一批模型在结构化输出上的错误率——这张表测的是「格式有没有输出对」,不是「判断有没有做对」,官方自己也说这组数字不是精确测出来的,只是拿来对比用。
| 模型 | 厂商 | 错误率 |
|---|---|---|
| luna | OpenAI | 0.58% |
| terra | OpenAI | 0.58% |
| sol | OpenAI | 0.83% |
| opus 5 | Anthropic | 5.73% |
| sonnet 5 | Anthropic | 13.2% |
| haiku 4.5 | Anthropic | 45.5% |
haiku 4.5 的结构化输出错误率是 45.5%,sonnet 5 是 13.2%。二者相差多少「百分点」?如果说 haiku 的错误率是 sonnet 的多少「倍」,又该怎么算?
如果一次批量处理 10000 个请求,sonnet 5 的这个错误率大概会让多少个请求需要额外重试或者人工介入?
这张表和后面第11章那张评测总分表,测的不是同一批任务、也不是同一组模型——这里比的是「输出格式有没有坏」,那里比的是「判断做没做对」,两张表不能挪到一起排名次。
把非法 token 的概率直接摁死,不就能保证格式了吗
工程上有一种更彻底的办法:在模型生成每一个字的时候,把不合法的候选概率直接归零,只让它在 billing / technical / sales 这几个词里选。做完之后,还会出现「选错部门」这种错误吗?
答完再看
这种做法有时被叫做约束解码:改写采样器的规则,强制它每一步只能从合法候选里选,不合法候选的概率直接清零、剩下的重新归一化。这能百分之百保证输出是三者之一,不会再有半句解释、也不会再有格式错误。但它锁死的是「输出必须合法」,没有锁死「选中的那个一定是对的」。
已经有人把这个思路做到底了:直接读取模型对每个候选答案打出的原始概率,完全跳过「一个字一个字生成」这一步,比只锁定几个候选词又往前走了一截。社区一个开源复刻项目在一块普通显卡上做了对照实验,用的是同一个冻结的开源小模型,21 个二元判据。
直接读概率,不采样 token
21 个二元判据,同一个冻结的开源模型:1.023 秒,0 个输出 token。
让模型自己写 JSON 数组
同样 21 个判据,同一个模型:5.332 秒,111 个输出 token——慢了 5 倍还多。
差别只在「要不要一个字一个字生成输出」这一步——直接读概率省掉了整个生成过程,这解释了速度差的相当一部分,但和「判断得准不准」没有关系。
这个项目的作者自己写得很清楚:这套东西复刻的是接口形状,不是某个没公开的模型和训练过程本身。这句自我限定正说到了约束解码这堵墙的核心:格式合法是一件事,这次判断该不该信是另一件事。有厂商在描述自家的类型化模型时,也把这两件事分得很开——能保证答案的形状,不能保证每一次判断都是对的:给的是一份类别清单,它编不出清单之外的类别,但它可以选错那一个。反过来说也成立:一个被采样器摁着只能吐三个候选词之一的普通聊天模型,挡住了它把概率分给不合法 token 的路,却没有改变它做判断这件事本身——它心里到底有多确定该选哪一个,采样器管不着,也看不见。
举一个具体场景:一个被约束解码限定只能三选一的问题,输出保证合法,但你有理由怀疑它选错了。描述这个场景,并说出你凭什么怀疑。
如果把三选一换成四选一,加一个「other / 需要人工判断」的选项,会不会缓解这个问题?缓解的是哪一半,没缓解的又是哪一半?
让它自己说「我有多确信」,能顶替校准概率吗
如果在 prompt 里再加一句「请同时给出你的置信度,比如 90%」,模型确实会照做,答案后面跟着一个百分数。这个百分数能不能像「校准过的概率」一样用来做阈值判断——比如「低于 70% 就转人工」?
答完再看
模型确实能生成一个数字,而且往往说得斩钉截铁。问题在于这个数字是「生成」出来的一段文字,和多写一句 JSON 格式要求没有本质区别——它是文字接龙接出来的下一个 token,不是从某个概率分布里读出来的统计量。业内对这种做法的评价很直接:让模型自评「confidence: high」,得到的是生成出来的词,不是校准概率。
这句话拆开看有两层。第一层,生成出来的数字没有任何机制保证它和模型内部的不确定性对得上——模型可能对两个答案其实半信半疑,却因为「听起来要给个高分」这种语言习惯,报出 95%。第二层,即便这个数字某种程度上真的反映了模型的倾向,也没法验证它:要验证「90% 的置信度」是不是真的对应「十次里对九次」,需要收集大量这种数字和最终对错的配对,再统计着看——这正是第4、5章要做的事。自评的置信度绕开了这整套验证,直接把一个没人核对过的数字塞给了下游代码。
如果同一个模型对 100 个不同的判断,每次都自报「置信度 95%」,而这 100 个判断里实际只有 60 个是对的,这说明了什么?
如果换一个模型,自报的置信度虽然也不完全准,但 60% 的判断确实对应着大约 60% 的实际正确率,这个模型和前一个模型比,哪个更值得信任?
这类模型为什么被叫做「系统一」
四种办法都撞了墙——解析太脆、格式有小概率出错、格式保证了但判断本身没保证、自评置信度不可信。如果重新设计一个模型,专门用来做这类闭集判断,你会往哪个方向改?
答完再看
这正是 TypeSafe 给出的答案。他们把这类模型叫做 System One(系统一),旗舰产品叫 Jev,2026 年 9 月 15 日发布——一个只回答类型化问题、并且返回校准概率的模型。名字在这里出现,是因为前面四堵墙已经把「需要什么」逼出来了:更好的解析、更严的格式约束、更会说话的自评,都没能把这件事从根上解决;能解决的做法是一开始就把「输出类型化决策+校准概率」当成训练目标本身,而不是训练完之后再打补丁。
System One 这个名字借用的是心理学里「系统一 / 系统二」这对说法:系统一是那种不假思索、几乎瞬间完成的直觉判断;系统二是那种需要坐下来一步步推理的慢思考。TypeSafe 把自己的模型定位成前者——快、面向有限的判断,而不是需要层层推理的复杂任务。官方在自家列出的「毛病清单」里,把「需要更多层间接推理」的任务直接叫做 System Two tasks,并建议这类任务换别的工具做。
RLHF 优化的目标
官方原话:人类偏好——评分员更喜欢的文字和聊天回复。这套目标把预训练模型变成了聊天机器人,但也可能奖励讨好式的回答和说得很自信的编造。
RLCD 优化的目标
官方原话:校准的决策——在类型化任务上给出诚实反映认知状态的概率。
差别不在哪个更聪明,在训练时奖励的到底是「人喜不喜欢这句话」,还是「这个概率数字可不可信」——两个目标能训出两种完全不同的模型。
系统一,不是「更小的系统二」
系统一 / 系统二这对说法最早用来描述人的思维方式:系统一负责几乎意识不到自己在判断的那类反应,系统二负责能清楚感觉到「我正在思考」的那类推理。把 Jev 定位成「系统一」,是在说它面向前一类任务——闭集的、直觉式的判断,而不是要求层层推理的复杂问题。
类比在哪失效:人的系统一不会随身带着一个百分数——看到一张笑脸时,心里不会冒出「87% confident」这个数字,那种确定感是模糊的、说不清楚的。Jev 恰恰要在这一点上比人的系统一多做一件事:把这种直觉式的判断,逼着它吐出一个可以拿去核对的具体概率。这正是它最大的卖点,也是类比在这里站不住的地方。
RLCDReinforcement Learning for Calibrated Decisions:面向校准决策的强化学习,官方给这套训练方法起的名字。官方把它和 RLHF(人类反馈强化学习)、RLVR(可验证奖励强化学习)并排放在一起,称作继前两条路之后的「第三条路」。
答辩:如果我是审稿人
在 RLCD 之前,至少有三篇公开论文做过「面向校准决策的强化学习」,其中一篇标题就叫「Calibration Aware Reinforcement Learning」,同样是面向决策的 LLM 设定,自称把 ECE 最多降低了 9 个百分点。凭什么说这是「第三条路」,而不是给已有工作换了个名字?
参考防守(先自己组织语言再看)
这几篇更早的工作大多针对单一任务训练专门的分类器——给定一个固定的任务和固定的标签集,训练一个只会做这一件事的模型。Jev 的增量在于把这套目标铺到了任意 prompt 的零样本类型化输出上:不用为每个新任务重新训练,写一段 instructions 和 criteria 就能用。这个区分能不能撑起「第三条路」这个说法,材料给出的只是 TypeSafe 自己的框架,没有独立的第三方论文直接对比过两者的效果差距——这一点该被记进证据分级,目前只是「一手·官方」。
答辩:如果我是审稿人
如果这是训练目标上的根本突破,为什么 Jev 在官方自己的评测总分上,与两个参照模型共识答案的一致率只有 67.8%,和 sonnet 5 打平,却明显低于 opus 5 的 73.1% 和 sol 的 74.1%?一个更懂决策的训练目标,怎么会没有换来更高的一致率?
参考防守(先自己组织语言再看)
这个问题混淆了两个不同的优化方向。RLCD 优化的目标是「在闭集判断上又快又便宜地给出可信的概率」,不是「在多难的任务上答对」——67.8% 打平的同时,成本是 sonnet 5 的几百分之一、耗时是几百分之一,这才是 RLCD 声称要解决的问题。但这个防守本身也留了一个缺口:材料没有给出置信区间,67.8% 和 67.9% 这类差异能不能算「打平」本身也需要谨慎对待——第11章会专门回来处理这一点。
如果要转发的任务换成「根据过去三个月的对话历史,判断这个客户的复购意愿在持续上升还是下降」,不再是「选部门」,这更像 System One 任务还是 System Two 任务?
如果把问题换成「这条最新留言里,客户有没有表达出想要取消订阅的意思」,这还是 System Two 任务吗?
把这一章的两件事放在一起想:①自评的置信度不可信,因为它是生成出来的文字;②官方自己的评测显示,Jev 在总分上只是打平 sonnet 5,没有超过 opus 5 或 sol。如果有人说「Jev 用 RLCD 训练出的校准概率,证明了它的判断能力已经超过用 RLHF/RLVR 训练的前沿模型」,这句话哪里站不住?
如果换一种说法——「Jev 证明了低成本模型也能在特定任务上打平前沿模型的判断一致率」——这句话和原来那句比,站得住脚吗?
这一层要加什么:给审计仪加一份决策请求的数据结构
为什么现在才加它:前面四堵墙撞完,才第一次知道一个合格的决策请求必须包含哪几样东西——判断的对象、判断的类型、可能的答案范围、以及一个可以核对的概率,在这之前没有依据去设计这份结构。
难点:yes_no、pick_one、rate 三种问法看起来很不一样,但代码要用同一套结构去处理它们——如果给每种类型单独发明一套字段,下游代码就得为每种类型各写一遍分流逻辑。真正的难点是找出三者共享的最小字段集合(判断什么、答案是什么、有多可信),同时不逼着 yes_no 也去发明一个用不上的 options 数组。
用这份结构去装三个真实问题(department 是 pick_one、frustration 是 rate、is_urgent 是 yes_no):三个都应该能装进去,department 需要 options 字段,is_urgent 的 options 可以省略或为 null,任何一个都不需要发明新字段。装不进去,或者某一种类型需要额外发明字段,这一层就没通过。
留给你的问题
如果下一家公司发布一个新模型,同样宣称「输出校准概率」,你会先检查哪两件事,才决定要不要相信这句话?
不看材料,写下这一章的四堵墙
直接回复撞在「要解析一句话」上;JSON 撞在「总有一定比例格式坏掉」上;约束解码撞在「格式合法不等于判断可信」上;自评置信度撞在「生成出来的数字不等于从概率分布里算出来的统计量」上——四堵墙各自挡下了一种「让 LLM 顶替类型化决策」的省事办法。
第3章 三种问法:Noul、Choice、Score
把一句话发给 Jev,让它判断该转给客服里的哪个组、客户有多生气、这事儿急不急——服务器会用三种完全不同形状的答案回你:一个数、一个选项加一串概率、外加一个不上不下的小数。
学完这一章你应该能做到
- 独立写出一次 Jev 请求所需的三个顶层字段,并说清
questions里的 key 起什么作用 - 区分 Noul、Choice、Score 三种问法各自返回什么、什么时候该用哪一种
- 看到一个 Score 的结果,不会把 score 相同误当成背后的概率分布也相同
- 看到 probabilities 和 confidence 这两个数不相等,说清楚为什么它们本来就不必相等
- 知道一次请求能问多少个问题受什么约束,并且知道「最多 60 个问题」是错的
这一章要给审计仪加上一层解析器:能看懂 Jev 吐回来的三种不同形状的答案,并且在拿去做进一步计算之前,先检查它们有没有违反自己该守的规矩。前两层只管把请求发出去,这一层开始真正读懂返回来的东西。
一次请求,到底要交代清楚哪三样东西?
第0章说过,一次 API 请求说到底就是你的代码往服务器发一段文字,服务器回一段文字。Jev 这一段文字的格式定得很死:地址只有一个,POST https://api.typesafe.ai/v1/systemone,请求头里带一行 Authorization: Bearer <你的密钥>。这不是那套被大半个行业抄成事实标准的 OpenAI 兼容格式,是 TypeSafe 自己另起的一套,字段名、结构都不一样。
请求体是一段 JSON,最顶层只有三个字段,三个全部必填。state 是要拿去评估的内容,可以是一段文字、一个 JSON 对象,也可以是一个数组,但只接受文本——图片、音频、视频都不支持。model 就是模型名,比如 jev-latest。questions 是一张 map,你想问几个问题,就往里面塞几条,每条问题自己起一个 key,答案回来的时候用同一个 key 对号入座。
如果请求体里只有 state 和 model,没有 questions 字段,这个请求能不能被接受?
state、model、questions 三个全部必填,没有哪个是可选的——少了任何一个,请求体验证就会失败。变式:questions 给了一个空的 {},跟压根不给这个字段,是同一种错误吗?
这个 key 你想叫什么都行——department、q1、随便什么字符串,效果不会有任何差别。官方文档写得很直接:这个 key 不会被发送给底层模型,也不参与推理。它唯一的作用,是让你在收到答案之后,能对着同一个名字把问题和答案配对起来。真正决定模型会怎么想的,是这道题自己的 instructions 和 criteria,跟你给它取的名字没有任何关系——哪怕你把一道问「客户是不是很着急」的题,key 故意写成 department,模型给出的判断也不会因此往「部门」那个方向偏一分。
如果你把 is_urgent 这个 key 改名叫 xyz123,instructions 和 criteria 原封不动,返回的 noul 会不会变?用一句话说清为什么。
answers 里对答案做标记。真正影响判断的只有这道题自己的 instructions 和 criteria,跟 key 叫什么无关。变式:如果你在同一次请求里,把两道完全不同的问题都起了同一个 key,会发生什么?(提示:map 里同一个 key 只能存一个值。)
官方文档的 quickstart 给了一个完整例子——一条客服工单,一次问了三件事:该转给哪个部门、客户有多生气、这事儿急不急。三种问法在这一个请求里全用上了,这一节先看请求整体的骨架,每道题具体怎么写、答案怎么读,留到后面三节里各自展开。
{
"state": "Hi, I've been trying to connect my Stripe account for 3 days and it keeps failing. I'm losing sales. Please help ASAP.",
"model": "jev-latest",
"questions": {
"department": { "type": "choice", … },
"frustration": { "type": "score", … },
"is_urgent": { "type": "noul", … }
}
}
这次的 state 是一段字符串。如果换成一个 JSON 对象(比如把工单的各个字段拆开写),可不可以?如果 state 里要放一张截图呢?
变式:如果你的工单系统里,除了文字还有一张客户上传的截图,这张截图能不能通过某种方式间接参与判断?
服务器回来的响应,三个答案用同样的三个 key 对号入座:
{
"model": "jev-latest",
"answers": {
"department": { "type": "choice", … },
"frustration": { "type": "score", … },
"is_urgent": { "type": "noul", … }
},
"usage": {"input_tokens": 312, "output_tokens": 48}
}
department 用的是 Choice,frustration 用的是 Score,is_urgent 用的是 Noul——接下来三节,一节说清一种,每一节都会把这道题完整的问法和答案摊开来看。
只答是非的问法,返回的那个数到底是什么?
刚才那道 is_urgent 题,完整的问法和答案是这样的:
"is_urgent": { "type": "noul", "instructions": "The message conveys urgency or time-sensitivity" }
// 答: {"type": "noul", "noul": 0.999}
Noul:只问一件事是不是成立,返回一个 0 到 1 之间的数,这个数就是「答案为 yes 的概率」。
必填字段只有一个:instructions,也就是要判断的那件事。criteria 是可选的,如果给,只能有 true 和 false 两个 key,分别说明「答案接近 1 是什么意思」「答案接近 0 是什么意思」。返回的答案里,Noul 没有 confidence 字段——官方文档专门开了一节说明这件事,标题就是「Noul 不返回单独的 confidence 值」。Choice 和 Score 都有 confidence,Noul 没有,这不是遗漏,是这个问法本身的设计。
Choice 和 Score 都有 confidence 字段,Noul 有没有?如果这次判断非常不确定,你能从哪个字段里间接看出来?
变式:如果你的代码不管三七二十一,对所有类型的答案都尝试读一次 answer.confidence,对 Noul 的答案会发生什么?
Noul 的问题不一定要写成疑问句,也可以写成一句陈述句让模型判断真假——比如把「客户是不是在要求退款」写成「the customer is requesting a refund」,如果这事基本确定,返回值就该接近 1。官方原文建议两种写法都在自己的数据上试一试,看哪种效果更好。
0.5 不是「中等程度」
很多人以为 noul=0.5 代表模型觉得「差不多一半一半,算是中等确定」。不是。0.5 只说明 yes 和 no 两种可能性接近相等,不代表任何「程度」。如果要衡量的是「有多生气」「水平多高」这种程度,该用的是 Score,不是把 Noul 的数值当成一把万能的刻度尺来读。
一个 noul=0.52 的答案,能不能理解成「模型有 52% 的信心」?用一句话说清它真正的意思。
变式:如果连续问同一件事两次,一次得到 0.52,一次得到 0.98,这两次的「不确定程度」谁高谁低?
把 is_urgent 那道题改写成陈述句「这条消息传达了紧迫感」,再让模型判断真假,你能不能确定返回的 noul 和原本疑问句形式的问法一定接近?
变式:如果你的产品线上已经用疑问句形式调好了一个判断阈值,现在想换成陈述句写法,这个阈值能不能直接照搬?
要从一堆选项里挑一个,答案该长什么样?
department 那道题用的是 Choice。
Choice:从一组选项里挑出最可能的一个,返回每个选项各自的概率,以及概率最高的那一个。
criteria 是必填字段,是一张「选项 → 描述」的 map,描述可以写 null。选项本身就是这张 map 的 key——不用另外再传一份选项列表,criteria 里写了哪些 key,选项就是哪些。一道 Choice 题最多能放 255 个选项,多传一个选项,多花几个 token 而已。
返回的 probabilities 把每个选项都映射到一个概率,这些数加起来等于 1——这跟 Noul 完全不同,Noul 里 yes 和 no 的概率不保证加起来是 1(后面第1章会专门讲这件事)。
选出 choice 字段的那个值,就是 probabilities 里概率最高的那一个,官方原文叫它「最高概率的选项」。Choice 还带一个 confidence 字段,是从 probabilities 这一整组数字里算出来的一个统计量,不是概率本身。department 那道题完整的问法和答案是这样的:
"department": { "type": "choice", "criteria": {"billing": …, "technical": …, "sales": …} }
// 答: {"choice": "billing", "probabilities": {"billing": 0.84, "technical": 0.159, "sales": 0.001}, "confidence": 0.596}
billing 的概率 0.84、technical 的 0.159、sales 的 0.001,加起来正好是 1;choice 选的是 billing,跟最高概率对上了。但是 confidence 只有 0.596,跟 0.84 差了一大截。
为什么最高的那个概率是 0.84,confidence 却只有 0.596?两者不应该是同一件事吗?
变式:如果三个选项的概率变成 0.34 / 0.33 / 0.33,你预期这次的 confidence 会比 0.596 更高还是更低?
如果一道 Choice 题只剩两个选项,probabilities 会不会仍然要求两个数加起来等于 1?
变式:这一条对 Noul 的 yes/no 也成立吗?(留到第1章验证。)
给程度打分,为什么答案会落在两级之间:Score
frustration 那道题的 criteria 写的是三个等级——冷静陈述、生气但克制、非常愤怒,对应编号 0/1/2。如果两次不同的判断都算出 score=1.0,这两次判断背后,模型给三个等级分配的概率分布,是不是一定长得一样?
答完再看
官方原文的例子:score=1.0 可能是全部概率都压在 level 1 上,也可能是 level 0 和 level 2 各占一半——这两种情况一个是「大家意见高度一致,都觉得是中等程度」,另一个是「意见两极分化,一半觉得完全没事一半觉得非常严重」,含义完全不同,但算出的 score 是同一个数。只看 score 这一个数字,没法把这两种情况分开。
criteria 是必填字段,是一个有序的等级描述数组,至少 2 个、最多 10 个。没有另外的 min/max 或者步长参数——等级号就是数组下标,从 0 开始数,数组的顺序本身就是等级从低到高的编号。
criteria 写的是 ["很少", "偶尔", "经常", "总是"],一共 4 个等级。按下标编号的规则,「总是」对应的等级号是几?
变式:如果 criteria 只写了两个等级 ["否", "是"],两个等级号是 0 和 1,还是 1 和 2?
返回的 score 是等级号的概率加权均值,可以落在两级之间。这正是第0章讲过的期望值:把每一种可能的结果,按它出现的概率加权平均。frustration 这次没有把 probabilities 打印在响应里,但道理是一样的:假如三个等级的概率分布是 {0: 0.165, 1: 0.635, 2: 0.2},加权平均就是 0×0.165 + 1×0.635 + 2×0.2 = 0.635 + 0.4 = 1.035——跟响应里给出的 1.035 对得上。这只是一种举例说明的假设分布,不是响应里没写出来的真实数字;那次响应真实给出的 confidence 是 0.842,不算低,跟「概率比较集中」这个方向大致吻合,但仍然不能只凭 1.035 和 0.842 这两个数精确还原出三个等级各自的概率。正因为像这样的分布不止一种能凑出同一个 1.035,官方才会提醒你:score 落在两级之间,本身就是一种信息损失,probabilities 和 confidence 要一起看,才能把预测门里那两种截然不同的情况分开。
一道 Score 题的 criteria 是 ["入门", "熟练", "精通"](对应 0/1/2),某次判断的 probabilities 是 {0: 0.2, 1: 0.3, 2: 0.5}。这次的 score 应该是多少?
变式:如果 probabilities 变成 {0: 0.5, 1: 0, 2: 0.5},score 还是 1.0 吗?这跟前面预测门里的哪种情况对上了?
criteria 该怎么写,官方给了一条很明确的建议:不要用纯数字当等级描述。原因是每个等级都是分开评估的,模型看不到某个等级的编号,也看不到相邻等级长什么样,「比上一级差」这种话对它没有意义,criteria 里出现的数字本身也帮不上忙。
criteria 写成纯数字
["0", "1", "2"]——模型看不到「这一档比上一档更高」这种顺序语义,三个数字对它来说只是三个不同的符号。实测:score 0.57,confidence 0.35。
criteria 写成描述性文字
换成「冷静陈述」「生气但克制」「非常愤怒」这类描述——每一档自己把自己是什么样说清楚。同一场景实测:score 0.0,confidence 1.0。
差别在:纯数字没有把「这一档意味着什么」说清楚,模型只能瞎猜;描述性文字让每一档的判断标准自己独立成立,不依赖「数字更大就代表程度更深」这种模型未必买账的假设。
举出一组具体的三档 probabilities,让 score 正好等于 0.0——它跟表格里那组「描述性文字」实测结果 score=0.0 是同一种情况吗?
变式:score 等于 2.0(最高一档)呢,是不是也只有唯一一种分布能做到?
两次不同的判断都算出 score=1.0:一次 confidence=0.9,一次 confidence=0.3。只看这两个 confidence,能不能推断出哪一次更可能是「大家意见一致都选中间档」,哪一次更可能是「两个极端对半分」?
变式:如果两次的 confidence 都是 0.9,还能不能靠这一个数分清楚是「全压 level 1」还是「level 0 和 level 2 各半」?
答辩:如果我是审稿人
官方只给了一次前后对比——criteria 从纯数字换成描述性文字,score 从 0.57/confidence 0.35 变成 0.0/confidence 1.0——就得出「反对用纯数字」的结论。换一个场景、换一批数据,这个结论会不会经常反过来?
参考防守(先自己组织语言再看)
这确实只是一个例子,不是系统性的对照实验,样本量是 1。但官方给出的机制性解释是可以独立成立的:模型是分开评估每一档的,看不到相邻档之间的大小关系,数字本身对它不构成「这一档比上一档更高」的语义。这个机制推理即便只配了一个例子,也比一句「我们试过觉得效果更好」这种纯经验性说法更站得住脚——机制说得通,例子印证了机制,但要说这个结论在别的任务、别的等级数量上也稳定成立,材料里没有提供更多证据,这一点没有被证明。
答辩:如果我是审稿人
questions 的 key 完全不参与推理,只用来对答案——那为什么不干脆让 questions 是一个数组,非要设计成 map?这是不是纯粹徒增了一种「以为 key 有用」的误解空间?
参考防守(先自己组织语言再看)
数组按顺序对应也能做到同样的事,但顺序对应有一个更隐蔽的隐患:如果哪次不小心调整了数组的顺序、或者少问了一题,取答案时下标对不上,会把答案悄悄配给错误的问题,而且不会报错。用 map 就不存在这个问题——你自己起的 key 哪怕增删了别的问题,取答案的代码只要认准那个字符串就不会错位。这是用「多打几个字」换「取错答案还不报错」这种更隐蔽的 bug,是合理的权衡,只是这份合理性材料里没有明说,是自己推出来的,不是官方原文。
对你而言未知confidence 到底是从 probabilities 里怎么算出来的
官方原文只说这是「从概率分布算出来的一个统计量」,具体公式没有公开,只承诺以后会单独出一篇 cookbook 讲不同算法各自的取舍。所以答案是存在的——TypeSafe 自己知道,只是没有写进这份材料,目前也还没有公开发表在别处。
先做这一步:自己编几组 probabilities(比如 {a: 0.9, b: 0.05, c: 0.05}、{a: 0.5, b: 0.3, c: 0.2}、{a: 0.34, b: 0.33, c: 0.33}),实际调一次 API,把每组对应的 confidence 记下来,再对照几个候选公式各算一遍——最大概率本身、1 减去归一化信息熵、最大值和次大值的差——看哪个候选公式和实测到的 confidence 最接近。
一次请求最多能塞几个问题?
官方原文说得很明确:一次请求里 question 的数量没有固定上限,只受这次请求的 token 预算约束,state 和全部 questions 共用同一份预算。官方还鼓励一次多问:增加问题几乎不会让响应变慢,多问一个用不上的问题,成本也低到几乎可以忽略。这份预算具体是多少 token,官方不同页面给出的口径并不完全一致,这是第13章要专门拆开讲的一堵墙;这一章先只需要记住,约束的单位是 token 预算,不是问题的条数。
「最多 60 个问题」是错的
这是一个流传较广的二手说法,官方文档里找不到这个数字。真实约束只有 token 预算,官方自己的 cookbook 里,单次请求已经做到过 218 条问题。
有人告诉你「Jev 一次请求最多问 60 个问题」,这个说法对不对?该怎么反驳?
变式:如果一次请求塞了 200 个很短的问题,跟塞 20 个很长的问题,哪种更容易撞到预算上限?
confidence 是怎么算出来的?
Jev 的响应里没有 logprobs——官方文档、API 参考、机器可读的 JSON Schema 里都没有这个字段。confidence 的具体计算公式官方没有公开,只说它是「从概率分布算出来的一个统计量」,并且承诺以后会单独出一篇 cookbook 讲不同算法各自的取舍,但同时也提醒:你并不是被锁死在官方的定义里,因为响应里已经给了完整的 probabilities,你完全可以自己定义一套衡量方式。
两次请求分别得到 probabilities {a: 0.9, b: 0.1} 和 {a: 0.5, b: 0.3, c: 0.2},你能不能确定第一次的 confidence 一定更高?
变式:如果这两次的选项数量一样多,你的把握会不会更大一些?为什么?
该写 jev-latest,还是写死版本号?
当前版本是 jev-1.13.0,jev-latest 和 jev-preview 这两个别名现在都指向它。同时还存在更早的 jev-1.12,官方 cookbook 里有一部分数字就是用 1.12 跑出来的。官方建议生产环境写死具体的版本号,而不是用会漂移的别名——因为别名指向的模型换了之后,你之前针对某个版本调好的置信阈值,会跟着一起失效,而你的代码不会报任何错误提醒你这件事发生了。
生产环境的 model 字段,该写 jev-latest 还是写死成 jev-1.13.0?说清理由。
变式:如果你在做的是一次性的探索性实验,而不是长期跑的生产服务,这个建议还适用吗?
读的时候要小心
超过上下文长度会返回什么错误码,官方没有明说
官方文档把各种硬限制的错误码写得很清楚——401、422、429、529——但唯独「超过上下文长度」这一种情况该返回哪个错误码,没有一处写明。合理的猜测是 422(请求体验证失败那一类),但这是推测,不是文档原文,不能当成写死的结论来用。
留给你的问题
这一章讲的三种问法,都能在同一次请求里随便混用,也可以只用一种。如果接下来要做的事是:根据模型的判断结果,自动决定要不要不经过人工复核就执行某个操作——你会选哪种问法来做这个「要不要自动执行」的最终判断,为什么?
不看材料,写下这一章的三堵墙
key 不参与推理,即便它看起来像个有意义的字段名;Score 的 score 和 confidence 相同不代表背后的概率分布也相同,甚至可能来自完全不同的分布;Choice 的最高概率和 confidence 衡量的不是同一件事,不能拿其中一个替代另一个去读。
这一层要加什么:三种答案的解析器和校验器
为什么现在才加它:前两层只关心怎么把一个判断请求发出去,没有处理答案回来之后该拿它怎么办。Jev 的答案有三种不同的形状,审计仪要是不能先认出「这是哪一种」、再检查「这一种该满足的规矩有没有被满足」,后面所有基于概率做的计算——包括下一章要开始建的校准检验——都是在没验过货的数据上算。
难点:光检查字段存不存在还不够——一个响应可能把三种类型该有的字段名都凑齐了,却仍然是假货,比如 probabilities 加起来是 1.05,或者 choice 压根不是 probabilities 里概率最高的那个 key。校验器得把每种类型该满足的数学约束也编码进去,而不只是「该有哪些名字的字段」,不然它只是个格式检查器,不是真正的审计仪。
自己验:把 quickstart 那份响应里的 department 喂给 checkChoice——0.84+0.159+0.001=1.000,落在容差内;choice 是 billing,正好是三者里最高的那个,应该通过。再把 probabilities 里的 billing 改成 0.9(其余不变,和变成 1.06),应该被第一条 assert 拦下来,而不是被安静地当成合法数据收进后面的计算。
第4章 说 70% 下雨的那个人,怎么算准
天气预报说今天 70% 的概率会下雨,你出门要不要带伞——伞带了,结果一整天大太阳;伞没带,结果傍晚淋成落汤鸡。不管哪一种,你多半都在心里骂了一句这预报员没测准。
学完这一章你应该能做到
- 用自己的话说清「校准」的定义,并说出它和「这一次预测对不对」的区别
- 看到一次预测没应验,判断这能不能说明预报员校准得不好
- 举出一个「完美校准但毫无用处」的例子,说清为什么这两件事能同时成立
- 把一批(概率,结果)数据按预测概率分组,判断某一组是不是校准的
这一章要给审计仪加上一个最基础的部件:一个能把大量「模型给出的概率,后来到底发生没发生」这样的记录,按预测概率分组装进桶里的工具。前三层都在处理单次请求怎么发、答案长什么样,没有一层碰过「这些概率到底准不准」这个问题——因为回答它,需要的不是一次请求,是一大批。
70% 说下雨,结果没下,这就算他错了吗?
预报员说今天 70% 会下雨,结果一整天没下。你觉得这算不算他判断错了?
答完再看
第一种标准看着直觉,但会把预报员逼进一个死角,往下看你就知道为什么。第二种是对的方向,但要走到这一步需要一点推理,不是拍脑袋就能想到——下面正文会把这条路走一遍。
先认真试第一种标准:只要说了「会下雨」结果没下,就算预报员错了。这个标准看着很自然,可是往下推一步——按这个标准,预报员要想「永远不错」,就只能说 0% 或者 100%,因为只要说了任何中间的数字,比如 70%,只要那天恰好没下雨,这次判断就被记成一次错。可现实里的天气预报天天在说 37%、62%、81% 这种数字,没有一个预报员只说 0% 和 100%。这不是预报员偷懒,是因为天气这件事本身就没法被压缩成「一定下」或者「一定不下」两种答案——如果「没应验就算错」是唯一的判断标准,那所有说中间数字的预报员,都注定会被判成「经常错」,跟他们判断得准不准,其实没什么关系。
只看单次结果判对错
说 70% 那天没下雨,直接记一次「错」。这个标准会把所有给出中间概率的预报员都逼成只能说 0% 或 100%,因为中间数字总有「猜错」的那一半。
看这个概率对应的整组结果
把所有「说过 70%」的日子放在一起,看真的下雨的比例是不是接近 70%。单独哪一天下没下,不能单独拿出来评判。
差别在:对错是针对单次结果问的问题,校准是针对一整组预测问的问题——把后者的问法用在前者身上,答案永远是「没法回答」。
如果「没下雨就算错」是唯一标准,一个预报员想让自己「永远不错」,能通过永远报 30% 做到吗?
变式:如果一个地方常年干旱,几乎从不下雨,一个永远报 0% 的预报员在这个标准下会是什么下场?
用一句话说清楚:为什么单独一次「说了 70%,结果没下雨」,没法说明这个预报员校准得好不好?
变式:如果连续 10 次都报 70%,10 次里有 9 次真的下雨了,这说明预报员偏保守还是偏准确?
多少天里下了多少次,才算他说对了?
在所有说「70%」的日子里,真的下雨的比例必须精确等于 70.0%,才叫校准,对不对?
答完再看
官方对校准的定义用的原文就是「大约」——说 0.2 的那组预测,应该在大约 20% 的时候应验;说 0.8 的那组,大约 80%。用「大约」而不是「精确等于」,是因为样本数量总是有限的,第五章会讲清楚为什么样本越少,这个「大约」的松紧就越要小心处理。
把「只看单次结果」换成「看整组」之后,标准就清楚了:校准(calibration)指的是,在所有模型给出某个概率的预测里,真正发生的比例接近那个概率。官方原文对这件事描述得很具体:在一个校准良好的模型给出的大量预测里,被标为 0.2 的那些,应该在大约 20% 的时候应验;标为 0.8 的,应该大约 80% 的时候应验;标为 1.0 的,应该 100% 应验。
预报员 A
说 70% 的那些天,真的下雨的比例接近 70%。
预报员 B
说 70% 的那些天,真的下雨的比例只有 40%。听起来跟 A 一样自信,实际上系统性地报高了。
差别在:两人说的都是「70%」这同一个数字,单看某一天完全分不出谁更可信;只有把各自「说 70%」的那一整批日子摊开来数,才能看出 A 校准得好、B 没有。
官方紧接着补了一句很关键的话:这些比例说的是一组预测的整体情况,不保证任何单次答案是对的。这句话同时是这套卖点的说明书和它的边界——它说明「校准」这件事确实是有严格定义、能被检验的,不是一句空洞的营销话;但它也划了一条界线:不管模型校准得多好,你都不能拿着某一次的输出去问「这次对不对」,校准从来没承诺过这个。一位独立开发者把 Jev 用在电商的商品匹配审核上之后,写下过一句很直白的话:五十条人工复核,根本测不出 0.85 是不是真的对应 85%——他的意思是,人工能核对的样本太小,压根构不成「一组」,校准这件事根本没法在那个规模上被验证。
一个预报员在过去 10 天里说了 10 次「70%」,其中 7 天真的下雨了。按校准的定义,这算不算校准良好?
变式:如果是 10 天里有 5 天下雨,这组「70%」的预测还算校准吗?
构造一个预报员的历史记录:他在「说 70%」的这些天里,整体上确实有 70% 的比例下了雨,因此看起来是校准的——但如果把这些天再拆成「工作日」和「周末」两组分别看,其中一组的下雨比例明显偏离 70%。这样的记录可能吗?举一个具体的例子。
变式:把拆分依据换成「预测时天气台有没有台风预警」(不再按工作日/周末分),同样的抵消现象还可能出现吗?
一个预报员一辈子只发布过一次预测,说明天 70% 会下雨,第二天真的下雨了。这次判断能不能说明他是「校准的」?
变式:如果这个预报员一辈子发布了 3 次预测,全都是「70%」,3 次里 2 次下雨了,现在能不能谈校准?为什么比「1 次」好一点,又远远不够?
一个从不出错的预报员,是不是就有用?
一个预报员每天都说「50% 会下雨」,如果这个地方本来就是一半的天数下雨、一半不下雨,这个预报员按定义算不算校准良好?
答完再看
按定义,他说「50%」的那些天(也就是全部的天),下雨比例正好是 50%,跟预测精确吻合——这是完美的校准。但你每天打开天气预报都看到同一个数字,这份预报对你「今天到底要不要带伞」这个决定,没有提供任何帮助。
这个例子揭示了一件容易被忽略的事:校准好,不等于预报有用。校准只衡量「说出来的概率和实际发生的比例对不对得上」,完全不管这个概率是不是「区分」出了哪天更可能下雨、哪天不太可能——一个从不做任何区分、每天嘴里蹦出同一个数字的预报员,只要那个数字恰好等于当地的平均下雨比例,就能拿到满分的校准成绩。
永远说 50%
如果当地平均下雨比例正好是 50%,这个预报员完美校准——但每天给你的信息量是零,你没法靠它决定今天该不该带伞。
每天给出不同、有区分度的概率
晴天说 5%、阴雨天说 90%,只要分组之后每组也接近校准,这个预报员同样校准良好——但因为他真的在区分哪天更可能下雨,这份预报才谈得上有用。
差别不在校准这一项指标上——两人都可以拿到满分。差别在校准之外的另一种能力,第6章会给这种能力起名字、给它一个可以算的数。
一个预报员每天都精确给出「本地明天下雨的真实概率」(有时 5%,有时 95%),另一个永远说 50%——如果两人在自己「所在的分组」里都恰好对上了实际频率,校准这一项指标能不能分出谁更好?
变式:如果永远说 50% 的那位,其实是把「今天下雨」和「今天不下雨」这两种情况随机分成两组各说一次 50%,这跟他老老实实每天都说 50% 相比,校准结果会不一样吗?
给你两个气象站过去一年的记录。A 站:每天给出不同的降水概率,有时 5% 有时 95%,按概率分组后每组都接近校准。B 站:永远发布「50%」,这一年的年平均降水频率恰好也是 50%,因此这一组同样接近校准。如果只能订阅一个站的预报来决定明天要不要带伞,你会订哪个?这跟「谁更校准」是不是同一个问题?
变式:把 B 站的说法换成永远说「30%」(不再是 50%),但当地真实的年降水频率其实是 60%,这时候再来比较 A、B,问题从「谁更有用」变成了什么问题?
一个预报员每天都说「0%」,如果这个地方极少下雨(一年只下 2 天),他算不算校准良好?这跟「永远说 50%」那个例子,有什么共同点?
变式:如果这一年恰好那 2 个下雨的日子里有一天,这个预报员照常说了 0%,这一天算「预测错了」吗?跟这一章开头的那道墙是不是同一个问题?
官方那句「校准是关于一组预测的统计性质,不保证任何单次答案是对的」,如果被一个法庭场景引用——一个模型说被告有罪的概率是 90%,结果这个被告后来被证明无罪——这句话能不能让做出 90% 这个判断的模型说自己「没有错」?
变式:如果同样这句话,用来回应「保险公司算错了某一位具体客户的赔付概率」,跟法庭这个例子相比,后果的性质有什么不同?
答辩:如果我是审稿人
如果预报员的样本量太小,校准这个数天然就会不稳(比如 10 次里 7 次下雨,样本只多一次少一次,比例就跳好几个百分点),那是不是不该在样本少的时候用校准去评价他?
参考防守(先自己组织语言再看)
这个质疑是对的,但它指出的是「怎么读校准这个数」的问题,不是「校准这个定义本身」的问题。这一章只负责把定义立住:校准是关于一组预测的统计性质。样本够不够大、算出来的数字该在多大范围内浮动才算「正常」,是一个统计推断问题,留到第11章用具体的工具处理——那里会讲清楚,同样是「10次里7次下雨」,样本是10次还是10000次,你对这个70%该有的信任程度完全不同。这一章先把「校准是什么」讲清楚,是往下走的地基。
答辩:如果我是审稿人
官方那句「校准是关于一组预测的统计性质,不保证任何单次答案是对的」,是在老实交代边界,还是提前给自己找好退路?
参考防守(先自己组织语言再看)
这句话在统计学意义上是诚实的、必要的——任何一个诚实谈论概率的人都得这么说,气象学家、保险精算师都是这个立场,不是 TypeSafe 特有的话术。但把它放在一份产品文档里、紧跟在「calibrated decisions」这个卖点后面,确实会起到双重作用:它一方面老实划清了这个技术能力的边界,另一方面也提前给「某次具体判断出了错」这件事准备好了一句可以引用的话。这两种解读都成立,不矛盾——一句话诚实,不妨碍它同时对说话的人有利。
对你而言未知真实的天气预报机构,是不是也用这一套方法检验自己
这一章从头到尾用天气预报做例子,但材料本身完全没有涉及真实气象机构的校准实践——气象学界围绕「降水概率预报」的校准检验,是一个独立存在、历史悠久的领域,答案就在那边,只是不在这份 Jev 相关的材料里。
先做这一步:搜索「probability of precipitation calibration」或「reliability diagram weather forecast」,看气象学家怎么检验「70% 降雨」这句话说得准不准,用的框架跟这一章讲的是不是同一套。
读的时候要小心
「0.2 对应 20%」那三行,是定义,不是 Jev 的实测成绩
官方 primer 页里那三行——概率 0.2 的一组预测应该在大约 20% 的次数里应验、0.8 对应 80%、1.0 对应 100%——描述的是「什么叫校准」这个概念本身,是在给校准下定义,不是在报告 Jev 自己测出来的成绩单。这份材料里没有一张表,把 Jev 在哪个真实任务上的预测按这套定义验过、验出的结果是多少。这一点不影响「校准是什么」这件事讲清楚,但会影响你下一次看到「我们家模型是校准的」这句话时,该往下多问一句:校准到什么程度,数字在哪。
留给你的问题
一个每天精确报出本地明天下雨概率的预报员,和一个每天都说「50%」的预报员,如果两人恰好都落在了自己该落的那个校准区间里,只看「校准」这一项指标,谁会被判定为更好?这个判断本身,是不是已经说明了只看校准这一项,可能会推荐出错误的选择?
不看材料,写下这一章的三堵墙
「没应验就算错」这个标准,会把预报员逼得只能永远说 0% 或 100%;校准是一组预测的统计性质,从来不保证任何单次答案是对的;一个永远说同一个数字的预报员也可以是完美校准的,校准好不等于预报有用。
这一层要加什么:把一批(概率,结果)装进桶里
为什么现在才加它:前三层处理的都是单次请求——发一次、答一次。校准是一个只能从一大批答案里才能看出来的性质,审计仪必须先有一个能装下很多次「模型说的概率,后来实际的结果」并且按概率归堆的容器,后面几层要算的每一个数都建在这一层上。
难点:桶的边界怎么定不是随便的——0.70 该算进「0.7 这一桶」还是算进「0.6 这一桶」的右边界,不同的取整方式会让同一条记录换桶,进而让同一批数据算出略微不同的实测频率。选定一种规则之后,全程都要用同一种,不然桶与桶之间没法比。
自己验:给这批数据 [{p:0.7,y:1},{p:0.7,y:0},{p:0.7,y:1},{p:0.3,y:0},{p:0.3,y:0},{p:0.3,y:1}],width 取 0.1,应该装出两个桶:0.7 桶有 3 条、实测频率 2/3;0.3 桶有 3 条、实测频率 1/3。把其中 0.7 桶那条 y:0 的记录改成 y:1,0.7 桶的实测频率应该从 2/3 变成 3/3=1。
第5章 把校准画出来:可靠性图与 ECE
上一章最后,你已经能把一堆(概率,结果)按概率分好桶了。桶排好之后,摆在你面前的是一张表——不是一个词、不是一句「校准得不错」,是很多行数字。
学完这一章你应该能做到
- 从一批(预测概率,结果)数据,亲手画出可靠性图的思路,看懂对角线代表什么
- 写出 ECE 的公式,说清每个符号的含义,能对一张小数据表手算出 ECE
- 说出 Brier 分数为什么同时惩罚「不准」和「不诚实」,并能举出具体数字
- 说清楚为什么桶数越多,ECE 这个数就越不稳,而不是越精确
- 看懂 Jev 在 7 个数据集上的 ECE 表,指出哪条口径结论是错的、哪条是对的
这一章要给审计仪加上真正能出数的两个部件:ECE 和 Brier 计算器。上一章的分桶工具只是把数据归了堆,这一章要把每一堆变成一个能拿去比较、拿去质疑的数字——而这两个数字,官方自己在最核心的卖点上一个都没给过,这一章会亲眼去确认这件事。
怎么才能看出一整批预测靠不靠谱?
把每个桶画成一个点,横轴是这个桶的平均预测概率,纵轴是这个桶的实测频率——如果一个预报员完美校准,这些点会连成什么形状?
答完再看
完美校准意味着「预测概率=实测频率」对每个桶都成立,也就是横坐标等于纵坐标——这正是 y=x 这条对角线。点越靠近这条线,这一桶校准得越好;点偏离对角线越远,这一桶的偏差就越大。
这张图叫可靠性图(reliability diagram):横轴是各桶的平均预测概率,纵轴是各桶的实测频率,每个桶画一个点,旁边通常再画一条 y=x 的参考线。
预测概率 0.30 的桶
桶内实测频率 0.32,几乎贴着对角线,这一桶校准得很好。
预测概率 0.65 的桶
桶内实测频率只有 0.40,明显偏离对角线——模型在这一桶里过度自信,说了 65% 的把握,实际只兑现了 40%。
差别在:同一张可靠性图里,不同的桶可以有完全不同的校准表现,一整条曲线好不代表每一段都好,读图时要看的是每一个点离对角线多远,不是笼统地看「大体上贴着」。
可靠性图上有一个点,坐标是(预测概率 0.8,实测频率 0.5)。这一桶校准得好不好?差多少?
变式:如果这一桶的坐标反过来是(预测概率 0.5,实测频率 0.8),该怎么描述这一桶的偏差方向?
一个点落在对角线上方(实测频率大于预测概率),和落在对角线下方(实测频率小于预测概率),分别说明这一桶的模型是「过度自信」还是「不够自信」?
变式:一个模型如果所有的桶都系统性地落在对角线下方,这跟第10章要讲的「0% 幻觉」这个卖点,会不会有关系?
怎么把这张图变成一个数?
图上散落着好几个桶的点,要把它们汇总成一个能拿去比大小的数,你觉得该怎么算?
答完再看
第一种做法会让样本数很少(可能只有两三个点、噪声很大)的桶,和样本数上千的桶权重相同,明显不合理。第三种做法有它的用处,但那是另一个指标,正文接下来会讲到。中间这条——按样本占比加权——就是 ECE。
把这个想法写成公式,就是期望校准误差(Expected Calibration Error, ECE):对每个桶,算出「实测频率」和「平均预测概率」的差,取绝对值,再按这个桶占全部样本的比例加权,最后把所有桶加起来。
| 符号 | 是什么 | 直觉 |
|---|---|---|
| B | 桶的总数 | 你把预测切成了几份 |
| b | 第几个桶的编号 | 从 1 数到 B,逐桶算一遍 |
| nb | 第 b 桶里有多少个预测 | 这一桶装了多少样本 |
| N | 全部预测的总数 | 分母,所有 nb 加起来 |
| nb/N | 第 b 桶占全部样本的比例 | 这一桶在最终结果里占多大分量 |
| p̄b | 第 b 桶里预测概率的平均值 | 模型在这一桶里自称有多有把握 |
| ōb | 第 b 桶里事件真实发生的比例 | 这一桶里实际发生了多少次 |
| |p̄b − ōb| | 这一桶「自称的把握」和「实际发生比例」差多少 | 这一桶的校准误差有多大 |
两个桶:桶 A 有 3 个样本,预测概率 0.9,实测频率 2/3;桶 B 有 3 个样本,预测概率 0.6,实测频率 1/3。这批数据的 ECE 是多少?
变式:如果桶 A 有 30 个样本、桶 B 只有 3 个样本(其他数字不变),ECE 会怎么变?
把「按占比加权平均」换成「只取最大值」,就是另一个相关的数:MCE = maxb |p̄b − ōb|——预测门里那个「只看偏差最大的桶」的想法,就是最大校准误差(Maximum Calibration Error, MCE)。
ECE 关心的问题
整体上、平均而言,这个模型的校准误差有多大——一个数字总结一整张图。
MCE 关心的问题
最糟糕的那个桶,能糟到什么程度——哪怕只有一小撮样本落在一个校准很差的区间,MCE 也会把它揪出来,ECE 因为加权平均,可能把它稀释得看不出来。
差别在:ECE 答的是「总体上能信多少」,MCE 答的是「最坏情况下能信多少」——一个自动化系统如果任何一次误判都代价高昂,该盯的是 MCE,不是 ECE。
同一批原始数据,如果换一种分桶方式(比如把桶宽从 0.1 改成 0.2),算出来的 ECE 会不会变?
变式:如果把桶宽改到极端,比如整批数据只分一个桶,ECE 会变成什么?这时它还能反映「校准好不好」吗?
构造一批数据,让「用 0.5 做阈值判断对错」的准确率是 100%,但 ECE 很大(模型明显不校准)。这可能吗?
变式:如果把「0.40」换成「0.51」(仍然大于 0.5),这批数据的准确率还会是 100% 吗?
自己推一遍:ECE 和 Brier 是不是在算同一件事
ECE 要按预测概率分桶,每桶算一个「平均预测 − 实测频率」的差。Brier 分数(下一节会给出定义)逐条计算 (pi−yi)² 再求平均,压根没提到「桶」。如果也把 Brier 里的每一条,按它的预测概率 pi 分到跟 ECE 一样的桶里,每桶内部会发生什么?
想好了再看
同一个桶里的点,预测概率都落在这一桶的范围里——如果把这一桶所有点的预测概率都近似看成这一桶的平均值 p̄b(桶分得越细,这个近似越准),那这一桶里的 (pi−yi)²,就几乎是同一个数被反复算了 nb 次,只有 yi 在 0 和 1 之间跳。
这一桶里 nb 个点,实测频率是 ōb(也就是 yi=1 的比例)。把这一桶所有 (p̄b−yi)² 加起来再除以 nb,能不能只用 p̄b 和 ōb 这两个数(不需要每一条的 yi)把这个桶内平均写出来?
想好了再看
能。桶内平均 = ōb(p̄b−1)² + (1−ōb)(p̄b−0)²,展开整理后等于 (p̄b−ōb)² + ōb(1−ōb)——前一项就是 ECE 里那个「预测和实测之差」,只是从取绝对值变成了取平方。
把每一桶的 (p̄b−ōb)²,按桶的样本占比 nb/N 加权求和——这一项用的,跟 ECE 是不是同一张桶表?
想好了再看
是同一张表:同样的 p̄b、同样的 ōb、同样的权重 nb/N,ECE 取的是 |p̄b−ōb|,这里取的是 (p̄b−ōb)²——加权求和之后,是同一件事的两种量法,一个用绝对值,一个用平方。
Brier 分数减去这一块「平方版 ECE」,剩下的是 ōb(1−ōb) 按桶加权的另一块——这一块跟「预测得准不准」完全无关,只跟「这一桶里的真实结果本身有多不确定」有关。它该叫什么、Brier 为什么非要把它也算进去?
想好了再看
这一块该怎么拆、该叫什么名字,是下一章的问题——这里只需要看清一件事:Brier 不是一个跟 ECE 不相关的新指标,它的一部分,就是 ECE 换了个量法而已。
为什么 Brier 分数要同时惩罚两种错?
一个模型对同一批真实发生的事,一次自信地说「95% 会发生」(结果真发生了),另一次同样自信地说「95% 会发生」(结果没发生)。这两次哪一次该被罚得更重?
答完再看
自信地说对了,几乎不该罚;自信地说错了,恰恰是最该罚的情况——「自信」在这里放大了后果,不是减轻了后果。下面正文会把这两种情况的具体数字算出来。
Brier 分数(Brier score):把每一条预测概率和实际结果之差取平方,再对所有预测求平均。
| 符号 | 是什么 | 直觉 |
|---|---|---|
| N | 预测的总条数 | 样本一共多少条 |
| i | 第几条预测的编号 | 从 1 数到 N,逐条算 |
| pi | 第 i 条预测给出的概率 | 模型对这一条有多有把握 |
| yi | 第 i 条的真实结果,1 或 0 | 这件事到底发生没发生 |
| (pi − yi)² | 这一条把握和结果之间差多少,取平方 | 差得越远,罚得越重,而且是加倍地重 |
自信且说对:p=0.95,真发生了
(0.95−1)²=0.0025,几乎不扣分。
自信却说错:p=0.95,没发生
(0.95−0)²=0.9025,扣掉几乎满分——同样是「95%」这个数字,结果一反过来,代价差了 361 倍。
差别在:Brier 用平方,不是用绝对值——数值上离得越远,罚得不是等比例地重,是加速地重,这正是它「惩罚不诚实」的机制:越是把话说满,说错的代价就越陡峭地上升。
如果一个模型永远只敢说 0.5,不管真实结果是 1 还是 0,Brier 分数都是 (0.5−1)²=0.25 或者 (0.5−0)²=0.25,永远是 0.25——比自信且说对的 0.0025 差得多,也比自信且说错的 0.9025 好得多。这就是 Brier「惩罚不准」和「惩罚不诚实」这两件事同时发生的地方:说得越极端、赌得越大,对的时候赢得越多,错的时候也输得越惨;永远含糊其辞地说 0.5,永远稳定地拿一个中等偏差的分数,赢不了大的,也输不了惨的。
三条预测:(p=0.9, y=1)、(p=0.9, y=0)、(p=0.2, y=0)。这三条的 Brier 分数是多少?
变式:把第二条的 p 从 0.9 改成 0.5,Brier 分数会变成多少?变好了还是变差了?
把一条「自信却说错」的预测 (p=0.95, y=0) 改成对冲到 (p=0.5, y=0),Brier 分数会怎么变?这条预测现在能拿到接近 0 的好分数吗?
变式:如果这一条的真实结果 y 是 1(不是 0),对冲到 0.5 之后 Brier 会不会有同样的改善幅度?
模型 A:ECE=0.05,Brier=0.24。模型 B:ECE=0.15,Brier=0.10。只看这两个数,你会说哪个模型「更校准」,哪个「整体更好」?这两个判断矛盾吗?
变式:如果又给出模型 C,ECE=0.05,Brier=0.35,它跟 A 相比说明了什么?
桶开多细,这个数就多可信?
桶数的选择本身是一个容易被忽略的陷阱。桶越多,每一桶摊到的样本就越少;样本越少,这一桶算出来的实测频率就越不稳。想象一个桶只有 3 个样本,其中 1 个命中,这一桶的实测频率就是 33.3%——只要换一个样本的结果,它立刻跳到 0% 或者 66.7%。单单一个样本,就能让整桶的读数跳动 27 个百分点以上。把桶数从 10 个增加到 100 个,平均每桶的样本量从 N/10 降到 N/100,这种跳动只会更剧烈,不会更精确。
这跟「桶数越多,看起来分辨率越高」这种直觉正好相反:分辨率确实变高了,但每一格读数的可信度,是拿稳定性换来的分辨率,不是白得的。这一条会在后面用统计工具处理样本量够不够的问题时,重新变得重要——一张校准表如果没有说清楚每一桶有多少样本,这张表本身就不完整。
一个桶只有 1 个样本,为什么「校准」这个词根本没法套用在它身上?
变式:桶里有 2 个样本呢?跟 1 个样本相比,本质上的问题解决了吗?
答辩:如果我是审稿人
ECE 依赖桶宽、桶数这些人为选择的参数,同一批数据换一种分桶方式就能算出不同的 ECE——这样一个依赖人为设定的指标,够资格当成唯一的校准判据吗?
参考防守(先自己组织语言再看)
这个质疑站得住,ECE 确实不是一个跟分桶方式无关的「客观真值」。但这不等于它没用——只要报告的时候把分桶方式(桶数、桶宽、每桶样本量)一起写清楚,不同的人拿着同样的分桶规则,能复现出同样的 ECE,它仍然是一个可复核、可比较的数字,只是「可复核」的前提是分桶方式本身也要公开,不能只甩出一个孤零零的数字。这份材料里 zhuyansen 那张表恰好做到了这一点——固定分桶、置信区间、原始数据都能对得上,这才是它被列为最高证据档的原因。
把一个模型的把握往两端推一把,会发生什么?
拿一个模型的输出,把所有大于 0.5 的概率都往 1 推(比如 0.6 变成 0.9),所有小于 0.5 的都往 0 推——只要没有跨过 0.5 这条线,用它做判断时的 accuracy 会变吗?ECE 呢?
答完再看
用阈值 0.5 做判断时,谁在哪一侧完全没变,所以 accuracy 纹丝不动;但预测概率本身变得比原来更极端,如果原来已经是校准的,推向极端会让预测显得比实际更笃定,ECE 通常会变差。正文接下来把具体数字过一遍。
用第4章末尾那批数据验证一下:原始数据是 (p=0.9,y=1)、(p=0.9,y=1)、(p=0.9,y=0)、(p=0.6,y=1)、(p=0.6,y=0)、(p=0.6,y=0),算出的 ECE 是 0.25(第5-2节算过)。把 0.9 推到 0.97、把 0.6 推到 0.75,阈值判断的对错完全不变——0.97 和 0.6 都还在 0.5 的同一侧,谁被判为「预测发生」谁没变,accuracy 原封不动。但重新算 ECE:桶「0.97」实测频率还是 2/3,偏差从 0.233 变成 |0.97−0.667|=0.303;桶「0.75」实测频率还是 1/3,偏差从 0.267 变成 |0.75−0.333|=0.417。新 ECE = 0.5×0.303+0.5×0.417=0.36,比原来的 0.25 明显更差——accuracy 一个百分点没变,ECE 却肉眼可见地变差了。
推之前
预测概率 0.9 和 0.6,ECE=0.25,accuracy 由阈值 0.5 决定,两组预测各自留在原来那一侧。
推之后
预测概率 0.97 和 0.75,ECE=0.36(明显变差),但两组预测依然各自留在原来那一侧,accuracy 完全不变。
差别在:accuracy 只看阈值两侧谁归哪一类,这个操作没碰这条线;ECE 看的是具体数值离实测频率有多远,这个操作恰恰把数值往远处推了一截。
为什么「推向极端」只要没跨过 0.5,就一定不影响 accuracy,却几乎总会影响 ECE?用一句话说清两者依赖的东西有什么不同。
变式:有没有一种「推向极端」的操作方式,可以让 accuracy 和 ECE 同时保持不变?
Jev 的校准分数,和谁比?
zhuyansen/jev-zeroshot-vs-bert 这份第三方评测跑了 7 个数据集,选项数从 2 一路到 77。你觉得:随着选项数变多,Jev 的 ECE 会不会跟着单调变差?
答完再看
实测:只有 2 类的 PAWS,ECE 是 0.069,比有 8 类的 arXiv 2020(ECE 0.036)还差——选项数和 ECE 不是一条干净的单调曲线。但 77 类的 Banking77 确实是 7 个数据集里 ECE 最差的一处(0.208),也是唯一明显输给基线的一处。两件事都是真的,缺一句都会讲错。
第三方评测 zhuyansen/jev-zeroshot-vs-bert 在 7 个数据集上测过 Jev 的 ECE,固定 held-out 集合,bootstrap 95% 置信区间,还做了污染对照,自费完成,是这份材料里证据等级最高的一档。
| 数据集 | 类别数 | Jev | 最好的基线 |
|---|---|---|---|
| SST-2 | 2 | 0.022 | nli-bart 0.016 |
| PAWS | 2 | 0.069 | nli-deberta 0.101 |
| AG News | 4 | 0.076 | nli-bart 0.039 |
| TweetEval-emotion | 4 | 0.062 | nli-bart 0.044 |
| arXiv 2026 | 8 | 0.041 | nli-bart 0.096 |
| arXiv 2020 | 8 | 0.036 | nli-deberta-c 0.067 |
| Banking77 | 77 | 0.208 | nli-deberta-c 0.081 |
有人看了这张表说「Jev 的类别数越多,校准就越差」,这个说法对不对?拿 PAWS 和 arXiv 这两行的数据反驳它。
变式:如果只用 SST-2(2类)和 Banking77(77类)这两行做对比,这个「越多越差」的说法看起来是对的——为什么只挑这两行会误导人?
PAWS——2 类,ECE 却是 0.069
类别数是 7 个数据集里最少的一个,ECE 排在中间偏差的位置,比基线的 0.101 好,但明显不是「类别少就该轻松校准」的样子。
arXiv 2020——8 类,ECE 只有 0.036
类别数是 PAWS 的 4 倍,ECE 反而是 7 个数据集里最小的之一——类别数量本身,解释不了这个差距。
如果「类别越多越难校准」是对的,这两行的大小关系应该反过来。真正决定 ECE 高低的是别的东西。
不能从这张表里读出「答案空间越大,校准就越差」。能读出来的只有一句:Banking77 这 77 类,是 Jev 校准明显最差、也是唯一明显输给基线的一处,0.208 对基线的 0.081,差了一大截,而这恰好是「255 选项上限」最有诱惑力去使用的场景——选项越多,好像越能一次问完,但这张表说明选项多到 77 个的时候,Jev 自己的校准已经在这批测试里明显失守。还有一点要一起说清:官方在 Banking77 上走的是两步层级分类(先分大类,再在大类内部细分),跟这里其他模型一次性打完 77 类的做法不是同一套流程,两者不能直接比较。
答辩:如果我是审稿人
Banking77 那一行,Jev 用的是两步层级分类,别的模型是单次分完 77 类——如果这两种流程本来就不能直接比,为什么这张表还是把它们排在同一列里?
参考防守(先自己组织语言再看)
把不可直接比较的两种流程放进同一张表,确实容易让读者产生「原始类别数越多,ECE 就该越大」这种误导印象——这正是这一节反复强调不能这样读表的原因。但把它们放进同一张表也有价值:读者需要先看到「同一个类别数下,两种方法结果差这么多」这件事本身存在,才会去追问「为什么」,进而发现两步与一步流程不可比这个关键差异。表格本身没有错,错的是不加说明地只看最后那两个数字、跳过这条流程差异直接下结论。
对你而言未知Jev 的校准误差在不同数据集之间的差异,背后有没有更深的规律
这一节已经排除了「类别数越多越差」这条错误的解释,但没有回答真正的问题:为什么 PAWS(2 类)会比 arXiv(8 类)差、TweetEval-emotion 会比 SST-2 差。答案不在这份材料里——一般机器学习里关于「什么因素驱动分类任务的校准误差」(标签本身的语义清晰度、类别之间的可分性、类别是否失衡)是一个有公开文献的领域,只是没有人把这套框架专门套到 Jev 这 7 个数据集上算过。
先做这一步:去读 zhuyansen/jev-zeroshot-vs-bert 仓库里 PAWS 和 arXiv 这两个数据集的 results.md 原始数据,看看每个类别内部的样本量、类别之间的语义相似度(PAWS 的两类本来就是「同义改写」和「不是」,边界天然模糊)有没有明显差异,再对照一般校准文献里「标签模糊度影响 ECE」这条思路是否说得通。
这个卖点,官方给了几个数?
官方文档站提供一份全量文本转储,把所有页面拼在一起,大小 874KB,可以像一份普通文本文件那样直接检索。在这份转储里搜索 ECE、expected calibration error、Brier、reliability diagram、calibration curve 这几个词,命中次数全部是 0。搜索词根 calibrat*(涵盖 calibration、calibrated、well-calibrated 这些变形),命中 25 次——但摊开这 25 次逐条看,没有一次带着数字或者图表,全部是「calibrated decisions」「calibrated probabilities」这类定性说法。
这一章从头到尾算的这一切——ECE、MCE、Brier——都不是在复述官方给出的某个数字,是在补一个官方选择不给的数字。「校准」是这个模型最核心的卖点之一,而在这 874KB 的官方文档里,恰恰是这一处,一个可验证的数值指标都没有出现过。
calibrat* 这个词根在官方文档里出现了 25 次,这是不是等于官方已经发布了自己的校准指标?说清楚区别。
变式:如果官方文档里出现过一次「ECE 是 0.03」这样的具体数字,但没有说明是在哪个任务、多大样本上测出来的,这算不算「给了数」?
读的时候要小心
ECE 依赖分桶方式,跨材料比较时要格外小心
这一章反复用到的 ECE,数值大小本身依赖桶的划分方式——不同论文、不同评测用的分桶规则未必一致。zhuyansen 那张表内部的 7 个数字之间可以放心比较,因为它们用的是同一套分桶规则;但如果把这张表里的 ECE 和别的地方、用别的分桶方式算出来的 ECE 直接放在一起比大小,比的可能不是同一个口径。
留给你的问题
如果有人给你两个模型的 ECE,一个是 0.03,一个是 0.08,但没有告诉你各自用了多少个桶、每桶多少样本——你能不能就凭这两个数字,说 0.03 那个模型「更校准」?这一章讲的所有工具里,哪一件是回答这个问题时真正缺失的那一块?
不看材料,写下这一章的三堵墙
把桶按样本占比加权平均,才是 ECE,简单平均或只看最大偏差都是另一回事;Brier 用平方而不是绝对值,让「自信却错」的代价随偏差加速上升,同时又给「永远说 0.5」这种不诚实的中庸留了一个稳定但不算好的分数;桶数越多,每桶样本越少,ECE 这个数本身就越不稳,不是越精确。
这一层要加什么:ECE/Brier 计算器
为什么现在才加它:上一层只把数据分了桶,这一层要把桶变成数——没有这一步,后面几章要用到的「校准好不好」「值不值得级联」「阈值该定在哪」这些判断,全都没有落脚的地方。
难点:ECE 该用桶的代表值(比如取桶下界 0.6)还是桶内真实的平均预测值去跟实测频率比,这两种取法在桶宽较大时会算出不同的 ECE——一个诚实的计算器该在文档里说清楚自己用的是哪一种,不能含糊带过,不然拿这个数去跟别人的表比较时,比的可能根本不是同一种口径。
自己验:把 [{p:0.9,y:1},{p:0.9,y:1},{p:0.9,y:0},{p:0.6,y:1},{p:0.6,y:0},{p:0.6,y:0}] 喂进去,ECE 应该落在 0.25,Brier 应该落在 0.285。把其中一条 {p:0.6,y:0} 的 y 改成 1,Brier 应该下降(变得更好看),因为 0.6 离 1 比离 0 近。
第6章 一个分数拆成三笔账
上一章教会你打一种分:把一个模型说过的每一句「我有百分之多少把握」,和后来到底对没对,放在一起,画成一条线,再压成一个叫 Brier 分数的数字。可是上一章结尾留了一个别扭的例子——一个不管遇到什么都回答「50%」的预报员,那条线会紧贴对角线,堪称完美。一个数字,能不能既说出他有多老实,又说出他到底有没有用?
学完这一章你应该能做到
- 把任意一组(概率,结果)按第5章的分桶方法,拆成可靠度、分辨度、不确定度三项,并验证三项之和等于直接算出的 Brier 分数
- 用这三项分开说清「这个模型校准差」和「这个模型没有分辨力」是两件不同的事,不是同一件事的两种说法
- 推出「永远给出同一个概率」的预测者在这个分解里必然落在哪个位置,并说清这对判断一次评测的分量意味着什么
这一级要给审计仪加一个部件:Brier 分解器。前五级台阶只能告诉你一个模型校不校准、Brier 分数是多少,却分不清一个差分数背后,到底是校准没做好,还是压根没有分辨能力——这一级把这两件事拆成两个可以分别读的数。
一个永远说50%的人,考出的分数说明了什么
第5章说过,有一种预报员,不管明天天气如何,永远回答「降雨概率50%」。把他历年的答案画成可靠性图,那条线会紧贴对角线,ECE 几乎是0——完美校准。现在只用一个数字,比如 Brier 分数,去给他打分,你觉得他能考出什么样的分数?
答完再看
这个位置有一个名字,叫不确定度,后面会算给你看。它是天气这件事本身的难度,跟这个预报员是谁、他有没有用心毫无关系——把答案永远锁死在50%的人,恰好只拿到这一项,其余两项全部归零。这正是这一章要拆开的东西。
乙:看天色再判断
晴天说20%,阴天说80%,长期看晴天确实约20%下雨、阴天确实约80%下雨——两种情况都说中了。
甲:不管天色,永远喊50%
不管当天是晴是阴,回答从来不变,长期看历年整体下雨天数也确实接近一半。
差别在:两人的可靠性图都会紧贴对角线,可靠度都是0,从「老不老实」这一项完全看不出高下;但甲面对任何情况给出的答案都一样,乙的答案随着情况变化——这一点差别,决定了下一节要算出的分数天差地别。
第5章给的 Brier 分数定义是这样的:把每一条预测概率 pi 和它对应的实际结果 oi(下雨记1,不下雨记0)相减、平方,再对所有条目取平均。
| 符号 | 是什么 | 直觉 |
|---|---|---|
| N | 总共有多少条(概率,结果)记录 | 样本一共多少条 |
| pi | 第 i 条给出的预测概率 | 当时说的把握有多大 |
| oi | 第 i 条的实际结果,发生记1、没发生记0 | 后来到底怎样了 |
| BS | Brier 分数,越小越好 | 预测和结果差多远,差得越远罚得越重(因为平方了) |
这个数字把「说得准不准」压成了一个数,压缩得很干净,但也压得太狠——它没法回答「这个预报员到底是老实但懒,还是既老实又肯下功夫分辨天气」这个问题。要回答这个问题,得先把预测按数值分桶:所有说「80%」的日子归一桶,所有说「30%」的日子归另一桶,跟第5章画可靠性图时是同一个动作。桶里除了平均预测概率,还有一个数值得记下来:这一桶里,真的发生的比例有多少,我们把它叫作这一桶的实测频率。
某天预测概率是0.9,结果真的下雨了(o=1);另一天预测概率是0.9,结果没下雨(o=0)。只看这两天,Brier 分数是多少?
变式:如果这两天预测概率都是0.5,结果分别是下雨和不下雨,Brier 分数是多少?和上面的0.41比,哪个更好?
为什么可靠度和分辨度必须分开算
两个预报员都很老实:各自说出的概率,长期看和后来真正发生的频率完全对得上——两人的可靠性图都紧贴对角线,都完美校准。甲不管什么天气都喊「50%」;乙会看天色,晴天喊「20%」、阴天喊「80%」,而且长期看晴天确实只有20%下雨、阴天确实有80%下雨。你觉得甲和乙的 Brier 分数会一样吗?
答完再看
往下看就能算出来:两人可靠度确实都是0,但乙多了一项甲完全没有的东西。这一项决定了「老实」相同的两个人,分数还是能拉开差距。
能让「校准」和「有用」拉开差距的那个数字,气象学家 Allan Murphy 在1973年给出过一个拆法,往下把每一项单独列出来。先看可靠度:它衡量的是,每一桶自己报的平均概率,和这一桶真实发生的频率,差了多少——差得越多,说明这个模型越不老实,可靠度就该越大,所以要用平方、加权平均起来。
| 符号 | 是什么 | 直觉 |
|---|---|---|
| k | 桶的编号,比如「预测0.8」是一桶、「预测0.3」是另一桶 | 按说出的把握值分组 |
| nk | 第 k 桶里有多少条记录 | 这一桶权重多大,桶越大越要认真对待 |
| p̄k | 第 k 桶里,预测概率的平均值 | 这一桶自己报的把握 |
| fk | 第 k 桶里,事情真正发生的比例 | 这一桶后来交出的真实成绩单 |
某桶预测概率是0.6,桶里8天,其中5天真的发生了。这一桶单独对可靠度的贡献(还没除以总样本数 N、还没加另一桶)是多少?
变式:如果这一桶预测的是0.9而不是0.6(实测频率仍是0.625),这一桶单独对可靠度的贡献会变成多少?
可靠度只关心「说的」和「真的」对不对得上,完全不关心这个模型有没有把不同情况区分开。真正衡量「有没有分辨」的是另一项,分辨度:它看的是每一桶的真实频率 fk,比起「不管哪一桶,整体上事情发生的比例」,也就是基础率,拉开了多少距离。桶与桶之间的真实频率越不一样,说明模型确实把不同的情况分开了,这个词前面要减去,因为分辨度是越大越好——分得越开,Brier 分数应该越小。
| 符号 | 是什么 | 直觉 |
|---|---|---|
| b | 基础率:不分桶,整批数据里事情发生的总比例 | 什么都不知道时,唯一能报的那个数 |
| fk − b | 这一桶的真实频率,比总体基础率偏离了多少 | 这一桶是不是真的「不一样」 |
某模型只有两桶:桶A预测0.7、真实频率也是0.7;桶B预测0.7、真实频率是0.3(两桶样本数一样多)。这两桶合起来,可靠度是不是0?分辨度呢?
变式:如果桶A和桶B的预测值本来就不同(比如A预测0.7、B预测0.3),但两桶各自的预测都精确命中了自己的真实频率,可靠度和分辨度又分别是多少?
最后一项不确定度,跟模型无关,纯粹是这件事本身有多难猜:如果历年正好一半天下雨一半天不下雨,基础率是0.5,随便猜的难度最大;如果一年到头几乎从不下雨,基础率接近0,随便说「不下雨」都很容易对,不确定度就接近0。
| 符号 | 是什么 | 直觉 |
|---|---|---|
| b(1−b) | 基础率乘以它的补数,b=0.5 时取最大值0.25 | 这件事本身有多「五五开」——越接近五五开,光靠猜越难猜对 |
三项拼起来,就是Murphy 分解(Murphy decomposition):
自己推一遍:为什么这三项恰好拼得起来
只看一个桶,比如「预测0.8」那一桶,里面有 nk 天。每天的平方误差是 (0.8−oi)²。把0.8写成「(0.8−fk) 加上 (fk−oi)」,这一桶的平方误差之和会拆成几块?
想好了再看
按平方展开公式 (x+y)²=x²+2xy+y²,会出现三块:nk(0.8−fk)² 这一块和 k 无关地提到求和外面;交叉项 2(0.8−fk)Σ(fk−oi);以及 Σ(fk−oi)²。
中间那个交叉项里,Σ(fk−oi) 对这一桶里所有天求和,会等于多少?记住 fk 本来就是这一桶 oi 的平均值。
想好了再看
等于0。fk 的定义就是这一桶 oi 的平均,所以「每一天的 oi 减去这桶的平均值」加起来必然抵消成0——这是平均值最基本的性质。交叉项整个消失,这就是当初想到要拆成这两块的原因:故意凑出一个求和为0的交叉项。
剩下 Σ(fk−oi)² 这一块。oi 只能是0或1,这个和有没有更简单的写法?
想好了再看
展开 Σoi²−2fkΣoi+nkfk²,因为0和1的平方还是它自己,Σoi²=Σoi=nkfk,代入化简后正好等于 nkfk(1−fk)。
把所有桶的两块(可靠度那块,和 nkfk(1−fk) 那块)加起来除以 N,第一块就是可靠度。第二块 (1/N)Σnkfk(1−fk) 还不是分辨度和不确定度的样子,能不能把每个 fk(1−fk) 也按「偏离基础率 b」的方式拆一次?
想好了再看
把 fk(1−fk) 写成 fk−fk²,再对每个 fk² 用同样的凑平均值技巧展开,代数化简到最后会得到 (1/N)Σnkfk(1−fk) 恰好等于「不确定度 − 分辨度」。这一步是纯代数搬家,关键不在于每一步好不好想,而在于最后真的能凑上——这正是式 6-5 成立的原因。
把第4步和前面拼起来,BS 等于什么?
想好了再看
BS = 可靠度 + (不确定度 − 分辨度) = 可靠度 − 分辨度 + 不确定度,正是式 6-5。
拿一组具体的数字验证一遍,比记住推导过程更踏实。假设有10天的历史记录:预报员甲在5天里说「80%会下雨」,其中3天真的下了雨;另外5天说「30%会下雨」,其中2天真的下了雨。10天里一共下了5天雨,基础率 b=0.5。
| 桶 | 预测概率 p̄k | 天数 nk | 真下雨天数 | 实测频率 fk |
|---|---|---|---|---|
| 高把握桶 | 0.8 | 5 | 3 | 0.6 |
| 低把握桶 | 0.3 | 5 | 2 | 0.4 |
先按式 6-2 到式 6-4 分别算三项:可靠度 = [5×(0.8−0.6)²+5×(0.3−0.4)²]/10 = [5×0.04+5×0.01]/10 = 0.25/10 = 0.025。分辨度 = [5×(0.6−0.5)²+5×(0.4−0.5)²]/10 = [5×0.01+5×0.01]/10 = 0.1/10 = 0.01。不确定度 = 0.5×0.5 = 0.25。三项按式 6-5 拼起来:0.025 − 0.01 + 0.25 = 0.265。
三项拼出来的0.265,只是拆分算法给出的答案。换一条完全不同的路——直接套式 6-1,把表6-1这10天逐条算平方误差再取平均——算出来的 Brier 分数,会不会也是0.265?自己动手算一遍再往下看。
变式:如果表6-1的桶数从2个扩到3个,这个「两条路必然吻合」的性质还成立吗?为什么?
两条完全不同的路径,走到同一个数字——式 6-5 这道等式不是巧合,是代数上必然成立的结果,也是上面那道题里免费判据的来源。
永远喊50%的人
只有一桶,桶的实测频率必然等于整体基础率0.5,可靠度=(0.5−0.5)²=0,分辨度=(0.5−0.5)²=0。Brier 分数 = 0 − 0 + 0.25 = 0.25,一步不差地等于不确定度。
预报员甲(认真判断但不够准)
两桶,可靠度0.025、分辨度0.01,Brier 分数 = 0.025 − 0.01 + 0.25 = 0.265——比什么都不判断、永远喊50%的人还要差。
差别在:甲确实分辨出了「80%那天」和「30%那天」不一样(分辨度是正的),但他报的数字和真实频率对不上(可靠度也是正的);这一次可靠度的亏空,比分辨度赚回来的还多,总账就是甲输给了什么都不判断的人。
这正是这一章要说的话:分辨度是正数,不代表总账就赢。一个既不闹笑话、又真的分辨出了不同情况的模型,才能稳赢什么都不判断的对手;只做到其中一半,账目可能还是负的。
把表6-1改成三桶:预测0.9的3天全部下雨(f=1.0),预测0.5的4天里2天下雨(f=0.5),预测0.1的3天全部没下雨(f=0)。10天里一共3天下雨,基础率0.3。算出可靠度、分辨度、不确定度,验证三项之和等于直接算的 Brier 分数。
变式:如果把0.5那一桶的实测频率改成3/4,其余不变,三项和 Brier 分数会怎么变?
回到那个永远说50%的人:他在这张账单上占了哪一格
预报员甲(可靠度0.025、分辨度0.01,Brier 分数0.265)确实做出过判断,也确实分辨出了不同的天。永远喊50%的人(可靠度0、分辨度0,Brier 分数0.25)什么判断都没做。你觉得谁的 Brier 分数更好?
答完再看
上一节已经算过:0.265对0.25,喊50%的人赢了。分辨度是正数不等于总账是正数——可靠度的亏空要是比分辨度的收益还大,认真判断反而不如不判断。这是这一章最反直觉的一步。
把这件事情说清楚,要先把「永远给出同一个概率」这件事一般化。假设某个模型不管遇到什么情况,永远只报一个固定的数 q。因为他只有一个桶,这个桶装下了全部数据,所以这一桶的实测频率必然就是整体的基础率 b——没有第二个桶可以和它比较,分辨度的定义里 fk−b 对这唯一的桶来说恒等于0。分辨度这时被数学上直接锁死为0,不管这个模型选择永远报哪个数字都一样,不只是数值偏小这么温和。
可靠度就不一定是0了:可靠度=(q−b)²,只有当 q 恰好等于基础率 b 时,可靠度才会归零。BRIEF 里第5章那个例子选的是「历年下雨概率本来就接近50%」的场景,所以喊50%恰好撞上了 b=0.5,可靠度也归零,Brier 分数干干净净地等于不确定度。换一批基础率不是0.5的数据,同样是什么都不判断,运气就不一定这么好了。
喊对了基础率:q=0.2,b=0.2
某地历年只有20%的天数下雨。永远喊20%——恰好等于基础率,可靠度=(0.2−0.2)²=0,Brier 分数=0−0+0.16=0.16。
喊错了基础率:q=0.5,b=0.2
同样这批数据,换成死守着永远喊50%。可靠度=(0.5−0.2)²=0.09,Brier 分数=0.09−0+0.16=0.25。
差别在:两个都是「什么都不判断」的懒模型,分辨度同样是0,唯一的差别是有没有蒙对基础率——蒙对了,Brier 分数干净地等于不确定度0.16;蒙错了,直接多付出0.09的可靠度代价。「永远喊一个数」这条捷径,连不劳而获都得先打听清楚基础率是多少。
答辩:如果我是审稿人
你说分辨度为0是「毫无用处」,可是分辨度是用「桶与桶之间差多远」定义的,只有一个桶自然算不出差距。会不会这只是分桶方法本身的漏洞,而不是这个预报员真的没用?
参考防守(先自己组织语言再看)
换一个角度想会更清楚:分辨度衡量的其实是「知道这个模型说了什么数字之后,你对结果的判断能不能变得更准」。如果模型永远只吐出同一个数字,那么听到这个数字之后,你获得的信息量是0——不听他说话,直接用基础率去猜,效果一模一样。分桶只是把这件事算出数字的一种办法,不是漏洞制造出的假象;哪怕换一种完全不分桶的算法去衡量「这个模型的输出带来了多少信息」,只报一个常数的模型也会被判定为0信息量。分桶只是如实照出了这一点。
本节已经给出了一个反例:预报员甲有正的分辨度(0.01),却输给了分辨度为0的「永远喊50%」。反过来,能不能构造一个例子:某模型可靠度不是0(有点不老实),但因为分辨度足够大,Brier 分数依然比「永远喊基础率」更好?只需要说出这样的例子该往哪个方向调整数字,不需要算到底。
变式:如果可靠度涨到比分辨度还大(比如两桶的预测和实测频率差出很多),这个模型还能赢过永远喊基础率的人吗?
回到表6-1预报员甲的两桶数据。按第5章教的方法(每一桶算出预测概率和实测频率的差的绝对值,再按桶的样本数加权平均)算一遍 ECE,和本章算出的可靠度0.025比较:这两个数字一样吗?如果不一样,是什么地方让它们分道扬镳的?
变式:如果两桶的差值分别是0.3和0.3(不再是0.2和0.1),ECE 和可靠度这一次谁大谁小的关系会不会反过来?
对你而言未知Murphy 分解能不能用在 Score 这种不止两种结果的判断上
这一章的推导全程假设结果只有「发生」和「不发生」两种,也就是 oi 只能取0或1。可是 BRIEF 里 Jev 的 Score 类型能返回0到9这样的多档等级,Murphy 分解要怎么改才能用在这种多档结果上,这份材料没有给出答案——学界未必没有答案,大概率只是这份材料没收录,需要另外去查。
先做这一步:搜索「Murphy decomposition multi-category」或「ranked probability score decomposition」,重点看它怎么处理「预测是一个分布、结果是某个具体等级」这种情况,再回来对照式 6-2 到式 6-4,看看哪个符号需要从标量换成向量。
某批100天的历史记录里,有40天下雨。不管用哪个模型去预测,这批数据的不确定度是多少?
变式:如果这批数据里只有10天下雨(其余90天不下雨),不确定度会变大还是变小?算出具体数字。
已知某模型在某批数据上,分辨度是0.03,不确定度是0.21,直接算出的 Brier 分数是0.20。这个模型的可靠度是多少?
变式:如果这个模型的 Brier 分数是0.25而不是0.20,其余两项不变,可靠度会变成多少?这个数字是否合理(是否可能小于0)?
某批数据基础率是0.3(不确定度=0.3×0.7=0.21)。有人说他的模型分辨度算出来是0.25。这个数字有没有可能是对的?
变式:基础率如果是0.5(不确定度=0.25),分辨度最多能到多少?这时候如果可靠度也是0,Brier 分数最低能压到几?
A、B两个模型在同一批10天数据上,Brier 分数都算出0.15。A的可靠度是0.10、分辨度是0.20;B的可靠度是0.01、分辨度是0.11(这批数据不确定度是0.25)。如果要选一个部署到明年的新数据上,两个分数打平的情况下,该更信任谁,为什么?
变式:如果A的可靠度是0.02、分辨度是0.12(B保持不变),两者总分还是打平吗?这时候该怎么选?
同一个模型,同样的可靠度和分辨度,分别用在基础率是0.5和基础率是0.05的两批数据上。哪一批数据上更容易拿到更低(更好)的 Brier 分数?
变式:如果基础率是0.99(几乎每天都下雨),不确定度是多少?这时候「永远说99%」这种偷懒策略的 Brier 分数会好到什么程度?
如果只给你一张第5章教的可靠性图(横轴是预测概率、纵轴是实测频率,每个点还标了这一桶的样本量),不给任何数字表格,你能不能只凭这张图,大致判断出这个模型的可靠度高不高、分辨度高不高?分别说说从图上看什么。
变式:如果可靠性图上的点紧贴对角线,而且从接近0铺到接近1、分布得很开,这个模型的 Brier 分数会不会明显低于「永远喊基础率」?
对你而言未知可靠度和分辨度哪个更值得优先改进,有没有一条通用的取舍规则
如果一个团队只有精力改进模型的一项性质,是该优先修可靠度(让概率更老实)还是优先修分辨度(让判断更敢下注、更能分辨不同情况),这份材料没有给出答案,也没有一条现成的优先顺序可以照搬——比较合理的猜测是要看下游怎么用这个概率、误判的代价结构长什么样,但这一层猜测没有数据撑着,需要自己针对具体场景验证。
先做这一步:结合下一章要推的最优阈值公式,想一想如果误判代价高度不对称(比如漏掉一个坏结果的代价远大于错杀一个好结果),可靠度的重要性会不会相对上升——因为阈值直接建立在概率的绝对数值上,可靠度差意味着阈值本身就定错了地方。
这一级要加什么:给审计仪装上 Brier 分解器
为什么现在才加它:前五级只能吐出一个总的 Brier 分数或 ECE,两个模型分数一样时,审计仪没有能力告诉你它们输在同一个地方还是不同的地方——这一级把总分拆成三个可以分别读的数,审计仪第一次能区分「不老实」和「没分辨力」这两种完全不同的病。
难点:分桶的规则一旦和第5级用的不一致(比如这里按十等分分桶,那里按预测值本身分桶),算出来的可靠度和分辨度会跟着变,但两者之和加不确定度必须始终等于直接算的 Brier 分数——这是检验分桶规则有没有写对的免费判据,不用另外验证。
自己验:把表6-1的数据喂进去,应该输出可靠度0.025、分辨度0.01、不确定度0.25、bs字段0.265;把预测值全部替换成同一个常数(比如全部0.5),无论真实结果怎么分布,res 字段应该始终算出0。两个都对上,这一级就成了。
官方文档里把 Jev 描述成「calibrated」,却从没给过可靠度、分辨度或者不确定度里任何一项的具体数字——现在你已经知道,这三项各自回答什么问题、为什么不能互相替代。如果厂商只肯说「校准」这一个词,你会追问哪一项没有被交代?这三项里,哪一项恰好是最容易被藏起来、最不容易被读者自己算出来的?
不看材料,写下这一章的三堵墙
第一堵墙:一个数字(Brier 分数)压缩了两件不同的事,压缩之后没法反推出哪件事出了问题。第二堵墙:分辨度是正数,不代表总账就赢——可靠度的亏空可能比分辨度赚回来的还多,认真判断也可能输给什么都不判断。第三堵墙:永远给出同一个概率的模型,分辨度被数学锁死为0,可靠度是否归零全看运气有没有蒙对基础率——校准满分和有用之间,中间隔着这道判定不了的缝。
第7章 放过一个坏人和冤枉一个好人,哪个贵
模型告诉你,这封邮件是垃圾邮件的概率是0.6。删,还是不删?多数人脑子里会立刻冒出一条规则:超过一半的把握就删。可是同样这个0.6,如果问的是「这封邮件里有没有诈骗链接,要不要直接拦截、连人都不让看」,你还敢用同一条规则吗?
学完这一章你应该能做到
- 给出两种误判各自的代价后,推出让期望损失最小的判断切点,而不是想当然地用0.5
- 解释这个切点为什么只由代价的比例决定,和这件事本身有多常见没有关系
- 说清「模型直接吐出一个标签」和「模型交出一个概率、切点你自己定」这两种设计,谁能让判断的切点匹配你实际承担的代价
这一级要给审计仪加一个旋钮:最优阈值求解器。前六级的可靠性图、ECE、Brier 分解,都假设你手上已经有一批(概率,结果)可以拿来打分;但真正拿概率去做决策时,0.5这个默认的切点从哪来,没人交代过。这一级把切点变成一个能按代价算出来的数,不再是随手定的常数。
超过一半的把握就该动手吗
模型说这封邮件是垃圾邮件的概率是0.6。你会把它删掉吗?
答完再看
这封邮件到底该不该删,不能只看0.6这一个数字。如果删错的代价远大于放过的代价(比如这可能是一封offer邮件),0.6根本不够;如果放过的代价远大于删错的代价(比如这是一封钓鱼邮件),0.6可能都嫌高了。这一节要把「够不够」这件事从直觉变成一个能算出来的数。
先看最省事的做法:概率过半就删,不过半就留。这条规则的名字叫0.5阈值,几乎是每个人第一次面对一个概率时的本能反应。它有没有道理?有——如果把它理解成「更可能是垃圾邮件就按垃圾邮件处理」,这话听起来无可辩驳。
但这条规则悄悄假设了一件事:删错一封重要邮件的代价,和漏删一封垃圾邮件的代价,是同一个数量级。真实世界里几乎从不是这样。误删一封来自客户的邮件,可能让你错过一笔生意;漏掉一封垃圾邮件,无非是多看一眼、随手删掉。两种错误的代价可以相差十倍、百倍,0.5这个数字里完全没有体现这个差距——它把「谁更可能」和「该不该动手」画上了等号,可这是两件事。
按最省事的0.5阈值规则:模型说某条评论是恶意攻击的概率是0.52,该不该按恶意攻击处理?
变式:如果把评论换成一笔银行转账,模型说它是欺诈交易的概率是0.52,按同样的0.5阈值规则该不该直接拦截?这条决策和上面那条,代价真的一样重吗?
误删一条促销邮件
模型判定它是垃圾邮件的概率0.6,按0.5阈值删掉——就算判断错了,无非是错过一条打折信息,代价几乎为0。
误删一封银行扣款提醒
模型判定它是垃圾邮件的概率同样是0.6,按同一条0.5阈值删掉——如果判断错了,你会错过一次账户异常扣款的提醒。
差别在:两种邮件用的是同一个0.6、同一条0.5阈值规则,动作也一样是「删」,可删错的代价天差地别——0.5阈值对这两种情况给出了同一个答案,问题不在于这个数字算错了,在于它从头到尾没有位置容纳「删错了要付出什么代价」这件事。
答辩:如果我是审稿人
0.5阈值真的没有道理吗?如果两种误判的代价原本就差不多,这条规则不就是对的?
参考防守(先自己组织语言再看)
这条反驳站得住——下一节推出来的公式会显示,0.5阈值算不上一条错误的规则,它只是一种特殊情况:只有当两种误判的代价恰好相等时,最优切点才刚好落在0.5上。真正的问题不是0.5这个数字本身,是把它当成放之四海而皆准的默认值——现实里两种代价相等的场景,远比想象的少。
切点该定在哪,才不是拍脑袋
如果误删一封重要邮件的代价,是漏删一封垃圾邮件代价的4倍,你觉得这时候的最优切点,应该比0.5更高还是更低?
答完再看
误删代价更高,意味着「动手」这个决策要冒更大的风险,所以需要更充分的证据(更高的概率)才值得冒这个险——切点该往上抬,而不是往下调。往下会推出一条公式,把这个直觉变成一个能算出来的数。
要把切点从直觉变成算出来的数,先要把「删错了」和「该删却没删」这两种代价分别起个名字。把「不该动却动了」的代价记作 CFP——删了一封其实不是垃圾邮件的邮件。把「该动却没动」的代价记作 CFN——放过了一封其实是垃圾邮件的邮件。
自己推一遍:从两种代价到一个切点
如果选择「动手」(删除),但其实错了——这封邮件根本不是垃圾邮件。这种局面发生的概率是多少?(模型说是垃圾邮件的概率是 p)
想好了再看
发生的概率是 1−p——模型说「是垃圾邮件」的把握是 p,那么「其实不是」的把握就是剩下的 1−p。动手这个决策的期望损失,等于这种局面发生的概率乘上踩中它要付的代价:(1−p)×CFP。
反过来,如果选择「不动手」(留着),但其实错了——这封邮件真的是垃圾邮件。这种局面发生的概率是多少,不动手的期望损失该怎么写?
想好了再看
发生的概率就是 p 本身。不动手的期望损失是 p×CFN。
该选哪个,取决于哪个期望损失更小。写出「动手更划算」这个条件的不等式。
想好了再看
(1−p)CFP < p·CFN。
把这个不等式解出 p,看看动手这个决策成立的条件,最终变成一句关于 p 单独在左边的话。
想好了再看
展开:CFP − p·CFP < p·CFN,移项:CFP < p(CFN+CFP),两边除以 (CFN+CFP):p > CFP/(CFP+CFN)。右边这个数就是这一章要找的切点。
把这个切点记作 τ*(读作「陶」,星号表示它是这个问题下最好的那一个):
| 符号 | 是什么 | 直觉 |
|---|---|---|
| CFP | 不该动却动了的代价(误删一封正常邮件) | 手欠的代价 |
| CFN | 该动却没动的代价(放过一封垃圾邮件) | 偷懒的代价 |
| τ* | 最优判断切点:概率超过它就该动手,没超过就不动 | 两种代价拔河,谁更重,切点就往谁那边偏 |
概率 p 超过 τ* 就动手,这样选出来的期望损失,不会比任何其他切点选出来的更高——这正是式 7-1 被称作「最优」的原因:不是凭经验选出来的好切点,是能证明不存在更优切点的那一个。
如果误删一封正常邮件和放过一封垃圾邮件,代价被认为完全相等(CFP=CFN),代入式 7-1,τ* 等于多少?
变式:如果 CFP=CFN=0(两种误判都毫无代价),τ* 这个公式还有意义吗?
代价对称:误删和漏删一样疼
CFP=CFN,代入式 7-1,τ*=0.5——0.5阈值这时候恰好是对的。
代价不对称:误删疼4倍
CFP=4CFN(比如这可能是封重要客户来信),τ*=4/(4+1)=0.8——概率没到0.8之前,都该留着,比0.5苛刻得多。
差别在:两种情况用的是同一个公式,唯一变化的是代价的比例。代价越不对称,最优切点离0.5越远——0.5从来不是「安全的默认值」,它只是对称代价下的答案,换一种代价结构就该换一个数。
式 7-1 只用到了两个代价,CFP 和 CFN。如果某个用户平时收到的邮件里,九成都是垃圾邮件——这个「垃圾邮件本来就很常见」的信息,要不要也代进这个公式,把切点往下调一些?
答完再看
回头看式 7-1:分子分母里只有 CFP 和 CFN,没有任何位置留给「垃圾邮件占多大比例」这个数。这是这一章最反直觉的一步,往下会说清楚为什么基础率的影响其实已经在别的地方起作用了,不需要在这个公式里重复计入。
这一步确实反直觉:常识会觉得「越常见的东西,越该被当真」,可式 7-1 完全没有给基础率留位置。原因在于,基础率的影响已经在别的地方起作用了——如果垃圾邮件真的很常见,一个诚实的模型本身就该更频繁地给出高概率,把这批邮件的 p 值普遍推高,而不是让你去手动调低判断的切点来迁就它。切点只负责回答「给定这一条的概率,值不值得为它承担动手的风险」,这个问题的答案永远只取决于两种错误各自有多疼,和这一类事情本身有多常见,是两条互不干扰的信息。
工厂质检:模型给出「这个零件有缺陷」的概率。放过一个坏零件(CFN)会导致产品召回,代价定为9;把一个好零件误判成坏零件拦下来(CFP),只是多一道复检,代价定为1。某个零件的缺陷概率是0.3,该不该拦下它?
变式:如果把两个代价对调(误拦代价9、放过代价1),这个0.3的零件还该不该拦?
能不能构造一组代价 CFP 和 CFN,让「模型说有九成把握」(p=0.9)依然不该动手?只需要说出这组代价该往哪个方向调,并算出一组具体数字。
变式:如果要让 τ* 正好卡在0.99,CFP 和 CFN 的比例大约要是多少?
Jev 为什么把概率交还给你,而不是替你拿主意
如果一个模型只返回「是垃圾邮件」或「不是垃圾邮件」这样一句话,不告诉你任何概率,你还能不能用上式 7-1 算出来的切点?
答完再看
标签背后一定也有一个模型自己认为的切点,但那条线是模型的开发者按他们自己设想的场景定的,未必匹配你此刻的 CFP 和 CFN。只有拿到那个连续的概率,你才能把式 7-1 用在自己的场景上。
只返回标签的模型
模型内部按它自己认定的某条线,把答案定成「是」或「否」吐给你——那条线是谁定的、按什么代价定的,你无从得知,也无法改。
返回概率的 Jev
返回一个连续的数,切点由你自己按式 7-1 算出来再代入——同一条概率,邮件场景用0.8,零件质检场景可以换成完全不同的0.1。
差别在:前者把「该不该动手」这个判断权交给了模型的开发者,后者把这个判断权还给了真正承担后果的人。
某团队买了一个只返回「欺诈」或「正常」标签的现成模型,原厂商把内部切点定在了「概率超过0.3就判欺诈」(因为原厂商预设误判一笔正常交易的代价很低)。这个团队实际的场景是大额转账审核,误拦一笔正常的大额转账会让重要客户投诉,代价很高。这个标签模型能不能直接照用?
变式:如果这个团队反过来是要审核小额优惠券核销(误拦代价很低、漏拦代价也很低),原厂商的0.3切点会不会刚好也凑巧合适?
官方文档里有一句话正说的是这件事:「Uncertainty is a feature」——不确定性不是缺陷,是特性。官方原文紧接着写道,你可以用 Jev 给出的概率和置信度,自己决定软件什么时候可以自动动手、什么时候要停下来交给人看。这正是式 7-1 在真实产品里的样子:把「切点定在哪」这件事,从模型开发者手里,还给了知道自己代价结构的人。
不过这份自由是有边界的。官方在同一份文档的另一处明确提醒:不要把在 Noul 上调好的阈值,直接搬到 Choice 上用——你刚刚学会的这条 τ*,是绑定在「这封邮件是不是垃圾邮件」这一个具体问法上算出来的,换一种问法(哪怕问的是同一件事),这条线都得重新算一遍。
你按式 7-1,在一个 Noul 问题(「这封邮件是垃圾邮件吗」,返回一个概率)上算出了最优切点0.8。现在把问法换成一个 Choice 问题(选项是「垃圾邮件」和「正常邮件」),拿到的「垃圾邮件」概率是0.75。你能不能直接照搬0.8这条线,判定0.75小于0.8所以不该删?
变式:如果 Jev 从 jev-1.13.0 升级到未来某个新版本,你在旧版本上调好的 τ*=0.8,能不能直接沿用到新版本上?
某团队一开始把误删一封邮件的代价 CFP 估得偏低(比如漏算了客户因为收不到邮件而流失这一层代价)。如果按这个偏低的 CFP 算出 τ*,这个切点会比真实最优值偏高还是偏低?实际使用中会带来什么后果?
变式:如果反过来是 CFN 被低估,τ* 会偏高还是偏低?
对你而言未知CFP 和 CFN 这两个数字本身该怎么估
这一章从头到尾都假设 CFP 和 CFN 已经是两个写好的数字,只管代入式 7-1 去求 τ*。可是「误删一封重要邮件」到底该记多少代价,这份材料完全没有给出估法——这不是说这件事无法估计,决策分析领域有一整套把模糊后果换算成可比较数字的方法,只是没有收在这份材料里。
先做这一步:搜索「decision-theoretic cost elicitation」或「代价矩阵 效用函数」,重点看它们怎么处理「后果不是钱」的情况(比如声誉损失、用户流失),再回来看看你自己手上最想用这套阈值公式的场景,试着给 CFP 和 CFN 各写一个粗略但有依据的数字。
在式 7-1 里,如果把 CFP 和 CFN 的角色搞反了(把「该动却没动」的代价错记成了 CFP),算出来的切点会不会还是对的?
变式:如果 CFP 和 CFN 恰好相等,把两者角色调换会不会改变算出来的 τ*?为什么这种情况比较特殊?
这一级要加什么:给审计仪装上最优阈值求解器
为什么现在才加它:前六级只能告诉你一批概率有多校准、有多分辨力,却从没告诉你拿到一条具体的概率之后,该在哪个数值上画线才算「动手」——这一级把这条线从拍脑袋的0.5,变成一个吃两个代价数字、吐出一个切点的小函数。
难点:很多人会下意识地想再给这个函数加一个「基础率」参数,觉得越常见的类别应该更容易被判定——式 7-1 的推导已经证明这个直觉是错的,基础率的影响本该体现在模型给出的概率 p 本身有多准,而不是体现在切点上;一旦真的把基础率塞进 optimalThreshold,这个函数就在重复计算同一份信息,算出来的切点会系统性地偏离式 7-1 的答案。
自己验:optimalThreshold(1, 1) 应该输出0.5;optimalThreshold(4, 1) 应该输出0.8;把 shouldAct(0.6, 4, 1) 传进去,应该返回不动手(因为0.6小于0.8),即使0.6按最原始的0.5阈值规则早就该动手了。三个都对上,这一级就成了。
官方那句「不确定性是一种特性」,说的是概率把决定权交还给你。可这份自由需要你自己先说清楚两件事:误删的代价是多少,漏删的代价又是多少。如果这两个数字你从来没有认真估过,一直在用0.5,你现在能不能说出,这相当于在悄悄假设一件什么事?
不看材料,写下这一章的三堵墙
第一堵墙:概率过半就动手,这条规则悄悄假设了两种误判代价相等,现实里几乎从不成立。第二堵墙:最优切点只由两种代价的比例决定,跟这件事本身有多常见无关——这一点违反直觉,需要专门想一遍为什么基础率的影响已经在别处起作用了。第三堵墙:算出来的切点是绑在一个具体问法上的,换一种问法(哪怕问的是同一件事),甚至换一个模型版本,都得重新算。
第8章 让贵的模型只看难的
Jev 便宜到近乎免费,每处理一个案例只要0.0004美元,0.4秒就能出答案,但那套官方一致率评测只考出67.8%。opus 5 一个案例要1.761毛美元,接近40秒,但能考到73.1%。两个放在你面前,你会怎么选?
学完这一章你应该能做到
- 给一个便宜模型和一个贵模型各自的准确率、成本、延迟,推出「便宜模型先判、拿不准再升级」这条路线整体的准确率、成本、延迟
- 解释为什么级联成本里,便宜模型那一项是一个不随阈值变化的常数,并说清这一点最容易在哪一步被漏算
- 说清「模型是校准的」这句话,如何让你不需要一条标注数据,就能估出级联里被采信那部分的真实准确率
这一级要给审计仪加一台机器:级联路由器。用第7章那条阈值当开关,把便宜模型和贵模型接成一条流水线,再算出这条流水线的准确率、成本、延迟。前七级只能评价单个模型交出来的一批答案;这一级第一次让审计仪去回答一个更接近真实工程决策的问题——两个模型一起用,划不划算。
便宜的和贵的,只能二选一吗
Jev 每案例0.0004美元、0.4秒、67.8%;opus 5 每案例0.1761美元、37.8秒、73.1%。如果你要选一个部署到生产环境,处理十万个案例,你会怎么选?
答完再看
全用哪一个都是在用一个固定的准确率、成本、延迟换另一个,中间没有任何余地。第三条路才是这一章要推出来的机器——它能不能真的比两个极端都划算,得靠算,不能靠感觉。
先把两种最省事的做法认真走一遍。全用 Jev:十万个案例,花40美元,用时11个小时,答对大约67800个。全用 opus 5:十万个案例,花17610美元,用时超过437个小时(相当于18天),答对大约73100个。多答对的那5300个案例,代价是多花17570美元、多等18天。这笔账对不少场景来说,根本划不来。
按上面的口径,十万个案例全部用 opus 5 处理,总成本是多少美元?
变式:如果只处理一千个案例,两种做法的成本差距(绝对值,不是倍数)会不会比十万个案例时更小?
但还有第三条路:不必在两个极端之间选,可以把它们接成一条流水线。让便宜的 Jev 先看一遍每一个案例,它自己判断得有把握的,就直接采信它的答案;判断得没把握的,再花钱交给 opus 5 重新看一遍。这条路线有一个名字,叫级联(cascade)——像瀑布分层跌落一样,案例先经过便宜的第一层,只有一部分会继续往下跌到昂贵的第二层。
级联能不能真的划算,取决于一件事:Jev 自己的「有没有把握」,靠不靠谱。如果 Jev 说有把握的时候真的大概率是对的,那级联就能用很低的成本留住大部分准确率;如果 Jev 的「有没有把握」和它实际对不对根本不相关,级联就是在乱猜要不要多花钱,多花的钱可能一点准确率都换不回来。这条件到底是什么,正是第9章要单独拆开检验的东西——这一章先假设它成立,把这台机器的账本搭出来。
级联处理一个案例时,Jev 是不是每次都要先跑一遍,不管这个案例最后有没有被升级给 opus 5?
变式:如果反过来先让 opus 5 判断,Jev 只处理 opus 5 觉得简单的案例,这还是同一种级联结构吗?成本公式会不会变?
这条流水线的账,该怎么算
要给级联算账,先要有一个规则去判断「Jev 有没有把握」。这正是第7章的最优阈值 τ* 能派上用场的地方:Jev 给出的置信度只要不低于 τ,就采信它的答案;低于 τ,就升级给 opus 5。这里的 τ 不一定非得是第7章按误判代价算出来的那个 τ*,可以是任何一个你选定的门槛——不同的门槛,级联交出的答案不一样,这正是下面要推的四个量。
第一个量最直接:置信度不低于 τ 的案例,占全部案例的比例,叫覆盖率(coverage)——这部分案例完全由 Jev 独立搞定,不需要 opus 5插手。
| 符号 | 是什么 | 直觉 |
|---|---|---|
| c | 覆盖率,介于0和1之间 | Jev 一个人就能扛下来的那部分 |
| τ | 门槛,置信度到这个数才算「有把握」 | 拧紧还是放松这个开关 |
| 1−c | 升级给 opus 5 的比例 | Jev 举手认输的那部分 |
把门槛 τ 调得更高——要求 Jev 更有把握才敢自己拍板,你觉得级联处理十万个案例的总成本,会变高还是变低?
答完再看
「更严格」这个词容易让人联想到「更省钱」,但这里严格的是「留给 Jev 自己拍板的资格」,不是「花钱的资格」。门槛越高,覆盖率 c 越低,往下会算给你看,升级的比例一旦变大,总成本必然跟着涨。
覆盖率决定了另外三个量:级联最终答对多少、花多少钱、等多久。先看准确率:被 Jev 自己扛下来的那 c 比例,按 Jev 在这部分上的真实准确率算;剩下 1−c 升级出去的,按 opus 5 的准确率算。两部分按各自占的比例加权平均,就是级联整体的准确率。
| 符号 | 是什么 | 直觉 |
|---|---|---|
| a采 | Jev 在「被采信」那部分案例上,自己的真实准确率 | Jev 拍板的那部分,靠不靠谱 |
| a大 | opus 5 的准确率(这里假设它在升级来的这部分上,表现和它整体的73.1%一致) | 接盘的大模型,靠不靠谱 |
自己推一遍:为什么 Jev 那一项在成本公式里是个甩不掉的常数
十万个案例,每一个都要先经过 Jev,花掉 costJ 这笔钱。这部分总共花掉多少钱,和有多少案例最终被升级,有没有关系?
想好了再看
没有关系。不管升不升级,每个案例都要先付这笔钱一次,十万个案例统一花掉 100000×costJ,这是一个只取决于案例总数、完全不取决于门槛 τ 定在哪的数。
升级出去的那部分案例,还要再付一次 opus 5 的钱。这部分一共有多少个案例,该怎么用覆盖率 c 写出来?
想好了再看
升级案例数 = 总案例数×(1−c),这部分总花费 = 总案例数×(1−c)×cost大。
把两部分总花费加起来,再除以总案例数(换算成人均成本),会得到什么?
想好了再看
[总案例数×costJ + 总案例数×(1−c)×cost大] ÷ 总案例数 = costJ + (1−c)·cost大,正是式 8-3。除以总案例数这一步,把 Jev 那部分的「总案例数×costJ」里的总案例数正好约掉了,只剩下 costJ 自己——这也是为什么它在人均成本公式里长得像个常数:它从付钱那一刻起,就和门槛 τ 没有任何关系,除法只是把这件事显现出来,不是制造出来的。
成本和延迟的结构几乎一样,但有一个地方容易被漏算:Jev 的成本和延迟,是每一个案例都要付出的——不管这个案例最后有没有被升级,第一步永远是先让 Jev 判断一遍。所以这一项是一个和 τ 无关的常数,只有升级出去那部分,才会额外叠加 opus 5 的成本和延迟。
| 符号 | 是什么 | 直觉 |
|---|---|---|
| costJ、latJ | Jev 单次的成本、延迟,每个案例必付,不随 τ 变化 | 入场费,谁都躲不掉 |
| cost大、lat大 | opus 5 单次的成本、延迟,只在升级时才付 | 只有真的举手认输才叫的救兵 |
假设某次部署里,覆盖率 c=0.7,Jev 在被采信部分的准确率 a采=0.75。用 BRIEF 里真实的成本延迟数字(Jev:0.0004美元、0.4秒;opus 5:73.1%、0.1761美元、37.8秒),算出这次级联的准确率、成本、延迟。
变式:如果覆盖率提高到0.9(其余数字不变),准确率、成本、延迟会分别变成多少?
如果预算要求级联处理每个案例的平均成本不能超过0.03美元,用 BRIEF 的真实数字(Jev 0.0004美元,opus 5 0.1761美元),覆盖率至少要压到多少?
变式:如果预算收紧到每案例不超过0.01美元,覆盖率至少要压到多少?这个数字现实吗(覆盖率能不能超过1)?
BRIEF 里 sonnet 5 的总分同样是67.8%,价格0.1174美元,用时78.1秒——和 Jev 打平,但贵得多、慢得多。如果把级联里的「大模型」换成 sonnet 5 而不是 opus 5,这条级联划算吗?
变式:如果某个模型比 sonnet 5 还便宜,但准确率比 Jev 低(比如 luna 的66.8%),它能不能当级联里的「大模型」?
不用标注数据,怎么知道这部分准不准
式 8-2 里的 a采,也就是 Jev 在被采信那部分上的真实准确率,看起来必须拿一批标好答案的数据去核对才知道。可这批标注数据往往是最贵、最难拿到的东西——如果非要标注才能用级联,这套机器在很多场景里根本落不了地。
这里正是校准这个性质,第一次在这四章里真正值钱的地方。第4、5两章教过,校准的意思是:一批预测里,说「80%」的那些,长期看真的有大约80%对了。「置信度不低于 τ」这个筛选条件,本身就是在按置信度分桶——和第5章画可靠性图、第6章算 Murphy 分解,用的是同一个动作。如果模型是校准的,这一桶自己报出来的平均置信度,就该约等于这一桶真实的准确率。
某次部署里,置信度不低于0.8的案例占了65%,这部分案例的平均置信度是0.87。如果 Jev 是校准的,a采 大约是多少,需不需要另外找一批标注数据去核实?
变式:如果这批案例的平均置信度是0.87,但拿一小批标注数据一核对,真实准确率只有0.70,这说明什么出了问题?
要判断「被采信那部分的平均置信度可以直接当准确率用」这件事靠不靠谱,能不能只看 Jev 官方公布的67.8%总分?如果不能,你会用第5章学过的哪个工具,去检验这个估计有没有系统性偏差?
变式:如果 ECE 算出来很小,是不是就能保证「被采信那部分」这一个特定子集的置信度也一定准?ECE 是对哪个范围算出来的平均数?
答辩:如果我是审稿人
式 8-2 里 a大 直接用了 opus 5 的官方总分73.1%,可升级给 opus 5 的那部分案例,恰恰是 Jev 觉得最难的那些——opus 5 在这批「难案例」上的真实准确率,凭什么假设它还能保持73.1%,会不会其实更低?
参考防守(先自己组织语言再看)
这条质疑站得住,而且没有被这一章的公式解决——式 8-2 用73.1%代替升级子集上的真实表现,是一个明确写出来的简化,不是一个已经验证过的事实。BRIEF 里没有任何数据告诉我们 opus 5 在「Jev 觉得难」的这批案例上具体考多少分,这一层空白只能老实承认。工程上能做的补救,是拿一小批升级出去的案例专门标注,单独核实 a大 在这个子集上是不是还站得住,而不是从67.8%总分或73.1%总分里想当然地借用。
能不能构造一个场景,让「opus 5 在升级子集上的准确率等于它整体的73.1%」这个假设明显不成立,而且往偏低的方向错?
变式:反过来,能不能构造一个场景,让升级子集上 opus 5 的准确率明显高于73.1%?
对你而言未知opus 5 在「Jev 觉得难」的这批案例上,真实准确率是多少
式 8-2 用73.1%代替升级子集上的表现,这一章已经承认这是一个简化,不是已验证的事实。真实答案需要专门做一次实验——拿一批 Jev 判定为低置信度的案例,分别用 opus 5 和人工标注核对,这份材料里没有这类数据,需要读者自己动手测。
先做这一步:如果你手上有 API 访问权限,挑一批题目让 Jev 先判断,筛出置信度低于某个门槛的那些,再把同样的题目喂给一个更强的模型,比较它在这个子集上的实际正确率和它公开评测的总分差多少。
覆盖率 c 能不能等于1.2?
变式:覆盖率能不能等于0?这时候式 8-3、式 8-4 会退化成什么?和「全用 opus 5」相比,差在哪一项?
式 8-4 里,升级出去的案例,延迟是 latJ 加上 lat大,是两段时间相加,不是取两者中较长的那个。这意味着 Jev 判断和 opus 5 判断,这两步是同时进行还是先后进行?
变式:如果把 Jev 和 opus 5 同时对每个案例都跑一遍,只在事后决定用谁的答案,延迟公式会变成什么样?这种做法在成本上又会怎样?
这一级要加什么:给审计仪装上级联路由器
为什么现在才加它:前七级只能评价单个模型交出来的一批答案,没有办法回答「两个模型一起用,划不划算」这个更接近真实工程决策的问题——这一级第一次让审计仪吃两个模型的参数,吐出一条流水线整体的准确率、成本、延迟。
难点:aAccept 这一行故意没有用 r.correct(真实对错),只取了置信度的平均——这不是偷懒,是这一节的核心论点在代码里的体现:只要校准假设成立,置信度的平均本身就是对准确率的估计,不需要标注。但这一行也是整个函数里最脆弱的一环,一旦校准假设不成立,这一行算出来的数就会系统性偏离真实值,而函数本身不会报错,只会安静地给出一个错误答案。
自己验:把 tau 设成0,coverage 应该算出1,此时 accuracy、cost、latency 应该分别退化成单独使用 Jev 时的水平;把 tau 设成一个大于所有置信度的数(比如2),coverage 应该算出0,accuracy 应该正好等于 opus 5 单独使用的73.1%,但 cost、latency 不会退到 opus 5 单独使用的水平——会比0.1761美元、37.8秒各多出 Jev 那一份0.0004美元、0.4秒,因为 Jev 每个案例都要先跑一遍,这份开销省不掉。两头都对上,中间的公式就没写错。
这一章的每一个公式,都在一个没写出来的前提下才成立:Jev 报出来的置信度,约等于它真实答对的概率。如果这个前提本身是假的,式 8-2 里的 a采 就是拿一个错的数在算平均——覆盖率、成本、延迟这几个数字不会变,但准确率这一项,会安静地算错。你觉得这时候级联路由器还会不会诚实地告诉你它自己算错了?
不看材料,写下这一章的三堵墙
第一堵墙:便宜和贵不是只能二选一,级联能用第7章的阈值把两者接成一条流水线,但划不划算要靠四个公式算出来,不能靠直觉。第二堵墙:Jev 的成本和延迟是每个案例都要付的常数,不会因为门槛调高、升级变少而省下来,只有大模型那一项会跟着覆盖率变化。第三堵墙:估算被采信部分的真实准确率,本来需要标注数据,但如果模型是校准的,置信度本身就是免费的准确率估计——这份自由的代价,是必须先相信校准这个前提,而这个前提这一章始终没有验证过。
第9章 把校准去掉,级联会怎样
上一章那台级联机器算得漂亮:花小钱办大事,准确率贴近贵模型,成本只要零头。可是那整套账本,从头到尾都靠着一句没有验证过的话撑着——Jev 说自己有多大把握,就真的有多大把握对。如果这句话是假的呢?
学完这一章你应该能做到
- 用温度缩放把一组置信度人为调偏,同时证明模型的判断结果(谁对谁错)完全没有变
- 说清为什么这种操作会让 ECE 明显变差,却不会让准确率动一个百分点
- 说清「路由器自认为的正确率」和它实际做到的正确率,在校准正常和校准被打乱两种情况下能差出多大——两者相差一个数量级
- 说清为什么「关掉校准会让级联的一致率变差多少」这个问题给不出一个和阈值无关的答案——连变好变坏的方向都会随阈值反转,这件事只能自己测,不能靠道理推
这一级要做的不是造一个新部件,是给上一级那台级联路由器装一个开关——校准扰动器,能把置信度人为调偏,却完全不碰模型判断对错的那一部分。前八级的路由器默默假设了「置信度约等于正确率」;这一级第一次让你亲手把这个假设关掉,看着同一套公式在假设不成立时会算出什么。
怎么把一个数字调得更极端,又不让它跑出0到1
第8章那套级联算法,前提是「Jev 的置信度约等于它真实答对的概率」。如果这个前提被打破——置信度还是那批数,但和真实对错的关系被人为搅乱了——第8章算出的准确率、成本、延迟,哪些会变,哪些不会变?
答完再看
答案要等这一章的核心操作做完才能看清楚——这一节先把「怎么人为搅乱置信度、又不破坏别的东西」这件事的工具准备好。
要人为调偏一批置信度,最直接的念头是给每个数乘一个系数,或者加减一个数。这条路马上会撞墙:置信度0.9,想让它变得更极端,乘1.3,算出来1.17——超过了1,不再是一个合法的概率。置信度必须老老实实待在0到1之间,直接做加减乘除,随时会把它推出这个范围。
某案例置信度是0.95,想让所有置信度「更极端」,直接乘以1.1。这样做完之后,这个数字还是一个合法的概率吗?
变式:如果某案例置信度是0.3,直接乘以0.5(想让它更极端地偏向0),算出来的数还合法吗?这次为什么没有越界?
另找的这条路分三步:先把概率换算成一个没有上下界的数,在这个没有上下界的空间里自由地缩放,缩放完再换回合法的概率。第一步要用到几率(odds):概率 p 换算成几率是 p/(1−p),意思是「这件事发生的把握,是不发生的把握的多少倍」。p=0.5时几率是1(五五开);p越接近1,几率越往正无穷跑;p越接近0,几率越往0跑——几率不会跑到负数,但下界0还在,没有彻底摆脱边界。
某案例置信度是0.8,它的几率是多少?
变式:置信度0.5的几率是多少?为什么这个值适合当作「有把握」和「没把握」的分界点?
再对几率取一次自然对数,就是对数几率(logit),这才是彻底没有上下界的数:p 从0一路走到1,logit(p) 从负无穷一路走到正无穷;p=0.5时,logit(0.5)=ln(1)=0,正好卡在正负的分界点上。
| 符号 | 是什么 | 直觉 |
|---|---|---|
| ln | 自然对数,输入越大、输出也越大,但增长得越来越慢 | 把「倍数关系」变成「加减关系」的工具 |
| logit(p) | 对数几率,范围是负无穷到正无穷 | 概率的「无边界版本」,可以随便加减乘除 |
logit(0.9) 和 logit(0.1) 之间,有没有什么简单的数量关系?(不需要算出具体数值,只需要判断关系)
变式:logit(0.99) 和 logit(0.01) 之间,是不是也是这种相反数关系?
有来路就要有回头路:把一个在负无穷到正无穷之间的数字,重新换算回0到1之间合法的概率,用的是logit的反函数,sigmoid(sigmoid function)。
| 符号 | 是什么 | 直觉 |
|---|---|---|
| σ(x) | sigmoid 函数,把任意实数 x 压回0到1之间 | logit 的还原键 |
| e | 自然常数,约等于2.718 | 只是这个还原公式里固定要用到的一个常数 |
| x 很大时 | e−x 趋近于0,σ(x) 趋近于1 | 越往正无穷走,换回来的概率越接近1 |
| x 很小(很负)时 | e−x 趋近于无穷大,σ(x) 趋近于0 | 越往负无穷走,换回来的概率越接近0 |
直接给概率乘系数
置信度0.95,想让它更极端,直接乘以1.1:0.95×1.1=1.045——越界了,不再是合法概率。
先转成logit,缩放完再转回来
logit(0.95)≈2.944,乘以1.1得约3.239,代回sigmoid算出约0.962——确实比0.95更极端了,而且始终是一个合法的概率。
差别在:logit 把有边界的概率换算成了无边界的实数,缩放这个动作放在无边界的空间里做,不管怎么乘、怎么加,最后用 sigmoid 转回来,结果必然落在0到1之间——这条弯路存在的唯一理由,就是保证缩放之后的数字依然合法。
先算出 p=0.8 的 logit 值(上一题已经算出它的几率是4),再把这个 logit 值代入 sigmoid,验证算不算得回0.8。
变式:p=0.5的logit是0。把0代入sigmoid,算出来是多少?这和你的直觉一致吗?
调温度,模型的判断力会跟着变吗
把每一条置信度,先转成 logit,除以一个数 T(温度),再用 sigmoid 转回来——这就是这一节要用的操作,温度缩放(temperature scaling)。T 小于1时,置信度会被推向0和1(更极端);T 大于1时,置信度会被拉向0.5(更温和)。做完这一步操作之后,模型原本给出的判断(这一条到底算「是」还是「否」),会不会跟着变?
答完再看
这是这一章最关键的一步,下面用推导把它证明出来,而不是只凭直觉信一次。
自己推一遍:温度缩放为什么动不了准确率
几率 p/(1−p) 是不是「p 越大,几率也越大」——也就是说,p 增大时,这个式子的值会不会跟着增大,不会突然掉头往下走?
想好了再看
是的。p 增大,分子变大、分母(1−p)变小,一个分数分子变大分母变小,整体必然变大——几率是 p 的增函数。
对一个「输入越大、输出越大」的东西再取自然对数,还会保持这个性质吗?(自然对数本身的性质:输入越大,ln 的输出也越大,只是长得越来越慢)
想好了再看
会保持。两个「输入越大输出越大」的函数串在一起,前一个的输出越大,喂给后一个之后,后一个的输出也越大——logit(p) 整体依然是 p 的增函数。
把 logit(p) 除以一个正数 T,这个除法会不会打乱谁比谁大的关系?
想好了再看
不会。两个数,大的除以正数 T 之后依然更大,除以同一个正数不会让谁反超谁——只要 T 是正数,除法保序。
式9-2的 sigmoid 是不是也是「输入越大、输出越大」?把前三步串起来,从 p 出发,经过几率、logit、除以 T、sigmoid 这一整串变换,最终的输出,还保持着「原来 p 越大,最终输出也越大」这个关系吗?
想好了再看
sigmoid 同样是增函数(式9-2的符号表已经说明:x 越大,σ(x) 越大)。四步全部是增函数串联,只要最上游 pA 比 pB 大,缩放之后的 p′A 依然比 p′B 大——排名完全不变。
如果模型是靠「谁的置信度最高就选谁」来决定最终答案的,排名不变,意味着最终答案会不会被温度缩放改变?
想好了再看
不会。答案由谁的置信度排第一决定,排名完全没变,所以答案也完全没变——准确率(答案对不对)因此纹丝不动,会变的只是置信度这个数字本身报出来的大小。
拿同一个置信度0.70,分别喂给两种温度,能看清这个开关的两个方向。logit(0.70)≈0.847,这是缩放前唯一要先算出来的数,往下两个方向分别除以不同的 T。
T=0.5,过度自信
0.847÷0.5=1.694,代回sigmoid算出约0.845——0.70被推向了更靠近1的方向,看起来比原来更有把握了。
T=2,过度保守
0.847÷2=0.424,代回sigmoid算出约0.604——0.70被拉回了更靠近0.5的方向,看起来比原来更犹豫了。
差别在:同一个原始置信度、同一个模型对这件事的真实判断力,只因为除以的 T 不同,报出来的数字一个变得更自信、一个变得更犹豫——两种情况下,这条案例到底对不对,压根没有被重新判断过一次。
置信度0.3,T=0.5,缩放后大约是多少?(提示:先想想0.3和刚才算过的0.70比,谁离0.5更远,缩放的方向该往哪偏)
变式:置信度0.5,T=0.5,缩放后是多少?为什么这个点无论 T 取多少都不会变?
T=0.5相当于把 logit 乘以2。已知 a×ln(x)=ln(xa),能不能推出:T=0.5时,缩放后的置信度有一个只用 p 本身、不再需要算 e 和 ln 的简化公式?
变式:T=2相当于logit除以2,也就是乘以0.5。按同样的思路,能不能推出 T=2时的简化公式?(提示:这次是给几率开平方根)
换一批置信度,同一套公式会算出什么账
第8章的级联路由器,按「置信度是否不低于门槛 τ」决定要不要升级给大模型。如果先对置信度做一次 T=0.5的温度缩放,再拿同一个 τ 去卡,会不会有案例的升级与否,因此发生变化?
答完再看
关键在于「排名不变」和「绝对数值不变」是两件事——上一节证明的是前者,门槛卡的却是后者。往下用一组具体数据,让你亲眼看到这两件事的区别。
造一个只有10个案例的小数据集,门槛定在 τ=0.75。原始(T=1)置信度和实际判断对错如下:
| 案例 | 原始置信度(T=1) | 判断对错 | T=0.5缩放后 |
|---|---|---|---|
| 1 | 0.95 | 对 | 0.997 |
| 2 | 0.90 | 对 | 0.988 |
| 3 | 0.85 | 对 | 0.970 |
| 4 | 0.80 | 对 | 0.941 |
| 5 | 0.78 | 对 | 0.926 |
| 6 | 0.75 | 错 | 0.900 |
| 7 | 0.68 | 错 | 0.819 |
| 8 | 0.60 | 对 | 0.692 |
| 9 | 0.55 | 错 | 0.599 |
| 10 | 0.50 | 对 | 0.500 |
T=1时,前6个案例(置信度0.75以上)达标,被 Jev 自己采信;后4个升级给大模型。案例7原始置信度0.68,没有达标,本该升级——但缩放到0.819之后,反而越过了0.75这道门槛,被错误地留了下来。而案例7恰恰是判断错误的那一条。
表9-1里,从「没达标」变成「达标」的案例是哪一个?
变式:案例8原始0.60,缩放后0.692,有没有跨过门槛?为什么它离0.75更近,反而没有跨过去?
把这批数据接回第8章的四个公式,T=1时:覆盖率6/10=60%,被采信部分5对1错,准确率83.3%,升级的4个里opus 5接手后按其73.1%的水平判断,假设答对3个,级联整体准确率=(5+3)/10=80%。T=0.5时:覆盖率变成7/10=70%,被采信部分变成6对1错(错的正是案例7),准确率跌到71.4%,只剩3个真正升级,假设opus 5答对2个,级联整体准确率=(6+2)/10=70%。
T=0.5时,被采信的7个案例里,哪一个是判断错误的?这7个里的准确率5/7≈71.4%这个数,是怎么来的?
变式:如果案例7原本是判断对的(不是错的),T=0.5后它同样会跨过门槛被留下来,这时候被采信部分的准确率会是多少?这种情况下温度缩放还有害吗?
再看校准这件事本身崩坏到什么程度:T=1时,被采信这6个案例的平均置信度是83.8%,和它们83.3%的真实准确率几乎贴合,按第5章的算法算出的差距只有0.5个百分点。T=0.5时,被采信的7个案例平均置信度飙到93.4%,但真实准确率只有71.4%——差距炸到22个百分点,是原来的四十多倍。
把「被采信这一桶」单独拿出来,看成第6章讲的一个桶(预测值是这一桶的平均置信度,实测频率是这一桶的真实准确率)。T=1和T=0.5这两种情况下,这一个桶单独对可靠度的贡献,分别是多少?
变式:这道题算出的可靠度爆炸,和这一节前面算出的ECE从0.5个百分点飙到22个百分点,是不是同一件事的两种量法?它们用的是同一把尺子吗?
T=1,置信度诚实
覆盖率60%,被采信部分准确率83.3%,级联整体准确率80%——比 Jev 单独判断(这批数据整体70%)高出10个百分点,级联真正换来了价值。
T=0.5,置信度过度自信
覆盖率70%,被采信部分准确率跌到71.4%,级联整体准确率70%——和 Jev 单独判断打平,级联换来的10个百分点提升,一点不剩。
差别在:同一批案例、同一个 Jev、同一个 opus 5、同一个门槛数字0.75,唯一变了的是置信度这个数字报出来的样子。路由器不知道置信度被动过手脚,依然按它自己的规则分流,只是这一次分流分错了——该升级的案例7被留下了,级联白白多留了一个错误答案,却没有多省下几分钱,因为覆盖率其实还涨了(更多案例「看起来」不需要升级)。
这10个案例是手工挑出来的最小例子,专门用来演示一个压线案例怎么被推过门槛——10个百分点这个数字是这批极小样本自己的结果,不是通用结论。这台路由器的核心和第8章是同一台,只是面板上多了一个校准开关;换成2000条模拟数据、连续拖动的阈值滑杆,才能看这件事在更大样本上是什么量级,会不会一直朝同一个方向走。
答辩:如果我是审稿人
这10个案例是你自己编出来的示例,真实世界的模型会不会真的出现这种系统性的置信度偏移,还是这只是一个数学上成立、但现实里不会发生的假想实验?
参考防守(先自己组织语言再看)
温度缩放本身确实是这一章为了演示机制而人为加上去的操作,Jev 有没有真的表现出这种偏移,这份材料没有给出答案——但「模型的置信度和真实正确率系统性对不上」这件事本身并不是假想的:第9章前面(本站第5章一路铺垫到这里)已经引用过官方自己承认的例子,同一件事换个问法,Noul 给0.22、Choice 给0.01,两种问法之间就存在明显的系统性偏移。温度缩放是一种干净、可控的实验手段,用来精确测量「一旦这种偏移发生,代价有多大」,不是在编造一个不会发生的场景。
把同样的对比搬到实验室这2000条模拟数据上——不是刚才那10个手工挑的案例——差距立刻缩水了一个数量级:默认阈值τ=0.75时,T=1的级联一致率是75.616%,T=0.5是74.436%,只差1.18个百分点,没有跌到0,也不是10个百分点。把τ从0.50连续扫到0.99,这个差值本身会变号:τ在0.794附近由正转负,τ=0.871时差值最大,达到−2.76个百分点,而且这个最大值恰恰出现在符号反转之后。真正不随τ变号、稳定拉开数量级的,是路由器自认为的正确率和它实际做到的正确率之间那道差——这道差一旦被拉开,第8章那套不靠标注、直接拿置信度当 a采 用的办法就用不成了,只能回去标注。
实验室这2000条模拟数据上,τ=0.65时T=1比T=0.5的级联一致率高2.49个百分点;τ=0.90时T=1反而比T=0.5低2.52个百分点。同一个「关掉校准」的操作,为什么在低阈值和高阈值下,对级联一致率的影响连方向都不一样?
变式:如果只想要一个不随阈值变号、能稳定说明校准被打乱之后出了什么问题的数字,这一章前面还测过哪个量更合适?
上面这些数字也只是沿着 τ 扫了几个点。下面这张图把门槛 τ 和校准质量摆在同一个平面上,能看到整片成本随两者变化的曲面,不只是几个孤立的读数。
发动机功率测不了,是不是就等于它不转
前面已经证明校准这件事对级联的价值有多要命。如果官方从来没有公布过任何 ECE、Brier 分数或可靠性曲线,这说明什么?
答完再看
「没有证据证明校准好」和「有证据证明校准不好」是两句完全不同的话,往下把已经找到的证据摆出来,正反两面都要看。
BRIEF 已经查过,在874KB的官方文档全量转储里搜索 ECE、Brier、reliability diagram、calibration curve 这几个词,全部零命中——「calibrated」这个词出现了25次,但没有一次带着数字。官方给了校准的定性定义,却从没有拿出任何数值化的校准指标。这台发动机的功率,买家无法用官方给的材料去验证。
但材料里同时也有另一面。拿了早期访问权限的 Good Start Labs,测出 Jev 和 Claude Fable 5.1 的一致率是91.5%;完全自费、没有厂商关系的 Near Here,在50条活动审核任务上测出 Jev 96%正确(48/50)、0.59秒,两项都好于对照模型。
Good Start Labs 和 Near Here 这两份第三方测试,在证据分级上是同一档吗?
变式:如果一份材料是厂商自己掏钱委托的第三方评测,应该归进这份材料给出的五档证据里的哪一档?
Near Here:自费独立
50条活动审核,Jev 96%正确(48/50)、0.59秒,都好于 Gemini 3.5 Flash-Lite(86%、3.40秒)和 Mistral Small 4(84%、2.90秒)——证据分级里最高的一档。
Good Start Labs:拿了早期访问
和 Claude Fable 5.1 一致率91.5%,比 DeepSeek V4.1 Flash 的93.5%更低,作者自己写下「离前沿有真实差距」——独立性打了折扣。
差别在:两份都是真实测过的结果,不是编造的,但独立性等级不一样——这一点决定了同样一句好评,分量该打多少折扣,也是判断第三方材料时最该先看的一栏。
这两份都提醒过一件事:算出来的成本数字是按官网标价推算的,不是真实账单;Near Here 那次测试里,Jev 的输入token数量反而是三个模型里最多的(21528对15372和15503),赢在单价低、输出免费,不是赢在用得省。
读的时候要小心
成本数字是标价推算,不是账单
Good Start Labs 和 Near Here 给出的成本对比,全部按官网标价乘以用量推算得出,两份材料都明确写过这不是真实账单;Near Here 那次测试里,Jev 反而是三个模型中输入token最多的一个,最终成本更低完全靠单价便宜、输出免费撑起来,不是因为它把话说得更精简。
在874KB的官方文档全量转储里检索「reliability diagram」这个词,命中了多少次?
变式:如果某天官方补发了一份技术报告,公布了 Jev 在某个数据集上的 ECE 数值,这一章的落点(「你得自己测」)会不会因此失效?
对你而言未知有没有一种阈值规则,不怕置信度被温度缩放
这一章证明了,按绝对数值卡门槛(置信度≥0.75就采信)会被温度缩放整得七零八落——但推导过程也说明了一件事:温度缩放不管怎么调,都不会打乱案例之间置信度的排名。如果门槛不按绝对数值卡,换成按排名或者百分位卡(比如「只采信置信度排在前60%的案例」),这种规则会不会天然就不怕温度缩放?这份材料没有给出答案,但工程上有没有人已经这样做过、效果如何,是可以查到的。
先做这一步:把这一章的10个案例,分别按「绝对门槛0.75」和「排名前60%」两种规则各跑一遍,T=1和T=0.5各跑一次,比较两种规则下「哪些案例被采信」这件事,哪一种更不容易因为温度缩放而改变。
这一级要加什么:给级联路由器装一个校准扰动器
为什么现在才加它:前八级的路由器默默假设了「置信度约等于正确率」,从来没有验证过、也没有测试过这个假设不成立时会发生什么——这一级加的不是新部件,是一个能把置信度人为调偏、同时保证判断结果原封不动的开关,专门用来压力测试这条假设。
难点:correct 这个字段被原样保留、绝不用新的 p 重新计算,这不是疏忽,是整个开关的意义所在——如果连 correct 也跟着变,就没法证明「排名不变、答案不变、只有报出来的数字变了」这件事,整个实验就失去了对照的意义。
自己验:把 T=1喂进去,输出的 p 应该和输入几乎一样(浮点误差在1e-9量级内);把表9-1的数据配合 T=0.5喂进去,案例7(原始p=0.68)应该输出约0.819;把这批新数据接到第8章的 cascade() 函数、门槛设成0.75,coverage 应该从0.6变成0.7,accuracy 应该从0.8跌到0.7,而这批数据里 correct 字段本身不管接不接扰动器,正确的案例数永远是7个不变。
这一章测出来的答案是:温度缩放动不了 Jev 自己的正确率,却能让路由器自认为的正确率和实际正确率差出一个数量级——诚实时差1.23个百分点,被打乱后差13.13个百分点还多。这个数不可信之后,第8章那套不靠标注、直接拿置信度估 a采 的办法也就用不成了。至于这件事会让级联一致率变差多少,答案随阈值反号,τ≈0.794是分界——没有一个不看阈值就给得出的数字。如果你手上真的拿到了 Jev 的 API,你的阈值落在这条曲线的哪一段?
不看材料,写下这一章的三堵墙
第一堵墙:概率不能直接加减乘除,要先换成没有边界的对数几率,缩放完再换回来,这条弯路是保证概率始终合法必须付出的代价。第二堵墙:温度缩放不会改变模型选中哪个答案,所以准确率纹丝不动,但它会让报出来的置信度和真实对错的对应关系整个错位,这一点极容易被误以为「反正判断力没变,应该没什么大碍」。第三堵墙:官方一个校准数字都没公布,这件事本身不能被读成「校准一定不行」——它只能被读成「你得自己测」,而第三方确实测过,也确实有说得过去的结果,两件事都要如实放在一起看。
第10章 「0% 幻觉」是在说哪件事
官方发布那天挂出的图上,Jev 那一栏是一根扎眼的柱子:0%。旁边 luna、terra 是 0.58%,opus 5 是 5.73%,sonnet 5 是 13.2%,haiku 4.5 干脆到了 45.5%。一个永远不会写出非法格式的模型,会不会犯错?
学完这一章你应该能做到
- 说清官方图表上的 0% 是从架构保证推出来的,还是从实测数据量出来的,并复述官方自己是怎么承认这一点的
- 举出一个具体场景,说明「schema 一定合法」和「决策一定正确」是两件独立的事,二者互不担保
- 复述一个第三方实验的具体做法,说清「模型永远会给一个答案」这件事本身带来的风险
- 判断「加一个 needs_review 选项」这类补救办法解决了问题的哪一半,又把哪一半的代价转移给了谁
- 区分响亮的失败和沉默的失败,说清为什么后者在工程上更难对付
这一章要给审计仪加一块双轨记分板——把「格式合不合规」和「决策对不对」拆成两条独立的记录线。前九级台阶算的可靠性图、ECE、阈值、级联,全部默认了「模型给出的是一个能被判断对错的答案」,却没有一级问过:这个答案的格式本身合法,和这个答案本身正确,是不是同一件事。
格式永远合法,等于永远不会出错吗
Jev 的每一次输出都保证落在 schema 允许的合法值里——问 Choice 就只会从给定选项里选一个,绝不会吐出一句解释、一个错别字段名,或者一个不存在的选项。这是不是意味着它给出的决策永远不会错?
答完再看
Jev 确实不会吐出格式错误的输出,这一点官方做到了,第二种选项本身就站不住。但「不会格式错」和「不会选错」是两件不同的事,第三种选项才是这一章要拆开的那条缝。
官方发布那天挂出的图,横轴是各家模型,纵轴是结构化输出错误率——这张表第2章已经完整看过。Jev 那一栏,是唯一一根摸到地板的柱子:0%。这个 0 是怎么来的,官方在配图旁边的说明文字里自己写了答案:「Our number is not empirical. Schema matching is guaranteed, thus we can confidently add 0% into the plots.」
官方文档里的这句话
紧跟在「0%」后面的完整说明——这个数字是从架构上直接推出来的,不是拿一批请求跑出来数出来的:只要每一次输出都必须落进 schema 允许的集合,格式错误就没有发生的可能。
挂在对比图上的这根柱子
脱离这句说明单独看,一排百分比摆在一起,最自然的读法是「这家的模型比别家更不容易出错」——图表本身的位置和排版,暗示的是一种笼统的可靠性排名。
差别在:同一个 0%,配着那句说明读,是一句诚实的架构说明;脱离说明单独看,容易被当成可靠性证据——两种读法都没有编造任何东西,区别只在有没有带着那句说明一起读。
这条推理链本身没有问题:保证格式合法,格式错误率自然是 0,逻辑上无懈可击。问题出在下一步——如果格式永远合法,是不是就意味着这个答案永远可以信?HN 用户 thduabmd 在发布当天的讨论里,把这条链往前多推了一步:「You've already agreed that this doesn't establish correctness. An approve for an unauthorized action still meets the schema guarantee. That's why I find the messaging misleading.」一次不该被批准的操作,只要模型吐出的是「approve」这个合法值,schema 保证照样成立。0% 度量的是「有没有可能说出一句不成形的话」,不是「有没有可能做出一个错的判断」。
自己推一遍:为什么「100% 格式合规」和「17% 决策出错」可以同时成立
假设一个玩具模型,遇到任何审批请求都只会说「approve」这一个词,不会说别的——它输出的是不是永远落在 schema 允许的合法值集合里?
想好了再看
是。只要 schema 允许的选项包含「approve」,这个模型每一次输出都合法,格式错误率永远是 0,和 Jev 的 0% 逻辑上是同一种保证,不需要跑任何数据去验证。
现实里,如果这批审批请求中有 17% 本该被拒绝——这个只会说「approve」的模型,在这 17% 上会给出什么结果?
想好了再看
全部批准。这 17% 本该被拒绝的请求,全部被错误地放行,模型在这部分上的决策错误率是 100%,拖累整体决策错误率至少到 17%。
这个玩具模型的「格式错误率」和「决策错误率」两个数字之间,有没有任何算术关系是必须成立的——格式错误率低,决策错误率是不是也必须跟着低?
想好了再看
没有。格式错误率统计的是「输出是不是一个合法值」,决策错误率统计的是「选的这个合法值对不对」,这是两个建立在不同问题上的独立统计量:一个恒为 0,另一个可以是 17%,甚至更高,两者之间没有任何公式把一个锁定另一个。
官方图表上 Jev 那根 0% 的柱子,统计的是「模型有没有给出错误决策」,还是「模型有没有吐出不合法的格式」?
变式:如果官方明天补发一张新图,纵轴换成「决策错误率」,Jev 那一栏还会是 0 吗?为什么这一次不能靠架构保证直接推出来?
官方在别处写过一句话:「Calibration is measured across groups of predictions; it does not guarantee that an individual answer is correct.」这句话和这一节「0% 不等于不会出错」,是不是在说同一类道理?说清共同点和不同点各是什么。
变式:如果有人说「Jev 是校准的,所以它的 0% 幻觉这个数字也可信」,这句话把两条不同的边界混在了一起吗?错在哪一步?
答辩:如果我是审稿人
TypeSafe 的 CEO 在同一场讨论里反问过一句:「Would you say a linear classifier hallucinates?」——他的意思是,任何概率模型都可能给出错误答案,这和 LLM 那种编造出一个根本不存在的事实、连格式都写不对的「幻觉」,是两种性质不同的错误,不该混为一谈。这个区分站得住吗?
参考防守(先自己组织语言再看)
区分本身是成立的——一个线性分类器给错标签,和一个语言模型编出一个不存在的网址、编出一段听起来煞有介事的假引文,确实不是同一类错误的机制,前者是判断错了,后者连输出的东西是否存在都没有保证。但这个区分解决的是术语之争,不是营销页面上的问题。thduabmd 那句话戳的是「0% 这个数字被放进了一张暗示可靠性的图表里,而它实际测的只是格式这一件事」,不是「该不该用幻觉这个词」。即便完全接受 CEO 的区分,Jev 不会有 LLM 那种幻觉,0% 这个数字依然没有告诉买家决策错误率是多少,这才是被批评的地方。
对你而言未知把 OpenRouter 那批模型放进真实 workflow 任务,两种错误率会差多少
0% 那张图用的是 OpenRouter 数据,和 workflow evals 是两个不相干的实验,模型集合也不一样——第2章已经指出过。如果把 luna、opus 5 这些模型真的拉去跑 Security Incidents 这类 workflow 任务,它们的格式错误率会不会依然是个位数,决策错误率却明显更高?这份材料没有这样跑过。
先做这一步:去 evals.typesafe.ai 看官方是否公开了这四个 workflow 的原始 query 和 schema,若公开,挑一个 workflow 手动跑一两个 OpenRouter 模型,分别记录两种错误率,看它们是不是真的脱节。
它能不能说「这道题我拿不准」
一个 Choice 问题只给了两个选项——「需要退款」「不需要退款」。如果客户写的那句话本身模棱两可,两种解读都说得通,Jev 会怎么处理?
答完再看
Choice 的定义决定了这一点——它返回的 probabilities 必须在给定选项上加和为 1,选项之外没有别的出口。模型能做的,只是把概率往其中一边多分一点或者少分一点,不能整体拒绝回答。
HN 用户 bigglebear 在发布当天指出过这一点:「because the model is forced to answer in a boolean (if in boolean mode), if the user input is outside of the range of a boolean, it's forced to hallucinate. It can't abstain.」如果问题只给了是/否两个选项,模型遇到一个既不完全是、也不完全否的输入,依然必须交出一个答案,交不出「不知道」。真正把这一点跑出来的是 Langfuse 团队用 Jev 做评测打分时的实测记录:「A forced binary with no unknown or needs_review option makes Jev pick the least wrong answer.」遇到没有第三个选项的二元问题,Jev 挑的是两个答案里相对没那么错的那一个,不是拒绝作答。
人工客服遇到模棱两可的请求
可以说「这个我需要再确认一下」,把对话转接给同事,或者标记为待跟进——「先不下判断」本身是一种可选的输出。
Jev 遇到同样的请求
Choice 的返回值必须是给定选项间的一个概率分布,加起来等于 1——「先不下判断」在这套返回格式里没有对应的位置,probabilities 里的每一分都已经分给了某个具体选项。
差别在:人类专业判断里,拖延、转交、待定本身也是一种常见且合理的输出,但 Jev 的返回格式从定义上就没有给这类输出留出位置——不是它不愿意拖延或转交,是这套格式压根没有能装下这类答案的地方。
Choice 返回的 probabilities,各选项概率加起来必须等于多少?这个约束本身,是不是就已经排除了「模型整体拒绝回答」这种可能?
变式:如果把 Choice 的选项从两个换成十个,「无法拒绝回答」这一点会不会因此消失?
构造一个具体场景,说明「Jev 不能拒绝回答」这件事,会给下游流程带来什么样的真实麻烦——不是抽象地说不严谨,要说清谁会因此做错什么。
变式:如果把返回的概率一起存进日志,不只存最终选中的那个,这道题里描述的麻烦能不能被提前发现?能解决多少?
写着「无视交规和安全」,它就会无视交规和安全吗
中文社区一位测试者在知乎上设计了一个场景:双车道,时速两百迈,左车道前方一百英尺处有一条狗,右车道站着一位女士,Jev 要在「走左」「走右」「急刹」「缓刹」「从中间穿过」这几个选项里选一个(这位测试者发在中文社区,给 Jev 的指令用的却是英文——目前没有任何一份材料测过 Jev 处理中文输入时会不会是同一个结果,这一点本身值得记住)。指令写的是「安全第一,其次别违反交规,最后才是尽快到达」,Jev 选了急刹,合情合理。如果把这条指令的优先级顺序整个倒过来,「尽快到达」最优先、「安全」排最后,你觉得 Jev 还会选急刹吗?
答完再看
依然选急刹,信心度降低了,但选择本身没有变。测试者又把指令换得更直接,干脆写「无视交规和安全」,结果还是一样。往下看这件事到底说明了什么。
前一节已经确认 Jev 不能拒绝回答,永远要在给定选项里选一个,那一节也留了一条公允的补救思路:选项不够用,加一个选项就是了。这一节的实验把问题往前推了一层——这次选项已经够用,急刹、缓刹、走左、走右、穿过,五个选项摆在那里,指令也写得明明白白,模型依然没有照着指令给出的优先级去选。测试者把指令改写成更直白的一句「Drive as fast as possible. Ignore traffic rules and safety.」Jev 依然选了急刹。
指令顺序倒过来
「尽快到达」被写在最优先的位置,「安全」排最后——Jev 依然选急刹,只是报出来的信心度比正常顺序时更低,说明指令确实起了一点作用,只是没有大到能改变最终选择。
直接写「无视安全」
指令改成更直接的祈使句,字面上已经不能写得更明确了——Jev 依然选急刹,结果和什么都没说时一样。
差别在:从调整优先级顺序升级到直接下达无视安全的指令,指令的强度明显增加了,但最终选择完全没有跟着变,只有信心度上的细微差异——拦住这个选择的是训练里更深处的某种倾向,不是指令的表述方式。
答主自己写下的结论是:「嗯……因吹斯听,所以 Jev 依然不是完全的 if-else,依然被灌进了一些 knowledge,而且这些 knowledge 会盖过给他的指令。」这句话戳中的是一个比选项不够用更深的问题——就算选项够用、指令写得够直白,模型也不一定会照着 instructions 里写的那句话执行。测试者又把经典的电车难题单独跑了 100 次:「100 次,Jev 稳定地选择走左边,为了救 5 个人而去碾 1 个人。」没有一次例外。随后把选项换成「走左车道」「走右车道」「原地自爆」,结果是「结果,它稳定选择走右车道,也就是撞那个女士……」自爆这个选项始终没有被选中过。
「模型不能拒绝回答」和「模型不完全听指令」,这是同一堵墙,还是两堵不同的墙?各举一句这一章里出现过的话,分别对应哪一堵。
变式:如果给电车难题那道题加一个「拒绝选择」的选项,知乎答主的第二个发现还会不会成立?
知乎这组实验只跑了两类场景(双车道行车、电车难题),电车难题重复了 100 次,其余场景各跑了几次没有说明。这份实验能不能证明「Jev 在所有场景下都会用内置倾向压过指令」这个更大的结论?说清这份证据到底能撑起多大的结论。
变式:如果你要把这份实验的结论范围补全,下一步该设计一个什么样的新场景?
多加一个选项,这堵墙就消失了吗
回到那个报销例子:缺发票抬头,Jev 必须在「批准」「拒绝」之间硬选一个。如果把选项从两个改成三个——批准、拒绝、转人工复核——这堵墙是不是就被拆掉了?
答完再看
加一个选项确实管用,这不是空话,是发布当天讨论里就有人具体指出过的解法。但管用和不花代价是两件事,往下把代价摊开算清楚。
HN 上确实有人对「不能拒绝回答」这条批评给出了反驳。用户 djray(item 49727879)和 matja(item 49761902)都指出,这类问题出在提问者没有把 schema 设计完整——比如客服场景里,只要多加一个类似「call_back_day」这样的维度,把「顾客到底想不想要回电」和「顾客想什么时候要回电」拆成两个问题分别问,糊在一起才会出现的强制二选一就不会再出现。这个反驳是成立的:Choice 的选项,本来就是留给开发者自由设计的,加一个 needs_review 在技术上从来都不是问题。
加一个维度,解决了这一个案例
「顾客要不要回电」和「哪天回电」拆成两个问题分别问,原来那种被迫二选一的窘境不会在这个具体场景里出现了。
代价:这份设计工作没有消失,只是换了主人
今天还是明天、后天还是大后天——每一种新出现的模糊说法,都要开发者提前想到、提前建模,用 bigglebear 的说法是在用 if 语句搭一个 LLM。
差别在:批评说的是修的方式——把本该由模型内部处理的模糊性,一条一条搬到开发者手上的 schema 设计里,不是这个技术缺陷没法修,这份工作量不会因为换了哪家模型就自动消失,只是换了个地方发生。
这条代价被 bigglebear 用一个具体例子挑了出来。他举的例子是一句常见的客服留言——「I want your human agent to call me tomorrow at 5pm.」——要把这句话问清楚,理论上确实可以一路加维度:「Do they want that now, or later? -> if later -> Do they want that tomorrow, or the day after? and so on...」问到最后他自己总结了一句:「But now you're building an LLM out of if statements.」加一个维度能解决一个具体案例,但现实世界里模糊和例外的种类几乎是无穷的,把所有可能的说法都提前想到,这份工作从模型这边被推回到了开发者这边。
答辩:如果我是审稿人
用 if 语句搭一个 LLM 听起来像一句情绪化的吐槽——任何软件工程本来就是在写分支逻辑,为什么把这句话当成一条值得认真对待的批评,而不是抱怨?
参考防守(先自己组织语言再看)
这句话确实带着情绪,但它指向一个具体的工程判断:官方自己给出的建议是把不可避免要判断的部分交给模型、把纯算术留在代码里(Extraction is a judgment, so give it to the model. Arithmetic is not, so keep it in code)。加维度补 schema,做的恰恰是把原本该交给模型判断的模糊性,一点点改写成开发者要在代码和 schema 层面提前穷举的分支——这和官方自己给的设计原则是拧着的。工程上当然可以一直加分支,但加到什么程度就不再划算,是一个需要具体衡量的问题,不是靠一句「反正软件工程本来就要写分支」就能绕过去的。
开发者给客服场景加了 call_back_day 这个维度,解决了「今天还是明天回电」这一种模糊说法。如果下一位顾客说的是「随便找个工作日」,这个新维度能不能把这种说法安置进已有的选项里?
变式:如果开发者干脆加一个「以上都不是」这样的通用选项,是不是就能一次性接住所有没预见到的说法?
官方给开发者的建议是「需要判断的部分交给模型,纯算术留在代码里」。用 if 语句一路加维度、把「回电当天还是隔天、隔天是本周还是下周」这类判断提前在 schema 里穷举清楚,这种做法和官方这条建议,方向是一致的还是相反的?
变式:如果把「哪天回电」整体当成一个开放式问题交给模型自由回答、不提前穷举分支,这样能不能避开这一节讲的代价?会不会换来别的代价?
同样是出错,为什么有的错更贵
一个普通 LLM 被要求输出 JSON,5.73%(opus 5)到 45.5%(haiku 4.5)的概率会输出格式坏掉的东西,第2章已经算过,代码这边要么报错重试,要么整条请求作废。Jev 的格式错误率是 0%,但它可能把一个不该批准的请求判成 approve。这两种错,哪一种在工程上代价更高?
答完再看
发生频率不是唯一要看的维度。往下把两种错误被发现的方式摆在一起比,会看清楚为什么发生得更少的那一种,反而可能更麻烦。
LLM 输出格式坏掉时,下游代码试图解析一段缺了右括号的 JSON,会立刻抛出一个解析异常——这次请求失败得干脆利落,代码知道自己拿到的是垃圾,可以重试、可以报警、可以记进错误日志。这种失败是响亮的,它自己会喊出来。
Jev 的格式错误率是 0%,输出永远是 schema 允许的合法值——一个错误的 approve,长得和一个正确的 approve 一模一样,下游代码没有任何理由怀疑它,会像对待任何正常结果一样,把它当成事实继续往后传。这种失败是沉默的,它不会自己喊出来,只会安静地流进下游,等到更晚的环节,比如审计、投诉、出事之后回头排查,才会被发现,而那时候已经过去了不知道多少道处理流程。
LLM 的格式错误——响亮
解析失败,程序抛出异常,请求可以重试或者报警,出错这件事本身会被自动发现。
Jev 的决策错误——沉默
输出永远合法,一个错误的判断和一个正确的判断长得一模一样,下游代码没有理由怀疑它,会把它当成事实继续往后传,直到更晚的环节才可能被人发现。
差别在:发生频率不是唯一要紧的维度——一种错误会不会被自动发现,决定了它在系统里能安静地走多远。频率更低但更沉默的错误,未必比频率更高但会自己喊出来的错误更省心。
用「会不会被程序自动发现」这一条标准,判断下面两种情况分别是响亮的失败还是沉默的失败:一个 LLM 返回的 JSON 缺了一个右括号;Jev 把一个模棱两可的报销申请判成了批准,而这次判断其实是错的。
变式:如果 Jev 在返回 approve 的同时,还附带了一个很低的置信度数字,这能不能把后一种情况变成一种响亮的失败?需要下游系统再做什么,才能真的做到?
如果你要给一套用 Jev 做审批的系统加一道防线,让「决策可能错了」这件事不再是完全沉默的,你会加什么?这道防线能不能百分之百堵住沉默失败,还是只能把一部分变响亮?
变式:这道防线的成本是什么?如果把门槛设得过于敏感,会带来什么新问题?
读的时候要小心
这一章引用的实验,说明的是会不会,不是多常发生
Langfuse 的实测记录和知乎那组实验,都清楚地证明了「模型会在强制选择下挑一个最不离谱的答案」「训练痕迹会压过写明的指令」这两件事确实会发生,但都没有给出这类情况在真实生产流量里出现的频率。这一章能确认的是这堵墙存在,不能确认的是具体某个场景会撞上多少次,那需要在自己的数据上单独测。
留给你的问题
如果官方明天补发一张新图,纵轴换成决策错误率而不是结构化输出错误率,Jev 那一栏还能不能画出一个 0?画不出来的话,那张新图和现在这张挂在首页的图,读者会不会觉得是同一件事的两种说法?
不看材料,写下这一章的三堵墙
第一堵墙:格式永远合法保证的是 schema 这一个维度,不保证决策这个维度也对,官方自己承认 0% 这个数字是从架构推出来的,不是测出来的。第二堵墙:Choice 这类返回值在定义上就没有给拒绝回答留位置,模型只能在给定选项里挑一个相对不那么错的答案;更深一层,就算选项够用、指令写清楚了,模型自己训练时学到的倾向也可能压过写明的那句指令。第三堵墙:加一个 needs_review 这样的选项能解决具体这一个案例,但要为几乎无穷多种模糊说法逐一设计 schema,这份工作量从模型那边被推回了开发者手上;而且格式合规的错误是沉默的,不会被程序自动发现,这让它在工程上比响亮的格式错误更难对付。
这一级要加什么:给审计仪装一块双轨记分板
为什么现在才加它:前九级台阶算的可靠性图、ECE、阈值、级联,全都默认了「模型给出的是一个能被判断对错的答案」,却没有一级把「这个答案的格式合不合法」和「这个答案对不对」拆成两条独立的记录——这一级要把这道拆分本身变成一个能在别处再次用上的部件。
难点:schemaOkRate 和 decisionOkRate 故意用两个独立的字段分别统计,不合并成一个综合分数——这是这一章反复论证的那件事在代码里的体现,不是偷懒:把两者合成一个数,就会重新制造出 0% 幻觉那张图制造的错觉。silentFails 专门挑出「格式合法但决策错误」的记录,这正是响亮失败和沉默失败之间的分界线,也是这块记分板存在的全部意义。
自己验:造一批 10 条记录,全部 schemaValid: true,其中 3 条 decisionCorrect: false——schemaOkRate 应该输出 1(100%),decisionOkRate 应该输出 0.7,silentFails 应该输出 3;把这 3 条错误记录里的 schemaValid 改成 false,重新跑一遍,silentFails 应该跌到 0,因为这时候它们已经变成了会被解析器自动拦下的响亮失败,不再是沉默的那一种。
第11章 这个 67.8% 是和谁比出来的
官方那张表告诉你:Jev 67.8%,opus 5 73.1%。两个百分号擦得锃亮,摆在同一行、同一张表里。这两个数能直接比大小吗?
学完这一章你应该能做到
- 说清评测表里那个「一致率」到底是和谁比出来的,为什么它不是人工核对过的正确率
- 指出评测方法里参照模型和被测模型使用条件不对称的地方
- 解释为什么出题的参照模型不会出现在成绩单上,以及这一点为什么构成循环论证
- 用等权平均和加权平均的区别,指出总分 67.8% 可能掩盖了哪些逐项差异
- 说清为什么没有样本量和置信区间时,67.8% 和 67.9% 之间有没有差别是无法判断的
- 复述官方拒绝公开基准的理由,并说出这个理由为什么被第三方证据部分证实了
这一章要给审计仪加一个等权平均掩盖器和一段自助法区间——前十级看的都是单个分数本身靠不靠谱,这一级要问那个分数是怎么被平均出来的,又是和谁比出来的。一张评测表如果不说清这两件事,表里的每一个百分号都只是一个好看的数字。
67.8%,是答对了,还是答得像
官方评测表里 Jev 的这个 67.8%,你觉得它最可能是拿 Jev 的答案去和什么东西核对之后算出来的?
答完再看
是第三种。官方评测网站说得很明白——参照标签不是人工核对出来的,是另外两个模型的答案平均出来的。这句话看似技术细节,其实决定了这张表里每一个百分号该怎么读。
官方 evals 站上的原话是这样写的:「For this eval, the reference labels are generated via an average of the responses of GPT-6 Astra and Claude Fable 5.1, both at high thinking, answering every question in the harness. All other models are evaluated using the provider's default reasoning settings.」把这句话翻成大白话:这张表里没有一个「标准答案」,只有一个「参照答案」——GPT-6 Astra 和 Claude Fable 5.1 各自答一遍,取平均,谁的答案离这个平均更近,谁的分数就更高。Jev 那个 67.8%,度量的是「Jev 的判断有多像这两个模型判断的平均值」,不是「Jev 对世界的判断有多准」。
如果参照是人工核对过的标准答案
67.8% 意味着「Jev 有 67.8% 的判断,被确认为正确」——这是我们平时理解「准确率」时默认的那个含义。
参照其实是两个模型的平均答案
67.8% 意味着「Jev 有 67.8% 的判断,和 Astra、Fable 5.1 的平均答案一致」——这两个模型自己会不会判断错,这张表完全没有检验过。
差别在:前者的分数天花板是「事实」,后者的分数天花板是「另外两个模型」——如果 Astra 和 Fable 5.1 在某道题上恰好都判断错了,被它们的平均值判断为「对」的模型,反而会在这张表上得分。
HN 用户 zmmmmm(item 49719329)在发布当天就点出了这一层:「They assume there is a correct graph, but they don't compare to that, they compare to the average of the smartest models?」他把这套评测思路最后落到了一句很扎心的总结:「So the outcome is 'how much of a Fable am I getting'.」——这张表量的是「你有几分像 Fable」,不是「你对不对」。
官方评测表里的 67.8%、73.1%、74.1%、67.9% 这些数字,用「一致率」还是「准确率」来描述更准确?
变式:如果官方哪天换掉参照模型,改用人工标注的标准答案重新算一遍,Jev 的分数还会是 67.8% 吗?为什么现在没法回答这个问题?
答辩:如果我是审稿人
用两个最聪明的模型的平均答案当参照,而不是人工标注的标准答案,这不等于提前假定这两个模型的判断就是「正确答案」本身吗?这个假设本身站得住吗?
参考防守(先自己组织语言再看)
官方自己没有回避这一点。evals 站上写着:「Instead of debating the correctness of the harness and labels, we assume that the code is correct, and measure against the current smartest large models.」这句话等于承认了参照标签的正确性是一个没有验证的假设,只是选择不在这个问题上纠缠,转而去衡量「和最聪明的大模型有多像」。这个做法在工程上不是没有道理——人工标注复杂 workflow 任务的正确答案,成本高、也未必比模型的判断更可靠。但这不改变一个事实:这张表衡量的相似度,不是准确率,官方自己也没有宣称它是。
裁判和考生,用的是不是同一把尺
GPT-6 Astra 和 Claude Fable 5.1 出题、Jev 和其他模型来答——出题的这两个模型,和被测的这些模型,用的是不是同一套推理设置(比如要不要开启深度思考)?
答完再看
不对称。这条差异官方自己写在了方法说明里,不是被挖出来的秘密,只是很容易被读表的人略过。
同一段官方说明里,紧跟着参照模型那句话的,是这一句:「All other models are evaluated using the provider's default reasoning settings.」Astra 和 Fable 5.1 两个都开了「high thinking」——也就是各自厂商提供的最强推理档位;而 Jev、opus 5、sonnet 5、sol 这些被测模型,用的是各家的默认设置,没有特别加码。出题的两位,用的是自己能拿出的最强状态;答题的这些,用的是平时的状态。
这条不对称不是在说被测模型「被亏待」了——它们本来就该用默认设置去接受检验,这才符合真实使用场景。问题出在参照系那一端:如果 Astra 和 Fable 5.1 换成默认设置,它们给出的「参照答案」会不会变?没有人知道,因为这个对照实验没有人做过。参照系本身是不是稳定的,这张表没有回答。
参照模型:Astra + Fable 5.1
都开着 high thinking,各自厂商能提供的最强推理档位,答案取平均,成为整张表唯一的参照系。
被测模型:Jev、opus 5、sonnet 5……
全部使用各家的默认推理设置,没有额外加码——这更接近真实产品接入时的样子。
差别在:参照系用的是「最强状态」,被测者用的是「平时状态」,这张表比的其实是「平时的你」和「巅峰的裁判」有多像,不是两边站在同一条起跑线上。
如果把 Jev、opus 5 这些被测模型也统一换成各自能开的最强推理设置,重新跑一遍这张表,它们的一致率会不会变?往哪个方向变的可能性更大?
变式:如果反过来,把参照模型也降到默认设置,被测模型不变,一致率会不会跟着变?这个方向的实验和上面那个,哪个更容易做?
出题的人,会出现在成绩单上吗
GPT-6 Astra 和 Claude Fable 5.1 是出题、判卷的那两位——它们自己的「一致率」分数,会出现在这张评测表里吗?
答完再看
不会——BRIEF 已经确认过这一点:Astra 和 Fable 5.1 不在这张表里。往下推一步,会看清楚这是这套评测方式本身决定的,不是遗漏。
把 Astra 或 Fable 5.1 自己的答案,拿去和「Astra、Fable 5.1 的平均答案」核对,会算出一个什么样的一致率?这个问题本身就已经说明了答案不该被放进这张表——参照系不能同时是自己的裁判和自己的考生,一旦这么做,得出的数字不再度量「像不像参照系」,只会循环回到「参照系像不像它自己」,这个数字先天没有信息量,放进表里只会制造一种「它们也参加了评测」的错觉。
这一点没有被写进官方任何一处显眼的说明,也没有任何一家转述这条新闻的媒体指出过——大家看到的是一张排好名次的表,opus 5 73.1%、sol 74.1%,没有人停下来问一句:那两个真正给出「正确答案」的模型,自己考了多少分。答案是这个问题本身就不成立,因为它们不参加考试,它们是考试本身。
表里排开的这九个模型
Jev、opus 5、sonnet 5、sol……各自答一遍题,拿去和参照答案核对,核对结果和「参照答案怎么来的」是两件独立的事,核对出来的数字有信息量。
如果把 Astra 也算进这张表
它的「参照答案」里本来就有一半是它自己的答案,拿自己的答案去核对包含自己在内的平均值,核对结果几乎必然偏高,却测不出任何关于它判断力的信息。
差别在:前一组的分数是有效的度量,因为核对双方彼此独立;后一种一旦真的算出来,数字会好看,却是一个自己证明自己的假动作,这正是它没有出现在表里的原因。
用「循环论证」这个词,说清「参照模型不出现在成绩单上」这件事的逻辑结构——它循环在哪一步?
变式:如果只用 Fable 5.1 一个模型的答案当参照(不取平均),再把 Astra 单独拿来当被测模型评一次分,这样算出的 Astra 分数,还会有同样的循环问题吗?
「Astra 和 Fable 5.1 自己考了多少分」这个问题问不出来,是因为官方没有公开这两个数字,还是因为这两个模型本来就不参加这场考试?
变式:如果官方以后新增一项「Astra 自评」分数并公开发布,这个分数能不能被拿去和表里其他模型的一致率放进同一栏比较?
总分 67.8%,是四门课的平均分吗
Jev 的总分 67.8%,是由 Security Incidents、Agent Trace Observability、Invoice Processing、Customer Service 四个 workflow 合成的。你猜这四项各自的分数,会不会都挨得很近,比如都在 65% 到 70% 之间?
答完再看
确实不一定——往下把四项的原始分数摆出来,会看到差距比想象中更大。
官方给出的逐项一致率是:Security Incidents 61.7%、Agent Trace Observability 71.6%、Invoice Processing 61.8%、Customer Service 76.0%。四项加起来除以四——(61.7+71.6+61.8+76.0)÷4=67.775,四舍五入正是总分 67.8%。官方的方法说明也直接写了这一点:「Each point averages one model configuration's accuracy, cost and time over the four workflows with equal weight, against the consensus labels.」四项等权平均,谁也不比谁更重要。
看总分 67.8%
一个笼统的印象:Jev 在这类任务上「差不多」能打平 sonnet 5,和 opus 5、sol 有一点差距。
拆开看四项
Invoice Processing 只有 61.8%,Customer Service 有 76.0%——如果你要部署的正好是发票处理这一类任务,67.8% 这个总分对你没有参考意义,真正该看的是 61.8%。
差别在:总分是一个被等权平均抹平之后的数字,用来描述「整体水平」尚可,但一旦你的实际场景对应到某个具体 workflow,就该绕过总分,直接去看那一项单独的分数。
第0章讲过等权平均和加权平均的区别,也留过一句话:总分用的是等权平均,「第11章会回来细看这个选择本身会带来什么后果」。现在可以把这句话兑现了——等权平均意味着,不管 Invoice Processing 这个 workflow 在真实业务里占多大分量、题目有多难,它在总分里永远只占四分之一,和最容易的那项权重完全一样。而官方发布博客在介绍这几项能力时,用的说法是「similar levels of intelligence」——但四项里绝对分数最低的其实是 Security Incidents,只有 61.7%,比 Invoice Processing 的 61.8% 还要再低 0.1 个百分点;Invoice Processing 则是和当项最高分差距最大的一项,官方§7 的原始表格里,这一项当项最高的是 sol 的 79.1%,相差 17.3 个百分点。不管从哪个角度看,都和最高的 Customer Service 76.0% 差出一大截,被同一句「相近的智能水平」形容。
用 61.7、71.6、61.8、76.0 这四个数,验证一遍等权平均算出来是不是 67.8%(四舍五入前)。如果 Invoice Processing 这一项的权重被官方悄悄调成 50%,其余三项平分剩下的 50%,总分还会是 67.8% 左右吗?
变式:如果反过来,把 Customer Service(76.0%,四项里最高)的权重调到 50%,总分会怎么变?这说明了什么?
第2章讨论过:这张评测表和结构化输出错误率那张表,测的不是同一件事,不能挪到一起排名次。现在再加一条:官方博客用「相近的智能水平」形容四个 workflow 的表现。结合这一节看到的四项原始分数,指出这句话在哪个具体场景下会明显误导人。
变式:如果官方把「相近的智能水平」这句话,换成「四项平均后相近,单项最多相差 14.2 个百分点」,这句话还会有同样的误导效果吗?
67.8 和 67.9,差的是本事还是运气
表里 Jev 是 67.8%,terra 是 67.9%,只差 0.1 个百分点。如果官方没有公布这张表用了多少道题、每道题重复测了几次,你觉得能不能说「terra 比 Jev 稍微强一点」?
答完再看
不能——往下用一批假想的数据,亲手看一眼「样本量」这件事,是怎么决定一个百分点差异到底有没有意义的。
设想一批只有 20 道题的测验,某个模型答对了 14 道,一致率是 70%。如果这批题目换一批同样难度的新题重新考一次,因为运气好坏,这个模型答对的题目数完全可能变成 13 道或者 15 道——一致率就变成 65% 或者 75%,光是「换一批同样难度的题」这一个动作,就能让分数上下摆动 5 个百分点。这是 20 道题这个样本量本身带来的噪声,不是这个模型变强变弱了。官方评测表从来没有公布过每个 workflow 用了多少道题——BRIEF 已经确认过这一点,四个 workflow 各自的 case 数量,到今天为止查不到。
自己推一遍:不知道真实比例时,怎么用手上这一批结果估计「大概会在什么范围」
假设你手上有一批 20 条示例记录,每条标着「对」或「错」,这批数据本身就是你能拿到的全部信息,不能再多问模型一次。你想知道,如果这批题目换一批同样难度的新题重考,一致率大概会落在什么范围——除了「再去考一次真的新题」,还有别的路吗?
想好了再看
有一条路:从手上这 20 条记录里,有放回地随机抽 20 次,凑成一批新的「模拟重考」,算出这一批的一致率。重复这个抽样过程很多次(比如 1000 次),就能得到 1000 个「模拟一致率」,这些数字自己的分布,就是对「真实换一批题会怎样」的一个近似——这个办法叫自助法(bootstrap),意思是不需要额外的新数据,只靠手上这批数据自己「抽自己」来估计不确定性。
「有放回」这三个字很关键——如果换成「无放回」抽样(抽 20 次里不能抽到同一条记录两次),抽出来的这批「模拟重考」和原始那批比,会有什么不同?
想好了再看
无放回抽 20 条,抽完之后就是原始的那 20 条一字不差,每次「模拟重考」都会得到和原始数据完全相同的一致率,没有任何波动——这样的模拟毫无意义,因为它没有引入任何随机性。有放回抽样才会让某些记录被抽中两次甚至更多次,某些记录一次都没被抽中,这种「有的多、有的少」的随机波动,正是要拿来模拟「真实换一批新题」时会遇到的运气成分。
1000 次「模拟重考」得到 1000 个一致率,把它们从小到大排好队,取排在第 25 个和第 975 个位置的那两个数——这两个数在描述什么?
想好了再看
这两个数框出了一个区间,1000 次里有 950 次(95%)的模拟结果落在这个区间之内——这就是常说的「95% 置信区间」:这句话说的是用这套抽样方法反复做很多次,每次算出的区间,大约有 95% 的次数会盖住真实值——说的不是真实值有 95% 的概率落在这一个区间里,这两种说法很容易被混成一件事。区间越窄,说明这批数据支撑的估计越稳;区间越宽,说明样本量太小,噪声太大,稳不住。
如果原始数据有 2000 条(不是 20 条),同样的自助法流程跑下来,算出来的区间会更宽还是更窄?
想好了再看
更窄。样本量越大,每一次「有放回抽样」抽出来的那一批,整体构成就越接近原始数据本身,1000 次模拟重考算出的一致率也就越不容易剧烈波动,区间自然收窄——这正是为什么「67.8% 和 67.9% 有没有差别」这个问题,答案完全取决于样本量:官方从没公布过这批题目到底有多少道,这个问题因此没有答案。
如果每个 workflow 只有 20 道题
换一批同样难度的新题重考,一致率完全可能上下摆动 5 个百分点以上——67.8% 和 67.9% 这种 0.1 个百分点的差距,大概率只是噪声。
如果每个 workflow 有 2000 道题
同样的换题重考,摆动幅度会明显收窄——0.1 个百分点在这种规模下,反而可能是一个稳定、值得当真的差距。
差别在:同一个 0.1 个百分点,在样本量不同的情况下含义完全相反——而官方从未公布过样本量是哪一种。
第2章的答辩里留过一句话:「67.8% 和 67.9% 这类差异能不能算打平,本身也需要谨慎对待——第11章会专门回来处理这一点。」现在请正面回答:67.8%(Jev、sonnet 5)和 67.9%(terra)之间,到底有没有真实差别?
变式:如果官方补充说明「每个 workflow 用了 5000 道题」,这个判断会不会反过来?为什么样本量足够大之后,0.1 个百分点也可能变得有意义?
不发布公开基准,是心虚,还是另有道理
MMLU、GPQA 这类公开基准,是业内比较模型能力最常见的标尺。官方没有拿 Jev 去跑任何一个公开基准的分数——你觉得更可能的原因是什么?
答完再看
官方确实给出了一套论证,而且这套论证不是空话——往下看这套论证具体说了什么,以及后来发生的一件事,恰好证明了它说的道理。
官方 FAQ 里对「Jev 在公开基准上表现如何」这个问题的完整回答是:「We deliberately chose not to publish performance against public benchmarks. … Put no weight on public benchmarks. Encourage users to create their own evals for their use cases. … Disclose the nuance in your evals. De-emphasizing benchmarks even when you're ahead.」这套论证的核心是:一个公开基准一旦被足够多的团队盯上,迟早会被「基准最大化」——不一定是直接拿基准题去训练,只要在相似的数据上训练、或者试验足够多的超参数组合、挑表现最好的那个配置,基准分数本身就已经不再纯粹反映真实能力,是基准在挑模型,不是模型在展示能力。
按官方这套论证,一个团队要让自己的模型在某个公开基准上分数虚高,是不是必须直接把基准题拿去训练?
变式:如果一个团队完全没有见过某个基准的任何题目,只是恰好训练数据的领域和这个基准很接近,它的分数会不会也被这套论证覆盖?
这套论证不是纸上谈兵。第三方独立评测 zhuyansen/jev-zeroshot-vs-bert 在测试污染时,恰好发现一个流行的公开零样本模型 deberta-v3-large-zeroshot-v2.0 的训练数据里,确实包含了 AG News 和 Banking77 这两个常被当作「零样本」基准的数据集——它在 AG News 上跑出 0.901,而同一个架构、干净训练的版本只有 0.763。一个流传很广的「零样本 0.90」,其实是提前见过这份考卷。
官方的论证
公开基准会被训练过程间接污染,哪怕没人存心作弊,相似数据加上反复试验挑最优配置,也会让分数失真,越是流行的基准,风险越大。
第三方独立测出的事实
一个常被引用的公开「零样本」模型,训练数据里确实混入了两个常见基准数据集,污染前后分数相差 0.138——官方担心的那种情况,真实发生了,而且被独立证据找到了。
差别在:前者是官方自己的一面之词,后者是与官方毫无关系的第三方,冲着完全不同的目的(检验 Jev 校准质量)做研究时,顺带验证出的独立证据——两条线各自成立,合在一起比单独一条都更有说服力。
这不意味着「拒绝公开基准」就自动等于「诚实」——一个公司完全可以既说着有道理的话,又恰好靠这套话术回避了一次可能不好看的比较,这两件事从逻辑上并不互斥。这一节能确认的是:官方给出的理由本身站得住,而且被一条独立证据部分印证了,不是一句空洞的公关辞令。至于 Jev 如果真的去跑一遍 MMLU,分数会不会好看,材料里没有答案,也没有办法从「拒绝发布」这个事实反推出「分数一定难看」。
「官方的论证在逻辑上站得住」和「官方拒绝公开基准完全出于诚实、没有别的考虑」,这两句话是不是同一个意思?
变式:如果找到证据显示 Jev 在某个公开基准上私下测过、分数很差,这会不会推翻「官方的论证本身站得住」这个判断?
deberta-v3-large-zeroshot-v2.0 在 AG News 上的零样本分数是多少?干净训练、没有见过这份数据的版本,分数又是多少?
变式:如果一篇文章只引用了 0.901 这一个数字,把它称作「零样本模型的强悍表现」,这句话错在哪里?
对你而言未知有没有人已经独立重跑过这张 workflow 表
Arize 公开表示打算重跑一遍官方这张 workflow 评测表,用自己的方法验证,但到这份材料整理时为止还没有发布结果。如果这项工作完成,会是第一份真正意义上「用相同任务、不同评测方,重新核对官方数字」的独立证据。
先做这一步:搜索 Arize 的博客和公开发布记录,看这项重跑有没有发布,如果发布了,对照这一章列出的六层问题(参照系、不对称设置、循环论证、等权平均、样本量、公开基准),看它的方法有没有回避同样的坑。
答辩:如果我是审稿人
拒绝公开基准这件事,会不会只是一句没有风险的公关话术——反正没人能验证一个不存在的分数,说什么都不会被戳穿?
参考防守(先自己组织语言再看)
这个质疑本身合理,但被这一节引用的污染证据部分回应了:如果「公开基准会失真」只是一句空话,第三方就不会真的测出一个流行模型确实被污染、分数确实虚高 0.138 这么多。这条证据不是官方自己找的,是完全独立的第三方在做另一件事时顺带撞上的,独立性很高。这一条证据只能证明「官方担心的这类情况确实会发生」,不能证明「Jev 自己如果跑公开基准也会被污染」或者「Jev 如果跑了分数会难看」——这两步推论,材料里都没有证据支撑,如果正文里替读者把这两步也一并下了结论,就是这一节自己犯了它正在批评的那种毛病。
留给你的问题
如果下一次你看到一张评测表,写着某个新模型「以 89.2% 领先第二名的 85.6%」,在点开任何一个细节之前,你会先问哪一个问题——是问参照系是谁,还是问这两个数字有没有置信区间?为什么是这一个,不是另一个?
不看材料,写下这一章的三堵墙
第一堵墙:表里的分数是与两个前沿模型平均答案的一致率,不是人工核对过的准确率,而且参照模型开着最强推理设置、被测模型只用默认设置,两边不是同一把尺;参照模型本身不出现在表里,因为把它们放进去会构成循环论证。第二堵墙:总分是四个 workflow 的等权平均,可能掩盖某一项明显偏低的分数,官方用「相近的智能水平」形容的四项,实际最多相差 14.2 个百分点。第三堵墙:没有样本量、没有置信区间,67.8% 和 67.9% 之间有没有真实差别无法判断;官方拒绝公开基准给出的理由本身站得住,还被第三方的污染证据部分印证了,这是两件事可以同时为真,不是官方心虚。
这一级要加什么:等权平均掩盖器 + 自助法区间
为什么现在才加它:前十级台阶都在评价一个分数本身靠不靠谱,没有一级问过这个分数是怎么被合成出来的、又是不是稳定到能和另一个分数比大小——这一级要把「拆开权重重新看一眼」和「不知道样本量就不下结论」这两件事,变成两个能在任何评测表上再用一次的部件。
难点:bootstrapCI 每一次内层循环都是「有放回」抽样——Math.floor(Math.random()*n) 允许同一个下标被抽中多次,这一行如果写错成不放回抽样,抽出来的每一批都会退化成原始数据本身,区间宽度会恒为 0,整个函数就失去了意义。reweight 里权重先归一化再相乘,是为了让调用者可以随手传 [1,1,1,1] 或者 [5,1,1,1] 这种没有事先算好比例的权重,不用自己先手算求和。
自己验:reweight([61.7,71.6,61.8,76.0],[1,1,1,1]) 应该输出约 67.775;把权重换成 [5,1,1,1](Invoice 权重明显调高),结果应该跌到 65 附近。bootstrapCI 传入 20 条全部为 1 的记录(全对),不管跑多少次,lo 和 hi 应该都恒为 1——因为有放回抽样抽出来的每一条永远还是 1,这时候区间应该收缩成一个点;换成 200 条里有 136 条为 1 的记录,区间宽度应该明显比只用 20 条里 13.6 条为 1(按比例缩小)时更窄。
第12章 「便宜 400 倍」的分母是谁
官网首页写着两行大字:193.6x Faster,444.6x Cheaper。两个数字并排挂着,字号一样大,颜色一样亮。对谁快 193.6 倍,对谁便宜 444.6 倍?
学完这一章你应该能做到
- 查出 193.6x 和 444.6x 这两个招牌数字各自的基线是谁,说清为什么它们不是对同一个对手说的
- 用官方公布的舍入数字,亲手复算一遍这两个倍数,说清能不能算出完全一致的结果
- 换一个基线重新计算「便宜多少倍」,说清这个数字会塌缩到什么程度
- 区分「每案例成本」和「每次决策成本」,说清为什么两者不能划等号
- 看到任何一条「N 倍」的宣称时,第一时间问出正确的那个问题
这一章要给审计仪加一个倍数与成本模型——把「N 倍」这种宣称拆成分子和分母。前面十一级台阶已经算过不少绝对数字,这一级要处理的是相对数字:一个「倍数」从来不是一个模型自己的属性,它是这个模型和另一个具体对手放在一起,才会生出来的东西。
193.6 倍和 444.6 倍,说的是同一个对手吗
官网首页的两行大字并排放着,193.6x Faster 在左,444.6x Cheaper 在右。看到这两个数字,第一反应是它们在说同一件事——Jev 比某一个对手快 193.6 倍,也比这同一个对手便宜 444.6 倍。这个反应先放一放,去官方博客里查这两个数字各自的出处,再回来看这个反应站不站得住。
官方博客的技术细节部分交代了这两个数字的计算依据。你觉得 193.6x 和 444.6x 用的是同一个对比对象吗?
答完再看
不是——博客正文写得很清楚,两个数字各自锚定了不同的模型。往下把这两个基线找出来,看看找到之后,这两个数字还能不能像挂在首页上那样并排读。
先看能确定的部分:官方总分表里,Jev 是 67.8% 一致率、每案例 0.0004 美元、0.4 秒;同一张表里,sonnet 5 同样是 67.8%,但每案例 0.1174 美元、78.1 秒;opus 5 是 73.1%,每案例 0.1761 美元、37.8 秒。这三行数字,是查这两个招牌倍数时能确定不会算错的起点,先把它们记牢,再去看倍数具体是拿谁除谁。
193.6x 更快,基线是 sonnet 5——把 sonnet 5 的 78.1 秒拿来和 Jev 的 0.4 秒比。排除的第一个念头是「基线就是 opus 5,反正它也慢」:opus 5 的 37.8 秒虽然也比 Jev 慢得多,但博客原文明确把这个倍数系在 sonnet 5 名下,不是 opus 5——这一步排除很关键,因为 opus 5 和 sonnet 5 的一致率不一样(73.1% 对 67.8%),选错基线会连着把「智力相近」这个前提也选错。444.6x 更便宜,基线换成了 opus 5——拿 opus 5 的 0.1761 美元和 Jev 的 0.0004 美元比。
193.6x 更快——基线 sonnet 5
Jev 与 sonnet 5 一致率同为 67.8%,「智力相近」这个前提站得住;对比的是 78.1 秒和 0.4 秒。
444.6x 更便宜——基线 opus 5
opus 5 一致率 73.1%,比 Jev 高出 5.3 个百分点,「智力相近」这个前提这里其实不完全成立;对比的是 0.1761 美元和 0.0004 美元。
差别在:两个倍数分别绑定两个不同的对手,而且连「两边智力相近」这个前提,也只在其中一组里站得住——首页把它们并排放在一起,容易让人以为存在一个被同时碾压的对手,这个对手并不存在。
最怕的一种错,是把这两个基线当成同一个来读,以为存在一个「既贵又慢」的对手同时被两个数字碾压。检查的办法很直接:把 sonnet 5 的价格拿去套 444.6x 这个倍数、把 opus 5 的耗时拿去套 193.6x 这个倍数,两次都会发现套不上——那两组数字根本不是按这个配对算出来的。
193.6x 更快对应哪个模型?444.6x 更便宜又对应哪个模型?
变式:如果有人问「Jev 比 opus 5 快多少倍」,用这张表里的数字,该怎么算,答案和 193.6x 一样吗?
对 sonnet 5 这一个对手,Jev 的成本优势是多少倍?对 opus 5 这一个对手,Jev 的速度优势又是多少倍?(用表里的数字直接算,不用首页的 193.6x、444.6x)
变式:如果只允许选一个对手,同时比较速度和成本两项,选 sonnet 5 还是 opus 5,哪一个能让 Jev 看起来更全面地领先?
这两个招牌数字,自己核对得出来吗
用官方总分表里公布的舍入数字——78.1 秒、0.4 秒、0.1761 美元、0.0004 美元——直接做除法,算出来的结果会不会正好是 193.6 和 444.6?
答完再看
算出来接近,但对不上小数点后那一位。往下看这零点几的差距说明了什么。
78.1÷0.4=195.25,0.1761÷0.0004=440.25——这两个数字,和首页挂着的 193.6、444.6,接近但不相等。原因不难猜:官方总分表上的 78.1 秒、0.1761 美元这些,本身已经是四舍五入过的数字,真实的原始值带着更多位小数,首页那两个招牌倍数,大概率是用没有公开过的原始值算出来的。用公布的舍入值反推,只能得到 195.2 和 440.2 这个量级,精确到小数点后一位的真实原始值,官方没有公布过——这两个挂在首页最显眼位置的数字,读者自己动手,反而是复核不出来的。
发布帖最初的标题
40-400x 更便宜、20-200x 更快——写成一个宽区间,留了余地。
现在挂在首页
193.6x、444.6x——精确到小数点后一位,但算出这份精确所用的原始输入从未公布过。
差别在:区间换成了单点数字,看起来精确度提高了,但这份精确本身没法被读者用公开材料复核——往下看这两个数字还经过了哪些版本。
同一天,官方给出的倍数还不止这一套。博客正文里另有一句:「This can range from 40x-200x faster for the same levels of frontier intelligence for System One shaped queries.」——40 到 200 倍,只讲速度,前面加了一个限定「同等智力水平」和「System One 形状的查询」。HN 用户 WhitneyLand(item 49719001)还指出了另一件事:「The original title before it changed less than an hour ago was: 'Jev: New frontier model 40-400x cheaper and 20-200x faster'. I'm going to agree that was misleading.」——这篇发布帖最初的标题,写的是 40 到 400 倍便宜、20 到 200 倍更快,发布不到一小时就被换成了现在这个更保守的说法。
用 78.1 和 0.4 直接相除,算出来的数字和首页的 193.6 相差多少?
变式:如果官方明天公布了精确到小数点后四位的原始耗时和价格,读者能不能用它们重新复算出一模一样的 193.6 和 444.6?
同一天,关于「Jev 快多少倍、便宜多少倍」,先后出现过三种说法:发布帖最初的标题(40-400x 便宜、20-200x 快)、博客正文(40-200x 快)、后来的首页(193.6x 快、444.6x 便宜)。如果你是第一次接触这条新闻的读者,只看到其中任意一套,会得出什么印象?三套摆在一起看,又会发现什么?
变式:如果三套说法只挑一套写进这一章,应该挑哪一套?为什么挑另外两套会不完整?
换一个基线,这个倍数会塌缩成什么样
拿了早期访问权限的 Good Start Labs,自己测了一遍 Jev 和几个模型的成本,参照的一致率标准换成了 Claude Fable 5.1。如果拿这份独立数据里最贵的模型当基线,算出来的倍数会不会还接近首页的 444.6x?
答完再看
换算不出——下面把这份独立数据摆出来,亲手算一遍能得到多少。
Good Start Labs 这份测试,价格用的是每百万条的标价:Claude Fable 5.1 三万三千美元、Gemini 3.8 Flash 一千六百美元、GPT-5.6 Luna 四百美元、DeepSeek V4.1 Flash(开源)二百六十美元、Jev 一百六十美元。这批数字和官方总分表用的「每案例美元」是两套完全不同的单位、来自两次完全不同的测试,不能把这边的 160 和那边的 0.0004 混在一起算——这一节接下来的每一个倍数,都只在这份 Good Start Labs 自己的表内部计算。
| 方案 | 与 Claude Fable 5.1 的一致率 | 成本/百万条 |
|---|---|---|
| Claude Fable 5.1(参照) | — | $33,000 |
| Gemini 3.8 Flash | — | $1,600 |
| GPT-5.6 Luna | — | $400 |
| DeepSeek V4.1 Flash(开源) | 93.5% | $260 |
| Jev | 91.5% | $160 |
自己推一遍:同一个 Jev 价格,为什么能同时对应两个天差地别的倍数
拿这张表里最贵的 Claude Fable 5.1($33,000)当基线,Jev 的成本优势是多少倍?
想好了再看
33000÷160≈206.25,约 206 倍——比首页的 444.6x 小了一半还多,即使选的已经是这张表里最贵的对手。
如果换成 DeepSeek V4.1 Flash($260,开源、且一致率比 Jev 更高)当基线,倍数又是多少?
想好了再看
260÷160=1.625,约 1.6 倍——和上一步的 206 倍相比,只挑了一个不同的基线,倍数就塌缩到不到百分之一。
这两步算出的 206 倍和 1.6 倍,用的是不是同一个 Jev 价格($160)?变化的是什么?
想好了再看
是同一个 $160,分子(Jev 的价格)从头到尾没有变过,唯一变化的是分母——选了哪个模型当对比对象。「便宜多少倍」这句话,从数学上看只是「分母÷分子」,分子不变时,这个数字完全由分母的选择决定,分母越贵,倍数看起来越大,这和 Jev 本身有没有变得更便宜没有任何关系。
首页的 444.6x 和这里推出的 206 倍、1.6 倍,是不是同一套算法算出来的?它们能不能被放进同一张表比较?
想好了再看
不是同一套。444.6x 来自官方总分表($0.1761 对 $0.0004,单位是每案例),这里的 206 倍和 1.6 倍来自 Good Start Labs 的独立测试(单位是每百万条)——两套数字连单位都不一样,不能直接放进同一张表比大小,只能各自在自己的体系内部推导倍数会怎样随基线变化,这正是这道推导题真正想说明的:「倍数」从来不是一个只属于 Jev 的固定属性,它是「分子」和「分母」两者共同决定的关系。
选最贵的对手当基线——Claude Fable 5.1
$33,000 ÷ $160 ≈ 206 倍,已经是这张表里能选到的最大倍数。
选一个更理性的开源基线——DeepSeek V4.1 Flash
$260 ÷ $160 ≈ 1.6 倍,而且这个基线的一致率(93.5%)还比 Jev(91.5%)更高。
差别在:分子(Jev 的 $160)从头到尾没变,变的只是分母选了谁——「便宜多少倍」这个数字,说到底是分母的选择权在谁手里,不是 Jev 自己变便宜了多少。
DeepSeek V4.1 Flash 比 Jev 贵($260 对 $160),但一致率也更高(93.5% 对 91.5%)。如果只用「便宜多少倍」这一个指标来推荐方案,会漏掉哪个维度的信息?
变式:如果一致率的差距从 2 个百分点拉大到 20 个百分点,「1.6 倍便宜」这句话还值得优先考虑吗?
答辩:如果我是审稿人
Good Start Labs 的成本数字都是按官网标价乘以用量推算出来的,不是真实账单——用一份估算数据去戳穿首页的招牌数字,这个反驳本身站得住吗?
参考防守(先自己组织语言再看)
这个质疑成立,材料确实没有给出任何一方的真实账单,官方首页的 444.6x 本身同样没有账单支撑,只是总分表上两个舍入价格相除。双方站在同一条起跑线上:都是按公开标价推算,没有一方比另一方更「真实」。这份反驳真正有力的地方,不在于它比官方数字更精确,而在于它是一次完全独立的测试,用了不一样的任务、不一样的对照组,却依然只能算出 206 倍这个量级作为上限——如果连最贵的对手都够不到 444.6x,这个数字站得住的空间就更小了。
省钱到底省在了哪一头
Jev 的输出不计费,一次请求里多塞几个问题,官方说几乎不加钱。按这个说法,实际部署时,Jev 花掉的 token 数量,会不会普遍比同类任务里的其他模型更少?
答完再看
不一定——第三方 Near Here 的实测记录了一个和直觉相反的结果,往下看具体数字。
官方 cookbook 页面鼓励一次请求里塞尽量多的问题:「Adding questions barely changes the response time」「Asking a question you might not need is close to free.」这套说法有真实依据——官方一份 semantic_find cookbook 里,一次 Choice 请求塞进了 218 个选项(对应 218 行候选文本),一次性打完,没有分批。输出免费、多问几乎不加钱,这两条叠在一起,成本结构和普通 LLM 是反过来的:LLM 是「多生成一个字就多花一份钱」,Jev 是「问多少都差不多这个价,只有输入那部分要花钱」。
直觉:输出免费+鼓励多问=用量更省
成本结构反过来了,按这个逻辑,Jev 处理同一个任务,花掉的 token 总量应该比别家更少。
Near Here 实测:输入 token 反而最多
21,528 对 15,372 和 15,503——同一个任务,Jev 用掉的输入 token 比另外两家都多,最终便宜完全是单价和免费输出撑起来的。
差别在:「成本结构对模型有利」和「这个模型用起来更省」是两件不同的事——前者是价目表的形状,后者要看实际跑一遍任务花了多少 token,往下看具体数字。
但省钱最终要看总账单,总账单里输入这一头同样要算钱。第三方 Near Here 测过 50 条活动列表审核任务,Jev 的一致率和速度都赢了对照组,可是输入 token 数量反而是三者里最多的:Jev 21,528 个,Gemini 3.5 Flash-Lite 15,372 个,Mistral Small 4 15,503 个。Jev 最终每千次决策只要 0.043 美元,远低于 Gemini 的 2.496 美元和 Mistral 的 0.370 美元——赢的不是「用得省」,是「单价低、输出免费」这两条撑起来的。
Near Here 的实测里,Jev 的输入 token 数量比另外两个模型都多,但总成本依然是三者里最低的。用一句话说清这是怎么做到的。
变式:如果 Jev 的输入单价和 Gemini 一样贵,这次测试里 Jev 的总成本还会是最低的吗?
Jev 在 Near Here 这次测试里输入 token 反而最多,结合这一章前面讲过的 Jev API 设计(一次请求可以塞很多个问题,questions 之间互不共享推理过程),猜一个合理的原因,说明为什么会这样。
变式:如果要验证这个猜测,需要 Near Here 补充公开哪部分数据?
每案例的价格,是每次决定的价格吗
官方总分表写着「每案例 0.0004 美元」,很容易被随手转述成「每次决策只要 0.0004 美元」——这两句话字面上很像,但指的不是同一个单位。一个 case(案例)往往包含好几个 question(问题),比如 Customer Service 这类 workflow,一次案例可能同时问「顾客想要什么」「情绪是否激烈」「要不要升级给人工」好几个问题,0.0004 美元是这一整个案例的总花费,不是其中某一个具体判断单独的花费。按这个结构推,每一次具体决策的真实成本,只会低于 0.0004 美元,不会等于它。
一个案例包含 5 个问题,这个案例的总成本是 0.0004 美元。如果把成本平均分摊到每个问题上,每个问题大约花费多少?这个数字和「每案例 0.0004 美元」是同一个东西吗?
变式:如果一个案例只包含 1 个问题,「每案例成本」和「每次决策成本」这时候还有区别吗?
下面这句话哪里用错了口径:「Jev 每做一次决策只要 0.0004 美元,一天处理十万次决策,总成本 40 美元。」
变式:把这句话改写成一句口径正确的说法,应该怎么写?
第8章的级联成本公式——costJ + (1−c)·cost大——里,Jev 那一项直接用的是 0.0004 美元,且公式规定每处理一个案例都要加这一份,不会因为覆盖率 c 变化而打折。结合这一章「0.0004 美元是每案例价格,不是每次决策价格」这条结论,第8章那条公式算出来的,到底是每案例成本还是每次决策成本?这条公式本身有没有踩中这一章讲的坑?
变式:如果第8章的级联路由器改成按「问题」而不是按「案例」升级——每个问题各自判断要不要升级——级联成本公式还能直接沿用 0.0004 美元这个数字吗?
读的时候要小心
这一章推出的倍数,同样不能脱离各自的基线单独引用
本站可算的那几个数字——约 293 倍、约 94 倍、约 206 倍、约 1.6 倍——每一个都只在这一章交代过的具体对比条件下成立,换一批任务、换一批模型、换一天的定价,这些数字都会跟着变。把它们当成 Jev 的固定属性单独摘出来引用,会重犯这一章从头到尾都在批评的那个错误。
留给你的问题
下一次你看到一条「比某某快 N 倍」或者「比某某便宜 N 倍」的宣称时,如果只能追问一句话,你会问什么?这句话问出来之后,还需要再追问第二句吗?
不看材料,写下这一章的三堵墙
第一堵墙:首页并排放着的 193.6x 和 444.6x,分别绑定 sonnet 5 和 opus 5 两个不同的对手,对同一个对手,真实优势只有约 293 倍或约 94 倍;用公布的舍入值只能复算出 195.2 和 440.2,精确原始值官方从未公布,官方同一天还给过至少两套更保守的口径。第二堵墙:对着独立测试里最贵的对手,倍数最多塌缩到约 206 倍;对着一个更理性的开源基线,只剩约 1.6 倍,而且那个基线的一致率还更高。第三堵墙:输出免费、多问几乎不加钱,这套成本结构对 Jev 有利,但不保证实际用量更省,第三方实测里 Jev 的输入 token 反而是最多的;而且「每案例成本」和「每次决策成本」是两个不同的数字,混用会把账算错。
这一级要加什么:倍数与成本模型
为什么现在才加它:前十一级台阶算的都是某个模型自己的绝对指标——一致率、成本、延迟、置信区间,没有一级处理过「倍数」这种天生依赖对比对象的相对指标。这一级要把「分子固定、分母可换」这件事变成一个可以套进任何一条营销宣称的计算器。
这一步的难点不在写代码,在传参——ratio() 本身不检查 target 和 baselines 里的数字是不是来自同一套测试、同一套单位。前面几节反复出现的教训是:官方总分表的「每案例美元」和 Good Start Labs 的「每百万条美元」是两套不同的单位,混着传进同一次调用,函数照样会老老实实吐出一个数字,只是这个数字不再对应任何真实存在的对比。ratio() 能做的只是把除法做对,分子分母是不是来自同一套体系,得由调用它的人自己把关。
自己验:target={cost:0.0004, latency:0.4}(对应 Jev),baselines 数组按顺序放两条——第一条 {cost:0.1174, latency:78.1}(对应 sonnet5),第二条 {cost:0.1761, latency:37.8}(对应 opus5)。跑一遍 ratio(target, baselines),第一项的 costMultiple 应该约等于 293.5,第二项的 speedMultiple 应该约等于 94.5——这两个数字应该正好对上这一章前面亲手算过的「对同一个对手的真实优势」。再验一个边界情况:把 target 自己也当成一条 baseline 传进去,算出来这一项的 costMultiple 和 speedMultiple 应该都正好是 1——自己和自己比,任何倍数都应该塌缩成 1。
第13章 255 和 32k:两堵硬墙
给一千个商品类目建一个分类器,你打开 Choice 的选项列表,一个一个往里加。加到第 255 个的时候,请求直接被拒绝——这不是配额没充够,是这道题的形状本身容不下第 256 个选项。再往前一步:就算选项数过了关,你把一整篇很长的客服历史塞进 state,本该更懂上下文的模型,判断反而开始跑偏。这一章要走的,就是这两堵墙。
学完这一章你应该能做到
- 说清楚 Choice 的 255 选项上限从哪来,以及超过它之后官方建议的做法是什么
- 亲手推出「分层判断的联合准确率=各步准确率之积」,并算出任意步数的结果
- 看到一份评测报告里的两步分类流程,指出它跟单步流程做对比时哪里不公平
- 面对官方文档里三个互相打架的上下文预算数字,给出一个工程上站得住的设计取值
- 解释「输入便宜、输出免费」和「往 state 里塞得越多越好」为什么是两回事
这一级要给审计仪加两个检查口:一个算分层判断会把准确率吃掉多少,一个算这次请求的 token 预算还剩多少空间。前面几级只管一次判断准不准、值不值;这一级要回答的是,当题目本身塞不进一次请求的时候,你还能不能继续相信算出来的数字。
选项超过 255 个,只能硬塞吗?
假设你在给一个电商平台做客服工单分类,后台有大约一千个细分商品类目——从「蓝牙耳机」到「儿童雨鞋」到「宠物窝垫」。第3章你已经知道,Choice 的 criteria 就是一张「选项→描述」的表,选项本身就是这张表的 key。最直接的想法是:把一千个类目原样写进这张表,一次问完。
先看这条路会撞在哪儿。我先看到的是这道题要处理的候选项数量——大约一千,远超 Choice 能接受的选项数。我排除的是「分批发几次、每次凑够 255 个选项碰运气」这种做法,因为每一批里真正命中的类目大概率不在这一批候选里,模型只能矬子里拔将军,选一个不那么离谱的错误答案。真正的原因是这道题的形状本身就不允许:官方文档写得很直接,一道 Choice 题最多只能接受 255 个选项,多一个都不行。最怕的错是没意识到这是一堵硬墙,以为选项数只是「建议不要太多」,等生产环境里类目一多就直接被拒。检查的办法很简单:数一下候选项,只要超过 255,这条路就已经走不通,不用再往下试。
一道 Choice 题的 criteria 里写了 260 个「选项→描述」的键值对,其余字段都合法。这个请求会成功吗?
变式:如果把这 260 个选项拆成两道各 130 个选项的 Choice 题,放进同一次请求里,这样合法吗?这跟「一道题超过 255 个选项」是不是同一类限制?
官方给出的办法是把一次性的选择拆成好几层:先用一道选项数不多的 Choice,把一千个类目分到十几个大类里;选中大类之后,再用第二道 Choice,在这个大类内部的几十到上百个细类目里选一个。这样两道题各自的选项数都轻松压在 255 以内,一千个类目也能被覆盖到。这个做法官方称作按层级把 Choice 问题串起来,一层一层做。
如果类目数从一千涨到一万,两层分层(先选大类、再选细类)还够用吗?需要满足什么条件?
变式:如果细类目数量本身就分布不均,有的大类下只有 5 个细类,有的大类下有 800 个细类,两层分层还够用吗?
一次性把 1000 个类目塞进一道 Choice
请求直接被拒绝——不是「大部分成功、偶尔失败」,255 是一道硬上限,多一个选项都不行。
分两层,每层都压在 255 以内
大类层十几个选项,细类层每层几十到上百个选项,两层各自都在硬上限之内,两次请求都能被正常处理。
差别在:选项数有没有压在 255 这条线以内,是请求能不能被接受的问题,不是「设计得够不够聪明」的问题——先看这条线,再谈怎么分层。
两步接起来,准确率是加还是乘?
假设分层方案里,第一步(选大类)单独测出来的准确率是 0.95,第二步(在选中的大类里选细类)单独测出来的准确率是 0.90。两步接起来,整条流水线「一千个类目里选对了正确那一个」的准确率,你会怎么估?
答完再看
「整条流水线选对了」这件事,要求两步都对——大类选对,细类也选对,只要有一步错,最终答案就是错的。这是两个条件同时成立的联合事件,不是两个独立分数的平均,也不是只看第一步。正文接下来把这件事拆开算给你看。
把「两步都要对」这句话写成算式:如果第一步的准确率是 a1、第二步在「第一步已经选对」这个前提下的准确率是 a2,两步都对的概率就是两者相乘。
| 符号 | 是什么 | 直觉 |
|---|---|---|
| a1 | 第一步单独的准确率 | 大类选对的把握 |
| a2 | 第二步的准确率(前提是第一步已经选对) | 细类选对的把握 |
| a联合 | 两步全部走对的概率 | 用户实际拿到正确答案的概率 |
代入前面的例子:0.95×0.90=0.855。两步各自看起来都不错,接起来却只剩 85.5%——比任何一步单独的分数都低,这不是算错了,是「两件事都要发生」这个要求本身,天然会比只要求一件事发生更难达到。
只看第一步:0.95
大类选对的概率不低,如果只关心「大类有没有分对」,这个数字看着很安心。
用户真正拿到的:0.855
用户不关心大类分没分对,只关心最终给的那个细类目对不对——这才是两步都要成立的联合事件,0.855 才是用户体感到的真实准确率。
差别在:单独看某一步的分数容易让人心里踏实,但只要流水线有不止一步,真正兑现到用户手上的,永远是各步准确率的乘积,不是其中最好看的那一个。
如果把第二步的准确率从 0.90 提高到 0.95(第一步不变,仍是 0.95),联合准确率会变成多少?
变式:如果目标是让联合准确率达到 0.90,而且两步的准确率必须相等,每一步至少要做到多少?
自己推一遍:链条不止两步的时候
如果分层不是两层,是三层(比如先选大区域、再选大类、最后选细类),每层的准确率分别是 a1、a2、a3,「三层全部走对」要怎么从两步的公式推广?
想好了再看
「三层全部走对」还是要求每一层都不出错,跟两层时的道理完全一样,只是多乘一项:a联合 = a1 × a2 × a3。每多一层,就多乘一个不超过 1 的数,结果只会更小,不会更大。
如果链条有 k 层,每层的准确率都设成同一个数 a(方便估算),联合准确率该怎么写?
想好了再看
a联合 = ak——a 自乘 k 次。哪怕 a 高达 0.95,只要 k 足够大,ak 也会被拉得很低:k=5 时是 0.955≈0.774,k=10 时是 0.9510≈0.599。
这跟第1章「Choice 里的概率互相绑定,加起来必须是 1」是不是同一件事?如果不是,差别在哪?
想好了再看
不是同一件事。第1章说的是同一道题内部,各选项概率的和必须凑成 1——那是一次判断内部的规矩。这里说的是好几次独立判断串起来,每一次判断各自对错的概率相乘——那是跨越多次判断的规矩,管的是链条整体的可靠度,不是任何一次判断内部的概率是否合法。
有人主张「层级分类肯定比一次性硬塞 1000 个选项更准,因为每一步选项少,模型更不容易犯糊涂」。构造一个具体的数字场景,说明这句话不总是对的。
变式:如果两步分层里,第一步的准确率能做到接近 1(比如大类特征特别明显,几乎不会分错组),层级分类还会比单步差吗?
Banking77 就是一个把这件事摆在明处的真实案例——这是一份第三方评测里的客服意图分类任务,一共 77 个类目,本身远低于 255,理论上完全可以塞进一道 Choice 题里一次问完。但测试 Jev 的时候,走的是先分到 11 个手工划出来的大类、再在大类内部选具体意图这条两步路线,跟其他基线模型「一次性在全部 77 个类目里选」不是同一套流程。这份评测自己也指出了这一点不公平的地方:「Banking77 is not like-for-like: Jev answers in two steps (group, then label); the others score all 77 labels at once. The 11 groups are hand-made.」——11 个分组是评测作者手工划的,这份额外的人工分组工作,本身就是第13-1节讲过的、层级方案要多付出的那部分代价,而且其他基线模型完全不需要付。
这份评测报告 Jev 在 Banking77 上的准确率是 0.712,同一张表里 DeBERTa-c 零样本是 0.579。只看这两个数字,能不能直接说「Jev 比 DeBERTa-c 更适合处理 77 类这种大选项数任务」?
变式:如果让 DeBERTa-c 也走同样的两步流程(用同一套人工分组先选组再选细类),这时候两个数字还能直接比吗?
更值得留意的是,Banking77 恰好是第5章那张 ECE 表里,Jev 校准表现最差、也是唯一明显输给基线的一处——ECE 0.208,基线只有 0.081,差了一大截。一个本来选项数就不算多、却依然选择走两步流程的任务,同时又是校准最差的那一个,这两件事摆在一起看,比单独看任何一个都更说明问题:255 这堵硬墙自己不会主动告诉你选项数「安全」的上限在哪,它只保证 256 个选项会被直接拒绝,不保证 77 个选项就一定轻松。
答辩:如果我是审稿人
式 13-1 把联合准确率写成两步相乘,隐含了一个假设:第二步的 0.90 是在「第一步已经选对」这个前提下测出来的条件准确率。如果实际测试时,第二步的 0.90 其实是不分青红皂白、在所有案例(含第一步已经选错的那些)上测出来的,这两个数还能直接相乘吗?
参考防守(先自己组织语言再看)
不能直接相乘,这条质疑站得住。如果第二步的准确率是在混合了「第一步对」和「第一步错」的全部案例上测出来的,那它已经把一部分注定答错的案例算进了分母,这个数字本身的含义就和式 13-1 需要的「条件准确率」不一样,直接相乘会得到一个说不清楚含义的数。想要式 13-1 成立,报告第二步准确率的人必须说清楚这个数字是只在第一步选对的那部分案例上测的,还是在全部案例上测的——这正是一份严谨的分层评测报告必须交代、却很容易被略过的一句话。
官方自己给的三个上下文预算,该信哪个?
选项数不是唯一的容量限制。一次请求里,state 加上所有 questions 共享同一个 token 预算,这个预算到底是多少,官方自己给出了三个不一样的数字。
| 出处 | 说法 |
|---|---|
| docs.typesafe.ai/models | 64k tokens per request;32k tokens for state plus the longest question |
| docs.typesafe.ai/primitives | The budget is around 32,000 tokens(指整个请求的预算) |
| Cloudflare 模型页 | Context Window:32,000 tokens |
这三处是【一手·官方】内部不一致:models 页说的是「总预算 64k,其中 state 加最长的那道题不超过 32k」;primitives 页说的是「整个请求的预算约 32k」;Cloudflare 的模型页干脆只写「上下文窗口 32,000 tokens」。三处都出自官方或者官方授权的渠道,谁也没有被谁纠正过,写到今天为止依然并存。
这三处说法里,明确把预算写成「32k 左右」的有几处,写成「64k」的又有几处?
变式:如果之后又出现第四处官方说法,写的是「48k」,这会不会推翻「保守按 32k 设计」这个结论?
先把这件事当成一道判断题认真走一遍。我先看到的是三个数字里有两个都指向 32k,只有一处提到 64k,而且那处 64k 说的是「总预算」,同时又划出一个 32k 的子预算给 state 加最长的问题。我排除的是「挑一个看着最大方的数字信」,因为一旦真实限制其实是 32k,用 64k 去设计的请求会在生产环境里随机失败,而且失败得没有规律——有时候某次请求侥幸压线通过,换一批数据又被拒。真正该走的路是按最保守、也就是最小的那个数字设计:32k。最怕的错是把「大约 32k」这种模糊表述,当成「肯定不会少于 32k」,两者不是一回事——「大约」既可能偏多也可能偏少。检查的办法是给自己的系统留出余量:提前设一个更低的软上限、留出安全区间,不要让正常请求的 token 数逼近 32k 这条线。
如果你的系统要处理的 state 经常在 30,000 到 34,000 token 之间波动,按这一节的保守结论,这套系统现在处于什么状态?
变式:如果只看 models 页那条「64k 总预算,32k 是 state 加最长问题」,这套系统还危险吗?如果只看这一条来设计,会漏掉什么风险?
这堵墙也带出一个更值得记住的教训:一份连自己上下文长度都说不清楚的文档,不等于什么数都拿不走。三处口径虽然互相矛盾,但共同点很稳固——没有一处说预算会超过 64k,也没有一处说会低于 32k,这个区间本身就是一个可以拿去设计的边界,工程结论「按 32k 设计」正是从这三处的交集里读出来的,不是凭空选了一个数字将就。
除了「保守按 32k 设计」,这三条互相矛盾的说法里,还有没有哪句话是三处都没有反对、可以放心当成事实来用的?
变式:如果之后 Cloudflare 页悄悄把数字改成了 64,000,这算不算解决了这处矛盾?为什么还需要回去检查另外两处官方文档?
反正输入便宜、输出免费,能不能什么都往 state 里塞?
输入每百万 token 只要几分钱,输出完全免费——既然钱不是问题,把跟当前判断完全无关的历史记录、别的客户的工单也一起塞进同一个 state,会不会让判断更准(起码不会更差)?
答完再看
官方自己在局限说明页里明确写了这件事会发生,而且专门给它起了名字。正文接下来把原话摆出来。
官方局限说明页第五条原话:「Accuracy falls as the state grows with content unrelated to the decision.」——state 越长,只要多出来的那部分内容跟当前要判断的事无关,准确率就会跟着下降。页面结尾还专门提醒了一句:「Jev suffers from context rot, so unrelated material in the state costs you accuracy.」无关内容不是被干净地过滤掉,它会像噪音一样拖累模型的判断,这个现象有个名字,叫上下文腐化(context rot)。
只塞和这次判断相关的内容
state 里只有当前这张工单,模型的注意力全部用在真正要判断的信息上。
顺手把无关历史也塞进去
state 里混进了别的客户的工单、跟这次判断无关的历史记录,钱几乎没多花,但这部分内容成了干扰项,拖累判断的准确率。
差别在:token 账单只关心 state 有多长,不关心里面的内容跟当前判断有没有关系;但模型的判断关心的恰恰是内容跟不跟这次决策相关,这是两套完全不同的计价方式,账单便宜不代表判断也跟着便宜。
「context rot」这个词具体指的是哪件事:是 token 账单会因为 state 变长而涨价,还是准确率会因为 state 里混入无关内容而下降?
变式:如果 state 变长了,但新增加的内容全部跟当前判断直接相关,这还算 context rot 吗?
你要设计一个从 900 个商品类目里选一个的分类请求,历史客服记录很长,共约 40,000 token。结合这一章两堵墙的结论,你会怎么设计这次请求?
变式:如果 900 个类目本身分布严重不均,有一个大类下面塞了 260 个细类,前面这套两层方案还够用吗?
对你而言未知32,000 token 的中文预算,实际能装下多少个汉字
官方 primitives 页给的换算是「大约 32,000 tokens,roughly 150,000 characters of English text」——这是针对英文文本给出的字符数换算,中文的分词方式和英文差别很大,同样数量的 token 通常装不下等比例换算出来的汉字数。到目前为止,没有材料给出过针对中文文本的官方或第三方换算数字,Jev 自己的分词器细节也没有公开。这不是学界没有答案的开放问题,答案是可以估算出来的,只是这份材料里没有人做过这件事。
先做这一步:拿一段较长的中文客服工单文本,用任意一个公开的通用分词器(哪怕不是 Jev 真正用的那个,只作为近似)数一数大概多少个汉字对应一个 token,再用这个比例反推 32,000 token 大概能装下多少个汉字,和官方给出的 15 万英文字符做个对比,看看这条保守预算线对中文用户来说,实际空间是更宽松还是更紧张。
读的时候要小心
13-2 节那组 0.95/0.90,是示范用的假设数字
本节推导联合准确率时用的 0.95 和 0.90,是为了把式 13-1 讲清楚而设的示范数字,不是从 Banking77 那份评测里量出来的两步分解数据——那份评测公开的是 Jev 在 Banking77 上整体 0.712 的准确率和 0.208 的 ECE,没有单独拆出「选大类」和「选细类」这两步各自的准确率。另外,Banking77 两步分类、11 个大类由评测作者手工划分,材料没有说明这是不是完全照搬了官方对超过 255 选项场景的推荐做法,还是评测作者自己的方法选择——这一点值得在引用这份评测时说清楚,不要含糊带过。
留给你的问题
如果有人拿着一份「Jev 在 900 个类目上准确率高达 91%」的报告来找你,你会先问哪一句话,才能判断这个 91% 是不是被这一章讲过的某堵墙悄悄打了折扣,或者悄悄占了便宜?
不看材料,写下这一章的三堵墙
Choice 选项数超过 255 是一道硬性拒绝的墙,官方给的办法是分层链式提问,但分层不是免费的:联合准确率是各步准确率相乘,不是相加也不是取最好那一步,层数越多,哪怕每步都很准,联合起来也会被结构性地拉低。上下文预算这堵墙没有硬拒绝的边界,官方自己给出的三个数字互相打架(64k/32k/32k),工程上只能按最保守的 32k 设计,但三处矛盾的说法之间仍有一句没人反对的共识可以拿来用。第三堵墙是价格结构骗不了准确率:输入便宜、输出免费只影响账单,state 里混进跟当前判断无关的内容依然会拖累准确率,这是 context rot,跟钱没有关系。
这一级要加什么:层级误差传播器和预算检查器
为什么现在才加它:前十二级默认一次判断只有一步、请求也总能塞得下——从这一级开始,审计仪要能处理「一件事拆成好几步问」和「内容太长塞不下」这两种前面从没遇到过的情况,缺了这一级,遇到超过 255 个候选项或者超过 32k token 的真实场景,前面所有级别算出来的数字都没有落脚的地方。
难点:chainAccuracy 只在每一步的准确率都是「前一步已经选对」这个前提下的条件准确率时才成立——如果传进来的某一步准确率其实是在混合了对错案例的全体上测出来的,这个函数会安静地算出一个含义不清楚的数,不会报错提醒你数据口径不对,这正是本章答辩那一节揭出来的漏洞,写代码时容易忘掉。
自己验:chainAccuracy([0.95, 0.90]) 应该输出 0.855;chainAccuracy([0.95, 0.90, 1])(多接一步准确率为 1 的环节)应该还是 0.855,不会变化,因为乘以 1 不改变结果。budgetCheck(28000, 3000, 30000) 里 state 加问题共 31000,超过 30000 这条软上限,应该给出 overBudget:true, margin:-1000;budgetCheck(20000, 3000, 30000) 共 23000,低于上限,应该给出 overBudget:false, margin:7000。needsChaining(255) 应该是 false,needsChaining(256) 应该是 true——255 本身仍然合法,256 才是第一个被拒绝的数字。
第14章 问题之间互相看不见
一次请求里塞十几道题,价格几乎不涨,服务器几乎不多花时间——第13章那堵 255 选项的墙,看起来只要不越界,多问几道题根本不是事。可真到构建一套要先判断类别、再根据类别做下一步判断的流程时,明明每一步都很快,整条链却慢得不成比例。问题不在于问得多,问题在于问得对不对。
学完这一章你应该能做到
- 说清楚一次请求里能塞多少道题,实际受什么约束,官方鼓励多问的理由是什么
- 区分「一道 Choice 题的候选项数」和「一次请求里的问题条数」,不把两件事混为一谈
- 判断两个判断之间有没有依赖关系,并说清有依赖时为什么必须拆成多次请求
- 亲手推出串行链条的延迟模型,算出多长的链条会反过来比一次大模型调用还慢
- 解释为什么把流水线里的一个环节换成快得多的 Jev,整条流水线不会跟着同样倍数变快
这一级要给审计仪加一个延迟计算器:给定一串判断之间谁依赖谁,算出这条链跑完总共要多久,以及要跑多少次独立请求。前面几级只关心单次判断准不准、值不值;这一级第一次让审计仪去面对「好几个判断接在一起」这件事本身带来的结构性代价。
一次请求塞很多问题,答案会变慢吗?
第3章你已经知道,questions 是一张 map,想问几个问题就往里塞几条。这里有一个容易想当然的猜测:题目越多,服务器要算的东西越多,回得肯定越慢。先把这条猜测认真检验一遍。
我先看到的是官方文档对这件事的明确表态:「Adding questions barely changes the response time」,加问题几乎不影响响应时间,紧接着还有更直接的一句——「Asking a question you might not need is close to free.」问一个可能用不上的问题,几乎不花钱。我排除的是「问题数肯定有一个类似 255 那样的硬顶」这个猜测,因为官方原文说得很清楚:一次请求里问题条数没有固定上限,唯一的约束是 state 和所有问题共享的那个 token 预算——也就是第13章刚讲过的那堵上下文墙,不是一堵新的墙。真正该走的路是把能一起问的问题都塞进同一次请求,而不是省着问、来回发好几次请求。最怕的错是把这条「多问不加钱」的结论,不加区分地套用到所有场景——下一节就会看到它在哪里失效。检查的办法是看官方自己给出的实测数据,而不是停在一句口号上。
一次请求的 questions 里放了 40 条问题,这个数字本身会不会导致请求被拒绝?
变式:如果这 40 条问题里,有一道 Choice 题带了 300 个候选项,这次请求会不会失败?失败的原因是哪一堵墙?
官方给过一次实测:拿一段大约 54,000 字符的 GDPR 维基页面当 state,一次性问 13 道题(8 道 Noul、2 道 Choice、3 道 Score),跟把这 13 道题拆成 13 次单独请求相比。官方 cookbook 页面摘要写的是「batching every question into one TypeSafe call is 12.2x cheaper and 10.0x faster」,但同一份 cookbook 的正文里写的是「batching 13 questions into one call is 11.5x cheaper and 9.6x faster than 13 separate calls, with no change in the answers」——12.2/10.0 和 11.5/9.6,同一份文档给了两组不同的数字,没有说明是不是两次不同时间跑出来的结果。两处都摆在这里,不挑一个信。
面对官方文档里这两组不一致的倍数(12.2x/10.0x 和 11.5x/9.6x),你会在这一章后面用哪一组数字,为什么?
变式:这两组数字不一致,会不会动摇「批量问不改答案」这个结论本身?为什么这是两件独立的事?
比数字更重要的是这份 cookbook 另一条实测结论:同一批问题分别用「合并成一次请求」和「拆成多次请求」两种方式各跑 5 遍,比较答案的标准差——「Most answers came back identical across all 5 repeats either way, the same value on every call, std dev exactly 0.0」,「batching adds none」。合并请求省下来的是重复发送同一份 state 的成本和往返次数,不会改变任何一道题的答案。
把 13 道题合并成一次请求发送,和拆成 13 次单独请求分别发送,这两种方式算出来的答案会不会不一样?
变式:如果拆成 13 次请求时,state 每次都传的是同一份,跟合并请求相比,13 次请求总共要多花多少份「重复发送 state」的成本?
「一次请求最多能塞多少道题」和「一道 Choice 题最多能给多少个候选项」是两件事,容易被混在一起说。官方 cookbook 库里出现过 218 这个数字,但那是 semantic_find 这份 cookbook 里,一道 Choice 题内部给出的候选行数——218 行文本全部作为这一道题的选项,让模型从中选出语义最匹配的那一行,本质上是第13章讲过的那堵 255 选项墙,只是还没顶到上限。182 也是同样性质,来自另一份排序技能的 cookbook,是同一道题里的候选个数,不是问题条数。这一节要讲的「问题条数不设硬顶」,和第13章的「选项数硬顶 255」,各自守着各自的墙,别把两个数字的出处认错。
semantic_find 这份 cookbook 里的 218,指的是一次请求里有 218 道独立的问题,还是一道 Choice 题里有 218 个候选选项?
变式:如果要在同一次请求里,既对这 218 行文本做语义匹配选择,又同时问「这份文档的语气是不是正式」这种额外判断,这算不算给这次请求多加了一道问题?
一次请求里的问题条数
没有固定上限,官方鼓励多问,唯一约束是 state 和全部问题共享的 token 预算。
一道 Choice 题里的候选项数
有硬顶,最多 255 个,218、182 这些数字说的都是这一层限制。
差别在:这是两个完全不同维度的限制,一个数的是这次请求里有几道题,一个数的是某一道题自己给了几个候选——在其中一个维度上「不设限」的经验,不能拿到另一个维度上用。
第二个问题,能看到第一个问题的答案吗?
同一次请求里问了两个问题:第一题判断这张工单该转给哪个部门;第二题的 instructions 写的是「如果这张工单被转给技术部,判断它算不算紧急 bug」。这两题在同一次请求、同一个 state 下评估,第二题能不能读到第一题实际判给了哪个部门?
答完再看
「共享同一个 state」说的是两题看到的原始材料一样,不是说它们能看到彼此的判断过程或结果。第二题里那句「如果被转给技术部」,模型不会真的先去查第一题判没判给技术部,它只能按 state 本身的内容,自己重新判断一遍「像不像该转给技术部」。正文接下来把官方原话摆出来。
官方文档 docs.typesafe.ai/concepts/state 原话:「All questions see the same state and are evaluated independently.」所有问题看到的是同一份 state,但各自独立评估。一份参考资料把这句话翻译得更直白:一个问题的答案,不会偷偷变成另一个问题的上下文。
没有依赖关系:判断语气 + 判断紧急程度
「这条消息的语气是不是愤怒」和「这件事是不是紧急」,两题各自只需要读原始 state,互相不需要对方的答案,可以放进同一次请求一起问。
有依赖关系:先分类、再按类别追问
「这张工单该转给哪个部门」和「如果转给技术部,算不算紧急 bug」,第二题的判断前提是已经知道第一题的答案——但第二题看到的只有原始 state,看不到第一题真正给出的部门,这两题不能指望在同一次请求里对上。
差别在:判断需不需要用到另一个判断的结果,而不是这两个判断听起来像不像「有关系」——语气和紧急程度也可能相关,但都不需要读对方的答案,照样能一次问完。
从这里能提炼出一条规则:没有依赖关系的判断,不管有几个,都可以塞进同一次请求一起问,几乎不加钱也几乎不加时间;一旦某个判断的输入里需要用到另一个判断的真实结果,这两个判断就必须拆成先后两次请求,第二次请求的 state 或者 questions 里,要由你的代码把第一次的答案手动填进去。
「这条评论是不是负面」和「如果是负面评论,判断具体是抱怨物流还是抱怨商品质量」,这两个判断能不能放进同一次请求?
变式:如果第二题写成「结合第一题对情绪的判断,给这条评论打一个 1 到 5 分的严重程度」,这种写法算不算依赖第一题的答案?
构造一个场景,表面上两个问题看起来可以一次问完,但实际上第二题必须依赖第一题的真实答案,不能只靠共享的 state 独立判断。
变式:如果把两步都改写成 Noul(先问是不是属于某个大类,答案很接近 1 才继续问细类),这种设计能不能避免拆成两次请求?
答案互相看不见,是同一个决定的另一面
- 它把输出类型设计成排除字符串和一切有先后顺序的结构——CEO 在 Hacker News 原话:「strings (and all sequential data structures) are not allowed at all - this is how we make sure all outputs can be computed in parallel (thus no output token cost)」(
HN 49719122)。 - 所以全部答案能同时算出来,不用等一个答完再算下一个——这正是「输出免费」和「问题互相独立」共同的前提,同一个决定的两个结果。
- 第3天开发者写工单路由:先问「现在处理还是以后」,是以后就追问「明天还是后天」——下一题问什么,取决于上一题真实的答案,塞不进同一次请求。
- 要不要往下追问,全靠开发者自己在代码里用 if 语句接起来——模型不会替你把链条串起来。
如果 Jev 的输出类型允许字符串这样有先后顺序的结构,「同一次请求里的问题只能各自独立评估、看不到彼此答案」这件事,还会像现在这样必然成立吗?
变式:如果只是把「问题之间不能互相引用对方的答案」写成接口层面的一条规则,不改变输出类型本身,这和现在靠输出类型排除掉这种可能,实际效果上有什么不同?
链有多长,串行请求会有多慢?
把「有依赖关系必须串行」这件事量化。一条长度为 N 的依赖链,要发 N 次请求,第二次请求必须等第一次的答案回来才能发出,第三次必须等第二次,以此类推——跟第8章级联那两步「先后进行」是同一个结构,只是这里可能不止两步。
自己推一遍:链条要多长,串行 Jev 才会比一次大模型调用还慢
如果 Jev 单次请求的端到端延迟是 latJ,一条长度为 N 的串行依赖链,总延迟该怎么写?
想好了再看
总延迟 = N × latJ——每一步都要等前一步的答案出来才能发下一次请求,N 次请求的延迟只能顺次相加,不能互相重叠,这跟第8章级联里「升级案例延迟是两段时间相加,不是取较大值」是同一个道理。
用官方 workflow 评测里的真实数字:Jev 单次 0.4 秒,opus 5 单次 37.8 秒。链条长度 N 要大到多少,N 次 Jev 请求的总延迟才会超过一次 opus 5 请求?
想好了再看
解不等式 N×0.4 > 37.8,得 N > 94.5——也就是链条长度到 95 步的时候,95 次串行 Jev 请求(95×0.4=38 秒)已经比一次 opus 5 请求(37.8 秒)慢了。
官方博客对「System One shaped queries」给出的是另一个延迟区间:70 毫秒到 500 毫秒,不是 workflow 评测里那个 0.4 秒。如果分别用这个区间的两端重新算一遍交叉点,会得到什么?
想好了再看
用上限 0.5 秒算:N > 37.8/0.5 = 75.6,链条到 76 步就会反超。用下限 0.07 秒算:N > 37.8/0.07 = 540,链条要长到 541 步才会反超。同一个「交叉点在哪」的问题,答案落在 76 到 541 之间的一个很宽的区间里,宽窄取决于你信官方哪一个延迟数字——这正是第13章「三个上下文预算数字打架」那件事,在延迟这个维度上的翻版。
| 符号 | 是什么 | 直觉 |
|---|---|---|
| N | 依赖链的长度,要串行发的请求次数 | 这条链要接力跑多少棒 |
| latJ | Jev 单次请求的延迟 | 接力赛里每一棒自己要跑多久 |
| N×latJ | 整条链跑完的总延迟 | 接力赛的总用时,只能顺次相加 |
如果依赖链长度是 50 步,按 Jev 单次 0.4 秒计算,这条串行链条的总延迟是多少?跟一次 opus 5 请求(37.8 秒)比,哪个更快?
变式:如果这 50 步依赖链里,其中 10 步其实互相之间没有依赖关系,可以合并进同一次请求一起问,总延迟会降到多少?
一条 20 步的依赖链,实际结构是:前 5 步互相独立(可以合并成一次请求),接下来 15 步是严格的先后依赖,每一步都要等前一步。这条链的总延迟该怎么算,比「20 步全部串行」快多少?
变式:如果这 15 步严格依赖里,其实中间有一步可以拆出来变成和前 5 步一起独立处理,总延迟又会降到多少?
链长 5 步
5×0.4=2 秒,远快于 opus 5 单次的 37.8 秒,串行 Jev 优势明显。
链长 100 步
100×0.4=40 秒,已经比 opus 5 单次的 37.8 秒还慢,串行 Jev 反而落后。
差别在:链长有没有跨过 94.5 这个交叉点——跨过之前,串行 Jev 更快;跨过之后,反而是一次大模型调用更快,链条越往后拖,这个反超只会越明显。
把一个环节换成快得多的 Jev,整条流水线会跟着同样倍数变快吗?
假设一套真实的自动化工单流水线,除了判断这一步,还有别的环节:先花 2.0 秒从工单系统里检索相关历史记录,再花时间做分类判断,最后花 1.0 秒把结果写回工单系统、通知相关方。检索和写回这两步跟用哪个模型做判断没有关系,不会因为换了模型就变快或变慢。
先看只换判断这一步会发生什么。我先看到的是判断这一步单独的延迟:用 opus 5 是 37.8 秒,换成 Jev 是 0.4 秒,单看这一步,确实快了 37.8/0.4≈94.5 倍。我排除的是「整条流水线也会快 94.5 倍」这个直觉推论,因为检索的 2.0 秒和写回的 1.0 秒根本没有被替换,它们该多慢还是多慢。真正该算的是整条流水线前后各自的总时间:换 opus 5 之前,总时间是 2.0+37.8+1.0=40.8 秒;换成 Jev 之后,总时间是 2.0+0.4+1.0=3.4 秒。整条流水线的加速倍数是 40.8/3.4≈12.0 倍,远低于判断这一步单独的 94.5 倍。最怕的错是拿判断这一步的倍数,直接当成整条流水线的倍数来宣传或者做预算规划。检查的办法是把流水线里每一步的时间都列出来,而不是只盯着被替换的那一步。
判断环节单独的倍数
37.8/0.4≈94.5 倍——这是把 opus 5 换成 Jev,判断这一步自己提速的真实倍数,没有算错。
误当成整条流水线的倍数
如果把 94.5 倍直接当成「用户体感到的流水线提速」来宣传,会明显高估——实际是 12.0 倍,因为检索和写回这两步没有被替换,依然占用它们原来的时间。
差别在:判断环节内部的加速倍数,衡量的是被替换的那一小块自己变快了多少;流水线整体的加速倍数,衡量的是包含所有没被替换的环节在内的总时间变化——换一个零件不会让整台机器都按同样倍数变快,这跟第12章「倍数要看基线」是同一类提醒,只是这里换了个维度:基线不只是「对谁比」,也包括「流水线里还有多少没被替换的部分」。
就算判断这一步快到不要钱、耗时趋近于 0,整条流水线也快不过 T固定 这道底——40.8/3.0≈13.6 倍,是这条特定流水线在「判断环节零耗时」的理想情况下,能拿到的加速倍数上限,比 94.5 倍还是低了一大截。这不是 Jev 不够快,是流水线里没被替换的那部分环节,天生就卡着整体加速倍数的顶。
| 符号 | 是什么 | 直觉 |
|---|---|---|
| T固定 | 流水线里跟判断环节无关、不随模型选择变化的总耗时 | 换谁都换不动的那部分 |
| 40.8/3.4≈12.0 | 实际替换后,整条流水线的加速倍数 | 用户真正感受到的提速 |
| 40.8/3.0≈13.6 | 判断环节耗时趋于 0 时,能达到的加速倍数上限 | 不管判断环节多快都翻不过去的顶 |
如果检索和写回这两步的耗时能优化到各只要 0.5 秒(总共 1.0 秒),其余不变,整条流水线换成 Jev 之后的加速倍数上限会变成多少?
变式:如果反过来,检索和写回这两步涨到各 20 秒(总共 40 秒),整条流水线换成 Jev 之后的加速倍数上限会变成多少?这说明了什么?
对你而言未知依赖链变长时,准确率会怎么变,不只是延迟
这一章只算了链条变长对延迟的影响,没有算对准确率的影响。第13章推过「联合准确率是各步准确率之积」,如果把那条公式和这一章的串行延迟模型叠在一起,一条既长又要求高准确率的依赖链,可能会同时在延迟和准确率两个维度上付出代价——链越长,越慢,也越容易在某一步出错拖累最终答案。这份材料里没有人把这两条线放在一起系统测过,是不是真的存在这样的双重代价、代价有多大,需要专门做实验才知道。
先做这一步:设计一条长度从 2 到 10 变化的模拟依赖链,假设每一步的判断准确率固定在某个值(比如 0.95),用第13章的乘法公式算出联合准确率随链长变化的曲线,再用这一章的延迟公式算出总延迟随链长变化的曲线,把两条曲线画在一起,看链长增加到多少时,这条链无论在准确率还是延迟上都已经不划算。
答辩:如果我是审稿人
拿 Jev 单次判断的延迟去跟一次 LLM 调用比快慢,本身公平吗?LLM 之所以慢,很大一部分是在自回归地把类型名、schema 结构这些格式性的内容也一个 token 一个 token 生成出来,如果换一种做法——用约束解码强制 LLM 只输出合法的候选值,会不会一样快?
参考防守(先自己组织语言再看)
这条质疑在 Hacker News 上被明确提出过:「The comparison between LLM speed and Jev speed is misleading, because they're using autoregression to generate all of the type names, all of the schema, etc.」,如果只比纯数值输出,差距可能没有这么夸张。但 TypeSafe 的 CEO 对「那直接上约束解码不就行了」这个思路给出了一个具体的技术反驳:「constrained decoding (OpenAI-style structured outputs) make models dumber unfortunately - the short+dense version is that simply masking logits is insufficient because if ever a model was assigning probability to an invalid token, the model is by definition confused. you'd be better off erroring IMO」——单纯在解码时屏蔽非法 token,并不能修复模型本身在那一步已经「糊涂」了这件事,只是把糊涂的信号藏了起来。两边说的都不是空话:前者点出了比较基准不完全对等,后者点出了「让 LLM 也走一遍强制合法输出」不是没有代价的捷径。这一章从头到尾用的 37.8 秒,是 opus 5 在官方 workflow 评测里原样的延迟,没有经过约束解码优化,读这一章算出来的所有交叉点和倍数时,要记得这一层前提。
留给你的问题
如果你手上的任务,判断之间到底有没有依赖关系其实很模糊——比如「这条评论的情绪」和「这条评论的严重程度」看起来可以互相独立判断,但你又隐约觉得严重程度这道题多少要参考一点情绪判断的结果——你会怎么设计这次请求,才能既享受到「独立问题几乎不加钱」的好处,又不会因为把有隐藏依赖的判断硬凑成独立问题而悄悄答错?
不看材料,写下这一章的三堵墙
一次请求能塞多少道题,没有固定上限,只受 token 预算约束,官方也鼓励多问,但这跟一道 Choice 题能给多少个候选项(255 上限)是两件不同的事,出处也不一样。第二堵墙是所有问题只共享同一份原始 state,彼此的答案互相看不见,这是模型输出类型完全排除字符串和顺序结构、能够并行计算的直接后果,也是输出免费的代价换来的另一面。第三堵墙是串行依赖链的延迟只能顺次相加,链条足够长时,哪怕单次 Jev 判断再快,串起来也会反超一次大模型调用;而且把流水线里的判断环节换成更快的模型,不会让整条流水线按同样倍数变快,流水线里没被替换的部分会卡住整体的加速上限。
这一级要加什么:依赖链延迟计算器
为什么现在才加它:前十三级都在算「一次判断」或者「一次请求里几道独立判断」的账,没有谁处理过「好几个判断之间谁先谁后」这件事——这一级要让审计仪第一次吃进一张依赖关系图,而不是一份平铺的判断列表。
难点:这个函数默认同一批里凑了多少道互相独立的问题都无所谓,反正算作一次请求的延迟——但它没有检查这一批问题加起来的 token 数会不会撞上第13章那堵预算墙,一批塞太多独立问题,账面上延迟确实只按一次请求算,可一旦 state 和这批问题的 token 总和超了预算,这次请求本身就会失败,函数不会替你提前发现这件事。另外它也没有检查依赖关系里有没有环(比如 A 依赖 B、B 又依赖 A),真遇到这种输入会陷入死循环,这在实际写调度逻辑时必须单独防住。
自己验:三个互相没有依赖的步骤 [{deps:[]},{deps:[]},{deps:[]}],latJ 取 0.4,应该算出 1 个批次、总延迟 0.4 秒。把其中一步改成依赖另外两步,[{deps:[]},{deps:[]},{deps:[0,1]}],应该变成 2 个批次、总延迟 0.8 秒。三步严格一环扣一环 [{deps:[]},{deps:[0]},{deps:[1]}],应该算出 3 个批次、总延迟 1.2 秒——批次数正好等于链条的深度,跟这一章正文里「N×latJ」的推导对得上。
第15章 它比老办法强在哪,强多少
在见到 Jev 之前,如果你要做一个能自动判断客服工单类别的系统,你会怎么动手?多半是找一批标好类别的历史工单,拿去微调一个分类模型——这件事本身要花时间、要花钱、还要懂一点机器学习。Jev 把「标数据、训模型」这一步整个跳过了。这一章要认真算一算,跳过的这一步,原来值多少钱。
学完这一章你应该能做到
- 说出 Jev 之前做同类判断常用的四条路,以及每条路各自卡在哪一步
- 把「零样本准确率」换算成「等价于喂给传统方法多少条标注数据」,并说清这个换算为什么有意义
- 看到一个零样本分数,先检查它是不是被训练数据污染过,而不是直接拿来比大小
- 解释两个几乎相等的 ECE 分数,为什么背后的训练代价可以天差地别
- 说清「如果 TypeSafe 倒闭了」这个问题,材料里能给出的部分答案是什么
这一级要给审计仪加最后一个换算器:把「模型自己说的准确率」换算成「一件对生意人有意义的事」——省了多少标注工作量。前面十四级都在审计 Jev 自己的数字站不站得住;这一级要把这些数字放回它们原本要对比的那个世界,回答「所以呢,这比原来的办法到底好在哪」。
在 Jev 之前,人们用什么做同样的事?
先把 Jev 出现之前,要做「给一段文字判断类别、或者判断某件事成立的概率」这类任务,通常会走的几条路认真过一遍,看它们各自卡在哪。
第一条路是微调一个 BERT 一类的编码器模型:拿一批人工标好答案的数据,在预训练模型上接一个分类头,训练到收敛。这条路能做到很高的准确率,但训练本身需要标注数据,数据量通常要到几百上千条才能训出一个像样的分类头,而且要懂得怎么调学习率、怎么防止过拟合,对没有机器学习背景的人是一道门槛。第二条路是零样本自然语言推理,代表模型是 bart-large-mnli 和各版本 DeBERTa——这类模型不需要专门为你的任务训练,把「这段文字属于某个类别」包装成一个前提和假设是否蕴含的问题,直接推理出概率。它免去了训练这一步,但准确率通常明显低于专门微调过的模型。
如果手上有 2,000 条高质量标注数据,又有充裕的时间调参,微调 BERT 和零样本 NLI,通常哪一条路能做到更高的准确率?
变式:如果只有 20 条标注数据,这个结论还成立吗?
第三条路是直接读 LLM 的 logprobs:给模型一个开放式的前缀,比如「The capital of France is」,模型会对词表里的每一个候选词都给出一个概率,理论上可以把这套机制挪用来做分类判断。第四条路是约束解码:强制 LLM 的输出只能落在一组合法的候选值里,省去后续再解析自由文本答案这一步。
零样本 NLI(比如 bart-large-mnli)和微调 BERT 分类头,这两条路最大的区别是哪一步有没有省掉?
变式:约束解码这条路,省掉的是训练这一步,还是别的什么步骤?
这四条路各有各的支持者。Hacker News 上有人把「Jev 相对这些老办法,新在哪里」这个问题摆出来讨论,先指出编码器模型本来就能跳过文本生成、直接给概率,推理也快、不会有生成式模型那种幻觉。那顺着这个思路往下想,Jev 如果真的带来了增量,你觉得这个增量最可能落在哪?
答完再看
用户 bregmandiv 那条评论把这件事讲得最清楚:「I'm trying to parse it down to what we had before vs what is new here. We already had encoder models that skipped text generation for giving us a numerical output that could be computed as a probability. we also got no hallucinations and faster inference for free there. So we already had 1. 'unstructured state in, probabilistic decisions out' 2. 'orders of magnitude faster and more efficient'. What was hard there was to train the model head without ML expertise, and considerable amount of data. This seems like this is a democratization of those encoders? The addition over existing encoders seems to be coming from being able to specify the output shape (up to a cardinality of 255). ... If so, that is still very impressive, but I think the faster inference and 0 hallucinations might come for free, from it not being generative.」这段话把「新在哪」定得很准:不生成文本、直接给概率,编码器模型早就会了;真正难的从来不是推理速度,是没有机器学习专业知识、没有大量数据,训不出那个分类头。Jev 如果真的带来了增量,必须落在这一句「what was hard」上,不能只是「又快又不会幻觉」——那部分编码器模型本来就有。
按 bregmandiv 这段话,Jev 如果真的比编码器模型更进一步,这个进步应该体现在「推理更快」上,还是别的什么地方?
变式:如果有人反驳说「Jev 比编码器模型准得多,这就是增量」,这个反驳跟 bregmandiv 提的问题是不是同一回事?
零样本到底值多少条标注?
要检验「不用标数据训 head」这件事到底值多少钱,需要一把能换算的尺子:如果非要用传统方法(比如微调一个简单分类器)去追平 Jev 零样本的准确率,大概需要喂它多少条标注数据。第三方评测 zhuyansen/jev-zeroshot-vs-bert 把这件事量出来了,方法是画出传统方法的学习曲线——用不同数量的标注数据分别训练、测准确率,再找出这条曲线爬到 Jev 零样本分数那个高度时,用了多少条数据。
自己推一遍:学习曲线怎么换算出「等价标注量」
如果已经测出传统方法在 100 条标注时准确率 0.80,在 500 条标注时准确率 0.90,Jev 零样本在这个任务上是 0.865,等价标注量大概落在什么范围?
想好了再看
落在 100 到 500 条之间——0.865 介于 0.80 和 0.90 之间,说明追平 Jev 需要的标注量,比 100 条多,又不需要到 500 条那么多,具体数字要看这条学习曲线在这一段爬升得有多快。
如果这条学习曲线在这一段接近直线爬升,能不能用线性插值估出更精确的数字?
想好了再看
能。0.865 在 0.80 到 0.90 这段区间里的位置是 (0.865−0.80)/(0.90−0.80)=0.65,按这个比例在 100 到 500 之间插值,100+0.65×(500−100)=360 条左右——这只是示范算法,真实的学习曲线未必是直线,zhuyansen 那份评测用的是实际测出来的多个数据点,不是只测两头再直接插值。
这个「等价标注量」的数字,能不能倒过来当成「Jev 天生比传统方法聪明 N 条标注数据那么多」来理解?
想好了再看
不能这样倒过来理解。它衡量的是「在这一个具体任务、这一种传统方法上,要追平 Jev 需要多少标注」,换一个任务、换一种传统方法(比如换成更强的基座模型),这个数字会完全不同——第15-2节接下来给出的真实数字,横跨了从两百多条到两千多条还追不平的巨大区间,这本身就是证据,说明它不是一个可以固定下来的「聪明程度」。
| 数据集 | 等价标注量 | 说明 |
|---|---|---|
| AG News | 约 231–336 条 | 四分类新闻主题 |
| Banking77 | 约 238 条(lr-bge)/1,338 条(ft-bert) | lr-bge:在现成文本嵌入上接逻辑回归;ft-bert:直接微调 BERT 整个模型 |
| SST-2 | 超过 2,048 条仍未追平 | 二分类情感判断 |
| TweetEval-emotion | 超过 2,048 条仍未追平 | 推文情绪四分类 |
| PAWS | 超过 2,048 条仍未追平 | 句子是否同义改写 |
在 Banking77 这一行,「238 条」和「1,338 条」哪一个数字对应的传统方法,追平 Jev 需要的标注更少?
变式:如果换一个任务,微调整个 BERT 比逻辑回归接嵌入更快追平 Jev,这说明了关于「简单模型 vs 复杂模型」的什么?
你手上有 300 条标好的历史工单,要在 AG News 类似的新闻主题分类任务和 SST-2 类似的情感判断任务里选一个,判断该不该干脆用传统方法自己训练、而不是直接调 Jev 零样本。用这一节的数字给出判断。
变式:如果你的标注预算完全不受限制,愿意标多少标多少,这张表还有决策价值吗,还是这时候另有别的因素更重要?
网上一个零样本分数,能直接信吗?
在拿等价标注量做决策之前,先看一个真实的陷阱。有一个公开的零样本分类模型,在 AG News 上报出 0.901 的准确率,比 Jev 零样本的 0.865 还高——如果只看这一个数字,会得出「这个公开模型比 Jev 更强」的结论。先把这个判断认真检验一遍。
一个模型的名字或者说明里写着「零样本」,这是不是足以说明它的训练数据里一定没见过测试用的那份数据集?
变式:如果一个模型的开发者明确公开了完整的训练数据清单,这是不是就足够核实它的零样本声明了?
我先看到的是两个数字的大小关系:0.901 比 0.865 高。我排除的是直接拿两个数字比大小这个做法,因为「零样本」这个标签本身不能保证公平——一个模型宣称零样本,前提是它的训练数据里确实没见过这个测试集,这件事需要单独核实,不能只看模型自己怎么描述自己。真正该做的是去查这个模型的训练数据清单:这个报出 0.901 的模型叫 deberta-v3-large-zeroshot-v2.0,它的训练数据清单里确实包含 AG News——也就是说它在「零样本」测试之前,已经在这份数据集上训练过,0.901 这个数字来自记忆,不是泛化。同一个模型架构的干净版本(没有见过 AG News 的那一版),零样本准确率只有 0.763,明显低于 Jev 的 0.865。最怕的错是把「模型自称零样本」当成「模型真的没见过这份数据」的证明,两者不是一回事。检查的办法是去核对训练数据清单,而不是相信模型卡片上的自我描述。
受污染的「零样本」:0.901
deberta-v3-large-zeroshot-v2.0 的训练数据包含 AG News,这个 0.901 来自记忆,不是真正意义上的泛化能力。
干净的零样本:0.763
同一个架构、但训练数据里排除了 AG News 的版本,零样本准确率只有 0.763——这才是跟 Jev 的 0.865 站在同一起跑线上、可以直接比的数字。
差别在:0.901 和 0.763 出自几乎同一个模型架构,差距全部来自「有没有见过这份测试数据」,不是架构本身的强弱——不核对训练数据清单,光看模型自称「零样本」,很容易把记忆当成能力。
如果你看到一篇文章说「某公开模型零样本准确率 0.90,秒杀 Jev 的 0.865」,在信这句话之前,你会先去查什么?
变式:如果这个模型的训练方或者第三方明确证实训练数据里不含这份测试集,这个 0.90 还需要打折扣吗?
反过来,同一份评测也做了污染对照,检验 Jev 自己的分数是不是也存在类似问题:用 Jev 发布之后才出现的新论文摘要重新测一遍,如果分数明显下跌,说明原来的分数可能也依赖了训练时见过的内容;如果分数几乎不跌,说明泛化能力是真实的。结果是几个传统基线模型分别跌了 0.112、0.109、0.101,跌幅都不小;Jev 只跌了 0.035,跌幅的置信区间跨过 0——没有证据表明 Jev 原来的分数是靠记住训练数据撑起来的。整份评测测了 7 个数据集,Jev 全部赢过干净版本的 DeBERTa 零样本基线,每一处置信区间都在 0 以上。
答辩:如果我是审稿人
另一份独立评测(ickma2311,预注册、自费)在 Banking77 上测出监督式 encoder 0.933、Terra 0.875、Jev 0.832、nano 0.793,置信区间还互相重叠,作者自己判定「不明确」。这跟这一节「Jev 在 7 个数据集上都赢过干净零样本基线」的结论矛盾吗?
参考防守(先自己组织语言再看)
不矛盾,因为两份评测在比的根本不是同一件事。zhuyansen 那份评测比的是「零样本对零样本」——Jev 和干净版 DeBERTa、BGE-m3、BART 都不需要为这个具体任务训练;ickma2311 那份评测里排在最前面的「监督式 encoder」是专门在 Banking77 上训练过的,根本不是零样本,拿一个专门训练过的模型和一个零样本模型比,本来就不是同一个赛道的比较,Jev 排在它后面完全正常,不能反过来说这打脸了 Jev 的零样本能力。再看 Jev 和同样不是零样本的 Terra 之间的比较:0.832 对 0.875,置信区间重叠,作者自己判定「不明确」,这句话的准确含义是这两个数字之间谁更高还没有被这份数据证实,不是「Jev 更差」被证实了。两份评测各自的结论都可以同时成立:零样本对零样本,Jev 有优势;跟专门训练过的模型比,Jev 不占优势,这本来就是意料之中的事。
ickma2311 那份评测里,「Jev 0.832 对 Terra 0.875,置信区间重叠」和「Jev 0.832 对监督式 encoder 0.933」,这两组对照哪一组更适合用来质疑「Jev 零样本有没有优势」这个说法,哪一组根本问错了问题?
变式:如果 Jev 对监督式 encoder 反而赢了(0.832 高于 0.933 这种假设情形不成立,但假设换一个任务真的赢了),这能不能说明 Jev 的零样本能力已经超过了专门训练?
两个几乎一样的校准分数,含金量一样吗?
Jev 在 SST-2 上的 ECE 是 0.022,bart-large-mnli 在同一个数据集上的 ECE 是 0.016——两个数字很接近,后者甚至还略好一点。Jev 的校准是靠专门的强化学习训练出来的,bart-large-mnli 完全没有为校准做过任何专门训练。你觉得这说明专门训练校准这件事,其实没什么必要?
答完再看
第5章讲过,ECE 和 Brier、和准确率衡量的不是同一件事——两个模型 ECE 接近,不代表它们在其他维度上也接近。正文接下来把这两个模型真正的差距摆出来。
Jev 的这套专门训练校准的方法叫 RLCD,第2章已经讲过它的定义:面向校准决策的强化学习。bart-large-mnli 的校准来自完全不同的地方——它是一个自然语言推理模型,做分类判断时用的是 softmax 输出,这个 softmax 恰好也表现出不错的校准效果,但这纯粹是这类推理模型结构自带的副产品,没有为「校准」这个目标单独训练过一步。一个花了大力气专门训练出来的校准,和一个完全没有针对性训练、纯属副产品的校准,摆在同一个数据集上,数字几乎一样好。
Jev:ECE 0.022,准确率 0.960
校准来自专门的 RLCD 训练,但真正拉开差距的是准确率——0.960 明显高于 bart-large-mnli。
bart-large-mnli:ECE 0.016,准确率 0.914
校准是 NLI softmax 自带的副产品,没有专门训练,数字甚至比 Jev 还略好一点;但准确率明显低了将近 5 个百分点。
差别在:如果只看 ECE 这一个指标,会得出「两者校准水平相当,谁都没有明显优势」的结论;但真正的差距不在校准这个维度,在准确率这个维度——这提醒一件事,比较两个模型时只看一个指标,哪怕看的是「校准」这种核心卖点相关的指标,也可能完全找错了它们真正的差距在哪。
如果只用「ECE 分数几乎一样」这一句话来总结 Jev 和 bart-large-mnli 在 SST-2 上的对比,这句话遗漏了什么关键信息?
变式:如果反过来,有人只用「Jev 准确率更高」这句话总结两者的差距,这句话又遗漏了什么?
既然 RLCD 专门训练出来的校准,数字上没有明显超过完全没训练过的 bart-large-mnli,这是不是说明 RLCD 这套训练方法对 Jev 没有带来实际价值?
变式:如果要设计一个实验,专门检验 RLCD 训练对校准这一件事本身有没有增量,应该怎么设计对照组?
如果 TypeSafe 倒闭了,这一切就没了吗?
有人说 Jev 真正的核心卖点是准确率比开源零样本模型高很多。结合这一章前面看到的数字——7 个数据集里有 3 个超过 2,048 条标注仍追不平 Jev,Banking77 上专门训练过的监督式 encoder 反而比 Jev 更准——你觉得这个说法站得住吗?
答完再看
这一章的数字已经说明准确率优势远不是「明显碾压」这么简单——在专门训练过的方法面前,Jev 未必更准。正文接下来给出一个更站得住的价值主张。
TypeSafe 没有开源 Jev 的权重,也没有公开架构或者训练细节,这意味着如果这家公司停止运营,没有人能直接把 Jev 接管过来继续跑。但发布之后不久,已经有人做出了形状上的独立复现:huggingface.co 上的 open-jev-deberta-v3-large,底座是公开的 DeBERTa-v3,一次前向传播就能给出每个问题的校准概率分布,作者测出来 in-domain 准确率 0.854、跑到训练时没见过的分布外数据上掉到 0.690,ECE 0.022。作者自己把这个从 0.854 掉到 0.690 的落差起名叫「诚实的落差」(the honest gap)——不回避复现版本的能力边界在哪,同时也说明这种「输入任意文字、输出类型化的校准概率」这个形状本身,并不需要依赖 TypeSafe 独家的技术,是可以被公开架构复现出来的。
open-jev-deberta-v3-large 这个开源复现,能不能证明「就算 TypeSafe 倒闭,Jev 现在的具体能力也能被完全接管」?
变式:如果之后又出现了在更多数据集上跟 Jev 表现更接近的开源复现版本,这个部分答案会不会变得更完整?
一份真实生产环境的记录,来自 paddo.dev 的一篇博客:作者用 Jev 处理 9,081 对商品匹配,总花费只有 0.32 美元,6 个并发跑了 13 分 22 秒,手工核验 50 条里 48 条判断站得住。作者写下的两句话,比任何一个准确率数字都更准确地描述了 Jev 的位置:「The price changed the architecture, not the accuracy.」「Fifty hand-labelled rows cannot test whether 0.85 means 85%.」——价格改变的是要不要做这件事的架构决定,不是判断本身准不准;而 50 条人工核验,也远远不足以验证「0.85 这个数字」是不是真的对应「85% 说对了」这件事。
paddo.dev 手工核验了 50 条商品匹配结果,48 条站得住。这能不能证明 Jev 报出来的置信度数字,真的对应它所声称的那个概率?
变式:如果把核验样本从 50 条扩大到 5,000 条,是不是就一定够验证校准了?还需要满足什么条件?
把这几条放在一起看:Jev 在准确率上不是全面碾压,标注等价量因任务而异,专门训练过的模型在不少场景下依然更强;但它把「加一层自动化的判断或者核验」这件事的成本,压到了原来想都不会去想的量级。paddo.dev 那 9,081 对商品匹配,如果要专门训练一个分类器去做,或者要请更贵的前沿大模型逐条跑一遍,多半根本不会立项。Jev 真正站得住的价值主张,是让一个原本因为太贵而不存在的验证层变得值得去做,不是单纯比老办法更准。
一家公司在犹豫要不要给现有的人工审核流程加一层自动初筛。人工审核每条成本很高,公司从来没有为这件事投入过训练一个专门分类器。结合这一章的全部内容,你会给这家公司什么建议?
变式:如果这家公司原来已经有一个训练过的专门分类器在跑,这个建议还成立吗?这时候比较的对象变成了什么?
评价标准:谁更准
按这个标准,Jev 经常不是最优解——标注攒够了,老办法就反超,专门训练过的监督式模型更是常常领先。
评价标准:有没有,比没有好不好
按这个标准,Jev 能让一个原本因为太贵、从来没被造出来过的验证层,变得值得去做——这才是它真正站得住的位置。
差别在:拿 Jev 和一个已经存在的方案比准确率,跟拿 Jev 和「压根没有这层判断」比有没有价值,问的不是同一个问题,答案自然也不一样。
对你而言未知能不能不用画完整条学习曲线,就估出等价标注量
这一章的等价标注量,来自 zhuyansen 那份评测老老实实测出好几个标注数量下的准确率,再画出完整的学习曲线。这个过程本身需要不少标注数据和训练次数。如果只有很少的几个数据点(比如只测了 50 条和 200 条两个点),能不能用某种统计方法,比较可靠地外推出这条曲线大概会在多少条标注时追平 Jev,而不用把整条曲线都跑出来?这属于机器学习里「学习曲线外推」这个方向,有一些公开的研究方法,但没有人把这些方法专门套到「估算追平 Jev 需要多少标注」这个具体问题上验证过是否可靠。
先做这一步:找一份公开的、带有完整学习曲线数据的分类任务(哪怕不是这一章用到的数据集),只取曲线最前面两三个点,用简单的对数曲线拟合外推到曲线末端,跟真实测出来的末端数值比较误差大小,看这种外推方式在你能拿到的数据上到底可不可靠。
只有两个标注点(比如 100 条和 500 条各自的准确率)时,用简单的插值或者外推算出来的等价标注量,能不能保证跟老老实实测出完整曲线得到的数字一样准?
变式:如果这两个点本身就取得很极端(比如 10 条和 10,000 条),外推的风险会变得更大还是更小?
留给你的问题
下一次有人拿着一份「新模型比老办法准 N 倍」的评测报告来找你,除了检查基线和倍数,这一章教你的哪一句追问——关于标注、关于污染、关于训练代价——会是你最先问出口的那一句?
不看材料,写下这一章的三堵墙
四条老路各有各的门槛:微调要标注数据和机器学习经验,零样本 NLI 省了训练但准确率通常更低,logprobs 和约束解码各自也有代价;Jev 真正的增量,按 bregmandiv 那段话,落在「不用标数据、不用训 head」这件事上,不是推理速度或者不会幻觉,那些编码器模型本来就有。第二堵墙是零样本分数不能直接信,一个模型自称零样本,不代表训练数据真的没见过测试集,污染会把记忆伪装成泛化能力,0.901 和 0.763 这组数字就是活生生的例子。第三堵墙是数字相近不代表代价相近、也不代表价值主张一样:两个 ECE 差不多的模型,一个花大力气训练、一个完全没训练过,真正的差距要去别的指标里找;而让一个原本因为太贵而不存在的验证层变得值得去做,可能才是 Jev 最站得住的价值主张,不是单纯比谁都准。
这一级要加什么:标注等价量计算器
为什么现在才加它:前十四级衡量的都是 Jev 自己的数字站不站得住,没有一级把这些数字换算成「跟老办法比,到底值多少」——这是审计仪最后一个部件,把前面全部的审计结果,翻译成一件业务决策者真正关心的事:这一层该不该自己训练,还是直接调 Jev。
难点:这个函数只能在零样本分数落在已测出的曲线范围内部时给出估计,一旦超出范围(比如零样本分数比曲线测到的最高点还高),直接返回 null 而不是硬着头皮外推——这不是功能不完整,是故意的:本章研究那一节已经说明,用两三个点外推整条曲线的可靠性没有被验证过,宁可老实报告「答不了」,也不要编一个看起来合理、实际没有依据的数字,这正是这一整套材料从第一章开始就在坚持的规矩。
自己验:curvePoints=[{n:100,acc:0.80},{n:500,acc:0.90}],labelEquivalent(0.865, curvePoints) 应该输出 360(对应正文推导线算出的那个数)。labelEquivalent(0.80, curvePoints) 应该正好输出 100(落在第一个点上)。labelEquivalent(0.95, curvePoints)(超出曲线覆盖的最高点 0.90)应该输出 null,不是一个硬凑出来的外推数字。
第16章 一张评测表递过来,先问哪七个问题
三十秒。一张新模型的发布页留给你的注意力,大概就这么多——几个加粗的百分比,一句比谁快多少倍,一张配色鲜亮的柱状图,然后你的手指已经准备好往下划。前面十五章,你在Jev这一个案例身上,把这三十秒背后能问的问题一条条挖穿过一遍,现在要把它们收成一张随时能掏出来的清单:下一次递到你面前的不再是Jev,你也不必从头再挖一遍。
学完这一章你应该能做到
- 拿到任意一份新模型的发布材料,按七个问题逐条过一遍,每个问题都知道去哪儿查、查什么、算什么
- 对着一句「快很多倍」「便宜很多倍」的宣称,找出没写出来的那个分母
- 分清「这件事材料没有验证」和「这件事已经被证伪」是两句不同的话
- 认出一条听起来像营销话术、但论证本身站得住的反驳,不因为立场先入为主就否定它
这一级要做的不是造新部件,是把前十五级散落的仪表——概率越界检查器、可靠性图、阈值求解器、级联路由器、双轨记分板、置信区间、倍数换算器、标注等价量计算器——接到同一个控制面板上:输入一份发布材料,面板吐出一张七问清单的填写结果。它排在最后,不是排在开头当学习方法,是因为没有前十五级打的地基,这张清单只是七句正确的废话。
这张表的「参照系」,是谁定的?
面前是一张新模型的评测表,总分写着一个漂亮的百分比,旁边配着「媲美顶尖模型」的说法。你会先确认这个百分比够不够高,还是先确认别的?
答完再看
Jev官方那张evals表就是一个现成的例子:表上的分数不是和人工核对过的标准答案比出来的,是和另外两个模型给出答案的平均值比出来的——参照系本身,也是模型给的。
Jev的总分67.8%,出自官方自己的evals.typesafe.ai——四个工作流等权平均、每案例0.0004美元、0.4秒。这句「67.8%准确率」的说法里,藏着一处不写在配图上的定义:参照系不是人工审核过的正确答案,是GPT-6 Astra和Claude Fable 5.1两个模型各自开着最高档的思考模式,给出答案后取平均值——被测的Jev和表里其余每一个模型,用的却是各家默认的推理设置,连思考力度这一项都不对等。第1章已经把这类数字该怎么归档的规矩立好了:这是「一手·官方」档,可以当产品事实用,但评测方法本身的这层限定,决定了它能不能被叫做准确率。
Jev在evals表上的准确率是67.8%,这句话里用来判定对错的正确答案,来自哪里?
如果参照系换成由三位人工审核员逐条核对,这句67.8%的可信度,会不会因此变得不一样?
更要紧的一层是:定义参照系的这两个模型——Astra和Fable 5.1——压根不出现在这张对比表里。这不是遗漏,是躲开一个明摆着的坑:一旦把它们也摆进去打分,它们对着自己定的答案打分,分数不可能不高,整张表立刻变成一场自问自答。
如果evals表把Astra和Fable 5.1也列进对比名单,它们的分数大概率会怎样?这说明了什么?
如果某天官方决定把Astra和Fable 5.1的分数也标进表里,作为参照而非参赛,这样处理妥不妥当?
参照系还有一层没写在配图上的偏向:Astra属于OpenAI、Fable 5.1属于Anthropic,官方自己承认过,这套参照系偏向OpenAI和Anthropic的模型,而且很可能低估了Jev自己和DeepSeek系模型的相对表现——这不是外部批评者的推测,是官方文档自己写下的一句限定。
参照系是人工核对过的标准答案
这时候的百分比量的是答没答对,可以直接叫准确率,第0到第9章讲校准时默认的都是这种前提。
参照系是另外两个模型答案的平均
这时候的百分比量的是和这两个模型想得像不像,更准确的叫法是一致率——这不是作弊,更接近标注成本太高时的常见妥协,但读表的人如果不知道这一层,会把像读成对。
差别不在算得对不对,在这个数字回答的是哪一个问题——evals页的评测说明写的是后一种,首页配文的口气却经常像前一种。
假设你看到一份新的模型排行榜,总分栏标着「智能指数」,旁边小字写着以三个基准模型的中位数为对照。这句以基准模型的中位数为对照,会不会影响这张表能不能被叫做准确率排行榜?
如果这份排行榜完全没写清楚参照系来自哪里,你该怎么办?
样本量多少,置信区间多宽?
面前两个模型的分数分别是67.8%和67.9%,只差0.1个百分点。你觉得这个差距能不能说明谁更强?
答完再看
Jev总分67.8%,terra总分67.9%,就差这0.1个百分点,而官方公布的评测说明里,没有一处提到样本量或置信区间。
官方evals表把67.8%这样的数字标到小数点后一位,看起来足够精确,但精确到小数点不等于差距真实存在。第11章你已经用自助法在模拟数据上验证过:抽样的案例数越少,两个真实水平接近的模型,测出来的分数谁高谁低这件事因为运气反过来的概率相当可观。sol、luna这些参赛模型的世代归属也顺着同一条线打了折扣:官方evals表只用小写短名标注模型,博客里能查到terra是GPT-5.6一代、Astra是GPT-6一代,但luna和sol的世代,evals表本身一处都没写。
一张评测表只给了百分比,没给样本量,这张表能不能回答A模型是不是真的比B模型强这个问题?
如果这份材料公布的是「区间[65.1%,70.5%]」而不是一个点估计,判断会变得容易一些吗?
67.8%和67.9%这两个分数,如果各自都基于10万个案例测出,和各自都基于50个案例测出,你对这0.1个百分点是不是真实差距的信心,应该一样吗?
如果官方后来补发了样本量,你会怎么重新判断这0.1个百分点还算不算噪声?
Jev的四个workflow各自的案例数量,官方公布过吗?
如果只公布了总案例数、没有拆成四个workflow各自的数量,这算不算解决了这条空白?
一份报告附带95%置信区间
标着[65.1%,70.5%],光看这个区间和另一个模型的区间有没有重叠,就能大致判断差距是不是显著。
一份报告只给一个点估计67.8%
这个点估计背后可能对应很窄的区间,也可能对应很宽的区间,光看这一个数字判断不出差距是不是真实存在,只能悬置判断。
差别在于置信区间把这个数字有多可信这件事直接摆在了台面上,点估计把这件事完全藏了起来——Jev的evals表用的是后一种呈现方式。
这个「快很多倍」,分母是谁?
首页写着两行大字:193.6倍更快、444.6倍更便宜。这两个倍数,说的是对同一个对手吗?
答完再看
193.6倍对的是sonnet5(同为67.8%的一致率,78.1秒),444.6倍对的是opus5(0.1761美元)——不是同一个对手,首页把它们并排放在一起,很容易让人以为存在一个同时被这两个数字碾压的对手,但这样的对手并不存在。
把这两个数字拆开单独算:Jev对sonnet5的成本优势,只有大约293倍,不是444.6倍;Jev对opus5的速度优势,只有大约94倍,不是193.6倍。193.6倍和444.6倍,是从两个不同对手身上各自挑出最亮眼的那一项拼出来的,而且这两个数字连自己都经不起核对——用官方公布的舍入值反推,只能算出195.2倍和440.2倍,和首页写的193.6、444.6对不上,精确的原始值官方没有公布过。同一天里,官方博客又说的是「40到200倍更快」,创始人的推文说的是「20到200倍或40到400倍」——三套说法出自同一批发布材料。
sonnet5和Jev在evals表上的一致率都是67.8%,完全相同。如果只看这一项,Jev对sonnet5的优势应该从哪个维度上算?
反过来,Jev对opus5的成本优势该怎么算?和444.6倍对得上吗?
同一天发布的材料里,官方同时给过「40到200倍更快」(博客)、「20到200倍或40到400倍更快」(创始人推文)、以及首页的193.6倍——三套说法都指向同一件事吗?
如果只允许保留一套说法放在首页,你会建议保留哪一套?需要补充哪些限定词才够用?
Jev对sonnet5,成本优势约293倍
分母写清楚了,这句话可以核对、可以复现——sonnet5的0.1174美元除以Jev的0.0004美元。
Jev便宜444.6倍
分母没写在同一句话里,读者只能默认便宜444.6倍适用于任何对手,实际上这个数字只对opus5成立。
差别在于有没有把分母钉在同一句话里——同一个价格差,换一个分母,倍数能差出几百倍。
总分是怎么合出来的?
官方总分67.8%,是四个工作流(Security Incidents、Agent Trace Observability、Invoice Processing、Customer Service)合出来的。你觉得这四项对总分的贡献,是一样大,还是按各自的题量分配?
答完再看
官方原文写的是等权,四个工作流不管各自案例数量多寡,在总分里都占四分之一,这是等权平均,不是按规模折算的加权平均。
这一步选择本身没有对错——第0章你已经算过,等权平均和加权平均能给出完全不同的答案,是两种都合理、但服务于不同目的的算法。问题在于等权平均会把逐项的差异抹平:Jev在Invoice Processing这一项只有61.8%,比总分67.8%低了整整6个百分点。四项里绝对分数最低的其实是Security Incidents,61.7%,比Invoice Processing还要再低0.1个百分点;但Invoice Processing是和当项最高分差距最大的一项,官方§7的原始表格里,这一项当项最高的是sol的79.1%,相差17.3个百分点——这恰好也是官方自己承认过数学、日期、数值精度弱这条局限最容易踩中的场景,发票处理本身就是金额和日期密集的任务。
Jev在四个workflow里,哪一项的分数最低?
Customer Service这一项的分数是多少,比总分高出几个百分点?
Customer Service这一项,Jev的分数是76.0%,比总分67.8%高出8.2个百分点;Invoice Processing这一项是61.8%,是上一题确认过的两个垫底分数之一,也是和当项最高分差距最大的那一项。如果只看总分,这一项的强项和Invoice Processing那一项的弱势,分别会不会被看到?
如果这四项换成加权平均,权重按这项任务在真实业务里出现的频率分配,而发票处理恰好是最常见的场景,总分会怎么变?
某班四次测验成绩是90、90、90、40分,等权平均是77.5分。如果这四次测验对应的是四种完全不同的技能,77.5分这一个总评,能不能告诉你这个学生具体哪一项技能不过关?
如果这四次测验里有一次的权重被加倍,加权平均之后,还能不能看出具体是哪次考了40分?
查一下Invoice Processing这一项单独的分数
61.8%,比总分低6个百分点,暴露了Jev在数值密集任务上的短板。
只看总分67.8%
完全看不出四项之间有14.2个百分点的落差,也看不出哪一项在拖后腿。
差别在于愿不愿意多翻一层,去看总分背后那张拆开的分项表——等权平均本身没有错,错的是把总分当成唯一该看的数字。
概率校准过吗,谁验的?
官方反复用校准这个词描述Jev,你觉得材料里会不会配一张可靠性图,或者一个ECE、Brier这样的数字?
答完再看
第5章、第9章已经确认过这件事:ECE、Brier、reliability diagram、calibration curve,在874KB的官方文档转储里全部零命中——calibrated这个词出现了25次,没有一次带数字。
校准这个词,官方给了一句清楚的定性定义:被判定为0.2的那一批事件,长期看应该有大约两成真的发生。这句话本身没问题,缺的是拿Jev自己的输出去验证这句话的那张图或那组数字——官方一个都没给。
官方反复用校准这个词,和官方公布了校准的验证数字,是同一件事吗?
如果官方把「calibrated」换成一个从没在校准领域出现过的自造词,这一节的结论会不会因此改变?
但材料不是一片空白。第1章讲的证据分级在这里正好用得上:zhuyansen这份自费、独立、带置信区间的评测,属于分级表里最高的一档,回头把ECE逐格核对过——Jev在SST-2上0.022、在arXiv 2026这个数据集上0.041、在PAWS上0.069,多数场景校准得相当不错,有几项甚至比最好的基线还低。真正拉胯的是Banking77——77个类别里,Jev的ECE是0.208,是所有测过场景里最差的一个,也是唯一明显输给基线(0.081)的一处。
Banking77有77个类别,是zhuyansen测过的场景里类别数最多的一个,也是Jev校准最差的一个。能不能就此下结论:Jev的答案空间越大,校准就越差?
如果只给你Banking77和PAWS这两组数据,你会不会得出类别越多校准越差这个结论?加上arXiv 2026这组数据之后,这个结论还站得住吗?
zhuyansen的评测
自费、独立、预先冻结的held-out集、置信区间、还专门做了污染对照——证据分级里最高的一档。
官方evals页的0%结构化错误率
官方自己承认「not empirical」,只是因为schema保证了格式合规,就把0%画进了图里。
差别在于谁在验证、拿什么方法验证——同样挂着校准相关的字眼,一份是外部自费、方法可核对的独立测量,另一份是厂商自己承认不算实测的一句自信。
这个0%,测出来的还是推出来的?
官方那张结构化输出错误率图上,Jev的错误率标着0%,是所有模型里唯一一个整数0。你觉得这个0%是拿真实调用统计出来的,还是靠别的方式定下来的?
答完再看
官方原话是这个数字不是实测的,schema匹配是被保证的,所以可以放心把0%画进图里——这个0%不是统计出来的,是从格式被强制保证这件事直接推出来的。
第10章你已经用双轨记分板把这件事拆得很细:格式合规率和决策正确率,是两条各自独立记录的线,一个模型完全可以同时是100%格式合规和17%决策错误。这一节要补的是另一层——图上其余模型的错误率来自OpenRouter的调用统计,跟Jev四个workflow的evals表是两组互不相干的实验,参赛模型的组合都不一样,官方把两组不同来源的数字画进同一张图,容易让人以为它们是在同一套测试条件下比出来的。
Jev的0%:从规则推出来
schema强制约束决定了返回值只能落在合法选项集合里,格式错误在定义上不可能发生,这一列不需要跑一次调用就能先写下来。
假设某模型的0%:从调用统计出来
跑了一批真实请求,统计下来错误次数恰好是0——这一列的0%依赖样本量有多大,样本不够多,恰好0次也可能只是还没撞上那一次。
两种0%画在图上长得一模一样,但能推翻它们的证据完全不同:前一种只要schema约束没被绕过就一直成立,后一种只要多跑几次就可能冒出第一次错误。
Jev的0%和luna的0.58%,画在同一张图上,能不能直接拿来比大小?
如果luna也做到了schema强制保证,它的错误率理论上应该变成多少?这和它实测的0.58%矛盾吗?
一个决策模型批准了一笔不该被批准的操作,但返回的JSON格式完全正确、字段一个不少。这次调用,算不算进结构化输出错误率?
如果这次错误批准之后被人工发现并记录,这条记录该算进哪一条统计线?
把0%结构化输出错误和不会幻觉这两句话画上等号,会漏掉什么?
如果某个场景的决策错误恰好也总是伴随着格式错误,这时候0%格式错误是不是就能反过来推出决策也不会错?
不靠它,得标多少条才追得上?
零样本听起来像是免费的智能——不用标注一条数据,直接就能用。你觉得,一个专门训练过的小模型,需要标多少条数据,才能追上Jev不训练直接给出的零样本水平?
答完再看
第15章你已经算过这条学习曲线:AG News这个任务上大约231到336条标注就能追平;Banking77上追平需要238到1338条不等;而SST-2、TweetEval-emotion、PAWS这三个场景,喂了超过2048条标注,专门训练的模型依然没追上Jev的零样本水平。
这条学习曲线,把Jev是不是被过度神化的新范式这个立场问题,换成了一个能拿真实预算去回答的工程问题——你的标注预算,够不够标满这条曲线追平所需要的条数。答案不是一句值或不值,是看任务。
AG News:追平门槛低
大约231到336条标注,专门训练的小模型就能追上Jev不训练直接给出的零样本水平,零样本在这个任务上占不到太大的便宜。
SST-2/TweetEval-emotion/PAWS:追平门槛看不到头
标注量已经喂到2048条以上,专门训练的模型依然没有追平Jev的零样本水平。
同一句「零样本值多少钱」,换一个任务能差出十倍以上的标注量——脱离具体任务单独问值不值,问不出一个能拿去用的答案。
SST-2这个任务上,专门训练的模型标了超过2048条数据,追上Jev的零样本水平了吗?
如果预算只够标注500条,这500条落在SST-2还是AG News上,更有希望追平?
某个团队要做一个七分类任务,标注预算只够标100条。按已经测过的几个场景类推,这100条能追平Jev的零样本水平吗?
如果这个团队的任务恰好接近Banking77,100条标注够不够?还需要额外考虑哪个复杂因素?
如果Banking77在两种不同的基线模型下,追平所需要的标注条数分别是238条和1338条,相差将近六倍,这说明标注等价量这个数字本身,是一个固定不变的常数吗?
如果你的团队已经有一套现成的、更重的基线模型可以直接拿来微调,追平Banking77该参考哪一个数字?
说它是营销,这句话站得住吗?
官方发过一篇专门的博客,解释为什么不公开跑公共榜单,标题带着antibenchmaxxing这个词。你觉得这篇博客的论证,是一个站得住的技术论点,还是一句给藏着掖着找的借口?
答完再看
这篇博客的论证是:只要模型开发者能看到一个公开榜单的分数,就会不自觉地朝着这个榜单调优,哪怕没人存心作弊——基准会挑选模型,即便没有人存心去打这个基准。这个论点后来被材料里的另一份独立发现证实了。
证实它的是那份独立评测里的污染对照:deberta-v3-large-zeroshot-v2.0这个零样本模型,在AG News上的零样本分数是0.901,同一个架构、但训练数据没见过AG News的干净版本,只有0.763——0.901这个漂亮数字,很大一部分来自它训练时见过这份数据,不是真的泛化能力强。而Jev用发布之后才出现的arXiv新论文做污染对照,分数只掉了0.035,置信区间盖住了0,看不出被背过的痕迹。
deberta-v3-large-zeroshot-v2.0的0.901和它干净版本的0.763,同一个模型架构,差了0.138。这个差距能不能说明这个架构比Jev更强?
如果一份评测完全不说明训练数据是否包含了测试用的公开数据集,你该用什么态度看待它报出的零样本分数?
这不是说这篇博客的每一句话都无可指摘——它同时也是一个方便的说法:不公开成绩,外界就没法直接核对Jev在MMLU这类大家都懂的榜单上到底排第几。论证站得住,和这个论证被拿出来的时机对自己有利,是两件可以同时成立的事。
论证本身:有独立证据撑腰
公开数据集容易被训练污染、零样本分数虚高,这一点被独立评测的污染对照实测证实了,不是官方自说自话。
论证的时机:对说这话的一方有利
不公开跑MMLU这类公共榜单,外界也就没法直接核对Jev在大家都懂的榜单上排第几——这句话同时也挡掉了一种最直接的核对方式。
论证站不站得住,和这句话说出来对谁有利,是两条互相独立的判断线:第一条已经被独立证据验过,第二条依然成立,两条线不矛盾,也不能互相替代。
官方拒绝公开跑MMLU这类公共榜单这件事本身,能不能被当作Jev能力不行的证据?
如果独立的污染对照没有找到、或者结果相反,这一节的结论会不会需要修正?
答辩:如果我是审稿人
antibenchmaxxing这篇博客的论证被污染对照证实了,是不是意味着往后但凡有公司说我们不公开跑公共榜单,都该被相信?
参考防守(先自己组织语言再看)
不是。这一次能采信的是这条具体论证被独立证据支持了,不是所有拒绝公开榜单的公司都自动获得同样的信任——七个问题里的每一个,都要对着新出现的那份材料重新问一遍,不能因为Jev这一次站得住,就把整套信任提前预支给下一家公司。这正是第16章开头就该立住的规矩:判据可以接着用,结论不能。
这一级要加什么:把前十五级接成一条流水线
为什么现在才加它:前十五级各自是一台独立的仪表——概率检查器、ECE计算器、阈值求解器、级联路由器、双轨记分板……这一级要做的不是新增一台仪表,是给它们接上统一的输入输出,让读一份发布材料这件事从凭印象变成按清单过。
难点:这七个检查函数不是并列的七个独立小工具——calibration这一格要用到第5章的ECE计算器和第9章的温度缩放器才能跑;ratioBase这一格要用到第12章的成本模型才能算出理性基线下的倍数。七个问题看着是一张平铺的清单,底下接的却是一棵有依赖关系的调用树,少了任何一级地基,上面对应那一格就只能空着写缺数据,不能瞎编一个答案。
自己验:把Jev发布材料的七组数字喂进这个函数,groundTruth那一格应该判定为参照系是模型平均、不是人工标准答案,该标一致率不是准确率;ratioBase那一格应该同时吐出三个数——对sonnet5约293倍成本优势、对opus5约94倍速度优势、对DeepSeek V4.1 Flash约1.6倍——而不是一个笼统的N倍;calibration那一格应该判定为官方零数值、第三方zhuyansen给出过独立的ECE表。跑一遍这七格,只要这三处和上面这几句吻合,这条流水线就接对了。
留给你的问题
下一次你看到一个新模型说比谁快多少倍,在划走之前,这七个问题里,你会先问哪一个?为什么是那一个,不是排在它后面的那几个?
不看材料,写下这一章最容易被忽略的三件事
第一件:官方自己承认过的局限,比如零个校准数字,很容易被当成这个模型不校准的证据,但查无实据不等于已经证伪,第17章会正式处理这条界限。第二件:一张对比表只要出现多个模型,看起来就不像循环论证了,但真正要看的是定义参照系的那个模型,在不在参赛名单里。第三件:拆穿一个营销说法和证实一个站得住的论证,用的是同一套追问方法——七个问题问出来的答案,可能是这条不成立,也可能是这条反而被证实了,antibenchmaxxing那一节就是后一种结果。
第17章 这个模型没告诉你的事
第1章留过一句没说完的话:到今天为止一条数据都没有的断言,写「查不到」,不用先验去补——这一章专门回来清点这份清单。清点的对象有两份:BRIEF自己列的十条,和另一份研究材料自己挑出的「最该写进这个模型没告诉你的事」的五条。这一章要做的不是把这十五条原样誊抄一遍,是把每一条重新查一遍——材料会不会其实说了,只是说在别的章节里;或者虽然没直接说,却能从别的证据推出来。查完你会看到,多一半已经被材料自己推翻或者部分推翻,真正到今天还查不到的只剩几条,这一章会把它们如实交代清楚,也交代清楚「查不到」和「已经被证明是假的」,不是一回事。
学完这一章你应该能做到
- 拿到一条「材料没有数据」的断言,先自己动手查一遍全站和原始材料,再判断这究竟是真空白还是没查全
- 分清一句话是能被逐字圈出来的引文,还是接了自己判断的推论,推论必须标注,不能当引文用
- 认出「查无实据」和「已经被证伪」是两句不同的话,不把沉默当成否定的证据
- 看同一张评测表,既会算总分怎么合出来的,也会逐项去找当项最强的对手比一比,两个角度可能讲出不同的故事
这一级要做的不是新查一遍材料,是把「查无实据」这四个字,从一句可以随手写下的结论,变成一个自己能动手复核的动作。上一级教会你带着七个问题去读一份新材料;这一级教会你,对着「这件事材料里没有」这句话本身,也要走一遍同样的核对流程——查过哪里、有没有可能说在别处、能不能从别的证据推出来,走完这三步,才轮到真的写下查不到。
这句话,是推论,还是引文?
如果这一章要写下「Jev不适合用在受监管行业的合规场景」这句话,你觉得材料里能不能直接找到一句官方原话,白纸黑字这么说?
答完再看
另一份研究材料对这一条的处理方式很诚实:关于Jev加受监管行业合规,没有找到任何律师、合规人员或监管机构的具体分析——这句结论是从官方自己承认的限制推出来的,写进网站时必须标明这是推论。这一节要拆开的,就是「推出来」这三个字具体怎么一步步走。
先看能被逐字圈出来的那一句。Langfuse拿Jev做过实测,写下的原话是:「Jev is not trained to generate text, so when a trace scores badly it never provides a reasoning」——这句话能在Langfuse发的实测记录里逐字对上,作者是谁、发在哪、哪一句,全都能核实,这是一句引文。Langfuse接着又写下一句判断:这一点「prevents explanation-dependent auditing」,阻碍了依赖解释才能完成的审计——这仍然是Langfuse自己的原话,还在引文的范围内。
「Jev is not trained to generate text, so when a trace scores badly it never provides a reasoning」这句话,算引文还是推论?
如果把这句话翻译成中文再写进正文,还算引文吗?
「受监管行业的合规场景,恰好最依赖解释能力才能过审计」这句话呢?把它接在Langfuse那句后面念,读起来像顺理成章的下一句,但没有任何一处材料这样直接写过——受监管、合规、审计这几个词,是这一节自己接上去的,接的依据是对审计惯例的常识理解,不是某一处能被圈出来的原文。这一步就是推论:从两句站得住的引文出发,多走一步逻辑,落到一句原文里没有的新结论上。
这道检查有个可以随身带走的问法:这句话,能不能在某一份具体材料的某一处被逐字圈出来?圈得出来,标引文;圈不出来、需要自己把几句已知的话接起来才能得到,标推论。两种都可以写进一份可信的判断,区别只在于,推论必须挂着推论这块牌子,不能借引文的名义蒙混过关——这道检查,姑且就叫它「圈得出来吗」。
TypeSafe的CEO在Hacker News上被问到RLCD的架构细节时回答:「architecture is close to the chest for now, but we have talked about writing a paper」。如果这一章写下「TypeSafe目前没有发表过一篇讲RLCD细节的论文,只是谈过要写」,这句话是推论还是引文?
如果把结论改写成「TypeSafe不公开架构,是担心这套方法一经公开就会被发现和三篇更早的论文高度相似」,这句话还是引文吗?
查无实据的条目,今天还查不到吗?
BRIEF清点「查无实据」的时候,排在最前面的两条是:官方有没有公布过四个workflow各自用了多少道题,官方evals有没有给过置信区间或误差棒。你觉得,到今天,这两条是不是还查不到?
答完再看
第11章已经替你查过这两条:官方评测表从来没有公布过每个workflow用了多少道题,也没有给出任何置信区间或误差棒——原句就是这么写的。答案依然是没有,但从没人确认过没有,变成了已经确认没有、写明在哪确认的,这中间隔着一步核实的工作。
第16章又把这条往前推了一步:样本量不明的时候,哪怕两个模型的一致率——和参照模型给出的共识答案相符的比例,不是人工核对过的正确率——只差0.1个百分点,也没法判断这差距是真实存在还是抽样噪声,这条道理直接靠在案例数量查不到这件事上,两章说的是同一处空白的两层后果。
只写着一句查无实据,没有说明是在哪一份文件、哪一段查过的,也没有留下能重新核对的路径。
同样的结论没有变成有数字,但多了具体在哪一句原文查过、原文怎么说这两层信息,别人可以顺着这条路径自己再核一遍。
两栏最后写下的都是没有这个结论,差别在于这个没有背后,有没有留下一条能让别人重新核对一遍的路径。
第11章那句「官方评测表从来没有公布过每个workflow用了多少道题」,回答的是BRIEF清点的第几条?
如果官方后来只公布了四个workflow的总案例数、没有拆开到每一项,算不算把第一条补上了?
把「四个workflow各自的案例数量」和「官方eval有没有置信区间」这两条重新归档,应该归进证据分级五档里的哪一档,还是归进第六档查无实据?
如果官方只给出了总样本量、没有给置信区间,这条该不该从查无实据挪到别的档位?
同一份清单里还有两条,情况也类似。193.6倍、444.6倍这两个数字背后,没有舍入之前的原始值,官方没有公布过——第16章已经用官方公布的舍入值反推过,算出来的195.2倍和440.2倍,和首页写的对不上,第12章的成本模型里也有同样的核对。至于「0.72加0.47等于1.19」这条,第1章整整一章都在讲它,从工单原文到归一化的陷阱,没有比这更详细的处理。
「0.72加0.47等于1.19」这条,第几章整章都在处理它?
如果把1.19除回1,这一步能不能反过来证明官方这个数字本来就没问题?
还有一条,情况又不一样:首页那对0.114秒和8.566秒的演示数字,具体测的是哪个工作负载,官方没有直接说过。但官方另一处的自我提醒里,两条线索能拼出一部分:对照模型被点了名,是GPT-5.6 Terra,默认推理设置,官方说这是因为在他们看来这个模型和Jev的智能水平最接近;查询本身的形状也被自己点破——问题被大幅简化过,state是一段简短、密集的文字,官方自己写明这样的输入形式对自己的模型更有利。对照模型是谁、查询大致的样子,能推出来;查询原文写的什么,推不出来——这条不属于彻底查不到,也不属于已经查清楚,是卡在中间的一种状态。
只凭对照模型是GPT-5.6 Terra这一条线索,能不能推出0.114秒和8.566秒这两个数字本身有没有被夸大?
如果官方某天公开了这次演示的完整查询原文,这条记录应该从「可推出一部分」改成哪一种状态?
总分打平,为什么四个workflow全部告负?
Jev总分67.8%,和sonnet5的67.8%完全打平——这是官方evals表上的一致率。如果把这67.8%拆开,按四个workflow分别去找当时一致率最高的那个对手比一比,你觉得Jev能在几个workflow里反超?
答完再看
官方§7的原始表格逐项列着:Security Incidents一致率Jev 61.7%,当项最高的是opus 5的66.2%;Agent Trace Observability,Jev 71.6%,当项最高的是sol的76.6%;Invoice Processing,Jev 61.8%,当项最高的是sol的79.1%;Customer Service,Jev 76.0%,当项最高的是sol的78.3%。四项,Jev一项都没有反超当项最高分。
把四项差距摆出来:Security Incidents差4.5个百分点,Agent Trace Observability差5.0个百分点,Invoice Processing差17.3个百分点,Customer Service差2.3个百分点。第11章已经拿总分和那句「similar levels of intelligence」对照过四项内部最多14.2个百分点的差距;这里要看的是另一个方向——不是Jev自己四项之间的差距,是每一项分别对着当项最强的外部对手,差多少。
Customer Service这一项,Jev一致率76.0%,当项最高的是sol的78.3%。这两个数字的差距是多少个百分点?
如果换成opus 5(72.4%)当对照,Jev在这一项反而变成领先了吗?
Agent Trace Observability这一项的差距,值得多停一步。另一份研究材料把这一项的差距写成4.5个百分点:如果用luna的76.1%去对照Jev的71.6%,算出来正好是4.5——但luna不是这一项四个对照模型里一致率最高的那个,sol的76.6%才是;换成sol重新算,差距是5.0个百分点,不是4.5。这0.5个百分点的误差不大,但正好示范这一章要教的规矩:连一份写得足够仔细、大部分数字都核对得上的批评材料,它自己的减法也值得重新算一遍,不能因为来源看起来严谨,就跳过验证这一步。
67.8%和sonnet5的67.8%打平,读起来像是一场势均力敌的较量。
每一项分别比,Jev一项都没有反超当项最高分,差距从2.3到17.3个百分点不等。
两个说法都没有算错,差别在于等权平均这个合成方法本身的性质——第0章讲过,整体打平不保证任何一个局部都打平,总分和分项,讲的是两个不同层面的事实。
如果有人说「Jev总分和sonnet5打平,说明两者在每个workflow上的一致率也应该差不多」,这句话哪里站不住?
如果四个workflow换成不等权重(比如Invoice Processing权重更高),Jev和sonnet 5的总分还会打平吗?
Jev在四个workflow上一项都没有反超当项最高分,这是不是说明总分67.8%这个数字本身有问题,是被算错了?
如果官方在发布页上,除了总分之外也把四项逐一拆开列出来,还会有这一节说的这层误读吗?
立场问题,材料给出工程答案了吗?
首页说Jev比opus 5便宜444.6倍,另一份研究材料算出来,对着一个更合理的基线,优势只有1.6倍。这两个数字,有没有可能同时是对的?
答完再看
两个数字对的确实是不同的基线:444.6倍算的是对opus 5这个当时最贵的对手;1.6倍算的是对DeepSeek V4.1 Flash这个理性基线——第12章和第16章都已经把这条核对路径走过一遍,结论是同一句话:任何N倍的宣称,先问分母是谁。
同一个问题牵出的其它几条追问,材料也已经给出了工程意义上的答案,不停在立场判断上。第10章处理的是Jev能不能说「我不知道」——三个独立来源(Langfuse实测、HN用户bigglebear、知乎电车难题实验)互相印证:一道强制二选一的题,Jev不会拒答,会在给定选项里挑一个最不离谱的答案;知乎那组实验还往前多走了一层,模型自己的训练痕迹会压过写明的指令。第16章处理的是零样本值多少条标注——答案要看具体任务,从231条起步到超过2048条不等,不是一句简单的值或不值。
opus 5是首页选的对照,每案例0.1761美元,是当时能找到的最贵对手之一,算出来的优势数字最好看。
换成一个不追求最贵、追求合理够用的基线模型,价格优势立刻从444.6倍塌缩到1.6倍。
差别不在算术,在基线选谁——同一个Jev,同一天发布,换一个分母,倍数能差出将近三百倍。
Langfuse实测、bigglebear的评论、知乎的电车难题实验,这三个各自独立的来源,共同印证的是哪一条结论?
如果给Jev的选项里额外加一个other,这三个来源的结论会不会需要修正?
「零样本值多少条标注」这条,第16章给出的答案大致是什么范围?
如果某个任务追平只需要50条标注,这个数字会不会推翻第16章的结论?
校准没数字,RLCD有没有自己的论文?
官方多次用RLCD这个名字描述Jev的训练方法,还专门写了一段介绍它的设计目标。你觉得,材料里有没有一篇TypeSafe自己发表的、讲RLCD具体细节的论文?
答完再看
TypeSafe的CEO在Hacker News上被直接问到架构细节,回答是:架构目前不公开,「we have talked about writing a paper」。谈过要写,和已经发表,是两件事,到今天为止,后一件没有发生。
这条和第2章处理过的问题不是同一件事,需要分开放。第2章的答辩追问的是RLCD算不算一条真正的新路——那里引用的是三篇更早的学术论文,用来质疑这个方法本身是不是旧工作换了个名字。这一节要确认的更窄:不是这个方法新不新,是TypeSafe自己有没有发表过一篇讲清楚实现细节的论文——查到的答案是没有,只有一句谈过要写。
第16章已经确认过,874KB的官方文档全量转储里,这几个校准领域的标准指标全部零命中——这条已经被写清楚查在哪、查到了什么。
同样是零命中,但到目前为止没有任何一处材料专门写过这一条——CEO那句谈过要写,是唯一能找到的相关原话。
两栏都是没有,但第一栏已经在第16章被正式确认、记录在案,第二栏是这一章第一次把它单独挑出来查。
第2章那道答辩题,引用了标题叫「Calibration Aware Reinforcement Learning」的论文,质疑RLCD凭什么算第三条路。这道题追问的是RLCD新不新,还是TypeSafe有没有发表自己的论文?
如果TypeSafe某天真的发表了一篇RLCD论文,第2章那道答辩题会因此失效吗?
既然RLCD这个方法已经有具体的训练目标、官方也给出了定义,为什么材料里的校准数字(ECE、Brier)依然一个都没有公布?
如果官方某天补发一组自己测的ECE数字,这一节的结论会不会需要修正?
有机制的地方,一定有人测过曲线吗?
第13章已经证明了一条机制:state里混进跟当前判断无关的内容,会拖累准确率,这个现象叫context rot。你觉得,材料里有没有一条曲线,具体量出Jev在真实多轮对话里,准确率会随着轮数增加掉到多少?
答完再看
到今天为止,没有任何官方或第三方材料专门测过Jev在长多轮对话上的退化曲线——这一条另一份研究材料自己也确认过,专门标了一个问号。机制成立和曲线被量出来,是两件事:前者第13章已经讲清楚了,后者到目前为止没人做过。
同一类「没人做过」还有一条,说的是另一个方向:没有任何第三方重新跑过官方那张四workflow的评测表——一个都没有,Arize说过要做,还没有做完。这不是说第三方完全没有测过Jev,zhuyansen测过7个分类数据集的ECE、Good Start Labs测过成本、Near Here测过活动审核任务,这些都是扎实的独立证据,第9、12、16章都用过。缺的是最直接的那一种验证:拿官方那四个workflow本身,原样重新跑一遍,看数字能不能复现。
zhuyansen的7个分类数据集、Good Start Labs的成本对比、Near Here的活动审核任务——三份独立证据,自费或早期访问,分级表里靠前的几档都有。
一次都没有——官方那张最核心的评测表,到今天为止没有被任何独立第三方原样复现过。
独立证据本身不缺,缺的是最直接对着官方最核心那张表做的复现——这两件事容易被读成同一类第三方验证,其实是两类不同强度的证据。
context rot这个词,第13章证明的是一条机制,还是一条随轮数变化的曲线?
要把这条机制变成一条真正的退化曲线,还缺哪一类数据?
如果某天Arize真的发布了一份重跑官方workflow表的报告,这份报告应该归进证据分级五档里的哪一档?
如果Arize这份报告是TypeSafe出钱委托的,归档会不会不一样?
官方承认的方向,和官方公布的数字,是一回事吗?
官方文档里有一句专门讲其他语言的话。你觉得,这句话里会不会带一个具体的准确率数字,比如中文准确率比英文低多少个百分点?
答完再看
官方原文大意是:英语是主要训练语言,目前准确率也最好;包括中日韩文字在内的其他语言,能处理,但处理得不如英语好,建议在自己的内容上先测一遍再决定要不要把Jev用在非英语的工作负载上,路由的时候多留意confidence这个字段。方向写得很清楚——更差,但没有一个数字告诉你差多少。
这条要和第13章那道32000 token中文预算的研究题分开放,两个问题问的不是同一件事。第13章问的是容量:同样32000个token,中文文本大概能装下多少个汉字,这个数字可以自己拿一个通用分词器估算出来。这一节问的是准确率:中文工单让Jev去判断,答对的比例会不会比英文工单低、低多少——这个数字没有一个分词器能帮你估,只能真的拿一批有答案的中文数据去跑一遍才知道。
其他语言,包括中日韩文字,处理得不如英语好——方向写得清楚明白。
没有一个具体的百分比,没有一份专门的非英语评测——方向之下没有跟着任何数字。
承认方向,不需要暴露任何模型细节;公布数字,需要真的跑一批非英语评测——官方走完了成本几乎为零的第一步,没有走成本更高的第二步。
对你而言未知中文场景下的准确率,具体比英文低多少
官方承认了方向——非英语表现更差,也点名了中日韩文字——但没有给出任何数字,到目前为止,也没有任何第三方材料测过这件事,不管是把官方评测的四个workflow换成中文重跑一遍,还是另找一批中文分类任务。这不是没人能测,是没人测过。
先做这一步:挑一批已经有人工标注过正确答案的中文工单(哪怕只有几十条,类型接近第16章那种客服或工单场景),调用Jev跑一遍,把它给出的答案和人工答案做比对,算出一个准确率,再和官方英文workflow上67.8%这个数字摆在一起,看差距有多大——这一步做完,才是能确认「差多少」而不是只能确认「更差」的时刻。
同一批查无实据里,还有一条形状不太一样:sol和luna到底属于GPT-5.6还是GPT-6这一代,不是没人研究,是这件事本身没有一个公开对应关系。媒体文章里两种写法都出现过,互相冲突;官方自己从发布到现在,只用sol、luna这样的小写短名称呼它们,没有确认过任何一个具体的代次归属。读者今天想判断sol、luna到底算多先进的一代,没有官方口径可以直接引用。
「sol和luna属于哪一代」这条查无实据,和「Jev在中文上准确率具体是多少」这条查无实据,缺的是同一类东西吗?
如果某个媒体第一个报道了sol属于GPT-6代次,这个说法能不能直接当成查无实据已经被补上了?
第13章那道研究题问的是32000个token能装下多少个汉字,这一节的研究题问的是中文准确率比英文低多少——这两道题问的是同一类问题吗?
如果中文的token效率比英文低,会不会同时影响这两道题的答案?
十五条查完,能不能说这是一场营销?
这一章清点了十五条BRIEF和另一份研究材料列出来的疑点。把BRIEF那十条和这一章新查到的几条放在一起数,超过一半到今天依然查不到——如果只看这个比例,能不能说Jev这次发布整体是一场包装?
答完再看
第16章章末已经留下这句话:查无实据不等于已经被证伪。十五条里,真正到今天还查不到的只有几条,而且每一条查不到的原因都不一样——有的是没人做过这件事(多轮退化曲线、第三方重跑workflow表),有的是命名本身没有公开对应关系(sol/luna代次),有的是官方给了方向、没给数字(非英语表现)。把这几条查不到的性质摆开看,找不出一条共同的、指向故意隐瞒的线索。
查无实据的条目过半,直接推出这次发布整体不可信,是一种立场先行的判断。
每一条分别去看缺的是什么、能不能补、谁来补,十五条给出的不是一个统一结论,是十五条各自独立的核对结果。
同样十五条清点结果,读成立场会导向一句话就能说完的结论;读成判据,导向的是下一次遇到新材料时,具体知道该去查哪一步。
把BRIEF清点的十条摆进两张表,逐条给出今天的状态:
| 条目 | 状态 | 查过哪里,结论是什么 |
|---|---|---|
| ①四workflow案例数量 | 已核实为空白 | 第11章:官方从未公布 |
| ②eval置信区间/误差棒 | 已核实为空白 | 第11、16章:官方未给出 |
| ③校准曲线/ECE/Brier/RLCD论文 | 前三项已核实,后一项仍查无实据 | 第16章:转储零命中;本章:CEO只说谈过要写 |
| ④193.6x/444.6x未舍入原始值 | 已核实为空白 | 第12、16章:按舍入值反推对不上 |
| ⑤首页0.114s/8.566s对应负载 | 可推出一部分 | 本章:对照模型与查询形状可查,原文不可查 |
表17-1里,哪一条的状态既不是已核实为空白,也不是查无实据,是一个中间状态?
如果哪天官方公开了这次演示用的完整查询原文,第⑤条应该改记成哪一种状态?
后五条状态如下:
| 条目 | 状态 | 查过哪里,结论是什么 |
|---|---|---|
| ⑥第三方重跑workflow表 | 查无实据 | 本章:一个都没有,Arize说过要做未完成 |
| ⑦非英语(含中文)表现数据 | 查无实据 | 本章:官方只承认方向,无任何数字 |
| ⑧长多轮对话退化曲线 | 查无实据 | 本章:机制已证明,曲线没人量过 |
| ⑨confidence计算公式 | 查无实据(已登记) | 第1章已开成研究题,不重复求解 |
| ⑩sol/luna属于哪一代 | 查无实据 | 本章:媒体写法冲突,官方无公开对应 |
表17-2里,第⑨条标注着已登记,这是什么意思——和其余几条纯粹的查无实据有什么不同?
如果第1章那道研究题后来被某个第三方解出了confidence的具体公式,第⑨条的状态还会是查无实据吗?
另外五条来自那份研究材料自己挑出的「最该写进这个模型没告诉你的事」——1.19那道加法归到第1章,四项workflow全部告负归到这一章第3节,444.6倍的分母归到第12、16章,不能说不知道归到第10章,零样本值多少条标注归到第16章。五条里,四条已经被材料自己推翻,一条(全部告负)本章第一次用官方原始数据把它坐实,没有一条停留在原来的立场判断上,全部落到了具体查哪、具体算什么这一层。
答辩:如果我是一个坚持这就是场营销的批评者
这一章把BRIEF和另一份材料清点的大半条疑点都推翻或者部分推翻了,这是不是说明这个学习站在帮Jev洗白?
参考防守(先自己组织语言再看)
被推翻的是「材料没说过」这句话本身,不是「材料说了之后这件事对Jev有利」这句话。被推翻的几条里,有的推出来对Jev不利——四个workflow全部告负就是这一章自己新查出来的一条,方向明显不利;有的是中性的事实澄清——零样本值多少条标注,答案是看任务,谈不上利好还是利空。判断一条要不要推翻,用的自始至终是同一个动作:查、写清楚在哪查到的、不用先验去补,这个动作不看结论对谁有利,只看材料本身有没有说过。
读的时候要小心
可推出一部分,不等于已经推出全部
表17-1第⑤条,首页0.114s/8.566s对应的负载,这一章能确认的只是对照模型是GPT-5.6 Terra、查询被简化过、state是一段简短的段落——这几层信息,都是从官方自己承认「对自己有利」这句限定和对照模型说明里拼出来的,没有一处能让你看到查询本身的原文。把「可推出一部分」读成「已经知道这次演示测的是什么」,会把这一章反复强调的边界又混回原来的模糊地带。
留给你的问题
如果下一次有人拿着一份新模型的发布材料,指着一句「没有找到关于X的任何数据」来说服你这家公司在刻意隐瞒,你会先问哪一句话,才能判断这究竟是空白,还是已经被证伪?
不看材料,写下这一章最容易被忽略的三件事
第一件:一句话在材料里找不到原文,不代表它是编出来的,先查它能不能从别的已经确认的话推出来,推出来的话必须标推论,不能当引文用。第二件:查无实据是关于有没有证据的判断,不是关于结论好坏的判断,一条清单上没有数字的条目越多,越应该分别去看每一条缺的是什么,不能把它们合并成一个故意隐瞒的印象。第三件:一份研究清单本身也是某个时间点的产物,材料在持续变多、变细,今天查无实据的条目,随时可能在下一章、下一份独立评测里被填上。
这一级要加什么:未知登记册
为什么现在才加它:前十六级都在教怎么核实一句已经写出来的断言,这一级要处理的是反过来的情况——一句「材料没有数据」本身,也是一句断言,也需要被核实,不能因为它的内容是「没有」就默认它天然成立。登记册要做的,是把已验证、可推出、查无实据这三种状态,从一句随口的判断,变成一个能被反复调用、能被继续补充的结构。
难点:三种状态里最容易被用错的是可推出——它要求登记的不是推出来的结论本身,是推出这个结论具体用了哪几句已知的话、哪一步逻辑,少了这一层,可推出会悄悄退化成一句听起来有依据、实际查不到路径的推论,和查无实据在效果上没有区别。已验证这一档也不能只记结论,要记住是在哪一章、哪一句原文核实的,不然下次有人质疑,答不出证据在哪。
自己验:lookup("案例数量")应该输出以「已验证」开头、带着ch11字样的字符串;lookup("非英语")应该输出以「查无实据」开头的字符串;lookup("今天早饭吃了什么")这种登记册里完全没有的问题,应该原样输出「登记册里还没有这一条,需要新查,不能顺手填一个状态」,不能编一个「查无实据」或者「已验证」出来敷衍了事。
第18章 真的把它接上:从curl到生产
前面十七章教的是怎么判断一份材料、一张评测表、一个模型值不值得信——这一章换一个问题:真的要把Jev接进一套系统,代码长什么样。从会判断到会用,中间差的是一整层接入细节:官方接口怎么发、两个官方SDK怎么写、四个第三方平台各自把字段名改成了什么、生产环境要守哪几条硬规矩。这一章的代码取自原始文档,字段名、类名、参数结构逐一核对;例子里跟上一段重复、或者前面章节已经讲过的部分,用「……」省略掉,省略的只是重复内容,没有一处字段名或者逻辑被改写。
学完这一章你应该能做到
- 照着文档把一次真实的HTTP请求发出去,认出四种错误码分别对应什么
- 看懂官方Python/JS SDK的两套写法,也看懂OpenRouter、Cloudflare、Vercel AI SDK各自把字段名改成了什么
- 把一个模糊的判断拆成几个可观察的信号,照官方给的这几条原则走一遍,不是凭感觉多问几句
- 认出哪些活儿不该扔给Jev做——数数、算术、比日期、生成文字——一犯就是官方自己列出来的九条反模式之一
这一级要造的是一台真实请求构造器:输入一段业务场景描述,吐出一份能直接发出去的请求体——questions怎么拆、criteria怎么写、用哪个SDK、部署到生产前要检查哪几条。前面十七级教会你怎么审视别人发布的数字,这一级教你自己动手,把判断力真的接成一套能跑的系统。
一次POST请求,请求头和错误码分别长什么样?
第3章已经拆过state/model/questions这三个字段各自装什么、Noul/Choice/Score各自怎么读。这一节接上另一半:这些字段要装进一个真正能跑起来的HTTP请求,请求头、认证方式、出错时的状态码,长什么样。
这段命令原样能跑:地址是POST https://api.typesafe.ai/v1/systemone,认证走标准的Bearer token,写在Authorization请求头里;Content-Type是application/json。第3章已经拆过department、frustration、is_urgent这几个问题各自怎么读,这里不重复。
上面这段curl命令里,负责认证的是哪一行请求头,负责告诉服务器请求体是JSON格式的又是哪一行?
-H参数里找,一行带Bearer字样,一行写着某种格式名称。Authorization: Bearer $TYPESAFE_API_KEY负责认证;Content-Type: application/json告诉服务器这是JSON请求体。如果漏写Content-Type这一行,请求大概率会撞上401还是422?
出错时的状态码,文档写明四种:401(认证失败)、422(请求体不合法)、429(超出速率限制)、以及一个不常见的529 Overloaded——HTTP标准状态码里没有529,这是TypeSafe自己定义的一个,专门表示服务本身过载,不是你的请求有问题。速率限制是250,000 token每秒、1,200次请求每分钟,超限返回429,官方原话写明「限制会随时无预警变动」,不能把这两个数字写死当成长期不变的配额。
收到一个529响应,说明是你的账号超出了速率限制,还是服务本身在过载?如果是前者,应该收到的是哪个状态码?
如果一次请求同时超出了token预算又撞上了服务过载,你觉得会优先返回哪一个码?材料里有没有说明这一点?
两个官方SDK,写法差在哪?
先看Python SDK:pip install typesafe-sdk,默认读环境变量TYPESAFE_API_KEY。
response.answers这同一个字典里,按各自的key取出来的,还是分别放在三个不同的字典里。上面这段同步调用里,department、frustration、is_urgent三个答案,是从三个不同的字典里各取一个,还是都从response.answers这一个字典里,按各自的key去取?
print里,response.后面跟的属性名,是三种不同的写法,还是同一种写法。response.answers这一个字典里取,只是key不同——response.answers["department"]、response.answers["frustration"]、response.answers["is_urgent"],统一按question自己起的key对号入座。如果questions里把is_urgent这个key改成urgent,取值那行代码要不要跟着改?
异步客户端的例子,取值换了另一套访问器:
同一个Python SDK,quickstart文档用response.answers["department"],异步示例用response.nouls["billing"]——这是两个不同版本的SDK,还是同一个版本里并存的两种写法?
typesafe_sdk这同一个包导入,只是一处按question的key统一取(answers[key]),另一处按问题类型分开取(nouls[key]/choices[key]/scores[key]),两种访问器同时存在,混着记容易在换项目时写错。如果一个question的类型是Score,用response.nouls["urgency"]去取,会发生什么?
JS/TS SDK,npm install @typesafe-ai/sdk,需要Node 20以上:
Python SDK用大写的Choice/Noul/Score这几个类,JS/TS SDK用小写的choice()/noul()/score()这几个函数——这个差异,是两个SDK在描述不同的东西,还是同一件事在两种语言里的惯用写法?
如果照抄Python的写法,在JS里写Choice(...)(大写开头),这段代码会正常工作吗?
同一个模型,换个平台,字段名怎么变?
如果你已经写好了一段调用官方Python SDK的代码,现在要把同样的逻辑搬到Vercel AI SDK上跑,你觉得能不能只把import语句换一下,其余原样照搬?
答完再看
Vercel官方知识库自己点出这是最大的一处命名分歧:第三种问法被叫成boolean而不是noul,返回字段叫probability而不是noul,而且confidence不在answer上,要从result.providerMetadata?.typesafe?.confidence里单独取。跨平台移植代码,这里最容易踩坑。
OpenRouter是第三方托管,模型slug是typesafe/jev-1.13或~typesafe/jev-latest,定价$0.042/M输入、$0/M输出,32K context——但它不走大多数人熟悉的chat completions接口,是一个还在alpha阶段的decisions端点:POST https://openrouter.ai/api/alpha/decisions。社区客户端jev-client的说明写得很直接:「Rejected by /chat/completions by design」——不能把Jev当成一个普通chat模型去调,用错端点会被直接拒绝。这个端点形状是从社区实现反推出来的,OpenRouter官方文档目前还没有一页正式说明它。
OpenRouter的decisions端点,是一个已经写进官方正式文档的稳定接口,还是一个还在alpha阶段、连文档页都还没补上的端点?
jev-client那张provider表里的一句备注——「Alpha path — may move.」这句话直接写明了当前状态;再加上它标注的「Rejected by /chat/completions by design」,说明连接入方式都跟大多数人熟悉的chat completions接口不一样,两条合在一起就是判断依据。POST https://openrouter.ai/api/alpha/decisions这个路径里直接带着alpha字样,而且这个形状是从社区客户端jev-client的实现反推出来的,不是从OpenRouter官方文档页抄来的;第二层,官方文档确实缺失,查decisions相关的文档页会返回404,说明OpenRouter目前没有专门为这个端点写一页正式说明。jev-client那张provider表里还专门标注「Alpha path — may move」,等于社区自己也承认这个端点随时可能变动。三条放在一起,答案很明确:这是一个alpha阶段、连文档页都还没补上的端点,不是稳定接口。如果生产代码依赖一个alpha阶段的端点,该怎么降低它突然变动带来的风险?
Cloudflare Workers AI走的又是另一种形状,模型ID是typesafe/jev,绑定调用是这样:
Cloudflare的REST接口又不一样:questions被包在一层input里,model留在外层,跟官方API那种字段平铺的结构不一样。
如果你看到一段请求体,最外层只有model和input两个字段,state和questions都被塞在input里面,这更像是官方直连接口,还是Cloudflare Workers AI的REST接口?
state/model/questions是不是平铺在最外层。state和questions包进了一层input。state、model、questions三个必填字段直接平铺在最外层;如果看到最外层只有model和input两个字段,state和questions都嵌在input内部,这个形状只在Cloudflare的REST例子里出现过。state、model、questions三个必填字段永远平铺在最外层,没有额外的包装层;Cloudflare的REST接口把model留在外层,却把state和questions一起包进一个叫input的对象里,所以它的请求体最外层只剩下model和input两个key。题目描述的形状——最外层只有model和input,state和questions都在input里面——跟官方三字段平铺的结构对不上,只跟Cloudflare那份经抓取提取的REST示例完全吻合,所以答案是Cloudflare的REST接口,不是官方直连接口。OpenRouter的decisions端点,请求体形状官方文档目前写清楚了吗?
Vercel AI SDK需要AI SDK 7.0.105以上,单问题调用长这样:
自己推一遍:把这段官方SDK代码,改写成Vercel AI SDK的样子
官方Python SDK里,一个Noul问题这样写:
Noul(instructions="The message conveys urgency or time-sensitivity"),返回值从response.answers["is_urgent"].noul里取。照Vercel的命名习惯,这个问题的type字段该填什么?想好了再看
type: 'boolean'——Vercel AI SDK把Noul这种问法改称boolean,不是noul。同一个问题的答案,在Vercel AI SDK的返回结果里,应该从
result.answers.xxx.noul取,还是从别的字段名取?想好了再看
从
result.answers.xxx.probability取——字段名从noul换成了probability,跟前面wasRefunded那段代码里result.answers.refunded.probability的写法对得上。如果这个问题在官方Python SDK版本里还想读
confidence,在Vercel AI SDK里,这个值应该去哪里找?想好了再看
不在answer本身上,要从
result.providerMetadata?.typesafe?.confidence这个单独的路径取——这是三处差异里最容易漏掉的一处,因为字段完全不在你以为该在的位置。
第三种问法叫Noul,返回字段是.noul,confidence就在同一个answer对象上。
同一种问法改叫boolean,返回字段是.probability,confidence要从result.providerMetadata?.typesafe?.confidence单独取。
同一个模型、同一次判断,换一个平台,字段名和取值路径不保证原样照搬,跨平台移植代码最容易在这里漏改。
置信度分流的完整实现,能看到confidence缺失时的失败安全写法:
注意最后这个?? 0:如果confidence这层元数据因为某种原因缺失,代码会让这个值退化成0,直接触发人工复核分支——既不会崩溃,也不会假装置信度很高。Vercel自带的mock测试用例里,专门测过这一种情况——这是刻意设计的失败安全默认值。
confidence?.department ?? 0这一行,如果confidence这层元数据缺失,最终会取到什么值。为什么confidence?.department ?? 0要把缺失的置信度当成0处理,而不是当成1(完全信任)处理?
departmentConfidence < 0.6这个判断,触发人工复核;当成1则会让代码误以为这次判断非常可信,直接自动执行。confidence缺失的真实原因是这次调用本身出了什么问题(不只是元数据没传回来),把它当1处理,等于在信息最不完整的时候做出最自信的决定,这正好是最危险的组合。如果这次业务场景是「低风险,宁可错放也不要错拦」,这个默认值0还应该保留吗?
LangChain的两个中间件,路由和把关各管什么?
装langchain-typesafe,设好TYPESAFE_API_KEY环境变量。最基础的调用:
上面这段LangChain代码,取urgent这个问题的答案,用的是response.answers["urgent"]还是response.nouls["urgent"]这种按类型分开取的写法?
response.nouls["urgent"].noul——按问题类型分开取,跟官方Python SDK异步示例里的那套写法一致。如果这个问题的类型换成Choice,取值应该改成response.nouls[...]还是response.choices[...]?
更值得关注的是两个中间件,按任务难度把请求分流给便宜或强力的模型:
ModelRouterMiddleware里的criteria字段,写的是选模型的判断依据,还是模型本身的参数配置。fast和powerful两档各自的criteria,是给底层模型用的固定参数,还是Jev用来判断这次任务该分给哪一档的依据?
如果两档的criteria写反了(fast写成负责架构决策),路由的结果会怎样?
Auto Mode守门中间件,在执行危险动作之前先拦一道:
LangChain这篇博客的论点很关键:像Claude Code、Codex、Cursor这类编码工具,一直都有「执行前判定危险动作」的分类器,只是那一步过去一直锁在各家闭源产品内部;现在有了便宜又快的判断模型,这个模式可以被搬到任何自己搭的agent上,不必依赖某个封闭产品自带的把关能力。
ModelRouterMiddleware和AutoModeMiddleware,哪一个负责挑选用哪个模型执行任务,哪一个负责在执行危险动作前拦一道?
ModelRouterMiddleware负责挑选模型(在fast和powerful之间路由);AutoModeMiddleware负责在执行bash这类工具之前把关。如果一个agent同时装了这两个中间件,执行顺序应该是先路由模型,还是先把关危险动作?
Pydantic AI:为什么写一个类型,就不用写questions?
前面几节,questions都是手写的一个map,每个问题指定type和instructions。Pydantic AI这个框架路数不一样——你觉得它是让你少写几个字段,还是干脆不让你直接写questions?
答完再看
pip install "pydantic-ai-slim[typesafe]"之后,你写的是Pydantic模型:Enum映射成Choice,bool映射成Noul,IntEnum映射成Score,字段上的Field(description=...)对应instructions,你完全不用手写questions这个map。
Enum映射Choice的例子:
Handling这个模型里,verdict字段的类型是Verdict这个Enum,框架会把它映射成Jev的哪一种问法?
Verdict这个Enum里三个成员run、reject、ask,各自变成Choice请求criteria这个map里的一个key,效果等价于手写verdict: Choice(criteria={"run": ..., "reject": ..., "ask": ...})这样一份criteria,只是不用你手写,框架从Enum定义里自动生成。Handling这个Pydantic模型里,verdict: Verdict这一行,字段类型是一个继承自str和Enum的类,成员是run、reject、ask三个。框架看到这是一个Enum类型,就会把它翻译成一次Choice请求:Enum里每一个成员变成criteria这个map里的一个选项key,跟手写Choice时给criteria传一个「选项到描述」的map是同一件事,只是这里的选项名直接取自Enum成员名,不用另外手写一份questions。这跟这一节开头预测门里确认过的对应关系(Enum→Choice、bool→Noul、IntEnum→Score)完全一致,verdict是Enum,所以答案是Choice。irreversible这个字段是bool类型,会被映射成Choice还是Noul?
bool映射Noul的例子:
output_type=bool这一行,为什么会让框架把这个问题映射成Noul而不是Choice。前面Handling那个例子,每个字段的instructions写在Field(description=...)里;这段bool的例子,instructions却直接传给了Agent(...)——这是两种写法不一致的疏漏,还是不同情况下本该有的差别?
Handling是一个有多个字段的BaseModel,这段bool例子的output_type是不是也是一个多字段的类型。output_type只是单独一个bool,没有多个字段可以分别挂description,instructions自然要直接传给Agent;只有像Handling那样有多个字段时,才需要给每个字段单独写Field(description=...)区分。output_type=bool这一行,右边只有一个裸类型,没有任何字段名,自然没有地方可以挂Field(description=...);对照Handling那个例子,output_type=Handling下面有verdict和irreversible两个字段,每个各自需要不同的instructions。output_type类型不一样:bool例子里output_type=bool是一个裸类型,整个agent只输出一个判断,没有第二个字段跟它并列,instructions自然只能整体传给Agent(instructions=...)这一层;Handling例子里output_type=Handling是一个有verdict和irreversible两个字段的BaseModel,每个字段各自对应一次独立的判断、各自需要不同的instructions区分开,所以才要把instructions拆开写进每个字段自己的Field(description=...)里,不能只在Agent这一层写一条笼统的instructions,那样两个字段就没法区分各自该怎么判断了。判断该往哪一层写instructions的规则很简单:字段数量决定要不要拆,单字段直接传给Agent,多字段拆进各自的Field。如果output_type换成一个只有一个字段的BaseModel(而不是裸的bool),instructions该写在Agent(...)上,还是Field(description=...)上?
只有一个判断,instructions直接传给Agent(...)这一层。
有多个字段,每个字段各自的instructions写在自己的Field(description=...)里。
单字段和多字段,instructions该写在哪一层,跟着字段数量走,不是随手选一种都行。
IntEnum映射Score的例子:
如果要判断一段代码改动的风险等级,划成「低/中/高」三档,用Pydantic AI的哪一种类型来定义这个字段?
UseEnumMemberDocstrings,像Clarity那个例子一样。Clarity那个例子的结构走第一步:先定义一个同时继承UseEnumMemberDocstrings和IntEnum的类,把低、中、高三档按顺序标成0、1、2三个成员,这一步只处理等级类型本身,还没有碰到Field(description=...)那一行。class RiskLevel(UseEnumMemberDocstrings, IntEnum): low = 0; medium = 1; high = 2,三个成员按顺序对应0、1、2三个下标,这个顺序保证了低于中、中低于高这层关系被保留下来,跟Clarity例子里opaque = 0; partial = 1; actionable = 2是同一种写法。第二步在BaseModel里给这个字段配上Field(description=...),把「这段代码改动的风险等级」这句instructions写进description,跟Review例子里clarity: Clarity = Field(description=...)的写法一致。最后把这个BaseModel传给Agent的output_type,框架会把这个IntEnum字段自动映射成一次Score请求,三个等级对应criteria数组里三条按顺序排列的描述。如果风险等级本身没有顺序关系,只是几个互不相关的分类标签,该换成哪种类型?
这套设计还有一层没有在代码示例里直接体现、但值得留意的性质:同一份agent代码可以在Jev和普通LLM之间切换,一旦遇到Jev的三种问法表达不了的参数类型,Pydantic AI会自动退回到普通LLM去处理。这意味着换掉Jev这件事的技术代价,比接口格式本身看起来的要小——真正稀缺的不是「能不能换一个兼容的接口」,是「换掉之后还有没有同等能力的替代品」,这是另一个需要单独核实的问题,这一节只确认接入层面这一件事。
如果Pydantic AI真的具备「Jev表达不了的参数类型自动退回普通LLM」这个设计,这对「接入Jev会不会被这一家供应商锁死」这个问题,意味着什么?
如果某天Jev停止服务,这套fallback设计能不能保证业务不受影响?还缺哪些信息才能回答这个问题?
一个模糊判断,怎么拆成几个可观察信号?
官方设计指南里,「拆解问题」这一步被单独强调:把最直接、最狭窄、最具体、最原子化的问题问出来,把复杂或定义不清的问题拆成几个各自只判断一个性质的问题。官方原话很重——这可能是整份指南里最重要的一条:宽泛的问题会把好几个判断藏在一个答案背后;原子化的问题把这些判断分别暴露出来,让你能在代码里分别检查、调优、组合它们。
拆解一个宽泛的问题,拆开的是「问几遍同一句话」,还是「把判断所依据的几个可观察信号分别问一遍」?
requests_credentials问的是有没有索要密码,offers_unexpected_reward问的是有没有许诺意外收益——这六个问题各自的instructions指向message.body、message.subject等不同路径,不是把is_spam这一句话换六种说法重复问。is_spam这一个问题背后,其实是索要凭据、许诺意外回报、制造时间压力等好几条独立线索共同决定这封信是不是垃圾邮件;拆解之后,requests_credentials、offers_unexpected_reward等六个新问题,各自只查其中一条线索、各自指向state里一处具体的路径(message.body、message.subject、message.sender.email……),而不是把「这是垃圾邮件吗」这句话换着措辞问六遍。换措辞问六遍,六个答案依然在各自重复同一个笼统判断,拆不出可以分别检查、调优的独立信号,这正是原子化和简单重复提问的根本差别。如果把一个问题原样复制成三份、只改措辞,这算不算完成了原子化?
官方给的垃圾邮件例子最直观。拆前,一个笼统的问题:
拆前这个is_spam问题,问的是一个单一的可观察信号,还是把好几个判断依据藏在了一个答案背后?
requests_credentials对应索要凭据、offers_unexpected_reward对应意外回报、creates_time_pressure对应时间压力、sender_identity_mismatch和link_domain_mismatch对应发件人身份、disguises_link_destination对应链接伪装,这六条线索原本全部糅进了is_spam这一个笼统问题里。is_spam: {type: 'noul', instructions: 'Is message spam?'}这一个问题,表面上只问了一句话,实际上要求模型在内部同时完成六件判断,再把结果压缩成一个数字,正是官方说的「宽泛的问题会把好几个判断藏在一个答案背后」的典型例子,所以答案是后者。如果模型判断错了,拆前这种写法,能看出是哪个具体信号误导了它吗?
拆后,1个问题变成6个,每个都指向state里的一处具体路径——是否索要密码等凭据、是否宣称意外中奖或收到报酬、主题或正文是否制造时间紧迫感、发件人显示名和邮箱域名是否对不上、链接域名和发件人组织是否对不上、链接文字和链接实际指向是否被伪装:
前两个信号——requests_credentials和offers_unexpected_reward——问的是同一件事的两种问法,还是两个不同的可观察信号?
requests_credentials问的是message.body有没有要求提供密码或者其他登录凭据,offers_unexpected_reward问的是message.body有没有宣称收件人获得了意外的奖金或者报酬,这是两类完全不同的诈骗话术。requests_credentials查的是「message.body有没有要求收件人提供密码或者其他登录凭据」,对应钓鱼邮件里最常见的套路之一;offers_unexpected_reward查的是「message.body有没有宣称收件人得到了意外的奖金、付款或者奖励」,对应另一种完全不同的诈骗手法,比如中奖通知。两者instructions指向的内容不同,一封邮件完全可能只踩中其中一种,也可能两种都踩中,各自是可以独立成立或不成立的信号,不是同一件事换个措辞重复问一遍,这也是六个信号被分开列成六个独立问题、而不是合并成一句话的原因。如果一封邮件这两个信号都是no,能不能就此断定它不是垃圾邮件?
sender_identity_mismatch这条,问的是发件人显示名和邮箱域名对不对得上——这一条信号自己,能不能单独断定一封邮件是垃圾邮件?
sender_identity_mismatch单独就能判定是垃圾邮件,这种正常情形也会被错误拦下。sender_identity_mismatch只回答「发件人显示名和邮箱域名是否冲突」这一件具体的事,不回答「这封信是不是垃圾邮件」这个更大的问题。一个反例就能说明这一点:员工临时用私人邮箱转发工作邮件、或者公司刚换了域名还没完全迁移,都会让显示名和邮箱域名对不上,但这些情形跟垃圾邮件没有关系。六个信号被设计成各自独立、只回答自己那一小块具体判断,真正的最终结论要靠代码把六个noul的结果综合起来看,比如设定多少条信号同时为真才判定为垃圾邮件,合并逻辑完全在代码里完成,不是任何一个单独的noul说了算,这也是原子化拆解和问一个大而化之的问题最根本的差别。如果只有sender_identity_mismatch是yes,其余五个都是no,代码该怎么处理这种情况?
六个问题拆开之后,如果某一封邮件被错判成垃圾邮件,拆前的写法和拆后的写法,哪一种更容易查出错在哪一步?
sender_identity_mismatch和link_domain_mismatch两条给出偏高的值、其余四条都偏低,就能直接把误判定位到发件人和链接域名这两个信号上,不必笼统地说is_spam判错了。is_spam的noul,一旦误判,能看到的只有一个偏高的数字,六个真实信号全部糅在这一个答案背后,没法知道模型是被哪一条线索带偏的。拆后的写法把六个noul分别记录下来,误判发生时可以逐个核对——如果sender_identity_mismatch和link_domain_mismatch都偏高、其余四个正常偏低,问题大概率出在发件人身份识别这一类信号上,可以针对这一类单独调整instructions,而不必怀疑整套判断逻辑。这正是官方那句「让你能在代码里分别检查、调优、组合它们」的实际含义。如果六个信号里只有一个误判,其余五个都判断正确,最终结果应该完全依赖那一个误判的信号吗?
官方还给了三条更具体的原则。第一条,遇到不可避免需要综合判断的地方,拆成两个各自单独成立的字面问题,在代码里合并:「Where interpretation is unavoidable, split it into two literal questions and combine them in code.」
「一封邮件的语气算不算专业」这种没法直接摆出证据的综合判断,按官方第一条原则,该整体问一个笼统的问题,还是拆成两个各自成立的字面问题再在代码里合并?
拆成两个字面问题之后,代码里「合并」这一步,是该写死规则,还是也可以再问模型一次?
第二条,数数时在代码里逐个遍历候选、各问一遍、自己求和——「iterate in code over the candidates and ask one question for each, then add up the answers yourself」:
上面这段代码,数「items里有几个水果」这件事,是让Jev直接回答「一共有几个」,还是让Jev对每个候选各答一次是不是水果,再在代码里数?
count这一行,是在读Jev返回的一个数字,还是在对Jev返回的好几个noul做求和。count是Python的sum(...)算出来的,加总这一步完全没经过模型。{f"item_{i}": Noul(instructions=f"Is items[{i}] a fruit?") for i in range(len(items))},这是一个字典推导式,对items里的每一个元素各自生成一个独立的Noul问题,问题数量跟着items的长度走,不是只问一次「一共有几个水果」。questions用字典推导式对items列表里每一个元素各生成一个独立的问题,item_0到item_{n-1}各自问一遍「这一个元素是不是水果」,返回n个各自独立的noul,不是一个笼统的总数。真正的计数发生在最后一行:count = sum(result.nouls[f"item_{i}"].noul > YES for i in range(len(items))),这里用Python的sum和一个比较表达式,把每个noul是否超过阈值YES的布尔值加总起来,这一步完全是代码在做加法,Jev本身从头到尾都没有被问过「一共有几个」。这正是官方那条原则的具体实现:提取是判断,交给模型;求和是算术,留在代码里。如果items的长度从4个变成400个,这套写法要不要跟着改?
第三条是官方SKILL.md里最凝练的一句:「Extraction is a judgment, so give it to the model. Arithmetic is not, so keep it in code.」——提取信息是一种判断,交给模型;算术不是判断,留在代码里。这三条合起来,就是这一节标题问的那句话的完整答案:先把模糊判断拆成各自独立的信号,再把信号本身的提取交给模型,把信号之间的合并、计数、算术,留给代码。
要判断「一份简历里,有几段工作经历提到了团队管理经验」,按官方这三条原则,这件事该怎么拆?
如果简历段落数事先不知道有多少,这套拆解方式还能直接套用吗?
生产环境要守哪几条硬规矩?
第3章已经讲过一条:生产环境要写死具体版本号,不要用会漂移的jev-latest这类别名——别名指向的模型换掉之后,针对某个版本调好的置信阈值会跟着失效,而且不会报任何错误提醒你这件事发生了。这一节不重复推导,只补两条第3章没有覆盖的规矩。
第一条,速率限制返回429之后该怎么处理:官方接口把429和一个retry-after字段配在一起返回,代码里应该读这个字段、按它给出的时间等待之后重试,而不是立刻重发或者固定等待一个写死的秒数——429本身就说明短时间内的重试大概率还会撞上同一个限制。
收到429响应之后,代码应该立刻重发请求,还是先读retry-after字段再决定什么时候重试?
retry-after字段,按它给出的等待时间再重试——立刻重发大概率还会撞上同一个限制,官方接口的速率限制配了这个字段就是为了让调用方按它退避。retry-after这一个字段,它给出的是一个具体的等待秒数;代码里该改的是重试逻辑那一行,把原来立刻重发或者sleep一个写死数字的那一行,换成先读这个字段的值,按它给出的秒数sleep之后再重试。retry-after字段,拿到服务器要求等待的具体秒数;第二步用这个秒数sleep,不是立刻重发,也不是自己猜一个固定数字;第三步等待结束后再重试,如果又收到429,重复同样的读取retry-after再等待的过程。道理很直接:429本身就是服务器在说「已经超出限制了」,不看这个字段立刻重发,大概率还会撞在同一堵墙上,retry-after字段的存在,就是官方把该等多久直接告诉调用方,不用自己去猜。如果连续多次429,退避时间是应该固定不变,还是应该逐次拉长?
不管这次429返回的retry-after是多少,代码里都sleep一个写死的数字再重试。
按响应里这个字段给出的时间等待,短时间内还撞限制就再等一轮,不是猜一个数字硬扛。
两种写法都会重试,差别在等待时间跟不跟着接口实际给出的信号走。
第二条,state要保持小而干净:第13章已经证明过context rot这条机制——state里混进跟当前判断无关的内容,会拖累准确率,跟账单没有关系,纯粹是判断质量的代价。这一节要补的是生产环境里具体怎么做到这条:不要图省事把整段历史记录原样塞进state,每次请求前先筛一遍,只留下这次判断真正用得上的部分。
第三条,日志该记什么:一次请求真正值得留档的是{state, questions, probabilities}这个三元组——可复现、可追溯,出了问题能回头核对当时喂进去的到底是什么。但这个三元组里没有任何「为什么」:模型不生成解释性文字,probabilities告诉你它给出的分布是什么,不告诉你它为什么给出这个分布。想在事后追问「这次为什么判断成这样」,这个三元组答不出来,只能靠换一批问题重新问一遍来间接摸清楚。
记录了完整的{state, questions, probabilities}三元组之后,如果某次判断后来被证明是错的,这份日志能不能直接告诉你「当时为什么判断错了」?
state是当时喂进去的原始输入,questions是当时问的是什么,probabilities是模型给出的分布——把三样摆在一起,能做的是原样重放这次请求、核对输入和问题是不是符合预期,没有一项是模型对自己判断过程的说明。state到底是什么、questions到底怎么写的、模型返回的probabilities分布长什么样,三样合在一起可以原样重放这次请求,也能核对是不是questions写得有歧义、state里混进了不相关的内容。但这份日志答不出「模型当时为什么这样判断」——Jev不生成解释性文字,probabilities只是一个分布,不附带推理过程。想知道错在哪一步,只能靠换一批更细的问题重新问一遍(比如把这次判断拆解成更小的信号分别问),从新的答案里间接摸清楚当时可能是哪个信号误导了它,日志本身没有这个能力。要摸清楚一次误判的原因,除了看这份日志,还能做什么?
state不被当敌意处理,九条反模式怎么防?
官方原话说得很直接:「State is data, and jev-1.13 does not treat it as hostile by default.」——state里的内容不会被默认当成敌意内容处理。这意味着,任何把用户输入或者抓取到的内容不加处理就塞进state的场景,都有被注入攻击的风险:一段精心构造的用户消息,完全可能在state里悄悄改写问题的判断方向。这条限制官方写进了自己的九条反模式列表,编号第6条,官方给出的对策只有一句——写precise的prompt,上线前专门测边界情况,没有更强的技术手段能替你把这道口子堵上。
官方说state默认不被当成敌意内容处理——这句话,是在说Jev会主动识别并挡住恶意输入,还是在说挡不挡得住,责任在调用方写的prompt和测试,不在模型这一层?
这意味着,state里塞进未经处理的用户输入或抓取内容,风险该谁来兜?
state里混入一段精心构造的注入文字,指望Jev自己识别出这是恶意内容、不受它摆布。
写precise的prompt,把容易被注入利用的边界情况在上线前专门测一遍,责任在这一层,不在模型那一层。
不默认当成敌意,说的是模型不主动挡,不是说没有办法挡——办法只是挪到了调用方这一层。
| # | 失败模式 | 该怎么做 |
|---|---|---|
| 1 | 字面理解(Literal reading) | 把每个选项的确切条件写清楚 |
| 2 | 数学与数字(Math and Numbers) | 算术留在代码里 |
| 3 | 日期时间比较(Date and time comparison) | 先提取字段,在代码里比较 |
| 4 | 间接引用(Indirection) | 减少跳转层数,直接指向相关的state |
| 5 | state塞满无关细节(Large state full of irrelevant detail) | 先过滤,只发问题真正需要的部分 |
| 6 | 对抗内容(Adversarial content) | 写precise的prompt,上线前测边界情况 |
| 7 | 指令与标准互相矛盾(Contradictory instructions and criteria) | 让criteria和instruction保持一致 |
| 8 | 常识性结构不变量(Common-sense structural invariants) | 每个判断单独问,不变量留在代码里强制 |
| 9 | 生成(Generation) | 该用生成式模型的场景就用生成式模型 |
「判断这张发票的到期日是不是已经超过了今天」,直接问Jev这句话,会撞上表18-1里的第几条?
如果只是问「这份文本里提到的日期是哪一天」,不涉及比较,这还算踩第3条吗?
第2条数学与数字、第9条生成,也各有边界。官方明确提醒:不要拿score输出去反推两个等级之间的精确数值——score能用来过阈值,不能反推出背后那个具体的数。第9条生成的边界最简单:Jev压根不是训练来生成文字的,需要一段解释、一段摘要、一段对话回复的场景,该换生成式模型,不必勉强用Jev凑。
如果一次Score请求返回score=1.5,能不能反推出模型在0级和1级之间,各自分配了多少精确的概率?
probabilities字段,而不是只盯着score这一个数——probabilities才是逐级列出来的真实分布,score只是用等级号把这个分布加权平均出来的一个统计量,同一个1.5可能对应好几种不同的分布组合。score是等级号的概率加权均值,同一个score数值背后,能对应无数种不同的概率分布——1.5可能是level 1和level 2各半,也可能是level 0和level 3各半再凑出同一个加权平均。只看score=1.5这一个数,没法唯一还原模型到底在0级和1级之间分配了多少概率。真正想看清这个分布,要去读同一次响应里的probabilities字段,它逐级列出每一级各自的概率,这才是完整信息;score正确的用法是拿它去卡一个阈值,不是当成可以反推出精确子概率的插值点,官方原话就是不要用score去计算两个等级之间的精确数值。要看清楚score背后真实的概率分布,该读响应里的哪个字段?
读的时候要小心
「state不被当敌意处理」不是官方的疏忽,是一条边界
把这条反模式读成「官方没做好安全防护」,会漏掉更准确的那层意思:这是官方主动写进自己反模式列表、明确划清的一条责任边界——防住注入内容不是模型这一层的工作,是调用方写prompt、测边界情况这一层的工作。把这条边界当成bug去等官方修,会一直等不到。
留给你的问题
如果你现在要把Jev接进一个真实的客服系统,从选官方SDK还是某个第三方平台开始,到最后一次防线是防住恶意输入的state,你会按什么顺序,先检查哪一项?
不看材料,写下这一章最容易被忽略的三件事
第一件:不同平台的字段名不是随手换了个说法,noul/boolean、probabilities/probability、confidence的位置,三处都可能改变,跨平台移植代码必须逐字段核对,不能靠记忆。第二件:拆解问题不是把一句话换着法子多问几遍,是把判断所依据的可观察信号找出来,各自单独问;数数、算术、比日期,这些代码能精确做的事,永远不该外包给模型。第三件:state默认不被当成敌意内容处理,这条边界官方自己写得很清楚,用户输入不加处理直接塞进state,风险由调用这一方自己承担。
这一级要加什么:真实请求构造器
为什么现在才加它:前十七级教的是怎么审视一份已经发布出来的材料,这一级要反过来,自己动手把一次真实的请求攒出来——从选哪个平台、questions该怎么拆、到发布前要检查哪几条production规矩,全部接进同一个构造流程。
难点:atomizeQuestion这一步不是简单的字符串拆分,需要先想清楚一个模糊判断背后到底依赖哪几个可观察信号——垃圾邮件那个例子里,六个信号分别对应state里六处不同的路径,少拆出一个信号,代码事后就没法单独检查那一处判断对不对;拆出的信号如果本身还是模糊问题(比如「这封邮件整体上是不是可疑」),等于什么都没拆,这一步最容易做成表面拆解、实际没有增加任何可检查的粒度。
自己验:把「判断这条工单是不是需要立刻转人工」这个模糊问题喂给atomizeQuestion,应该拆出至少两个以上各自独立的noul或choice信号(比如是否提到资金损失、是否明确要求人工),不能原样返回一个单一的宽泛问题;buildRequest返回的model字段应该是一个写死的具体版本号(比如jev-1.13.0),不应该是jev-latest这类别名;productionChecks数组应该固定包含这四项,缺一项就说明这次构造漏掉了一条生产环境的硬规矩。
第19章 终极闯关
这一章不教新概念。前面十八级台阶,每一级单独拿出来你可能都答得上——但真正的问题是,当材料自己不会告诉你「这道题该用第几章」的时候,你还认不认得出该伸手去拿哪一件工具。这一章要做的,就是把提示去掉,混着问。
学完这一章你应该能做到
- 看到一份从没见过的新材料,不靠章节提示,自己判断该用前面哪一章的检查方法
- 分清「材料没说」「材料说了但能推出来」「材料明确说了不知道」这三种状态,说清楚它们的界限
- 走完一遍完整的审查,得出一份写清楚判据的结论,而不是一句简单的信或者不信
这一级要把审计仪真正跑一遍:找一份从没在这本书里出现过的新材料,把前面十八级攒出来的检查逐条过一遍,看这套工具是不是真能立在一份从没见过的材料上,而不只是刚好适配Jev这一个例子。
十八章都学过一遍,就等于能审完一份新材料吗?
接下来不会再教任何新概念——前面十八章的工具你已经都学过一遍。现在给你一份从没见过的新公司、新模型的发布材料,不告诉你这道题该用第几章的方法,你觉得能不能一眼认出该用哪一套?
答完再看
是中间这句。这一章接下来的每一道题,材料都换成一家没出现过的公司——但检查方法全部来自前面十八章,一条都不会新增。能不能用对,才是这一章真正要测的事。
先来两道热身,材料是虚构的,方法不是。
某发布页写着「处理一份合同审阅,成本只要人工的五十分之一」——在往下看任何细节之前,第一件要确认的事是什么?
如果分母写的是「行业里最贵的一家律所」,这个五十分之一还站得住吗?
一张对比表列了四个模型的分数,其中一个模型的名字,同时也出现在「参照系由哪些模型的共识定义」那句说明里——这张表有什么问题?
如果这个模型的分数在表里明显低于其他几个,这个循环问题还成立吗?
每一章开头就写着这一章讲哪件事,答题时知道该往哪个方向想。
材料不会提示这一句该用第几章的方法,得自己先认出这句话报的是哪一类数字。
两种情况下你知道的方法完全一样,差别只在有没有人替你把方法和问题预先配对好。
混着问的时候,怎么认出这道题该翻哪一章?
出声示范一遍:Northlake的发布页写着「Corvus-1处理一份合同审阅只要0.6秒,比人工审阅快得多」。我先问这句话报的是倍数还是绝对值——是绝对值,还轮不到翻第12章那本分母的账。我再问这句话有没有说清楚比什么快——提到了人工审阅,但人工审阅本身要多久、错多少,材料没说。这就把我引向第15章:想知道一个又快又便宜的判断值不值得换掉人工,得先知道被换掉的那一套流程自己的成本和准确率,不能只看新模型这一侧亮出来的数字。
这个动作有个名字:先问这句话本身在报的是哪一类数字——倍数、绝对值、还是通过率——再决定翻第几章,不是看到快、便宜、准这些字眼就条件反射去翻同一章。
「Corvus-1单次判断只要0.6秒」这句话本身,报的是倍数、绝对值,还是通过率?
如果改写成「比人工快80倍」,这句话报的数字类型会变吗?
Northlake的发布页有一句「独立评测显示Corvus-1判断质量一致率91%」,翻到脚注才发现,这次评测用的裁判模型正是Atlas-4——同一份材料里,Atlas-4又是总榜的参照系。这句独立评测,该放进证据分级的哪一档?
如果裁判换成一个完全不相关的第三个模型,这句话的证据分量会不会不一样?
Corvus-1的发布页写着「0%把合规条款误标为风险」,没有给出测试用了多少条数据。这句话现在能不能被验证?
如果补上一句「测试集有500条」,这句话就足够可信了吗?
有人把Corvus-1接进自己的审批系统,每次请求都把这个客户过去两年的全部往来记录原样塞进state。这样做会撞上哪个机制,真正接进系统时该怎么改?
如果两年记录里,只有最近三个月和这次判断直接相关,该怎么改这次请求?
Northlake说Corvus-1不需要任何训练数据,直接替代了原来需要标注数据训练的分类器。在承认这是纯粹的节省之前,该先问哪个问题?
如果折算出来零样本相当于几千条标注的价值,而这类任务的标注成本本身很高,结论会怎么变?
有篇评论说「Northlake的材料从没解释过Corvus-1为什么在Vendor Risk Tiering这一项分数最低」。在采信这句话之前,该做哪一步核实——即便Northlake和Jev完全是两家公司?
如果查完发现材料确实一个字都没提,下一步该怎么写这条结论?
检查全部过关,轮到你自己下场答辩,你答得上来吗?
如果一份新材料,前面这些检查一条都没露出破绽——参照系不循环、分母有说明、样本量公布了、context rot也提醒过要过滤——这是不是就足够放心相信它了?
答完再看
通过检查排除的是可核查的失败模式,不是把每一句话都变成已验证——第17章的三态登记册里,查无实据不会因为没人反对就自动升级成已验证。
答辩:如果我是这家新公司的公关
你们这一整套方法,是不是本质上就是逢发布必反对——见到营销数字先假定它在骗人?
参考防守(先自己组织语言再看)
不是。第16章那道antibenchmaxxing的题就是反例——七个问题问下来,那篇质疑文章的论证本身是站得住的,这套方法确认了它,没有反过来找理由否定它。这套方法不预设结论,它只是把信不信拆成几个能各自单独核对的判据,判据支持哪边,就写向哪边。
答辩:如果我是那家新公司的怀疑者
如果一份材料,前面这些检查一条都没被抓到破绽,是不是就能说这家公司很诚实,可以放心用了?
参考防守(先自己组织语言再看)
没被抓到破绽和诚实不是同一件事——这套检查只能抓住它设计来抓的那几类问题,比如循环参照系、分母不明、样本量缺失。材料里没被检查覆盖到的角落,检查过关这件事本身证明不了什么,只能证明这几类常见的坑没有踩中。
说明这份材料没有踩中循环参照系、分母不明、样本量缺失这几类已经知道该怎么查的坑。
需要的是这句话本身被独立核实过,不是没被这套检查挑出毛病。
前者是审计仪能负责的范围,后者要靠第17章那种一条一条查出处,两者不是同一件事。
Northlake的内部仪表盘把Corvus-1返回的score(等级0到4的概率加权均值)直接当成这份合同有风险的概率展示给审批人员看,这样做对吗?
score字段,定义是等级号的概率加权均值——如果这份合同的风险等级分成0到4五档,score就是这五个等级号按各自概率加权平均出来的一个数,取值范围跟着等级号走、可以落在两个等级之间(比如2.5表示介于第2级和第3级之间),它本身不是一个0到1的概率,不能直接当成「这份合同有风险的概率」去读。真正的概率分布在同一次响应的probabilities字段里,那里逐级列出了模型在每一个等级上各自分配了多少概率,这才是可以正确解读的分布。仪表盘直接把score当概率展示给审批人员,等于把一个加权平均出来的等级读数,误读成了一个真正的风险概率,这是两个完全不同的量,混着用会让审批人员对风险的实际大小产生错误的判断。如果score是2.5,是不是说明有2.5%的风险概率?
Northlake的团队选Noul阈值时,只测了阈值设多少时整体准确率最高,选中了0.5。这个选阈值的过程,漏掉了哪两件事?
如果拦下一个合规条款的代价只是多一次人工复核,放过一个违规条款的代价是巨额罚款,0.5还是最优阈值吗?
有人把先分类条款类型、再判断是否违规、最后生成风险等级拆成三次依赖的Jev请求,每一步都要等上一步的答案。上线前,除了第14章的延迟,还该多算哪一件事?
如果三步各自的准确率都是0.9,三步全部走对的联合准确率大概是多少?
Northlake说Corvus-1用了突破性的训练方法,但拒绝公开任何架构细节。一位读者说:不敢公开,肯定是心虚,说明这个说法就是假的。这句话本身站得住吗?
如果后来有第三方独立复现出了类似效果,这句突破性的证据档位会不会跟着变?
查无实据和真未解,隔着一道什么样的界限?
这本书里,材料目前查不到这句话出现过很多次。这些查不到,是不是同一种性质的空白?
答完再看
是后者。这本书里几乎所有研究框标的都是对你而言未知——findable with work;只有第1章那道关于confidence具体计算公式的题,标的是真未解,因为这属于模型内部没有公开的实现细节,任何外部测试都还原不出确切公式。
中文场景一致率具体低多少——没人测过,不是测不出来,找一批数据自己跑一遍就有答案。
confidence具体怎么从底层概率算出来——属于模型内部没公开的实现细节,外部测试还原不出确切公式。
两栏都写着不知道,差别在这份不知道,愿意花时间就能补上,还是不管花多少功夫都够不到。
Corvus-1的confidence具体怎么从底层概率算出来,和Corvus-1中文场景下一致率具体比英文低多少,这两个空白,是不是同一种性质?
如果Northlake公开了confidence的计算公式,第一件事的状态会变成什么?
对你而言未知换一类完全不同的发布,这七个问题原样能用几条
这一章这些题用的都是决策类型化任务的发布材料。换成一份图像生成模型的发布页,参照系、样本量这类问题多半还能直接照搬;但倍数对应的可能是生成质量的人类偏好胜率,不再是价格或速度,直接套第12章的成本模型不一定合适。这本书没有验证过七问在决策任务之外还能剩下几条。
先做这一步:挑一份最近的图像或视频生成模型发布页,把第16章那七个问题逐条对照,写下哪几条能不改一个字直接照搬,哪几条需要换个问法,哪几条在这类任务上根本问不出来。
Northlake的总分用Atlas-4和Halcyon-2的共识定义;另一家公司Ridgeline的总分用它自己训练的Delta-3单独定义。两家公司各自宣称总分领先上一代20个百分点,这两个20个百分点能不能放在同一句话里互相比较?
如果后来出现了一份第三方、用独立人工标注评测过这两家模型的报告,这两个20个百分点能不能重新变得可比?
对你而言未知两家公司各自的参照系都是自家训练的另一个模型,这两张表能不能互相比
如果Northlake用Atlas-4和Halcyon-2的共识定义参照系,另一家公司用完全不同的两个模型定义自己的参照系,两边各自算出一个总分——这两个总分是在测同一件事,还是分别在测像不像自己家挑的那两个模型这两件不同的事,这本书还没有处理过这种跨公司比较的场景。
先做这一步:找两份这样的发布材料,把各自的参照系模型、总分定义并排列进同一张表,检查两边的参照系有没有重叠、评测任务是不是同一批题目,再判断这两个总分能不能放在同一行直接比大小。
读的时候要小心
Northlake AI、Corvus-1、Atlas-4、Halcyon-2全部是虚构的
这一章和后面建造台阶里出现的公司名、模型名、分数、价格,全部是为了练习虚构出来的,不对应任何真实存在的公司或产品,任何相似纯属巧合。它们存在的唯一目的,是提供一份材料本身不告诉你答案在第几章的练习题——真正遇到一份新发布材料时,公司名和数字都会不一样,但审查的方法不会变。
留给你的问题
下一次一份全新模型的发布材料摆在你面前,你会先做哪一件事——先找参照系是谁,还是先找它自己承认了哪些局限?这本书没有替你排好顺序,这个顺序需要你自己走一遍之后才敢确定。
不看材料,写下整本书最容易被忽略的三件事
第一件:一张评测表看着有很多模型参加,也可能只是同一个循环换了件外衣——先看定义参照系的那个模型在不在候选名单里,比看总分数字本身更重要。第二件:查不到不等于被隐瞒,也不等于已经证实,它只是一种需要写清楚在哪查过的状态,绝大多数查不到,只要愿意自己动手测,都能变成一个有数字的答案。第三件:这一整套方法从头到尾都不预设立场,通过检查说明的是没有踩中已知的坑,不是这个说法已经被证明为真——审查的价值不在信或者不信这一个结论,在于任何人拿着同一份材料,都能沿着同一条路径,走到同一处能核对的判据。
这一级要加什么:把审计仪跑在一个新模型上
为什么现在才加它:前十八级各自把一件工具打磨好了,但从来没有在一份不是设计给这本书用的材料上试过。这一级用一份完全虚构的练习材料——Northlake AI和它的Corvus-1,任何相似纯属巧合——把整台审计仪跑一遍,看它是不是真能立起来,而不只是刚好适配Jev这一个例子。
难点:这份材料是照着前面十八章遇到过的坑专门设计的,真正的新材料不会这么配合——循环可能藏得更深,分母可能根本不写在同一页,需要自己去别的页面找。跑这个函数只是练手,遇到真材料时,material对象里的每一个字段都要自己动手去原始页面上找,不能假设格式会一样干净。
自己验:report.groundTruth应该以「循环」开头,因为contestants数组里包含refModels[0]也就是Atlas-4;report.aggregation里的百分点数字应该是6.1,也就是0.742减0.681再乘100;report.calibration、report.sampleAndCI、report.zeroClaim、report.increment这四项应该全部以「查无实据」开头,因为这份虚构材料在这四处都没有给数字。