> For the complete documentation index, see [llms.txt](https://docs.clore.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.clore.ai/guides/guides_v2-zh/xun-lian/trl.md).

# TRL（RLHF/DPO 训练）

**TRL** （Transformer Reinforcement Learning）是 Hugging Face 的官方库，用于使用强化学习技术训练语言模型。它在 GitHub 上拥有 1 万+ 星标，提供 RLHF、DPO、PPO、GRPO 以及其他面向 LLM 的对齐算法的最先进实现。

{% hint style="success" %}
所有示例都可以在通过以下方式租用的 GPU 服务器上运行 [CLORE.AI 市场](https://clore.ai/marketplace).
{% endhint %}

***

## 什么是 TRL？

TRL 是许多当今最佳对齐语言模型背后的库。它提供：

* **SFT（监督微调）** — 使用 ChatML 格式的标准指令微调
* **RLHF/PPO** — 带奖励模型的经典近端策略优化
* **DPO** — 直接偏好优化（不需要奖励模型！）
* **GRPO** — 群体相对策略优化（DeepSeek-R1 的方法）
* **KTO** — 卡尼曼-特沃斯基优化（适用于未配对偏好）
* **奖励建模** — 从人类偏好数据中训练奖励模型
* **IterativeSFT** — 设置更简单的在线 RL
* **ORPO** — 赔率比偏好优化

TRL 可与 Hugging Face 生态系统原生集成： `transformers`, `peft`, `datasets`, `accelerate`，以及 `bitsandbytes`.

{% hint style="info" %}
**应该使用哪种算法？**

* **DPO** — 最简单、最稳定。适用于有成对偏好数据（选中/拒绝）时。
* **PPO** — 最强大但也最复杂。适用于有奖励模型或评分函数时。
* **GRPO** — 非常适合理解/数学任务。DeepSeek-R1 的训练方法。
* **SFT** — 在应用任何 RL 方法之前，始终先从这里开始。
  {% endhint %}

***

## 服务器要求

| 组件     | 最低                       | 推荐                |
| ------ | ------------------------ | ----------------- |
| GPU    | RTX 3090（24 GB）          | A100 80 GB / H100 |
| 显存     | 16 GB（SFT/DPO 7B + LoRA） | 80 GB（完整微调 7B）    |
| 内存     | 32 GB                    | 64 GB+            |
| CPU    | 8 核                      | 16+ 核             |
| 存储     | 100 GB                   | 300 GB+           |
| 操作系统   | Ubuntu 20.04+            | Ubuntu 22.04      |
| Python | 3.9+                     | 3.11              |
| CUDA   | 12.8+                    | 12.8+             |

### 按任务划分的 VRAM

| 任务   | 模型          | 方法          | 显存              |
| ---- | ----------- | ----------- | --------------- |
| SFT  | Llama 3 8B  | QLoRA 4-bit | \~8 GB          |
| DPO  | Llama 3 8B  | LoRA        | 约 20 GB         |
| PPO  | Llama 3 8B  | 完整          | 约 80 GB（2×A100） |
| GRPO | Qwen 7B     | LoRA        | 约 24 GB         |
| SFT  | Llama 3 70B | QLoRA 4-bit | 约 48 GB         |
| DPO  | Llama 3 70B | LoRA        | 约 80 GB         |

***

## 端口

| 端口 | 服务  | 备注           |
| -- | --- | ------------ |
| 22 | SSH | 终端访问、文件传输、监控 |

TRL 是一个训练库——它以 CLI/Python 脚本形式运行，不需要 Web 服务器。

***

## 在 Clore.ai 上安装

### 步骤 1 — 租用服务器

1. 前往 [Clore.ai 市场](https://clore.ai/marketplace)
2. 筛选 **VRAM ≥ 24 GB** （RTX 3090、A100 或 H100）
3. 选择一个 **PyTorch** 或 **CUDA 12.8** 基础镜像
4. 选择 **存储 ≥ 200 GB** 用于模型和数据集
5. 开放端口 **22** 用于 SSH 访问

### 步骤 2 — 通过 SSH 连接

```bash
ssh root@<server-ip> -p <ssh-port>
```

### 步骤 3 — 安装 TRL

```bash
# 创建 Python 虚拟环境
python3 -m venv /opt/trl
source /opt/trl/bin/activate

# 安装包含所有依赖的 TRL
pip install trl

# 为完整工作流安装额外依赖
pip install \\
    transformers \\
    datasets \\
    peft \\
    accelerate \\
    bitsandbytes \\
    wandb \\
    scipy \\
    sentencepiece \\
    protobuf

# 验证 GPU 支持
python3 -c "import torch; print(f'CUDA: {torch.cuda.is_available()}, GPU: {torch.cuda.get_device_name(0)}')"
```

### 步骤 4 — Hugging Face 身份验证

```bash
# 登录以访问受限模型（Llama、Gemma）
huggingface-cli login
# 输入你从 https://huggingface.co/settings/tokens 获取的 HF 令牌

# 或设置环境变量
export HF_TOKEN=hf_your-token-here
```

### 步骤 5 — 可选：Weights & Biases 跟踪

```bash
# 设置实验跟踪（强烈推荐）
pip install wandb
wandb login  # 输入你在 https://wandb.ai/settings 获取的 W&B API 密钥

# 或禁用 W&B
export WANDB_DISABLED=true
```

***

## 监督微调（SFT）

在任何 RL 技术之前，SFT 始终是第一步。

### 准备你的数据集

```python
# 格式：带有 'messages' 或 'text' 列的 datasets 库
# ChatML 格式（推荐）
from datasets import Dataset

data = [
    {
        "messages": [
            {"role": "system", "content": "你是一个乐于助人的 GPU 云助手。"},
            {"role": "user", "content": "我该如何在 Clore.ai 上租用 GPU？"},
            {"role": "assistant", "content": "访问 clore.ai/marketplace，按 GPU 规格筛选，选择一台服务器，然后点击租用。支付后会立即提供 SSH 访问。"}
        ]
    },
    # ……更多示例
]

dataset = Dataset.from_list(data)
dataset.save_to_disk("data/sft_dataset")
dataset.push_to_hub("your-username/my-sft-dataset")  # 可选
```

### SFT 训练脚本

```python
# sft_train.py
from trl import SFTTrainer, SFTConfig
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model
from datasets import load_dataset
import torch

# 模型配置
model_name = "meta-llama/Llama-3.2-8B-Instruct"

# QLoRA：4 位量化配置
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True,
)

# 加载模型
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    quantization_config=bnb_config,
    device_map="auto",
    trust_remote_code=True,
)

# 加载 tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"

# LoRA 配置
lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
                    "gate_proj", "up_proj", "down_proj"],
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)

# 加载数据集
dataset = load_dataset("trl-lib/ultrachat_200k", split="train_sft[:10%]")

# 训练配置
training_config = SFTConfig(
    output_dir="./sft_output",
    num_train_epochs=3,
    per_device_train_batch_size=2,
    gradient_accumulation_steps=4,
    learning_rate=2e-4,
    warmup_ratio=0.05,
    lr_scheduler_type="cosine",
    fp16=False,
    bf16=True,
    max_seq_length=2048,
    dataset_text_field="messages",
    logging_steps=10,
    save_steps=100,
    save_total_limit=3,
    push_to_hub=False,
    report_to="wandb",  # 或 "none"
)

# 初始化 trainer
trainer = SFTTrainer(
    model=model,
    args=training_config,
    train_dataset=dataset,
    peft_config=lora_config,
    tokenizer=tokenizer,
)

# 训练
trainer.train()
trainer.save_model("./sft_final")
```

```bash
# 运行训练
python3 sft_train.py
```

***

## DPO（直接偏好优化）

DPO 是最受欢迎的对齐方法——不需要奖励模型，只需要偏好对。

### 准备 DPO 数据集

```python
# 格式：每个样本包含 'prompt'、'chosen'、'rejected'
from datasets import Dataset

data = [
    {
        "prompt": "解释如何优化 GPU 利用率",
        "chosen": "要优化 GPU 利用率：1）使用更大的批次大小以最大化占用率，2）启用混合精度（bf16/fp16），3）使用 nvidia-smi 进行分析以找出瓶颈，4）使用 CUDA 流进行并行操作。",
        "rejected": "只需使用更多 GPU。"
    },
    # ……更多偏好对
]

dataset = Dataset.from_list(data)
```

### DPO 训练脚本

```python
# dpo_train.py
from trl import DPOTrainer, DPOConfig
from transformers import AutoTokenizer, AutoModelForCausalLM
from datasets import load_dataset
import torch

model_name = "./sft_final"  # 从你的 SFT 模型开始！

# 加载 SFT 模型（要对齐的策略）
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype=torch.bfloat16,
    device_map="auto",
)

# 参考模型（SFT 模型的冻结副本）
ref_model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype=torch.bfloat16,
    device_map="auto",
)

tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token

# 加载偏好数据集
dataset = load_dataset("trl-lib/ultrafeedback_binarized", split="train[:5%]")

# DPO 配置
dpo_config = DPOConfig(
    output_dir="./dpo_output",
    num_train_epochs=1,
    per_device_train_batch_size=2,
    gradient_accumulation_steps=4,
    learning_rate=5e-7,           # 远低于 SFT
    beta=0.1,                     # KL 惩罚系数
    loss_type="sigmoid",          # 标准 DPO 损失
    max_length=2048,
    max_prompt_length=512,
    bf16=True,
    logging_steps=10,
    save_steps=50,
    report_to="wandb",
)

trainer = DPOTrainer(
    model=model,
    ref_model=ref_model,
    args=dpo_config,
    train_dataset=dataset,
    tokenizer=tokenizer,
)

trainer.train()
trainer.save_model("./dpo_final")
```

***

## PPO（近端策略优化）

PPO 是经典的 RLHF 方法——当你有奖励信号时使用：

```python
# ppo_train.py
from trl import PPOTrainer, PPOConfig, AutoModelForCausalLMWithValueHead
from transformers import AutoTokenizer, pipeline
from datasets import load_dataset
import torch

model_name = "./sft_final"

# 策略模型（带有 PPO 的 value head）
model = AutoModelForCausalLMWithValueHead.from_pretrained(
    model_name,
    torch_dtype=torch.bfloat16,
)

tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token

# 奖励模型（可以是任何评分函数）
sentiment_pipe = pipeline(
    "sentiment-analysis",
    model="distilbert/distilbert-base-uncased-finetuned-sst-2-english",
    device=0,
)

def reward_fn(texts):
    """为每个响应打分。返回奖励张量列表。"""
    results = sentiment_pipe(texts)
    rewards = []
    for result in results:
        score = result["score"] if result["label"] == "POSITIVE" else -result["score"]
        rewards.append(torch.tensor(score))
    return rewards

ppo_config = PPOConfig(
    output_dir="./ppo_output",
    learning_rate=1.41e-5,
    mini_batch_size=1,
    batch_size=4,
    gradient_accumulation_steps=4,
    kl_penalty="kl",
    target_kl=6.0,
    cliprange=0.2,
    vf_coef=0.1,
)

trainer = PPOTrainer(
    config=ppo_config,
    model=model,
    ref_model=None,  # 自动将初始模型复制为参考模型
    tokenizer=tokenizer,
)

# 训练循环
dataset = load_dataset("imdb", split="train[:1000]")
for epoch in range(3):
    for batch in trainer.dataloader:
        queries = batch["input_ids"]
        
        # 生成响应
        responses = trainer.generate(queries, max_new_tokens=100)
        
        # 对响应打分
        texts = tokenizer.batch_decode(responses, skip_special_tokens=True)
        rewards = reward_fn(texts)
        
        # PPO 更新
        stats = trainer.step(queries, responses, rewards)
        trainer.log_stats(stats, batch, rewards)
```

***

## GRPO（群体相对策略优化）

GRPO 在 DeepSeek-R1 中用于推理训练：

```python
# grpo_train.py
from trl import GRPOTrainer, GRPOConfig
from transformers import AutoTokenizer, AutoModelForCausalLM
from datasets import Dataset
import re, torch

model_name = "Qwen/Qwen2.5-7B-Instruct"

model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype=torch.bfloat16,
    device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained(model_name)

# 数学数据集
def make_math_dataset():
    examples = [
        {"prompt": "2+2 等于多少？", "answer": "4"},
        {"prompt": "15 * 7 等于多少？", "answer": "105"},
        # ……更多数学题
    ]
    return Dataset.from_list(examples)

dataset = make_math_dataset()

def correctness_reward(completions, answer, **kwargs):
    """如果答案正确则奖励 1.0，否则奖励 0.0。"""
    rewards = []
    for completion in completions:
        # 从 completion 中提取最终数字
        numbers = re.findall(r'\d+', completion[-1]["content"])

        if numbers and numbers[-1] == answer:
            rewards.append(1.0)
        else:
            rewards.append(0.0)
    return rewards

grpo_config = GRPOConfig(
    output_dir="./grpo_output",
    num_train_epochs=3,
    per_device_train_batch_size=4,
    num_generations=8,       # GRPO 为每个提示生成 G 个响应
    learning_rate=5e-7,
    bf16=True,
    logging_steps=10,
)

trainer = GRPOTrainer(
    model=model,
    args=grpo_config,
    train_dataset=dataset,
    reward_funcs=correctness_reward,
    tokenizer=tokenizer,
)

trainer.train()
```

***

## 多 GPU 训练

使用 `accelerate` 用于分布式训练：

```bash
# 为多 GPU 配置 accelerate
accelerate config

# 4 张 GPU 的示例配置：
# - compute_environment: LOCAL_MACHINE
# - distributed_type: MULTI_GPU
# - num_processes: 4
# - mixed_precision: bf16

# 在所有 GPU 上启动训练
accelerate launch sft_train.py
accelerate launch dpo_train.py

# 或显式指定 GPU
CUDA_VISIBLE_DEVICES=0,1,2,3 accelerate launch \\
  --num_processes 4 \\
  --mixed_precision bf16 \\
  sft_train.py
```

***

## 使用 TRL CLI

TRL 提供了方便的 CLI 命令：

```bash
# 通过 CLI 进行 SFT
trl sft \
  --model_name_or_path meta-llama/Llama-3.2-8B-Instruct \
  --dataset_name trl-lib/ultrachat_200k \
  --dataset_text_field messages \
  --output_dir ./cli_sft_output \
  --num_train_epochs 3 \
  --per_device_train_batch_size 2 \
  --gradient_accumulation_steps 4 \
  --learning_rate 2e-4 \
  --bf16 \
  --use_peft \
  --lora_r 16 \
  --lora_alpha 32

# 通过 CLI 进行 DPO
trl dpo \
  --model_name_or_path ./cli_sft_output \
  --dataset_name trl-lib/ultrafeedback_binarized \
  --output_dir ./cli_dpo_output \
  --num_train_epochs 1 \
  --beta 0.1 \
  --bf16
```

***

## 监控训练

```bash
# 监控 GPU 利用率
watch -n 1 nvidia-smi

# 监控训练损失（如果使用 W&B）
# 在浏览器中打开 https://wandb.ai/your-username

# 检查输出目录中的检查点
ls -lh sft_output/checkpoint-*/

# 从检查点继续训练
python3 sft_train.py --resume_from_checkpoint sft_output/checkpoint-500/
```

***

## Clore.ai GPU 推荐

{% hint style="warning" %}
**Clore.ai 市场上未列出多 GPU 的 80GB 级机型。** 目前列出的最大配置是 4× RTX PRO 6000 Blackwell（每张 96GB，共 380GB）以及 8–11× RTX 5090（每张 32GB）。A100 / H200 / B200 容量可按 [裸机](https://clore.ai/bare-metal) 需求提供。部署前请查看 [GPU 价格与可用性](/guides/guides_v2-zh/ru-men-zhi-nan/pricing.md) 。
{% endhint %}

TRL 训练是最占用 VRAM 的工作负载之一。请根据模型大小和方法选择你的 GPU：

| 任务                           | GPU                | 备注                                                  |
| ---------------------------- | ------------------ | --------------------------------------------------- |
| 7–8B 上的 SFT / DPO（QLoRA）     | **RTX 3090** 24 GB | \~8 GB 用于 QLoRA 4 位；完全足够；在 Clore.ai 上每小时 $0.07–0.21 |
| 7–8B 上的 SFT / DPO（LoRA bf16） | **RTX 4090** 24 GB | 与 3090 相同的 VRAM，但计算速度快 30%；非常适合迭代速度                 |
| 7B 的完整 SFT 或 13B 的 DPO       | **A100 40 GB**     | 40 GB 可用于 7B 全精度训练；ECC 内存可避免静默错误                    |
| PPO / 7B 全量微调，或任意 70B QLoRA  | **A100 80 GB**     | PPO 需要在显存中同时放入 2× policy+ref 模型；80 GB 可同时运行而不会 OOM  |

**实用建议：** 先用 RTX 3090 和 QLoRA 做实验——在 1 万条样本上约 2 小时即可训练 Llama 3 8B。验证流程后，再迁移到 A100 80GB 进行全精度运行或 70B 模型。

**速度数据（Llama 3 8B SFT，QLoRA，batch=4，seq=2048）：**

* RTX 3090：约 1,100 tokens/秒 训练吞吐量
* RTX 4090：约 1,450 tokens/秒
* A100 80GB：约 2,800 tokens/秒（完整 bf16，无量化）

***

## 故障排查

### CUDA 显存不足

```bash
# 减小 batch 大小
per_device_train_batch_size=1
gradient_accumulation_steps=16  # 保持有效 batch 大小不变

# 使用 4 位量化（QLoRA）
# 添加 load_in_4bit=True 的 BitsAndBytesConfig

# 启用梯度检查点
gradient_checkpointing=True

# 缩短序列长度
max_seq_length=1024  # 而不是 2048+

# 检查 GPU 显存
nvidia-smi --query-gpu=memory.used,memory.total --format=csv
```

### 损失为 NaN

```bash
# 常见原因：学习率过高
learning_rate=1e-5  # 尝试更低

# 常见原因：数据有问题（空字符串、None 值）
# 验证数据集：
python3 -c \"
from datasets import load_from_disk
ds = load_from_disk('data/sft_dataset')
print(ds[0])
print(f'长度: {len(ds)}')
# 检查 None
none_count = sum(1 for x in ds if x.get('messages') is None)
print(f'None 数量: {none_count}')
"

# 启用 bf16 而不是 fp16（更稳定）
bf16=True
fp16=False
```

### DPO： `chosen_rewards > rejected_rewards` 为 False

```bash
# 这意味着模型更偏好被拒绝的回复——过拟合或数据不佳
# 解决方案：
# 1. 检查数据集质量
# 2. 降低 beta（减小 KL 惩罚）
# 3. 降低学习率
# 4. 在 DPO 前增加更多 SFT 训练
beta=0.05  # 尝试更小的值
```

### 训练非常慢

```bash
# 启用 Flash Attention 2
pip install flash-attn --no-build-isolation

# 在你的代码中：
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    attn_implementation="flash_attention_2",
    torch_dtype=torch.bfloat16,
)

# 在 Ampere+ GPU（A100、RTX 3000+）上使用 bf16 而不是 fp16
bf16=True

# 增加 DataLoader worker 数量
dataloader_num_workers=4

# 检查 GPU 是否 वास्तव际被使用
nvidia-smi  # 应该显示较高的 GPU 利用率
```

### `tokenizer.pad_token` 警告

```bash
# Llama/Mistral 分词器的标准修复方法
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"  # 对训练稳定性很重要
```

### 权限被拒绝 / HuggingFace 401

```bash
# 重新登录
huggingface-cli login

# 在环境变量中设置 token
export HF_TOKEN=hf_your-token

# 对于私有模型/数据集，请确保你有访问权限：
# 前往 https://huggingface.co/meta-llama/Llama-3.2-8B-Instruct
# 点击“Request access”并接受许可
```

***

## 保存并分享你的模型

```bash
# 将 LoRA 权重合并到基础模型中
python3 << 'EOF'
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

base_model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3.2-8B-Instruct",
    torch_dtype=torch.bfloat16,
    device_map="auto"
)
model = PeftModel.from_pretrained(base_model, "./sft_final")
merged = model.merge_and_unload()
merged.save_pretrained("./merged_model")

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.2-8B-Instruct")
tokenizer.save_pretrained("./merged_model")
print("合并后的模型已保存！")
EOF

# 推送到 HuggingFace
huggingface-cli upload your-username/my-trl-model ./merged_model
```

***

## 有用链接

* **GitHub**: <https://github.com/huggingface/trl> ⭐ 10K+
* **文档**: <https://huggingface.co/docs/trl>
* **DPO 论文**: <https://arxiv.org/abs/2305.18290>
* **GRPO / DeepSeek-R1**: <https://arxiv.org/abs/2501.12599>
* **PPO 论文（RLHF）**: <https://arxiv.org/abs/2203.02155>
* **HuggingFace PEFT**: <https://github.com/huggingface/peft>
* **Weights & Biases**: <https://wandb.ai>
* **Flash Attention**: <https://github.com/Dao-AILab/flash-attention>
* **Clore.ai 市场**: <https://clore.ai/marketplace>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.clore.ai/guides/guides_v2-zh/xun-lian/trl.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
