常见问题(FAQ)#

第一部分:参数配置#

Q: 如何编写 Trinity-RFT 的配置文件?

A: 推荐使用 Trinity Studio 进行配置文件编写。你可以通过以下命令启动:

trinity studio --port 8080

该指令提供一个直观易用的图形化界面来创建和修改配置文件。

对于进阶用户,建议参考配置文档以了解所有配置项的详细说明。你也可以直接编辑 YAML 配置文件(可参考 examples 目录下的模板和示例)。

如果你已经熟悉 veRL,请参考与 veRL 对齐配置。该教程介绍了如何将 Trinity-RFT 的配置参数与 veRL 对齐,方便迁移或复用已有的 veRL 配置。


Q: buffer.batch_sizebuffer.train_batch_sizeactor_rollout_ref.actor.ppo_micro_batch_size_per_gpu 及其他 batch size 参数之间的关系?

A: 这些参数的关系如下:

  • buffer.batch_size:一个 mini-batch 中的任务(task)数量,对 explorer 有效。

  • buffer.train_batch_size:一个 mini-batch 中的 experience 数量,对 trainer 有效。如果未显式指定,则默认为 buffer.batch_size * algorithm.repeat_times

  • actor_rollout_ref.actor.ppo_mini_batch_size:一个 mini-batch 中的 experience 数量,会被 buffer.train_batch_size 覆盖;但在 update_policy 函数中,其值表示每个 GPU 上的 mini-batch experience 数量,即 buffer.train_batch_size (/ ngpus_trainer)。除以 ngpus_trainer 是由于数据隐式分配到多个 GPU 上所致,但在梯度累积后不影响最终结果。

  • actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu:每个 GPU 上 micro-batch 中的 experience 数量。

一个简要示例:

def update_policy(batch_exps):
    dataloader = batch_exps.split(ppo_mini_batch_size)
    for _ in range(ppo_epochs):
        for batch_idx, data in enumerate(dataloader):
            # 分割数据
            mini_batch = data
            if actor_rollout_ref.actor.use_dynamic_bsz:
                micro_batches, _ = rearrange_micro_batches(
                        batch=mini_batch, max_token_len=max_token_len
                    )
            else:
                micro_batches = mini_batch.split(actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu)

            # 计算梯度
            for data in micro_batches:
                entropy, log_prob = self._forward_micro_batch(
                    micro_batch=data, ...
                )
                pg_loss, pg_clipfrac, ppo_kl, pg_clipfrac_lower = compute_policy_loss(
                    log_prob=log_prob, **data
                )
                policy_loss = pg_loss + ...
                loss = policy_loss / self.gradient_accumulation
                loss.backward()

            # 优化器更新
            grad_norm = self._optimizer_step()
    self.actor_optimizer.zero_grad()

详细实现请参考 trinity/trainer/verl/dp_actor.py。veRL 也在其 FAQ 中对此进行了说明。

第二部分:常见报错#

报错:

File ".../flash_attn/flash_attn_interface.py", line 15, in ‹module>
    import flash_attn_2_cuda as flash_attn_gpu
ImportError: ...

A: flash-attn 模块未正确安装。请尝试运行 pip install flash-attn==2.8.1pip install flash-attn==2.8.1 -v --no-build-isolation 进行修复。


报错:

UsageError: api_key not configured (no-tty). call wandb.login(key=[your_api_key]) ...

A: 请在启动 Ray 和运行实验前先登录 WandB。可以通过 export WANDB_API_KEY=[your_api_key] 设置环境变量。你也可以通过设置 monitor.monitor_type=tensorboard/mlflow 使用其他监控方式。


报错:

ValueError: Failed to look up actor with name 'explorer' ...

A: 请确保在运行实验前已启动 Ray。如果 Ray 已在运行,可通过以下命令重启:

ray stop
ray start --head

报错: 内存不足(OOM)错误

A: 可尝试调整以下参数:

  • 对于 trainer,当 trainer.use_dynamic_bsz=false 时,调整 trainer.max_token_len_per_gpu;当 trainer.use_dynamic_bsz=true 时,调整 trainer.ppo_max_token_len_per_gputrainer.ulysses_sequence_parallel_size。设置 trainer.trainer_config.actor_rollout_ref.actor.entropy_from_logits_with_chunking=true 也可能有帮助。

  • 对于 explorer,调整 explorer.rollout_model.tensor_parallel_size

此外,Trinity-RFT 提供了GPU 相关配置指南,可参考其中建议。

第三部分:调试方法#

Q: Trinity-RFT 运行日志在哪查看?

A: Trinity-RFT 支持 actor 级别日志,会自动将每个 actor(如 explorer 和 trainer)的日志保存到 <checkpoint_job_dir>/log/<actor_name>

常见日志包括:

  • <checkpoint_job_dir>/log/explorer.log:explorer 进程日志,包括每步起止时间、评测指标、模型权重同步、异常等。

  • <checkpoint_job_dir>/log/trainer.log:trainer 进程日志,包括每次训练迭代的起止时间、评测指标、模型权重同步等。

  • <checkpoint_job_dir>/log/explorer_runner_<n>.log:workflow runner 进程日志,包括 workflow 打印的日志和运行异常(需在 Workflow 中用 self.logger 打印日志)。

如需更详细日志,可在配置文件中设置 log.level=debug

如需查看所有进程的完整日志并保存到 debug.log

export RAY_DEDUP_LOGS=0
trinity run --config grpo_gsm8k/gsm8k.yaml 2>&1 | tee debug.log

Q: 如何在不运行完整实验的情况下调试 workflow?

A: 可用 Trinity-RFT 的 debug 模式,步骤如下:

  1. 启动推理模型:

    trinity debug --config <config_file_path> --module inference_model
    
  2. 在另一个终端调试 workflow:

    trinity debug --config <config_file_path> --module workflow --output-file <output_file_path> --plugin-dir <plugin_dir>
    

详细说明见 工作流开发指南

第四部分:其他问题#

Q: buffer.trainer_input.experience_buffer.path 有什么作用?

A: 该路径指定用于存储生成 experience 的 SQLite 数据库路径。如果不需要,可注释掉该行。

如需查看数据库中的 experience,可用如下 Python 脚本:

from sqlalchemy import create_engine
from sqlalchemy.exc import OperationalError
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import NullPool
from trinity.common.schema.sql_schema import ExperienceModel

engine = create_engine(buffer.trainer_input.experience_buffer.path)
session = sessionmaker(bind=engine)
sess = session()

MAX_EXPERIENCES = 4
experiences = (
    sess.query(ExperienceModel)
    .limit(MAX_EXPERIENCES)
    .all()
)

exp_list = []
for exp in experiences:
    exp_list.append(ExperienceModel.to_experience(exp))

# 打印 experience
for exp in exp_list:
    print(f"{exp.prompt_text=}", f"{exp.response_text=}")

Q: 如何在 Trinity-RFT 框架外加载 checkpoints?

A: 你需要指定模型路径和检查点路径。以下代码片段展示了如何使用 transformers 库进行加载。

以下是加载 FSDP trainer 检查点的示例:

import os
from transformers import AutoTokenizer, AutoModelForCausalLM
from trinity.common.models.utils import load_fsdp_state_dict_from_verl_checkpoint

# 假设我们需要第 780 步的检查点;
# model_path、checkpoint_root_dir、project 和 name 已定义
model = AutoModelForCausalLM.from_pretrained(model_path)
ckp_path = os.path.join(checkpoint_root_dir, project, name, "global_step_780", "actor")
model.load_state_dict(load_fsdp_state_dict_from_verl_checkpoint(ckp_path))

Q: Trinity-RFT 和 veRL 有什么区别?

A: Trinity-RFT 以 veRL 作为 trainer 后端,并在其基础上扩展了更模块化和灵活的架构。主要区别包括:

  • 模块化算法:Trinity-RFT 将 veRL core_algos.py 中的算法相关组件(如优势函数、损失函数)提取为独立模块,便于用户实现和注册新算法,无需修改核心代码。

  • Explorer 与 Trainer 分离:Trinity-RFT 用独立 Explorer 模块替代 veRL 的 rollout model,专门负责 agent 与环境交互,支持更灵活的 workflow 设计和 rollout-training 调度。

  • 全生命周期数据通路:Trinity-RFT 在 Explorer 和 Trainer 之间增加 Buffer 模块,提供完整的数据存储、处理和采样通路,支持经验回放、优先采样等高级数据处理策略。

我们还提供了 Trinity-RFT 与 veRL 及其衍生系统(如 rLLM)的基准对比,详见 Benchmark