Repository navigation
feat(vlm): Nemotron Super Omni GRPO with MTP under context parallelism #3494
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 55 commits
Commits
Show all changes
58 commits
Select commit
Hold shift + click to select a range
7bc1112
feat(nemo-gym): let structured images drive Super media placement
DanialTaheri 352bb3b
feat(vlm): apply Nemotron Omni tower controls and keep dynamic module…
DanialTaheri 8871c9a
fix(vllm): load the embedded chat template and honor the module cache
DanialTaheri ac66b32
feat(vlm): add Nemotron Super Omni async Gym recipe and launcher (MTP…
DanialTaheri 3c977ff
feat(vlm): add MTP variant of the Super Omni recipe
DanialTaheri e0b7345
feat(megatron): support MTP on the caller-packed THD context-parallel…
DanialTaheri 9c6ba4f
fix(vlm): align Super Omni MTP settings with the validated CP=2 refer…
DanialTaheri 900ed26
fix(megatron): unpack the sliced loss mask from self-CP-slicing models
DanialTaheri 429216f
feat(vlm): Super Omni recipe with trained MTP and speculative decoding
DanialTaheri 81ce0d6
fix(launcher): make the MTP cudagraph-capture-sizes delete opt-out
DanialTaheri b66515a
docs(patches): carry the Megatron-LM MTP SP-scatter fix as a patch
DanialTaheri 0e77143
chore(vlm): use placeholder paths in the Super Omni launcher defaults
DanialTaheri ee44f1d
chore(vlm): drop the Super Omni launcher and test-suite scripts
DanialTaheri cda02c3
chore(vlm): drop the vendored Gym verifier staging copies
DanialTaheri 2880278
feat(vlm): standalone Super Omni launcher; leave super_launch.sh unto…
DanialTaheri ec4bce1
docs(patches): note that submodule sync discards the MTP patch
DanialTaheri 04e6145
fix(vlm): carry MTP speculative decoding in the recipe
DanialTaheri 20f4857
fix(vlm): verify checkpoint and data are inside the container mounts
DanialTaheri c183031
fix(vlm): mount-check GYM_VENV_DIR when it points at host storage
DanialTaheri 682641c
fix(nemo-gym): stop fabricating content on items that carry none
DanialTaheri 7aaef4f
test(megatron): pin the MTP mask layout for model-CP-slicing models
DanialTaheri a58844e
test(suites): add Super Omni recipe drivers and disable them
DanialTaheri 907918d
fix(vlm): select the flashinfer_cutlass MoE backend for Super Omni
DanialTaheri ecdb0ca
refactor(vlm): make the MTP+specdec recipe self-contained
DanialTaheri 3cbace9
fix(nemo_gym): point the Super Omni launcher at the surviving entrypoint
DanialTaheri e592727
feat(vlm): train the MTP head in the Super Omni MTP recipe
DanialTaheri 6d619c8
Fix tests and linking to correct py script for grpo_nemo_gym
DanialTaheri 5274d11
docs(super-omni): name the override variable the launcher actually reads
DanialTaheri 4a055c2
docs(vlm): correct the inverted MTP gradient-clipping warning
DanialTaheri 868da54
fix(vlm): stop keying checkpoint selection on an uncollected val metric
DanialTaheri a3f7a9c
fix(vlm): cap retained Super Omni checkpoints at 5
DanialTaheri df64881
refactor(vllm): use vLLM's own default_chat_template_kwargs
DanialTaheri 802c302
test(megatron): make the full-MTP-mask assertions load-bearing
DanialTaheri 4acd5bb
style(vllm): drop the doubled blank line left by the renderer refactor
DanialTaheri 6b34de8
refactor(vlm): restore recipe inheritance and resolve cluster in the …
DanialTaheri 1e3e89b
docs(super-omni): register the guide in the toctree and document the …
DanialTaheri ddc1b6f
docs(super-omni): describe the launcher's placeholders, not defaults …
DanialTaheri 26e4471
fix(nemo_gym): populate the multimodal config fields in the builder
DanialTaheri c129d0f
Update nemo_rl/__init__.py
DanialTaheri 69e55a8
Update nemo_rl/models/megatron/setup.py
DanialTaheri d3764bc
Update nemo_rl/__init__.py
DanialTaheri a50ac7a
chore: drop patches/ now that the fix is in the pinned Megatron-LM
DanialTaheri 4bf9ef7
fix(nemo_rl): restore the module-cache lookup in patch_transformers_m…
DanialTaheri ac1b129
test(nemo_gym): cover image-placeholder sanitising and the ragged ima…
DanialTaheri 36346f7
fix(nemo_rl): thread apply_to_current_interpreter through as a keyword
DanialTaheri a3477b7
fix(megatron): repair the VLM override loop and align both call sites
DanialTaheri 7e480d6
fix(vllm): give the chat-template defaults to all three serving consu…
DanialTaheri 0095e6f
docs(super-omni): export the W&B opt-out so it reaches the launcher
DanialTaheri 771f5ad
fix(refit): keep the refit broadcast stream on one device
DanialTaheri 7006208
fix(nemo-gym): restore processor tensors on the ragged image path
DanialTaheri a4ac696
refactor(nemo-gym)!: remove image-placeholder sanitization
DanialTaheri 4ef7f7f
fix(nemo-gym): make the launcher's cluster read survive a missing uv env
DanialTaheri d71b1e2
docs(super-omni): drop the standalone guide from this PR
DanialTaheri 9a5f3d8
test(nemo_rl): stop an ambient HF_MODULES_CACHE from deciding the result
DanialTaheri 5be93ae
style(nemo-gym): drop the stray blank line left by removing the sanit…
DanialTaheri dfc4e56
test(vllm): stub the chat-template loader the async server now imports
DanialTaheri c1cb4f0
fix(nemo-gym): read _pad_dynamic_image_shapes with a default
DanialTaheri 6163e79
test(vllm): cover the chat-template wiring for all three serving cons…
DanialTaheri File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
24 changes: 24 additions & 0 deletions
24
...grpo-nemotron-super-omni-120ba12b-16n8g-megatron-tp8ep16cp2-async-gym-mtp-specdec.v1.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| defaults: ./vlm_grpo-nemotron-super-omni-120ba12b-16n8g-megatron-tp8ep16cp2-async-gym-mtp.v1.yaml | ||
| policy: | ||
| generation: | ||
| vllm_kwargs: | ||
| # MTP speculative decoding. Only method and num_speculative_tokens are | ||
| # set: this container's vLLM SpeculativeConfig has no attention_backend | ||
| # field and rejects it, and the backend is already selected globally by | ||
| # vllm_kwargs.attention_backend. | ||
| speculative_config: | ||
| method: mtp | ||
| num_speculative_tokens: 5 | ||
| # Super is a hybrid Mamba model, so the recurrent SSM state must roll back | ||
| # when draft tokens are rejected. MambaCacheMode defaults to "none"; | ||
| # "align" is what makes rejection correct for this model. | ||
| mamba_cache_mode: align | ||
| enable_chunked_prefill: true | ||
| max_num_batched_tokens: 8480 | ||
| checkpointing: | ||
| checkpoint_dir: results/nemotron-super-omni-async-gym-mtp-specdec | ||
| save_period: 5 | ||
| logger: | ||
| log_dir: logs/nemotron-super-omni-async-gym-mtp-specdec | ||
| wandb: | ||
| name: nemotron-super-omni-async-gym-mtp-specdec |
37 changes: 37 additions & 0 deletions
37
...vlm/vlm_grpo-nemotron-super-omni-120ba12b-16n8g-megatron-tp8ep16cp2-async-gym-mtp.v1.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| defaults: ./vlm_grpo-nemotron-super-omni-120ba12b-16n8g-megatron-tp8ep16cp2-async-gym.v1.yaml | ||
| policy: | ||
| megatron_cfg: | ||
| # Multi-Token Prediction, matching the reference Super Omni recipe that | ||
| # runs MTP at context_parallel_size=2. | ||
| # | ||
| # The checkpoint ships one physical MTP layer (num_nextn_predict_layers: 1, | ||
| # mtp_hybrid_override_pattern: "*E"), so mtp_num_layers: 1 with | ||
| # use_repeated_layer: false maps directly onto it. Asking for more layers | ||
| # would require repeating that single layer. | ||
| # | ||
| # detach_heads keeps MTP gradients from flowing back into the backbone, so | ||
| # the main next-token objective is unchanged by the auxiliary head. | ||
| mtp_num_layers: 1 | ||
| mtp_use_repeated_layer: false | ||
| mtp_detach_heads: true | ||
| # Train the MTP head: its loss is added to the training objective at this | ||
| # weight. Set 0.0 instead to keep the head present and refit into vLLM (so | ||
| # speculative decoding can use it) without training it, which is what the | ||
| # reference Super Omni CP=2 recipe does. | ||
| # | ||
| # MTP gradients are clipped separately from the backbone, not jointly with | ||
| # it. With mtp_detach_heads: true above, Megatron tags every MTP parameter | ||
| # grad_norm_group='mtp' (multi_token_prediction.py), and clip_grad_norm | ||
| # excludes tagged parameters from the main gradient norm and clips them | ||
| # against their own group norm (optimizer.py, SEPARATE_GRAD_NORM_GROUPS). | ||
| # So raising this weight does not feed MTP gradients into the backbone's | ||
| # clipping. Watch train/grad_norm anyway: measured over 24 steps at this | ||
| # weight it stayed in 0.03-0.22, so a departure from that range is a signal | ||
| # worth chasing -- but look past MTP clipping for the cause. | ||
| mtp_loss_scaling_factor: 0.1 | ||
| logger: | ||
| log_dir: logs/nemotron-super-omni-async-gym-mtp | ||
| wandb: | ||
| name: nemotron-super-omni-async-gym-mtp | ||
| checkpointing: | ||
| checkpoint_dir: results/nemotron-super-omni-async-gym-mtp |
155 changes: 155 additions & 0 deletions
155
...pes/vlm/vlm_grpo-nemotron-super-omni-120ba12b-16n8g-megatron-tp8ep16cp2-async-gym.v1.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| defaults: ../../../nemo_gym/grpo_nanov3.yaml | ||
| grpo: | ||
| num_prompts_per_step: 256 | ||
| max_num_steps: 1000 | ||
| val_period: 0 | ||
| advantage_clip_low: -50 | ||
| advantage_clip_high: 50 | ||
| zero_variance_prompt_filtering: false | ||
| async_grpo: | ||
| enabled: true | ||
| in_flight_weight_updates: true | ||
| recompute_kv_cache_after_weight_updates: false | ||
| loss_fn: | ||
| token_level_loss: false | ||
| truncated_importance_sampling_type: tis | ||
| truncated_importance_sampling_ratio: 2.0 | ||
| truncated_importance_sampling_ratio_min: 0.5 | ||
| checkpointing: | ||
| checkpoint_dir: results/nemotron-super-omni-async-gym | ||
| checkpoint_must_save_by: 00:03:45:00 | ||
| # This recipe disables validation (grpo.val_period: 0 above), so no val | ||
| # metric is ever collected. The parent sets metric_name to | ||
| # val:total_reward/mean, which is coherent there because it validates every | ||
| # 5 steps; inherited here it makes every checkpoint tie at -inf, warns on | ||
| # each save, and degrades best-checkpoint selection to "latest anyway". | ||
| # null selects the same behaviour deliberately: keep_top_k then ranks | ||
| # periodic checkpoints by step. Set a val metric here only alongside a | ||
| # non-zero val_period (or val_at_end). | ||
| metric_name: null | ||
| # A Super Omni checkpoint is ~1.4 TB with optimizer state, so the parent's | ||
| # keep_top_k: 1000000 (never prune) costs ~14 TB across a 50-step run at | ||
| # save_period: 5. Keep the 5 most recent instead. Safe to prune by step | ||
| # only because metric_name is null above: with a val metric named but | ||
| # never collected, every checkpoint ties at -inf and pruning is arbitrary. | ||
| keep_top_k: 5 | ||
| policy: | ||
| is_vlm: true | ||
| model_name: /path/to/nemotron-super-omni-hf-checkpoint | ||
| tokenizer: | ||
| chat_template: ${policy.model_name}/chat_template.jinja | ||
| train_global_batch_size: 4096 | ||
| max_total_sequence_length: 16384 | ||
| make_sequence_length_divisible_by: ${mul:${policy.megatron_cfg.context_parallel_size}, | ||
| ${mul:2, ${policy.megatron_cfg.tensor_model_parallel_size}}} | ||
| megatron_cfg: | ||
| empty_unused_memory_level: 2 | ||
| tensor_model_parallel_size: 8 | ||
| expert_model_parallel_size: 16 | ||
| pipeline_model_parallel_size: 1 | ||
| context_parallel_size: 2 | ||
| moe_per_layer_logging: false | ||
| # Keep MTP disabled for both training and refit. | ||
| mtp_num_layers: 0 | ||
| radio_force_cpe_eval_mode: true | ||
| freeze_vision_model: false | ||
| freeze_vision_projection: false | ||
| freeze_sound_encoder: true | ||
| freeze_sound_projection: true | ||
| optimizer: | ||
| min_lr: 2.0e-09 | ||
| adam_beta2: 0.99 | ||
| scheduler: | ||
| lr_warmup_init: 3.0e-08 | ||
| distributed_data_parallel_config: | ||
| overlap_grad_reduce: false | ||
| overlap_param_gather: false | ||
| env_vars: | ||
| NCCL_ALGO: Ring | ||
| NCCL_PROTO: Simple | ||
| NRL_REFIT_BUFFER_MEMORY_RATIO: '0.006' | ||
| NRL_REFIT_NUM_BUFFERS: '1' | ||
| generation: | ||
| bad_words: | ||
| - <image> | ||
| - <img> | ||
| - </img> | ||
| - <so_embedding> | ||
| - <so_start> | ||
| - <so_end> | ||
| vllm_cfg: | ||
| gpu_memory_utilization: 0.8 | ||
| load_format: auto | ||
| enable_prefix_caching: false | ||
| skip_tokenizer_init: false | ||
| logprobs_mode: raw_logprobs | ||
| env_vars: | ||
| NCCL_ALGO: Ring | ||
| NCCL_PROTO: Simple | ||
| NRL_REFIT_BUFFER_MEMORY_RATIO: '0.006' | ||
| NRL_REFIT_NUM_BUFFERS: '1' | ||
| http_server_serving_chat_kwargs: | ||
| chat_template: ${policy.tokenizer.chat_template} | ||
| chat_template_content_format: openai | ||
| reasoning_parser: deepseek_r1 | ||
| vllm_kwargs: | ||
| # Match the higher-throughput backend used by the earlier successful | ||
| # policy-serving runs. This must remain compatible with repeated refits. | ||
| moe_backend: flashinfer_cutlass | ||
| limit_mm_per_prompt: | ||
| image: 3 | ||
| mm_processor_cache_gb: 0 | ||
| max_num_batched_tokens: ${policy.max_total_sequence_length} | ||
| max_num_seqs: 32 | ||
| skip_mm_profiling: true | ||
| disable_custom_all_reduce: true | ||
| attention_backend: FLASH_ATTN | ||
| attention_config: | ||
| use_trtllm_attention: false | ||
| compilation_config: | ||
| cudagraph_mode: PIECEWISE | ||
| colocated: | ||
| enabled: false | ||
| resources: | ||
| gpus_per_node: 8 | ||
| num_nodes: 8 | ||
| data: | ||
| max_input_seq_length: ${policy.max_total_sequence_length} | ||
| train: | ||
| data_path: /path/to/super-omni-gym-train.jsonl | ||
| validation: | ||
| data_path: /path/to/super-omni-gym-validation.jsonl | ||
| env: | ||
| nemo_gym: | ||
| policy_max_input_tokens: ${policy.max_total_sequence_length} | ||
| skip_venv_if_present: true | ||
| pad_dynamic_image_shapes: true | ||
| config_paths: | ||
| - responses_api_models/vllm_model/configs/vllm_model_for_training.yaml | ||
| - resources_servers/math_with_judge/configs/math_with_judge.yaml | ||
| - resources_servers/mcqa/configs/mcqa.yaml | ||
| - resources_servers/gui_coordinate/configs/gui_coordinate.yaml | ||
| - resources_servers/string_match/configs/string_match.yaml | ||
| policy_model: | ||
| responses_api_models: | ||
| vllm_model: | ||
| uses_reasoning_parser: true | ||
| extra_body: | ||
| bad_words: | ||
| - <image> | ||
| - <img> | ||
| - </img> | ||
| - <so_embedding> | ||
| - <so_start> | ||
| - <so_end> | ||
| chat_template_kwargs: | ||
| enable_thinking: true | ||
| logger: | ||
| log_dir: logs/nemotron-super-omni-async-gym | ||
| wandb_enabled: true | ||
| tensorboard_enabled: true | ||
| wandb: | ||
| project: grpo-superv3omni | ||
| name: nemotron-super-omni-async-gym | ||
| cluster: | ||
| num_nodes: 16 | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.