推理模型与测试时计算 Reasoning & Test-Time Compute
2026 年最显著的技术转向之一:把「思考时间」当成一种可以按需分配的算力。预训练规模的边际收益在递减,而让模型在回答前多做几轮推演、多采样几条路径再择优,往往能显著提升复杂任务的准确率。这个阶段讲的就是这条新轴的原理、训练方法与工程取舍。
阶段总览
- 能清楚区分「通用模型 + 长提示」与「真正的推理模型」的差别
- 理解长 CoT 是如何被训练出来的:冷启动数据、RLVR、长度控制与自验证
- 掌握测试时计算扩展的六种手段与各自的成本收益
- 理解过程奖励模型(PRM)与结果奖励模型(ORM)的取舍,以及验证器的用法
- 能设计推理预算策略:按难度路由、设定 token 上限、思考与回答分离
- 能正确评测推理能力,识别基准污染与过拟合,理解影子评估的思路
- 能在产品里把推理模型用得起:成本、延迟、缓存与降级
| 周次 | 主题 | 交付物 |
|---|---|---|
| 第 1 周 | 推理模型原理与形态 | 读 R1 / o 系列技术材料并写对比笔记 |
| 第 2 周 | 推理能力的训练 | 在小规模数据上跑一次 RLVR,观察长度与准确率变化 |
| 第 3 周 | 测试时计算扩展 | 实现 Best-of-N / 自洽性 / 多数投票并做成本收益曲线 |
| 第 4 周 | 验证器与 PRM | 训练一个答案验证器,对比有无验证器的准确率 |
| 第 5 周 | 工程化与评测 | 设计一套推理预算路由策略 + 评测报告 |
1. 推理模型到底是什么
学习路径
- 读 1.1:对比「普通对话 vs 推理模型」表,抄下双通道输出与思考预算 minimal→high 的形态
- 跑内置 diagnose 代码,输入一组长度/正确/熵数据看长度与正确的相关
- 完成 1.3 练习 4:量化一次思考的边际收益,写出 Δp×成本判据
- 对接 M10:把思考预算做成 budget.py 的档位,先想清楚形态再写代码
核心知识点详解
- 可变算力的本质:把思考 token 当作预算:普通模型一次前向固定成本,推理模型可按需分配思考预算(
minimal→high档位)。代价是延迟高且波动(P99 可比首字高出一两个数量级),这正是成本控制的起点。 - 双通道输出:思考段可独立于答案段:推理模型输出分「思考段 + 答案段」,可由
reasoning/format开关分离。思考段通常不落库、不展示(见 14.3),否则多轮上下文会无限膨胀。 - 输入输出形态决定训练关键:形态上「先思考、后给答案」对应 RLVR 的答案可验证、格式必须统一;若任务答案无法程序化判定,就无法走推理 RL。
- 常见坑:预算档位拉满却不设上限:直接把思考强度开到
high而不做难度路由,简单题也会烧掉上千 token,账单 10–50× 于答案——必须配 12.3 的路由器。
学习路径
- 读 1.2:理解反思语 wait/recheck 与「长度随训练增长」是怎么被奖励塑造的
- 跑 diagnose 代码,观察「长度-正确 相关」弱正相关/熵崩塌的判读结论
- 完成 1.3 练习 3:写出「长思维链一定是真实推理」的两条反例
- 对接 M10:在 coT 管线里把反思语当作可观测信号统计出现频率
核心知识点详解
- 反思语是被奖励塑造的行为,不是天赋:
wait/recheck/hmm这类自检词并非模型天然会写,而是 RL 中「写出来更容易答对→奖励更高」涌现出的行为模式。它可观测、可统计出现频率,是判断模型是否真在迭代推理的信号。 - 长度随训练增长的双面性:更长的思考在可验证奖励下更容易碰对答案(正确率↑),但也带来成本问题:输出长度从几百涨到几千 token,推理账单线性上涨。
- CISPO 的裁剪陷阱:标准裁剪会「只裁 token」——把
wait/recheck这类低概率 token 的梯度裁掉,反而不利于学反思。CISPO 改为只裁权重、不裁 token(CISPO 全称 Clipped-Style Policy Optimization),保住低概率 token 的学习机会。 - 常见坑:把长度当能力:看到长度增长就以为模型更强是错的;要看每正确一次的 token 成本而非绝对长度,否则简单题也在烧思考预算。
学习路径
- 读 1.2 的「三条曲线必须一起读」:掌握奖励/长度/熵的健康组合
- 跑 diagnose 代码,用箱子统计 token/correct,看难题段收益是否递减
- 完成 1.3 练习 1:写判断「真在推理 vs 凑长度」的判据与对照实验
- 对接 M10:在评测脚本里输出 reward/length/entropy 三曲线脚本
核心知识点详解
- 三条曲线必须一起读:训练时监控 奖励 / 长度 / 熵:奖励升 + 长度升 + 熵稳 = 健康的长 CoT 训练;若奖励升、熵却崩塌、长度暴涨,多半是模式崩溃 + 过度思考。
- 熵崩塌是模式崩溃的信号:当输出分布从多样收敛到少数套路(熵 < 训练初期的一半),说明模型把所有样本推向同一种写法——这通常伴随「格队对但内容错」的奖励 hack。用
diagnose()中的H[-1] < 0.5*H[0]一判便知。 - 用 token/correct 判断长思考是能力还是凑长度:分箱统计每档长度的准确率与
token/correct:若难题段token/correct飙到数倍(如 210→6667),说明长思考对难题必要但收益递减;简单题段长却对准确率无提升则纯属浪费。 - 常见坑:只看单条曲线下结论:奖励一直涨也可能在走捷径。必须三者联合看,单一曲线升/降都不足以判断健康,否则会把模式崩溃误当训练成功。
学习路径
- 读 1.1 的错误提示:理解 CoT 事后合理化与不稳定依赖两个误区
- 跑 7.2 自洽性代码(或先看该方法),体会多次采样 + 一致性检验怎么替代盲信单次 CoT
- 完成 1.3 练习 2/5:用同题异答数据验证「多采样 + 一致性 + 外部验证器」
- 对接 M10:在 sc.py 里实现一致性比例当置信度的判据
核心知识点详解
- CoT 会事后合理化:模型可能先给出答案再反推步骤(事后合理化),看起来有推理过程实则不是真思考。所以「有思维链」≠「真实推导」。
- 不稳定依赖:同题异答:同一问题换温度/采样可能得到不同结论。要验证单次 CoT 是否可靠,就做同题多次采样,看答案是否符合多数一致性(一致性比例)。
- 用多次采样 + 一致性 + 外部验证器替代盲信:生产里更稳的组合是「多采样 + 一致性检验 + 外部验证器」,其中一致性比例可当置信度(见 7.2),低于阈值就升级或转人工。
- 常见坑:忽略边际收益 = 边际成本的判据:每次采样有成本 C,若新增正确率 Δp≈0.02,只有 Δp×(答错损失) > C 才值得继续采样;否则一味加采样是烧钱不涨分。
1.1 长思维链与思考预算
推理模型的核心变化不在架构,而在后训练目标与输出形态:模型被训练成在给出答案前先生成一段(可能很长的)思考过程,这段过程会被后续的自我检查反复审视。训练方式的关键是用可验证奖励做 RL,让「想对了才答对」这件事被奖励直接塑造。
| 维度 | 普通对话模型 | 推理模型 |
|---|---|---|
| 输出形态 | 直接给答案 | 思考段 + 最终答案(可分通道控制) |
| 训练重点 | SFT + 偏好对齐 | 可验证奖励 RL(数学 / 代码 / 逻辑) |
| 算力特性 | 固定(一次前向) | 可变(思考 token 数可调) |
| 延迟 | 低而稳定 | 高且波动大 |
| 强项 | 常识问答、写作、摘要、对话 | 数学、竞赛题、代码、多步规划、复杂分析 |
| 弱项 | 多步严格推理容易错 | 简单问题上浪费算力、成本高 |
| 参数控制 | 温度、Top-K | 推理强度 / 思考预算(minimal → high) |
1.2 涌现的自我纠错与长度增长
RL 训练中会自然出现两种现象:一是模型开始写出类似 「等一下,我前面这一步好像不对,让我重新检查」 的反思语句,并据此修正;二是输出长度随训练增长,因为更长的思考在可验证奖励下更容易碰对答案,但长度增长会带来成本问题——这就是 GFPO、Dr.GRPO 这类工作的动机。
- 反思词很脆弱:CISPO 的观察是,标准的裁剪机制会把「wait / recheck / hmm」这类低概率 token 的梯度裁掉,反而不利于学习反思行为,因此改为只裁剪权重不裁剪 token。
- 难度自适应:理想情况下简单问题短思考、困难问题长思考。但实际中模型常常在简单问题上也冗长,需要通过训练信号或推理端控制来纠偏。
- 长度不等于能力:把长度当作代理指标会误导。要同时看准确率、token 效率(每正确一次的 token 成本)。
python# 监控「长度 vs 准确率 vs 熵」:判断长思考是能力还是凑长度
import numpy as np
def diagnose(lengths, correct, entropy):
L, C, H = np.array(lengths), np.array(correct, float), np.array(entropy)
print("长度-正确 相关:", round(float(np.corrcoef(L, C)[0, 1]), 3))
bins = np.digitize(L, np.quantile(L, [0.25, 0.5, 0.75]))
for b in range(4):
m = bins == b
if m.sum():
print(f"箱{b}: 均长={L[m].mean():.0f} 准确率={C[m].mean():.2f} "
f"token/correct={L[m].sum()/max(1, C[m].sum()):.0f}")
print("熵是否崩塌:", H[-1] < 0.5 * H[0])
# 预期输出(示意)
# 长度-正确 相关: 0.31 <- 弱正相关, 长度并非主导因素
# 箱0: 均长=210 准确率=0.96 token/correct=219
# 箱3: 均长=4200 准确率=0.63 token/correct=6667 <- 难题确需长思考但收益递减
# 熵是否崩塌: False
# 判读: 相关弱 + 难题 token/correct 飙升 = 长思考对难题必要, 简单题则是浪费
1.3 动手练习与自测
- 给定「思考 token 数与最终准确率」散点,如何判断模型是「真在推理」还是「在凑长度」?写出判据与两条对照实验。
- 同一问题用 temperature=0 与 0.8 各采样 8 次,准确率 82% / 79%,但后者 8 次里 6 次答案一致。这说明什么?
- 「长思维链一定是模型的真实推理」错在哪?给出至少两条反例场景。
- 把一次思考的边际收益量化:若第 k 次采样新增正确率 Δp≈0.02、单次成本 C,写出「是否值得再采样」的判据。
- 为什么 2026 年很多产品用「多采样 + 一致性检验 + 外部验证器」而非相信单次 CoT?
2. 怎么训练出推理能力
学习路径
- 读 2.1 的流程四步:理解冷启动 → RLVR → 拒绝采样 → 对齐的先后依赖
- 跑内置 reward() 代码,逐层观察正确性/格式/语言三个奖励项的叠加
- 完成 2.2 练习 1/4:写出 RLVR 三段权重与长度惩罚系数的作用
- 对接 M10:为 hamauls-orion 设计冷启动 + RLVR 的最小流程骨架
核心知识点详解
- 四步的先后依赖:前一步的问题由后一步解决:冷启动 SFT 解决「格式不规整」→ RLVR 解决「会推理」→ 拒绝采样固化为 SFT 数据 → 通用对齐解决「只会答题」。跳步会导致相应能力缺失。
- 冷启动 SFT 数据量不必大,格式最关键:核心是「先思考再回答」的格式一致性,可用数十万条高质量样本;数据少但格式统一远好于量大但格式乱(RL 阶段会格式崩溃)。
- 拒绝采样把 RL 学到的固化:用训练好的模型对大量 prompt 采样,只保留答对的轨迹做 SFT,把 RL 探索出的行为沉淀为更稳定的监督数据。保留比例常 10%–40%。
- 常见坑:一步到位直接上 RL:跳过冷启动直接 RLVR,模型会在格式与易读性上失控(类似 R1-Zero 的语言混杂),生产基本都要先冷启动。
学习路径
- 读 2.1:掌握正确性 1.0 / 格式 0.1 / 语言 0.05 的权重设计原则
- 跑内置 reward() 代码并改动权重,观察正确性不主导时模型会走捷径
- 完成 2.2 练习 1/3:说明为什么正确性必须绝对主导、格式过高会 hack
- 对接 M10:为数学/代码做可验证奖励,写进 RLVR 训练脚本
核心知识点详解
- 奖励权重设计:正确性绝对主导:典型
1.0 / 0.1 / 0.05(正确性 / 格式 / 语言)。正确性对应唯一真实目标,格式与语言只是护栏;权重过高会诱导模型牺牲正确性换格式分。 - 格式不符要惩罚而非零分:代码里
if "思考" in c and "答案" in c: r+=0.1 else: r-=0.1——不惩罚则模型会绕开格式约束,直接空答也拿满分。 - 严禁用长度或「自信」当奖励:把输出长度或语气自信作为加分项是奖励黑客的入口:模型会「写得更长/更像答对了」而不是真的对。
- 常见坑:只看格式通过率不看正确率:监控「格式通过率 100% 但正确率停滞」——这就是 hack 的可观测信号。格式分被模型拿满而未带来正确率提升,应立即降格式权重。
学习路径
- 读 2.1 的「三个典型翻车」:奖励 hack / 模式崩溃 / 长度失控
- 跑 diagnose 三曲线代码,观察熵崩塌怎么被捕捉
- 完成 2.2 练习 3:奖励升但熵降、长度暴涨时的排查顺序
- 对接 M10:把三曲线监控写进训练记录,定义自动告警阈值
核心知识点详解
- 三个典型翻车:奖励 hack / 模式崩溃 / 长度失控:① 格式奖励过高→模型输出格式对内容错;② 全部回答趋同、熵崩塌;③ 平均输出从约 500 涨到 8000 token、成本爆炸而准确率不涨。
- 排查顺序:熵 → ε → 长度惩罚 → KL:先看熵(是否模式崩溃)→ 再查 GRPO 裁剪系数 ε(常
1e-2~2e-2)→ 看长度惩罚是否缺失 → 最后检查 KL 约束。定位顺序即「先看健康再查超参」。 - 监控必须三曲线一起看四指标:奖励 / 长度 / 熵 / 通过率要同时记录。熵崩往往是长度失控的前兆,三者联合才能区分「健康长想」与「翻车」。
- 常见坑:只看训练损失和奖励:RL 训练里奖励上升可能掩盖熵崩塌。要配自动告警:熵跌破阈值或长度暴涨即触发,而非训练结束才发现。
学习路径
- 读 2.2 练习 2/4 的结论:掌握 A_i=(r_i−mean)/std 与 std=0 的丢弃处理
- 跑 diagnose/基准脚本或手写小 GRPO,验证裁剪系数 ε 的作用域
- 完成 2.2 练习 2/4:写出 std 除零工程处理与 α 太大/太小的后果
- 对接 M10:在你的 RLVR 里落地 ε 裁剪与长度惩罚两个超参
核心知识点详解
- GRPO 组内优势:无价值网络:优势
A_i = (r_i − mean(r)) / std(r),用同一 prompt 的组内奖励做基线,不需要独立 critic 网络(对比 PPO),显存更省、训练更稳。 - std=0 的除零处理:当组内 8 条轨迹全对(std=0),A_i 会除零产生 NaN。工程处理:丢弃该 prompt 或对 std 加平滑(
(std+1e-6)),并保持采样温度不过低以保证组内多样性。 - 裁剪系数 ε 与长度惩罚 α 的量级:目标
L=−E[min(ρA, clip(ρ,1−ε,1+ε)A)],ρ=π_θ/π_old,ε 常取 1e-2~2e-2 限制单步更新幅度;长度惩罚reward−=α·len的 α 常取 1e-4~1e-3。 - 常见坑:α 太大或太小:α=1e-1 会让模型「偷懒过早停」、准确率下降;α=1e-4 压不住过度思考——应取 1e-4~1e-3 并配合难度路由。
2.1 四步标准流程
python# 可验证奖励的典型组合:正确性 + 格式 + 语言一致
import re
def extract_boxed(text):
m = re.findall(r"\\boxed\{([^}]*)\}", text)
return m[-1].strip() if m else None
def reward(prompt, completion, gold):
r = 0.0
# 1) 正确性:主要奖励,权重占绝对主导
if extract_boxed(completion) == gold:
r += 1.0
# 2) 格式合规:必须有思考段与最终答案段
if "思考" in completion and "答案" in completion:
r += 0.1
else:
r -= 0.1 # 格式不对要惩罚,否则模型会绕开格式约束
# 3) 语言一致性:避免中英混杂(按目标语言判断)
if re.search(r"[\u4e00-\u9fff]", completion):
r += 0.05
return r
# 注意:绝不要用「长度」或「看起来自信」作为奖励 —— 那就是奖励黑客的入口
2.2 动手练习与自测
- 写出 RLVR 三段奖励(正确性 / 格式 / 语言)的典型权重,并说明为什么正确性必须占绝对主导。
- GRPO 的优势 A_i = (r_i − mean(r)) / std(r)。若某 prompt 的 8 条轨迹全对(std=0)会怎样?工程上如何处理?
- 奖励曲线上升但熵骤降、长度暴涨,最可能是哪一步出错?给出排查顺序。
- 设计「长度惩罚 reward −= alpha × len」,说明 alpha 取 1e-4 与 1e-1 各会造成什么后果。
- 为什么格式奖励权重过高会导致「奖励被 hack」?给一个可观测的监控指标。
3. 测试时计算扩展:把算力花在推理上
学习路径
- 读 3.1 表格:比对六种手段的收益/成本/适用
- 跑 self_consistency 代码,对比 k=1/5/10 的准确率与成本
- 完成 3.3 练习 1/2:用二项分布算多数正确概率、区分 Best-of-N 与自洽性前提
- 对接 M10:在 test-time-compute 实验里对比至少两种扩展手段的收益-成本
核心知识点详解
- 六种扩展手段一览:Best-of-N(配验证器)、自洽性多数投票(无验证器)、思维链提示、长思考预算、树搜索/回溯、多模型交叉验证。选择第一分叉是有无可靠验证器。
- 自洽性的数学收益:k 次独立采样多数投票,单次正确率 p>0.5 时正确概率提升(如 p=0.6、k=9 多数正确约 0.73);p<0.5 时投票反而放大错误,应先用一致性过滤后升级模型。
- 成本收益横比的关键:Best-of-N + 验证器性价比最高(有验证器);无验证器只能自洽性或 LLM-as-Judge(需接受其偏见)。成本上都约 N 倍生成。
- 常见坑:开放式任务硬套 Best-of-N:没有可靠验证器就做 Best-of-N,等于「随机选一个候选」,收益趋近零——先确认有没有自动验证手段再选方法。
学习路径
- 读 3.1 的 softmax/top_p 代码:弄懂热度和截断对多样性的影响
- 跑 softmax(top_p) 代码,打印 T=0.1~2.0 的分布变化
- 完成 3.3 练习 5:把一致性比例当置信度,说明阈值怎么定
- 对接 M10:在 sc.py 里用答案归一化 + 温度实验记录敏感性
核心知识点详解
- 温度越高分布越均匀:softmax 除以 T 后概率趋于均匀:T=0.1 近似贪心(多样性≈0),T=1.0 保留原始分布,T=2.0 使所有候选接近等概率。用
np.exp(z/T)/sum一算便知。 - top_p 截断保留最小高概率集合:
top_p_filter(probs, 0.9)把累计概率到 0.9 的最小集合保留并重新归一化,去掉长尾低概率 token;数值上对超过 p 的集合之外全部置零再归一。 - 自洽性采样的推荐参数:经验上用 T=0.7~1.0 + top_p=0.9~0.95;温度过高会引入低级错误,过低则样本间差异小、投票失效。
- 常见坑:用一致性比例当严谨置信度却不定阈值:一致性比例(得票最高答案占比)可当置信度,但低于阈值(约 0.5)就该升级/转人工;否则把「瞎猜的多数」当结论也是错的。
学习路径
- 读 3.2:理解 ORM vs PRM 的监督信号差异与自动 PRM 的偏见
- 跑 reward() 或自洽性代码,体会验证器排序在 Best-of-N 里的作用
- 完成 3.3 练习 3:写出 PRM 连乘打分公式并解释为何用连乘
- 对接 M10:实现 prm.py 打分器并用于 Best-of-N 重排
核心知识点详解
- ORM 稀疏 vs PRM 密集:ORM 只看最终答案对错(信号稀疏、长推理难定位错步);PRM 对每一步打分(信号密集、可做逐步剪枝)。代价是 PRM 标注昂贵、步骤边界模糊。
- 自动 PRM 的偏见:用强模型/规则自动标注步骤,成本可控但继承教师偏见,可能强化某些错误模式——需人工抽查校准。
- PRM 连乘打分公式:轨迹分
= Π PRM(step_i),log 形式exp(Σ log max(p_i,1e-3))。连乘让任一步错误显著拉低整条轨迹,平均值会被单步高分稀释,因而不该用平均。 - 常见坑:PRM 与生成模型耦合不校准:PRM 训练数据偏向某类写法会导致「PRM 高分但答案错」比例上升,需 PRM 与生成模型解耦、定期用新数据校准(见 9.4 缓解)。
学习路径
- 读 3.1/3.2 的选型判断:先看有无验证器再定方法
- 跑 self_consistency 测温,读 p=0.5 分水岭的可视结果
- 完成 3.3 练习 4:解释「有世界模型≠会用」对 Agent 设计的启示
- 对接 M10:写出你在哪种子集用什么方法、依据是什么的决策备忘
核心知识点详解
- 选型第一问:有无验证器:有**(数学、单测、schema)→ Best-of-N,性价比最高;没有**(写作、开放问答)→ 自洽性 + 一致性置信度,或 LLM-as-Judge(接受偏见)。
- p=0.5 是自洽性的分水岭:单次正确率超过 0.5 时投票获放大正确、低于 0.5 时放大错误。因此先测温:若模型对该题一致性已低于 0.5,投票前应先升级模型。
- 把「世界模型≠会用」记进 Agent 设计:即便给 Agent 模拟能力,若缺乏「何时该用」的元判断,实际使用率可能不足 1%(部分实验),引入模拟反而可能降性能——能力与判断力要一起训练。
- 常见坑:忽略代价就定方法:任何选择都要量化:Best-of-N 是 N× 生成、树搜索是 b^d、多模型交叉是多次调用——选前先写下成本量级。
3.1 六种手段与成本收益
| 手段 | 做法 | 收益 | 成本 | 适用 |
|---|---|---|---|---|
| Best-of-N | 采样 N 个答案,用验证器 / 奖励模型筛最好的 | 中–高 | N 倍生成 + 验证 | 有可靠验证器的任务 |
| 自洽性(Self-Consistency) | 多次采样后对最终答案做多数投票 | 中 | N 倍生成 | 答案可归一化比较(数学、选择题) |
| 思维链提示 | 显式要求分步推理 | 低–中 | 略增 token | 几乎所有任务的基础手段 |
| 长思考预算 | 让模型自主决定想多久(推理强度档位) | 高 | 延迟与 token 大增 | 难题、Agent 规划 |
| 树搜索 / 回溯 | 把推理展开成树,逐步评估并回溯 | 高 | 搜索开销可能很大 | 可分解、可评估的任务 |
| 多模型 / 多角色交叉验证 | 生成 + 批判 + 修订分工 | 中–高 | 多次调用 | 高风险决策、评审场景 |
python# 自洽性(Self-Consistency):最简单、最实用的测试时扩展手段
import asyncio, re, collections
def normalize(ans):
if ans is None: return None
return re.sub(r"[,\s$%]", "", str(ans)).lower()
async def self_consistency(llm, question, n=9, temperature=0.8):
async def one():
text = await llm.chat(
[{"role": "system", "content": "分步推理,最后一行输出「答案: XXX」"},
{"role": "user", "content": question}],
temperature=temperature)
m = re.search(r"答案[::]\s*(.+)", text)
return normalize(m.group(1) if m else None)
answers = await asyncio.gather(*[one() for _ in range(n)])
answers = [a for a in answers if a]
if not answers: return None, 0.0
top, cnt = collections.Counter(answers).most_common(1)[0]
return top, cnt / len(answers) # 一致性比例可以当置信度用
# 实用技巧:把「一致性比例」作为置信度,低于阈值就升级到更强模型或转人工
python# 采样温度与 top-p:控制探索多样性的两个旋钮(自洽性采样的核心超参)
import numpy as np
def softmax(logits, temperature=1.0):
z = np.asarray(logits, dtype=float) / max(temperature, 1e-6)
z -= z.max() # 数值稳定
e = np.exp(z)
return e / e.sum()
def top_p_filter(probs, p=0.9):
order = np.argsort(probs)[::-1] # 按概率降序
csum = np.cumsum(probs[order])
keep = order[:np.searchsorted(csum, p) + 1] # 最小的高概率集合
out = np.zeros_like(probs); out[keep] = probs[keep]
return out / out.sum() # 重新归一化
logits = [3.0, 2.0, 1.0, 0.5, -1.0]
for T in [0.1, 0.7, 1.0, 2.0]:
print(f"T={T}:", np.round(softmax(logits, T), 3))
# 预期输出(示意):
# T=0.1: [1. 0. 0. 0. 0.] <- 几乎贪心,多样性≈0
# T=0.7: [0.66 0.24 0.09 0.01 0.]
# T=1.0: [0.52 0.19 0.07 0.04 0.01]
# T=2.0: [0.34 0.21 0.12 0.09 0.04] <- 更均匀,适合多采样投票
# 经验:自洽性采样用 T=0.7~1.0 + top_p=0.9~0.95;温度过高会引入低级错误
3.2 过程奖励模型(PRM)与验证器
结果奖励只看最终答案,问题是在几十步推理里无法定位是哪一步错了。过程奖励模型(PRM)对每一个中间步骤打分,从而支持逐步搜索与早期剪枝。代价是需要过程级标注,人工成本高,且标注标准难以统一。
| 类型 | 监督信号 | 优点 | 缺点 |
|---|---|---|---|
| ORM(结果奖励) | 只看最终答案对错 | 标注廉价、易自动化 | 长推理里信用分配困难,学习信号稀疏 |
| PRM(过程奖励) | 每一步是否正确 | 信号密集、支持搜索与剪枝 | 标注昂贵、步骤边界定义模糊 |
| 自动 PRM | 用强模型 / 规则自动标注步骤 | 成本可控 | 继承教师偏见,可能强化错误模式 |
| 验证器(Verifier) | 判断一个候选答案是否正确 | 可直接用于 Best-of-N 排序 | 对开放式任务难以定义「正确」 |
3.3 动手练习与自测
- 设单次正确率 p=0.6、k=9 自洽性投票(独立采样),用二项分布估算「多数正确」的概率,并解释 p<0.5 时投票为何反而有害。
- Best-of-N 与自洽性的区别是什么?分别需要什么前提才能生效?
- 写出用 PRM 给一条含 5 步的轨迹打分的连乘公式,并解释为什么用连乘(log 求和)而非平均。
- 「有世界模型不等于会用」这一发现,对 Agent 与推理系统设计有什么直接启示?
- 把「一致性比例」当置信度时,阈值该定多少?给出依据。
4. 推理效率:把长思考的代价降下来
学习路径
- 读 4.1 的六条策略:理解难度路由/预算上限/折叠/缓存/蒸馏/混合部署
- 跑内置 ROUTES 数据,看难度路由如何按信号分档
- 完成 4.2 练习 3:说明不落库/缓存/蒸馏各降哪部分成本
- 对接 M10:在 budget.py 里落地难度路由 + 缓存两招
核心知识点详解
- 难度路由是成本优化的单点之王:先分类简单/难题,简单题只走非推理/低预算模型(
trivial→0 token),难题才开长思考。把占用大头的简单请求思考降到 0 是最有效的单点优化。 - 预算上限 + 早期停止 + 思考不落库:设最大思考 token;多次采样一致则提前停止;思考折叠/不返回避免上下文膨胀。三者分别压「上限」「长尾」「多轮」三块成本。
- 缓存 + 蒸馏 + 混合部署的落点:语义缓存消除重复计算(近零成本);蒸馏用小模型约
1/10成本覆盖常见题;小模型兜底约 90% 请求、难题升级大模型并自动 fallback。 - 常见坑:默认全开最高推理强度:「默认 high 档」会让简单题也烧长思考,账单轻易翻 10 倍以上;上线前必须先统计真实流量的思考 token 分布。
学习路径
- 读 4.1 的 Budget 类:掌握 trivial→critical 四档的 token 预算
- 跑 route() 代码,观察 classify 对 signals 的映射
- 完成 4.2 练习 1/4:估算流量成本比、说明误判代价不对称
- 对接 M10:实现 budget.py 路由器,把简单题预算压到 0
核心知识点详解
- 四档预算的 token 设计:
trivial: 0、normal: ~512、hard: ~4096、critical: 16384+,并配合不同模型(8B / Sonnet / Opus)。简单题直接0思考。 - 成本估算公式:估算成本
≈ b.samples × (b.max_think_tokens + 512),从Budget里可算;真实流量上要再乘以各自的请求占比。 - 误判代价不对称 = 阈值要偏保守:把简单题误判难题只是浪费算力(可容忍);把难题误判简单会直接答错(不可容忍)。所以
classify的难度阈值要保守,宁可多花也不能漏难题。 - 常见坑:只按平均 token 配容量:成本由少数超长思考(P99)主导,用均值规划会低估峰值;要用分位数统计思考长度分布做容量规划。
学习路径
- 读 4.1 的「成本陷阱」:思考 token 是答案的 10–50 倍
- 跑 infer_cost(100万) 代码,确认思考成本是答案的约 20 倍
- 完成 4.2 练习 2/5:写出成本公式、用分位数做容量规划
- 对接 M10:上线前统计真实 token 分布,标出 P99 思考长度
核心知识点详解
- 思考 token 单价与输出同档,量却大 10–50×:推理 token 通常按输出价计费,而长思考的量是答案的
10–50倍,所以控制思考 token 比控制答案长度重要一个数量级。 - 成本公式与最敏感变量:
cost ≈ N×(c_in·L_in + c_think·L_think + c_out·L_out),最敏感的是 N(采样次数)× L_think(思考长度) 的乘积——这正是「降采样次数 + 压思考长度」优先级最高的原因。 - infer_cost 的量级直觉:100 万请求、20% 难题、难题思考 4000 token×3 次采样时,思考成本约 4800 万、答案约 240 万——思考是答案的约 20 倍。
- 常见坑:上线前不统计真实 token 分布:必须统计真实流量的思考 token 分布并标出 P99,否则「高均值被少数超长请求掩盖」,容量规划会系统性失真。
学习路径
- 读 4.2 练习 2 结论:掌握 cost≈N×(in+think+out) 与最敏感项
- 跑 infer_cost 代码改 p_hard/L_think,看成本怎么变
- 完成 4.2 练习 4:分析简单/难题误判的代价不对称
- 对接 M10:给出你预算曲线上的容量结论(分位数)
核心知识点详解
- 成本 = 四类 token × 单价之和:
cost ≈ N_samples × (c_in·L_in + c_think·L_think + c_out·L_out);在推理模型里N×L_think是绝对大头。 - 参数敏感度实验:改
p_hard(难题占比)或L_think(难题思考长度)观察成本曲线:把 80% 简单题思考压到 0、限制难题采样次数,是两个最大的杠杆。 - 误判代价不对称的量化:简单题误判难题 = 浪费几次前向(成本线性损失);难题误判简单 = 答错(业务损失)。保守阈值的期望损失更低,所以路由宁严勿松。
- 常见坑:用均值而非分位数做容量规划:思考长度是长尾分布,成本由 P99 主导。要用分位数(P50/P99)而非均值规划 GPU 数量与预算,否则高峰吞吐不够。
4.1 产品化的四层策略
python# 推理预算路由器:按难度与置信度决定「花多少算力」
from dataclasses import dataclass
@dataclass
class Budget:
model: str
max_think_tokens: int
samples: int
ROUTES = {
"trivial": Budget("qwen3-8b", 0, 1), # 不思考
"normal": Budget("qwen3-8b", 512, 1),
"hard": Budget("claude-sonnet-4-5", 4096, 3),
"critical": Budget("claude-opus-4-7", 16384, 9),
}
def classify(question: str, signals: dict) -> str:
"""信号可来自:问题长度、是否含数学/代码、检索命中度、历史失败率。"""
if signals.get("is_high_stakes"): return "critical"
if signals.get("has_math") or signals.get("needs_planning"): return "hard"
if len(question) < 20 and signals.get("cached_similar"): return "trivial"
return "normal"
def route(question, signals):
b = ROUTES[classify(question, signals)]
return b, {"estimated_cost": b.samples * (b.max_think_tokens + 512)}
4.2 动手练习与自测
- 给一个 100 万日请求、简单题占 80% 的流量模型,估算「全部开 high 档」与「按难度路由」的成本比。
- 写出推理成本的近似公式(含输入 token、思考 token、答案 token、采样次数),指出哪个变量最敏感。
- 思考不落库、缓存命中、蒸馏到小模型,三者各降的是哪部分成本?
- 路由器把 5% 的简单题误判成难题,代价是多少?把 5% 的难题误判成简单题呢?哪个更严重?
- 为什么「思考 token 分布」比「平均思考 token」更适合做上线前的容量规划?
5. 评测与污染:怎么知道模型真的会推理
学习路径
- 读 5.1 表格:理解各基准考什么与局限
- 跑 pollution 检测样例(或先看 shadow eval 思路),明白可靠信号来自哪
- 完成 5.2 练习 2/3:说明小样本方差风险与 shadow eval 代价
- 对接 M10:在评测脚本里记录每个子集的样本数与置信区间
核心知识点详解
- 各基准的局限:AIME/MATH 已被大量污染分数虚高;GPQA Diamond 题少方差大;SWE-bench 更强但依赖环境/版本;τ-bench 需模拟环境成本高;ARC-AGI-2 难被记忆但相关性有争议。
- 影子评估最抗污染:用尚未公开的高质量任务、由原作者打分,彻底规避污染,但成本高、难规模化。
- 判断分数是否可信:必须同时给样本数 + bootstrap 置信区间。小样本(如 AIME 仅约 30 题)单题权重 3%+,一两题的波动就能改几个百分点,没区间不可比。
- 常见坑:把公开榜当唯一依据:公开对抗基准可靠性在下降,最可信的信号来自私有、可溯源、自建的评测集——报告要含来源/风险分类/复现步骤。
学习路径
- 读 5.1 的「2026 评测共识」:从分数好看转向过程可信
- 跑污染检测代码,体验私有溯源自建集的可信度
- 完成 5.2 练习 5:说明自建评测按难度/场景如何分层
- 对接 M10:写出你的评测报告模板(来源/风险分类/复现步骤)
核心知识点详解
- 2026 评测共识:从分数好看转向过程可信:报告要讲清数据集来源、覆盖的风险分类、攻击方法、评估框架、复现步骤,而不只是报一个总分——这才叫「过程可信」。
- 私有可溯源自建集优于刷公开榜:用自己领域的真实样本建评测集,能反映真实业务分布且可溯源,比在公开榜刷分更有工程意义。
- 评测按难度与场景分层:自建集要按难度(易/中/难)与场景(数学/代码/多跳/业务)分层,并保证每层样本量足够给稳定估计。
- 常见坑:报告模板漏了风险分类:只写「准确率 X%」的评测报告无法被信任——补上样本来源、失败分布、复现命令,分数才有可审计性。
学习路径
- 读 5.1 的污染代码:理解 13-gram 重合检测的原理与阈值
- 跑 contamination_rate 代码,对你的评测集也跑一遍
- 完成 5.2 练习 1/4:说明 >5% 为何不可信、如何检测「被测试」
- 对接 M10:给每个子集附 bootstrap 置信区间
核心知识点详解
- 13-gram 重合检测:把文本切成连续的 13 个词元组合,求训练集与评测集的重合;
contamination_rate = 命中的评测样本数 / 总数。重合高说明评测文本几乎在训练集里出现过。 - 经验阈值:>1% 警惕,>5% 不可信:13-gram 重合率 >1% 就要警惕(越界可能是巧合),>5% 时指标基本不可信,必须换评测集或重建。
- bootstrap 给置信区间:对评测样本重采样(如 1000 次 bootstrap)算指标的分布,得到置信区间,避免单独样本波动造成「虚高/虚低」。
- 常见坑:只测词级不测嵌入级:13-gram 是字面重合;语义改写后污染仍存在。要配合嵌入级相似度、时间切分(用训练截止后数据)更彻底地查污染。
学习路径
- 读 5.2 练习 5 的答案:理解难度/场景分层与样本量原则
- 跑评测脚本在自有子集上分层统计,检查层内方差
- 完成 5.2 练习 2/4:写小样本方差示例与「被测试」检测法
- 对接 M10:建一套私有可溯源的评测集并给出稳定估计
核心知识点详解
- 分层评测:按难度与场景:样本按难度(易/中/难)与场景(数学/代码/多跳/业务)分层,每层单独出准确率;总准确率要按实际流量占比加权,避免「简单题拉高总分」。
- 样本量与估计稳定性:层内样本太少(如个位数)时,单题权重大、方差大,估计不稳定。目标是用 bootstrap 验证层内方差可接受,否则补样本或归并成更粗的层。
- 检测「怀疑自己被测试」:通过对比「明示测试任务 vs 自然提问」的分数差来检测模型是否「表演性」地按测试样式作答,避免低估/高估真实能力。
- 常见坑:总准确率被简单题稀释:不按难度分层看总分,会被大量简单题掩盖弱项。一定要拆层看「每层的稳定估计」,再想能否上线。
5.1 关键基准与它们的局限
| 基准 | 考什么 | 局限 |
|---|---|---|
| AIME / MATH | 数学竞赛与解题 | 公开题已被大量训练污染,分数虚高 |
| GPQA Diamond | 研究生级科学问答 | 题目数量少,方差大;公开后污染风险高 |
| SWE-bench / SWE-bench Verified | 真实仓库的缺陷修复 | 更接近工程真实能力,但依赖环境与版本 |
| τ-bench 类 | 多步工具使用与业务规则遵从 | 需要模拟环境,构建成本高 |
| ARC-AGI-2 | 抽象与泛化推理 | 与真实任务相关性有争议,但很难被记忆 |
| Humanity Last Exam 类 | 专家级跨学科难题 | 部分题目本身存在争议 |
| 影子评估(Shadow Eval) | 用尚未公开的高质量研究做任务,由原作者打分 | 彻底规避污染,成本高、难以规模化 |
python# 污染检查:训练集与评测集的 n-gram 重合检测(上线前必做)
import re, collections
def ngrams(text, n=13):
t = re.findall(r"\w+", text.lower())
return {" ".join(t[i:i + n]) for i in range(max(1, len(t) - n + 1))}
def contamination_rate(train_texts, eval_texts, n=13):
train_ng = set()
for t in train_texts:
train_ng |= ngrams(t, n)
hits = sum(1 for e in eval_texts if ngrams(e, n) & train_ng)
return hits / max(1, len(eval_texts))
# 经验阈值:>1% 就要警惕;>5% 说明指标基本不可信,必须换评测集
print("contamination:", contamination_rate(pretrain_docs, eval_set))
5.2 动手练习与自测
- 用 13-gram 重合率检查评测集污染,说明为什么阈值通常设在 1%(>5% 不可信)。
- 报告 AIME 分数时为什么必须同时给「样本数 + 置信区间」?举例说明小样本的方差风险。
- 影子评估(Shadow Eval)为什么能规避污染?它的代价是什么?
- 「模型怀疑自己在被测试」这类现象会如何影响分数?如何检测?
- 自建评测集时,样本该如何按难度与场景分层?
6. 推理模型谱系与训练路径
学习路径
- 读 6.1 表格:比较主流推理模型的思考可见性/RL方式/开源差异
- 跑一次 CoT 请求,观察你所选模型的思考可见性选项
- 完成 6.4 练习 1:写出 GRPO 组内优势与截断目标、ε 取值
- 对接 M10:说明你目标模型的思考可见性对预算路由的影响
核心知识点详解
- 谱系差异四维度:思考可见性(隐藏 vs 暴露)、训练数据(冷启动 / 私有题海)、RL 方式(GRPO vs 闭源)、是否开源——这四个维度决定「能否自部署、思考要不要给用户看」。
- 开源 vs 闭源的判断:需自部署/可审计思考/要蒸馏 ⇒ 优看 DeepSeek-R1、Qwen;追求最强单点能力且接受成本 ⇒ o 系列 / Gemini 3 / Claude extended thinking。
- 2026 共识:难题差距缩小:头部推理模型在难题上的差距已缩到几个百分点,真正的区分是成本、延迟与可控性(可否关思考、可否路由)。
- 常见坑:只看排行榜分点差:别为「高 1–2 个百分点的闭源」忽略可自部署开源方案的成本优势;先算 QPS × 成本 × 可控性再选型。
学习路径
- 读 6.2:理解稀疏奖励 + 大探索空间如何让长 CoT 被强化出来
- 跑 diagnose 三曲线代码,观察训练中长度/熵的先升后崩
- 完成 6.4 练习 3:解释为什么长 CoT 是被 RL 涌现而非人工写入
- 对接 M10:用你模型的轨迹数据统计反思语出现率
核心知识点详解
- 稀疏结果奖励 + 大探索空间催生长 CoT:奖励只给最终正确性(RLVR),模型在 RL 中自动发现「多写几步、自我检查、回溯」能提高奖励,于是长 CoT 作为高奖励策略被强化,而非人工写入。
- GRPO 组内优势做基线:
A_i=(r_i−mean)/std用组内相对优势,无独立 critic;目标含min(ρA, clip(ρ,1−ε,1+ε)A),ε≈1e-2~2e-2防更新过大。 - 为什么是 RL 而非 SFT:SFT 上限是示范数据本身;RL 能探索出示范里没有的更长、更绕但更准的路径——R1-Zero 无 CoT 冷启动也涌现反思语即是证据。
- 常见坑:熵先升后崩不处理:RL 中熵会先升(探索)后崩(收敛到少数套路)。若崩太快说明探索不足、易模式崩溃,需同时监控奖励/长度/熵/通过率。
学习路径
- 读 6.3 表格:对比 R1-Zero 与 R1 在可读性/收敛上的取舍
- 复盘 2.1 冷启动的数据格式,理解为何格式必须统一
- 完成 6.4 练习 2:说明工业界为何几乎都选 R1 路线
- 对接 M10:写下你冷启动样本的格式规范并落地样例
核心知识点详解
- R1-Zero 证明「无需人工 CoT」:基座直接 RLVR 也能涌现长 CoT,证明长 CoT 可被纯 RL 强化;但可读性差、语言混杂、收敛慢。
- R1 加冷启动换取可用性:先 SFT 少量格式规整 CoT(几十万条即可),换来可读性、稳定性与更快收敛,且几乎不损上限——工业界几乎都走 R1 路线。
- 冷启动格式必须统一:强制「思考段 + 答案段」结构;只要格式乱,RL 阶段就会格式崩溃、语言混杂。格式一致性 > 数据量。
- 常见坑:冷启动数据越多越好:错。冷启动是「授格式」,几十万条高质量的优先级远高于海量凑数样本。质量与统一性才是决定因素。
学习路径
- 读 6.4 练习 5 答案:理解 DAPO/GSPO 各自解决什么问题
- 对照 2.1 的 GRPO 公式,看 DAPO 解耦裁剪为何更稳
- 完成 6.4 练习 5:写出 DAPO/GSPO 相对 GRPO 的改进点
- 对接 M10:在你的 RLVR 里选一种变体并说明选择依据
核心知识点详解
- GRPO 是基线:无 critic 组内优势:
A_i=(r_i−mean)/std,省显存、稳定;但长推理里 token 级重要性比方差大、裁剪交互可出问题。 - DAPO 解决长推理训练的稳定与熵:用动态采样(适邻起采样避免熵过早崩)与解耦裁剪(对正负 token 分别处理、放宽上界),稳定「长度增长」阶段。
- GSPO 把重要性比放到序列级:GRPO/DAPO 的裁剪对 token 级 ρ 施加,长序列方差大;GSPO 用序列级重要性比缓解长路径梯度方差。
- 常见坑:无脑用 GRPO 默认超参:训练长 CoT 时直接搬 GRPO 默认正值可能熵崩/长度失控;生产用 DAPO 的动态采样 + 解耦裁剪更稳。
6.1 公开做法对比:不只是「多想一会儿」
2024–2026 年主流推理模型在思考可见性、训练数据、RL 方式、是否开源上差异很大。理解这些差异能帮你判断「该用哪个、能不能自部署、思考过程要不要给用户看」。
| 模型 / 家族 | 思考可见性 | 训练核心 | RL 方式 | 冷启动 | 开源 | 代表 |
|---|---|---|---|---|---|---|
| OpenAI o 系列 (o1/o2/o3) | 默认隐藏,仅暴露摘要 | 大规模 RLVR + 私有题海 | 闭源未公开 | 未公开 | 否 | GPT-5 内集成思考 |
| DeepSeek-R1 | 以 | 冷启动 SFT 800k + RLVR | GRPO 类 | 有 (R1) | 是 (含蒸馏小模型) | DeepSeek-R1 / R1-0528 |
| Qwen QwQ / Qwen3 思考 | 可见,可关闭 | 长 CoT SFT + RL | GRPO / DAPO | 有 | 是 | QwQ-32B / Qwen3-235B |
| Gemini thinking / Gemini 3 | 可选显隐 | 多模态 RLVR | 闭源 | 未公开 | 否 | Gemini 3 原生多模态思考 |
| Claude extended thinking | 可见、可关闭、可与工具并行 | RLHF 风格 + 工具使用思考 | 闭源 | 未公开 | 否 | Claude 4.5 / 4.7 |
| 模型 | 典型难题表现(示意) | 思考 token 量级 | 相对成本 | 备注 |
|---|---|---|---|---|
| DeepSeek-R1-0528 | AIME 2024 ~91%、GPQA 高 | 2k–16k | 低(开源可自部署) | 思考链可见,适合蒸馏 |
| Qwen3-235B (thinking) | 数学 / 代码接近头部 | 1k–8k(可关闭) | 中 | 混合思考模式,可路由 |
| o 系列 / GPT-5 | 难题领先,隐藏思考 | 隐藏(仅摘要) | 高 | 思考集成进统一模型 |
| Gemini 3 | 原生多模态思考领先 | 可选显隐 | 高 | 图像 / 视频 / 文本统一推理 |
| Claude 4.5 / 4.7 | 长程 Agent 与工具调用稳 | 可配置上限 | 高 | 支持思考与工具并行 |
6.2 长 CoT 是怎么被 RL「涌现」出来的
关键机制:当奖励只对最终正确性给出稀疏信号,而探索空间足够大时,模型在 RL 中会自动发现「多写几步、自我检查、回溯」能提高奖励,于是长思维链作为获得高奖励的策略被强化,而非被人工写进数据。这解释了为什么 R1-Zero(无任何 CoT 冷启动)也会自发出现反思语。
以 GRPO 为例,其优势函数不依赖独立价值网络,而是用同一 prompt 的组内奖励做基线:
text# GRPO 的优势估计(无 critic):组内相对优势
# 对同一个 prompt 采样 G 条轨迹 {o_i},得到奖励 {r_i}
# 优势 A_i = (r_i - mean(r)) / std(r) # 组均值与标准差
# 策略梯度目标(截断):
# L(θ) = -E[ min( ρ_i * A_i, clip(ρ_i, 1-ε, 1+ε) * A_i ) ]
# ρ_i = exp( log π_θ(o_i) - log π_old(o_i) ) ε 常取 1e-2 ~ 2e-2
# 奖励只来自答案是否正确(RLVR),长度不被直接奖励
# → 模型为了「更可能答对」主动拉长思考、引入自我检查
- 涌现的副作用:长度随训练单调增长;熵可能先升后崩(过早收敛到少数套路)。监控曲线必须同时看 奖励 / 长度 / 熵 / 通过率。
- 稀疏奖励难题:纯结果奖励在长链里信用分配困难。PRM(9 节)或过程奖励是把信号「铺到每一步」的主流解法。
- 为什么是 RL 而不是 SFT:SFT 只能模仿已有 CoT,上限是示范数据;RL 能探索出示范里没有的更长、更绕但更准的路径。
6.3 冷启动 SFT + RL 的两条路线:R1-Zero vs R1
| 维度 | R1-Zero(纯 RL) | R1(冷启动 + RL) |
|---|---|---|
| 起点 | 基座模型直接做 RLVR | 先 SFT 少量高质量 CoT 再 RL |
| 可读性 | 差,语言混杂、格式乱 | 好,格式规整、可读性强 |
| 语言混杂 | 中英文夹杂明显 | 被冷启动数据显著抑制 |
| 收敛效率 | 较慢,需更多步探索 | 更快收敛到可读模式 |
| 最终能力 | 接近 R1 | 略高且更易用 |
| 适用场景 | 研究验证「涌现」 | 生产部署首选 |
结论:R1-Zero 证明了长 CoT 可以被纯 RL 涌现(回答了「是不是必须人工写 CoT」);R1 证明加一点冷启动 SFT 能换来可读性、稳定性与更快收敛,且几乎不损上限。2026 年的工业实践几乎都走 R1 路线:冷启动数据量不大(几十万条即可),但格式一致性要求极高。
6.4 动手练习与自测
- 写出 GRPO 的组内优势与截断目标,并说明 ε 的典型取值与作用。
- R1-Zero(纯 RL)与 R1(冷启动 + RL)的主要差异是什么?为什么工业界几乎都选 R1 路线?
- 长 CoT 为什么能被 RL「涌现」出来,而不是被人工写进数据?给出机制解释。
- 若没有验证器(开放式任务),能否复刻 R1 的 RLVR 流程?为什么?
- DAPO / GSPO 相对原始 GRPO 各解决了什么问题?
7. 提示侧推理技术:不训练也能变强
学习路径
- 读 7.1:理解零样本 CoT 的 10–30pp 提升与 few-shot 示范
- 跑 zero_shot_cot 代码,设 temperature=0 观察稳定输出
- 完成 7.5 练习 1:说明零样本 CoT 是激活先验还是赋予能力
- 对接 M10:在 cot.py 里落地 CoT 结构化输出与终止条件
核心知识点详解
- 零样本 CoT 提升 10–30pp:仅加一句「让我们一步步思考」(
SYSTEM_COT)就可在多数推理任务上提升 10–30 个百分点;few-shot 再给 2–4 个带推理过程的范例进一步稳定。 - temperature=0 保确定:单条轨迹想要确定性用
temperature=0;要多样性配合 7.2 自洽性则用较高温多次采样。 - 本质是激活先验,不是赋能力:CoT 提示是把模型先验里已有的分步推理行为激活出来,并没让模型学会新技能——「模型本来不会的,提示救不了」。
- 常见坑:零样本 CoT 在长任务上中途跑偏:步骤长、易走岔、答案难抽取时零样本 CoT 不够;此时应上周自洽性或树搜索(ToT),别硬扛。
学习路径
- 读 7.2:理解多数投票降方差与 p=0.5 分水岭
- 跑 majority_correct 代码,看 k 增长对不同 p 的正确率曲线
- 完成 7.5 练习 2:写出 majority vote 伪代码,区分它和 pass@k
- 对接 M10:在 sc.py 里实现自洽性投票 + 温度样本数实验
核心知识点详解
- 多数投票降方差:对 k 条独立采样做答案多数投票,只要单次正确率 p>0.5,多数正确的概率随 k 增大而上升;k 越大越接近 p=1。
- p=0.5 是分水岭:用
majority_correct(p,k)=Σ_{i≥need} C(k,i)p^i(1−p)^{k-i}算:p=0.5 时恒为 0.5(投票无效),p<0.5 时投票放大错误。应先升级模型再投票。 - k=8~16 是甜蜜点:实际里 k 到 8~16 后边际收益快速趋平(k=20→40 提升仅 1–2pp 却多几十倍成本);多数投票救不了「模型完全不会」的题。
- 常见坑:混淆 majority@k 与 pass@k:majority 看「投票后是否对」(部署可用);pass@k 看「k 次里至少一次对」(能力上限)。别拿 pass@k 冒充单次部署准确率。
学习路径
- 读 7.3:理解 ToT 的扩展→评估→搜索骨架
- 跑 tree_of_thoughts 极简骨架,观察广度/深度对结果的影响
- 完成 7.5 练习 3:算 b=3,d=4 的完整展开与剪枝后的调用数
- 对接 M10:在难子集上用 PRM 当评估函数做一次 ToT 试跑
核心知识点详解
- ToT 骨架:扩展→评估→选择/回溯:
tree_of_thoughts(problem, expand, evaluate, breadth, depth):每节点扩展出 b 个候选,用评估函数打分排序,只保留 top-b,再向下一层,最后取最优叶路径。 - 成本是 b^d:完整展开需
b^d次评估:b=3、d=4 时完整约3^4=81次。每层只留 3 个分支时降到约 36 次(数量级下降)。 - 评估函数可选 PRM/Judge/checker:评估可来自
PRM打分、LLM-as-Judge或可执行的 checker;评估质量直接决定搜索是否有效。 - 常见坑:分支因子或深度无上限:b/d 过大则 b^d 爆炸。必须给 b、d 设预算上限,并用 PRM 早停剪枝低分分支,否则单次请求延迟不可控。
学习路径
- 读 7.4:理解 GoT 的分支聚合与适用条件
- 对照 7.3 的 ToT 代码,想清楚 sum/vote/keep-best 的差异
- 完成 7.5 练习 4:说明什么任务才值得上 GoT
- 对接 M10:判断你的任务是否为图结构,写下取舍结论
核心知识点详解
- GoT 增加分支聚合:相比 ToT 分支独立,GoT 允许不同分支汇聚合并,聚合操作有
sum(LLM 综合拼接)、vote(多数投票)、keep-best(保留最优)。 - 何时 GoT 划算:只有当问题天然是图结构、需要综合多条子结论(如「多视角互补后汇总」「子目标并行再合并」)时才值得;多数场景 ROI 不划算。
- 2026 主流仍是自洽性 + 少量 ToT:大多数团队用「自洽性 + 少量 ToT 回溯」;纯 GoT 多用于研究或特定规划,工程复杂度高是主要原因。
- 常见坑:把顺序任务硬建模成图:任务步骤是严格线性依赖时强上 GoT 只会增加聚合复杂度而无收益——先判断子结论是否真能并行/互补。
学习路径
- 读 7.5:对照 CoT/自洽性/ToT/GoT 的取舍
- 跑自洽性 + 少量 ToT 回溯,对比单链的准确率
- 完成 7.5 练习 2/5:区分 pass@k 与 consistency、解释提示上限
- 对接 M10:写出你在这轮里选的方法组合与理由
核心知识点详解
- 方法取舍要按「模型已会 + 答案可验证」:模型不会的任务用 ToT/GoT 徒增成本;模型已会但答案可归一化则自洽性性价比最高;可分解且需回溯才上 ToT/MCTS。
- pass@k vs consistency 分工:pass@k 看能力上限(多次采样的最优),consistency/自洽性看部署形态(多数投票后的表现)——选方法前先分清你要测哪个。
- 记住提示的上限:「模型本来不会的,提示救不了」:若多次 CoT 一致都错,说明是能力缺口,该靠训练/工具/蒸馏,而非加搜索。
- 常见坑:什么任务都上最强的搜索:搜索(ToT/MCTS)成本 b^d 级。多数任务自洽性就够;上更强的搜索前先确认验证器可靠、任务可分解,否则评估噪声盖过收益。
7.1 零样本 / few-shot CoT
最便宜的推理增强是提示本身。零样本 CoT 仅加一句「让我们一步步思考」(Let us think step by step)就能在多数推理任务上提升 10–30 个百分点;few-shot CoT 再给出 2–4 个带推理过程的范例,进一步稳定。其本质是把「分步推理」的行为从模型先验里激活出来。
python# 零样本 CoT 的最小封装:用系统提示激活分步推理
SYSTEM_COT = (
"你是一个严谨的推理助手。回答前先一步步思考,"
"每步只做一件可验证的事,最后用「答案: 」给出结论。"
)
def zero_shot_cot(llm, q, temperature=0.0):
# temperature=0 让单条轨迹更确定;要多样性则用 >0 配合自洽性(7.2)
return llm.chat([
{"role": "system", "content": SYSTEM_COT},
{"role": "user", "content": q},
], temperature=temperature)
# few-shot:把 2-4 个「问题→思考→答案」示范放进消息历史
DEMO = [
{"role": "user", "content": "若 3x+2=11,求 x。"},
{"role": "assistant", "content": "思考: 3x=11-2=9,所以 x=3。答案: 3"},
# 再补 1-3 个同风格示范
]
7.2 自洽性 Self-Consistency:用投票换准确率
思路:同一个问题采样 k 条独立 CoT 轨迹,对最终答案做多数投票。它不要求每条都对,只要「对的方向」占多数即可。数学上相当于用 k 次独立试验降低方差。
| 采样数 k | 相对 k=1 的准确率提升(示意,MATH 级) | 成本倍数 |
|---|---|---|
| 1 | 基准 0% | 1x |
| 5 | +8 ~ +12 pp | 5x |
| 10 | +11 ~ +14 pp | 10x |
| 20 | +12 ~ +15 pp | 20x |
| 40 | +12 ~ +16 pp(收益趋平) | 40x |
python# 自洽性收益的解析:k 次采样多数投票的期望正确率
from math import comb
def majority_correct(p, k):
"""单次正确率 p,k 次独立采样(取奇数)后多数正确的概率"""
need = k // 2 + 1
return sum(comb(k, i) * p**i * (1 - p)**(k - i) for i in range(need, k + 1))
for k in [1, 3, 5, 9, 15, 31]:
print(f"k={k:2d} p=0.5 -> {majority_correct(0.5, k):.3f} p=0.4 -> {majority_correct(0.4, k):.3f}")
# 预期输出(示意):
# k= 1 p=0.5 -> 0.500 p=0.4 -> 0.400
# k= 3 p=0.5 -> 0.500 p=0.4 -> 0.352 <- p<0.5 时投票反而下降
# k= 9 p=0.5 -> 0.500 p=0.4 -> 0.266
# k=31 p=0.5 -> 0.500 p=0.4 -> 0.130
# 结论:p=0.5 是分水岭;p>0.5 投票放大正确,p<0.5 投票放大错误 -> 应先升级模型再投票
7.3 思维树 ToT:把推理展开成可搜索的树
CoT 是单链,自洽性是多条独立单链取多数;思维树 ToT 则把推理显式建成树:每个节点是一个「思考步」,从节点扩展出多个候选下一步(分支),用一个评估函数给每个节点打分,再用搜索(BFS / DFS + 回溯)找通往答案的路径。它把「探索 + 评估 + 回溯」正式工程化。
python# ToT 的极简骨架:扩展 → 评估 → 选择/回溯
def tree_of_thoughts(problem, expand, evaluate, breadth=3, depth=4):
root = {"state": problem, "children": []}
frontier = [root]
for d in range(depth):
next_frontier = []
for node in frontier:
candidates = expand(node["state"], k=breadth) # 从当前步生成 b 个候选
scored = [(c, evaluate(c)) for c in candidates] # 评估每个候选(0~1)
scored.sort(key=lambda x: -x[1])
node["children"] = [{"state": c, "score": s} for c, s in scored[:breadth]]
next_frontier += node["children"]
frontier = next_frontier
return best_leaf(root) # 回溯:从叶子里选评分最高路径
# 评估函数可以是:PRM 打分 / LLM-as-Judge / 一个可执行的 checker
# 成本 ≈ (b ^ d) 次 LLM 调用 —— 见 10 节「算力爆炸」
| 方法 | 结构 | 评估 | 成本 | 适用 |
|---|---|---|---|---|
| 零/few-shot CoT | 单链 | 无 | 1x | 简单、模型已会 |
| Self-Consistency | 多独立单链 | 多数投票 | k x | 答案可归一化 |
| ToT | 树 | 逐步评估 + 搜索 | b^d x | 可分解、可评估 |
| GoT | 图(聚合) | 节点合并/投票 | 可控 b^d | 需综合多路径 |
7.4 思维图 GoT:在图上聚合多条推理
ToT 的分支彼此独立;思维图 GoT 允许不同分支在后续节点汇聚(合并),把多个推理路径的中间结论聚合起来。例如先并行探索「代数法」「几何法」两条路,再在某一层把两条路的结论融合。它对「多个子结论要汇总的复杂任务」更友好,但工程复杂度也最高。
- 聚合操作:sum(拼接再让 LLM 综合)、vote(多路结论投票)、keep-best(保留最优分支)。
- 代价:需要定义「哪些节点可以合并」(相似性 / 子目标一致),以及合并后如何重新评估。
- 现实取舍:多数团队在 2026 年用的是「自洽性 + 少量 ToT 回溯」,GoT 主要用于研究或特定规划场景——它的工程 ROI 通常不划算,除非问题天然是图结构。
| 聚合操作 | 做法 | 适用子目标 | 风险 |
|---|---|---|---|
| sum(综合) | 把多路中间结论拼接后让 LLM 综合 | 多视角互补 | 上下文膨胀、可能引入噪声 |
| vote(投票) | 多路结论多数表决 | 结论同构、可比 | 少数正确路径被淹没 |
| keep-best | 保留评分最高的分支 | 有可靠评估器 | 退化为普通搜索 |
7.5 动手练习与自测
- 零样本 CoT 通常能提升多少个百分点?它的原理是「让模型变强」还是「激活已有能力」?
- 写出 self-consistency 的 majority vote 伪代码,并说明它与 pass@k 的区别。
- ToT 成本是 b^d;取 b=3、d=4 时完整展开需多少次评估?每层剪枝保留 3 个能降到多少?
- GoT 相比 ToT 多了什么操作?什么任务才值得上 GoT?
- 为什么说「模型本来不会的,提示救不了」?
8. 测试时计算缩放(Test-Time Scaling)
学习路径
- 读 8.1:理解训练算力与测试时算力的本质区别
- 跑 budget 分配样例或对照 3.1 六种手段,体会「只给难题花钱」
- 完成 8.4 练习 4:说明训练 vs 测试时缩放的本质区别
- 对接 M10:在 test-time-compute.md 里定位你的难题子集
核心知识点详解
- 训练 vs 测试时缩放的本质区别:训练缩放一次性花算力换更强模型、摊薄到所有请求;测试时缩放每次按难度动态花钱,只给难题多分配算力。
- 只在难题上加算力的前提:当模型在简单题已达 95%+、难题只有约 50% 时,「中等模型 + 强测试时缩放」比一味堆参数划算,因为难题是主要失分点。
- 三类 TTC 手段的算力形态:采样类(Best-of-N/自洽)并行易批化;搜索类(MCTS/beam)串行依赖验证器;长度类(预算档位)单条但更长。
- 常见坑:所有题都加算力:不看难度对每题都拉满采样/搜索,就是「测试时缩放」最好的翻车方式——TTC 的精髓是只给难题花钱(难度路由)。
学习路径
- 读 8.2:理解难度 d=1−|2p−1| 与 d^1.5 加权分配
- 跑 allocate 代码,验证 B=100 时 p=0.5 与 p=0.9 的分配
- 完成 8.4 练习 1/2:解释难度与预算的关系、算采样分配
- 对接 M10:在 budget.py 里用探针估 p 再动态分配
核心知识点详解
- 难度定义:d=1−|2p−1|:p 是模型一次答对估计概率。p=0.5 时 d=1(最难,边界态);p=0 或 1 时 d=0(最易)。越接近边界越值得加算力。
- d^1.5 加权分配:
n_samples = max(1, round(total_budget × d^1.5))。B=100 时 p=0.5→100 次、p=0.9→约 9 次,预算被集中到难题。 - 便宜的探针:探针估 p 可用小模型一次低温度调用、或首次采样的答案一致性作代理,成本远低于大模型 k 次全采样。
- 常见坑:对必对/必错的题也砸预算:p≈0 或 p≈1 的题 d≈0,加算力几乎无收益;把预算给「卡在边界、加一点就做对」的中等问题才是最优。
学习路径
- 读 8.3 表格:对比参数扩张 vs 推理算力的收益曲线
- 跑成本/收益脚本,观察难样本在 TTC 上的近对数线性收益
- 完成 8.4 练习 3:给出「加推理算力更划算」的量化判据
- 对接 M10:画准确率-成本曲线并标出你的收益递减点
核心知识点详解
- 参数扩张幂律趋平:预训练每翻倍参数换来的能力提升越来越小(chinchilla 之后边际递减),且要永久承担训练 + 部署成本。
- TTC 难样本近对数线性:对难题加推理算力,准确率呈近对数线性上升;对比参数幂律趋平,TTC 在「卡在难题」时更划算。
- 量化判据:简单 95%+ / 难题约 50%:当模型在目标分布上「简单题 95%+ 对、难题只剩约 50%」时,加 TTC 优于换大模型——因为大模型对简单题提升微乎其微。
- 常见坑:不看准确率 - 成本曲线边界:是否加算力要看边际收益递减点(Pareto 曲线转角);过了它每加一次采样只涨不到 1pp 却在烧钱,应停止。
学习路径
- 读 8.4 练习 1/2 答案:掌握 B=100 的采样分配
- 跑 allocate 代码复核 p=0.5→100、p=0.9→约 9 的分配
- 完成 8.4 练习 5:列出便宜的探针做法
- 对接 M10:给出你预算策略在曲线上的位置与依据
核心知识点详解
- B=100 的分配示例:d=1−|2p−1|,
n=max(1,round(100·d^1.5)):p=0.5→d=1→100 次;p=0.9→d=0.2→约 9 次。预算向边界难题集中。 - 低成本探针的三条路:① 探针小模型一次低温度调用估 p;② 首次采样答案一致性代理难度;③ 问题启发式(是否含数学/代码/多步规划、长度、检索命中)。
- 结合预算路由器:探针估出的难度喂给
budget.py的allocate(),实现「先摸难度、再分配采样」,整体比全量 k 次便宜。 - 常见坑:探针与大模型同规格:探针用错模型反而贵。探针只需「大致判断难度」,用小模型完全够,把大模型的 k 次采样留给真正难的题。
8.1 核心思想:把算力从训练搬到推理
预训练规模的边际收益在递减(chinchilla 之后每翻倍参数换来的能力提升越来越小),而在推理时给难题多分配算力往往能更划算地提升准确率。这就是 test-time scaling:固定模型参数,靠「多采样 / 多搜索 / 长思考」把难样本做对。o 系列、DeepSeek 的实证都表明:在难题上,推理算力增加带来的收益可以超过单纯加大模型。
| 方法大类 | 做法 | 代表 | 算力形态 |
|---|---|---|---|
| 采样类 | 多次独立生成后择优 | Best-of-N、Self-Consistency | 并行、易批化 |
| 搜索类 | 逐步展开 + 评估 + 回溯 | ToT、MCTS、beam | 串行、依赖验证器 |
| 长度类 | 拉长思考预算 | 推理强度档位、budget forcing | 单条但更长 |
8.2 预算分配:难度自适应
最优分配不是「每个问题都算到极限」,而是简单问题少花、难题多花。可证明(compute-optimal 思路):给定总推理预算,应把更多采样/搜索资源投向「模型在边界上、加一点算力就能做对」的中等难度问题,而不是已经必对或必错的题。
python# 难度自适应预算:用一次「探针」估计难度,再决定算力
def allocate(p_true_estimate, total_budget):
# p_true_estimate: 模型一次答对的估计概率(0~1)
# 难度 d = 1 - |2p - 1| : p=0.5 最难(d=1),p=0/1 最易(d=0)
# 把预算按难度平方加权分配,难题拿到更多采样/搜索次数
d = 1 - abs(2 * p_true_estimate - 1)
n_samples = max(1, int(round(total_budget * (d ** 1.5))))
return n_samples
# 探针可以很便宜:用一个小模型或 1 次低温度调用估 p,
# 再用大模型的 k 次采样填满预算。整体仍比「全量 k 次」便宜。
8.3 与模型规模扩张的收益对比
| 扩展轴 | 典型收益曲线 | 边际成本 | 何时更划算 |
|---|---|---|---|
| 模型参数 | 幂律,但指数趋平 | 训练 + 推理都贵 | 通用能力天花板不足时 |
| 推理算力(TTC) | 难样本上近对数线性 | 仅推理贵、可动态 | 模型已够强、卡在难样本时 |
| 数据规模 | 幂律、易饱和 | 训练贵、需标注 | 领域数据稀缺时 |
经验结论:当你的模型在目标分布上已达「简单题 95%+ 对、难题只有 50%」时,加推理算力比换更大模型更划算。因为大模型对简单题的提升微乎其微,却要你永久承担训练与部署成本;而测试时算力的成本只在「真正难的请求」上发生。2026 年许多团队的解法是中等模型 + 强测试时缩放,而非一味堆参数。
8.4 动手练习与自测
- 难度自适应预算里 d=1−|2p−1|,解释 p=0.5 与 p=1 分别对应什么难度、应分多少预算。
- 给定总预算 B=100 次采样,两个问题估计 p=0.5 与 p=0.9,按 d^1.5 分配各得多少次?
- 什么条件下「加推理算力」比「换更大模型」更划算?给出量化判据。
- 测试时缩放与训练缩放的本质区别是什么?这如何解释难度路由的省钱原理?
- 把「探针」设计得很便宜有哪些做法?
9. 奖励模型与验证器:从 ORM 到 GenRM
学习路径
- 读 9.1:理解 ORM 稀疏 vs PRM 密集信号的差别
- 跑 reward() 或自洽性代码,体会信用分配问题
- 完成 9.5 练习 1/4:举 ORM 失败的例子、说明 RLVR 为何抗 hack
- 对接 M10:在 prm.py 里定义你的逐步打分信号
核心知识点详解
- ORM vs PRM 的信用分配:ORM 只看最终答案(稀疏信号,20 步推导里「错在哪一步」无法定位);PRM 每步打分(密集信号、可定位错步)。例:20 步最后一步算错,ORM 只报整条错。
- 标注成本之差:ORM 标注便宜可自动;PRM 需逐步标注、成本高,且「步骤边界」与「正确性标准」难统一。
- 自动 PRM 的折中:用强模型/规则自动给步骤打分,成本可控;但继承教师偏见,需人工抽查校准。
- 常见坑:高估 RLVR 的抗 hack:RLVR 只因答案来自确定程序(计算器/单测)而更抗 hack,但格式奖励过高仍会诱导 hack——正确性必须绝对主导(见 2.1)。
学习路径
- 读 9.2:理解 GenRM 把判断变成生成任务
- 跑 genrm_score 代码,观察可解释的判定输出
- 完成 9.5 练习 3:设计粗排 + 精排组合控制成本
- 对接 M10:在 prm.py 外层用 GenRM 对 top-k 做精排
核心知识点详解
- GenRM 把判断变成生成:让 LLM 生成「该答案是否正确」的推理,再取命中的判定 token 读结论(
genrm_score)。好处是可解释且能借 LLM 处理开放/主观任务。 - 成本高一个数量级:每次评判都要跑一次生成,比标量 RM 贵一个数量级。不能对每个候选都精判。
- 粗排 + 精排组合省钱:先用便宜的 ORM/标量 PRM 粗排,只对 top-k 候选用 GenRM 精排,在质量与成本间取平衡。
- 常见坑:判定为「不确定」时硬排序:GenRM 输出无法判定时(返回 0.5)不应强制参与排序;否则引入噪声。可对不确定项跳过或交给更强模型。
学习路径
- 读 9.3:理解 RLVR 用计算器/单测做可验证奖励
- 跑 math_reward / code_reward 代码,看规范化与测试通过率
- 完成 9.5 练习 2:写数学答案规范化步骤与 isclose 判等
- 对接 M10:为你的数学/代码子集实现确定性验证器
核心知识点详解
- 数学答案规范化:
norm_num():去逗号/美元号 →ast.literal_eval转数值 → 数值用math.isclose(rel_tol=1e-3)判等;非数值转小写字符串比对。「3」与「3.0」必须判等。 - 代码用单测通过率当奖励:
code_reward(solution, tests) = passed/total,把 solution 写临时文件跑 pytest。通过率即 0~1 奖励。 - 为什么 RLVR 更抗 hack:奖励来自独立、确定性外部程序(计算器/单测框架/类型检查器),模型无法靠「写得更自信」提高奖励,必须真的算对、真的过测试。
- 常见坑:未抽取公式直接整串比对:「x=3」这类要先抽取等号右侧再规范化;整串比会因格式差异误判,导致该对的被判错、训练信号受损。
学习路径
- 读 9.4:掌握 PRM 的 Best-of-N 与逐步搜索两种用法
- 跑 score_trajectory / best_of_n 代码,体会连乘打分
- 完成 9.5 练习 5:说明 PRM 被 hack 的表现与缓解
- 对接 M10:在 prm.py 里落地 Best-of-N 重排并监控 hack 比例
核心知识点详解
- PRM 的两种用法:Best-of-N 重排(对完整轨迹打分选最优)与逐步搜索(beam/MCTS 每步剪枝,
score_trajectory+beam_with_prm)。 - 连乘打分公式:轨迹分
= exp(Σ log max(p_i, 1e-3)),p_i=prm(step_i)。任一步错误都显著拉低总分,所以要乘积而非平均。 - Best-of-N 用 PRM 重排:
best_of_n(prm, trajectories) = max(...)用连乘分选最优候选;配合外部验证器可再兜底。 - 常见坑:PRM 被 hack 不自查:PRM 会学「某类写法总标对」。缓解:PRM 与生成模型解耦、定期校准,用 ORM/可验证奖励做最终裁决,并监控「PRM 高分但答案错」的比例。
9.1 ORM vs PRM:再细化
结果奖励模型(ORM)只判最终答案;过程奖励模型(PRM)对每一步判对错。两者不是替代关系,而是按需求选择:
| 维度 | ORM | PRM |
|---|---|---|
| 监督信号 | 最终答案对错 | 每步正确性 |
| 标注成本 | 低(可自动) | 高(需逐步标注) |
| 信用分配 | 稀疏、难定位错步 | 密集、可定位 |
| 支持搜索 | 仅做最终排序 | 可做逐步剪枝 |
| 奖励黑客风险 | 格式 hack | 逐步 hack 更隐蔽 |
| 典型用法 | Best-of-N 排序 | beam / MCTS 价值 |
9.2 生成式奖励模型(GenRM)
传统 RM 是一个回归头输出标量;GenRM 把「判断正确性」本身变成生成任务:让一个 LLM 生成「该答案是否正确」的推理,再从其输出里读出判定。好处是:① 可解释(给出判错理由);② 能借 LLM 的通用能力处理开放式、主观任务;③ 可用已有 SFT / RL 基础设施训练。
python# GenRM 的最小形态:用 LLM 生成「评判」再抽取结论
GENRM_PROMPT = (
"下面有一个问题、一个标准答案、一个待评判答案。"
"请逐步判断待评判答案是否正确,最后一行输出「判定: 正确/错误」。"
)
def genrm_score(llm, question, gold, candidate):
out = llm.chat([{"role": "user", "content":
f"问题: {question}\n标准答案: {gold}\n待评判: {candidate}"}])
if "判定: 正确" in out: return 1.0
if "判定: 错误" in out: return 0.0
return 0.5 # 不确定 -> 不强制排序
# 进阶:把多个 GenRM 的判定做集成(类似 self-consistency 的验证版)
9.3 可验证奖励:数学与代码单测
可验证奖励(RLVR)是推理训练最稳的奖励来源,因为它不依赖另一个模型打分、不会被 hack 得那么容易:数学有程序化答案比对,代码有单元测试通过率。
python# 数学:抽取答案做规范化比对(避免 "3" vs "3.0" 误判)
import re, ast, math
def norm_num(s):
s = s.replace(",", "").replace("$", "").strip()
try: return float(ast.literal_eval(s))
except Exception: return s.lower()
def math_reward(pred, gold):
p, g = norm_num(pred), norm_num(gold)
if isinstance(p, float) and isinstance(g, float):
return 1.0 if math.isclose(p, g, rel_tol=1e-3) else 0.0
return 1.0 if p == g else 0.0
# 代码:直接跑单元测试,通过率即奖励
def code_reward(solution, tests):
# 把 solution 写进临时文件,执行 pytest 收集的 tests
# 奖励 = passed / total
return run_pytest(solution, tests) # 0.0 ~ 1.0
9.4 用 PRM 做 Best-of-N 重排与逐步搜索
PRM 的两种用法:① Best-of-N 重排——生成 N 条完整轨迹,用 PRM 对轨迹整体打分(或逐步累积分)选最优;② 逐步搜索——在每个推理步用 PRM 当价值函数,beam / MCTS 只保留高分分支,做早期剪枝。
python# 用 PRM 给一条轨迹打分(逐步累积分)
def score_trajectory(prm, steps):
scores = [prm(s) for s in steps] # prm(step)->(0~1) 正确概率
import math
log_p = sum(math.log(max(s, 1e-3)) for s in scores)
return math.exp(log_p) # 乘积:任一步错都显著拉低
def best_of_n(prm, trajectories):
return max(trajectories, key=lambda t: score_trajectory(prm, t))
# 逐步搜索(beam):每步只保留 PRM 分数最高的 b 个前缀
def beam_with_prm(prm, expand, breadth=4, depth=6):
beams = [[]]
for _ in range(depth):
candidates = []
for prefix in beams:
for nxt in expand(prefix):
candidates.append((prefix + [nxt], prm(nxt)))
candidates.sort(key=lambda x: -x[1])
beams = [c[0] for c in candidates[:breadth]]
return beams[0]
9.5 动手练习与自测
- ORM 与 PRM 在「信用分配」上的差别是什么?举一个 ORM 会失败的具体例子。
- 写出数学答案规范化的关键步骤,说明为什么 "3" 与 "3.0" 需判等、而 "x=3" 需先抽取。
- GenRM 的两次用法(粗排 + 精排)如何组合以控制成本?
- 为什么 RLVR 比「用另一个模型打分」更抗 hack?
- PRM 被 hack 的表现是什么?给出至少两条缓解措施。
10. 推理搜索算法:beam / 多样束 / MCTS
学习路径
- 读 10.1:理解 beam 保留最高概率前缀与塌缩问题
- 跑 diverse_beam 代码,调 lambda_div 观察多样性变化
- 完成 10.4 练习 4:说明 lambda_div 调大/调小的后果
- 对接 M10:判断你的任务是否适合 beam,说明理由
核心知识点详解
- beam 保留最高概率前缀:标准 beam search 每步保留概率最高的 b 个前缀,稳定生成单链;但不做回溯,前几步选错就全程错。
- 塌缩到单一风格:纯 beam 的 b 条前缀会趋同到一种写法,探索不到不同思路——推理里这正是「换条路想」派不上用场的原因。
- 多样性 beam 的 lambda_div:把 beam 分组并加相似度惩罚,
lambda_div越大各组越不相似(多样性↑、单链质量可能↓);越小越退回普通 beam。 - 常见坑:beam 越大越好:推理里
beam=4~8常足够,过大因相似前缀收益递减却白烧算力;需要回溯时改用 ToT/MCTS(10.2)而非加大 beam。
学习路径
- 读 10.2:理解 MCTS 四阶段与 UCB 探索项
- 跑 mcts_reason 骨架,观察回溯如何纠正早期错误
- 完成 10.4 练习 2/3:写四阶段、对比 beam 无法回溯
- 对接 M10:在难子集上用 PRM 做价值函数的 MCTS 试跑
核心知识点详解
- MCTS 四阶段:选择(按 UCB 走高分低访问节点)→ 扩展(生成候选下一步)→ 模拟(Rollout 到底拿 ORM/PRM)→ 回溯(更新路径 value/visits)。
- UCB 的探索项:
value + C·sqrt(ln N / n):n越小(访问少)探索项越大,鼓励尝试没走过的步,避免只利用当前高分路径。 - PRM 当价值函数:节点价值可由 PRM 给该步正确概率,或 Rollout 到底后用 ORM 终值;
mcts_reason(root, prm, expand, rollout, iters)。 - 常见坑:UCB 系数 C 不调:C 太小偏利用(易陷局部最优)、太大偏探索(浪费算力)。根据算力预算和值域范围调 C,才能平衡利用-探索。
学习路径
- 读 10.3 表格:理解 b^d 指数增长的算力约束
- 跑 bs/bfs 或对照表格,算 b=5,d=6 的 15625 次调用
- 完成 10.4 练习 1:写剪枝策略把量级压到可控
- 对接 M10:在预算里给搜索设定 b/d 上限
核心知识点详解
- 完整展开是 b^d:算力随分支因子 b 与深度 d 指数增长:b=3,d=4→81;b=5,d=6→
5^6=15625;b=8,d=8→千万级;b=10,d=10→百亿级。 - 必须剪枝:现实把 b 控制在 2–5、d 控制在 5–10,每层只保留分数最高 2–4 个分支,再配合 PRM 早停剪掉低分分支,量级才可控。
- leaf 并行化:搜索天然可并行:不同叶子的展开/评估可批量并发,这是把 b^d 摊到多设备的主要手段。
- 常见坑:不加预算直接开搜:树搜索前必须给 b、d 设上限并算一次预算(
b^d × 单次评估成本),否则单个请求延迟与成本会失控。
学习路径
- 读 10.4 练习 5 答案:理解何时不该用树搜索
- 对照 sr-based 应用,判断你任务的步骤是否可分解可评估
- 完成 10.4 练习 5:写出不用树搜索的判据
- 对接 M10:记录你在哪种子集放弃搜索及原因
核心知识点详解
- 用树搜索的两个前提:任务要可分解为步骤(每个节点是一步)且可逐步评估(PRM/Judge 能给中间步打分)。缺一个就用不了。
- beam 不回溯的定位:beam 适合确定前缀、目标单一的生成(代码补全、严格格式);一旦早期选错无法回头,需回溯时用 ToT/MCTS。
- 不该用树搜索的判据:步骤不可分解、无法逐步评估、或答案唯一性弱时,评估噪声会盖过收益——此时自洽性或直接生成更合适。
- 常见坑:给不可分解任务硬上搜索:开放式主观任务(写作、综述)没有可靠的逐步评估函数,硬上 ToT 只会放大评估噪声、白烧 b^d 算力。
10.1 Beam Search 与多样性 Beam
标准 beam search 每步保留概率最高的 b 个前缀,能稳定生成高质量单链,但容易塌缩到单一风格。多样性 beam(diverse beam)在分组或加 diversity 惩罚,让不同 beam 走不同路线——这对推理很有用,因为「换条路想」常能绕过局部错误。
python# 多样性 beam:不同组之间加相似度惩罚,逼出不同思路
def diverse_beam(model, prompt, groups=4, beam_per_group=3, lambda_div=0.5):
# 把 b = groups*beam_per_group 个 beam 分成 groups 组
# 组间:已选 token 序列越相似,惩罚越大
beams = [{"seq": prompt, "score": 0.0, "group": i % groups}
for i in range(groups * beam_per_group)]
# 简化:实际实现用分组约束,每组独立扩展后再做组间去重/惩罚
# 关键参数:lambda_div 越大,各组越不相似(多样性↑、单链质量可能↓)
return beams
# 经验:推理里 beam=4~8 常足够;太大反而因相似前缀收益递减
10.2 MCTS 在推理中的应用
蒙特卡洛树搜索把推理建模成树:节点 = 一个推理步,边 = 从一步到下一步的动作,价值估计 = PRM 给出的该步正确概率(或 Rollout 到底后的 ORM)。四个阶段:选择(按 UCB 走高分低访问节点)→ 扩展(生成候选下一步)→ 模拟(Rollout 到答案)→ 回溯(用结果更新路径上的价值)。
python# MCTS 推理的极简骨架(价值由 PRM 提供)
import math, random
def mcts_reason(root, prm, expand, rollout, iters=200):
# 节点: {state, visits, value, children}
for _ in range(iters):
node = select(root) # UCB 选择
if not node["children"]:
node["children"] = [{"state": s, "visits": 0, "value": 0.0, "children": []}
for s in expand(node["state"])]
leaf = random.choice(node["children"]) if node["children"] else node
reward = rollout(leaf["state"]) # 跑到底拿 ORM/PRM 终值
backup(leaf, reward) # 回溯更新 value/visits
return best_child(root)
def ucb(node):
# 价值估计 + 访问惩罚(鼓励探索少走的步)
return node["value"] + 1.0 * math.sqrt(math.log(node["parent_visits"] + 1) / (node["visits"] + 1e-6))
10.3 树搜索的算力爆炸
搜索的算力随分支因子 b 和深度 d 指数增长:完整展开需 b^d 次调用。即使做了剪枝,大 b、大 d 依然会失控。这是测试时缩放的硬约束。
| 分支 b | 深度 d | 完整展开调用数 | 实际剪枝后(×0.1) |
|---|---|---|---|
| 3 | 4 | 81 | ~8 |
| 5 | 6 | 15,625 | ~1,500 |
| 8 | 8 | 16,777,216 | ~1.6M |
| 10 | 10 | 10,000,000,000 | ~1B |
- 控制手段:① 限制 b(每步只扩 2–4 个候选);② 限制 d(超过 N 步强制收敛);③ 用 PRM 早停剪枝(低分分支不展开);④ leaf 并行化(搜索天然可并行)。
- 现实经验:多数生产推理搜索把 b 控制在 2–5、d 控制在 5–10,再配合 PRM 强剪枝,否则单次请求的延迟与成本会超出承受范围。
10.4 动手练习与自测
- 计算 b=5、d=6 的完整展开调用数,并说明为什么实际要剪枝到每层 2–4 个分支。
- 写出 MCTS 的四个阶段(选择 / 扩展 / 模拟 / 回溯),并说明 UCB 中「探索项」的作用。
- beam search 与 MCTS 在「能否回溯纠正早期错误」上的本质区别是什么?
- 多样性 beam 的 lambda_div 调大 / 调小分别有什么后果?
- 什么任务不该用树搜索?给出判据。
11. 推理蒸馏:把思考能力压进小模型
学习路径
- 读 11.1:理解用强模型 CoT 微调小模型的思路
- 跑 teacher 生成 + SFT 小流程,理解 1.5B/7B/32B 分数规律
- 完成 11.4 练习 1/5:说明蒸馏为何比自训划算、写分数规律
- 对接 M10:考虑把蒸馏学生模型用作低预算兜底
核心知识点详解
- 蒸馏 = 用强模型 CoT 微调小模型:用 DeepSeek-R1 / o 系列对大量问题生成带思考链的轨迹,再 SFT 小模型(Qwen-1.5B/7B/32B)。小模型从未做 RL 却学会先思考再答。
- AIME 提升规律:R1 蒸馏小模型约
1.5B≈28%、7B≈55%、32B≈72%,随规模单调上升,且远超同尺寸直接 RL 自训(对照 <20%)。 - 何时该先蒸馏:有强教师时先蒸馏(训稳、数据效率高、成本低);资源极充裕才做自有 RL——蒸馏把「已探索出的好路径」直接喂给小模型。
- 常见坑:以为蒸馏能超越教师:蒸馏上限 ≤ 教师;想要超越教师须靠 RLVR 探索新路径(见 11.2),蒸馏只负责稳固打底。
学习路径
- 读 11.2 表格:对比蒸馏与 RLVR 的上限/稳定性/成本
- 对照 2.1 流程,理解「先蒸馏再轻量 RLVR」的组合
- 完成 11.4 练习 2:说明 RL 何时能超越教师
- 对接 M10:设计你最省成本的蒸馏+RL 组合顺序
核心知识点详解
- 蒸馏 vs RL 的关键边界:蒸馏上限 ≤ 教师但稳定、成本低;RLVR 可超越教师(探索新路径)但需奖励信号、需控熵/长度、成本高。
- 推荐顺序:先蒸馏再轻量 RL:工业组合是「先蒸馏打底、再轻量 RLVR 微调」:既拿到教师的推理模式,又有机会在特定领域超越教师。
- 何时 RL 能超越教师:只有当 RLVR 能探索出教师未覆盖的新路径(新解法、更长但更准)时才可能超越——否则 RL 只是重新接近教师。
- 常见坑:直接跳过蒸馏做 RL:小模型自训 RL 易熵崩、长度失控、简单题浪费;没有教师数据硬上 RL 往往不如先蒸馏。
学习路径
- 读 11.3:理解只保留答对轨迹的拒绝采样流程
- 跑 rejection_sample 代码,体验 verifier 硬筛先做、长度/PRM 软筛
- 完成 11.4 练习 3/4:写保留比例判断与「短且对」过滤逻辑
- 对接 M10:在数据集里用「短且对」缓解学生过度思考
核心知识点详解
- 只保留答对的轨迹:
rejection_sample()对每个 prompt 采样,只保留verifier(traj.answer, gold)判对的轨迹作为 SFT 数据,每 prompt 最多留 1–2 条防分布偏斜。 - 保留比例通常 10%–40%:太严(只留极少)数据不足、模型学不扎实;太松(错误轨迹混入)污染训练。按任务难度在 10%–40% 间取舍。
- 「短且对」双重过滤:先用 verifier 硬筛对错,再用长度/PRM 软筛保留「短且对」轨迹——能顺带缓解学生的过度思考(见 12 节)。
- 常见坑:只按对错筛不控长度:只保留答对轨迹会纵容学生学到冗长思考。加入长度过滤后,学生学到的才是简洁推理而非动辄上千 token 的写法。
学习路径
核心知识点详解
- 配比要覆盖易中难:拒绝采样后的数据要按难度分层采样,保证训练集同时覆盖易/中/难,否则模型只在它擅长的难度上表现好。
- 小模型自训易熵崩:小模型直接 RL 探索空间相对小,容易过早收敛到少数写法(熵崩)、长度失控、简单题浪费——这是「先蒸馏」优于「小模型自训」的主因。
- 配比原则:写清数据集作用域(任务类型/语言/难度)与配比原则,避免某一难度或场景过采样导致的偏差。
- 常见坑:只喂难题样本:若训练集全是难题,学生学到的是「极端解法」,对常规问题的泛化反而差——配比均衡与单类难度深耕同样重要。
11.1 用大模型 CoT 微调小模型
推理蒸馏的核心:用强推理模型(如 DeepSeek-R1 / o 系列)对大量问题生成带思考链的轨迹,再用这些轨迹做 SFT 微调小模型(Qwen / Llama 系列)。小模型从未做过 RL,却通过模仿学会了「先思考再答」。DeepSeek 的报告显示,蒸馏后的 Qwen-1.5B / 7B / 32B 在数学上远超同尺寸直接用 RL 训的版本。
| 学生模型 | 来源 | AIME 2024(示意) | 说明 |
|---|---|---|---|
| Qwen-1.5B | R1 蒸馏 | ~28% | 小模型也能获得基本推理行为 |
| Qwen-7B | R1 蒸馏 | ~55% | 接近部分 30B 级基线 |
| Qwen-32B | R1 蒸馏 | ~72% | 逼近部分闭源中等模型 |
| 同尺寸随机 | 无蒸馏 | <20% | 对照说明蒸馏收益显著 |
11.2 蒸馏与 RL 的效果对比
| 维度 | 蒸馏(SFT on CoT) | RLVR(自训练) |
|---|---|---|
| 数据来源 | 强教师生成 | 自身采样 + 奖励 |
| 上限 | ≤ 教师 | 可超越教师(探索新路径) |
| 稳定性 | 高 | 中(需控熵/长度) |
| 成本 | 低(一次生成 + SFT) | 高(反复采样 + 训练) |
| 可验证性依赖 | 否 | 是(需奖励信号) |
| 推荐顺序 | 第一步 | 第二步(锦上添花) |
工业上常见组合:先蒸馏打底,再轻量 RLVR 微调。这样既拿到教师的推理模式,又有机会在特定领域超越教师。
11.3 拒绝采样(Rejection Sampling)
拒绝采样是连接「生成」与「筛选」的桥梁:用教师(或当前模型)对一批 prompt 采样,只保留答对的轨迹作为训练数据。它把 RL 探索到的正样本固化为 SFT 数据,是 R1 流程里「RL 之后」的关键一步。
python# 拒绝采样:只保留正确的轨迹,用于后续 SFT
def rejection_sample(teacher, prompts, verifier, per_prompt=8):
kept = []
for p in prompts:
for _ in range(per_prompt):
traj = teacher.generate(p) # 含思考链
if verifier(traj.answer, p.gold): # 只对答案做硬判定
kept.append({"prompt": p.text, "completion": traj.text})
# 每个 prompt 最多留 1~2 条,避免分布偏斜
return kept
# 进阶:不只看对错,还按 PRM/长度过滤(保留「短且对」的轨迹)
# -> 这能顺带缓解学生学到的过度思考(见 12 节)
11.4 动手练习与自测
- 为什么蒸馏小模型常比小模型自己做 RLVR 更划算?列出至少三条原因。
- 蒸馏的上限是什么?什么条件下 RLVR 能超越教师?
- 拒绝采样的保留比例通常多少?太严 / 太松分别有什么问题?
- 写出「短且对」双重过滤的拒绝采样逻辑,说明它如何顺带缓解过度思考。
- R1 蒸馏到 Qwen-1.5B/7B/32B 的 AIME 分数大致呈什么规律?
12. 长度控制与过度思考(Overthinking)
学习路径
- 读 12.1:理解简单题超长思考与准确率不涨的现象
- 跑 token 统计,量化简单题 800 token 的浪费
- 完成 12.4 练习 1:举一个简单题超长思考的例子并说明代价
- 对接 M10:在上线统计里监控 Overthinking 占比
核心知识点详解
- Overthinking 的定义与证据:在本可一步答对的简单题上仍生成超长思考(简单题平均约 800 token,准确率已达 99% 却可压到 <100)。
- 浪费量级:多花 3–10× token:部分模型在简单题上平均多花 3–10 倍 token 而准确率无提升;这是纯成本损失(延迟 + 计费)。
- 成本被少数简单请求拉高:百万级日请求里简单题占多数,若它们都长思考,整体账单会被「不必要的长思考」系统性抬升——所以不是优化项而是必做项。
- 常见坑:只统计平均 token:长尾简单请求的长思考被平均掩盖。要按难度分箱统计思考 token,找出「简单题却超长」的占比再路由压掉。
学习路径
- 读 12.2:理解长度惩罚 reward−=α·len 及其副作用
- 跑 reward 改动,对比 α=1e-4 与 1e-1 的行为差异
- 完成 12.4 练习 2/4:说明 Budget Forcing 与长度惩罚的取舍
- 对接 M10:给训练加入长度惩罚并调 α
核心知识点详解
- 长度惩罚公式:
reward −= α × len(completion),在 RL 奖励里对 token 数加负项,抑制无意义拉长。α 常取 1e-4~1e-3。 - α 太大 vs 太小的后果:α 太大 → 模型「偷懒过早停」、准确率下降;α 太小 → 压不住过度思考。「更长=更准」的探索目标会与惩罚冲突。
- 对比 Budget Forcing:长度惩罚从训练根上治但 α 难调;Budget Forcing 在推理端强制收尾(注入「请给出最终答案」),不改权重、可在线调,但可能误截断真需要长想的题。
- 常见坑:全局惩罚一刀切:单纯全局 α 会误伤难题(难题本就该长想)。2026 主流是「难度路由 + 动态 budget」而非一次全局惩罚。
学习路径
- 读 12.2 的 budget_forcing 代码:理解推理端强制收尾
- 跑 budget_forcing 代码,调 max_think 观察收尾行为
- 完成 12.4 练习 2:对比长度惩罚与 Budget Forcing 优缺点
- 对接 M10:在推理管线里实现 budget forcing 收尾
核心知识点详解
- Budget Forcing 的做法:生成循环中若
think ≥ max_think且尚未给答案,就注入final_trigger(如“现在请给出最终答案。”)强制收尾,见budget_forcing()。 - 不改权重、可在线调:推理端控制的优点是不训练、可动态改 max_think,灵活适配不同请求的算力预算。
- 何时会误截断:对「真需要长想」的难题,硬顶
max_think会在模型其实正逼近结论时被截断,导致答案残缺或笔误。 - 常见坑:max_think 设得过小:把预算压太低会大面积截断难题。应先统计真实思考长度分布,让 max_think 至少覆盖难题的 P90,再让路由决定用几档。
学习路径
- 读 12.3:理解四档难度路由与简单不思考
- 跑 route 数据表,对照四档 token 与准确率
- 完成 12.4 练习 3/5:写四档对照并解释路由降本降压
- 对接 M10:在 budget.py 里实现按难度四档路由
核心知识点详解
- 四档路由的预算与准确率:简单 0–100 token(~99%)、中等 200–800(~88%)、困难 1500–4000(~70%)、关键 4000+ 且 k 次采样(~75%)。
- 简单题直接不开启思考:用廉价探针判断难度,简单/非推理直接走
0–100档位,避免在占大头的简单请求上烧思考 token。 - 同时降本降压的原因:用户最常问的恰恰是最简单的问题;把它们的思考关掉后,占大头请求的延迟骤降,整体 P50/P99 体验与账单同时改善。
- 常见坑:只省钱不顺带构图给延迟:路由不仅为成本,更为「简单题秒回」的用户体验;若只关注 token 省钱而没测 P99 延迟,会漏掉这个隐藏收益。
12.1 Overthinking 现象与证据
Overthinking:推理模型在本可一步答对的简单题上仍生成超长思考(几百到上千 token),造成无谓的延迟与成本。2025–2026 年的实测显示,部分模型在简单题上平均多花 3–10 倍 token,而准确率并无提升。
| 问题难度 | 平均思考 token(示意) | 准确率 | 是否过度 |
|---|---|---|---|
| 简单(一眼看出) | 800 | 99% | 是:可压到 <100 |
| 中等 | 1500 | 85% | 适度 |
| 困难 | 3500 | 62% | 必要 |
| 极难 | 6000+ | 40% | 必要但仍不足 |
12.2 长度惩罚与 Budget Forcing
两类克制手段:长度惩罚在 RL 奖励里对 token 数加负项(length penalty),抑制无意义拉长;Budget Forcing 在推理端强制预算——如「再想不超过 N token 就收尾」,或在思考过长时注入「是时候给出最终答案了」的指令。
python# Budget Forcing:推理端强制收尾,避免无限思考
def budget_forcing(llm, q, max_think=1000, final_trigger="现在请给出最终答案。"):
text = ""
think = 0
while True:
chunk = llm.generate(q, max_new_tokens=128)
text += chunk
think += len(chunk)
if "答案" in text or think >= max_think: # 自然收敛或触顶
break
if think >= max_think and "答案" not in text:
text += "\n" + final_trigger # 强制收尾
text += llm.generate(text, max_new_tokens=256)
return text
# 长度惩罚(训练侧):reward -= alpha * len(completion)
# alpha 太大模型会「偷懒过早停」,太小则压不住过度思考;典型 1e-4~1e-3
- Budget forcing 的优点:不改模型权重、可在线调;缺点是对「真需要长想」的题可能截断。
- 长度惩罚的优点:从训练根上治;缺点是 α 难调,且与「更长=更准」的探索目标冲突,需配合难度路由。
- 2026 前沿:按难度路由(12.3)+ 动态 budget 是主流组合,比单纯全局惩罚更稳。
12.3 按难度路由:简单问题不开启思考
最干净的解法:先用廉价探针判断难度,简单问题直接走非推理模型或不思考档位,只有难题才进入长思考。这与 8.2 的难度自适应预算、1.1 的预算路由器一脉相承。
| 判定 | 路由 | 思考 token | 典型准确率 |
|---|---|---|---|
| 简单 | 非推理 / 极低预算 | 0–100 | ~99% |
| 中等 | 短思考 | 200–800 | ~88% |
| 困难 | 长思考 | 1500–4000 | ~70% |
| 关键/高 stakes | 最长思考 + 多次采样 | 4000+ + k 次 | ~75% |
12.4 动手练习与自测
- Overthinking 的定义是什么?举一个「简单题却生成上千 token」的例子并说明代价。
- 对比长度惩罚(训练侧)与 Budget Forcing(推理侧)的优缺点。
- 写出按难度路由的四档(简单 / 中等 / 困难 / 关键)对应的思考 token 与典型准确率。
- 长度惩罚的 alpha 取太大或太小分别会怎样?
- 为什么「按难度路由」降本的同时还能降低延迟?
13. 评测进阶:pass@k 与 majority@k
学习路径
- 读 13.1:理解 pass@k 无偏估计的公式与含义
- 跑 pass_at_k 代码,算 n=20,c=8,k=1 与 k=10 的结果
- 完成 13.4 练习 1/2:写公式演算、区分 pass@k 与 majority@k
- 对接 M10:用 pass@k 报告你模型的能力上限
核心知识点详解
- pass@k 无偏估计公式:
pass@k = 1 − C(n−c,k) / C(n,k),n 次采样中 c 次通过;k≤n 时成立。n=20、c=8:k=1→0.40、k=10→约 0.93。 - 衡量能力上限,非单次准确率:pass@k 反映「采样 k 次至少对一次」,是能力上限。k=1 才是单次准确率(部署形态)。
- 误用风险:pass@k 高不代表单次部署靠谱。产品通常每次都只跑 1 次,应看单次准确率,把 pass@k 当作「配自洽性/重排后的可达上限」参考。
- 常见坑:把 pass@10 当 pass@1 报:报分数时若不说清是 pass@k 还是 accuracy@1,会严重高估单次可用性。必须标注采样方式与成本。
学习路径
- 读 13.2:理解 majority@k 与 pass@k 的关系
- 跑自洽性投票,对比越票前后正确率
- 完成 13.4 练习 2:说明哪个更接近部署形态且为何
- 对接 M10:报告 majority@k 作为部署形态指标
核心知识点详解
- majority@k 看「投票后是否对」:k 次采样做多数投票后,该题是否答对。它衡量自洽性收益,与 pass@k(看能力上限)互补。
- 为何常低于 pass@k:投票会丢掉「只有 1 次对但答案独特」的情况,所以
majority@k ≤ pass@k,但更贴近真实可用收益。 - 更接近部署形态:部署常用多数投票,
majority@k(或accuracy@1)能直接对应线上指标的稳定性,故更适合当部署指标。 - 常见坑:只用 pass@k 评估部署:pass@k 高是「多试才行」,若你的产品只跑一次,用 pass@k 会高估上线表现——需同时报 accuracy@1 与 majority@k。
学习路径
- 读 13.3:理解答案抽取/污染/严格格式三类坑
- 跑 token 规范化或评测样例,复现「3」vs「3.0」误判
- 完成 13.4 练习 3/5:举两种格式误判例子、说明为何别刷格式
- 对接 M10:评测里处理 flaky 与格式规范化
核心知识点详解
- 答案抽取误判:数学里「3」与「3.0」、
\boxed与 "x=3"、带单位 "3 cm" 形式不一就会判错——必须先抽取再数值规范化(见 9.3)。 - 13-gram 污染:公开题被训练数据污染,需 n-gram / 嵌入级污染检查与时间切分,占比 >5% 时指标不可信。
- 严格格式压低真实能力:要求特定输出格式会人为压低「等价但不同写法」的正确率;评测应允许等价表达。还有 SWE-bench 的 flaky 测试(不稳定用例)会污染指标。
- 常见坑:评测后发现 MSC 线不对再改流程:应在评测前定好规范化与重复运行策略(处理 flaky),而非看到异常再事后修补——否则易引入对自身有利的后验偏差。
学习路径
核心知识点详解
- 污染检查的多种做法:① 13-gram 词元重合;② 嵌入级相似度(语义改写也能查);③ 题目语义哈希去重;④ 时间切分(用模型训练截止后的数据)。
- "3" vs "3.0" 的规范化:抽取 → 去逗号/单位 →
float(ast.literal_eval)→ 数值用isclose(rel_tol=1e-3)判等;非数值转小写字符串比对。 - 评测前定好后验流程:规范化与 flaky 处理要在评测前写入流程,避免测试后补丁导致偏差;配合 bootstrap 给每个子集置信区间。
- 常见坑:只跑字面污染检查:只查 13-gram 会漏语义改写型污染。至少做到「字面 + 嵌入级」两层,并对高风险子集再用时间切分验证。
13.1 pass@k:模型「会不会」与「稳不稳」
普通准确率是「采样 1 次对不对」;pass@k 衡量「采样 k 次里至少有 1 次对」的概率,反映模型能力上限(会不会),而非稳定性。其无偏估计为:
text# pass@k 的无偏估计
# n 次采样中 c 次通过,则
# pass@k = 1 - C(n-c, k) / C(n, k)
# 当 k<=n 时成立;常用 n=20, k=1/5/10
# 直觉:k=1 是普通准确率;k 越大越接近「模型能否做对至少一次」
# 注意:若 n 次里有 c 次对,C(n-c,k)/C(n,k) 是「k 次全错」的概率
pythonimport math
from math import comb
def pass_at_k(n, c, k):
"""n: 总采样数, c: 通过数, k: 取前 k 次"""
if n - c < k:
return 1.0
return 1.0 - comb(n - c, k) / comb(n, k)
# 例:n=20 采样,c=8 通过
print(pass_at_k(20, 8, 1)) # ~0.40 (≈ 单次准确率)
print(pass_at_k(20, 8, 10)) # ~0.93 (采 10 次基本必对一次)
13.2 majority@k:投票视角
与 pass@k 互补,majority@k 看「k 次采样里最多数答案是否对」,衡量自洽性投票后的表现。它更接近部署形态(因为部署常用多数投票)。关系:majority@k 通常 < pass@k(因为投票会丢掉「只有 1 次对但答案独特」的情况),但更反映实际收益。
| 指标 | 问的问题 | 反映 | 部署可用性 |
|---|---|---|---|
| accuracy@1 | 单次对不对 | 稳定性 | 直接可用 |
| pass@k | k 次里能否至少对 1 次 | 能力上限 | 需配重排/采样 |
| majority@k | 投票后是否对 | 自洽性收益 | 可直接部署 |
13.3 数学与代码评测的陷阱
| 基准 | 考什么 | 陷阱 |
|---|---|---|
| AIME / MATH | 竞赛数学 | 公开题被大量训练污染;答案抽取格式严格(\boxed)易误判 |
| LiveCodeBench | 近期竞赛代码 | 相对新、污染低,但题量小、方差大 |
| SWE-bench / Verified | 真实仓库缺陷修复 | 依赖环境/版本;Verified 已去噪但仍有 flaky 测试 |
| Humanity Last Exam | 专家级跨学科 | 部分题存争议,且易被记忆而非推理 |
13.4 动手练习与自测
- 写出 pass@k 的无偏估计,并算 n=20、c=8、k=1 与 k=10 的结果。
- pass@k 与 majority@k 哪个更接近部署形态?为什么?
- 答案抽取有哪些坑?至少举两种格式不一致导致误判的例子。
- 污染检查除了 13-gram 还能怎么做?
- 为什么不建议用「严格输出格式」的 prompt 去刷基准分?
14. 生产化:何时开思考、如何控成本
学习路径
- 读 14.1 表格:掌握开思考模式的场景判据
- 跑 reason_with_verify 或对照表格,确认高风险应开 + 多采样
- 完成 14.5 练习 1:写「答错成本 vs 等待成本」经验法则
- 对接 M10:给高 stakes 场景开思考 + 多采样配置
核心知识点详解
- 开思考的场景:数学/代码/逻辑、多步规划/Agent、高风险决策(金融/医疗/法律)。这些「多步推理易错、答错代价高」,开思考显著提准。
- 关思考的场景:摘要/翻译/改写、客服/实时对话、海量简单查询。模板化或延迟敏感,思考无增益甚至伤人。
- 高并发 vs 高风险权衡:核心经验法则:答错成本高于多等几秒就开(金融/医疗/关键代码);延迟比偶尔错更伤就关(客服/实时/海量简单查询),高风险则开 + 多采样。
- 常见坑:全局统一开关:应提供按任务/信号动态开关(路由器),并给用户「深度思考」按钮;全局强开会把高并发简单请求也拖进长思考。
学习路径
- 读 14.2:掌握四档的相对延迟与成本
- 跑 infer_cost(100万) 代码,确认思考成本是答案的约 20 倍
- 完成 14.5 练习 2:写 off/low/medium/high 的延迟成本对照
- 对接 M10:上线前统计思考 token 分布
核心知识点详解
- 四档延迟成本对照:
off 1x/1x、low ~200 token 1.5–2x、medium ~1000 token 3–5x、high ~4000 token 10–20x。思考 token 是答案的 10–50×。 - 最敏感旋钮:思考 token 单价与输出同档而量却是答案的 10–50×,所以控制思考 token 比控答案长度重要一个数量级。
- 用 infer_cost 建模:
infer_cost(1M, …)显示 100 万请求、20% 难题、难题 4000token×3 次采样时,思考成本约 4800 万 vs 答案 240 万(约 20×)。 - 常见坑:用平均 token 拍脑袋:上线前必须统计真实流量思考 token 分布(含 P99);长尾由少数超长请求主导,均值会严重低估峰值成本。
学习路径
- 读 14.3:理解思考折叠/不落库/语义缓存/分通道流式
- 跑 ReasonCache 代码,验证阈值 0.97 的命中与复用
- 完成 14.5 练习 3:说明思考为何不落库
- 对接 M10:接入语义缓存并把 reasoning 分通道返回
核心知识点详解
- 思考默认折叠、不落库:思考过程默认折叠展示;不把思考存进对话历史,否则下轮上下文膨胀、成本二次叠加。只保留「最终答案 + 关键结论」。
- 语义缓存命中即零成本:
ReasonCache(embed, thresh=0.97)用嵌入余弦相似度命中「同一道题」。可验证任务命中率常达20%–40%,命中=零思考成本 + 极低延迟。 - 分通道流式:思考与答案分开流(
reasoning字段 vscontent字段),前端可分别渲染、中断,避免冗长思考淹没界面。 - 常见坑:缓存阈值放宽:
thresh降到 0.9 会让近似但不完全相同的题误命中、返回错误答案——可验证题缓存要保守(≥0.97)。
学习路径
- 读 14.4:理解推理 + 验证 + 升级/转人工的闭环
- 跑 reason_with_verify 代码,观察 self-refine 重试路径
- 完成 14.5 练习 4/5:设计生产闭环、对应 M10 交付物
- 对接 M10:交付 cot/sc/prm/budget 并画出准确率-成本曲线
核心知识点详解
- 生产闭环:推理 + 验证 + 升级:
reason_with_verify():推理 → 外部确定性校验(计算器/单测/schema)→ 通过即返回;不通过则把失败 detail 回灌 self-refine 重试;仍失败escalate_to_human。 - 不盲信 CoT,用外部验证器兜底:数学跑计算器、代码跑单测、结构化输出做 schema——验证通过才返回,把「看起来对」与「真的对」分开。
- 对应 M10 交付物:这套正是 Hamauls Orion M10:
hamauls_orion/reason/{cot,sc,prm,budget}.py+ 画「准确率–成本」Pareto 曲线定位收益递减点。 - 常见坑:重试无上限或无限回灌:self-refine 要设
max_retry(如 2 次),否则验证不过就死循坏烧成本;到点一律升级模型或转人工。
14.1 什么时候开思考模式
- 开:数学/代码/逻辑题、多步规划、复杂分析、需要可追溯推理的高风险决策。
- 关:常识问答、摘要、翻译、闲聊、创意写作、以及「简单且高并发」的请求。
- 混合:默认关,路由器检测到难信号(含数学/代码/规划、低首次一致性)才开——见 1.1 / 12.3。
- 用户可控:提供「深度思考」开关,把成本决策交还给用户(尤其高 stakes 场景他们愿意等)。
| 场景 | 是否开思考 | 理由 | 典型档位 |
|---|---|---|---|
| 数学 / 代码 / 逻辑 | 开 | 多步推理易错,思考显著提准 | medium–high |
| 多步规划 / Agent | 开 | 需要全局一致性与回溯 | high |
| 高风险决策(金融/医疗/法律) | 开 + 多采样 | 答错代价远高于延迟 | high + k 次 |
| 摘要 / 翻译 / 改写 | 关 | 模板化任务,思考无增益 | off |
| 客服 / 实时对话 | 关或极低 | 延迟比偶尔错更伤 | off–low |
| 海量简单查询 | 关 | 成本与吞吐优先 | off |
14.2 延迟与成本权衡
| 档位 | 思考 token | 相对延迟 | 相对成本 | 适用 |
|---|---|---|---|---|
| off | 0 | 1x | 1x | 简单/高并发 |
| low | ~200 | 1.5–2x | 1.5–2x | 中等 |
| medium | ~1000 | 3–5x | 3–5x | 困难 |
| high | ~4000 | 10–20x | 10–20x | 关键/研究 |
成本公式上,思考 token 单价通常与输出 token 同档,而思考量可能是答案的 10–50 倍。所以控制思考 token 比控制答案长度重要一个数量级。上线前务必统计真实流量的思考 token 分布,而不是用均值拍脑袋。
python# 推理成本估算:把四个变量都算进去,找出最敏感的旋钮
def infer_cost(n_req, c_in, c_out, c_think, p_hard, l_think_hard, l_think_easy, n_sample):
# n_req: 日请求; c_*: 每 token 单价; p_hard: 难题占比
easy = n_req * (1 - p_hard)
hard = n_req * p_hard
think_easy = easy * l_think_easy * c_think
think_hard = hard * l_think_hard * n_sample * c_think # 难题多采样
ans = n_req * 120 * c_out
inp = n_req * 300 * c_in
return {"think": round(think_easy + think_hard, 1),
"ans": round(ans, 1), "in": round(inp, 1)}
# 例:100 万请求,20% 难题,难题思考 4000 token 且 3 次采样,简单题 0
print(infer_cost(1_000_000, 0.001, 0.002, 0.002, 0.2, 4000, 0, 3))
# 预期输出(示意):
# {'think': 4800.0, 'ans': 240.0, 'in': 300.0} <- 思考成本是答案的 20 倍
# 结论:最大杠杆是「把简单题(占 80%)的思考降到 0」+「限制难题采样次数」
14.3 思考内容的展示与缓存
- 展示:思考过程默认折叠,仅对「想看推理」的用户/场景展开;避免用冗长思考淹没界面。
- 落库:一般不把思考存进对话历史发给模型(否则下轮上下文膨胀、成本二次叠加);如需多轮连贯,只保留「最终答案 + 关键结论」。
- 缓存:相同/近似问题命中语义缓存,直接复用已有思考与答案;批量任务先去重再推理。
- 流式:思考阶段与答案阶段分通道(如 reasoning 字段与 content 字段),前端可分别渲染与中断。
python# 语义缓存:用嵌入相似度命中「同一个问题」,直接复用思考与答案
import hashlib, numpy as np
class ReasonCache:
def __init__(self, embed, thresh=0.97):
self.embed = embed; self.thresh = thresh
self.keys = [] # 归一化后的 query 向量
self.vals = [] # 缓存的结果(answer + reasoning)
def get(self, q):
if not self.keys:
return None
v = self.embed(q)
sims = np.array(self.keys) @ v # 余弦相似度
i = int(sims.argmax())
return self.vals[i] if sims[i] >= self.thresh else None
def put(self, q, res):
self.keys.append(self.embed(q)); self.vals.append(res)
# 经验:可验证任务(同一道题被不同用户反复问)命中率常达 20%-40%,
# 命中即「零思考成本 + 极低延迟」,是推理模型降本的第一杠杆。
14.4 推理结果的可验证性
生产里最可靠的做法是不盲信 CoT,而用外部验证器兜底:数学跑计算器、代码跑单测、结构化输出做 schema 校验。验证通过才返回,否则升级模型/重试/转人工。
python# 生产闭环:推理 + 验证 + 升级
def reason_with_verify(llm, verifier, q, max_retry=2):
for attempt in range(max_retry + 1):
ans = llm.reason(q) # 带思考
ok, detail = verifier(ans) # 外部确定性校验
if ok:
return {"answer": ans, "verified": True}
q = f"{q}\n上次的答案未通过校验: {detail},请重新推理。" # self-refine
return escalate_to_human(q) # 仍失败 -> 人工
hamauls_orion/reason/cot.py、sc.py、prm.py、budget.py,并画出「准确率–成本」曲线找到你自己的边际收益递减点。14.5 动手练习与自测
- 给出「什么时候开思考模式」的一条经验法则,并区分高 stakes 与高并发场景。
- 四档推理强度(off/low/medium/high)的相对延迟与成本大致是多少?
- 思考内容该不该落库进对话历史?为什么?
- 设计一个「推理 + 外部验证 + 升级 / 转人工」的生产闭环,写出关键分支。
- 梳理本阶段哪些能力对应 Hamauls Orion M10 的交付物。
项目里程碑
把 Hamauls Orion 从「一次生成」升级为「会思考」:加入思维链、自一致性采样、以及一个过程奖励模型(PRM)做验证打分,并实现推理预算分配——简单问题短路,复杂问题多想。
本阶段产出(直接进入项目仓库)hamauls_orion/reason/cot.py:CoT 提示 + 结构化推理输出(含终止条件与最大步数保护)hamauls_orion/reason/sc.py:自一致性采样与多数投票,含温度/样本数敏感性实验hamauls_orion/reason/prm.py:过程奖励模型打分器 + 最佳轨迹选择hamauls_orion/reason/budget.py:按问题难度分配推理预算的路由器docs/exp/test-time-compute.md:准确率 vs 推理成本曲线,标出边际收益递减点
阶段练习项目
- 能把流量路由到 trivial / normal / hard / critical 四档,简单题(约占 80%)思考预算压到接近 0
- 对比「全开最高档」与「按难度路由」的估算成本比(期望 ≥ 3 倍),并给出真实流量下的成本公式
- 产出「准确率–成本」帕累托曲线,标出收益递减点(Pareto 转角)
budget.py定义四档Budget(model, max_think_tokens, samples),classify用信号(是否数学/代码/规划、长度、检索命中、历史失败率)路由- 加载真实/构造流量样本,按难度档位估算成本
≈ samples×(think+out),并与全开 high 档对比 - 接入语义缓存(余弦相似度 ≥ 0.97 命中直接复用),统计命中率与节省
- 监控误判:把难题误判为简单导致答错的代价不对称,路由阈值设计偏保守并量化
- 用 bootstrap 给每档准确率配置信区间,避免小样本误导
scripts/reason/budget.py+ 难度分类器 + 成本统计- 帕累托曲线图与「路由 vs 全开」成本对比表
- 一份决策备忘:哪类请求用哪档、依据是什么
不做真实模型的在线 A/B;只在离线脚本里用模型打分或已标注数据验证路由正确性。
- 得出 N=1/4/9/16 四档的准确率,明确准确率不再随 N 增长的收益递减点
- 能给出「每正确一次的成本」随 N 变化的曲线,并用「边际收益 > 边际成本」判据说清最优点
- 验证器(答案比对 / 单测)在重排中确实优于随机选,量化其增益
prm.py/verifier.py实现数学答案规范化(norm_num+isclose(rel_tol=1e-3))与确定性判定- 对每个问题采样 N 条,用验证器选最优(Best-of-N 重排),对比
N=1/4/9/16 - 控制温度探索(
T=0.7~1.0、top_p=0.9~0.95),记录温度敏感性 - 对失败样本做 fail case 分析,区分「验证器过筛但错」与「本就不会」
- 用 bootstrap 对每档准确率给置信区间
scripts/reason/best_of_n.py+ 验证器- 「N – 准确率 – 成本」曲线与收益递减点结论
- 失败样本清单与分析
不做 PRM 训练;验证器只做数学确定性判定,不引入 LLM-as-Judge。
- 完成一次可控的 GRPO 训练,记录奖励 / 长度 / 熵三曲线并给出健康度判读
- 观察到「长度随训练增长」现象,并判断是否真跨越简单题的过度思考(Overthinking)
- 能定位一次「奖励 hack / 模式崩溃 / 长度失控」并给出修复动作
reward()用可验证奖励三段(正确性 1.0 / 格式 0.1 / 语言 0.05),正确性绝对主导GRPO优势A_i=(r_i−mean)/std,处理std=0除零(丢弃该 prompt 或加平滑),ε≈1e-2~2e-2- 长度惩罚
reward−=α·len,α从1e-4起扫描观察「偷懒早停 vs 压不住」 - 边训练边记录奖励 / 长度 / 熵 / 通过率四指标,配自动告警阈值
- 统计反思语(wait/recheck/hmm)出现频率,判断「涌现反思」是否发生
scripts/reason/rlvr_train.py(minimal GRPO)- 三/四曲线监控图 + 健康度判读报告
- 一个翻车案例的排查记录(按熵→ε→长度惩罚→KL 顺序)
不在超大模型上做完整 RL pipeline;只复现最小可信的 GRPO 训练回路与监控。
- 让 2–3 个推理模型与 1 个非推理模型的分数可在同一尺度上比较(含置信区间)
- 污染检查通过(13-gram 重合率 < 1%)或明确标注污染风险
- 报告覆盖难度 / 场景分层,并单独列出弱项子集而非只给总分
- 自建 100–200 条真实样本,按难度与场景分层并注明来源
- 跑 13-gram / 嵌入级污染检查,
>1%标注警惕、>5%判定不可信 - 用 bootstrap(≥1000 次重采样)给每子集置信区间
- 报告模板含来源、风险分类、复现命令与失败分布(不只是报平均分)
- 把单次准确率与 pass@k 分开报告,避免混淆
scripts/evals/reason_bench.py+ 数据集(含版本哈希)- 带置信区间的评测报告(MD)+ 污染检查结果
- 弱项子集清单与基于证据的选型建议
不做影子评估(成本高、需外部评审);不训练/微调任何模型。
- CoT / 自洽性 / PRM+Best-of-N / 预算路由四者在同一基准上横向对比出准确率与成本
- 明确验证器驱动的 Best-of-N 相对单次生成的收益,并标出边际收益递减点
- 预算路由在固定成本约束下相对「一律最高档」显著提升准确率-成本比
cot.py:CoT 结构化输出(思考段 + 答案段)与终止条件sc.py:自洽性多数投票 + 答案归一化,token 香将k=1/5/9与温度敏感性prm.py:逐步打分(连乘 log 累积分)驱动 Best-of-N 重排,监控「PRM 高分但答案错」比例budget.py:难度预算路由,简单题低预算、难题加采样+PRM- 在数学/多跳子集上统计「准确率–成本」,用 bootstrap 配置信区间并定位收益递减点
- 用外部验证器(计算器/单测)对最终答案兜底,不满足则 self-refine 或降级
hamauls_orion/reason/{cot,sc,prm,budget}.py+ 测试- 「准确率–成本」帕累托曲线与收益递减点结论(M10 交付物)
- 一份「何时用哪种推理手段」的选型决策备忘
不做端到端产品 UI;不训练 PRM(沿用规则/验证器打分);不做树搜索(MCTS/ToT)。
常见误区
- 把「输出更长」当成「更聪明」,不监控 token 效率与准确率的联合曲线。
- 所有请求都开最高推理强度,成本爆炸却没换来相应收益。
- 相信单次思维链就是模型的真实推理过程,不做多次采样交叉验证。
- 用公开基准分数下结论,忽略训练数据污染,指标严重虚高。
- 在开放式任务上硬套 Best-of-N,却没有可靠验证器,结果只是随机选一个。
- 忽略了思考 token 会进入上下文,导致多轮对话成本与延迟快速累积。
- 把推理模型的输出直接落库或展示给用户,暴露冗长思考且增加后续成本。
面试高频问题速答
推理模型和普通模型在训练上的本质区别是什么?
普通模型主要在「预测下一个 token」的预训练目标 + SFT + 偏好对齐上训练,学的是输出形式与偏好。推理模型在 SFT 冷启动之后,关键一步是用可验证奖励做 RL(RLVR):奖励来自程序化判定(答案是否正确、单测是否通过),模型通过探索发现更长的思考与自我纠错能提高奖励,于是「长思维链 + 反思」作为行为被强化出来,而不是靠人工写进训练数据。
测试时计算扩展有哪些手段,怎么选?
六类:Best-of-N(配验证器)、自洽性多次采样投票、思维链提示、长思考预算、树搜索回溯、多模型交叉验证。选择的第一分叉是「有没有可靠验证器」:有则用 Best-of-N,性价比最高;没有则用自洽性并把一致性比例当置信度,或引入 LLM-as-Judge 并接受其偏见。第二分叉是任务难度:难题才值得开大预算,简单题开大预算纯属浪费。
PRM 和 ORM 的取舍是什么?
ORM 只看最终结果,标注便宜、易自动化,但长推理时信用分配困难、信号稀疏。PRM 对每步打分,信号密集、支持逐步搜索与剪枝,但标注昂贵且步骤边界与正确性标准难以统一。2026 年的折中是「自动 PRM」——用强模型或规则自动标注过程,成本可控但会继承教师偏见。实践建议:先用 ORM 起量,只在确有搜索需求时才上 PRM。
RL 训练中输出越来越长是好事还是坏事?
短期看常伴随准确率提升(更多思考机会),但它是成本问题:推理成本与延迟随长度线性甚至更差地增长。要把它当成需要监控与控制的指标:用长度惩罚 / 长度归一化、采样后按 token 效率过滤(GFPO)、或裁剪方式调整(CISPO)来抑制。判断标准是「每正确一次的 token 成本」而不是绝对长度。
公开基准分数还能信吗?你会怎么做评测?
公开基准存在训练污染、题目泄露、以及模型「言语化地意识到自己在被测试」等问题(有研究报告约 20% 的样本出现这种怀疑表达),因此不能作为唯一依据。我的做法是:① 建自己的私有评测集,样本来自真实业务分布;② 做 n-gram / 嵌入级污染检查;③ 用 bootstrap 给置信区间而不是只报均值;④ 对高风险场景用影子评估思路(未公开的任务 + 独立评审);⑤ 同时报告延迟与成本,而不是只报准确率。