LAPO
Paper · arXiv 2025 · 2507.15758

LAPO:先发现该想多长,再让模型自己把这件事说出来

推理模型对简单题也写上千个 token,这是 overthinking。LAPO 不靠外部截断,也不靠固定长度惩罚,而是先用 GRPO 从正确解的长度分布里统计出「这张题大约要想多久」, 再把中位数写进 <think> 后的一句自我声明,让模型把预算当成自己的计划,而不是别人下达的指令。

Xingyu Wu 等 · 浙江大学 arXiv 2507.15758 ↗ 代码 zju-real/lapo ↗
TL;DR · 30 秒抓住核心

「长推理」的浪费不在于想得多,而在于题难不难都用同样多的字。论文的观察是:同一道题采样 N 条 rollout,做对的那几条长度天然不同,它们的分布本身就刻画了这道题需要多少思考。

第一阶段(Discovery)用 GRPO 加一个只奖正确解的长度奖励:正确解落在 [P30, P70] 区间得满分,偏离按线性衰减,错误解的长度奖励恒为 0。同时把正确解长度的中位数存成问题到长度的映射 M(q)。

第二阶段(Internalization)把 M(q) 写成 <think> I will answer the question with n tokens. 放进 prompt,奖励换成高斯形的一致度 R₂:越接近 n 分越高。关键在位置——声明必须在 <think> 之内,模型才会把它当计划,放到外面就变成照抄指令。

推理时不需要再喂 n,模型自己写出它。代价是:训练仍是标准 GRPO,两阶段各 3 个 episode,4 张 A800;但实验全部在数学题上,声明一旦被写出,预算也就被自己钉死。

−38.5%
DeepScaleR-1.5B 平均 token
6229 → 3832,准确率 +2.3 pp
−41.0%
DeepSeek-R1-1.5B 平均 token
8086 → 4775,准确率 +1.2 pp
0.0
错误解的长度得分
错解无论多短都拿不到长度奖励
01

正确解的长度并不唯一,而模型对每道题都用同一种长度

把「该想多长」当成一个可以观测的统计量,而不是一个要人为设定的超参数。

经过 RLVR 训练的推理模型(o1、R1 这一类)靠长思维链换来准确率,但采样时的自由度没有被约束:论文引用的数据显示,这类模型的推理轨迹可以达到短 CoT 模型的数倍,简单题上也塞满重复验证与自我怀疑。这就是 overthinking,直接后果是推理成本与延迟。

LAPO 的前提是一个可以被检验的经验事实:同一道题,模型做对多次时,每次的长度是分散的。比如 Table 1 里 DeepScaleR-1.5B 在 MATH-500 上平均 3280 token,在 AIME2024 上平均 9246 token——平均长度本身随题群变化,说明长度里确实编码了难度;而每条 rollout 之间的离散,则给出了「这张题想多长都算做对」的区间。

ℒ(q) = { |ri|  :  𝕀(yi = ygold) = 1,   i ∈ [1, N] }
Eq. 1 · 从 GRPO 同一批 rollout 里直接筛出「做对了的回答」的长度集合

问题因此从「怎么把长度压到某个数」变成了「怎么让模型自己在解题前知道 ℒ(q) 的大致位置」。前者需要人给每个任务设定预算(L1、ThinkPrune 走这条路),后者如果把 ℒ(q) 直接告诉模型,又会在推理时依赖外部标注。论文要的是训练阶段知道、部署阶段不需要。

为什么不是越短越好

长度缩短一旦损害正确性,收益就是负的

推理任务的奖励是二值的:答对 1、答错 0。在此之上加的每一分长度奖励,都在和「保住正确性」争梯度。论文把所有长度奖励都乘上正确性指示 𝒞i,错误解的长度奖励恒为 0——缩短的前提是先做对。

02

三条路各有各的偏:会过短、不会估、只会开或关

论文在 Related Works 与 Introduction 里把已有方法分成三类,每一类的失效方式都不同。

奖励惩罚 / 外部预算

长度目标由人给

在奖励里加长度惩罚(如 HAPO 的历史感知奖励),或训练模型服从给定的预算(L1 用 exact / max 预算,ThinkPrune 用截断价位的长度约束)。

问题:惩罚给重了会 over-shortening、准确率下降;预算要逐题逐任务人工指定,且不会随问题复杂度变化。

提前终止

边想边判断要不要停

根据置信度或验证信号在推理中途截断(如 s1、Concise 一类方法)。

问题:终止决策发生在「思考过程中」,论文认为这经常把逻辑链截断在半路,让模型无法得出正确结论。

思考开关

只能在两档之间选

学习一个 think / no-think 的二值策略(AutoThink、AdaptThink、Thinkless)。

问题:粒度太粗。一道 AIME 题和一道 Level 1 代数题可能都落在「要思考」这一档,长度没有区分。

论文给出的共同诊断是:这三类方法都把长度控制当成施加在推理过程之外的约束。而数学题本身有内在复杂度,模型做对时已经自然收敛到某个长度——这个长度信号就在 rollout 里,没有被用起来。

同一张表里,三条路各自漏在哪

下表取自 Table 1 的 DeepScaleR-1.5B-Preview 一栏(平均列)。可以看到 L1-Exact 最短(2278)但准确率掉到 56.2;ThinkPrune-4k 准确率最高(63.5)但 token 仍是 4094;LAPO-I 用 3832 token 拿到 64.8。

方法思路平均 Pass@1 ↑平均 #Tok ↓
L1-Exact外部给定精确预算56.22278
L1-Max外部给定最大预算57.52541
ThinkPrune-4k截断式训练 + 4k 约束63.54094
AutoThinkthink / no-think 二值策略60.44144
Acc-Only只用准确率奖励的 GRPO63.94696
BaseDeepScaleR-1.5B-Preview 原始模型62.56229
LAPO-I发现 + 内化两阶段64.83832

数据来源:Table 1 · Average 列。表中只保留代表每种思路的一行,完整对照见第 06 节。

03

两个阶段、两个奖励:先把长度统计出来,再让模型声明并遵守它

第一阶段学「多长算对」,第二阶段学「说了多长就做多长」,两个奖励都不惩罚错误解的长度。

第一阶段 · Discovery:长度奖励只作用于正确解

从正确解集合 ℒ(q) 里取两个百分位作为「合理区间」,取中位数作为「目标长度」:

[Lmin, Lmax] = [Percentile30(ℒ(q)), Percentile70(ℒ(q))]      M(q) = Median(ℒ(q))
Eq. 2 · 区间用来给第一阶段做奖励;Eq. 3 · 中位数用来给第二阶段做声明目标

对一条正确解,先算它到区间的距离 di = min(||ri|−Lmin|, ||ri|−Lmax|),再用线性衰减 f(d) = max(0, 1 − d/100) 打分。奖励是准确率加上长度分:

RD(ri, q) = 𝕀(yi = ygold) + α · R1(ri, q)      (α = 0.7)
R1 = 1.0  if 𝒞i=1 ∧ |ri| ∈ [Lmin, Lmax]  ·  f(di)  if 𝒞i=1 ∧ |ri| ∉ [Lmin, Lmax]  ·  0  if 𝒞i=0
Eq. 4–5 · 落在区间内的正确解得满额长度分;偏离 100 token,长度分归零;错误解的长度分恒为 0

这意味着 α 设成 0.7 时,一条正确但偏长 10 token 的解得 1 + 0.7 × 0.9 = 1.63,而一条正确且落在区间内的解得 1.7;一条错误解最多得 1.0,无论它多短。长度分只在同样做对的解之间区分优劣,这正是 GRPO 的组内比较所需要的。

第二阶段 · Internalization:把中位数写进 <think> 里,用高斯奖励对齐

进入第二阶段时,每道题的 prompt 后面被追加一句自我声明,n 就是第一阶段算出的 M(q):

<think> I will answer the question with n tokens. …
论文 Figure 2 / 3.3 节 · 声明位置紧贴 <think> 之后,被当作推理上下文的一部分,而不是前置的系统指令

奖励换成以 n 为中心的高斯函数,奖励「说多少做多少」,同样只对正确解生效:

RI(ri, q′) = 𝕀(yi = ygold) + β · R2(ri, n)      (β = 0.7)
R2 = exp( −(|ri| − n)2 / 2σ2 )  if 𝒞i=1      0  if 𝒞i=0
Eq. 6–7 · 与 n 完全一致的解得满分长度分,偏离越大分越低;σ 的具体取值论文未在正文给出

注意和第一阶段的结构差异:Discovery 的奖励是不对称的——区间内一律满分,区间外按距离线性扣分;Internalization 的奖励是单峰对称的——只认一个点 n。前者给模型一个宽裕的探索带,后者收窄成一个可以复述的目标。

第一次进入第二阶段时,n 是 Discovery 最后一次算出的 M(q);之后每个训练步都用新的 rollout 更新 M(q):之前没做对的题用本轮中位数,已经做对的题取旧值与新中位数的较小者(Eq. 8)。这让刚做对的题拿到一个宽松的起点,已做对的题只会越来越短。

为什么「位置」比「有没有」更关键

声明在外面 = 外部指令,声明在里面 = 自己的计划

论文的消融(Table 2)把同一套奖励下的四种写法放在一起比:声明精确 vs 区间 vs 无声明,以及声明放在 <think> 前 vs 后。准确率最好的不是最小值、不是均值,而是精确命中 <think> 之后的中位数——64.8%,而同样内容放到外面是 63.9%,完全不写是 63.6%。

自己动手:在 5 条 rollout 上算一遍两个奖励

下面是一个玩具题目 q,模型采样了 5 条 rollout(N=8 的简化版),其中 3 条做对。切到第一阶段看长度分怎么从正确解里挑出「典型长度」;切到第二阶段看高斯奖励怎么让所有正确解都往中位数靠。n 固定为 Discovery 阶段算出的 M(q),σ 取 700(论文未给出具体值,此处仅作示意)。

正确解长度的 30 / 70 分位 中位数 = 第二阶段声明的 n R₁ 满分区间
当前选中

点击任意 rollout 卡片,可看单条的手算过程。

这个模拟简化了什么?点开看与论文公式的差异

模拟用 5 条 rollout、3 条正确,论文是每步 N=8 条。长度单位取 token,数值是手选的示意值;分位数在 3 个样本上用 最近秩(nearest-rank)算:P30 取排序后第 ⌈0.3×3⌉ = 1 个,P70 取第 ⌈0.7×3⌉ = 3 个,所以区间恰好等于最小与最大的正确解。论文没有说明分位数的插值方式,样本量更大时两者差别很小。

第二阶段的高斯 σ 在正文和附录里都没有给出具体值,模拟取 σ = 700 只是让曲线在 700–3800 的跨度上看得清楚,不代表论文设置。两阶段的 α、β 均按论文取 0.7。

论文真实训练时,出错或无正确解的题会触发一些分支(例如无正确解时 M(q) 置为最大长度 4096),模拟只保留「所有 rollout 都可解析、有至少一个正确解」这一最常见情形。

04

没有新模型、没有新数据:仍是 GRPO,只是换了两次奖励和一次 prompt

LAPO 是训练流程的改造,不是新算法;开销主要来自两阶段各跑一遍 rollout。

项目设置出处
基础模型DeepSeek-R1-1.5B(即 DeepSeek-R1-Distill-Qwen-1.5B)与 DeepScaleR-1.5B-Preview§4 · 附录 A.1
训练数据10,000 道数学题:DeepScaleR-Preview 6,000 + MATH 中等级 4,000§4 Training Details
算法GRPO(OpenRLHF 实现),两阶段各 3 个 episode,约 240 步§4 · 附录 A.1
奖励权重α = 0.7(R₁),β = 0.7(R₂)§4 · 附录表 5
采样每问 8 条 rollout,温度 1.0;训练最大长度 4096;KL 系数 0.0001,学习率 1e-6,batch 128附录 A.1 表 5
评测生成长度上限放宽到 32,768;每问采 4 条(MATH-500 / OlympiadBench)或 32 条(AIME / AMC);温度 0.6、top-p 0.95§4 Evaluation Details
硬件4 × A800附录 A.1

M(q) 在训练中怎么演化

关键的设计在于 M(q) 是一条随训练自我更新的曲线,不是静态统计:

结论:为什么「发现」之后还要「内化」

只做第一阶段(LAPO-D)只能压掉 1/3,剩下的要让模型自己说出来

Table 1 中 DeepScaleR-1.5B:Base 6229 token → LAPO-D 4116(原文表内无百分比;论文章节称 LAPO-D 单独实现 36.0% 的 token 压缩)→ LAPO-I 3832。第二阶段的额外 6.9% 正是来自「声明 + 一致度奖励」——如果把声明去掉(Table 2 的 w/ Implicit),token 退回 4088,准确率也回到 63.6%,和 LAPO-D 相近。

训练动态:两段阶梯式回落

附录 A.2 用 MATH-500 验证集的检查点记录了过程:Discovery 把平均长度从 3280 迅速压到约 2365 后稳定,Internalization 再压到 2200 以下;同时准确率从 85.8% 爬到 86.4% 以上并保持,论文称内部化阶段出现一个「短暂的性能高峰」,说明声明不只是限制,也在引导模型更集中地推理。

工程上最容易低估的是训练长度上限是 4096,而评测上限是 32,768。也就是说,模型在训练时从未见过超过 4096 token 的解,但评测时对 AIME 这类最难题的平均长度为 5371(Table 1),明显超出训练窗口——论文把这一点当作泛化的证据(见第 06 节),同时它也是理解「内化的是规律而非模板」的关键。

05

一条闭环:采样 → 统计 → 声明 → 对齐 → 收紧

把 03 节的公式放回训练循环,就是下面的数据流;两个阶段之间共享同一张 M(q) 表。

Discovery · 3 episodes 长度统计 Internalization · 3 episodes GRPO · N = 8 问题 q → 8 条 rollout 有对有错,长度各异 ℒ(q) 只收正确解的长度 区间 [P30, P70] R₁ 的满分带 R_1 只加给正确解 拍错 100 token 以内有分 每步重算 ℒ(q),覆盖 M(q) M(q) = Median(ℒ(q)) 代表这张题的「典型」长度 没做对 → 4096(探索上限) 持久化:跨阶段共享 <think> … with n tokens. n = M(q),写进推理上下文 位置:紧贴 think 之后 推理时只写一次自己的预算 R_2 = exp(−(|r|−n)²/2σ²) 只对正确解;越接近 n 越高 GRPO 组内比较 → 更新 π_θ 声明 + 对齐奖励 = 内化 Eq. 8 · M(q) 更新 未做对 → 用新中位数 已做对 → min(旧 M, 新中位数) 预算只收紧,不反弹 推理时无声明输入 · 长度匹配问题难度 Figure 3:复杂度与生成长度近似线性正相关 两段各自压一次长度 主结果见 06 节
图 1:LAPO 的数据流(依论文 Figure 2 与 Algorithm 1 重绘)。左:Discovery 阶段在 GRPO rollout 上统计长度,用 R₁ 训练;中:中位数被持久化为 M(q),并写入第二阶段的声明;右:Internalization 用 R₂ 对齐声明与输出,同时用 Eq. 8 更新 M(q)。虚线表示每步都会重算一次 M(q)。
展开说明 ▸
  • 两个阶段用的是同一批训练题:没有额外的标注数据,也没有专门的描述长度模型。ℒ(q) 完全来自第一阶段模型自己的采样。
  • M(q) 跨阶段共享是设计的核心:第二阶段的声明 n 直接是第一阶段算出的数,这意味着如果第一阶段没有学会「做对但更短」,第二阶段的目标也会随之偏长。
  • 「声明」既是输入也是输出:训练时每道题被加上声明,推理时模型自己生成声明。论文的假设是模型学到了「在 think 开头先估一个长度」这套模式,所以不需要外部再喂。
  • 奖励的两个阶段完全平行分工:R₁ 看「长度是否落在合理区间」,R₂ 看「长度是否等于声明的 n」。前者是分布层面的,后者是点层面的。

图中最值得留意的是「自举」关系:第二阶段的奖励目标 n 来自第一阶段策略的采样结果,而第一阶段的采样又随着训练变短。两阶段各只有 3 个 episode,这个正反馈没有时间走得很远——它既是 LAPO 的简洁之处,也是后面 07 节的边界之一。

06

两个基础模型都「更短更准」,难点题的长度反而超出了训练窗口

四个数学基准的平均列是全篇最干净的证据;消融则说明中位数和声明位置都不能随便换。

主结果(Table 1,只摘两个基础模型的关键行)

方法MATH-500AIME2024AMC-23OlympiadBenchAverage
Pass@1#TokPass@1#TokPass@1#TokPass@1#TokPass@1#Tok
基础模型 · DeepSeek-R1-1.5B
HAPO82.2228831.3864967.3473550.1502457.75174
Base83.1403130.31215068.3722250.0894257.98086
+ Acc-Only83.3306131.61062870.5530750.6640259.06349
+ LAPO-D84.7256628.5841572.2413251.3559559.25177
+ LAPO-I84.3235429.3831871.2356851.7486359.14775
基础模型 · DeepScaleR-1.5B-Preview
Base85.8328035.5924674.2641654.6597462.56229
ThinkPrune-4k86.6204235.5648876.3383955.7401063.54094
+ Acc-Only85.6251036.9731977.6424455.6471263.94696
+ LAPO-D86.4236537.6594577.6365556.1449964.44116
+ LAPO-I86.3216838.1537178.3376556.3402464.83832

几个从表里能直接读出的点:

反直觉发现:内化的证据是「不听外部指令」

Table 4 是一个对抗性测试:对已经训练好的 LAPO-I 和「声明放在 think 外面」的变体,在推理时额外注入彼此矛盾的长度要求(Short = 500,Long = 3500)。如果模型学到的是「服从长度指令」,两者都应该跟着变;如果学到的是「自己的计划」,LAPO-I 应该无视外部要求。

模型注入约束MATH-500 Pass@1#Tok
LAPO-I(声明在 think 内)无86.32168
+ Short (500)86.02279
+ Long (3500)85.92300
LAPO-I w/ Outside(声明在 think 外)无86.22251
+ Short (500)85.11247
+ Long (3500)86.12821

LAPO-I 在 Short 下长度只从 2168 浮动到 2279、在 Long 下到 2300,基本围着 2200 左右的基线;同一个模型家族把声明放到外面的版本,Short 下 token 直接砍到 1247,Long 下拉到 2821。「听到就照做」是外部指令,「听到也不改」才是内化的计划——这是论文对 internalization 一词最直接的操作化。

消融:中位数与精确声明分别不可替代

Table 2 · 声明写法

精确 > 区间 > 外面 > 不写

w/ Exact 64.8 · 3832
w/ Range 64.1 · 3964
w/ Outside 63.9 · 4022
w/ Implicit 63.6 · 4088

精确单点比区间高 0.7 pp、少 132 token;同样的内容挪到 think 外面掉 0.9 pp;完全不写掉 1.2 pp 且 token 回到与 LAPO-D 相近的水平。

Table 3 · 统计量

中位数 > 均值 > 最小值

w/ Median 64.8 · 3832
w/ Mean 64.1 · 4040
w/ Minimum 63.5 · 3821

均值被少数超长正确解拉高,预算给宽了;最小值压得最狠(3821)却掉 1.3 pp。论文的解释与 03 节一致:中位数才是「典型但不过短」的稳健代表。

更多结果:训练动态、数据配比、GPQA 泛化来自附录 A.2–A.4

训练动态(Figure 5):MATH-500 上平均长度从 3280 两段式下降,先到约 2365(LAPO-D),再降到 2200 以下(LAPO-I);准确率始终保持或略升。

训练数据配比(Table 6):仅用 DeepScaleR 数据时 LAPO-I 平均 63.8 / 4088,仅用 MATH 时 63.0 / 4251,混合数据 64.8 / 3832。论文把均衡的难度梯度视为学到准确「复杂度—长度映射」的前提。

GPQA 泛化(Table 7):在知识密集型、非数学的 GPQA 上,DeepSeek-R1-1.5B 的 LAPO-D 准确率 +2.0 pp、token −26.2%;DeepScaleR-1.5B 的 LAPO-D +2.2 pp、−19.4%。Learning Rate 等其他超参见附录表 5。

07

它学会的是「说多少做多少」,而声明一旦写出就是硬约束

LAPO 的收益依赖两个前提:题目能判对错、模型能估准。前者让长度分布可统计,后者让声明不至于误导。

边界一

靠二值正确性定义「好长度」

ℒ(q) 只由 𝕀(yi = ygold) 筛出。没有参考答案、无法自动判定的任务(开放式写作、多步 Agent 交互)就没有「正确解长度分布」可统计。附录的 GPQA 实验说明知识题也能泛化,但 GPQA 仍是单轮选择题,与前沿数学一样有标准答案。

边界二

n 算偏了会连带压准准确率

第二阶段奖励以 n 为中心。如果某道题在第一阶段的正确解本来就偏短(例如碰巧走了捷径),M(q) 就会偏小,模型被推向这个点。Table 3 中最小值方案准确率跌到 63.5 是对这个风险的直接证据。

边界三

声明是「先写后想」,写错了改不了

Artifact 在 <think> 的第一句就出现,之后整段推理跟着它走。论文没有讨论「先声明后发现自己估错」的处理方式,也没有 token 级的动态调整机制。增强型的「边想边改预算」仍然是一个开放问题。

边界四

实验面窄,超参未经充分搜索

四个数学基准、两个 1.5B 模型、平均列上的差距多为 1–2 pp;训练只有 3 + 3 个 episode、4 张 A800,不足以支撑更大模型上的结论。作者自己也写明 α、β 是经验选取,「未做大量超参搜索」。

什么时候别用:先问三个问题

一句话总结:LAPO 把长度控制从「外部设定」变成「从正确解里统计出来的自我计划」。它便宜、改造范围小、效果稳定,但内化的前提是问题有标准答案,而声明的代价是思考一旦开头就基本定了长度。