FlowGRPO Trainer
Last updated: 07/18/2026
This example shows how to post-train Qwen-Image with FlowGRPO on an OCR-style image generation task using vllm-omni rollout and a visual generative reward model (Qwen3-VL-8B-Instruct in this example).
For the full installation and quickstart guide, see Quickstart: FlowGRPO training on OCR dataset. For algorithm details and rule-based reward training (e.g. JPEG incompressibility), see Algorithms - Flow-GRPO.
Installation
Follow the installation guide to set up the base environment, then install the FlowGRPO-specific dependency:
pip install Levenshtein
The provided script is configured for a single node with 4 GPUs.
Prepare the dataset
Obtain the raw OCR dataset from the original Flow-GRPO repository:
https://github.com/yifan123/flow_grpo/tree/main/dataset/ocr
Place the raw dataset under $WORKSPACE/data/ocr (where WORKSPACE defaults to $HOME), then preprocess it into parquet files:
python3 examples/flowgrpo_trainer/data_process/qwenimage_ocr.py \
--input_dir $WORKSPACE/data/ocr \
--output_dir $WORKSPACE/data/ocr/qwen_image
This produces:
$WORKSPACE/data/ocr/qwen_image/train.parquet$WORKSPACE/data/ocr/qwen_image/test.parquet
Prepare the models
Policy model (Qwen-Image): the script uses the Hugging Face Hub ID Qwen/Qwen-Image directly — no manual download is required. Hugging Face will cache the weights automatically on first run. To use a local copy instead, edit the model_name variable in the script directly.
Reward model (Qwen3-VL-8B-Instruct): the script defaults to the Hugging Face Hub ID Qwen/Qwen3-VL-8B-Instruct, so no manual download is required — Hugging Face will cache it automatically on first run. To use a local copy instead, edit the reward_model_name variable in the script directly.
Run training
Launch the example from the repository root:
bash examples/flowgrpo_trainer/qwen_image/run_qwen_image_ocr_lora.sh
GPU training defaults to matched kernels FA3 in config (attn_backend: _flash_3_varlen_hub;
rollout_attn_backend: FLASH_ATTN_3_HUB). Training falls back to native/SDPA if FA3 deps
are unavailable.
Optional KL loss tuning:
actor_rollout_ref.actor.use_kl_loss=Trueactor_rollout_ref.actor.kl_loss_coef=0.001
The script runs python3 -m verl_omni.trainer.main_diffusion with:
algorithm.adv_estimator=flow_grpoactor_rollout_ref.model.path=Qwen/Qwen-Imageactor_rollout_ref.model.lora_rank=64actor_rollout_ref.model.lora_alpha=128actor_rollout_ref.rollout.name=vllm_omnireward.custom_reward_function.name=compute_score_ocrtrainer.n_gpus_per_node=4
Logging
W&B logging is enabled by default in the example script:
export WANDB_API_KEY=<your_wandb_api_key>
The script sets:
trainer.logger='["console", "wandb"]'
trainer.project_name=flow_grpo
trainer.experiment_name=qwen_image_ocr_lora
Override these values on the command line if you want to log under a different project or run name.
Diffusion-specific metrics
See the Metrics Documentation for a full description of all diffusion-specific training metrics.
Variants
All example scripts in this directory:
Qwen-Image
Variant |
Script |
GPUs |
Notes |
|---|---|---|---|
LoRA (baseline) |
|
4×GPU |
Standard LoRA FlowGRPO + OCR reward |
LoRA + async reward |
|
5×GPU |
Dedicated GPU pool for reward model |
LoRA + SP=2 |
|
4×GPU |
Ulysses sequence parallelism |
LoRA + FA3 |
|
4×GPU |
FSDP2 with FlashAttention 3 |
LoRA + rollout corr |
|
4×GPU |
Bypass old-log-prob recompute |
LoRA + multi-node |
|
2×4 GPU |
Horizontal scaling across nodes |
LoRA + NPU |
|
8×NPU |
Ascend NPU LoRA training |
Full model |
|
4×H200 |
Non-CFG full-weight training |
Full + FSDP2 64-card |
|
64×GPU |
Large-scale FSDP2 |
Full + VeOmni |
|
64×H100 |
VeOmni engine backend |
Full + VeOmni 64-card |
|
64×GPU |
VeOmni at scale |
Full + H200 MFU opt |
|
H200 |
MFU-optimized config |
Full + NPU |
|
16×NPU |
Ascend NPU full model |
HTTP reward server |
|
4×GPU |
External HTTP OCR reward service |
Multi-reward |
|
4×GPU |
Multiple reward functions combined |
Stable Diffusion 3.5 Medium
Variant |
Script |
GPUs |
Notes |
|---|---|---|---|
LoRA |
|
3×GPU |
2 actor+rollout, 1 reward pool |
LTX-2.3
Variant |
Script |
GPUs |
Notes |
|---|---|---|---|
T2AV LoRA |
|
8×GPU |
Joint audio-video CPS, CLAP + ImageBind rewards |
BAGEL
Variant |
Script |
GPUs |
Notes |
|---|---|---|---|
LoRA (OCR) |
|
4×GPU |
OCR reward (Qwen3-VL) |
LoRA (PickScore) |
|
4×GPU |
CLIP-based image-text alignment |
Engine backends
The diffusion trainer defaults to FSDP2. To use VeOmni instead, follow the VeOmni install instructions, then run the VeOmni counterpart:
bash examples/flowgrpo_trainer/qwen_image/run_qwen_image_ocr_veomni.sh
run_qwen_image_ocr_veomni.sh mirrors run_qwen_image_ocr.sh and differs only in engine-selection overrides:
Override |
FSDP2 (default) |
VeOmni |
|---|---|---|
|
(unset; uses |
|
|
|
|
Actor engine config block |
|
|
Sequence-parallel field |
|
|
Ref engine config block |
|
|
Do not mix fsdp_config and veomni_config overrides — diffusion/model_engine=... selects the schema, and overrides for the other engine are rejected.
Performance
All experiments were conducted on NVIDIA H800 GPUs using the OCR reward.
The experiment settings and throughputs are shown in the table below.
Script |
Model |
Algorithm |
Hybrid Engine |
# Cards |
Reward Fn |
# GPUs for Actor |
# GPUs for Rollout |
# GPUs for Async Reward |
Batch Size |
|
lr |
# Val Samples |
Training Samples per Step |
|
Throughput (Samples / GPU / Seconds) |
Time per Step (Seconds) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Qwen-Image |
Flow-GRPO |
True |
4 |
qwenvl-ocr-vllm |
4 |
4 |
0 (sync) |
32 |
16 |
3e-4 |
1k (full set) |
32×16=512 |
16 |
0.305 |
420 |
|
Qwen-Image |
Flow-GRPO |
True |
5 |
qwenvl-ocr-vllm |
4 |
4 |
1 |
32 |
16 |
3e-4 |
1k (full set) |
32×16=512 |
16 |
0.280 |
360 |
Validation reward curve (evaluated with
trainer.val_before_train=True):
qwen_image_ocr_lora: corresponding with the script `examples/flowgrpo_trainer/qwen_image/run_qwen_image_ocr_lora.sh`;
qwen_image_ocr_lora_async_reward: corresponding with the script `examples/flowgrpo_trainer/qwen_image/run_qwen_image_ocr_lora_async_reward.sh`.
Note: Reward curves may differ from the references above mainly due to rollout-side stochasticity: diffusion rollouts sample random latents/noise, and the example scripts do not fix the data seed, so prompt ordering can vary between runs.
Further Reading
For more examples of FlowGRPO training other models, see
Stable Diffusion: Quickstart: FlowGRPO training on OCR dataset
Image-to-image model: Examples - Qwen-Image-Edit-2511 FlowGRPO training
Unified image understanding and generation model: Examples - BAGEL-7B-MoT FlowGRPO training
To train a model with a latent reward model, see Examples - SD3.5 FlowGRPO training with a latent reward model.