DeepSeek-R1 的开源实现
DeepSeek-R1 的开源复现项目已在 GitHub 发布,在 Hacker News 上获得 101 个积分。该项目旨在以开源方式复现 DeepSeek-R1 模型。
Hugging Face 把 DeepSeek-R1 的完整训练管线拆解得清清楚楚,从数据蒸馏到 GRPO 强化学习都开源了,还放出了复现的模型和数据集。想理解或自己训练推理模型的开发者,这大概是目前最实用的路线图。
DeepSeek-R1 的完全开源复现。本仓库仍在持续开发中,让我们一起共建!
目录
概述
本仓库的目标是构建 R1 流程中缺失的部分,让每个人都能复现并在其基础上进行开发。该项目设计简洁,主要包括:
src/open_r1: contains the scripts to train models as well as generate synthetic data:grpo.py:使用 GRPO 在给定数据集上训练模型。sft.py:对模型在数据集上执行简单的 SFT。generate.py:使用 Distilabel 从模型生成合成数据。
Makefile:包含利用上述脚本执行 R1 流程各步骤的易运行命令。
行动计划
我们将以 DeepSeek-R1 的 技术报告 为指导,大致可分为三个主要步骤:
- 步骤 1:通过从 DeepSeek-R1 蒸馏高质量语料,复现 R1-Distill 模型。
- 步骤 2:复现 DeepSeek 用来创建 R1-Zero 的纯强化学习流程。这可能需要为数学、推理和代码整理新的大规模数据集。
- 步骤 3:展示我们可以通过多阶段训练,从基础模型走到强化学习微调后的模型。

新闻 🗞️
- 🧑🍳 [2025/05/26](第 1 步已完成!) 我们发布了 Mixture-of-Thoughts——一个精心策划的推理数据集,包含 35 万条从 R1 蒸馏而来的已验证推理轨迹。该数据集涵盖数学、编程和科学任务,旨在教语言模型逐步进行推理。我们还提供了训练 OpenR1-Distill-7B 的方案,该模型复现了 deepseek-ai/DeepSeek-R1-Distill-Qwen-7B 的推理能力,并标志着 Open R1 项目第 1 步的完成。
- ⚡️ [2025/03/11] (第 3 次更新): 我们发布了 CodeForces-CoTs 数据集,包含 1 万道竞赛编程题和 10 万条从 R1 蒸馏而来的解答。我们还发布了 IOI24:一个由国际奥林匹克竞赛中 非常困难的题目组成的新基准。在 CodeForces-CoTs 上训练的 7B Qwen 模型在 IOI24 上可以超越 Claude 3.7 Sonnet,而 32B 模型甚至可以超越 R1 本身。
- ∞ [2025/02/10] (第 2 次更新): 我们发布了 OpenR1-Math-220k 数据集,包含 22 万条从 R1 在新版 NuminaMath 上蒸馏而来的推理轨迹。在该数据集上训练的模型可以达到 DeepSeek 蒸馏模型的性能水平。
- 🔥 [2025/02/02] (更新 #1): 我们实现了 训练、推理和 评测流水线的第一部分。开始吧!
安装
[!CAUTION] 相关库依赖 CUDA 12.4。如果你看到与段错误(segmentation fault)相关的错误,请用
nvcc --version仔细检查你系统正在运行的版本。
要运行本项目中的代码,首先请使用例如 uv 创建一个 Python 虚拟环境。要安装 uv,请按照 UV 安装指南操作。
[!NOTE] 作为快捷方式,运行
make install来安装开发所需的库(详见下文说明)。之后,如果一切配置正确,你就可以试用 Open-R1 模型了。
uv venv openr1 --python 3.11 && source openr1/bin/activate && uv pip install --upgrade pip
[!TIP] 对于 Hugging Face 集群用户,请将
export UV_LINK_MODE=copy添加到你的.bashrc中,以屏蔽来自uv的缓存警告
接下来,安装 vLLM 和 FlashAttention:
uv pip install vllm==0.8.5.post1
uv pip install setuptools && uv pip install flash-attn --no-build-isolation
这也会安装 PyTorch v2.6.0,并且 非常重要的是要使用这个版本,因为 vLLM 的二进制文件是针对它编译的。然后你可以通过 pip install -e .[LIST OF MODES] 为你的特定使用场景安装其余的依赖项。对于大多数贡献者,我们推荐:
GIT_LFS_SKIP_SMUDGE=1 uv pip install -e ".[dev]"
接下来,按照如下方式登录你的 Hugging Face 和 Weights and Biases 账户:
huggingface-cli login
wandb login
最后,检查你的系统是否安装了 Git LFS,以便你能够向 Hugging Face Hub 加载和推送模型/数据集:
git-lfs --version
如果尚未安装,请运行:
sudo apt-get install git-lfs
训练模型
[!NOTE] 以下训练命令针对配备 8 x H100(80GB)的节点进行配置。对于不同的硬件和拓扑结构,你可能需要调整 batch size 和梯度累积步数。
我们支持使用 DDP 或 DeepSpeed(ZeRO-2 和 ZeRO-3)训练模型。例如,要在从 DeepSeek-R1 蒸馏得到、带有推理轨迹的数据集(如 open-r1/Mixture-of-Thoughts)上执行 SFT,请运行:
# Train via command line
accelerate launch --config_file=recipes/accelerate_configs/zero3.yaml src/open_r1/sft.py \
--model_name_or_path open-r1/Qwen2.5-Math-7B-RoPE-300k \
--dataset_name open-r1/Mixture-of-Thoughts \
--dataset_config all \
--eos_token '<|im_end|>' \
--learning_rate 4.0e-5 \
--num_train_epochs 5 \
--max_seq_length 32768 \
--per_device_train_batch_size 2 \
--gradient_checkpointing \
--bf16 \
--use_liger_kernel \
--output_dir data/OpenR1-Distill-7B
# Train via YAML config
accelerate launch --config_file recipes/accelerate_configs/zero3.yaml src/open_r1/sft.py \
--config recipes/OpenR1-Distill-7B/sft/config_distill.yaml
目前支持以下任务:
- 监督微调(SFT)
sft - 组相对策略优化(GRPO)
grpo
[!TIP] 如果你增加或减少 GPU 数量,我们建议同时相应调整每设备 batch size 或梯度累积步数,以保持全局 batch size 不变。
默认情况下,这些脚本会将每个模型推送到你的 Hugging Face Hub 用户名下,即 {username}/{model_name}-{task}。你可以通过在命令后附加参数来覆盖每个 YAML 配置中的参数,如下所示:
# Change the base model to a smaller variant
accelerate launch --config_file recipes/accelerate_configs/zero3.yaml src/open_r1/sft.py \
--config recipes/OpenR1-Distill-7B/sft/config_distill.yaml \
--model_name_or_path Qwen/Qwen3-0.6B-Base \
--hub_model_id OpenR1-Distill-0.6B \
--output_dir data/OpenR1-Distill-0.6B
如果你还想覆盖 Weights and Biases 的默认设置,可以按如下方式操作:
accelerate launch --config_file recipes/accelerate_configs/zero3.yaml src/open_r1/sft.py \
--config recipes/OpenR1-Distill-7B/sft/config_distill.yaml
--wandb_entity huggingface --wandb_project open-r1 --run_name Qwen2.5-1.5B-GRPO
🚨 警告 🚨
大多数基座模型(如 meta-llama/Llama-3.2-1B)没有聊天模板,因此我们在训练期间默认使用 ChatML。然而,对于 Qwen 基座模型(如 Qwen/Qwen2.5-1.5B),其分词器中已预定义了聊天模板,因此必须相应地设置 EOS token,例如:
# Align EOS token with chat template for Qwen base models
accelerate launch --config_file=recipes/accelerate_configs/zero3.yaml src/open_r1/sft.py \
--model_name_or_path Qwen/Qwen2.5-1.5B \
+ --eos_token '<|im_end|>'
--dataset_name open-r1/Mixture-of-Thoughts \
--dataset_config all \
--learning_rate 4.0e-5 \
--num_train_epochs 1 \
--max_seq_length 32768 \
--per_device_train_batch_size 16 \
--gradient_checkpointing \
--bf16 \
--use_liger_kernel \
--output_dir data/Qwen2.5-1.5B-Open-R1-Distill
如果你想使用自定义聊天模板(例如 Llama 或 Gemma),则必须提供聊天模板及对应的 EOS token:
# Align EOS token with custom chat template
accelerate launch --config_file=recipes/accelerate_configs/zero3.yaml src/open_r1/sft.py \
--model_name_or_path meta-llama/Llama-3.2-1B \
+ --chat_template "$(cat llama_chat_template.jinja)" \
+ --eos_token '<|eot_id|>' \
--dataset_name open-r1/Mixture-of-Thoughts \
--dataset_config all \
--learning_rate 4.0e-5 \
--num_train_epochs 1 \
--max_seq_length 32768 \
--per_device_train_batch_size 16 \
--gradient_checkpointing \
--bf16 \
--use_liger_kernel \
--output_dir data/Llama-3.2-1B-Open-R1-Distill
SFT 知识蒸馏
我们提供了一个方案,可以从相同的基座模型出发,复现 deepseek-ai/DeepSeek-R1-Distill-Qwen-7B 的推理能力。为此,请运行:
ACCELERATE_LOG_LEVEL=info accelerate launch --config_file recipes/accelerate_configs/zero3.yaml \
src/open_r1/sft.py \
--config recipes/OpenR1-Distill-7B/sft/config_distill.yaml
结果将得到一个类似于 open-r1/OpenR1-Distill-7B 的模型,其下游性能如下:
| 模型 | AIME 2024 | MATH-500 | GPQA Diamond | LiveCodeBench v5 |
|---|---|---|---|---|
| OpenR1-Distill-7B | 52.7 | 89.0 | 52.8 | 39.4 |
| DeepSeek-R1-Distill-Qwen-7B | 51.3 | 93.5 | 52.4 | 37.4 |
你可以调整 YAML 配置,以便在其他基础模型或数据集上进行训练。
GRPO
我们使用 TRL 的 vLLM backend 将训练扩展到跨多个节点的大模型。对于在 8 块 GPU 上进行小模型的单节点训练,请使用 vllm_mode="colocate" 在与训练脚本相同的进程中运行 vLLM:
ACCELERATE_LOG_LEVEL=info \
accelerate launch --config_file recipes/accelerate_configs/zero3.yaml \
src/open_r1/grpo.py --config recipes/DeepSeek-R1-Distill-Qwen-1.5B/grpo/config_demo.yaml \
--vllm_mode colocate
[!WARNING] 蒸馏版 DeepSeek 模型所使用的聊天模板会省略
<think>和</think>标签内推理块的内容。同时它还会用<think>预填充助手回复,这会干扰格式奖励函数。为处理这个问题,必须像 recipes/DeepSeek-R1-Distill-Qwen-1.5B/grpo/config_demo.yaml 中的做法那样覆盖聊天模板。
对于在 N+1 个节点上进行多节点训练(1 个节点运行 vLLM 服务器,N 个节点运行训练),我们提供了一个示例 Slurm 脚本。例如,要在 1+1 个节点上以数据并行方式运行上述示例,请执行:
sbatch --nodes=2 slurm/train.slurm --model Qwen2.5-1.5B-Instruct --task grpo --config demo --accelerator zero2 --dp 8 --tp 1
更多细节请参阅 在 Slurm 集群上启动任务 章节。
GRPO 数据集过滤
我们支持通过在可验证任务上生成并计算通过率来过滤数据集,详见这份 README
👨💻 使用代码解释器进行训练
我们提供了一个 code 奖励函数,用于执行策略在训练期间生成的代码。目前,该奖励函数面向 Codeforces 这类编程竞赛,其解法会针对一组测试用例执行,并将整体成功率作为最终奖励返回。为确保安全执行,我们支持多种沙箱提供方:
要使用代码奖励函数,首先安装必要的依赖:
uv pip install -e '.[code]'
E2B Provider
要使用 E2B 沙箱,请创建一个 .env 文件并添加你的 E2B API token:
E2B_API_KEY="e2b_xxx"
Morph Provider
要使用 Morph,首先安装 morphcloud 包:
pip install morphcloud
然后将你的 Morph API token 添加到 .env 文件中:
MORPH_API_KEY="YOUR_MORPH_API_KEY"
要指定使用哪个 provider,请在你的配置中添加 provider_type 参数:
# For E2B
provider_type: e2b
# For Morph
provider_type: morph
数据集要求
确保你的数据集包含一个具有以下模式的 verification_info 列(采用自 PrimeIntellect 出色的可验证问题 datasets):
{
"language": "python", # Morph supports more languages including C++, Java, etc.
"test_cases": [
{
"input": "4\n4\n0001\n1000\n0011\n0111\n3\n010\n101\n0\n2\n00000\n00001\n4\n01\n001\n0001\n00001\n",
"output": "1\n3 \n-1\n0\n\n2\n1 2 \n",
"type": "stdin_stdout",
}
],
}
例如,要在 Python 问题上训练一个小型模型,先启动 vLLM 服务器:
CUDA_VISIBLE_DEVICES=0 trl vllm-serve --model Qwen/Qwen2.5-1.5B-Instruct
然后使用以下命令运行训练:
CUDA_VISIBLE_DEVICES=1,2,3,4,5,6,7 ACCELERATE_LOG_LEVEL=info \
accelerate launch --config_file recipes/accelerate_configs/zero2.yaml --num_processes=7 \
src/open_r1/grpo.py --config recipes/Qwen2.5-1.5B-Instruct/grpo/config_demo_code.yaml
使用路由服务
当在沙箱服务上执行过多脚本时,可能会触发速率限制。针对这两个提供商,我们提供了可以在 CPU 节点上启动的路由脚本:
对于 E2B:
sbatch slurm/e2b_router.slurm
对于 Morph:
sbatch slurm/morph_router.slurm
然后在你的训练 YAML 配置中添加路由 URL:
# For E2B
e2b_router_url: 1.2.3.4:8000
# For Morph
morph_router_url: 1.2.3.4:8000
端口应与启动路由时使用的端口一致。所有训练任务可以共享同一个路由 IP,这将确保并行执行得到妥善管理。
竞技编程问题:IOI 与 CodeForces
我们提供了 ioi_code_reward 和 cf_code_reward 奖励函数,分别用于执行来自 IOI 和 CodeForces 的问题。你可以使用 piston 或 Morph(目前仅支持 IOI)作为执行提供商。
Piston
要使用 Piston:
- 让 piston worker 运行起来,参见 slurm/piston/README.md
- 将你的环境变量
PISTON_ENDPOINTS设置为slurm或 piston worker 端点列表
对于 IOI:
- 在你的配置中,使用
ioi_provider: "piston"
对于 CodeForces:
- 下载生成的(困难)测试用例:
# change PATH_TO_SAVE_TESTCASES. Increase --max-workers according to your machine's capacity
huggingface-cli download open-r1/codeforces --repo-type=dataset --include='generated_tests/*.parquet' --max-workers=8 --local-dir PATH_TO_SAVE_TESTCASES
- 将路径保存到 .env 中:
CF_TESTS_FOLDER=PATH_TO_SAVE_TESTCASES
Morph
Morph 是一个基于云的解决方案,提供用于运行代码的沙箱环境。使用方法如下:
- 安装 Morph 客户端:
pip install morphcloud - 将你的 Morph API key 添加到
.env文件中:MORPH_API_KEY="your_key_here" - 在你的配置中,使用
ioi_provider: "morph"
示例配方
对于 IOI:
请参阅 示例配方 了解如何使用 IOI 奖励函数:
ACCELERATE_LOG_LEVEL=info accelerate launch --config_file recipes/accelerate_configs/zero2.yaml \
--num_processes=7 src/open_r1/grpo.py \
--config recipes/Qwen2.5-1.5B-Instruct/grpo/config_demo_code_ioi.yaml
对于 CodeForces:
sbatch --job-name=cf-grpo --nodes=2 slurm/train.slurm --model Qwen2.5-Coder-7B-Instruct --task grpo --config codeforces --accelerator zero3 --dp 8 --tp 1
在 Slurm 集群上启动任务
如果你有 Slurm 集群的访问权限,我们提供了一个 slurm/train.slurm 脚本,可以自动为你排队训练任务。使用方法如下:
sbatch --job-name=open_r1 --nodes=1 slurm/train.slurm --model {model_name} --task {task} --config {config_suffix} --accelerator {accelerator}
这里 {model_name} 和 {task} 如上文所定义,而 {config_suffix} 指具体的配置文件,{accelerator} 指 recipes/accelerate_configs 中 🤗 Accelerate 配置的选择。如果你想覆盖默认配置参数,可以通过追加一个空格分隔的字符串来提供,例如 '--arg1=value1 --arg2=value2'。下面是在 1 个节点的 8 张 GPU 上运行 SFT 的具体示例:
sbatch --job-name=open_r1 --nodes=1 slurm/train.slurm --model OpenR1-Distill-7B --task sft --config distill --accelerator zero3
你可以通过增加 --nodes 标志来扩展节点数量。
对于 GRPO,我们使用 1 个节点运行 vLLM 服务器,用 N 个节点进行训练。例如,要在 1+1 个节点上以数据与张量混合并行的方式运行 GRPO,请执行:
sbatch --job-name=open_r1 --nodes=2 slurm/train.slurm --model Qwen2.5-1.5B-Instruct --task grpo --config demo --accelerator zero2 --dp 4 --tp 2
[!NOTE]
slurm/train.slurm中的配置是针对 Hugging Face 计算集群优化的,可能需要调整才能适配你自己的计算节点。
自定义数据集混合比例
要将多个数据集组合成单一的训练混合数据,你可以在 YAML 配置文件中指定 dataset_mixture 参数。下面是一个操作模板:
dataset_mixture:
datasets: # List of datasets to include in the mixture
- id: dataset_1 # Hub dataset ID
config: config_name_1 # Name of the dataset config
split: split_1 # Split to use from the dataset
columns: # Columns to keep
- column_1
- column_2
weight: 0.25 # Fraction of dataset to use
- id: dataset_2
config: config_name_2
split: split_2
columns:
- column_1
- column_2
weight: 0.5
seed: 42 # Seed for shuffling the combined dataset
test_split_size: 0.1 # Fraction of mixture to use for a test split
评估模型
我们使用 lighteval 来评估模型。对于能放进单张 GPU 的模型,运行:
export VLLM_WORKER_MULTIPROC_METHOD=spawn # Required for vLLM
MODEL=deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B
MODEL_ARGS="model_name=$MODEL,dtype=bfloat16,max_model_length=32768,gpu_memory_utilization=0.8,generation_parameters={max_new_tokens:32768,temperature:0.6,top_p:0.95}"
OUTPUT_DIR=data/evals/$MODEL
# AIME 2024
TASK=aime24
lighteval vllm $MODEL_ARGS "lighteval|$TASK|0|0" \
--use-chat-template \
--output-dir $OUTPUT_DIR
# MATH-500
TASK=math_500
lighteval vllm $MODEL_ARGS "lighteval|$TASK|0|0" \
--use-chat-template \
--output-dir $OUTPUT_DIR
# GPQA Diamond
TASK=gpqa:diamond
lighteval vllm $MODEL_ARGS "lighteval|$TASK|0|0" \
--use-chat-template \
--output-dir $OUTPUT_DIR
# LiveCodeBench
lighteval vllm $MODEL_ARGS "extended|lcb:codegeneration|0|0" \
--use-chat-template \
--output-dir $OUTPUT_DIR
要跨多个 GPU 提升吞吐量,请按如下方式使用 数据并行:
NUM_GPUS=8
MODEL=deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B
MODEL_ARGS="model_name=$MODEL,dtype=bfloat16,data_parallel_size=$NUM_GPUS,max_model_length=32768,gpu_memory_utilization=0.8,generation_parameters={max_new_tokens:32768,temperature:0.6,top_p:0.95}"
TASK=aime24
OUTPUT_DIR=data/evals/$MODEL
lighteval vllm $MODEL_ARGS "lighteval|$TASK|0|0" \
--use-chat-template \
--output-dir $OUTPUT_DIR
对于需要跨 GPU 分片的大型模型,请使用 张量并行 并运行:
NUM_GPUS=8
MODEL=deepseek-ai/DeepSeek-R1-Distill-Qwen-32B
MODEL_ARGS="model_name=$MODEL,dtype=bfloat16,tensor_parallel_size=$NUM_GPUS,max_model_length=32768,gpu_memory_utilization=0.8,generation_parameters={max_new_tokens:32768,temperature:0.6,top_p:0.95}"
TASK=aime24
OUTPUT_DIR=data/evals/$MODEL
export VLLM_WORKER_MULTIPROC_METHOD=spawn
lighteval vllm $MODEL_ARGS "lighteval|$TASK|0|0" \
--use-chat-template \
--output-dir $OUTPUT_DIR
你还可以使用 make evaluate 启动评估,指定模型、任务,以及可选的并行技术和 GPU 数量。
在单个 GPU 上评估:
make evaluate MODEL=deepseek-ai/DeepSeek-R1-Distill-Qwen-32B TASK=aime24
使用数据并行:
make evaluate MODEL=deepseek-ai/DeepSeek-R1-Distill-Qwen-32B TASK=aime24 PARALLEL=data NUM_GPUS=8
使用张量并行:
make evaluate MODEL=deepseek-ai/DeepSeek-R1-Distill-Qwen-32B TASK=aime24 PARALLEL=tensor NUM_GPUS=8
复现 DeepSeek 的评估结果
DeepSeek-R1 论文使用每个查询采样 4-64 个回答来估计 pass@1 准确率,但并未说明每个基准测试所使用的具体回答数量。在下表中,我们按如下每个查询的回答数量来估计 pass@1 准确率:
| 基准测试 | 每个查询的回答数量 |
|---|---|
| AIME 2024 | 64 |
| MATH-500 | 4 |
| GPQA Diamond | 8 |
| LiveCodeBench | 16 |
请注意,对于 AIME24 这类评测基准,采样大量响应非常重要,因为其中只有 30 道题目,这可能在重复运行之间引入较大的方差。每个提示词采样多少次响应的选择,很可能是我们的评测结果与 DeepSeek 报告结果之间存在细微差异的原因。
AIME 2024
我们能够在约 1-3 个标准差范围内复现 DeepSeek 在 AIME 2024 基准上报告的结果:
| 模型 | AIME 2024 (🤗 LightEval) | AIME 2024 (DeepSeek 报告值) |
|---|---|---|
| DeepSeek-R1-Distill-Qwen-1.5B | 30.7 | 28.9 |
| DeepSeek-R1-Distill-Qwen-7B | 50.8 | 55.5 |
| DeepSeek-R1-Distill-Qwen-14B | 65.9 | 69.7 |
| DeepSeek-R1-Distill-Qwen-32B | 69.7 | 72.6 |
| DeepSeek-R1-Distill-Llama-8B | 43.9 | 41.7 |
| DeepSeek-R1-Distill-Llama-70B | 63.0 | 70.0 |
要复现这些结果,请使用以下命令:
NUM_GPUS=1 # Set to 8 for 32B and 70B models
MODEL=deepseek-ai/{model_name}
MODEL_ARGS="model_name=$MODEL,dtype=bfloat16,max_model_length=32768,gpu_memory_utilization=0.8,data_parallel_size=$NUM_GPUS,generation_parameters={max_new_tokens:32768,temperature:0.6,top_p:0.95}"
OUTPUT_DIR=data/evals/$MODEL
lighteval vllm $MODEL_ARGS "lighteval|aime24|0|0" \
--use-chat-template \
--output-dir $OUTPUT_DIR
另外,你也可以按如下方式启动 Slurm 作业:
python scripts/run_benchmarks.py --model-id {model_id} --benchmarks aime24
MATH-500
我们在 MATH-500 基准上复现了 DeepSeek 报告的结果,误差在约 1-3 个标准差以内:
| 模型 | MATH-500(🤗 LightEval) | MATH-500(DeepSeek 报告值) |
|---|---|---|
| DeepSeek-R1-Distill-Qwen-1.5B | 83.1 | 83.9 |
| DeepSeek-R1-Distill-Qwen-7B | 94.5 | 92.8 |
| DeepSeek-R1-Distill-Qwen-14B | 94.1 | 93.9 |
| DeepSeek-R1-Distill-Qwen-32B | 95.6 | 94.3 |
| DeepSeek-R1-Distill-Llama-8B | 88.6 | 89.1 |
| DeepSeek-R1-Distill-Llama-70B | 95.1 | 94.5 |
要复现这些结果,请使用以下命令:
export VLLM_WORKER_MULTIPROC_METHOD=spawn
NUM_GPUS=1 # Set to 8 for 32B and 70B models
MODEL=deepseek-ai/{model_name}
MODEL_ARGS="model_name=$MODEL,dtype=bfloat16,max_model_length=32768,gpu_memory_utilization=0.8,data_parallel_size=$NUM_GPUS,generation_parameters={max_new_tokens:32768,temperature:0.6,top_p:0.95}"
OUTPUT_DIR=data/evals/$MODEL
lighteval vllm $MODEL_ARGS "lighteval|math_500|0|0" \
--use-chat-template \
--output-dir $OUTPUT_DIR
或者,你也可以按如下方式启动 Slurm 作业:
python scripts/run_benchmarks.py --model-id {model_id} --benchmarks math_500
GPQA Diamond
我们在 GPQA Diamond 基准上复现了 DeepSeek 报告的结果,误差在约 1-3 个标准差之内:
| 模型 | GPQA Diamond(🤗 LightEval) | GPQA Diamond(DeepSeek 报告值) |
|---|---|---|
| DeepSeek-R1-Distill-Qwen-1.5B | 35.8 | 33.8 |
| DeepSeek-R1-Distill-Qwen-7B | 50.5 | 49.1 |
| DeepSeek-R1-Distill-Qwen-14B | 61.5 | 59.1 |
| DeepSeek-R1-Distill-Qwen-32B | 63.1 | 62.1 |
| DeepSeek-R1-Distill-Llama-8B | 46.7 | 49.0 |
| DeepSeek-R1-Distill-Llama-70B | 67.4 | 65.2 |
要复现这些结果,请使用以下命令:
export VLLM_WORKER_MULTIPROC_METHOD=spawn
NUM_GPUS=1 # Set to 8 for 32B and 70B models
MODEL=deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B
MODEL_ARGS="model_name=$MODEL,dtype=bfloat16,max_model_length=32768,gpu_memory_utilization=0.8,generation_parameters={max_new_tokens:32768,temperature:0.6,top_p:0.95}"
OUTPUT_DIR=data/evals/$MODEL
lighteval vllm $MODEL_ARGS "lighteval|gpqa:diamond|0|0" \
--use-chat-template \
--output-dir $OUTPUT_DIR
python scripts/run_benchmarks.py --model-id {model_id} --benchmarks gpqa
LiveCodeBench
在 LiveCodeBench 代码生成基准上,我们复现出的 DeepSeek 报告结果误差在约 1-3 个标准差以内:
| 模型 | LiveCodeBench(🤗 LightEval) | LiveCodeBench(DeepSeek 报告值) |
|---|---|---|
| DeepSeek-R1-Distill-Qwen-1.5B | 16.1 | 16.9 |
| DeepSeek-R1-Distill-Qwen-7B | 37.4 | 37.6 |
| DeepSeek-R1-Distill-Qwen-14B | 51.3 | 53.1 |
| DeepSeek-R1-Distill-Qwen-32B | 56.0 | 57.2 |
| DeepSeek-R1-Distill-Llama-8B | 37.4 | 39.6 |
| DeepSeek-R1-Distill-Llama-70B | 55.9 | 57.5 |
要复现这些结果,请使用以下命令:
NUM_GPUS=1 # Set to 8 for 32B and 70B models, or data_parallel_size=8 with the smaller models for speed
MODEL=deepseek-ai/{model_name}
MODEL_ARGS="model_name=$MODEL,dtype=bfloat16,max_model_length=32768,gpu_memory_utilization=0.8,data_parallel_size=$NUM_GPUS,generation_parameters={max_new_tokens:32768,temperature:0.6,top_p:0.95}"
OUTPUT_DIR=data/evals/$MODEL
lighteval vllm $MODEL_ARGS "extended|lcb:codegeneration|0|0" \
--use-chat-template \
--output-dir $OUTPUT_DIR
python scripts/run_benchmarks.py --model-id {model_id} --benchmarks lcb
数据生成
从一个小型的蒸馏 R1 模型生成数据
以下示例可在单张 H100 上运行。首先安装以下依赖:
uv pip install "distilabel[vllm]>=1.5.2"
现在,将以下代码片段保存到一个名为 pipeline.py 的文件中,并用 python pipeline.py 运行它。它会为 10 个示例中的每一个生成 4 个输出(将仓库的用户名改为你的组织/用户名):
from datasets import load_dataset
from distilabel.models import vLLM
from distilabel.pipeline import Pipeline
from distilabel.steps.tasks import TextGeneration
prompt_template = """\
You will be given a problem. Please reason step by step, and put your final answer within \boxed{}:
{{ instruction }}"""
dataset = load_dataset("AI-MO/NuminaMath-TIR", split="train").select(range(10))
model_id = "deepseek-ai/DeepSeek-R1-Distill-Qwen-7B" # Exchange with another smol distilled r1
with Pipeline(
name="distill-qwen-7b-r1",
description="A pipeline to generate data from a distilled r1 model",
) as pipeline:
llm = vLLM(
model=model_id,
tokenizer=model_id,
extra_kwargs={
"tensor_parallel_size": 1,
"max_model_len": 8192,
},
generation_kwargs={
"temperature": 0.6,
"max_new_tokens": 8192,
},
)
prompt_column = "problem"
text_generation = TextGeneration(
llm=llm,
template=prompt_template,
num_generations=4,
input_mappings={"instruction": prompt_column} if prompt_column is not None else {}
)
if __name__ == "__main__":
distiset = pipeline.run(dataset=dataset)
distiset.push_to_hub(repo_id="username/numina-deepseek-r1-qwen-7b")
看看 HuggingFaceH4/numina-deepseek-r1-qwen-7b 处的示例数据集。
从 DeepSeek-R1 生成数据
为了运行更大的 DeepSeek-R1,我们使用了 2 个节点,每个节点配备 8×H100 GPU,使用本仓库中位于 slurm/generate.slurm 的 slurm 文件。首先,安装依赖项:
(目前我们需要安装 修复了 R1 cuda 图捕获问题 的 vllm 开发版 wheel 包)
pip install https://wheels.vllm.ai/221d388cc5a836fa189305785ed7e887cea8b510/vllm-1.0.0.dev-cp38-abi3-manylinux1_x86_64.whl --extra-index-url https://download.pytorch.org/whl/cu121
uv pip install "distilabel[vllm,ray,openai]>=1.5.2"
然后运行以下命令:
sbatch slurm/generate.slurm \
--hf-dataset AI-MO/NuminaMath-TIR \
--temperature 0.6 \
--prompt-column problem \
--model deepseek-ai/DeepSeek-R1 \
--hf-output-dataset username/r1-dataset
[!NOTE]
在任务运行期间,你可以通过集群登录节点设置一个 SSH 隧道,在运行ssh -L 8265:ray_ip_head_node:8265 <login_node>的电脑上访问 Ray 仪表板,然后浏览http://localhost:8265
数据去污染
按照 s1: Simple test-time scaling 的做法,可以使用位于 scripts/decontaminate.py 的脚本对数据进行去污染,该脚本使用 8-gram 对数据集进行去污染并去重。示例运行:
python scripts/decontaminate.py \
--dataset "open-r1/verifiable-coding-problems-python" \
--problem_column problem \
--cleanup
它会对基准测试数据集进行去污染处理,并在之后移除被污染的样本。如果没有提供参数 --new_dataset_name,则会复用同一数据集,并附加一个 _decontaminated。它针对提示词运行检查,对于该数据集来说提示词是 problem 这一列,但也可以提供不同的列。
脚本的参数:
usage: decontaminate.py [-h] --dataset DATASET [--split SPLIT] [--ngram_size NGRAM_SIZE] [--problem_column PROBLEM_COLUMN] [--cleanup] [--new_dataset_name NEW_DATASET_NAME]
options:
-h, --help show this help message and exit
--dataset DATASET Name of the dataset to check for contamination.
--split SPLIT Split to check for contamination, defaults to `train`.
--ngram_size NGRAM_SIZE
Size of n-grams to build, defaults to 8.
--problem_column PROBLEM_COLUMN
Name of the column containing the problem (prompt).
--cleanup Whether to remove the contaminated rows before pushing the dataset.
--new_dataset_name NEW_DATASET_NAME
New name for the dataset. If not provided, will reuse the name and add a `_decontaminated` to the name.
贡献
欢迎贡献。请参考 https://github.com/huggingface/open-r1/issues/23。
致谢
本项目凝聚了开放 AI 社区中众多团体和个人的共同努力。我们尤其感谢 vLLM 和 SGLang 团队打造了高性能工具来扩展 GRPO 的 rollout。我们也感谢 OpenThoughts、Prime Intellect 和 General Reasoning 的团队创建并分享高质量的推理数据集。
引用
如果您认为本项目对您的工作有用,请考虑按如下方式引用:
@misc{openr1,
title = {Open R1: A fully open reproduction of DeepSeek-R1},
url = {https://github.com/huggingface/open-r1},
author = {{Hugging Face}},
month = {January},
year = {2025}
}
来源:Hacker News 热门(buzzing.cc 中文翻译) · github.com