news 2026/4/23 17:09:22

手把手教你用verl做LLM强化学习(附配置)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手把手教你用verl做LLM强化学习(附配置)

手把手教你用verl做LLM强化学习(附配置)

1. 引言:为什么选择 verl 做大模型强化学习?

你有没有遇到过这样的问题:想给大语言模型做一次强化学习训练,却发现流程复杂、代码难懂、框架封闭?trl 太黑盒,LLaMA-Factory 虽然灵活但对 RL 支持有限。这时候,一个真正为 LLM 后训练设计的高效、可扩展又生产就绪的框架就显得尤为重要。

今天要介绍的verl,正是这样一个“宝藏级”开源项目。它由字节跳动火山引擎团队推出,是其在HybridFlow论文中的完整实现,专为大型语言模型(LLMs)的后训练阶段打造,尤其擅长处理复杂的强化学习任务。

它的最大亮点是什么?
不是“支持 PPO”,而是——你可以只用几行代码,构建出高度定制化的 RL 数据流。无论是 GRPO、PPO 还是未来的新算法,都能轻松集成。

本文将带你从零开始,一步步部署 verl,完成一次完整的 GRPO 强化学习训练,并手把手教你如何修改配置、自定义奖励函数、保存模型。全程小白友好,不讲理论堆砌,只讲能落地的操作。


2. 环境准备与快速验证

2.1 安装 verl 框架

我们推荐将 verl 克隆到本地进行安装,这样后续修改源码更方便:

git clone https://github.com/volcengine/verl && cd verl pip3 install -e .

注意:-e参数表示“可编辑安装”,意味着你修改了本地代码后无需重新安装即可生效。

2.2 关键依赖版本建议

verl 对底层库有一定要求,以下是经过验证的稳定组合(适用于单机多卡环境):

torch==2.4.0+cu124 transformers==4.47.1 peft==0.14.0 vllm==0.5.4 flash-attn==2.5.9.post1 ray==2.42.1 numpy==1.26.4 pandas==2.2.3 omegaconf>=2.3.0 # Hydra 配置系统所需

建议使用 Conda 或 venv 创建独立虚拟环境,避免依赖冲突。

2.3 快速验证是否安装成功

进入 Python 环境,执行以下命令:

import verl print(verl.__version__)

如果输出类似0.1.0的版本号,说明安装成功!


3. SFT 训练实战:先打好基础

在开启强化学习之前,通常需要先做一个监督微调(SFT),让模型学会基本的任务格式。verl 提供了fsdp_sft_trainer.py来支持这一过程。

3.1 默认运行方式:脚本传参

官方示例中通过 shell 脚本传递参数,例如:

torchrun --standalone --nnodes=1 --nproc_per_node=8 \ -m verl.trainer.fsdp_sft_trainer \ data.train_files=$HOME/data/gsm8k/train.parquet \ model.partial_pretrain=Qwen/Qwen2.5-0.5B-Instruct \ optim.lr=1e-4 \ trainer.default_local_dir=./checkpoints/sft \ trainer.total_epochs=1

这种方式虽然灵活,但参数一多就容易混乱。更好的做法是——写成 YAML 配置文件

3.2 推荐做法:使用自定义 YAML 配置

打开verl/trainer/fsdp_sft_trainer.py,你会发现它是基于 Hydra 框架加载配置的:

@hydra.main(config_path='config', config_name='sft_trainer', version_base=None) def main(config): ...

这意味着默认读取的是verl/trainer/config/sft_trainer.yaml文件。我们可以复制这个文件,改名为sft_config.yaml,然后按需修改。

示例 sft_config.yaml 片段:
data: train_batch_size: 256 micro_batch_size_per_gpu: 4 train_files: /your/path/to/train.parquet val_files: /your/path/to/test.parquet prompt_key: question response_key: answer max_length: 1024 model: partial_pretrain: Qwen/Qwen2-7B-Instruct lora_rank: 32 lora_alpha: 16 target_modules: all-linear optim: lr: 1e-5 weight_decay: 0.01 trainer: default_local_dir: ./checkpoints/sft_qwen7b project_name: my_sft_exp experiment_name: qwen7b_grpo_ready total_epochs: 2 logger: ['console']

3.3 修改主函数以支持外部 YAML 文件

为了让程序接受外部配置路径,我们需要稍微改造一下main函数。注释掉原来的@hydra.main,改为手动加载 YAML:

import argparse from omegaconf import OmegaConf def load_config(config_path): return OmegaConf.load(config_path) def main(args): config = load_config(args.config_path) local_rank, rank, world_size = initialize_global_process_group() device_mesh = init_device_mesh('cuda', (world_size,), ('fsdp',)) dp_size = world_size // config.ulysses_sequence_parallel_size sp_mesh = init_device_mesh('cuda', (dp_size, config.ulysses_sequence_parallel_size), ('dp', 'sp')) trainer = FSDPSFTTrainer(config, device_mesh, sp_mesh) trainer.fit() if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('--config_path', type=str, required=True) args = parser.parse_args() main(args)

保存后,运行命令变得简洁清晰:

torchrun --nnodes=1 --nproc_per_node=8 \ -m verl.trainer.fsdp_sft_trainer \ --config_path ./configs/sft_config.yaml

3.4 小技巧:去掉验证环节

如果你只有训练集,不想跑 validation,可以找到fsdp_sft_trainer.py中的val_dataloader相关逻辑并注释掉,或者设置data.val_files=null并确保训练循环中跳过评估步骤。


4. GRPO 强化学习训练详解

SFT 完成后,就可以进入真正的强化学习阶段。这里我们以GRPO(Group Relative Policy Optimization)为例,展示如何使用 verl 实现高效的 RL 训练。

4.1 GRPO 是什么?简单说清楚

GRPO 不依赖外部奖励模型(RM),而是通过比较同一个 prompt 下多个生成结果之间的相对优劣来更新策略。比如模型生成了 8 条回答,其中某一条被人工标注为最优,那我们就鼓励模型向这条靠拢,同时拉开与其他回复的距离。

优点:

  • 无需训练额外的 Reward Model
  • 更适合偏好数据丰富但难以打分的场景
  • 训练更稳定

4.2 配置文件解析:ppo_trainer.yaml 关键字段

GRPO 的入口是verl/trainer/main_ppo.py,它加载的是ppo_trainer.yaml。下面我们重点解读几个核心模块。

(1)数据配置data
data: train_files: ~/data/gsm8k/train.parquet prompt_key: prompt max_prompt_length: 512 max_response_length: 1024 train_batch_size: 1024

注意:这里不需要response_key,因为 response 是由模型自己生成的。

(2)Actor & Rollout 配置

这是最关键的模块,控制策略模型的训练和推理行为。

actor_rollout_ref: model: path: Qwen/Qwen2-7B-Instruct actor: ppo_mini_batch_size: 256 ppo_micro_batch_size_per_gpu: 1 optim: lr: 1e-6 fsdp_config: wrap_policy: min_num_params: 0 rollout: name: vllm temperature: 1.0 top_p: 1.0 n: 8 # 每个 prompt 生成 8 个 response,用于 group 比较 dtype: bfloat16 gpu_memory_utilization: 0.8 tensor_model_parallel_size: 2

关键点:

  • n: 8表示每个 prompt 采样 8 条回复,构成一个 group
  • 使用vllm加速推理,提升 throughput
  • tensor_model_parallel_size应根据 GPU 显存调整
(3)Algorithm 设置 GRPO 模式
algorithm: adv_estimator: grpo kl_ctrl: type: fixed kl_coef: 0.001

只需把adv_estimator设为grpo,框架就会自动切换为 GRPO 损失计算逻辑。

(4)Reward Manager:决定怎么打分
reward_model: enable: False reward_manager: naive

由于我们不使用 RM,所以enable=False,评分交给naivemanager 处理——即根据数据集中提供的chosen_idx字段判断哪个 response 是最优的。


5. 自定义奖励函数:让你的模型更有“个性”

有时候你想让模型追求特定目标,比如“回答越长越好”、“尽量少用专业术语”。这时就需要自定义奖励函数

5.1 如何添加自定义 Reward Manager?

verl/workers/reward_manager/目录下新建custom_reward.py

from verl import DataProto import torch class LengthBasedRewardManager: def __init__(self, tokenizer, num_examine=2) -> None: self.tokenizer = tokenizer self.num_examine = num_examine def __call__(self, data: DataProto): reward_tensor = torch.zeros_like(data.batch['responses'], dtype=torch.float32) for i in range(len(data)): item = data[i] response_ids = item.batch['responses'] valid_len = item.batch['attention_mask'][item.prompt_length:].sum().item() decoded = self.tokenizer.decode(response_ids[:valid_len]) # 自定义奖励:长度越长得分越高 score = min(len(decoded) / 100, 5.0) # 上限 5 分 reward_tensor[i, valid_len - 1] = score return reward_tensor

别忘了在__init__.py中注册:

from .custom_reward import LengthBasedRewardManager __all__ = ['NaiveRewardManager', 'LengthBasedRewardManager']

5.2 在配置中启用自定义奖励

修改ppo_trainer.yaml

reward_model: enable: False reward_manager: custom # 注意这个名字要对应

并在代码中注入类映射(可在main_ppo.py初始化时添加):

if config.reward_model.reward_manager == 'custom': config.reward_model._target_ = 'verl.workers.reward_manager.custom_reward.LengthBasedRewardManager'

6. 模型保存与格式转换:导出 HuggingFace 可加载的 checkpoint

verl 默认保存的是包含优化器状态的 FSDP 格式检查点,不能直接用AutoModel.from_pretrained()加载。我们需要将其转换为标准 HF 格式。

6.1 转换脚本:fsdp_to_hf.py

import torch from transformers import AutoConfig, AutoModelForCausalLM, AutoTokenizer from collections import defaultdict import os def convert_fsdp_to_hf(fsdp_ckpt_dir, hf_model_path, output_dir, world_size=8): os.makedirs(output_dir, exist_ok=True) state_dict = defaultdict(list) # 收集所有 rank 的分片 for rank in range(world_size): ckpt_file = f"{fsdp_ckpt_dir}/model_world_size_{world_size}_rank_{rank}.pt" print(f"Loading {ckpt_file}") shard = torch.load(ckpt_file) for k, v in shard.items(): state_dict[k].append(v.to_local()) # 合并分布式张量 # 沿 dim=0 拼接 merged = {k: torch.cat(v, dim=0) for k, v in state_dict.items()} # 加载结构并注入权重 config = AutoConfig.from_pretrained(hf_model_path) model = AutoModelForCausalLM.from_config(config) model.load_state_dict(merged) model.save_pretrained(output_dir, max_shard_size="10GB") # 保存 tokenizer tokenizer = AutoTokenizer.from_pretrained(hf_model_path) tokenizer.save_pretrained(output_dir) print(f"Conversion completed. Saved to {output_dir}") if __name__ == "__main__": convert_fsdp_to_hf( fsdp_ckpt_dir="/path/to/global_step_50/actor", hf_model_path="/path/to/hf_model", # 原始 Qwen 路径 output_dir="/path/to/hf_checkpoint/global_step_50" )

运行后,你就可以像加载普通模型一样使用:

from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("/path/to/hf_checkpoint/global_step_50")

7. 总结:掌握 verl 的三大关键能力

通过本文的实践,你应该已经掌握了使用 verl 进行 LLM 强化学习的核心技能:

  1. 灵活配置:不再依赖繁琐的命令行参数,通过 YAML 文件统一管理训练配置,清晰易维护。
  2. 自定义扩展:无论是替换奖励函数还是新增训练逻辑,verl 的模块化设计让你可以自由拓展,真正实现“我的训练我做主”。
  3. 生产可用:支持 FSDP、vLLM、LoRA 等工业级特性,具备高吞吐、低通信开销的优势,适合真实业务场景部署。

verl 的强大之处在于它的“灵活性 + 高性能”双重基因。它不像 trl 那样封闭,也不像一些实验性框架那样难以落地。只要你愿意动手改几行代码,就能让它为你所用。

下一步你可以尝试:

  • 结合自己的数据集跑通全流程
  • 实现基于规则或轻量模型的 reward function
  • 尝试 PPO + RM 的组合模式
  • 多机训练扩展

只要迈出第一步,后面的路会越来越顺。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 14:23:12

生产级RL框架怎么选?verl的三大核心优势告诉你

生产级RL框架怎么选?verl的三大核心优势告诉你 在大模型时代,强化学习(RL)已成为提升语言模型推理能力、对齐人类意图的关键技术。然而,传统的RL训练系统往往面临效率低、扩展难、调试复杂等问题,尤其在处…

作者头像 李华
网站建设 2026/4/23 8:27:30

Python日志实战:从零构建电商系统日志模块

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个电商系统日志模块,包含:1. 用户行为日志(登录、浏览、购买) 2. 订单处理日志 3. 支付异常监控 4. 性能指标记录。要求&…

作者头像 李华
网站建设 2026/4/23 8:27:24

DS4Windows实战:在PC上完美使用PS5手柄玩Steam游戏

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个详细的配置指南应用,展示如何在DS4Windows中设置PS5手柄玩《艾尔登法环》。包含以下内容:1) 基础按键映射设置 2) 陀螺仪瞄准配置 3) 触控板自定义…

作者头像 李华
网站建设 2026/4/23 8:26:39

零基础学C指针:从困惑到精通的AI指南

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个面向初学者的C语言指针交互式学习应用,包含:1. 指针概念的图形化解释 2. 分步骤的代码示例(从简单到复杂) 3. 交互式练习和即时反馈 4. 常见错误及…

作者头像 李华
网站建设 2026/4/23 8:25:37

新手必看:如何快速解决‘项目未找到‘错误

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 创建一个新手友好的错误解决指南应用,针对THE PROJECT YOU WERE LOOKING FOR COULD NOT BE FOUND OR YOU DONT HAVE PERMIS错误。应用功能:1. 分步错误解决…

作者头像 李华
网站建设 2026/4/23 8:25:17

1小时搭建X64环境:快马平台极速原型开发

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 构建一个X64开发环境快速配置工具,自动完成编译器设置、库依赖安装和测试框架部署。支持生成Hello World示例到多线程应用的不同复杂度模板。集成性能监测工具&#xf…

作者头像 李华