源文件:chapter7/AdaptThink/README.md AdaptThink: 让推理模型学会何时思考 📋 目录 项目简介 核心原理 研究动机 方法设计 实验设置 模型与数据 训练配置 实验结果分析 整体性能表现 训练过程分析 不同难度的自适应行为 效率与准确率的权衡 操作指南 关键发现 参考资源 项目简介 AdaptThink 是一种创新的强化学习算法,旨在教会大型推理模型(Large Reasoning Models, LRMs)根据问题难度自适应选择推理模式。
源文件:chapter7/AdaptThink/README.md
AdaptThink 是一种创新的强化学习算法,旨在教会大型推理模型(Large Reasoning Models, LRMs)根据问题难度自适应选择推理模式。
当前的推理模型(如 OpenAI o1、DeepSeek-R1)在处理问题时会进行长时间的"思考"(Thinking),这种深度推理虽然提升了复杂任务的表现,但也带来了显著问题:
AdaptThink 让模型学会在两种模式间智能切换:
<think>...</think>)来解决复杂问题这种自适应机制在大幅降低推理成本的同时,进一步提升了整体准确率。
论文首先通过实验发现了一个关键现象:
对于相对简单的问题(高中竞赛级别以下),NoThinking 模式的性能与 Thinking 模式相当甚至更优,同时显著减少了 token 使用量。只有当问题足够困难时,Thinking 的优势才会显现。
这一发现启发了核心研究问题:
能否让模型自主学习根据问题难度选择最优的推理模式?
AdaptThink 通过两个核心组件实现自适应推理:
其中:
核心思想:在保证整体性能不低于参考模型(允许轻微降幅 \delta)的前提下,最大化奖励。由于 NoThinking 的 token 数更少,KL 散度项会鼓励模型在可能的情况下选择 NoThinking。
在训练过程中,为了平衡 Thinking 和 NoThinking 样本:
具体实现:对每个问题,同时采样 Thinking 和 NoThinking 响应,并根据其性能动态调整采样权重。
通过在输入提示中添加空的 think 标签来实现:
User: [问题] Assistant: <think></think>[直接答案]
这种简洁的实现方式利用了模型的预训练知识,让模型理解"跳过思考"的语义。
| 参数 | 值 |
|---|---|
| 上下文长度 | 16K tokens |
| 批次大小 | 128 |
| 学习率 | 2e-6 |
| 训练轮数 | 1 epoch (314 steps) |
| δ(性能容忍度) | 0.05 |
| 硬件配置 | 1 × 8×H800 节点 |
| 训练时长 | ~32 小时 |
| 检查点选择 | Step 300 |
训练前需要对参考模型进行预采样以评估实例级准确率:
根据本次实验(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% |
关键成果:
从 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) - 自适应行为完全形成,准确率持续提升
关键观察:不同数据集的响应长度降低幅度与其难度完美匹配!
GSM8K(简单数学):
MATH500(中等数学):
AIME2024(困难数学):
从图表 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)表明:
从 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)突然涌现!
从 adapt_think 系列指标可以观察到训练过程的稳定性:
奖励演变:
Token 概率:
思考链长度优化(adapt_think/thinking_response_length):
响应长度的整体趋势(response_length):
| 难度级别 | NoThinking 比例 | 准确率变化 |
|---|---|---|
| Level 1 | 95% | +3% |
| Level 2 | 88% | +2% |
| Level 3 | 72% | +1% |
| Level 4 | 45% | 持平 |
| Level 5 | 28% | 持平 |
观察:
论文对比了不同 δ 值的效果:
| δ 值 | NoThinking 比例 | 响应长度降低 | 准确率变化 |
|---|---|---|---|
| 0 | 最低 | 较小 | 小幅提升 |
| 0.01 | 中等 | ~40% | 小幅提升 |
| 0.02 | 较高 | ~50% | 持平 |
| 0.05 | ~80% | ~53% | +2.4% |
| 0.075 | 更高 | ~60% | 可能下降 |
| 0.1 | 最高 | 最大 | 轻微下降 |
本次实验选择 δ=0.05 的理由:
# 创建环境 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
# 启动 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,可直接使用。
bash scripts/preprocess_dataset.sh
# 1.5B 模型,单节点 bash scripts/run_adapt_think_1.5b_deepscaler_16k_delta0.05_btz128_lr2e-6.sh
训练监控:
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
关键发现:模型成功学会了识别哪些问题可以跳过思考过程。
观察:
模型能够自动学习到难度与推理模式的映射关系,无需显式的难度标注:
简单问题 (GSM8K): "简单算术" → NoThinking (85%) 中等问题 (MATH500): "高中数学" → NoThinking (80%) 困难问题 (AIME): "竞赛级问题" → 混合使用 (55%)
传统观念认为效率和性能是权衡关系,但 AdaptThink 实现了双赢:
效率大幅提升:
性能持平或提升:
原因:
从 WandB 图表可以观察到训练过程非常稳定,并且存在一个明显的关键拐点:
Step 150 - 能力涌现的拐点:
训练稳定性指标:
关键观察:
| 方法 | 核心思路 | 响应长度降低 | 准确率变化 | 自适应性 |
|---|---|---|---|---|
| 基线模型 | 所有问题都思考 | 0% | - | ❌ |
| Length Reward | RL 中加入长度惩罚 | ~30% | 持平/下降 | ❌ |
| DPO (短偏好) | 偏好短响应的对齐 | ~35% | 持平 | ❌ |
| 模型合并 | 推理/非推理模型融合 | ~25% | 持平 | 部分 |
| AdaptThink | 自适应模式选择 | 45-69% | +2-10% | ✅ |
本次实验(1.5B, δ=0.05)的具体数据:
AdaptThink 的独特优势:
训练:
推理:
以 1.5B 模型为例:
如果您觉得这项工作有帮助,请引用:
@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 在实际训练中的表现和效果。