跳到主要内容 Llama-3 接入 verl 框架的强化学习训练实践 | 极客日志
Python AI 算法
Llama-3 接入 verl 框架的强化学习训练实践 将 Llama-3 模型接入 verl 框架进行强化学习后训练的完整流程。内容包括环境安装与依赖配置,针对 Llama-3 的 tokenizer 和 chat template 处理,基于 GRPO 算法的训练脚本配置,自定义奖励函数实现以控制生成质量,以及常见问题的排查方案如 OOM 和生成循环。最后提供了将 verl 分布式 checkpoint 转换为 HuggingFace 标准格式的方法,便于后续部署使用。
DockerOne 发布于 2026/4/6 更新于 2026/4/17 6 浏览Llama-3 接入 verl 框架的强化学习训练实践
1. 引言:为何选择 verl 进行 LLM 后训练
大型语言模型(LLM)在完成预训练后,通常需要通过**后训练(post-training)**进一步适配特定任务或行为目标。这一阶段主要包括监督微调(SFT)和强化学习人类反馈(RLHF 或其变体),是实现模型对齐的关键环节。
当前主流的 post-training 框架包括 trl、LLaMA-Factory 和 。其中, 是由字节跳动火山引擎团队开源的一个高效、灵活且面向生产环境的强化学习训练框架,专为大模型后训练设计,并作为 HybridFlow 论文的开源实现,具备显著优势:
verl
verl
支持多样化的 RL 算法(如 PPO、GRPO)
与 PyTorch FSDP、Megatron-LM、vLLM 等现代分布式框架无缝集成
提供模块化 API,易于扩展和定制
具备高效的 3D-HybridEngine 实现,优化通信与内存使用
原生支持 HuggingFace 模型生态
本文将重点介绍如何将 Llama-3 系列模型 成功接入 verl 框架,完成基于 GRPO 的强化学习训练流程,涵盖环境配置、参数调整、自定义奖励函数及模型导出等关键步骤,提供可落地的工程实践指南。
2. 环境准备与 verl 安装验证
2.1 安装 verl 及依赖项 首先,建议从源码安装 verl,以便后续进行代码修改和调试:
git clone https://github.com/volcengine/verl && cd verl pip install -e .
为了确保 Llama-3 能够顺利加载并运行,需安装以下关键依赖包(推荐版本):
torch==2.4.0+cu124 transformers==4.47.1 accelerate==0.33.0 peft==0.14.0 vllm==0.5.4 flash-attn==2.5.9.post1 ray==2.42.1 omegaconf==2.3.0 hydra-core==1.3.2 datasets==2.20.0 wandb==0.16.3
注意 :若使用 vLLM 进行推理加速,请提前设置环境变量:
export VLLM_ATTENTION_BACKEND=XFORMERS
2.2 验证安装是否成功 import verl
print (verl.__version__)
若能正常输出版本号(如 0.1.0),则说明安装成功。
3. 将 Llama-3 接入 verl 的核心配置
3.1 数据格式与 tokenizer 处理 Llama-3 使用特殊的 chat template(<|begin_of_sentence|> 等特殊 token),因此必须正确配置 tokenizer 行为。
修改 tokenizer 初始化逻辑 在 verl 中,默认 tokenizer 加载方式可能无法识别 Llama-3 的模板。建议在配置文件中显式指定:
actor_rollout_ref:
model:
path: meta-llama/Meta-Llama-3-8B-Instruct
trust_remote_code: True
override_config: {}
enable_gradient_checkpointing: True
use_remove_padding: False
同时,在数据处理部分启用 chat template 自动填充:
data:
chat_template: "llama-3"
prompt_key: "prompt"
max_prompt_length: 512
max_response_length: 1024
若 verl 不原生支持 "llama-3" 模板,可在 verl/data/utils.py 中添加如下注册逻辑:
from transformers import AutoTokenizer
def get_chat_template (tokenizer_name_or_path ):
if "llama-3" in tokenizer_name_or_path.lower():
return {
"chat_template" : "{% for message in messages %}{{'<|start_header_id|>' + message['role'] + '<|end_header_id|>\n\n' + message['content'] + '<|eot_id|>'}}{% endfor %}{% if add_generation_prompt %}{{ '<|start_header_id|>assistant<|end_header_id|>\n\n' }}{% endif %}"
}
return None
3.2 配置 GRPO 训练脚本(以 Llama-3-8B 为例) 创建 grpo_llama3.yaml 配置文件,内容如下:
data:
train_files: ~/data/gsm8k/train.parquet
val_files: ~/data/gsm8k/test.parquet
prompt_key: prompt
max_prompt_length: 512
max_response_length: 1024
train_batch_size: 1024
val_batch_size: 1312
shuffle: true
actor_rollout_ref:
hybrid_engine: true
model:
path: meta-llama/Meta-Llama-3-8B-Instruct
trust_remote_code: true
enable_gradient_checkpointing: true
use_remove_padding: false
actor:
strategy: fsdp
ppo_mini_batch_size: 256
ppo_micro_batch_size_per_gpu: 1
ppo_max_token_len_per_gpu: 16384
grad_clip: 1.0
clip_ratio: 0.2
entropy_coeff: 0.001
use_kl_loss: true
kl_loss_coef: 0.001
kl_loss_type: low_var_kl
ppo_epochs: 1
optim:
lr: 5e-7
lr_warmup_steps_ratio: 0.1
warmup_style: cosine
fsdp_config:
wrap_policy:
min_num_params: 0
param_offload: false
optimizer_offload: false
ref:
fsdp_config:
param_offload: false
wrap_policy:
min_num_params: 0
rollout:
name: vllm
temperature: 0.7
top_p: 0.95
dtype: bfloat16
gpu_memory_utilization: 0.8
enforce_eager: true
free_cache_engine: true
load_format: dummy_dtensor
tensor_model_parallel_size: 2
max_num_batched_tokens: 8192
max_num_seqs: 1024
n: 8
enable_chunked_prefill: true
critic: null
reward_model:
enable: false
algorithm:
gamma: 1.0
lam: 1.0
adv_estimator: grpo
kl_penalty: kl
kl_ctrl:
type: fixed
kl_coef: 0.001
trainer:
total_epochs: 3
project_name: llama3-grpo-finetune
experiment_name: gsm8k-v1
logger: ['console' ]
nnodes: 1
n_gpus_per_node: 8
default_local_dir: ./checkpoints/llama3-grpo
save_freq: 100
resume_mode: auto
4. 自定义 Reward 函数:提升训练可控性
4.1 实现 CustomRewardManager 由于 GRPO 不依赖外部 reward model,我们可以通过编写自定义奖励管理器来控制生成质量。
在 verl/workers/reward_manager/custom_reward.py 中新增:
from verl import DataProto
import torch
class LengthBonusRewardManager :
"""鼓励更长、结构完整的回答"""
def __init__ (self, tokenizer, num_examine=5 ) -> None :
self .tokenizer = tokenizer
self .num_examine = num_examine
self .print_counter = 0
def __call__ (self, data: DataProto ):
reward_tensor = torch.zeros_like(data.batch['responses' ], dtype=torch.float32)
for i in range (len (data)):
if self .print_counter < self .num_examine:
print (f"Sample {i} : Prompt and Response:" )
data_item = data[i]
prompt_ids = data_item.batch['prompts' ]
response_ids = data_item.batch['responses' ]
valid_prompt_len = data_item.batch['attention_mask' ][:prompt_ids.shape[-1 ]].sum ().item()
valid_response_len = data_item.batch['attention_mask' ][prompt_ids.shape[-1 ]:].sum ().item()
prompt_str = self .tokenizer.decode(prompt_ids[-valid_prompt_len:], skip_special_tokens=True )
response_str = self .tokenizer.decode(response_ids[:valid_response_len], skip_special_tokens=True )
if self .print_counter < self .num_examine:
print ("Prompt:" , prompt_str)
print ("Response:" , response_str)
self .print_counter += 1
length_score = len (response_str.split()) * 0.1
ends_with_punct = 1.0 if response_str.strip()[-1 ] in '.?!' else 0.0
final_score = length_score + ends_with_punct
reward_tensor[i, valid_response_len - 1 ] = final_score
return reward_tensor
并在 verl/workers/reward_manager/__init__.py 中注册:
from .custom_reward import LengthBonusRewardManager
__all__ = ['NaiveRewardManager' , 'LengthBonusRewardManager' ]
4.2 在配置中启用自定义 Reward 修改主配置文件中的 reward_manager 字段:
reward_manager: custom
custom_reward_class: LengthBonusRewardManager
if config.reward_manager == 'custom' :
from verl.workers.reward_manager.custom_reward import LengthBonusRewardManager
reward_manager = LengthBonusRewardManager(tokenizer=tokenizer, num_examine=5 )
else :
reward_manager = NaiveRewardManager(tokenizer=tokenizer, rm_model=None )
5. 启动训练与常见问题解决
5.1 启动命令 set -x
export VLLM_ATTENTION_BACKEND=XFORMERS
CONFIG_PATH="./configs/grpo_llama3.yaml"
python3 -m verl.trainer.main_ppo --config_path=$CONFIG_PATH
5.2 常见问题与解决方案
❌ 问题 1:vLLM 加载 Llama-3 报错'unknown model type' 原因 :vLLM 版本过低不支持 Llama-3 架构。
解决方案 :升级至 vLLM >= 0.5.4,并确认 HF 模型路径正确。
❌ 问题 2:FSDP 训练时 OOM 原因 :Llama-3-8B 显存占用高,batch size 设置过大。
降低 ppo_micro_batch_size_per_gpu 至 1
开启 enable_gradient_checkpointing
使用 bfloat16 精度
调整 gpu_memory_utilization: 0.7
❌ 问题 3:生成结果重复或陷入循环 原因 :temperature 设置过低或 top_p 过小。
rollout:
temperature: 0.7 ~1.0
top_p: 0.9 ~0.95
n: 8
6. 模型保存与 HuggingFace 格式转换
6.1 检查点结构说明 verl 默认保存的是包含优化器状态的完整 checkpoint,路径结构如下:
checkpoints/
└── llama3-grpo/
└── global_step_100/
└── actor/
├── model_world_size_8_rank_0.pt
├── model_world_size_8_rank_1.pt
...
6.2 转换为 HuggingFace 可加载格式 使用以下脚本将 FSDP 分片权重合并为标准 HF 格式:
import torch
from collections import defaultdict
from transformers import AutoConfig, AutoModelForCausalLM, AutoTokenizer
def convert_fsdp_to_hf (fsdp_ckpt_dir, hf_model_path, output_dir, step=100 , world_size=8 ):
state_dict = defaultdict(list )
ckpt_path = f"{fsdp_ckpt_dir} /global_step_{step} /actor"
for rank in range (world_size):
file_path = f"{ckpt_path} /model_world_size_{world_size} _rank_{rank} .pt"
print (f"Loading rank {rank} ..." )
shard = torch.load(file_path)
for k, v in shard.items():
state_dict[k].append(v.to_local())
merged_state_dict = {}
for k, v_list in state_dict.items():
merged_state_dict[k] = torch.cat(v_list, dim=0 )
config = AutoConfig.from_pretrained(hf_model_path)
model = AutoModelForCausalLM.from_config(config)
model.load_state_dict(merged_state_dict)
model.save_pretrained(output_dir, max_shard_size="10GB" )
tokenizer = AutoTokenizer.from_pretrained(hf_model_path)
tokenizer.save_pretrained(output_dir)
print (f"Model saved to {output_dir} " )
if __name__ == "__main__" :
convert_fsdp_to_hf(
fsdp_ckpt_dir="./checkpoints" ,
hf_model_path="meta-llama/Meta-Llama-3-8B-Instruct" ,
output_dir="./hf_checkpoints/llama3-grpo-step100" ,
step=100 ,
world_size=8
)
from transformers import pipeline
pipe = pipeline(
"text-generation" ,
model="./hf_checkpoints/llama3-grpo-step100" ,
device_map="auto" ,
torch_dtype=torch.bfloat16
)
7. 总结 本文系统介绍了如何将 Llama-3 系列模型 成功接入 verl 框架,完成基于 GRPO 的强化学习训练全流程。主要内容包括:
环境搭建 :正确安装 verl 及其依赖,特别是 vLLM 和 FlashAttention;
模型接入 :通过配置文件指定 Llama-3 路径,并处理其特有的 chat template;
训练配置 :合理设置 GRPO 参数,尤其是 n 采样数、KL 正则系数等;
自定义奖励 :实现 CustomRewardManager 来引导模型生成更高质量响应;
问题排查 :针对 OOM、生成异常等问题提供实用调参建议;
模型导出 :将 verl 的分布式 checkpoint 转换为 HuggingFace 标准格式,便于部署。
通过上述实践,开发者可以充分利用 verl 的高性能与灵活性,高效完成 Llama-3 等先进大模型的对齐训练任务,为实际应用场景提供强有力的支持。
微信扫一扫,关注极客日志 微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
RSA密钥对生成器 生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
Mermaid 预览与可视化编辑 基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online