Skip to content

Add DATASET_COMBOS for grouped calibration datasets - #1508

Merged
kevalmorabia97 merged 6 commits into
mainfrom
feat/dataset-combos
May 19, 2026
Merged

Add DATASET_COMBOS for grouped calibration datasets#1508
kevalmorabia97 merged 6 commits into
mainfrom
feat/dataset-combos

Conversation

@cjluo-nv

@cjluo-nv cjluo-nv commented May 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add DATASET_COMBOS to modelopt.torch.utils.dataset_utils — single --dataset tokens that fan out to several entries in SUPPORTED_DATASET_CONFIG. The per-entry num_samples is split evenly across the members inside get_dataset_dataloader.
  • Two initial combos:
  • get_supported_datasets() now appends combo names so they show up in --dataset help.
  • hf_ptq.py's default --calib_size bumped from 512 to 1024 so the cnn_nemotron_v2_mix combo's even split preserves the previous total sample count (was 512 per-dataset × 2 datasets = 1024; now 1024 split → 512 per-dataset × 2). --calib_size now denotes the total calibration budget regardless of combo cardinality.
  • Reject mixing a combo with one of its member datasets in the same --dataset list (e.g. cnn_dailymail,cnn_nemotron_v2_mix) — combo would otherwise double-sample the explicit member with a smaller per-member quota.
  • Reject combo names in get_dataset_samples; combos are dataloader-only. The error message points callers to get_dataset_dataloader.
  • Validate DATASET_COMBOS at import time: empty member lists, name collisions with SUPPORTED_DATASET_CONFIG, and references to unknown datasets raise ValueError up front.

Test plan

End-to-end validated against /hf-local/Qwen/Qwen3.5-0.8B via get_dataset_dataloader on the actual streamed data, plus 5 new unit tests in TestDatasetCombosExpansion (all 44 tests in test_dataset_utils.py pass with no regressions).

  • python -c "from modelopt.torch.utils.dataset_utils import DATASET_COMBOS, get_supported_datasets; assert 'cnn_nemotron_v2_mix' in get_supported_datasets() and 'nemotron-post-training-v3' in get_supported_datasets()"
  • hf_ptq.py with no --dataset flag still calibrates on cnn_dailymail + nemotron-post-training-dataset-v2 with the same total sample count as before.
  • --dataset nemotron-post-training-v3 --calib_size 1024 allocates 146 per member across the seven Nemotron datasets; full 1022-sample dataloader builds without error.
  • --dataset cnn_dailymail,nemotron-post-training-v3 --calib_size 256,1024 composes correctly: 256 from cnn_dailymail (as a plain entry) plus the 7-way split from the combo. (The earlier cnn_dailymail,cnn_nemotron_v2_mix example is rejected by design since cnn_dailymail is a member of that combo.)
  • --dataset cnn_dailymail,cnn_nemotron_v2_mix raises ValueError with a clear message.
  • get_dataset_samples("cnn_nemotron_v2_mix", ...) raises ValueError pointing to get_dataset_dataloader.
  • Unit tests: pytest tests/unit/torch/utils/test_dataset_utils.py — 44 passed.

Post-validation fix

End-to-end testing surfaced that the original nemotron-sft-agentic-v2 entry kept the two splits (interactive_agent, tool_calling) that pyarrow's streaming JSON reader cannot parse, and excluded search which is the only clean split. Failures reproduce deterministically across cache wipes with force_redownload, so they are content-level defects in the published JSONL files at the pinned revision, not local artifacts:

  • interactive_agent — heterogeneous schema (Column(.../member_id/type) changed from string to array) at JSONL row 4.
  • tool_calling — malformed JSON row in a later shard, fails at sample ~885 with Missing a closing quotation mark in string.
  • search — streams cleanly (verified to 2500 samples).

Commit 10f3cfd corrects nemotron-sft-agentic-v2 to use only search, with an updated comment. The CHANGELOG calls this out as a separate bullet so the behavior change on a previously-released dataset entry from #1498 is discoverable.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Dataset combo support: a single dataset token can expand into multiple registered datasets with even sample splitting; predefined combos added (e.g., cnn_nemotron_v2_mix, nemotron-post-training-v3) and listed as supported.
  • Updates

    • Default dataset when none specified now uses cnn_nemotron_v2_mix.
    • Calibration size default increased from 512 to 1024.
  • Bug Fixes

    • nemotron-sft-agentic-v2 now uses only the deterministic "search" split to avoid streaming JSON errors.
  • Tests

    • Added coverage for combo expansion, splitting, overlap validation, and rejection behavior.

Review Change Stack

Lets a single --dataset token fan out to several entries in
SUPPORTED_DATASET_CONFIG, with that entry's num_samples split evenly
across the members. Initial combos:

- ``default``: cnn_dailymail + nemotron-post-training-dataset-v2.
  hf_ptq.py now uses this when --dataset is omitted, replacing a
  hardcoded two-element list. --calib_size default bumped 512 -> 1024
  so the per-dataset sample count after the even split matches the
  prior behavior.
- ``nemotron-sft-mix``: the seven nvidia/Nemotron-* SFT datasets
  registered in #1498.

get_supported_datasets() now lists combo names so they appear in
--dataset --help. Expansion happens inside get_dataset_dataloader
after list normalization.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>
@cjluo-nv
cjluo-nv requested review from a team as code owners May 17, 2026 17:57
@cjluo-nv
cjluo-nv requested a review from meenchen May 17, 2026 17:57
@coderabbitai

coderabbitai Bot commented May 17, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 54964be5-6872-495e-aeee-e46433b8712e

📥 Commits

Reviewing files that changed from the base of the PR and between fb32476 and 6a752ce.

📒 Files selected for processing (4)
  • CHANGELOG.rst
  • examples/llm_ptq/hf_ptq.py
  • modelopt/torch/utils/dataset_utils.py
  • tests/unit/torch/utils/test_dataset_utils.py
✅ Files skipped from review due to trivial changes (1)
  • CHANGELOG.rst
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/unit/torch/utils/test_dataset_utils.py
  • modelopt/torch/utils/dataset_utils.py

📝 Walkthrough

Walkthrough

Adds a DATASET_COMBOS registry that expands single --dataset tokens into multiple datasets with even sample splitting; updates get_dataset_samples/get_dataset_dataloader, exposes combos in supported datasets, adjusts hf_ptq.py defaults, adds unit tests, and documents the change in the changelog.

Changes

Dataset Combos Expansion

Layer / File(s) Summary
Combo registry and nemotron config
modelopt/torch/utils/dataset_utils.py
Introduce DATASET_COMBOS and import-time _validate_dataset_combos(); update nemotron-sft-agentic-v2 to use only the search split.
Dataloader expansion and guard
modelopt/torch/utils/dataset_utils.py
get_dataset_dataloader expands combo tokens into member datasets and distributes num_samples evenly (remainder to earlier members); rejects mixing a combo with its members. get_dataset_samples now raises on combo names.
Supported datasets discovery
modelopt/torch/utils/dataset_utils.py
get_supported_datasets() returns the union of SUPPORTED_DATASET_CONFIG keys and DATASET_COMBOS keys.
hf_ptq.py defaults and CLI
examples/llm_ptq/hf_ptq.py
Fallback args.dataset when unset changes to ["cnn_nemotron_v2_mix"]; CLI --calib_size default increased from 512 to 1024.
Unit tests for combos behavior
tests/unit/torch/utils/test_dataset_utils.py
Add TestDatasetCombosExpansion asserting expansion, even split, remainder allocation, composition rules, overlap rejection, and that get_dataset_samples rejects combo names.
Changelog entry
CHANGELOG.rst
Document DATASET_COMBOS feature, initial combos, nemotron split change, and calibration-size update.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • NVIDIA/Model-Optimizer#1498: Modifies Nemotron dataset registrations and related tests; closely related to the nemotron split changes in this PR.

Suggested reviewers

  • claude
🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'Add DATASET_COMBOS for grouped calibration datasets' directly and concisely summarizes the main change: introducing a new feature (DATASET_COMBOS) that groups multiple calibration datasets together.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Security Anti-Patterns ✅ Passed No security anti-patterns found. PR adds DATASET_COMBOS with proper validation. No unsafe deserialization, eval/exec, hardcoded trust_remote_code, or nosec comments detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/dataset-combos

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
modelopt/torch/utils/dataset_utils.py (1)

198-212: ⚡ Quick win

Add import-time validation for combo integrity.

Please validate combo definitions early (non-empty members, no name collisions with SUPPORTED_DATASET_CONFIG, and all members registered). Without this, typos can silently fall through to auto-detected HF loading and produce hard-to-debug behavior.

🔧 Proposed guardrails
 DATASET_COMBOS: dict[str, list[str]] = {
@@
 }
+
+_dataset_keys = set(SUPPORTED_DATASET_CONFIG)
+_combo_keys = set(DATASET_COMBOS)
+overlap = _dataset_keys & _combo_keys
+if overlap:
+    raise ValueError(f"DATASET_COMBOS keys must not overlap dataset keys: {sorted(overlap)}")
+
+for combo_name, members in DATASET_COMBOS.items():
+    if not members:
+        raise ValueError(f"DATASET_COMBOS['{combo_name}'] must contain at least one dataset.")
+    unknown = [m for m in members if m not in _dataset_keys]
+    if unknown:
+        raise ValueError(
+            f"DATASET_COMBOS['{combo_name}'] contains unknown datasets: {unknown}"
+        )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modelopt/torch/utils/dataset_utils.py` around lines 198 - 212, DATASET_COMBOS
needs import-time validation to avoid silent typos and collisions: add a guard
that runs when the module loads to (1) ensure each combo in DATASET_COMBOS has a
non-empty list of members, (2) ensure no combo name conflicts with
SUPPORTED_DATASET_CONFIG keys, and (3) ensure every member string in each combo
is a registered dataset (exists in SUPPORTED_DATASET_CONFIG); raise a clear
ValueError listing offending combo names/members if any checks fail so callers
of get_dataset_dataloader receive immediate, actionable errors.
examples/llm_ptq/hf_ptq.py (1)

536-537: ⚡ Quick win

Avoid hardcoding combo members in the warning text.

This message can drift from the registry over time. Prefer referencing only the combo name (or deriving members from the registry) so runtime messaging stays accurate.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/llm_ptq/hf_ptq.py` around lines 536 - 537, Replace the hardcoded
combo-members text in the warning string ("No dataset specified. Defaulting to
the 'default' combo (cnn_dailymail + nemotron-post-training-dataset-v2).") so it
no longer lists combo members directly; either simplify the message to only
reference the combo name (e.g., "No dataset specified. Defaulting to the
'default' combo.") or dynamically derive members from the dataset registry
(e.g., lookup the 'default' combo via the registry API and interpolate its
members) and use that value in the log call where the original string appears.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@examples/llm_ptq/hf_ptq.py`:
- Around line 536-537: Replace the hardcoded combo-members text in the warning
string ("No dataset specified. Defaulting to the 'default' combo (cnn_dailymail
+ nemotron-post-training-dataset-v2).") so it no longer lists combo members
directly; either simplify the message to only reference the combo name (e.g.,
"No dataset specified. Defaulting to the 'default' combo.") or dynamically
derive members from the dataset registry (e.g., lookup the 'default' combo via
the registry API and interpolate its members) and use that value in the log call
where the original string appears.

In `@modelopt/torch/utils/dataset_utils.py`:
- Around line 198-212: DATASET_COMBOS needs import-time validation to avoid
silent typos and collisions: add a guard that runs when the module loads to (1)
ensure each combo in DATASET_COMBOS has a non-empty list of members, (2) ensure
no combo name conflicts with SUPPORTED_DATASET_CONFIG keys, and (3) ensure every
member string in each combo is a registered dataset (exists in
SUPPORTED_DATASET_CONFIG); raise a clear ValueError listing offending combo
names/members if any checks fail so callers of get_dataset_dataloader receive
immediate, actionable errors.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 4939a8b8-763d-4295-bcd5-ab868e512468

📥 Commits

Reviewing files that changed from the base of the PR and between 7038dec and df6040d.

📒 Files selected for processing (3)
  • CHANGELOG.rst
  • examples/llm_ptq/hf_ptq.py
  • modelopt/torch/utils/dataset_utils.py

@github-actions

github-actions Bot commented May 17, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-05-19 21:38 UTC

@cjluo-nv
cjluo-nv requested review from Fridah-nv and realAsma May 17, 2026 18:02
@codecov

codecov Bot commented May 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.47%. Comparing base (7038dec) to head (6a752ce).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1508      +/-   ##
==========================================
- Coverage   76.93%   75.47%   -1.47%     
==========================================
  Files         474      474              
  Lines       51506    53469    +1963     
==========================================
+ Hits        39625    40354     +729     
- Misses      11881    13115    +1234     
Flag Coverage Δ
examples 41.76% <100.00%> (+0.93%) ⬆️
gpu 59.75% <75.00%> (-0.59%) ⬇️
regression 15.23% <32.14%> (+0.08%) ⬆️
unit 52.63% <96.42%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

End-to-end probing of the nemotron-sft-mix combo showed both
``interactive_agent`` and ``tool_calling`` fail under pyarrow's streaming JSON
reader: the former at JSONL row 4 (``Column(.../member_id/type) changed from
string to array``), the latter deterministically at sample ~885
(``Missing a closing quotation mark in string``). Both failures reproduce after
a full HF cache wipe with ``force_redownload``, so they are content defects in
the published JSONL — not local cache corruption.

``search``, which the previous comment incorrectly described as the skipped
split, is the only one that streams cleanly (verified to 2500 samples). Switch
the config to use only ``search`` and update the comment to describe the actual
failure modes of the dropped splits.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>

@meenchen meenchen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bot review — DM the bot to share feedback.

Small, cohesive feature (~40 lines). Logic looks correct: divmod-based even split with remainder distribution is fine, and get_supported_datasets() correctly surfaces combo names in --help. A few things worth a human look before merge:

  1. No unit tests for the new combo expansion. The diff adds a non-trivial branch to get_dataset_dataloader (combo-membership lookup, even split, remainder fan-out) with zero coverage. The "test plan" in the PR body is manual end-to-end runs. A simple unit test that mocks get_dataset_samples and asserts the expanded dataset_name / num_samples lists for a combo input (including the remainder case, e.g. n=10 over 7 members → [2,2,2,1,1,1,1]) would be cheap and would also pin combo membership against accidental edits. The existing tests/unit/torch/utils/test_dataset_utils.py::TestGetDatasetDataloaderBlending is the natural home.

  2. --calib_size default change from 5121024 is broader than the PR body suggests. The justification ("preserve previous total sample count for the default combo") only holds when the user is also using the new default-combo path. Anyone running hf_ptq.py --dataset cnn_dailymail (or any single dataset) without --calib_size now gets 2× the calibration samples they got before — a silent runtime/cost regression for existing single-dataset workflows. Two cleaner options: (a) keep --calib_size default at 512 and have the default combo not split (or absorb the doubling inside the combo), or (b) call out the doubling explicitly in CHANGELOG so users with pinned scripts notice. The CHANGELOG entry today only mentions the doubling in the context of the combo, not as a standalone default change.

  3. nemotron-sft-agentic-v2 split swap is a piggybacked behavior change. Changing split from ["interactive_agent", "tool_calling"] to ["search"] silently alters what users of that single dataset key get, independent of combos. The PR body justifies it (data-quality bugs in the upstream JSONL files at the pinned revision) and the rationale is reasonable, but it's worth a maintainer eyeballing — and ideally a CHANGELOG line of its own, since it's a behavior change on a previously-released dataset entry from #1498.

  4. Minor: combos are only expanded inside get_dataset_dataloader. If someone passes a combo name straight to get_dataset_samples (a public function listed in __all__ and exposed via get_supported_datasets()), it falls through to the "treat as HF path" branch and will fail confusingly. Either expand combos in get_dataset_samples too, or document that combos are dataloader-only.

None of these are blockers; flagging for owner sign-off because of the silent default change and the absence of tests on new logic.

cjluo-nv and others added 2 commits May 18, 2026 21:54
Passing both a combo and one of its member datasets (e.g.
``--dataset cnn_dailymail,default``) silently double-samples the member —
the combo expansion would take a per-member quota from cnn_dailymail in
addition to the explicit entry. Raise ValueError in
``get_dataset_dataloader`` listing the combo and the overlapping member(s)
so the user can drop one.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>
- Validate DATASET_COMBOS at import time: empty member lists, name
  collisions with SUPPORTED_DATASET_CONFIG, and references to
  unregistered datasets now raise ValueError up front so typos
  surface immediately rather than as confusing HF lookup failures.
- Reject combo names in ``get_dataset_samples`` with a message
  pointing callers to ``get_dataset_dataloader``. Previously a combo
  name would fall through to the auto-detected HF path and fail
  opaquely.
- Add five unit tests in ``TestDatasetCombosExpansion`` covering even
  split, divmod remainder distribution (n=10 over 7 members →
  [2,2,2,1,1,1,1]), plain + combo composition, overlap rejection,
  and the new ``get_dataset_samples`` combo-name guard. Tests mock
  ``get_dataset_samples`` so they don't touch the HF Hub.
- Split the CHANGELOG entry: document the combo + member overlap and
  combo-in-``get_dataset_samples`` rejections, and add a separate
  bullet for the ``nemotron-sft-agentic-v2`` split swap so it isn't
  buried inside the combo entry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@modelopt/torch/utils/dataset_utils.py`:
- Around line 624-634: The combo-expansion logic (using DATASET_COMBOS and
building expanded_names/expanded_num_samples) currently appends members even
when their allocated sample count is zero, causing later calls to
get_dataset_samples to load unused datasets; change the distribution loop that
builds expanded_names/expanded_num_samples so it only appends a member when its
computed allocation (base + (1 if i < remainder else 0)) is > 0, and also add a
guard before invoking get_dataset_samples to skip entries where num_samples == 0
so no HF datasets are loaded for zero-allocated members.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 48a8c88b-028b-475d-b8cd-9595e1077786

📥 Commits

Reviewing files that changed from the base of the PR and between 10f3cfd and 936a374.

📒 Files selected for processing (3)
  • CHANGELOG.rst
  • modelopt/torch/utils/dataset_utils.py
  • tests/unit/torch/utils/test_dataset_utils.py
✅ Files skipped from review due to trivial changes (1)
  • CHANGELOG.rst

Comment on lines +624 to +634
for ds_name, n in zip(dataset_name, num_samples):
if ds_name in DATASET_COMBOS:
members = DATASET_COMBOS[ds_name]
base, remainder = divmod(n, len(members))
for i, member in enumerate(members):
expanded_names.append(member)
expanded_num_samples.append(base + (1 if i < remainder else 0))
else:
expanded_names.append(ds_name)
expanded_num_samples.append(n)
dataset_name, num_samples = expanded_names, expanded_num_samples

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Skip zero-allocated combo members before loading datasets.

When a combo gets fewer samples than its member count, Lines 625-633 still enqueue members with 0 allocation, and Lines 637-640 still call get_dataset_samples for them. That triggers unnecessary HF loads and can fail calibration even though those members contribute no samples.

Proposed fix
     expanded_names: list[str] = []
     expanded_num_samples: list[int] = []
     for ds_name, n in zip(dataset_name, num_samples):
+        if n <= 0:
+            continue
         if ds_name in DATASET_COMBOS:
             members = DATASET_COMBOS[ds_name]
             base, remainder = divmod(n, len(members))
             for i, member in enumerate(members):
-                expanded_names.append(member)
-                expanded_num_samples.append(base + (1 if i < remainder else 0))
+                alloc = base + (1 if i < remainder else 0)
+                if alloc <= 0:
+                    continue
+                expanded_names.append(member)
+                expanded_num_samples.append(alloc)
         else:
             expanded_names.append(ds_name)
             expanded_num_samples.append(n)
     dataset_name, num_samples = expanded_names, expanded_num_samples
+
+    if not dataset_name:
+        raise ValueError("No positive sample allocations were produced from --dataset/--calib_size.")

Also applies to: 637-640

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modelopt/torch/utils/dataset_utils.py` around lines 624 - 634, The
combo-expansion logic (using DATASET_COMBOS and building
expanded_names/expanded_num_samples) currently appends members even when their
allocated sample count is zero, causing later calls to get_dataset_samples to
load unused datasets; change the distribution loop that builds
expanded_names/expanded_num_samples so it only appends a member when its
computed allocation (base + (1 if i < remainder else 0)) is > 0, and also add a
guard before invoking get_dataset_samples to skip entries where num_samples == 0
so no HF datasets are loaded for zero-allocated members.

@meenchen meenchen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bot review — DM the bot to share feedback.

Re-review of PR #1508. Most previously-flagged critical items are addressed in the new diff:

  • ✅ Unit tests for combo expansion: new TestDatasetCombosExpansion (5 tests) covers even split, remainder distribution (10/7 → [2,2,2,1,1,1,1]), plain+combo composition, overlap rejection, and combo-name in get_dataset_samples.
  • ✅ Import-time validation of DATASET_COMBOS (_validate_dataset_combos() checks empty members, key collisions, and unknown member references).
  • ✅ Combo names rejected from get_dataset_samples with a pointer to get_dataset_dataloader.
  • ✅ Mixing a combo with a member dataset (cnn_dailymail,default) raises a clear ValueError.
  • nemotron-sft-agentic-v2 split swap now has its own CHANGELOG bullet.

What still warrants a human eyeball before merge:

  1. --calib_size default 512 → 1024 still silently doubles single-dataset workflows. This was the most concrete concern in the previous review (meenchen item 2). The author's PR body justifies it as "--calib_size now denotes the total calibration budget regardless of combo cardinality," and the CHANGELOG mentions the bump — but only in the context of the default combo. A user running hf_ptq.py --dataset cnn_dailymail (single dataset, no --calib_size) now silently gets 1024 samples where they previously got 512. That's a 2× cost/runtime regression on existing pinned scripts that is not explicitly called out as a standalone behavior change. Worth either (a) keeping the default at 512 and absorbing the doubling inside the default combo, or (b) adding an explicit CHANGELOG line that single-dataset users without --calib_size will now get 2× the samples.

  2. Minor / not blockers: the warning message in hf_ptq.py hardcodes the combo members in prose (will drift if DATASET_COMBOS["default"] changes); zero-allocated combo members (e.g. nemotron-sft-mix with --calib_size 3 → 4 members get allocation 0) still get passed to get_dataset_samples(name, 0), which triggers a pointless HF load_dataset call per zero-member. Only a concern for callers passing very small calib sizes against the 7-member combo; the default 1024/7 → 146 each path is fine.

Deferring to owner to confirm the --calib_size default change is intended for single-dataset users too.

Comment thread examples/llm_ptq/hf_ptq.py
Comment thread modelopt/torch/utils/dataset_utils.py Outdated
Comment on lines +616 to +620
raise ValueError(
f"--dataset includes both combo '{ds_name}' and its "
f"member(s) {sorted(overlap)}; remove one to avoid "
"double-sampling."
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
raise ValueError(
f"--dataset includes both combo '{ds_name}' and its "
f"member(s) {sorted(overlap)}; remove one to avoid "
"double-sampling."
)
raise ValueError(
f"--{dataset_name} includes both combo '{ds_name}' and its "
f"member(s) {sorted(overlap)}; remove one to avoid "
"double-sampling."
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

a nit suggestion

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Also remove --, seems to be referring to --dataset CLI arg, but meaningless inside this utils file.

@Fridah-nv Fridah-nv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I notice that the current PR does not support per-member knob of num_samples, i.e. specify different number of samples for each dataset under the combo. This would be a useful feature for dataset blend study.
Is the scope of the PR only to add the calib dataset example for GLM5? Overall I haven't fully explored the nemotron v3 dataset blend, not sure if we want to recommend it as default.

@cjluo-nv

Copy link
Copy Markdown
Collaborator Author

I notice that the current PR does not support per-member knob of num_samples, i.e. specify different number of samples for each dataset under the combo. This would be a useful feature for dataset blend study. Is the scope of the PR only to add the calib dataset example for GLM5? Overall I haven't fully explored the nemotron v3 dataset blend, not sure if we want to recommend it as default.

Yes. If user want this, then they should specify them 1by1 instead of using the combo.
No. the nemotron-v3 dataset is not the default. The default is still cnn_daily + v2

The combo's seven member datasets are exactly the ones in NVIDIA's
``nemotron-post-training-v3`` HuggingFace collection
(https://huggingface.co/collections/nvidia/nemotron-post-training-v3),
so reuse the upstream name to make the relationship explicit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>
@cjluo-nv
cjluo-nv enabled auto-merge (squash) May 19, 2026 18:01
@kevalmorabia97
kevalmorabia97 disabled auto-merge May 19, 2026 19:37
Comment thread CHANGELOG.rst
- DeepSeek PTQ (``examples/deepseek/ptq.py``) now defaults to native top-k calibration with post-hoc per-layer peer-max sync of expert ``input_quantizer.amax``; the all-experts path is preserved behind ``--calib_all_experts``.
- Add NVFP4 W4A16 weight-only quantization (``w4a16_nvfp4``): FP4 weights with group_size=16, BF16 activations, no calibration forward pass required. Use ``mtq.W4A16_NVFP4_CFG`` or ``--qformat w4a16_nvfp4`` in ``hf_ptq.py``. vLLM deployment support is in progress.
- Add ``DATASET_COMBOS`` to ``modelopt.torch.utils.dataset_utils`` — single ``--dataset`` tokens that fan out to multiple registered datasets; per-entry ``num_samples`` is split evenly across the members. Initial combos: ``default`` (``cnn_dailymail`` + ``nemotron-post-training-dataset-v2``, used by ``hf_ptq.py`` when no ``--dataset`` is provided) and ``nemotron-post-training-v3`` (the seven ``nvidia/Nemotron-*`` SFT datasets added in #1498, mirroring the `nemotron-post-training-v3 collection <https://huggingface.co/collections/nvidia/nemotron-post-training-v3>`_). Combo names are listed by ``get_supported_datasets()`` and surfaced in ``--dataset`` help. ``get_dataset_dataloader`` rejects inputs that mix a combo with one of its member datasets (e.g. ``cnn_dailymail,default``) to avoid double-sampling, and ``get_dataset_samples`` rejects combo names so callers route through the dataloader. ``hf_ptq.py`` default ``--calib_size`` is bumped from ``512`` to ``1024`` so the total calibration sample count under the new ``default`` combo matches the previous two-dataset fallback.
- The ``nemotron-sft-agentic-v2`` registered dataset (added in #1498) now uses only the ``search`` split. The previously configured ``interactive_agent`` and ``tool_calling`` splits contain content-level defects (heterogeneous schema and a malformed JSON row, respectively) that cause pyarrow's streaming JSON reader to fail deterministically.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nemotron-agentic-v1 also has tool_calling split which is correctly structured if you are interested to use it. Its also much larger than nemotron-sft-agentic-v2's tool_calling split

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

maybe next run. RIght now we pick these 7 datasets for GLM5.1

Comment thread modelopt/torch/utils/dataset_utils.py Outdated
# Useful when callers want a single ``--dataset`` token that fans out to several
# entries; per-dataset ``num_samples`` is split evenly across the members.
DATASET_COMBOS: dict[str, list[str]] = {
"default": ["cnn_dailymail", "nemotron-post-training-dataset-v2"],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

having default dataloader means if we later change default to something else, people will see regression in their ptq results. Is that okay? Or should we explicitly name it something else?

@cjluo-nv cjluo-nv May 19, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I see what you mean. Let me actually rename it.

``default`` is too generic for a registry key — it doesn't say what the
combo contains and clashes with the common English sense ("the default
thing"). Rename it to ``cnn_nemotron_v2_mix`` so the combo's contents
(cnn_dailymail + nemotron-post-training-dataset-v2) are obvious from the
name, matching the descriptive style of the other combo
(``nemotron-post-training-v3``).

``hf_ptq.py``'s no-``--dataset`` fallback now uses the new key.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>
@kevalmorabia97
kevalmorabia97 merged commit a5bc6f8 into main May 19, 2026
47 of 50 checks passed
@kevalmorabia97
kevalmorabia97 deleted the feat/dataset-combos branch May 19, 2026 21:38
jenchen13 pushed a commit that referenced this pull request May 27, 2026
## Summary

- Add ``DATASET_COMBOS`` to ``modelopt.torch.utils.dataset_utils`` —
single ``--dataset`` tokens that fan out to several entries in
``SUPPORTED_DATASET_CONFIG``. The per-entry ``num_samples`` is split
evenly across the members inside ``get_dataset_dataloader``.
- Two initial combos:
- ``cnn_nemotron_v2_mix`` → ``cnn_dailymail`` +
``nemotron-post-training-dataset-v2``. Replaces the hardcoded
two-element fallback list in ``hf_ptq.py`` when ``--dataset`` is
omitted.
- ``nemotron-post-training-v3`` → the seven ``nvidia/Nemotron-*`` SFT
datasets registered in #1498 (mirroring the upstream
[`nemotron-post-training-v3`
collection](https://huggingface.co/collections/nvidia/nemotron-post-training-v3)).
- ``get_supported_datasets()`` now appends combo names so they show up
in ``--dataset`` help.
- ``hf_ptq.py``'s default ``--calib_size`` bumped from ``512`` to
``1024`` so the ``cnn_nemotron_v2_mix`` combo's even split preserves the
previous total sample count (was 512 per-dataset × 2 datasets = 1024;
now 1024 split → 512 per-dataset × 2). ``--calib_size`` now denotes the
total calibration budget regardless of combo cardinality.
- Reject mixing a combo with one of its member datasets in the same
``--dataset`` list (e.g. ``cnn_dailymail,cnn_nemotron_v2_mix``) — combo
would otherwise double-sample the explicit member with a smaller
per-member quota.
- Reject combo names in ``get_dataset_samples``; combos are
dataloader-only. The error message points callers to
``get_dataset_dataloader``.
- Validate ``DATASET_COMBOS`` at import time: empty member lists, name
collisions with ``SUPPORTED_DATASET_CONFIG``, and references to unknown
datasets raise ``ValueError`` up front.

## Test plan

End-to-end validated against ``/hf-local/Qwen/Qwen3.5-0.8B`` via
``get_dataset_dataloader`` on the actual streamed data, plus 5 new unit
tests in ``TestDatasetCombosExpansion`` (all 44 tests in
``test_dataset_utils.py`` pass with no regressions).

- [x] ``python -c "from modelopt.torch.utils.dataset_utils import
DATASET_COMBOS, get_supported_datasets; assert 'cnn_nemotron_v2_mix' in
get_supported_datasets() and 'nemotron-post-training-v3' in
get_supported_datasets()"``
- [x] ``hf_ptq.py`` with no ``--dataset`` flag still calibrates on
cnn_dailymail + nemotron-post-training-dataset-v2 with the same total
sample count as before.
- [x] ``--dataset nemotron-post-training-v3 --calib_size 1024``
allocates 146 per member across the seven Nemotron datasets; full
1022-sample dataloader builds without error.
- [x] ``--dataset cnn_dailymail,nemotron-post-training-v3 --calib_size
256,1024`` composes correctly: 256 from cnn_dailymail (as a plain entry)
plus the 7-way split from the combo. (The earlier
``cnn_dailymail,cnn_nemotron_v2_mix`` example is rejected by design
since ``cnn_dailymail`` is a member of that combo.)
- [x] ``--dataset cnn_dailymail,cnn_nemotron_v2_mix`` raises
``ValueError`` with a clear message.
- [x] ``get_dataset_samples("cnn_nemotron_v2_mix", ...)`` raises
``ValueError`` pointing to ``get_dataset_dataloader``.
- [x] Unit tests: ``pytest
tests/unit/torch/utils/test_dataset_utils.py`` — 44 passed.

## Post-validation fix

End-to-end testing surfaced that the original
``nemotron-sft-agentic-v2`` entry kept the two splits
(``interactive_agent``, ``tool_calling``) that pyarrow's streaming JSON
reader cannot parse, and excluded ``search`` which is the only clean
split. Failures reproduce deterministically across cache wipes with
``force_redownload``, so they are content-level defects in the published
JSONL files at the pinned revision, not local artifacts:

- ``interactive_agent`` — heterogeneous schema
(``Column(.../member_id/type) changed from string to array``) at JSONL
row 4.
- ``tool_calling`` — malformed JSON row in a later shard, fails at
sample ~885 with ``Missing a closing quotation mark in string``.
- ``search`` — streams cleanly (verified to 2500 samples).

Commit ``10f3cfd`` corrects ``nemotron-sft-agentic-v2`` to use only
``search``, with an updated comment. The CHANGELOG calls this out as a
separate bullet so the behavior change on a previously-released dataset
entry from #1498 is discoverable.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Dataset combo support: a single dataset token can expand into multiple
registered datasets with even sample splitting; predefined combos added
(e.g., cnn_nemotron_v2_mix, nemotron-post-training-v3) and listed as
supported.

* **Updates**
  * Default dataset when none specified now uses cnn_nemotron_v2_mix.
  * Calibration size default increased from 512 to 1024.

* **Bug Fixes**
* nemotron-sft-agentic-v2 now uses only the deterministic "search" split
to avoid streaming JSON errors.

* **Tests**
* Added coverage for combo expansion, splitting, overlap validation, and
rejection behavior.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/NVIDIA/Model-Optimizer/pull/1508?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants