前置知识: 本文假设读者具备深度学习基础(理解神经网络,反向传播),不需要 RL 背景。我会从最基础的概念开始,逐步深入到框架的技术细节和工业实践。


Agent RL 框架深度对比:从算法原理到工程实践

引言:从 SFT 到 RL,一个根本性的转变

在深入框架之前,我们需要先理解一个根本问题:为什么预训练和监督微调(SFT)已经不够用了?

预训练:学会「说什么」

预训练的核心目标是 next token prediction——给定前文,预测下一个词。这个过程让模型学会了语言的知识、语法、世界知识——本质上是在学习「说什么」。

SFT:学会「怎么说」

SFT(Supervised Fine-Tuning)用人类标注的数据,教会模型「怎么说」——遵循指令、生成合理的回答。但这带来了两个根本性的局限:

  1. 数据效率低: 人类标注成本极高,模型只能学到「最好的回答」,无法探索大量可能的回答空间
  2. 能力天花板: SFT 本质上是「模仿」,模型无法超越标注者的水平

RL:学会「什么是好」

RL(Reinforcement Learning)的核心思想是:让模型自己探索,通过奖励信号学习什么是「好」的回答

这带来质的飞跃:

  • 数据效率: 同一个 prompt 可以生成成千上万条 response,模型从中学习
  • 超越模仿: 不再受限于人类标注,模型可以发现人类没想过的回答方式
  • 涌现能力: DeepSeek-R1、OpenAI o1 等推理能力的涌现,都离不开 RL

关键洞察: RL 的本质不是「执行指令」,而是「定义目标,让模型自己找到最优路径」。


第一部分:RLHF 算法与流程基础

1.1 强化学习基本概念

让我们用「教狗狗握手」来理解 RL:

RL 概念比喻LLM 中的含义
Agent狗狗LLM 本身
Action伸爪子生成一个 token
Reward零食 (+1) 或没有 (0)奖励模型评分 / 规则判断
Policy狗狗的「决策脑」LLM 的生成逻辑

1.2 完整的 RLHF 训练流程

┌─────────────────────────────────────────────────────────────────────────┐
│                        RLHF 完整训练流程                                    │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   ┌─────────┐     ┌─────────┐     ┌─────────┐     ┌─────────┐        │
│   │ Prompt  │ ──→ │ Rollout │ ──→ │  Reward│ ──→ │ Update  │        │
│   │  准备   │     │  生成   │     │  计算   │     │  策略   │        │
│   └─────────┘     └─────────┘     └─────────┘     └─────────┘        │
│                                                                         │
│   阶段 1          阶段 2           阶段 3          阶段 4          │
│   准备问题      LLM 生成回答    评估回答质量    更新模型参数          │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

每个阶段的详细说明

阶段输入输出耗时占比
1. Prompt 准备原始问题池待生成的问题~5%
2. Rollout问题生成的回答~70-90%
3. Reward回答奖励分数~10-20%
4. Update奖励模型参数更新~5-10%

什么是 Rollout?

Rollout 是 RL 术语,意思是「推演」——让 Agent 与环境交互,收集数据。

在 LLM 场景中:

# Rollout = 让 LLM 生成回答
prompt = "如何实现快速排序?"

# 对同一个问题,生成多个不同的回答
responses = [
    "快速排序是一种分治算法...",
    "我来介绍快速排序的实现...",
    "快速排序的核心思想是..."
]

为什么要生成多个回答?

这是 RL 的核心思想:通过比较来学习

问题: "2 + 3 = ?"

回答 A: "2 + 3 = 5"     → 奖励: 1.0 (正确)
回答 B: "2 + 3 = 6"     → 奖励: 0.0 (错误)
回答 C: "2 + 3 等于 5"  → 奖励: 1.0 (正确)

→ 模型学会: 生成类似 A、C 的回答,避开 B

奖励(Reward)从哪来?

奖励类型来源例子
规则奖励代码执行、格式验证数学答案正确=1,错误=0
Reward Model训练好的神经网络判断回答质量
人类反馈人工标注成本高,很少用

1.3 PPO——RLHF 的开山之作

PPO(Proximal Policy Optimization)是 RLHF 的经典算法,也是 ChatGPT 背后的核心技术之一。

为什么需要 PPO?

直接用标准 RL 更新策略会有两个致命问题:

  1. 策略崩溃(Policy Collapse): 模型完全放飞自我,生成语法错误、逻辑混乱的文本
  2. 训练不稳定: 梯度更新幅度过大,模型性能急剧下降

PPO 的核心思想:保守更新

PPO 通过一个简单的 Clip 机制,确保策略不会发生剧烈变化:

# PPO 目标函数(简化)
L(θ) = E[min(r(θ) * A, clip(r(θ), 1-ε, 1+ε) * A)]

# r(θ) = π_θ(a|s) / π_OLD(a|s)  # 新旧策略的概率比
# A = Advantage                                 # 优势函数
# clip() 限制 r(θ) 在 [1-ε, 1+ε] 范围内       # ε 通常取 0.2

这就是 PPO 中 「Proximal(近端)」 的含义——步子不要迈太大。

PPO 在 LLM 中的架构

PPO 需要 四个模型

模型作用比喻
Actor生成 response,学习做题的学生
Critic评估「这个回答大概能得多少分」评分老师
Reward Model判断「这个回答好不好」改卷老师
Reference保持「不偏离太远」锚点

问题: 对于百亿参数的 LLM,4 份模型权重意味着巨大的显存开销。

1.4 GRPO——工业界的主流选择

GRPO(Group Relative Policy Optimization)是 DeepSeek 在 2024 年提出的算法,迅速成为工业界主流。

GRPO 的核心 insight

PPO 需要 4 个模型的根本原因是:需要估计 value function(如果没有采取这个动作,会获得多少奖励)

DeepSeek 发现:对于 LLM,其实可以不用显式估计 value function!

GRPO 的做法

# 1. 对每个 prompt,采样 G 个 response
responses = [policy.generate(prompt) for _ in range(G)]

# 2. 计算每个 response 的奖励
rewards = [reward_model(r) for r in responses]

# 3. 用 group 内相对排名计算 Advantage
mean_r = sum(rewards) / len(rewards)
std_r = (sum((r - mean_r)**2 for r in rewards) / len(rewards)) ** 0.5
advantages = [(r - mean_r) / std_r for r in rewards]

# 4. 直接更新策略
policy_update(advantages)

GRPO 的优势

对比项PPOGRPO
模型数量4 个2 个
Value Function需要不需要
显存开销降低 50%+
对稀疏奖励一般更友好

GRPO 为什么会 work?

核心洞察: RL 的本质是 利用「相对比较」而非「绝对分数」

  • PPO 问:「这个回答得 85 分,好还是不好?」
  • GRPO 问:「这个回答在 100 个回答里排第 10,好还是不好?」

答案是:相对比较更稳定。奖励模型的分数可能有偏,但 group 内的相对排序更 robust。

1.5 DAPO——字节的最新突破

DAPO 是字节跳动在 2025 年初开源的算法,是 GRPO 的增强版:

改进说明效果
Clip-Higher改变 Clip 方向允许策略在「好」的方向上多学一点
Token-level Loss从 sequence 细化到 token更精细的梯度
Dynamic Sampling过滤明显错误的样本提高数据效率

关键结果: DAPO 在 AIME 2024 数学竞赛上取得了 50 分(Qwen2.5-32B),超越同期 DeepSeek-R1-Zero。


第二部分:如果让你实现一个最简单的框架

现在,让我们从第一性原理出发,思考一个问题:最简陋的 RL 训练框架应该怎么实现?

这个思考过程会帮助我们理解:为什么需要专门的框架?这些框架在解决什么问题?

2.1 最简单的实现:顺序执行

def simplest_rl_framework():
    """最 naive 的实现:每个阶段顺序执行"""
    
    while training:
        # 阶段 1: 准备问题
        prompts = get_prompts(batch_size=16)
        
        # 阶段 2: 生成回答 (GPU 跑推理)
        responses = []
        for prompt in prompts:
            response = actor.generate(prompt)
            responses.append(response)
        
        # 阶段 3: 计算奖励 (CPU 或 GPU)
        rewards = []
        for response in responses:
            reward = reward_fn(response)
            rewards.append(reward)
        
        # 阶段 4: 更新模型 (GPU 跑训练)
        actor.update(responses, rewards)

这段代码有什么问题?

问题后果
生成是串行的GPU 大部分时间在等待
训练要等生成完成GPU 利用率极低
没有并行16 个 prompt 串行生成

2.2 问题分析:生成是瓶颈

时间线(顺序执行):

GPU 利用率: ████░░░░░░░░░ 40%

[生成...] [生成...] [生成...] [生成...] [奖励...] [训练...]
   ↑ GPU 跑      ↑ GPU 等待  ↑ GPU 等待

关键洞察: LLM 生成一个 response 可能需要几秒钟,而 GPU 做一次前向传播只需要几毫秒。生成是绝对的瓶颈

2.3 改进一:批处理

def with_batching():
    """改进 1: 批量生成"""
    
    prompts = get_prompts(batch_size=64)
    
    # 批量生成 - GPU 并行处理
    responses = actor.generate_batch(prompts)
    
    # 批量计算奖励
    rewards = reward_fn_batch(responses)
    
    # 批量更新
    actor.update_batch(responses, rewards)

效果: 批量生成可以提高 GPU 利用率,但还不够。

2.4 改进二:流水线化

def with_pipelining():
    """改进 2: 流水线化 - 多个 batch 并行"""
    
    # 启动三个并行的 worker
    prompt_worker = ThreadPool(get_prompts)
    rollout_worker = ThreadPool(actor.generate)
    reward_worker = ThreadPool(reward_fn)
    update_worker = ThreadPool(actor.update)
    
    # 流水线执行
    queue1, queue2, queue3, queue4 = Queue(), Queue(), Queue(), Queue()
    
    # Worker 1: 准备问题 -> queue1
    # Worker 2: queue1 -> 生成 -> queue2
    # Worker 3: queue2 -> 奖励 -> queue3
    # Worker 4: queue3 -> 更新
    
    # 关键: 多个 batch 同时在不同阶段

效果: 不同阶段可以并行,GPU 利用率提高。

2.5 改进三:分布式训练

对于超大模型,需要多 GPU:

def with_distributed():
    """改进 3: 分布式训练"""
    
    # 模型并行: 不同的 GPU 跑模型的不同部分
    actor = FSDP(model, device_ids=[0,1,2,3])
    
    # 数据并行: 多个 GPU 跑同一个模型
    # 梯度聚合: all_reduce

2.6 还有什么挑战?

即使做了这些优化,还有更多问题:

挑战描述解决方案
显存不够4 个模型跑不动3D 并行、ZeRO、Offload
多节点多台机器如何协同Ray、PyTorch DDP
算法多样GRPO/PPO/DAPO 不同灵活的模块化设计
推理框架vLLM vs SGLang统一的推理接口

2.7 总结:框架要解决的核心问题

经过这个思考过程,我们可以总结出 LLM RL 框架要解决的三个核心问题

问题目标手段
吞吐量让 GPU 少等待批处理、流水线、异步
灵活性支持不同算法模块化、可插拔
扩展性多卡多节点能跑分布式、并行策略

第三部分:四大框架深度对比

这一部分基于对各框架源码和文档的深度调研,力求呈现每个框架的设计思路、实现原理和真实优缺点。

3.1 OpenRLHF——开源先驱

背景: 2024 年初开源,是最早将 Ray + vLLM 引入 RLHF 的开源框架之一

设计思路

OpenRLHF 的核心理念是 「Agent-Based Execution」——将所有 RLHF 训练流程统一为「Agent 执行」:

# OpenRLHF 的核心抽象
class AgentExecutorBase:
    def execute(self, tokens):
        # Token-in, Token-out
        # 统一处理单轮和多轮场景
        return trajectories

这个设计让 单轮 RLHF多轮 Agent 共享同一套代码。

架构实现

┌─────────────────────────────────────────────────────────────┐
│                  OpenRLHF Architecture                      │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────────────────────────────────────────────────┐ │
│   │              Ray Scheduler (分布式调度)               │ │
│   └──────────────────────┬──────────────────────────────┘ │
│                          │                                  │
│   ┌──────────┬──────────┼──────────┬──────────┐        │
│   ▼          ▼          ▼          ▼          ▼        │
│   │ Actor  │ Ref    │ Reward │ Critic │ vLLM  │        │
│   │ (训练)  │ (参考)  │ (奖励)  │ (价值)  │ (推理)  │
│   └──────────┴──────────┴──────────┴──────────┘        │
│                                                             │
│   Backend: Ray + vLLM + DeepSpeed                        │
└─────────────────────────────────────────────────────────────┘

关键技术点:

  1. Ray 分布式调度

    • Actor、Ref、Reward、Critic 分布在不同 GPU
    • 支持 70B+ 参数模型
    • 自动化的资源分配
  2. vLLM 高效推理

    • RLHF 80% 时间花在生成
    • vLLM 的 Auto TP/PP 支持高吞吐生成
    • PagedAttention 减少显存碎片
  3. DeepSpeed 训练

    • ZeRO-3 显存优化
    • DeepCompile 加速
    • 原生支持 HuggingFace 模型

优缺点

优点缺点
✅ 简单易用,门槛低❌ 吞吐量不如 verl
✅ Agent 抽象优雅❌ 主要支持 PPO/GRPO
✅ 文档详尽❌ 大规模扩展一般
✅ 社区活跃 (9.1k stars)❌ 需要较多 GPU 才能高效

适用场景

  • 快速实验
  • 小规模训练 (8-16 GPU)
  • 学习 RLHF 原理
  • 需要自定义 reward function

3.2 verl——工业级标准

背景: 字节跳动 Seed 团队开源,已在生产环境验证多年

设计思路

verl 的核心理念是 「HybridFlow」——灵活的数据流编排 + 高效的 3D 并行:

传统框架: 固定的数据流
verl:      可编程的数据流 (你定义怎么跑)

这让 verl 可以适配各种训练场景:从 GRPO 到 DAPO,从单轮对话到 Agent 训练。

架构实现

# verl 的核心抽象 - Hybrid Controller
class HybridController:
    def __init__(self):
        self.trainer = ...
        self.rollout = ...
        self.reward = ...
    
    # 你可以自定义数据流
    def forward(self, data):
        # 方式 1: PPO 风格
        responses = self.rollout.generate(data)
        rewards = self.reward.compute(responses)
        return self.trainer.ppo_update(responses, rewards)
        
        # 方式 2: GRPO 风格
        responses = self.rollout.generate_group(data)
        advantages = self.compute_grpo_advantage(responses)
        return self.trainer.grpo_update(advantages)

核心创新:

  1. 3D-HybridEngine

    模型切分维度:
    - 数据并行: 多个 prompt 同时处理
    - 流水线并行: 模型分 stages
    - 张量并行: 模型内部并行
    
    关键优化: 训练 ↔ 生成 阶段切换时,动态调整显存布局
  2. 模块化设计

    # 训练后端可选
    trainer = verl.trainer.FSDPTrainer()  # 或 MegatronTrainer
    
    # 推理后端可选
    rollout = verl.rollout.vLLMRollout()  # 或 SGLangRollout
  3. 丰富的算法支持

    • GRPO、DAPO、VAPO、PPO、PF-PPO
    • ReTool (代码 Agent)
    • VLA (视觉语言 Agent)

优缺点

优点缺点
✅ 工业级验证 (字节生产环境)❌ 复杂度高
✅ 吞吐量 SOTA❌ 文档偏向内部
✅ 算法最全 (DAPO/VAPO)❌ 门槛较高
✅ 支持超大规模 (DeepSeek-671B)

生产案例

  • Seed-Thinking-v1.5: AIME 2024 86.7 分
  • DAPO: AIME 2024 50 分
  • DeepSeek-R1: 部分训练使用 verl
  • Mind Lab: 1 万亿参数 MoE 模型训练

3.3 slime——智谱的选择

背景: 清华大学 THUDM(智谱 AI)开源,支撑 GLM 系列模型训练

设计思路

slime 的核心理念是 「SGLang-Native + 彻底解耦」

slime = SGLang (最快推理) + Megatron (高效训练) + Data Buffer (异步解耦)

与 verl 的「可配置」不同,slime 选择了 「解耦得彻底」——Training 和 Rollout 完全独立运行。

架构实现

# slime 的核心设计

# 1. Data Buffer - 异步数据传递
class DataBuffer:
    def __init__(self):
        self.prompt_queue = Queue()      # 待生成的问题
        self.response_queue = Queue()    # 生成好的回答
        self.reward_queue = Queue()       # 计算好的奖励
    
    async def put_prompt(self, prompt):
        await self.prompt_queue.put(prompt)
    
    async def get_response(self):
        return await self.response_queue.get()

# 2. Training - 独立进程
# 读取 response_queue,计算梯度,更新参数

# 3. Rollout - 独立进程 (SGLang)
# 读取 prompt_queue,生成 response,写入 response_queue

关键设计:

  1. SGLang 深度集成

    • 连续批处理 (Continuous Batching)
    • Prefix Caching
    • 最快的 LLM 推理框架之一
  2. 自定义数据生成接口

    # 用户可以定义任意的 rollout 策略
    class MyRollout:
        def generate(self, prompt):
            # 可以是多轮对话
            # 可以是工具调用
            # 可以是复杂环境交互
            return response
  3. Megatron 训练后端

    • 张量并行原生支持
    • 流水线并行优化

优缺点

优点缺点
✅ SGLang 推理极快❌ 生态较小
✅ 灵活的数据生成❌ 文档较少
✅ GLM 系列背书❌ 算法支持有限
✅ 解耦设计利于调试

生态项目

  • P1: 物理推理模型,完全 RL 训练
  • TritonForge: RL 训练 GPU kernel 生成
  • qqr (hilichurl): 阿里开源 Agent 进化框架

3.4 AReaL——极速代表

背景: 清华大学 IIIS + 蚂蚁集团开源,专注极致速度

设计思路

AReaL 的核心理念是 「Fully Async + boba²」——全异步流水线,目标是消除一切等待时间:

其他框架: 同步执行,GPU 大部分时间等待
AReaL:     全异步,GPU 永远在干活

架构实现

# AReaL 的异步流水线

# 阶段 1: Rollout (生成)
async def rollout_worker(prompts, model):
    while True:
        batch = await prompt_queue.get()
        responses = await model.generate(batch)
        await reward_queue.put(responses)

# 阶段 2: Reward (奖励)
async def reward_worker(reward_model):
    while True:
        responses = await reward_queue.get()
        rewards = await reward_model.score(responses)
        await advantage_queue.put((responses, rewards))

# 阶段 3: Update (更新)
async def update_worker(actor):
    while True:
        data = await advantage_queue.get()
        await actor.update(data)

# 三个 worker 完全并行运行

boba² 加速技术:

  1. 动态批处理

    • 根据实际生成长度动态调整 batch size
    • 短序列和长序列自动分组
  2. 预取优化

    • 提前准备下一个 batch 的数据
    • 消除 I/O 等待
  3. 2.77× 吞吐量提升 (相比同步方案)

优缺点

优点缺点
✅ 速度最快 (boba²)❌ 算法支持较少
✅ Agent 友好❌ 主要针对推理任务
✅ 支持华为 NPU❌ 社区较小
✅ AReaL-lite 轻量

生产案例

  • 235B MoE: 超越 GPT-5
  • 搜索 Agent: 端到端异步训练
  • 客服 Agent: 多轮对话训练

3.5 横向对比

核心架构对比

框架调度器推理引擎训练后端核心创新
OpenRLHFRayvLLMDeepSpeedAgent 抽象
verl自研vLLM/SGLangFSDP/MegatronHybridFlow
slime自研SGLangMegatron彻底解耦
AReaL自研SGLang自研Fully Async

算法支持对比

算法OpenRLHFverlslimeAReaL
PPO
GRPO
DAPO---
VAPO---
REINFORCE++-
RLOO--
PF-PPO---

性能与效率

指标OpenRLHFverlslimeAReaL
吞吐量SOTA很高
显存效率很高
扩展性极高
启动难度

选型决策树

需要大规模生产训练?

  ├─ YES → verl (工业验证)

  └─ NO → 需要快速实验?

            ├─ YES → OpenRLHF (简单) 或 AReaL-lite (快速)

            └─ NO → 需要训练 GLM?

                      ├─ YES → slime

                      └─ NO → 需要 Agent 训练?

                                ├─ YES → AReaL (异步) 或 verl (ReTool)

                                └─ NO → 都可以,看团队熟悉度

第四部分:从零开始跑通你的第一个 RLHF 训练

这一部分是写给完全新手的。不需要你有 GPU 集群,不需要你有模型权重,只要你有一台有显卡的电脑,就能跟着一步步做下来。

我们会解决一个问题:网上教程要么太简单(只告诉你安装命令),要么太难(假设你已经有完整基础设施)

这篇不会告诉你所有参数什么意思,而是带你从 0 到 1 跑通第一个 RLHF 训练,然后你自己会去探索那些参数。

4.1 跑 RLHF 之前,你必须知道的 3 件事

在动手之前,先回答 3 个问题:

问题 1: 我需要什么硬件?

配置能做什么
1 张 RTX 3090/4090 (24G)跑通流程,验证代码能work
4 张 A100 80G可以训练 7B 模型
8+ 张 A100 80G可以训练 70B 模型

我的建议: 先用 1 张卡验证流程,不要一上来就搞多卡。

问题 2: 模型从哪里来?

你不需要自己训练模型,可以直接下载开源的:

# 方法 1: 用 HuggingFace
from transformers import AutoModelForCausalLM, AutoTokenizer

model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct")

# 方法 2: 用魔搭社区 (国内快)
# https://modelscope.cn/models/qwen/Qwen2.5-7B-Instruct

推荐模型(按难度排序):

模型大小适合
Qwen2.5-1.5B3GB第一次跑,显卡一般
Qwen2.5-7B15GB主流实验
Llama-3-8B16GB效果更好

问题 3: 训练一个 RLHF 要多久?

模型GPU预计时间
1.5B1x 30901-2 小时
7B4x A1002-4 小时
7B8x A10030-60 分钟

重要的是先跑通,而不是优化时间。


4.2 环境搭建:最简单的方式

方式 A: 用 Docker(推荐)

如果你的服务器有 NVIDIA 显卡 + Docker:

# 1. 启动容器
docker run --runtime=nvidia -it --rm \
    --gpus all \
    --shm-size=10g \
    -v $PWD:/workspace \
    nvcr.io/nvidia/pytorch:24.03-py3 bash

# 2. 容器内安装 OpenRLHF
pip install openrlhf[vllm]

好处: 不用自己装 CUDA、cuDNN,不会遇到环境问题。

方式 B: 不用 Docker

如果你想本地装:

# 创建虚拟环境
conda create -n rlhf python=3.10
conda activate rlhf

# 安装 PyTorch (选择和你显卡匹配的版本)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

# 安装 OpenRLHF
pip install openrlhf[vllm]

新手常见问题:

  • ❌ 不要自己装 CUDA —— 用 Docker 或 conda
  • ❌ 不要一上来就尝试多节点 —— 先单机跑通

4.3 第一步:准备你的数据

RLHF 训练的数据格式其实很简单。你需要两类数据:

数据 1: Prompt(问题)

就是你想让模型回答的问题。

[
  {"role": "user", "content": "如何快速排序?"},
  {"role": "user", "content": "什么是强化学习?"},
  {"role": "user", "content": "用 Python 写一个 Hello World"}
]

保存为 prompts.jsonl(每行一个 JSON):

{"role": "user", "content": "如何快速排序?"}
{"role": "user", "content": "什么是强化学习?"}

数据 2: Reward(奖励)

有两种方式:

方式 A: 自己写奖励函数(不需要额外数据)

# reward.py
def reward_func(prompts, responses, labels=None):
    """根据规则计算奖励"""
    rewards = []
    
    for response in responses:
        score = 0.0
        
        # 规则 1: 回答不能太短
        if len(response) > 20:
            score += 0.3
            
        # 规则 2: 回答中包含代码关键词
        if "def " in response or "class " in response:
            score += 0.4
            
        # 规则 3: 回答长度适中
        if 50 < len(response) < 500:
            score += 0.3
            
        rewards.append(score)
    
    return rewards

方式 B: 用已有数据集(推荐新手)

# 最简单的开始方式:直接用现成数据集
from datasets import load_dataset

# 这个数据集包含各种编程问题
dataset = load_dataset("openai/gsm8k", "main")  # 数学问题
dataset = load_dataset("bigcode/humaneval", "main")  # 代码问题

# 取前 100 条作为 prompt
prompts = [item["question"] for item in dataset["test"][:100]]

4.4 跑通你的第一个训练

最简配置(1 张 GPU 就能跑)

python -m openrlhf.cli.train_ppo_ray \
    --pretrain Qwen/Qwen2.5-1.8B-Instruct \
    --prompt_data path/to/your/prompts.jsonl \
    --input_key content \
    --remote_rm_url path/to/your/reward.py \
    --train_batch_size 32 \
    --rollout_batch_size 128 \
    --micro_rollout_batch_size 16 \
    --micro_train_batch_size 4 \
    --max_samples 1000 \
    --num_epochs 1 \
    --save_path ./checkpoints/rlhf_model

你会看到什么?

运行后,等 1-2 分钟(首次启动要编译),你会看到类似输出:

# 启动阶段
[INFO] Initializing model...
[INFO] Model: Qwen2.5-1.8B-Instruct
[INFO] Loading prompts from: prompts.jsonl
[INFO] Total prompts: 1000
[INFO] Initializing vLLM engine...

# 训练阶段
[INFO] Step 1/100 | Loss: 0.523 | Reward: 0.234 | KL: 0.012
[INFO] Step 10/100 | Loss: 0.456 | Reward: 0.389 | KL: 0.018
[INFO] Step 20/100 | Loss: 0.412 | Reward: 0.512 | KL: 0.021
...
[INFO] Training completed! Saving model to ./checkpoints/rlhf_model

怎么看训练是否顺利?

指标正常范围警惕
Loss逐渐下降突然飙升
Reward逐渐上升一直 0
KL0.01 ~ 0.05> 0.1

重点: 第一次跑,不用追求效果,先看能不能跑完。


4.5 怎么评估模型变好了?

跑完后,你会得到一个微调过的模型。评估它:

方法 1: 简单测试

from transformers import AutoModelForCausalLM, AutoTokenizer

model = AutoModelForCausalLM.from_pretrained("./checkpoints/rlhf_model")
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-1.8B-Instruct")

# 测试一个问题
prompt = "如何实现快速排序?"
inputs = tokenizer(prompt, return_tensors="pt")

output = model.generate(**inputs, max_new_tokens=200)
response = tokenizer.decode(output[0], skip_special_tokens=True)

print(response)

方法 2: 对比基准

# 对比原始模型 vs 微调模型
original_response = original_model.generate(...)
tuned_response = tuned_model.generate(...)

print("原始回答:", original_response)
print("微调后回答:", tuned_response)

方法 3: 用评估数据集

from datasets import load_dataset
from transformers import evaluate

# 用 HumanEval 评估代码能力
accuracy = evaluate.load("humaneval")
predictions = [generate_code(item["prompt"]) for item in dataset]
results = accuracy.compute(predictions=predictions, references=dataset["test"])

print(f"Pass@{1} = {results['pass_at_k']}")

4.6 常见问题与解决

Q1: 显存不够怎么办?

Error: CUDA out of memory

按顺序尝试

  1. 减少 batch size:

    --micro_rollout_batch_size 8
    --micro_train_batch_size 2
  2. 开启梯度检查点:

    --gradient_checkpointing
  3. 用更小的模型:

    7B → 1.8B → 0.5B
  4. 用量化:

    --quantization 4bit

Q2: 训练一直卡着不动?

检查:

# 看 GPU 使用率
nvidia-smi

# 看进程日志
ps aux | grep python

如果 GPU 利用率 0%,可能是:

  • vLLM 启动太慢(等 3-5 分钟)
  • 代码有 bug(看错误日志)

Q3: Reward 一直是 0?

原因: 奖励函数设计太难,模型答不到

解决:

  • 简化奖励函数(先只看回答长度)
  • 增加正例比例
def reward_func(prompts, responses):
    # 先用最简单的:只要回答了就给分
    return [min(len(r) / 100, 1.0) for r in responses]

4.7 下一步做什么?

跑通第一个 Demo 后,你可以:

进阶 1: 换成真正的奖励模型

# 不再用自己的 reward.py,而是用训练好的 Reward Model
python -m openrlhf.cli.train_ppo_ray \
    --pretrain Qwen/Qwen2.5-7B-Instruct \
    --reward_pretrain openai/shepherd-2-1.8b \
    ...

进阶 2: 加入 SFT 热启动

# 先做 SFT,再做 RLHF
# 1. SFT
python -m openrlhf.cli.train_sft \
    --pretrain Qwen/Qwen2.5-7B-Instruct \
    --dataset your_sft_data.jsonl

# 2. RLHF (用 SFT 后的模型)
python -m openrlhf.cli.train_ppo_ray \
    --pretrain ./checkpoints/sft_model \
    ...

进阶 3: 尝试不同算法

# GRPO (更简单,不需要 Reward Model)
--advantage_estimator group_norm

# REINFORCE++ (适合推理任务)
--advantage_estimator reinforce

4.8 资源汇总

入门首选

模型下载

学习资料

  • PPO 原始论文
  • DeepSeek GRPO 论文

4.9 总结

这一节我们覆盖了:

  1. 硬件需求: 1 张卡就能跑
  2. 模型来源: HuggingFace 直接下载
  3. 数据准备: Prompt + Reward 两类
  4. 完整流程: 从跑通到评估
  5. 常见问题: 显存、卡住、Reward=0

核心建议: 先跑通,再优化。不要一上来就调参。


总结

写到最后,分享几点我的思考。

关于算法:PPO 统治了 ChatGPT 时代,但 GRPO 用「相对比较」的智慧,让 RLHF 变得简单高效。DeepSeek 证明了一个深刻的道理:有时候,少即是多。

关于框架:我调研了四个主流框架,发现它们本质上在解决三个问题——怎么让 GPU 少等待(吞吐)、怎么支持更多算法(灵活)、怎么在大规模训练(扩展)。每个框架给出了不同的答案:OpenRLHF 追求简单、verl 追求极致性能、slime 追求解耦、AReaL 追求速度。

关于实践:框架只是工具,真正的能力来自对问题的理解。建议先跑通一个 Demo,感受数据是怎么流动的,然后再深入研究框架的细节。

关于未来:Agent RL 是下一个爆发点。Coding Agent 的发展会倒逼训练框架的进化。异步化、Agent 化、多模态是明确的方向。

希望这篇文章能帮你建立起对 LLM RL 训练的整体认知。动手实践远比纸上谈兵重要。


参考资源

  1. OpenRLHF GitHub · 文档
  2. verl GitHub · 文档
  3. slime GitHub · 博客
  4. AReaL GitHub · 文档
  5. DeepSeek GRPO Paper
  6. DAPO Paper
  7. VAPO Paper

本文会持续更新。