这一篇对应视频 07:“limits of RLVR,base vs. RL, pass@k, ppl 基于 vLLM 计算细节以及采样效率”(BV1pWSvBtEAk)。
我把它拆成三条主线:
- Base vs RL 的“能力”到底在对比什么:RLVR 更像分布削尖(distribution sharpening)还是能力外推(capability uplift)?
- 为什么一定要看 pass@k 而不只看 pass@1:以及怎么低方差地估算整条 pass@k 曲线。
- 怎么用 vLLM 可靠地算 PPL / entropy(评测细节):不踩坑地得到能解释现象的指标。
系列导航:
配套资料(你本地已有):
- 视频 07:
BV1pWSvBtEAk - 代码/笔记仓库(对应你本地下载的
modern_genai_bilibili-main):- GitHub:wdkns/modern_genai_bilibili/agentic_rl
- 本文主要对齐的 notebook:
agentic_rl/reasoning/rlvr.ipynb - 你本地路径:
/Users/wangpeng/Downloads/modern_genai_bilibili-main/agentic_rl/reasoning/rlvr.ipynb
- 论文/复现参考(视频里提到的方向):LeapLabTHU 的
limit-of-RLVR
1. 先把“结论冲突”说清楚:Base 很强,为什么还要 RLVR?
在 math/coding 这种 verifiable reward 任务上(做对就是 1,做错就是 0,或者有一个可程序验证的 score),RLVR 的一个常见现象是:
- RL 模型的 pass@1(只采样 1 次就做对的概率)会涨;
- 但 Base 模型只要你肯多采样(例如 128/256/1024 次),pass@k 可能已经很高了;
- 更糟的是,RL 训练经常会让输出分布更尖,多样性下降,一些“低概率但正确”的路径会被压没。
这就引出视频 07 的核心问题(也是你做 agentic RL / deep research 训练时必须面对的):
RLVR 到底是在“让模型更会推理”,还是只是把 Base 已经会的那一小撮正确轨迹的概率拉高,让它更容易一次采样命中?
如果你只看 pass@1,你会高估“能力提升”;如果你把 pass@k、PPL、entropy 一起看,你更容易看清它到底是在做什么。
2. pass@k:为什么它比 pass@1 更接近“能力上限”
2.1 pass@k 的定义(直觉)
pass@k 的语义很简单:
- 你对同一道题采样 $k$ 次;
- 只要这 $k$ 个答案里至少有一个是正确的,就算“这题被解决”。
这对 coding/math 的意义尤其大:Base 模型可能偶尔能走到正确解,但概率小。只要你愿意多采样,你会看到它的“潜力上限”。
形式化写法(论文里常见写法):
$$\text{pass}@k := \mathbb{E}\left[1 - \frac{\binom{n-c}{k}}{\binom{n}{k}}\right]$$
其中:
- $n$ 是你为该题采样的总次数(例如 128/256/1024);
- $c$ 是其中正确的样本数;
- $\frac{\binom{n-c}{k}}{\binom{n}{k}}$ 是“从 $n$ 个里抽 $k$ 个,抽到的全是错的”的概率;
- 所以 $1-\cdot$ 就是“至少有一个对”的概率。
2.2 为什么论文爱固定 $n$,再算一条完整的 pass@k 曲线
工程上你往往会固定一个比较大的 $n$(例如 1024),然后对所有 $k<n$ 估算出整条 pass@k 曲线:
- 这样你能比较“采样次数增加”带来的收益;
- 也能更清楚地对比 Base vs RL:RL 是否真的让曲线整体上移,还是只让小 $k$ 的点变好。
2.3 数值实现:别直接算组合数(会溢出)
rlvr.ipynb 里给了两个实现,组合数版在大 $n$ 时会数值爆炸,工程里更常用乘积版:
1 | import numpy as np |
这里的一个关键边界条件:
- 如果错的样本数 $n-c < k$,你抽 $k$ 个一定会抽到至少一个正确样本,所以 pass@k 直接是 1。
2.4 pass@k 的“隐藏前提”:采样相关性会让你误判潜力上限
pass@k 很强,但它也非常容易被“采样细节”影响,导致你误把“采样策略变了”当成“模型能力变了”。你至少要注意两点:
- 样本相关性(correlation)
- 同一 prompt 下的多次采样并不是独立同分布的“理想抽样”,尤其当你用的是低温度、强约束(top-p 很小、强 repetition penalty)或带模板的生成。
- 相关性越强,你的“多采样潜力”会被高估或低估,曲线的形状也会变得更难解释。
- pass@k 对解码超参极度敏感
- 同一个 Base 模型,
temperature/top_p/top_k一改,pass@k 曲线可能整体平移。 - 所以对比 Base vs RL 时,除了报告 pass@k,你还应该固定并报告解码策略(最好把 Base 和 RL 放在同一组解码设置下对比)。
- 同一个 Base 模型,
我建议你把 pass@k 当成“系统行为”的指标,而不是纯粹“模型静态能力”的指标:它反映的是 模型分布 + 解码策略 + 评测器 的合成效果。
3. Sampling Efficiency Gap:把“潜力上限”和“单次命中率”放到同一个数里
视频 07 里另一个很关键的指标是采样效率差距(Sampling Efficiency Gap):
$$\Delta_{\text{SE}} = \text{pass}@k_{\text{Base}} - \text{pass}@1_{\text{RL}}$$
直觉上它在衡量:
- Base 模型“只靠多采样”能到哪(上限);
- RL 模型“只采 1 次”离这个上限还有多远(效率)。
你可以把它理解成一种很现实的 tradeoff:
- RL 的意义很多时候不是“发明新能力”,而是把 Base 的潜力变成可用的采样效率(从 256 次变成 1 次)。
- 但如果 $\Delta_{\text{SE}}$ 仍然很大,说明你当前 RL 算法(PPO/GRPO/变体)仍然没把 Base 的潜力吃干榨净。
这对 agentic RL 非常重要:你做 deep research agent 时,很多能力也可能“Base 偶尔能做到”,但成本太高。你的目标往往是把它变成稳定可用的行为,而不是在 benchmark 上秀 pass@1。
4. 用 PPL 识别“分布削尖”还是“边界拓展”
4.1 Base 对 RL 输出的困惑度:RL 是否逃逸出 Base 分布?
rlvr.ipynb 里写了一个非常有用的诊断:
- 固定 Base 模型 $P_{\text{Base}}$;
- 让 RL 模型生成答案 $Y_{\text{RL}}$;
- 计算 Base 模型对这些 token 的负对数似然,并转成 perplexity。
$$\text{PPL}_{\text{Base}}(Y_{\text{RL}}\mid x)=\exp\left(-\frac{1}{T}\sum_{t=1}^{T}\log P_{\text{Base}}(y_t\mid x,y_{<t})\right)$$
判读要点:
- 如果 $\text{PPL}{\text{Base}}(Y{\text{RL}}\mid x)$ 很低,说明 RL 输出在 Base 看来“很合理”,更像是在 Base 分布内部做 reweighting(削尖)。
- 如果它明显升高,说明 RL 输出更像“跑出了 Base 的高概率区域”,有边界拓展的迹象(但也可能是胡言乱语,需要结合 correctness)。
4.2 distillation 为什么可能更“扩边界”
视频与笔记里对比了 distillation:如果你引入 teacher(例如强推理模型)的输出再蒸馏,学生模型的推理边界可能会真的被推开。
这给你的启示是:
- 如果你期待“深研究 agent 真的学会新东西”,只靠 RLVR 可能不够;
- 你可能需要 distill / curriculum / tool-augmented data,让“新轨迹”进入可学习分布,然后再用 RL 提升单次命中率与稳定性。
4.3 PPL 的误读风险:风格/模板变化也会让 PPL 变大
用 $PPL_{\text{Base}}(Y_{\text{RL}})$ 做分布诊断很有用,但它也有一个常见误区:PPL 变大不一定代表“更强/更弱”,很多时候只是“写法变了”:
- RL 改了输出风格(更啰嗦/更简洁/更多模板化 token),Base 当然会困惑。
- prompt 模板、system prompt 或工具输出拼接方式不同,token 边界变化会直接影响 PPL。
- Base 可能对“低概率但正确”的解法本来就不自信,正确解也可能对应高 PPL。
所以我更建议把它当成 “分布漂移报警器”:PPL 明显上升时,你应该做两件事:
- 人工抽样看输出是否变怪(格式、重复、幻觉、答非所问)。
- 联合 correctness/pass@k/entropy 一起判断:是“跑偏”还是“拓展到罕见但正确的区域”。
5. vLLM 评测细节:如何可靠地算 PPL / token entropy
视频 07 专门讲了一个“很工程但决定你指标是否可信”的点:在 vLLM 里算 logprob 的方式。
如果你发现自己还在 vLLM 的 OOM/吞吐低/ITL 差 里挣扎,建议先把推理引擎的参数体系搞清楚(否则评测脚本可能根本跑不起来):
5.1 核心思路:把 (prompt + response) 当成 prompt,取 prompt_logprobs
vLLM 的 LLM.generate 支持:
prompt_logprobs=K:返回输入文本每个位置的 Top-K token logprob;max_tokens=1:只 forward,不真的生成(评测模式)。
因此你可以把完整文本拼起来:
1 | full_texts = [p + r for p, r in zip(prompts, responses)] |
然后关键是做 masking:
- 你只想算 response 的 PPL,不想把 prompt 的 logprob 算进去;
- 所以需要找到 response 在 token 序列里的起始 index(
start_idx)。
rlvr.ipynb 的做法是:重新 tokenize prompt,取其长度作为 start_idx。
5.2 最容易踩的坑:Top-K 太小,actual token 不在返回字典里
vLLM 返回的 output.prompt_logprobs 是一个 list[dict]:
- 每个位置一个 dict;
- dict 里是 Top-K 的
{token_id: Logprob}。
如果你把 prompt_logprobs 设成 1,那么它只返回 top-1 token 的 logprob。
但你要算 PPL,需要的是“实际发生的那个 token”的 logprob;如果实际 token 不是 top-1,那么你在字典里根本找不到它。
因此 notebook 里强调:prompt_logprobs 应该设大一些(vLLM 目前上限通常是 20)。
下面是 notebook 里更完整的 PPL + entropy 计算逻辑(我把注释精简成“你真正要记住的”):
1 | def calculate_metrics(llm, prompts, responses, top_k_for_entropy=20): |
你应该从这段代码里带走 3 个“评测原则”:
- prompt 与 response 的 token 边界必须对齐(同一个 tokenizer,同一个模板)。
- Top-K 截断会让 PPL/entropy 失真:K 太小就别算,或至少要在 log 里显式标记为 NaN/跳过。
- entropy 只是 Top-K 近似,但对“分布变尖/多样性下降”的趋势判断很有用。
5.3 prompt 模板要和训练一致,否则指标不对
rlvr.ipynb 里特意强调:不要直接用默认 chat template,而是要用和训练一致的模板拼 prompt。否则:
- token 边界变了;
- 你算的 PPL / pass@k / entropy 全都不可比。
它用的是一个手写的 Qwen 风格模板(system + user + assistant),这在 LLM-RL 评测里非常常见。
6. 对你做 Agentic RL / Deep Research 的启示
如果你想用 agentic RL 做 deep research,你需要一开始就想清楚“你究竟想优化什么”,以及“你愿意牺牲什么”:
- 只要你用的是 verifiable reward(可验证正确/错误),你大概率会遇到同样的问题:RL 把分布削尖,提升单次命中率,但可能降低探索与多样性。
- deep research 的难点往往不是“写出一个正确答案”,而是“找到正确问题、覆盖足够证据、做出可信引用、控制成本”,它更像一个需要探索的搜索问题。
因此你至少要准备一个“反削尖”的评测闭环:
- 主指标:任务成功率(含引用/事实一致性/覆盖)。
- 稳定性指标:KL、entropy、clip fraction(你前面几篇博客讲过)。
- 潜力上限:Base 的 pass@k 曲线(以及 RL 的 $\Delta_{\text{SE}}$)。
- 分布诊断:$\text{PPL}{\text{Base}}(Y{\text{RL}}\mid x)$,看是否真的出现“边界拓展”。
如果你后续想把这一套真正落到“可复现的训练 pipeline”,下一步建议从 verl 的 rollout + reward manager + objective 开始,把训练日志里的这些量都打通(我可以继续按代码结构拆给你)。

