mcpField
G
grpo-rl-training

grpo-rl-training

github.com/kalarislabs开发9657 次安装3 天前更新
代码仓库

关于 grpo-rl-training

该技能为使用 TRL 实现 GRPO 强化学习训练提供指导,面向需要通过自定义奖励函数微调 LLM 的从业者。内容涵盖数据准备、奖励设计、训练配置、调试及部署,并强调逐步验证训练流程。

主要功能

  1. 01GRPO 算法与训练流程指导
  2. 02设计并组合自定义奖励函数
  3. 03配置 TRL 训练参数
  4. 04提供 Transformers 与 Unsloth 示例
  5. 05涵盖 LoRA 合并和推理

适用场景

  1. 01用正确性奖励训练数学或编码任务
  2. 02通过奖励约束 JSON 等输出格式
  3. 03针对多个目标组合奖励信号
  4. 04排查奖励函数与训练过程问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/kalarislabs/research-agent-skills --skill grpo-rl-training

安装后在 Claude Code 中输入/grpo-rl-training确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

README.md
examples/
reward_functions_library.py
references/
advanced-patterns.md
critical-training-insights.md
templates/
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. 奖励函数设计理念

黄金法则:

  1. 组合多个奖励函数——每个函数处理一个方面(格式、正确性、风格)
  2. 恰当设置奖励权重——权重越高,信号越强
  3. 使用增量奖励——部分遵循要求也给予部分奖励
  4. 独立测试奖励函数——单独调试每个奖励函数

奖励函数类型:

类型使用场景示例权重
正确性可验证的任务(数学、代码)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 权重
  • 使用多样化的提示词进行测试
  • 与基线模型进行比较
  • 记录奖励权重和超参数
  • 保存可复现配置

故障排除指南

调试工作流
  1. 隔离奖励函数 - 单独测试每个函数
  2. 检查数据分布 - 确保提示词具有多样性
  3. 降低复杂度 - 从单个奖励开始,再逐步添加
  4. 监控生成结果 - 每隔 N 步打印样本
  5. 验证提取逻辑 - 确保答案解析有效
快速修复
# 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

参考资料和资源

官方文档:

示例代码库:

推荐阅读:

  • 面向 Agent 指令的渐进式披露模式
  • 强化学习中的奖励塑形(Ng 等人)
  • LoRA 论文(Hu 等人,2021)

Agent 使用说明

加载此技能后:

  1. 实现 GRPO 训练前,请通读整个文件
  2. 从最简单的奖励函数开始(例如,基于长度的函数),以验证配置
  3. 使用 templates/ 目录中的模板作为起点
  4. 参考 examples/ 中的示例,实现特定任务
  5. 按顺序遵循工作流(不要跳过步骤)
  6. 逐步调试 - 每次添加一个奖励函数

重要提醒:

  • 始终使用多个奖励函数(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…

评论

支持 Markdown