Module:
rllm.trainer.unified_trainerUnifiedTrainer is the central orchestrator for backend-agnostic training in rLLM.
It manages the full training loop ā episode generation, data transformation, advantage
computation, policy updates, validation, and logging ā while delegating all
backend-specific operations to a pluggable BackendProtocol implementation.
This page contains the technical details of the unified trainer training loop.
Architecture overview
BackendProtocol interface (see backend protocol).
Entry points
There are two ways to start training:AgentTrainer (recommended for standard backends)
A convenience wrapper that selects the correct TrainerLauncher for the backend
string ("verl" or "tinker") and handles environment setup.
UnifiedTrainer (direct, for custom backends)
When using a custom backend class, instantiate the trainer directly:
TrainerState
A mutable dataclass that serves as the shared context between the trainer and the
backend throughout a training step. It is reset at the start of each batch via
reset_batch().
has_episodes, has_trajectory_groups, has_backend_batch
ā used by the trainer to detect early-return conditions (e.g. all episodes filtered).
Initialization sequence
When theUnifiedTrainer is constructed, the following happens in order:
The workflow pool initialization (
initialize_pool) happens when fit_async() starts, not in the constructor.
Training loop
Callingtrainer.fit() runs fit_async() via asyncio.run(...). The high-level
flow:
Training loop diagram
Training loop diagram
If
val_before_train=true and val_only=true, training returns after initial validation and does not enter _fit_async().The 8-stage batch pipeline
Each call to_train_batch_async executes the following stages. Stages 1-3 are
framework-managed. Stages 4-7 are delegated to the backend.
Early returns: The pipeline returns early (skipping stages 4-8) if no episodes
are generated in stage 1, or if all trajectory groups are filtered out in stage 3.
The lifecycle hooks (
on_batch_end, logger.log) still execute even after an early
return.
Validation loop
Validation is triggered:- Before training (if
config.rllm.trainer.val_before_trainis true) - Periodically during training (every
config.rllm.trainer.test_freqsteps) - After training completes (only when
test_freq > 0)
backend.generate_episodes(..., is_validation=True),
transforms the results, and computes reward metrics (no advantage computation or
policy updates). Pass@1 and pass@K metrics are computed per data source and logged.
The backend can control validation via hooks:
on_validation_startreturns aboolā returnFalseto skip validation entirelyon_validation_endis called when validation actually runs (i.e. not skipped)
Configuration
The trainer reads configuration fromconfig.rllm (the rLLM sub-config within the
full Hydra config). Key config groups:
For the full configuration reference, see configuration.
AlgorithmConfig fields
Async design
The trainer uses an async-prioritized design:fit()is the sync entry point and runsfit_async()viaasyncio.run(...)fit_async()is available directly if you are already in an async context- The pipeline mixes async and sync steps:
- async:
generate_episodes,process_backend_batch,compute_advantages,update_policy - sync: transformation/rejection-sampling steps, dataloader access, logging, visualization
- async:
Shutdown
Always calltrainer.shutdown() when done (or use a try/finally block). This:
- Shuts down the workflow engine
- Calls
backend.shutdown()for backend-specific cleanup - Calls
logger.finish()to flush and close the tracking backend (e.g. wandb)

