【SkillRL】RL阶段

RL阶段操作手册 - Template Mode 技能增强强化学习

本手册是SFT训练完成后,启动RL强化学习阶段的逐步操作指南


目录

  1. 前置检查清单
  2. [Step 1:准备技能库JSON文件](#Step 1:准备技能库JSON文件)
  3. [Step 2:准备训练数据(Parquet)](#Step 2:准备训练数据(Parquet))
  4. [Step 3:配置环境变量](#Step 3:配置环境变量)
  5. [Step 4:启动RL训练](#Step 4:启动RL训练)
  6. [Step 5:监控训练过程](#Step 5:监控训练过程)
  7. [Step 6:检查产出与模型保存](#Step 6:检查产出与模型保存)
  8. [Step 7:恢复中断的训练](#Step 7:恢复中断的训练)
  9. 三个环境的完整命令
  10. 关键参数调优指南
  11. 常见问题排查
  12. 关键文件速查表

1. 前置检查清单

在开始RL训练之前,请逐项确认:

检查项 命令/方法 通过条件
Python环境已安装所有依赖 `pip list grep verl`
vllm已安装 pip show vllm 版本 0.11.0
flash-attn已安装 pip show flash-attn 版本 2.7.4+
SFT模型checkpoint已就绪 ls $MODEL_PATH 目录存在且包含模型文件
技能库JSON文件已就绪 见下方Step 1 文件存在且格式正确
对应环境已安装(以ALFWorld为例) pip show alfworld 已安装
GPU显存充足(7B模型建议) nvidia-smi 每张GPU >= 40GB(4卡配置)
Azure OpenAI API(动态更新用) 见下方Step 3 若启用动态更新则需要

Step 1:准备技能库JSON文件

技能库是RL训练的核心输入之一,提供Agent的先验知识。

1.1 确认技能库文件已存在

bash 复制代码
# ALFWorld
ls memory_data/alfworld/claude_style_skills.json

# WebShop
ls memory_data/webshop/claude_style_skills.json

# Search
ls memory_data/search/claude_style_skills_search.json

1.2 验证JSON格式正确

python 复制代码
import json
with open("memory_data/alfworld/claude_style_skills.json") as f:
    skills = json.load(f)

# 检查三个顶级key
assert "general_skills" in skills, "缺少 general_skills"
assert "task_specific_skills" in skills, "缺少 task_specific_skills"
assert "common_mistakes" in skills, "缺少 common_mistakes"

# 检查每个技能包含必要字段
for s in skills["general_skills"]:
    assert "skill_id" in s, f"技能缺少 skill_id: {s}"
    assert "title" in s, f"技能缺少 title: {s}"
    assert "principle" in s, f"技能缺少 principle: {s}"

print(f"通用技能: {len(skills['general_skills'])} 条")
print(f"任务特定技能类别: {list(skills['task_specific_skills'].keys())}")
print(f"常见错误: {len(skills['common_mistakes'])} 条")

ALFWorld正常输出示例

复制代码
通用技能: 12 条
任务特定技能类别: ['pick_and_place', 'pick_two_obj_and_place', 'look_at_obj_in_light', ...]
常见错误: 5 条

1.3 如果需要自己生成技能库

bash 复制代码
# 从已有的memory数据生成技能库(需要Azure API)
python skill_generation/alfworld.py \
    --memory_path memory_data/alfworld/generated_memories_alfworld_total.json \
    --output_path memory_data/alfworld/claude_style_skills.json

python skill_generation/webshop.py \
    --memory_path memory_data/webshop/generated_memories_webshop_100.json \
    --output_path memory_data/webshop/claude_style_skills.json

python skill_generation/search.py \
    --memory_path memory_data/search/generated_memories_search.json \
    --output_path memory_data/search/claude_style_skills_search.json

Step 2:准备训练数据(Parquet)

RL训练需要一个Parquet格式的数据文件,但其中的prompt内容为空,仅用于指示数据模态和大小。真正的任务由环境在运行时动态生成。

bash 复制代码
# ALFWorld / WebShop(共用同一种占位数据)
python3 -m examples.data_preprocess.prepare \
    --mode 'text' \
    --train_data_size 16 \
    --val_data_size 64

# 生成到 ~/data/verl-agent/text/train.parquet 和 test.parquet

参数说明

  • --mode text:文本模态(ALFWorld/WebShop都用这个)
  • --train_data_size:训练集大小(每个epoch的batch数量,不是真实数据条数)
  • --val_data_size:验证集大小

Search任务使用独立的数据文件(包含真实的搜索问题):

bash 复制代码
# Search的数据路径在启动脚本中指定
# data.train_files=$HOME/data/searchR1_processed_direct/train.parquet
# data.val_files=$HOME/data/searchR1_processed_direct/test.parquet

Step 3:配置环境变量

bash 复制代码
# 【必须】SFT模型路径
export MODEL_PATH=/path/to/your/sft_checkpoint

# 【可选】WandB日志(推荐开启,便于监控)
export WANDB_API_KEY="your_wandb_key"
export WANDB_NAME="alfworld_grpo_qwen2.5_7b_skills_dynamic"

# 【可选】动态技能更新需要Azure OpenAI(不启用动态更新则不需要)
export AZURE_OPENAI_API_KEY="your_azure_key"
export AZURE_OPENAI_ENDPOINT="https://your-endpoint.openai.azure.com/"
export AZURE_OPENAI_API_VERSION="2025-01-01-preview"

# 【推荐】vLLM推理引擎后端
export VLLM_ATTENTION_BACKEND=FLASH_ATTN

Step 4:启动RL训练

方式A:使用Shell脚本(推荐)

bash 复制代码
export MODEL_PATH=/path/to/your/sft_checkpoint

# ALFWorld
bash examples/grpo_trainer/run_alfworld_skills.sh

# WebShop
bash examples/grpo_trainer/run_webshop_skills.sh

# Search(需要先启动搜索服务)
bash examples/grpo_trainer/run_search_skills.sh

方式B:手动执行完整命令

以ALFWorld为例,以下是完整命令及逐行注释:

bash 复制代码
python3 -m verl.trainer.main_ppo \
    # ========== 算法 ==========
    algorithm.adv_estimator=grpo \                      # 使用GRPO优势估计
    algorithm.use_kl_in_reward=False \                  # 不在奖励中使用KL惩罚

    # ========== 数据 ==========
    data.train_files=$HOME/data/verl-agent/text/train.parquet \
    data.val_files=$HOME/data/verl-agent/text/test.parquet \
    data.train_batch_size=16 \                          # 每个step取16个任务
    data.val_batch_size=64 \                            # 验证时取64个任务
    data.max_prompt_length=4096 \                       # prompt最大token长度
    data.max_response_length=512 \                      # Agent每步回复最大token长度
    data.filter_overlong_prompts=True \
    data.truncation='error' \
    data.return_raw_chat=True \                         # 必须开启,环境交互需要

    # ========== 模型 & Actor ==========
    actor_rollout_ref.model.path=$MODEL_PATH \          # SFT模型路径
    actor_rollout_ref.actor.optim.lr=1e-6 \             # 学习率
    actor_rollout_ref.model.use_remove_padding=True \
    actor_rollout_ref.actor.ppo_mini_batch_size=128 \   # PPO mini batch大小
    actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu=4 \  # 每GPU微批次大小
    actor_rollout_ref.actor.use_kl_loss=True \          # GRPO需要开启KL损失
    actor_rollout_ref.actor.kl_loss_coef=0.01 \         # KL损失系数
    actor_rollout_ref.actor.kl_loss_type=low_var_kl \
    actor_rollout_ref.model.enable_gradient_checkpointing=True \
    actor_rollout_ref.actor.fsdp_config.param_offload=True \    # 参数卸载到CPU
    actor_rollout_ref.actor.fsdp_config.optimizer_offload=True \ # 优化器卸载到CPU
    actor_rollout_ref.actor.use_invalid_action_penalty=True \   # 无效动作惩罚
    actor_rollout_ref.actor.invalid_action_penalty_coef=0.1 \

    # ========== Rollout ==========
    actor_rollout_ref.rollout.name=vllm \               # 使用vLLM推理引擎
    actor_rollout_ref.rollout.tensor_model_parallel_size=4 \    # TP并行度
    actor_rollout_ref.rollout.gpu_memory_utilization=0.5 \      # vLLM GPU显存占比
    actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu=8 \

    # ========== 参考策略 ==========
    actor_rollout_ref.ref.log_prob_micro_batch_size_per_gpu=4 \
    actor_rollout_ref.ref.fsdp_config.param_offload=True \

    # ========== 环境 ==========
    env.env_name=alfworld/AlfredTWEnv \                 # 环境名称
    env.seed=0 \
    env.max_steps=50 \                                  # 每个episode最多50步
    env.rollout.n=8 \                                   # GRPO分组大小(每个任务重复8次)
    env.resources_per_worker.num_cpus=0.1 \

    # ========== 技能库(Template Mode核心配置)==========
    +env.use_skills_only_memory=True \                  # 开启技能库
    +env.skills_only_memory.skills_json_path=memory_data/alfworld/claude_style_skills.json \
    +env.skills_only_memory.top_k=6 \                   # 注入6条通用技能
    +env.skills_only_memory.enable_dynamic_update=True \ # 开启动态更新
    +env.skills_only_memory.update_threshold=0.4 \      # 成功率低于40%时触发更新
    +env.skills_only_memory.max_new_skills=3 \          # 每次更新最多新增3条技能

    # ========== 训练控制 ==========
    trainer.critic_warmup=0 \                           # 不使用Critic(GRPO不需要)
    trainer.logger=['console','wandb'] \
    trainer.project_name='verl_agent_alfworld' \
    trainer.experiment_name='grpo_qwen2.5_7b_skills_dynamic' \
    trainer.n_gpus_per_node=4 \                         # 使用4张GPU
    trainer.nnodes=1 \                                  # 单机训练
    trainer.save_freq=10 \                              # 每10步保存checkpoint
    trainer.test_freq=5 \                               # 每5步进行一次验证
    trainer.total_epochs=150 \                          # 总共训练150个epoch
    trainer.val_before_train=False                      # 训练前不先验证

Step 5:监控训练过程

5.1 控制台日志

训练启动后,控制台会输出关键日志。正常流程的日志序列如下:

复制代码
# 1. Ray初始化
ray init kwargs: ...

# 2. 技能库加载
[SkillsOnlyMemory] Loaded skills: 12 general, 48 task-specific, 5 mistakes | retrieval_mode=template

# 3. 数据集加载
dataset len: 16
filter dataset len: 16

# 4. Worker初始化(可能需要几分钟)
# 5. 训练循环开始
Training Progress:   1%|          | 1/150 [02:30<6:12:00, ...]

5.2 关键日志标记

日志关键词 含义 出现位置
[SkillsOnlyMemory] Loaded skills 技能库加载成功 环境初始化
[SkillUpdate] All task success rates above 0.4 验证通过,无需更新技能 验证阶段
[SkillUpdate] Low success tasks: [...] 某类任务成功率低,触发更新 验证阶段
[SkillUpdate] Analyzing N failed trajectories with o3 正在用o3分析失败轨迹 动态更新
[SkillUpdate] Added N new skills to training envs 新技能已添加到训练环境 动态更新
[SkillUpdate] Saved updated skill bank to ... 更新后的技能库已保存到磁盘 动态更新
validation generation end 验证rollout完成 验证阶段

5.3 WandB监控

若开启了 trainer.logger=['console','wandb'],可在WandB面板查看:

  • val/{data_source}/test_score:验证集平均奖励(越高越好)
  • val/{data_source}_success_rate:各类任务成功率
  • val/{data_source}/tool_call_count/mean:平均工具调用次数
  • training/actor/entropy_loss:策略熵(过低表示策略退化)
  • training/actor/ppo_policy_loss:策略损失
  • training/actor/approx_kl:近似KL散度(不应过大)

5.4 训练健康指标

指标 健康范围 异常处理
test_score 逐步上升 若长期不涨 → 检查技能库是否正确加载
success_rate 逐步上升 若始终为0 → 检查环境是否正常
approx_kl < 0.1 > 0.2 → 降低学习率或增大kl_loss_coef
entropy_loss 缓慢下降 急剧下降 → 策略坍塌,降低学习率
ppo_policy_loss 震荡但趋势下降 持续上升 → 检查奖励信号

Step 6:检查产出与模型保存

6.1 Checkpoint保存位置

复制代码
checkpoints/{project_name}/{experiment_name}/
    global_step_10/
        actor/          # Actor模型权重
        data.pt         # DataLoader状态
    global_step_20/
        ...

默认路径:checkpoints/verl_agent_alfworld/grpo_qwen2.5_7b_skills_dynamic/

可通过 trainer.default_local_dir 自定义。

6.2 动态更新的技能库文件

复制代码
{default_local_dir}/updated_skills_step{N}.json

例如:checkpoints/.../updated_skills_step5.json

6.3 查看模型checkpoint

bash 复制代码
# 查看已保存的checkpoint
ls checkpoints/verl_agent_alfworld/grpo_qwen2.5_7b_skills_dynamic/

# 查看最新checkpoint的内容
ls checkpoints/.../global_step_10/actor/

Step 7:恢复中断的训练

训练会自动检测最新checkpoint并恢复:

bash 复制代码
# 确保default_local_dir下有checkpoint
ls checkpoints/verl_agent_alfworld/grpo_qwen2.5_7b_skills_dynamic/

# 直接重新运行同样的命令,trainer.resume_mode=auto 会自动找到最新的global_step_N
bash examples/grpo_trainer/run_alfworld_skills.sh

日志中会显示:

复制代码
Load from checkpoint folder: .../global_step_10
Setting global step to 10
Training Progress:   7%|6          | 11/150 [...]

如果要从特定checkpoint恢复:

bash 复制代码
python3 -m verl.trainer.main_ppo \
    ... \
    trainer.resume_mode=resume_path \
    trainer.resume_from_path=/path/to/global_step_20 \
    ...

9. 三个环境的完整命令

9.1 ALFWorld

bash 复制代码
export MODEL_PATH=/path/to/sft_checkpoint
# 可选:export WANDB_API_KEY="..."
# 可选:export AZURE_OPENAI_API_KEY="..."

# 准备数据
python3 -m examples.data_preprocess.prepare \
    --mode 'text' --train_data_size 16 --val_data_size 64

# 启动训练
bash examples/grpo_trainer/run_alfworld_skills.sh

关键环境参数

  • env.env_name=alfworld/AlfredTWEnv
  • env.max_steps=50(每episode最多50步交互)
  • env.rollout.n=8(GRPO分组8条轨迹)
  • data.max_prompt_length=4096
  • data.max_response_length=512

9.2 WebShop

bash 复制代码
export MODEL_PATH=/path/to/sft_checkpoint

# 准备数据
python3 -m examples.data_preprocess.prepare \
    --mode 'text' --train_data_size 16 --val_data_size 64

# 启动训练
bash examples/grpo_trainer/run_webshop_skills.sh

关键环境参数(与ALFWorld的差异):

  • env.env_name=Webshop
  • env.max_steps=15(WebShop步数更少)
  • data.max_prompt_length=6000(WebShop页面内容更长)
  • data.max_response_length=768
  • data.truncation='left'(左侧截断)
  • actor_rollout_ref.rollout.gpu_memory_utilization=0.7
  • trainer.n_gpus_per_node=8
bash 复制代码
export MODEL_PATH=/path/to/sft_checkpoint

# Search需要先启动搜索服务
# 确保搜索服务在 http://127.0.0.1:8030/retrieve 可用

# Search使用独立的数据文件(不是prepare.py生成的占位数据)
bash examples/grpo_trainer/run_search_skills.sh

关键环境参数(与ALFWorld的差异):

  • env.env_name=search
  • env.max_steps=4(搜索只需几步)
  • env.rollout.n=4(GRPO分组更小)
  • env.history_length=4
  • env.search.search_url='http://127.0.0.1:8030/retrieve'
  • data.train_files=$HOME/data/searchR1_processed_direct/train.parquet(独立数据)
  • data.max_prompt_length=5000
  • data.max_response_length=700
  • trainer.test_freq=200(验证频率更低)
  • 动态更新未开启(Search脚本中没有enable_dynamic_update)

10. 关键参数调优指南

10.1 显存不足时

症状CUDA out of memorytorch.cuda.OutOfMemoryError

bash 复制代码
# 方案1:开启参数/优化器卸载到CPU(已默认开启)
actor_rollout_ref.actor.fsdp_config.param_offload=True
actor_rollout_ref.actor.fsdp_config.optimizer_offload=True

# 方案2:减小micro batch size
actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu=2    # 从4减到2

# 方案3:减小GRPO分组大小
env.rollout.n=4    # 从8减到4

# 方案4:降低vLLM显存占比
actor_rollout_ref.rollout.gpu_memory_utilization=0.3    # 从0.5减到0.3

# 方案5:减少GPU并行中的TP大小
actor_rollout_ref.rollout.tensor_model_parallel_size=2    # 从4减到2

10.2 训练不收敛时

症状:success_rate始终为0或持续震荡

bash 复制代码
# 方案1:降低学习率
actor_rollout_ref.actor.optim.lr=5e-7    # 从1e-6降到5e-7

# 方案2:调整KL系数
actor_rollout_ref.actor.kl_loss_coef=0.001    # 从0.01降到0.001

# 方案3:检查技能库是否生效
# 确保日志中出现:[SkillsOnlyMemory] Loaded skills: ...

# 方案4:增大训练epoch数
trainer.total_epochs=300    # 从150增到300

10.3 技能库不更新时

症状 :日志中没有 [SkillUpdate] 相关输出

复制代码
排查清单:
1. +env.skills_only_memory.enable_dynamic_update=True  是否设置?
2. export AZURE_OPENAI_API_KEY 和 AZURE_OPENAI_ENDPOINT 是否配置?
3. trainer.test_freq 是否设置?验证是否在运行?
4. success_rate 是否低于 update_threshold(0.4)?

10.4 小模型(1.5B)配置参考

bash 复制代码
# 针对1.5B模型的推荐参数
actor_rollout_ref.model.path=Qwen/Qwen2.5-1.5B-Instruct
actor_rollout_ref.actor.ppo_mini_batch_size=256
actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu=32
actor_rollout_ref.actor.fsdp_config.param_offload=False
actor_rollout_ref.actor.fsdp_config.optimizer_offload=False
actor_rollout_ref.rollout.tensor_model_parallel_size=2
actor_rollout_ref.rollout.gpu_memory_utilization=0.6
trainer.n_gpus_per_node=2

11. 常见问题排查

Q1: FileNotFoundError: Skills file not found

复制代码
原因:技能库JSON路径错误
解决:确保路径正确,使用绝对路径或相对于项目根目录的路径

Q2: EnvironmentError: SkillUpdater requires AZURE_OPENAI_API_KEY

复制代码
原因:开启了动态更新但未配置Azure API
解决方案A:配置API密钥
    export AZURE_OPENAI_API_KEY="..."
    export AZURE_OPENAI_ENDPOINT="..."
解决方案B:关闭动态更新
    +env.skills_only_memory.enable_dynamic_update=False

Q3: KeyError: 'raw_prompt'

复制代码
原因:缺少 data.return_raw_chat=True
解决:确保启动命令中包含 data.return_raw_chat=True

Q4: real_train_batch_size must be divisible by total n_gpus

复制代码
原因:train_batch_size * rollout.n 不能被GPU总数整除
解决:调整 train_batch_size 或 env.rollout.n
例如:4卡GPU → train_batch_size=16, rollout.n=8 → 16*8=128, 128/4=32 ✓

Q5: 训练启动后长时间无输出

复制代码
可能原因:
1. Worker初始化中(加载模型到多GPU,可能需要5-10分钟)
2. 数据预处理中(filter_overlong_prompts)
3. Ray调度等待中

排查:查看Ray dashboard(通常在 http://127.0.0.1:8265)

Q6: SIGSEGV 段错误

复制代码
常见原因:vLLM与flash-attn版本不兼容
解决:
    pip install vllm==0.11.0
    pip install flash-attn==2.7.4.post1 --no-build-isolation --no-cache-dir

Q7: 验证时OOM但训练时不OOM

复制代码
原因:验证时 val_batch_size=64 可能远大于 train_batch_size=16
解决:
1. 减小 val_batch_size:data.val_batch_size=32
2. 减小验证并行度:actor_rollout_ref.rollout.val_kwargs.n=1

12. 关键文件速查表

用途 文件路径
RL训练入口 verl/trainer/main_ppo.py
默认配置文件 verl/trainer/config/ppo_trainer.yaml
主训练循环 verl/trainer/ppo/ray_trainer.pyfit() (line 1209)
验证+技能更新 verl/trainer/ppo/ray_trainer.py_validate() (line 689)
GRPO算法 verl/trainer/ppo/core_algos.py
多轮交互循环 agent_system/multi_turn_rollout/rollout_loop.py
技能库(Template Mode) agent_system/memory/skills_only_memory.py
动态技能生成器 agent_system/memory/skill_updater.py
环境管理器 agent_system/environments/env_manager.py
Episode奖励 agent_system/reward_manager/episode.py
数据集加载 verl/utils/dataset/rl_dataset.py
数据预处理 examples/data_preprocess/prepare.py
ALFWorld启动脚本 examples/grpo_trainer/run_alfworld_skills.sh
WebShop启动脚本 examples/grpo_trainer/run_webshop_skills.sh
Search启动脚本 examples/grpo_trainer/run_search_skills.sh
ALFWorld技能库 memory_data/alfworld/claude_style_skills.json
WebShop技能库 memory_data/webshop/claude_style_skills.json
Search技能库 memory_data/search/claude_style_skills_search.json
技能生成脚本 skill_generation/alfworld.py / webshop.py / search.py
相关推荐
RoboWizard1 小时前
DIY移动硬盘?2230能否堪大任!
数据库·人工智能·智能手机·性能优化·负载均衡
CITY_OF_MO_GY1 小时前
DFlash:用块扩散模型打破推测解码的加速天花板
人工智能
Acrel150003531381 小时前
安科瑞 EMS3.0智慧能源管理解决方案-光伏智维先知引擎,AI驱动预测性维护新范式
人工智能
covco1 小时前
星链引擎矩阵系统:多模型融合调度与统一 AI 能力中台技术实践
人工智能·矩阵·多模型融合
啦啦啦_99991 小时前
机器学习 总结1
人工智能·机器学习
渡我白衣1 小时前
定时器与时间轮思想
linux·开发语言·前端·c++·人工智能·深度学习·神经网络
Marry Andy1 小时前
Atlas 800T A2部署qwen3-32b
linux·人工智能·语言模型·自然语言处理
拓朗工控1 小时前
工业视觉检测:从像素到决策的智能制造之眼
人工智能·视觉检测·制造·工控机·工业电脑
互联网江湖1 小时前
腾讯的船“漏水”了,可灵AI会成为“补丁”吗?
大数据·人工智能