Skip to content

Emit VisualGen-compatible sparse_attention_config for diffusers skip-softmax export - #2868

Open
Edwardf0t1 wants to merge 2 commits into
mainfrom
fix/skip-softmax-visualgen-export
Open

Edwardf0t1 wants to merge 2 commits into
mainfrom
fix/skip-softmax-visualgen-export

Conversation

@Edwardf0t1

@Edwardf0t1 Edwardf0t1 commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

Type of change: Bug fix

The diffusers skip-softmax HF export wrote the LLM phase-keyed schema (threshold_scale_factor.prefill and a {phase: ratio} target_sparsity). TRT-LLM VisualGen (PR #14687) expects threshold_scale_factor.coefficients and a scalar target_sparsity, so the exported Wan2.2 checkpoint fails to load (float() ... not 'dict'). NVBug 6927804.

  • export_sparse_attention_config(model, *, for_diffusion=False): with for_diffusion=True, emit one coefficients block and a scalar target_sparsity. The LLM path and the vLLM calibration plugin are unchanged. _export_diffusers_checkpoint passes for_diffusion=True.
  • Fix the READMEs, which referenced the removed resolve_for_target_sparsity.

Based on #1816 (closed, approved). Deliberately dropped its initial_disabled_steps -> disabled_until_timestep rename: initial_disabled_steps shipped in 0.46 and the vLLM calibration path now depends on it, so the rename is a separate, breaking change.

Usage

python examples/diffusers/sparsity/wan22_skip_softmax.py --calibrate --target-sparsity 0.5 --export-dir ckpt ...
# transformer/config.json -> sparse_attention_config.config_groups.group_0:
#   threshold_scale_factor: {formula, coefficients: {a, b}}, target_sparsity: 0.5

Testing

  • Extended test_sparse_attention_conversion.py (diffusion schema) and the Wan calibrated-export example test.
  • Not run: no torch environment was available where this was written, so pytest has not been executed; only pre-commit passed and the conversion logic was checked standalone. Relying on CI. No TRT-LLM VisualGen load was tested.

Before your PR is "Ready for review"

  • Is this change backward compatible?: ❌ Diffusers skip-softmax checkpoints are now emitted in the VisualGen schema (previous ones did not load in VisualGen); LLM export is unchanged.
  • If you copied code from any other sources or added a new PIP dependency, did you follow guidance in CONTRIBUTING.md: N/A
  • Did you write any new necessary tests?: ✅
  • Did you update Changelog?: ✅
  • Did you get Claude approval on this PR?: ❌

Additional Information

NVBug 6927804; supersedes #1816.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Fixed skip-softmax Hugging Face exports for diffusion models to use the TRT-LLM VisualGen format, including grouped threshold coefficients and scalar target sparsity.
    • Existing affected checkpoints must be re-exported to apply the corrected format.
  • Documentation
    • Updated diffusion sparsity documentation to describe the exported checkpoint schema and its calibration and runtime-sparsity settings.

@Edwardf0t1
Edwardf0t1 requested review from a team as code owners October 19, 2026 05:14
@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: NVIDIA/Model-Optimizer/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: 4aa1841d-68c7-4593-9cd3-5315339193c0
📥 Commits

Reviewing files that changed from the base of the PR and between 98511f6 and cb0cc62.

📒 Files selected for processing: 2
  • CHANGELOG.rst
  • modelopt/torch/export/unified_export_hf.py
🚧 Files skipped from review as they are similar to previous changes: 1
  • CHANGELOG.rst

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 10 remain after this review.

📝 Walkthrough

Diffusers sparse-attention export now emits coefficients under threshold_scale_factor.coefficients and scalar target_sparsity. The conversion preserves the default schema and uses the diffusion-specific schema for Diffusers exports. Tests and documentation describe the updated fields.

Changes: Diffusers sparse-attention export

Layer / File(s) Summary
Add diffusion-specific schema conversion
modelopt/torch/sparsity/attention_sparsity/conversion.py, tests/unit/torch/sparsity/attention_sparsity/test_sparse_attention_conversion.py
export_sparse_attention_config adds the for_diffusion option. When enabled, it combines phase-specific coefficients and selects a scalar target sparsity. Unit tests check the diffusion schema.
Use and verify the diffusion schema
modelopt/torch/export/unified_export_hf.py, tests/examples/diffusers/sparsity/test_sparsity.py, examples/diffusers/README.md, examples/diffusers/sparsity/README.md, CHANGELOG.rst
Diffusers component export enables the diffusion schema. Example tests and documentation check and describe the exported fields. The changelog records the export fix.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: kevalmorabia97, cjluo-nv

Merge Risk: ⚪ Minimal · up to cb0cc

No concrete current-head merge-blocking defect was established.

Pre-merge checks: Passed 6
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and specifically describes the main change: generating VisualGen-compatible sparse attention configuration for diffusers skip-softmax exports.
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 4 files. (1 skipped: 1 …
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 PASS. The PR adds no security-sensitive loading, evaluation, execution, # nosec, or dependency patterns. The only changed package Python code adds a for_diffusion argument and transforms sparse-at…
Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 4 files. (1 skipped: 1 unsupported.)

Full details: Security Anti-Patterns

Explanation

PASS. The PR adds no security-sensitive loading, evaluation, execution, # nosec, or dependency patterns. The only changed package Python code adds a for_diffusion argument and transforms sparse-attention dictionaries. No example Python files or dependency manifests changed.

✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://NVIDIA.github.io/Model-Optimizer/pr-preview/pr-2868/

Built to branch gh-pages at 2026-10-21 19:39 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@codecov

codecov Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.30769% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 78.91%. Comparing base (31e9ea6) to head (cb0cc62).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
...pt/torch/sparsity/attention_sparsity/conversion.py 91.66% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2868      +/-   ##
==========================================
+ Coverage   70.16%   78.91%   +8.75%     
==========================================
  Files         659      659              
  Lines       74081    74092      +11     
==========================================
+ Hits        51979    58473    +6494     
+ Misses      22102    15619    -6483     
Flag Coverage Δ
examples-diffusers 20.05% <92.30%> (+<0.01%) ⬆️
examples-gpt-oss 13.51% <7.69%> (-0.01%) ⬇️
examples-hf_ptq 23.18% <7.69%> (-0.04%) ⬇️
examples-llm_distill 13.59% <7.69%> (-0.01%) ⬇️
examples-llm_eval 17.24% <7.69%> (-0.01%) ⬇️
examples-llm_qat 17.48% <7.69%> (-0.02%) ⬇️
examples-llm_sparsity 15.76% <7.69%> (-0.01%) ⬇️
examples-megatron_bridge 26.42% <7.69%> (-0.14%) ⬇️
examples-specdec_bench 13.29% <7.69%> (-0.01%) ⬇️
examples-speculative_decoding 17.47% <7.69%> (-0.01%) ⬇️
examples-torch_onnx 21.37% <7.69%> (-0.03%) ⬇️
examples-torch_trt 15.23% <7.69%> (-0.01%) ⬇️
examples-vllm_serve 15.08% <7.69%> (-0.01%) ⬇️
gpu 59.17% <15.38%> (+37.04%) ⬆️
regression 15.09% <7.69%> (-0.01%) ⬇️
unit 60.60% <92.30%> (+<0.01%) ⬆️

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

☔ View full report in Codecov by Harness.
📢 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.

@cjluo-nv cjluo-nv left a comment

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.

Bot review (bedrock-claude-opus-5-5) — DM the bot to share feedback.

Nudge: the fix is small and looks correct, but nobody has run the tests or tried loading the checkpoint in VisualGen, so a human should check before merge.

Needs action:

  • Confirm CI passes on test_sparse_attention_conversion.py and test_wan22_calibrated_export. The PR says pytest was never run.
  • Confirm with the TRT-LLM VisualGen owners (TRT-LLM PR #14687) that a Wan2.2 checkpoint with coefficients and a scalar target_sparsity loads.
  • Fix the next(iter(ratio.values())) default in conversion.py. Python evaluates it even when prefill is present, and it raises StopIteration on an empty dict (see inline comment).

No action needed:

  • The design review fired only because the PR touches 6 directories. The change is just a keyword-only for_diffusion flag on the existing exporter, not a new system. The LLM path and the vLLM path through export_threshold_scale_factor are unchanged.
  • The edit to the existing test in tests/examples/diffusers/sparsity/test_sparsity.py is justified. Its assertions now check coefficients instead of prefill, matching the schema change, and it gains a check that target_sparsity is a scalar.
  • The CodeRabbit summary in the PR body lists unrelated features (GGML, ONNX Runtime). It looks stale, not like an injection attempt.

tsf["coefficients"] = phases.get("prefill") or next(iter(phases.values()))
ratio = skip_group.get("target_sparsity")
if isinstance(ratio, dict):
skip_group["target_sparsity"] = ratio.get("prefill", next(iter(ratio.values())))

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.

Bot comment.

Python evaluates the dict.get default eagerly, so next(iter(ratio.values())) runs even when prefill exists, and an empty dict raises StopIteration. Suggest ratio["prefill"] if "prefill" in ratio else next(iter(ratio.values()), None). If the result is None, drop the key, since VisualGen needs a scalar.

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.

Good catch, verified: the eager default evaluated next(iter(...)) even when prefill was present and would raise on an empty dict. Fixed in 98511f6: uses ratio["prefill"] when present, else the first value, and drops target_sparsity if there is none.

@cjluo-nv cjluo-nv left a comment

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.

Bot review (bedrock-claude-opus-5-5) — DM the bot to share feedback.

Nudge: the eager-default bug is fixed and the code looks correct, but the tests still haven't been run and nobody has confirmed the checkpoint loads in VisualGen.

Needs action:

  • Confirm CI passes on test_sparse_attention_conversion.py and test_wan22_calibrated_export. The PR says pytest was never run locally.
  • Confirm with the TRT-LLM VisualGen owners (TRT-LLM PR #14687) that a Wan2.2 checkpoint with threshold_scale_factor.coefficients and a scalar target_sparsity loads.

No action needed:

  • ✔️ Resolved since the last review: the eagerly evaluated next(iter(ratio.values())) default in conversion.py. It now uses ratio["prefill"] when present, falls back to the first value, and drops target_sparsity when the dict is empty.
  • Design review: the PR only adds a keyword-only for_diffusion flag to the existing exporter, not a new system. The other callers in plugins/sparse_attn_config.py and plugins/sparse_attn_calibration.py use the default and are unchanged.
  • The edit to the existing test in tests/examples/diffusers/sparsity/test_sparsity.py is justified. It now checks coefficients instead of prefill, which matches the schema change.
  • The CodeRabbit summary in the PR body lists unrelated features. It looks stale, not like an injection attempt.

Edwardf0t1 and others added 2 commits October 21, 2026 12:33
…softmax export

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Zhiyu Cheng <zhiyuc@nvidia.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Signed-off-by: Zhiyu Cheng <zhiyuc@nvidia.com>

This branch has not been deployed

No deployments
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.

2 participants