Skip to content

feat: add MiniMax H3 t2va Flow-GRPO support - #154

Open
niehen6174 wants to merge 8 commits into
radixark:mainfrom
niehen6174:feat/minimax-h3
Open

feat: add MiniMax H3 t2va Flow-GRPO support#154
niehen6174 wants to merge 8 commits into
radixark:mainfrom
niehen6174:feat/minimax-h3

Conversation

@niehen6174

@niehen6174 niehen6174 commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add MiniMax H3 t2va Flow-GRPO training (LoRA + LoRA-IPC) against sglang-diffusion rollout.
  • Pin diffusers to the main commit that merged H3 (not in a release yet).
  • Add 2-GPU recipe: scripts/run_diffusion_grpo_h3_t2va_2gpu.py.
  • Small prerequisites H3 exposed: modular-pipeline component specs, lazy num_train_timesteps, LoRA test fixture sglang_tp_size.

H3-specific bits (sampling target, SDE scorer, LoRA name/layout map) go through TrainPipelineConfig hooks instead of if family == "h3" in generic code.

Dependencies

  1. diffusers — from this PR’s requirements.txt (git pin f53d5520). Force-reinstall if pip keeps an older wheel:
    pip install --force-reinstall -r requirements.txt
  2. sglang-diffusion H3 RLsgl-project/sglang#34365. Install that branch (or wait until it merges):
    pip install -e "python[all]"   # from the PR checkout
    export PYTHONPATH=/path/to/sglang/python:$PYTHONPATH
  3. GPUs — at least 2 for the smoke/alignment path; more for the recommended batch=8 / group=16 scale. HF access to MiniMaxAI/MiniMax-H3, dataset rockdu/miles-diffusion-datasets (flowgrpo_pickscore; auto-downloaded by the recipe).

Reproduce

We only had 2 GPUs, so the long run used rollout_batch_size=4, n_samples_per_prompt=16. That is enough to train, but the GRPO group is smaller than we would like. rollout_batch_size=8 / group 16 is the better recipe when more GPUs are available (e.g. 8).

# alignment check on 2 GPUs (optimizer frozen; small batch)
python3 scripts/run_diffusion_grpo_h3_t2va_2gpu.py \
  --cuda-visible-devices 0,1 \
  --num-rollout 2 --eval-interval 0 --debug-alignment

# short train on 2 GPUs
python3 scripts/run_diffusion_grpo_h3_t2va_2gpu.py \
  --cuda-visible-devices 0,1 --num-rollout 5 --eval-interval 0

# this PR's 2-GPU long-run scale (resource-limited)
python3 scripts/run_diffusion_grpo_h3_t2va_2gpu.py \
  --rollout-batch-size 4 --n-samples-per-prompt 16 \
  --cuda-visible-devices 0,1

# recommended scale when more GPUs are available
python3 scripts/run_diffusion_grpo_h3_t2va_2gpu.py \
  --rollout-batch-size 8 --n-samples-per-prompt 16 \
  --cuda-visible-devices 0,1,2,3,4,5,6,7

On 2 GPUs, expect log_prob_mean_abs_diff around 1e-5 .. 8e-5, and LoRA IPC with skipped 0.

Notes:

  • SDE window is 1,4 (skip step 0 from the recipe: σ=1 is singular for H3 flow-SDE). The train-side scorer is the generic flow-SDE backend.
  • H3 requires --use-lora --lora-ipc-weight-sync.
  • Geometry is aspect_ratio + duration_seconds (not width/height); sglang fixes short_edge=768.

Results

log_prob_diff stays in 1.4e-5 .. 7.1e-5 (well under 1e-4), so the train-side scorer matches the rollout log-probs at this scale:

log_prob_diff

Eval PickScore (every 10 rollouts) moves 0.806 → 0.814, peak 0.816 at step 59. The lift is small; this is the batch-4 curve, not the recommended batch-8 recipe:

reward_eval

Train rollout reward is noisier (64 samples / step) and sits around ~0.79 raw PickScore:

reward_rollout

Test plan

  • Install this branch + sglang#34365
  • Alignment run: log_prob_mean_abs_diff < 1e-4
  • Short train for a few rollouts
  • Existing non-H3 CI still green

prepare_flow_grpo_batch read scheduler.config.num_train_timesteps up front, but
only multi-DiT families use it — to decide which component a timestep belongs to
— and only their schedulers are guaranteed to declare it. A single-DiT family
whose scheduler config omits the field (MiniMax H3's carries just shift) died on
a FrozenDict AttributeError before reaching the branch that needs it.
…ackend

_component_class required model_index.json to describe a component as exactly
[library, class_name]. Modular pipelines append a third loading-spec element,
so every component of one resolved to None and load_component raised "cannot
resolve the class". Only the first two elements carry meaning in either format.
_compute_server_args reads args.sglang_tp_size, which the hand-built Namespace
never set, so test_lora_ipc_uses_resolved_args failed on an AttributeError
rather than on anything it meant to assert.
Trains H3 with LoRA against an sglang-diffusion rollout: 1344x768 / 107-frame
t2va video, flow-SDE dynamics, PickScore reward. A 2-GPU verification run holds
log_prob_mean_abs_diff at 4e-5..9e-5, i.e. the train-side scorer reproduces the
sampler's own log probs.

Three family hooks on TrainPipelineConfig carry what cannot be generic, so no
call site needs to know a family name:

  * apply_rollout_sampling_params — H3's sgl-d request takes a target of
    {short_edge, aspect_ratio, duration_seconds} and rejects the generic
    width/height/num_frames/fps and CFG fields, which it drops here. The pixel
    canvas is an output of sglang's shape policy, not an input, so the two
    cannot be mapped onto each other: 16:9 resolves to 1344x768, itself 7:4.
  * sde_step_backend_overrides — picks H3SdeStepBackend per --diffusion-sde-type.
  * lora_layer_group_collector_path — LoRA IPC is the only weight-sync path that
    can reach H3's rollout DiT, which renames modules and fuses Q/K/V, so the
    family rejects every other mode instead of silently training nothing.

H3SdeStepBackend inherits the generic flow-SDE kernel and only resolves sigma
differently (linearly from the rollout timesteps, since H3's scheduler is never
given a sigma grid). It rejects sigma=1 rather than propagating the NaNs the
1/(1-sigma) factor produces there, which is why the recipe's SDE window starts
at step 1.

diffusers is pinned to a main commit: H3's model code is merged there but ships
in no release yet.
Resolve SKILL.md in favor of upstream's install-skill rewrite (radixark#146). The
H3 diffusers pin stays documented in requirements.txt. Also drop the recipe's
--diffusion-model flag, which radixark#142 folded into --hf-checkpoint.
Keep both H3 and Cosmos3 CondKwargs fields. Delete the wandb
sglang_enable_metrics forward: the CLI flag is gone, so the
branch never ran.
@Rockdu Rockdu added run-ci-basic Authorize and run only basic unlabeled CI tests and removed run-ci-basic Authorize and run only basic unlabeled CI tests labels Aug 17, 2026
@Rockdu Rockdu mentioned this pull request Aug 17, 2026
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-ci-basic Authorize and run only basic unlabeled CI tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants