RL阶段操作手册 - Template Mode 技能增强强化学习
本手册是SFT训练完成后,启动RL强化学习阶段的逐步操作指南。
目录
- 前置检查清单
- [Step 1:准备技能库JSON文件](#Step 1:准备技能库JSON文件)
- [Step 2:准备训练数据(Parquet)](#Step 2:准备训练数据(Parquet))
- [Step 3:配置环境变量](#Step 3:配置环境变量)
- [Step 4:启动RL训练](#Step 4:启动RL训练)
- [Step 5:监控训练过程](#Step 5:监控训练过程)
- [Step 6:检查产出与模型保存](#Step 6:检查产出与模型保存)
- [Step 7:恢复中断的训练](#Step 7:恢复中断的训练)
- 三个环境的完整命令
- 关键参数调优指南
- 常见问题排查
- 关键文件速查表
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/AlfredTWEnvenv.max_steps=50(每episode最多50步交互)env.rollout.n=8(GRPO分组8条轨迹)data.max_prompt_length=4096data.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=Webshopenv.max_steps=15(WebShop步数更少)data.max_prompt_length=6000(WebShop页面内容更长)data.max_response_length=768data.truncation='left'(左侧截断)actor_rollout_ref.rollout.gpu_memory_utilization=0.7trainer.n_gpus_per_node=8
9.3 Search
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=searchenv.max_steps=4(搜索只需几步)env.rollout.n=4(GRPO分组更小)env.history_length=4env.search.search_url='http://127.0.0.1:8030/retrieve'data.train_files=$HOME/data/searchR1_processed_direct/train.parquet(独立数据)data.max_prompt_length=5000data.max_response_length=700trainer.test_freq=200(验证频率更低)- 动态更新未开启(Search脚本中没有enable_dynamic_update)
10. 关键参数调优指南
10.1 显存不足时
症状 :CUDA out of memory 或 torch.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.py → fit() (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 |