关于 grpo-rl-training
该技能为使用 TRL 实现 GRPO 强化学习训练提供指导,面向需要通过自定义奖励函数微调 LLM 的从业者。内容涵盖数据准备、奖励设计、训练配置、调试及部署,并强调逐步验证训练流程。
主要功能
- 01GRPO 算法与训练流程指导
- 02设计并组合自定义奖励函数
- 03配置 TRL 训练参数
- 04提供 Transformers 与 Unsloth 示例
- 05涵盖 LoRA 合并和推理
适用场景
- 01用正确性奖励训练数学或编码任务
- 02通过奖励约束 JSON 等输出格式
- 03针对多个目标组合奖励信号
- 04排查奖励函数与训练过程问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ kalarislabs/ research-agent-skills --skill grpo-rl-training安装后在 Claude Code 中输入/grpo-rl-training确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.mdexamples/reward_functions_library.pyreferences/advanced-patterns.mdcritical-training-insights.mdtemplates/basic_grpo_training.py详细介绍
使用 TRL 进行 GRPO/RL 训练
使用 Transformer Reinforcement Learning(TRL)库实现 Group Relative Policy Optimization(GRPO)的专家级指南。本技能提供经过实践检验的模式、关键见解和可用于生产环境的工作流,帮助你使用自定义奖励函数微调语言模型。
何时使用本技能
在以下情况下使用 GRPO 训练:
- 强制指定输出格式(例如 XML 标签、JSON、结构化推理)
- 教授可验证的任务,并使用客观的正确性指标(数学、编码、事实核查)
- 通过奖励思维链模式提升推理能力
- 在没有标注偏好数据的情况下,使模型符合特定领域的行为要求
- 同时优化多个目标(格式 + 正确性 + 风格)
不要在以下情况下使用 GRPO:
- 简单的监督微调任务(改用 SFT)
- 没有明确奖励信号的任务
- 已有高质量偏好对时(改用 DPO/PPO)
核心概念
1. GRPO 算法基础
关键机制:
- 为每个提示词生成多个补全(组大小:4-16)
- 使用奖励函数比较每组中的补全
- 更新策略,使其倾向于获得更高奖励的响应,同时以组内表现为参照
与 PPO 的关键区别:
- 无需单独的奖励模型
- 样本效率更高(通过组内比较学习)
- 实现和调试更简单
数学直觉:
For each prompt p:
1. Generate N completions: {c₁, c₂, ..., cₙ}
2. Compute rewards: {r₁, r₂, ..., rₙ}
3. Learn to increase probability of high-reward completions
relative to low-reward ones in the same group
2. 奖励函数设计理念
黄金法则:
- 组合多个奖励函数——每个函数处理一个方面(格式、正确性、风格)
- 恰当设置奖励权重——权重越高,信号越强
- 使用增量奖励——部分遵循要求也给予部分奖励
- 独立测试奖励函数——单独调试每个奖励函数
奖励函数类型:
| 类型 | 使用场景 | 示例权重 |
|---|---|---|
| 正确性 | 可验证的任务(数学、代码) | 2.0(最高) |
| 格式 | 严格的结构约束 | 0.5-1.0 |
| 长度 | 鼓励详尽或简洁 | 0.1-0.5 |
| 风格 | 惩罚不需要的模式 | -0.5 到 0.5 |
实现工作流
步骤 1:准备数据集
关键要求:
- 使用聊天格式的提示词(包含 'role' 和 'content' 的字典列表)
- 包含系统提示词以设定预期
- 对于可验证的任务,将标准答案作为额外列包含在内
示例结构:
from datasets import load_dataset, Dataset
SYSTEM_PROMPT = """
Respond in the following format:
<reasoning>
[Your step-by-step thinking]
</reasoning>
<answer>
[Final answer]
</answer>
"""
def prepare_dataset(raw_data):
"""
Transform raw data into GRPO-compatible format.
Returns: Dataset with columns:
- 'prompt': List[Dict] with role/content (system + user messages)
- 'answer': str (ground truth, optional but recommended)
"""
return raw_data.map(lambda x: {
'prompt': [
{'role': 'system', 'content': SYSTEM_PROMPT},
{'role': 'user', 'content': x['question']}
],
'answer': extract_answer(x['raw_answer'])
})
实用建议:
- 对复杂格式,在系统提示词中使用单样本或少样本示例
- 保持提示词简洁(max_prompt_length:256-512 个 token)
- 训练前验证数据质量(输入垃圾,输出也会是垃圾)
步骤 2:实现奖励函数
模板结构:
def reward_function_name(
prompts, # List[List[Dict]]: Original prompts
completions, # List[List[Dict]]: Model generations
answer=None, # Optional: Ground truth from dataset
**kwargs # Additional dataset columns
) -> list[float]:
"""
Evaluate completions and return rewards.
Returns: List of floats (one per completion)
"""
# Extract completion text
responses = [comp[0]['content'] for comp in completions]
# Compute rewards
rewards = []
for response in responses:
score = compute_score(response)
rewards.append(score)
return rewards
示例 1:正确性奖励(数学/编码)
def correctness_reward(prompts, completions, answer, **kwargs):
"""Reward correct answers with high score."""
responses = [comp[0]['content'] for comp in completions]
extracted = [extract_final_answer(r) for r in responses]
return [2.0 if ans == gt else 0.0
for ans, gt in zip(extracted, answer)]
示例 2:格式奖励(结构化输出)
import re
def format_reward(completions, **kwargs):
"""Reward XML-like structured format."""
pattern = r'<reasoning>.*?</reasoning>\s*<answer>.*?</answer>'
responses = [comp[0]['content'] for comp in completions]
return [1.0 if re.search(pattern, r, re.DOTALL) else 0.0
for r in responses]
示例 3:增量格式奖励(部分得分)
def incremental_format_reward(completions, **kwargs):
"""Award partial credit for format compliance."""
responses = [comp[0]['content'] for comp in completions]
rewards = []
for r in responses:
score = 0.0
if '<reasoning>' in r:
score += 0.25
if '</reasoning>' in r:
score += 0.25
if '<answer>' in r:
score += 0.25
if '</answer>' in r:
score += 0.25
# Penalize extra text after closing tag
if r.count('</answer>') == 1:
extra_text = r.split('</answer>')[-1].strip()
score -= len(extra_text) * 0.001
rewards.append(score)
return rewards
关键见解: 组合 3-5 个奖励函数,以实现稳健训练。信号的多样性比排序更重要。
步骤 3:训练配置
内存优化配置(小型 GPU)
from trl import GRPOConfig
training_args = GRPOConfig(
output_dir="outputs/grpo-model",
# Learning rate
learning_rate=5e-6, # Lower = more stable
adam_beta1=0.9,
adam_beta2=0.99,
weight_decay=0.1,
warmup_ratio=0.1,
lr_scheduler_type='cosine',
# Batch settings
per_device_train_batch_size=1,
gradient_accumulation_steps=4, # Effective batch = 4
# GRPO-specific
num_generations=8, # Group size: 8-16 recommended
max_prompt_length=256,
max_completion_length=512,
# Training duration
num_train_epochs=1,
max_steps=None, # Or set fixed steps (e.g., 500)
# Optimization
bf16=True, # Faster on A100/H100
optim="adamw_8bit", # Memory-efficient optimizer
max_grad_norm=0.1,
# Logging
logging_steps=1,
save_steps=100,
report_to="wandb", # Or "none" for no logging
)
高性能配置(大型 GPU)
training_args = GRPOConfig(
output_dir="outputs/grpo-model",
learning_rate=1e-5,
per_device_train_batch_size=4,
gradient_accumulation_steps=2,
num_generations=16, # Larger groups = better signal
max_prompt_length=512,
max_completion_length=1024,
num_train_epochs=1,
bf16=True,
use_vllm=True, # Fast generation with vLLM
logging_steps=10,
)
关键超参数:
| 参数 | 影响 | 调优建议 |
|---|---|---|
num_generations | 用于比较的组大小 | 从 8 开始;如果 GPU 资源允许,增加到 16 |
learning_rate | 收敛速度/稳定性 | 5e-6(稳妥),1e-5(更快,但风险更高) |
max_completion_length | 输出详尽程度 | 根据任务设定(推理任务为 512,简短回答为 256) |
gradient_accumulation_steps | 有效批次大小 | 如果 GPU 内存受限,则增大该值 |
步骤 4:模型设置与训练
标准设置(Transformers)
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import LoraConfig
from trl import GRPOTrainer
# Load model
model_name = "Qwen/Qwen2.5-1.5B-Instruct"
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.bfloat16,
attn_implementation="flash_attention_2", # 2-3x faster
device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
# Optional: LoRA for parameter-efficient training
peft_config = LoraConfig(
r=16, # Rank (higher = more capacity)
lora_alpha=32, # Scaling factor (typically 2*r)
target_modules=[
"q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"
],
task_type="CAUSAL_LM",
lora_dropout=0.05,
)
# Initialize trainer
trainer = GRPOTrainer(
model=model,
processing_class=tokenizer,
reward_funcs=[
incremental_format_reward,
format_reward,
correctness_reward,
],
args=training_args,
train_dataset=dataset,
peft_config=peft_config, # Remove for full fine-tuning
)
# Train
trainer.train()
# Save
trainer.save_model("final_model")
Unsloth 设置(快 2-3 倍)
from unsloth import FastLanguageModel
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="google/gemma-3-1b-it",
max_seq_length=1024,
load_in_4bit=True,
fast_inference=True,
max_lora_rank=32,
)
model = FastLanguageModel.get_peft_model(
model,
r=32,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj",
"gate_proj", "up_proj", "down_proj"],
lora_alpha=32,
use_gradient_checkpointing="unsloth",
)
# Rest is identical to standard setup
trainer = GRPOTrainer(model=model, ...)
trainer.train()
关键训练见解
详细信息、代码示例和参数表: references/critical-training-insights.md。适用此步骤时请阅读。
高级模式
详细信息、代码示例和参数表: references/advanced-patterns.md。适用此步骤时请阅读。
部署和推理
保存并合并 LoRA
# Merge LoRA adapters into base model
if hasattr(trainer.model, 'merge_and_unload'):
merged_model = trainer.model.merge_and_unload()
merged_model.save_pretrained("production_model")
tokenizer.save_pretrained("production_model")
推理示例
from transformers import pipeline
generator = pipeline(
"text-generation",
model="production_model",
tokenizer=tokenizer
)
result = generator(
[
{'role': 'system', 'content': SYSTEM_PROMPT},
{'role': 'user', 'content': "What is 15 + 27?"}
],
max_new_tokens=256,
do_sample=True,
temperature=0.7,
top_p=0.9
)
print(result[0]['generated_text'])
最佳实践清单
训练前:
- 验证数据集格式(提示词为 List[Dict])
- 在样本数据上测试奖励函数
- 根据数据计算预期的 max_prompt_length
- 根据 GPU 内存选择合适的 num_generations
- 设置日志记录(推荐使用 wandb)
训练期间:
- 监控奖励变化(应当上升)
- 检查 reward_std(应保持 > 0.1)
- 留意 OOM 错误(必要时减小批次大小)
- 每 50-100 步采样生成结果
- 在留出集上验证格式合规性
训练后:
- 如果使用 PEFT,则合并 LoRA 权重
- 使用多样化的提示词进行测试
- 与基线模型进行比较
- 记录奖励权重和超参数
- 保存可复现配置
故障排除指南
调试工作流
- 隔离奖励函数 - 单独测试每个函数
- 检查数据分布 - 确保提示词具有多样性
- 降低复杂度 - 从单个奖励开始,再逐步添加
- 监控生成结果 - 每隔 N 步打印样本
- 验证提取逻辑 - 确保答案解析有效
快速修复
# Debug reward function
def debug_reward(completions, **kwargs):
responses = [comp[0]['content'] for comp in completions]
for i, r in enumerate(responses[:2]): # Print first 2
print(f"Response {i}: {r[:200]}...")
return [1.0] * len(responses) # Dummy rewards
# Test without training
trainer = GRPOTrainer(..., reward_funcs=[debug_reward])
trainer.generate_completions(dataset[:1]) # Generate without updating
参考资料和资源
官方文档:
- TRL GRPO Trainer:https://huggingface.co/docs/trl/grpo_trainer
- DeepSeek R1 论文:https://arxiv.org/abs/2501.12948
- Unsloth 文档:https://docs.unsloth.ai/
示例代码库:
- Open R1 实现:https://github.com/huggingface/open-r1
- TRL 示例:https://github.com/huggingface/trl/tree/main/examples
推荐阅读:
- 面向 Agent 指令的渐进式披露模式
- 强化学习中的奖励塑形(Ng 等人)
- LoRA 论文(Hu 等人,2021)
Agent 使用说明
加载此技能后:
- 实现 GRPO 训练前,请通读整个文件
- 从最简单的奖励函数开始(例如,基于长度的函数),以验证配置
- 使用
templates/目录中的模板作为起点 - 参考
examples/中的示例,实现特定任务 - 按顺序遵循工作流(不要跳过步骤)
- 逐步调试 - 每次添加一个奖励函数
重要提醒:
- 始终使用多个奖励函数(3-5 个为最佳)
- 监控奖励指标,而不是损失
- 训练前测试奖励函数
- 从小规模开始(num_generations=4),再逐步扩大
- 经常保存检查点(每 100 步)
此技能面向专家级实现。初学者应先从监督微调入手,再尝试 GRPO。
相关技能
fine-tuning-with-trl:使用 TRL 通过强化学习微调 LLM - 用于指令微调的 SFT、用于偏好对齐的 DPO、用于奖励优化的 PPO/GRPO…unsloth:提供使用 Unsloth 微调大语言模型的指导;Unsloth 是一个利用 LoRA 和 QLoRA 实现更快、占用更少内存训练的库,基…axolotl:提供使用 Axolotl 微调大语言模型的指导,涵盖 YAML 训练配置、LoRA 和 QLoRA、偏好训练 w…