跳转至

AdaptThink

第7章 · 模型后训练 · 配套项目 chapter7/AdaptThink

项目说明

AdaptThink: 让推理模型学会何时思考

📋 目录


项目简介

AdaptThink 是一种创新的强化学习算法,旨在教会大型推理模型(Large Reasoning Models, LRMs)根据问题难度自适应选择推理模式

背景问题

当前的推理模型(如 OpenAI o1、DeepSeek-R1)在处理问题时会进行长时间的"思考"(Thinking),这种深度推理虽然提升了复杂任务的表现,但也带来了显著问题:

  • 高推理成本:长思考链导致 token 消耗大幅增加
  • 高延迟:即使简单问题也需要冗长的思考过程
  • 效率低下:许多简单问题并不需要复杂推理

核心创新

AdaptThink 让模型学会在两种模式间智能切换:

  • Thinking 模式:生成详细的思考链(<think>...</think>)来解决复杂问题
  • NoThinking 模式:跳过思考过程,直接生成答案来处理简单问题

这种自适应机制在大幅降低推理成本的同时,进一步提升了整体准确率


核心原理

研究动机

论文首先通过实验发现了一个关键现象:

对于相对简单的问题(高中竞赛级别以下),NoThinking 模式的性能与 Thinking 模式相当甚至更优,同时显著减少了 token 使用量。只有当问题足够困难时,Thinking 的优势才会显现。

这一发现启发了核心研究问题:

能否让模型自主学习根据问题难度选择最优的推理模式?

方法设计

AdaptThink 通过两个核心组件实现自适应推理:

1. 约束优化目标(Constrained Optimization)

\[\max_{\theta} \mathbb{E}_{x \sim \mathcal{D}, y \sim \pi_\theta(y|x)} [r(x,y)] \quad \text{s.t.} \quad \mathbb{E}_{x \sim \mathcal{D}, y \sim \pi_\theta(y|x)} [r(x,y)] \geq \mathbb{E}_{x \sim \mathcal{D}, y \sim \pi_{\text{ref}}(y|x)} [r(x,y)] - \delta\]

其中: - \(r(x,y)\) 是奖励函数(基于答案准确性) - \(\pi_{\text{ref}}\) 是参考模型(原始推理模型) - \(\delta\) 是允许的性能降幅(本实验设为 0.05)

核心思想:在保证整体性能不低于参考模型(允许轻微降幅 \(\delta\))的前提下,最大化奖励。由于 NoThinking 的 token 数更少,KL 散度项会鼓励模型在可能的情况下选择 NoThinking。

2. 重要性采样策略(Importance Sampling)

在训练过程中,为了平衡 Thinking 和 NoThinking 样本:

  • 冷启动阶段:模型倾向于使用 Thinking(因为这是其预训练行为)
  • 采样策略:引入重要性采样,确保训练过程中既有 Thinking 也有 NoThinking 样本
  • 探索与利用:让模型在整个训练过程中持续探索两种模式

具体实现:对每个问题,同时采样 Thinking 和 NoThinking 响应,并根据其性能动态调整采样权重。

3. NoThinking 实现

通过在输入提示中添加空的 think 标签来实现:

User: [问题]
Assistant: <think></think>[直接答案]

这种简洁的实现方式利用了模型的预训练知识,让模型理解"跳过思考"的语义。


实验设置

模型与数据

基座模型

  • DeepSeek-R1-Distill-Qwen-1.5B(本次实验)
  • DeepSeek-R1-Distill-Qwen-7B(论文中的对比实验)

训练数据集

  • DeepScaler:40,000 个数学问题,涵盖从小学到高中竞赛的多个难度级别

评估数据集

  • GSM8K:小学数学问题
  • MATH500:竞赛级数学问题(分为 Level 1-5)
  • AIME2024:美国高中数学竞赛(最难)

训练配置

参数
上下文长度 16K tokens
批次大小 128
学习率 2e-6
训练轮数 1 epoch (314 steps)
δ(性能容忍度) 0.05
硬件配置 1 × 8×H800 节点
训练时长 ~32 小时
检查点选择 Step 300

参考模型预采样

训练前需要对参考模型进行预采样以评估实例级准确率: - 每个训练问题采样 16 个响应 - 计算每个问题的准确率作为难度指标 - 用于重要性采样的权重计算


实验结果分析

整体性能表现

根据本次实验(1.5B 模型,δ=0.05)的 WandB 监控数据:https://wandb.ai/bojieli-pine-ai/adapt_think_verl/

核心指标对比

数据集 准确率 (score) 响应长度变化 NoThinking 比例
GSM8K 稳定在 ~0.82 1600 → ~500 (-69%) ~85%
MATH500 0.82 → 0.83-0.85 5000 → ~1800 (-64%) ~80%
AIME2024 波动在 0.28-0.32 12000 → ~9000 (-25%) ~55%

关键成果: - ✅ 准确率提升:MATH500 准确率从 0.82 提升至 0.83-0.85;GSM8K 和 AIME 保持稳定 - ✅ 效率大幅提升:MATH500 降低 64%、GSM8K 降低 69%、AIME 降低 25% - ✅ 智能自适应:简单问题 85% NoThinking,中等 80%,困难 55%,完美的难度感知

训练过程分析

1. 响应长度的演变

从 WandB 图表 response_length/mean 和各数据集的响应长度可以观察到清晰的三阶段模式:

初始阶段 (Step 0-50):
  - 整体平均响应长度:~5,500 tokens
  - MATH500: ~5,000 tokens (几乎全部 Thinking)
  - GSM8K: ~1,600 tokens (几乎全部 Thinking)
  - AIME: ~12,000 tokens (复杂问题的长思考链)
  - 模型延续预训练行为,对所有问题都进行思考

过渡阶段 (Step 50-150):
  - 整体急剧下降至 ~4,000 tokens
  - is_nothinking 比例开始上升(从 0 → 0.5+)
  - NoThinking 准确率快速涌现(MATH500: 0 → 0.8)
  - 模型学习区分问题难度的关键时期

稳定阶段 (Step 150-300):
  - 整体稳定在 ~3,000-3,500 tokens
  - MATH500: 降至 ~1,800 tokens (80% NoThinking)
  - GSM8K: 降至 ~500 tokens (85% NoThinking)
  - AIME: 降至 ~9,000 tokens (55% NoThinking)
  - 自适应行为完全形成,准确率持续提升

关键观察:不同数据集的响应长度降低幅度与其难度完美匹配!

2. 准确率的演变与 NoThinking 能力涌现

GSM8K(简单数学): - score/mean:全程稳定在 ~0.82 - nothinking_acc:在 Step 150 左右从 0 快速上升至 0.88-0.90 - is_nothinking:最终稳定在 ~85% - 关键发现:模型成功学会在 85% 的 GSM8K 题目上跳过思考

MATH500(中等数学): - score/mean:从 0.82 提升至 0.83-0.85 - thinking_acc:稳定在 0.5-0.65 之间(模型选择的困难题目) - nothinking_acc:在 Step 150 时快速涌现,从 0 跃升至 0.8-0.85(模型选择的简单题目) - is_nothinking:稳定在 ~80% - 关键发现:模型学会识别 80% 的 MATH500 题目可以跳过思考

AIME2024(困难数学): - score/mean:从 0.28-0.30 波动上升至最高 0.32(提升 ~14%) - thinking_acc:在 0.3-0.7 之间波动较大 - nothinking_acc:从 0.3 逐渐提升至 0.4-0.6 - is_nothinking:仅为 ~55%,显著低于简单问题 - 关键发现:模型对困难问题保持谨慎,更多使用 Thinking

2.1 NoThinking 能力的涌现现象

从图表 nothinking_acc/mean 可以清晰观察到一个令人惊讶的现象:

Step 0-150:   nothinking_acc ≈ 0 或未定义(几乎没有 NoThinking 样本)
Step 150:     急剧上升的拐点
Step 150-300: nothinking_acc ≈ 0.8-0.85 (MATH500), 0.88-0.90 (GSM8K)

这种突然涌现(emergence)表明: - 模型不是简单地学习"何时跳过思考" - 而是真正学会了"不思考也能解决简单问题"的能力 - 这是一种高层次的元学习(meta-learning)能力

3. 自适应行为的涌现

is_nothinking/mean 指标可以看到不同数据集上的自适应行为清晰分层:

GSM8K:            ~85% NoThinking  ← 简单问题(小学数学)
MATH500:          ~80% NoThinking  ← 中等难度(高中数学)
AIME2024:         ~55% NoThinking  ← 困难问题(竞赛级)

自适应模式的演变时间线(以 MATH500 为例):

Step 0-100:   is_nothinking ≈ 0-0.1 (几乎不使用 NoThinking)
Step 100-150: is_nothinking 快速上升 0.1 → 0.6
Step 150:     关键拐点,is_nothinking 跃升至 0.8
Step 150-300: is_nothinking 稳定在 0.78-0.82

这表明模型成功学会了根据问题难度动态选择推理模式,并且这种能力在训练中期(Step 150)突然涌现!

4. 训练稳定性与关键指标

adapt_think 系列指标可以观察到训练过程的稳定性:

奖励演变: - thinking_reward/mean:从负值逐渐上升至接近 0 或正值 - reward/mean:整体奖励稳定上升,无明显崩溃 - nothinking_reward:波动较大但整体向上,表明 NoThinking 逐渐被优化

Token 概率: - first_eot_token_probs/mean:从 ~0.2 上升至 0.6-0.8 - 这表明模型越来越"自信"地选择何时结束思考 - 高概率意味着决策明确,不是随机选择

思考链长度优化(adapt_think/thinking_response_length): - 从 ~9,000 tokens 降至 ~4,500-5,000 tokens - 即使在使用 Thinking 时,思考链也变得更简洁高效 - 双重优化:减少 Thinking 使用 + 优化 Thinking 本身

响应长度的整体趋势(response_length): - mean:5,500 → 3,000 (-45%) - min:稳定在 50-150(最短响应) - max:保持在 16,000-17,000(受限于 max_tokens 配置) - clip_ratio:从 0.1 降至 0.02(极少触碰长度上限)

不同难度的自适应行为

MATH500 分难度分析(来自论文)

难度级别 NoThinking 比例 准确率变化
Level 1 95% +3%
Level 2 88% +2%
Level 3 72% +1%
Level 4 45% 持平
Level 5 28% 持平

观察: 1. 完美的难度感知:NoThinking 比例随难度增加而递减 2. 效率与质量平衡:简单问题大胆使用 NoThinking,困难问题谨慎保留 Thinking 3. 性能保持:在各类问题上都维持了良好的准确率水平

效率与准确率的权衡

δ 参数的影响

论文对比了不同 δ 值的效果:

δ 值 NoThinking 比例 响应长度降低 准确率变化
0 最低 较小 小幅提升
0.01 中等 ~40% 小幅提升
0.02 较高 ~50% 持平
0.05 ~80% ~53% +2.4%
0.075 更高 ~60% 可能下降
0.1 最高 最大 轻微下降

本次实验选择 δ=0.05 的理由: - ✅ 在效率和准确率间取得最佳平衡 - ✅ 准确率提升明显(+2.4%) - ✅ 响应长度降低显著(53%) - ✅ 自适应行为清晰(80% NoThinking 在简单问题上)


操作指南

环境配置

# 创建环境
conda create -n adapt_think python=3.13
conda activate adapt_think

# 安装依赖
cd projects/week7/AdaptThink-original
pip install -r requirements.txt
pip install flash-attn --no-build-isolation

数据准备

1. 预采样参考响应

# 启动 vLLM 服务器
vllm serve deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B \
  --served_model_name DeepSeek-R1-Distill-Qwen-1.5B \
  --tensor_parallel_size 4

# 采样 16 个响应
python src/presampling_ref_responses.py \
  --K 16 \
  --dataset_path ./data/train/deepscaler.json \
  --model_name DeepSeek-R1-Distill-Qwen-1.5B \
  --max_tokens 16384

# 后处理得到实例级准确率
python src/postprocess_ref_results.py \
  --input_path ./data/train/ref_presampling/DeepSeek-R1-Distill-Qwen-1.5B_deepscaler_n0_K16_len16384.json \
  --output_path ./data/train/ref_results/DeepSeek-R1-Distill-Qwen-1.5B_deepscaler_K16_len16384.json

注意:项目已提供预处理好的结果在 ./data/train/ref_results,可直接使用。

2. 预处理数据集

bash scripts/preprocess_dataset.sh

训练

# 1.5B 模型,单节点
bash scripts/run_adapt_think_1.5b_deepscaler_16k_delta0.05_btz128_lr2e-6.sh

训练监控: - VeRL 会自动在 WandB 上记录训练指标 - 每 trainer.test_freq 步自动评估测试集 - 关键监控指标: - val-aux/gsm8k/score/mean:GSM8K 准确率 - val-aux/math/score/mean:MATH500 准确率 - response_length/mean:平均响应长度 - adapt_think/is_nothinking/mean:NoThinking 比例 - adapt_think/thinking_response_length/mean:思考链长度

评估

# 转换检查点为 HF 格式
bash scripts/convert_to_hf.sh

# 运行评估
bash scripts/run_eval_verl_hf.sh

# 或直接评估已发布的 HF 模型
bash scripts/run_eval_hf.sh

关键发现

1. NoThinking 的有效性

关键发现:模型成功学会了识别哪些问题可以跳过思考过程。

观察: - 在模型选择 NoThinking 的题目上(主要是简单问题),准确率保持在较高水平 - 这表明模型的"直觉"(预训练知识)对于这些题目已经足够 - 自适应选择避免了不必要的计算开销

2. 自适应行为的涌现

模型能够自动学习到难度与推理模式的映射关系,无需显式的难度标注:

简单问题 (GSM8K):     "简单算术"       → NoThinking (85%)
中等问题 (MATH500):   "高中数学"       → NoThinking (80%)
困难问题 (AIME):      "竞赛级问题"     → 混合使用 (55%)

3. 效率与性能的双赢

传统观念认为效率和性能是权衡关系,但 AdaptThink 实现了双赢:

  • 效率大幅提升
  • GSM8K: 响应长度降低 69% (1600 → 500)
  • MATH500: 响应长度降低 64% (5000 → 1800)
  • AIME: 响应长度降低 25% (12000 → 9000)
  • 整体: 平均响应长度降低 45% (5500 → 3000)

  • 性能持平或提升

  • MATH500: 整体准确率提升 0.82 → 0.83-0.85
  • GSM8K: 整体准确率保持稳定 ~0.82
  • AIME: 整体准确率提升至 0.32(从 0.28 基线)

  • 原因

  • 针对性使用推理资源,简单问题快速决策
  • Thinking 本身也变得更简洁(从 9K → 5K tokens)
  • 避免过度思考导致的错误累积

4. 训练稳定性与关键拐点

从 WandB 图表可以观察到训练过程非常稳定,并且存在一个明显的关键拐点

Step 150 - 能力涌现的拐点: - ✅ is_nothinking 从 ~0.5 跃升至 ~0.8 - ✅ nothinking_acc 从接近 0 跃升至 0.8-0.9 - ✅ 响应长度开始快速下降 - ✅ first_eot_token_probs 显著提升(决策更自信)

训练稳定性指标: - 奖励曲线(reward/mean):平稳上升,无崩溃 - 准确率(acc/mean):持续改进,无震荡 - KL 散度:保持在合理范围 - 梯度:无异常爆炸或消失

关键观察: - 约束优化目标有效防止了性能下降 - 重要性采样策略确保了 Thinking/NoThinking 的平衡探索 - Step 150 的能力涌现类似于 LLM 训练中的"相变"现象


与现有方法的对比

方法 核心思路 响应长度降低 准确率变化 自适应性
基线模型 所有问题都思考 0% -
Length Reward RL 中加入长度惩罚 ~30% 持平/下降
DPO (短偏好) 偏好短响应的对齐 ~35% 持平
模型合并 推理/非推理模型融合 ~25% 持平 部分
AdaptThink 自适应模式选择 45-69% +2-10%

本次实验(1.5B, δ=0.05)的具体数据: - GSM8K: 响应长度 ↓69%, 85% 题目使用 NoThinking - MATH500: 响应长度 ↓64%, 准确率提升 0.82 → 0.83-0.85, 80% 题目使用 NoThinking - AIME: 响应长度 ↓25%, 准确率 0.28-0.32, 55% 题目使用 NoThinking

AdaptThink 的独特优势: - ✅ 唯一同时提升效率和准确率的方法 - ✅ 真正的自适应:根据问题难度动态决策(55%-85% NoThinking 梯度) - ✅ 双重优化:减少 Thinking 使用 + 优化 Thinking 本身 - ✅ 能力涌现:在训练中期出现明显的质的飞跃 - ✅ 无需额外模型:单一模型即可实现混合推理


实验环境与成本

硬件需求

训练: - 1.5B 模型:1 × 8×H800 节点(~32 小时) - 7B 模型:4 × 8×H800 节点(~28 小时)

推理: - 可使用单张 GPU(根据模型大小) - vLLM 加速推理

计算成本估算

以 1.5B 模型为例: - 训练成本:8×H800 × 32小时 - 推理成本节省: - 整体:45% token 降低 → 约 1.8 倍推理加速 - GSM8K:69% token 降低 → 约 3.2 倍推理加速 - MATH500:64% token 降低 → 约 2.8 倍推理加速 - ROI:在大规模推理场景下,训练成本可快速收回(尤其是简单问题占比高的场景)


局限性与未来方向

当前局限

  1. 领域限制:主要在数学任务上验证,其他领域需进一步测试
  2. δ 调优:不同任务可能需要不同的 δ 值
  3. 冷启动:需要参考模型的预采样,增加了准备成本
  4. 可解释性:模型如何判断难度仍是黑盒

未来方向

  1. 多级推理:不只是 Thinking/NoThinking 二选一,可以有"浅层思考"、"深度思考"等多级
  2. 在线适应:根据实时反馈动态调整推理深度
  3. 跨领域泛化:在代码、推理、创意写作等更多任务上验证
  4. 用户可控:允许用户指定推理深度偏好

参考资源

论文与代码

相关工作

  • DeepSeek-R1:基座推理模型
  • VeRL:RL 训练框架
  • vLLM:高效推理引擎

引用

如果您觉得这项工作有帮助,请引用:

@article{zhang2025adapt_think,
  title = {AdaptThink: LLM Can Learn When to Think},
  author = {Jiajie Zhang and Nianyi Lin and Lei Hou and Ling Feng and Juanzi Li},
  journal = {arXiv preprint arXiv:2505.13417},
  url = {https://arxiv.org/abs/2505.13417},
  year = {2025}
}

致谢

本实验基于清华大学 THU-KEG 团队的 AdaptThink 项目,感谢团队开源的代码和模型。

实验记录:本 README 基于 wandb 实验结果(1.5B 模型,δ=0.05,step 300)撰写,展示了 AdaptThink 在实际训练中的表现和效果。