Skip to content

feat: add Energon-owned SFT sequence packing - #4070

Open
rohitrango wants to merge 12 commits into
NVIDIA-NeMo:mainfrom
rohitrango:rohit/sft_v2_stage2
Open

feat: add Energon-owned SFT sequence packing#4070
rohitrango wants to merge 12 commits into
NVIDIA-NeMo:mainfrom
rohitrango:rohit/sft_v2_stage2

Conversation

@rohitrango

@rohitrango rohitrango commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add minimal Energon-owned multimodal SFT packing
  • add greedy and balanced greedy knapsack packing algorithms
  • support producer-packed batches in Megatron SFTv2
  • add Qwen2.5-VL and Nemotron Omni packing recipes

The implementation adds ~600 nonblank, non-comment Python lines. Configs and tests are excluded from that count.

Validation

  • Ruff format, Ruff lint, and the standard allow-listed Pyrefly check passed
  • 6 focused knapsack unit tests passed
  • 3 focused Energon/Megatron packing unit tests passed with the mcore selector
  • Qwen2.5-VL non-packing recipe completed 50 steps from a clean checkpoint; final loss 0.01768
  • Qwen2.5-VL packing recipe trained through step 36 and saved step 30 before the validation node was repurposed
  • Nemotron Omni non-packing recipe completed 50 steps; final loss 0.08346 and final gradient norm 5.47
  • Nemotron Omni packing recipe completed 50 steps; 24,238 valid tokens, final loss 0.03185, and final gradient norm 3.1183
  • Nemotron packed W&B run: https://wandb.ai/nvidia/sft-dev/runs/ub57wmfz

Convergence
Qwen2.5VL with and without packing
image

Nemotron-Omni with and without packing and CP>1
image

@rohitrango
rohitrango requested review from a team as code owners September 10, 2026 04:10
@copy-pr-bot

copy-pr-bot Bot commented Sep 10, 2026

Copy link
Copy Markdown

Auto-sync is disabled for ready for review pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@rohitrango
rohitrango requested a review from a team as a code owner September 10, 2026 04:44
@rohitrango rohitrango added the CI:Lfast Runs a fast test suite and re-use nightly `main` container (but sync dependencies to PRs version) label Sep 10, 2026
@rohitrango
rohitrango requested a review from a team as a code owner September 10, 2026 04:52
Signed-off-by: rohitrango <rohit.rango@gmail.com>
Signed-off-by: rohitrango <rohit.rango@gmail.com>
Signed-off-by: rohitrango <rohit.rango@gmail.com>
Signed-off-by: rohitrango <rohit.rango@gmail.com>
Signed-off-by: rohitrango <rohit.rango@gmail.com>
@rohitrango

Copy link
Copy Markdown
Contributor Author

/ok to test da8a263

@rohitrango rohitrango left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed by a team of five agents (RL codebase, Megatron-Core/Bridge/Energon upstream, bug scan, tests, plus an adversarial pass that re-derived every finding from source and dropped six that did not survive).

Nice piece of work — moving packing ownership into the Energon task encoder is the right shape for SFTv2, it keeps media travelling with the pack instead of over the wire in padded rows, and the convergence curves for both models are a good thing to have up front.

Please look at the four blocking items first (all reproduced locally):

  1. balanced_knapsack_delta=20 is the shipped default and both recipes select that packer — 1.6x-3.2x more microbatches at ~30-57% bin utilization, with no config path to change it.
  2. Any conversation longer than data.max_input_seq_length raises out of the packer and ends the job, because packing_cost keeps the pre-truncation length. The non-packing path handled the same sample gracefully.
  3. Four existing test files break and were not updatedtests/unit/algorithms/test_sft_v2.py (6 failures), tests/unit/models/policy/test_tq_policy_placed.py (1), tests/unit/data/test_energon_sft.py (3), tests/unit/data/test_energon_sft_v2.py. Verified by running the first two and by execution/AST for the rest.
  4. Both new recipe YAMLs turn test_all_recipe_yamls_accounted_for_in_test_suites red — that module is run_first, so it is an L0 break.

On evidence: the convergence curves establish that packing does not break training, which is the harder half. What is missing is any number showing the feature does its job — tokens/s or step time, peak memory, and mean bin utilization, packed vs unpacked. get_packer is called without collect_metrics, so PackingMetrics never runs and the feature currently ships with no way to observe what it packed. A three-row table would also have surfaced items 1 and the greedy_knapsack question below before review. (Worth noting the Qwen packing run stopped at step 36 against 50 for the others.)

Checked and clean, recorded so nobody re-derives them: the GreedyKnapsackPacker bisect sentinel (brute-forced against a naive reference over 3000 cases, 0 mismatches); the per-source loss-mask shift, which correctly zeroes every source's first token; sample_mask per physical pack for loss normalization; data.size and the MICRO_BATCH_INDICES / MICRO_BATCH_LENGTHS nesting; the sample_schema removal (zero readers anywhere); packing_buffer_size as a kwarg on all three Energon loader entry points; Sample.derive_from with the extra fields; and max_seqlen_q, total_tokens and position_ids=None against Megatron-Core at the pinned SHA. No upstream defects found in Megatron-LM, Megatron-Bridge or megatron-energon — nothing to file.

Ruff format and Ruff lint both pass on the changed files.

Generated by Claude Code

Comment thread nemo_rl/data/packing/algorithms.py Outdated
Comment thread nemo_rl/data/energon/multimodal/packing.py
Comment thread nemo_rl/algorithms/sft_v2.py
Comment thread nemo_rl/models/policy/tq_policy.py
Comment thread nemo_rl/data/energon/config.py Outdated
Comment thread nemo_rl/data/packing/algorithms.py
Comment thread nemo_rl/data/energon/multimodal/packing.py Outdated
Comment thread nemo_rl/data/energon/sft_dataloader.py
Comment thread tests/unit/data/packing/test_knapsack.py
Comment thread tests/unit/data/test_energon_packing.py Outdated
rohitrango and others added 3 commits September 10, 2026 08:55
Signed-off-by: Rohit Jena <rohitrango@users.noreply.github.com>
Signed-off-by: rohitrango <rohit.rango@gmail.com>
Signed-off-by: rohitrango <rohit.rango@gmail.com>
@rohitrango
rohitrango requested a review from a team as a code owner September 10, 2026 17:32
@github-actions github-actions Bot added the Documentation Improvements or additions to documentation label Sep 10, 2026
@rohitrango

rohitrango commented Sep 10, 2026

Copy link
Copy Markdown
Contributor Author

Review follow-up: the full code/test/doc fixes are pushed in 31d3111f, the one-node CP2 validation recipe is in 51cdc68d, and packed metric semantics are documented in 1fa10334. 295add73 allows all PackingAlgorithm values through Energon SFT and tests selection across the full enum. I replied to every inline review thread and resolved all conversations. A utilization table and additional method-level/API docstrings are not required for this minimal migration.

rohitrango and others added 3 commits September 10, 2026 10:41
Signed-off-by: rohitrango <rohit.rango@gmail.com>
Signed-off-by: rohitrango <rohit.rango@gmail.com>
@rohitrango

Copy link
Copy Markdown
Contributor Author

/ok to test f8eaef7

Signed-off-by: rohitrango <rohit.rango@gmail.com>
@rohitrango

Copy link
Copy Markdown
Contributor Author

/ok to test 619c3d6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI:Lfast Runs a fast test suite and re-use nightly `main` container (but sync dependencies to PRs version) Documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant