Skip to content

Add Qwen 3.5 0.8B Puzzletron configs - #2116

Draft
j-rausch wants to merge 7 commits into
feature/puzzletron_v2from
qwen35-0p8b-puzzletron-configs
Draft

Add Qwen 3.5 0.8B Puzzletron configs#2116
j-rausch wants to merge 7 commits into
feature/puzzletron_v2from
qwen35-0p8b-puzzletron-configs

Conversation

@j-rausch

@j-rausch j-rausch commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Type of change: New example and tests.

Qwen 3.5 0.8B does not have a version-pinned Puzzletron model example. It also needs a clear separation between a conservative default and broader targets that have not yet been validated end to end.

This PR pins the public checkpoint identity and geometry, then provides two search choices:

  • model.yaml is the default and searches only FFN intermediate sizes [3072, 2048].
  • advanced.yaml is an explicit opt-in. It inherits the pinned model config and exposes six pruning axes. The axis structure is adapted from the existing Qwen 3.5 9B config, while the concrete targets are derived from the pinned 0.8B geometry. These targets were not selected from completed 0.8B search results and have not been fully runtime-validated.

Hugging Face conversion now passes the configured model revision to checkpoint resolution, so a repository ID resolves to the pinned teacher snapshot instead of the repository's current revision. Converted teachers record that source and revision locally and are reused only when the configured identity matches. Replacements are built and validated in a clean sibling directory before publication, preventing stale shards and preserving the previous teacher if conversion or the directory swap is interrupted. In distributed runs, rank-zero failures are broadcast before later barriers so peers exit promptly instead of waiting for a timeout. A pinned legacy teacher without this record is converted once to establish the identity; unpinned legacy checkpoints retain the existing resume behavior.

The outcome is a narrow default for normal example reuse plus a clearly labeled advanced surface for follow-up validation, without presenting derived targets as measured results. The proposed advanced gdn_key_head_dim change from 128 to 96 remains documented but disabled with no executable candidate values until physical runtime-equivalence evidence is available.

Usage

Select the default model config in a run:

- /families/qwen3_5/qwen3p5_0p8b/model@_global_

Replace that line with the advanced choice when evaluating the broader validated search surface:

- /families/qwen3_5/qwen3p5_0p8b/advanced@_global_

Testing

The dedicated Puzzletron v2 CPU suite covers the pinned public model identity, exact default and advanced domains, portable configuration discovery, Hydra inheritance and revision resolution, blocked-axis behavior, offline propagation of optional Hugging Face revisions through conversion, and rejection of a converted teacher from a different revision. No GPU smoke has been run, so the advanced configuration remains experimental.

Summary by CodeRabbit

  • New Features

    • Added support for the Qwen3.5 0.8B model, including standard and advanced pruning/search configurations.
    • Added pinned model revision support for more reproducible model conversion.
  • Bug Fixes

    • Improved conversion recovery after interruptions or failures.
    • Conversion results are now validated before publishing, with safer reuse of compatible checkpoints.
    • Changed model revisions or incompatible layouts now trigger reconversion automatically.
  • Tests

    • Added coverage for Qwen3.5 configuration validation and reliable conversion workflows.

Signed-off-by: Johannes Rausch <jrausch@nvidia.com>
Cover the complete model metadata and axis domains so incomplete recipe changes fail in CPU CI.

Signed-off-by: Johannes Rausch <jrausch@nvidia.com>
Keep the default aligned with the tracked 0.8B FFN campaign while making the broader 9B-derived search an explicit, unvalidated opt-in.

Signed-off-by: Johannes Rausch <jrausch@nvidia.com>
@copy-pr-bot

copy-pr-bot Bot commented Aug 8, 2026

Copy link
Copy Markdown

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

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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: 069dea0a-131f-4cc8-9d3e-111bfcb0f662

📥 Commits

Reviewing files that changed from the base of the PR and between 92fcce9 and f5c4e93.

📒 Files selected for processing (2)
  • modelopt/torch/puzzletron/stages/convert.py
  • tests/unit/torch/puzzletron/test_convert_anymodel.py

📝 Walkthrough

Walkthrough

Adds a pinned Qwen3.5 0.8B model configuration, pruning and search spaces, revision-aware Hugging Face conversion, transactional checkpoint publication, and unit tests for configuration and conversion behavior.

Changes

Qwen3.5 0.8B configuration and conversion

Layer / File(s) Summary
Model contract
examples/puzzletron/configs/families/qwen3_5/qwen3p5_0p8b/model.yaml
Defines the pinned Hugging Face model, revision, architecture, geometry, vocabulary, attention, MTP, layer-count, and Mamba metadata.
Pruning and search spaces
examples/puzzletron/configs/families/qwen3_5/qwen3p5_0p8b/model.yaml, examples/puzzletron/configs/families/qwen3_5/qwen3p5_0p8b/advanced.yaml
Adds FFN pruning candidates and advanced search axes. GDN value-head grouping axes remain disabled with empty value lists.
Transactional conversion
modelopt/torch/puzzletron/stages/convert.py
Passes model revisions to Hugging Face resolution, records source metadata, validates converted checkpoints, recovers interrupted swaps, and publishes conversion output atomically.
Configuration and conversion validation
tests/unit/torch/puzzletron/test_portable_configs.py, tests/unit/torch/puzzletron/test_qwen3p5_0p8b_example.py, tests/unit/torch/puzzletron/test_convert_anymodel.py
Validates model identity, search domains, disabled axes, Hydra composition, revision handling, metadata matching, checkpoint reuse, failed retries, and interrupted transaction recovery.

Estimated code review effort: 4 (Complex) | ~45 minutes

Suggested reviewers: separius

Sequence Diagram(s)

sequenceDiagram
  participant convert_stage
  participant HuggingFace
  participant TemporaryCheckpoint
  participant PublishedCheckpoint
  convert_stage->>HuggingFace: Resolve source with configured revision
  convert_stage->>TemporaryCheckpoint: Convert and write metadata
  TemporaryCheckpoint->>convert_stage: Validate checkpoint layout and metadata
  convert_stage->>PublishedCheckpoint: Atomically publish validated checkpoint
Loading
🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the primary user-facing change: adding Qwen 3.5 0.8B Puzzletron configurations.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 PR changes add no unsafe torch/numpy loads, eval/exec, shell bypasses, or # nosec; trust_remote_code remains caller-controlled with default False, and no dependency manifests changed.
✨ 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 qwen35-0p8b-puzzletron-configs

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

@codecov

codecov Bot commented Aug 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.63636% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 55.26%. Comparing base (3485fd0) to head (f5c4e93).

Files with missing lines Patch % Lines
modelopt/torch/puzzletron/stages/convert.py 93.63% 7 Missing ⚠️
Additional details and impacted files
@@                    Coverage Diff                    @@
##           feature/puzzletron_v2    #2116      +/-   ##
=========================================================
+ Coverage                  54.76%   55.26%   +0.50%     
=========================================================
  Files                        704      704              
  Lines                      90869    90960      +91     
=========================================================
+ Hits                       49761    50269     +508     
+ Misses                     41108    40691     -417     
Flag Coverage Δ
puzzletron 33.00% <93.63%> (+0.12%) ⬆️
unit 29.71% <0.00%> (-0.04%) ⬇️

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.

@j-rausch
j-rausch marked this pull request as ready for review August 8, 2026 09:46
@j-rausch
j-rausch requested a review from a team as a code owner August 8, 2026 09:46

@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.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 2

🤖 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 `@examples/puzzletron/configs/families/qwen3_5/qwen3p5_0p8b/advanced.yaml`:
- Around line 45-50: Disable the unvalidated gdn_key_head_dim candidate by
setting its enabled flag to false or removing 96 from values, while preserving
the teacher value. Update the matching expected domain assertion in
test_qwen3p5_0p8b_example.py so it reflects the disabled or removed candidate.

In `@examples/puzzletron/configs/families/qwen3_5/qwen3p5_0p8b/model.yaml`:
- Around line 3-10: Update the Hugging Face source-resolution flow for
input_hf_model_path to read model_info.hf_revision and pass it as the revision
argument to snapshot_download alongside the repository ID, ensuring the resolved
teacher checkpoint uses the configured pinned revision.
🪄 Autofix

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: 6e6e202c-5d2d-4f31-8a7e-d0ce33d32e2e

📥 Commits

Reviewing files that changed from the base of the PR and between 3485fd0 and d10ccbd.

📒 Files selected for processing (4)
  • examples/puzzletron/configs/families/qwen3_5/qwen3p5_0p8b/advanced.yaml
  • examples/puzzletron/configs/families/qwen3_5/qwen3p5_0p8b/model.yaml
  • tests/unit/torch/puzzletron/test_portable_configs.py
  • tests/unit/torch/puzzletron/test_qwen3p5_0p8b_example.py

Comment thread examples/puzzletron/configs/families/qwen3_5/qwen3p5_0p8b/advanced.yaml Outdated
Prevent the blocked GDN target from entering advanced searches and pin Hub downloads to the configured model revision.

Signed-off-by: Johannes Rausch <jrausch@nvidia.com>
@j-rausch
j-rausch marked this pull request as draft August 8, 2026 13:19

@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.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

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/puzzletron/stages/convert.py`:
- Line 281: Update _is_complete_checkpoint and the surrounding convert_stage
resume logic to include model_cfg.get("revision") in the teacher checkpoint
identity, storing and comparing it before marking the stage skipped. Ensure
checkpoints from different source revisions are not reused, and add a regression
test covering the revision mismatch.
🪄 Autofix

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: 806e8377-150e-4e6b-9cca-9504f635fa0a

📥 Commits

Reviewing files that changed from the base of the PR and between d10ccbd and ed546ec.

📒 Files selected for processing (5)
  • examples/puzzletron/configs/families/qwen3_5/qwen3p5_0p8b/advanced.yaml
  • examples/puzzletron/configs/families/qwen3_5/qwen3p5_0p8b/model.yaml
  • modelopt/torch/puzzletron/stages/convert.py
  • tests/unit/torch/puzzletron/test_convert_anymodel.py
  • tests/unit/torch/puzzletron/test_qwen3p5_0p8b_example.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • examples/puzzletron/configs/families/qwen3_5/qwen3p5_0p8b/advanced.yaml
  • examples/puzzletron/configs/families/qwen3_5/qwen3p5_0p8b/model.yaml
  • tests/unit/torch/puzzletron/test_qwen3p5_0p8b_example.py

Comment thread modelopt/torch/puzzletron/stages/convert.py Outdated
Signed-off-by: Johannes Rausch <jrausch@nvidia.com>
@j-rausch

j-rausch commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 1

🧹 Nitpick comments (3)
tests/unit/torch/puzzletron/test_convert_anymodel.py (2)

52-57: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider using the real dist helpers in single-process tests.

modelopt/torch/utils/distributed.py already degrades to single-process behavior: size() returns 1, broadcast returns the object unchanged, barrier returns early, and rank() returns 0. The fakes for is_master, broadcast, and barrier therefore add no isolation, and they hide call-signature drift. For example, lambda value, src: value breaks if production later calls dist.broadcast(obj) positionally without src.

Keep the _distributed_if_needed and _register_automodel_config_aliases patches, and drop the three dist patches so the tests exercise the real single-rank path.

♻️ Proposed simplification
 def _patch_single_rank_convert(monkeypatch):
     monkeypatch.setattr(convert_stage_module, "_register_automodel_config_aliases", lambda: None)
     monkeypatch.setattr(convert_stage_module, "_distributed_if_needed", nullcontext)
-    monkeypatch.setattr(convert_stage_module.dist, "is_master", lambda: True)
-    monkeypatch.setattr(convert_stage_module.dist, "broadcast", lambda value, src: value)
-    monkeypatch.setattr(convert_stage_module.dist, "barrier", lambda: None)

Based on learnings from the coding guidelines: "For backend or runtime behavior, include an end-to-end test using the real implementation rather than replacing it with a fake."

🤖 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 `@tests/unit/torch/puzzletron/test_convert_anymodel.py` around lines 52 - 57,
Update _patch_single_rank_convert to retain only the
_register_automodel_config_aliases and _distributed_if_needed patches. Remove
the dist.is_master, dist.broadcast, and dist.barrier monkeypatches so
single-process tests use the real distributed helpers and their production call
signatures.

Source: Coding guidelines


409-436: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider covering the ambiguous transaction state.

This test covers both crash windows of _publish_conversion_transaction. It does not cover the third branch, where the backup directory, the checkpoint directory, and the transaction directory all exist. That branch raises RuntimeError("ambiguous conversion transaction state...") and protects against deleting the wrong checkpoint. Add a short case so a future change cannot silently turn the guard into a delete.

💚 Proposed additional coverage
     convert_stage_module._recover_conversion_transaction(teacher_dir)
 
     assert (teacher_dir / "published-shard.bin").read_text() == "published"
     assert not backup_dir.exists()
+
+    backup_dir.mkdir()
+    transaction_dir.mkdir()
+    with pytest.raises(RuntimeError, match="ambiguous"):
+        convert_stage_module._recover_conversion_transaction(teacher_dir)
+    assert (teacher_dir / "published-shard.bin").read_text() == "published"
🤖 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 `@tests/unit/torch/puzzletron/test_convert_anymodel.py` around lines 409 - 436,
Add a focused case to test_conversion_transaction_recovers_interrupted_swap that
creates the teacher, backup, checkpoint, and transaction directories
simultaneously, then assert _recover_conversion_transaction raises RuntimeError
with the ambiguous conversion transaction message and preserves all directories
and their contents.
modelopt/torch/puzzletron/stages/convert.py (1)

192-217: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Consider guarding the transaction with a file lock.

_prepare_conversion_transaction and _publish_conversion_transaction have no mutual exclusion across processes. Within one job, dist.is_master() limits writers to one rank. If two jobs share the same teacher_dir, the two runs can interleave: both create the transaction directory, and the second path.replace(backup_dir) can hit the ambiguous state or delete the other run's backup. The repository already provides FileLock in modelopt/torch/utils/distributed.py, which uses O_EXCL for this purpose.

Wrap prepare/publish in a lock on a sibling lock file if concurrent jobs on one experiment directory are supported.

🤖 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/puzzletron/stages/convert.py` around lines 192 - 217, Guard
the conversion transaction lifecycle in _prepare_conversion_transaction and
_publish_conversion_transaction with the repository’s existing FileLock, using a
lock file adjacent to the target path so concurrent jobs sharing the same
teacher directory cannot interleave. Hold the lock across recovery,
transaction-directory creation, publishing, rollback, and backup cleanup, while
preserving the current behavior once the lock is acquired.
🤖 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/puzzletron/stages/convert.py`:
- Around line 427-471: Wrap the master-only conversion and publishing block
around _prepare_conversion_transaction through _publish_conversion_transaction
in coordinated error handling that captures any exception on the master,
broadcasts the failure to all ranks, and raises it on every rank before reaching
dist.barrier(). Preserve the barrier only for successful conversions and ensure
non-master ranks do not wait when the master fails.

---

Nitpick comments:
In `@modelopt/torch/puzzletron/stages/convert.py`:
- Around line 192-217: Guard the conversion transaction lifecycle in
_prepare_conversion_transaction and _publish_conversion_transaction with the
repository’s existing FileLock, using a lock file adjacent to the target path so
concurrent jobs sharing the same teacher directory cannot interleave. Hold the
lock across recovery, transaction-directory creation, publishing, rollback, and
backup cleanup, while preserving the current behavior once the lock is acquired.

In `@tests/unit/torch/puzzletron/test_convert_anymodel.py`:
- Around line 52-57: Update _patch_single_rank_convert to retain only the
_register_automodel_config_aliases and _distributed_if_needed patches. Remove
the dist.is_master, dist.broadcast, and dist.barrier monkeypatches so
single-process tests use the real distributed helpers and their production call
signatures.
- Around line 409-436: Add a focused case to
test_conversion_transaction_recovers_interrupted_swap that creates the teacher,
backup, checkpoint, and transaction directories simultaneously, then assert
_recover_conversion_transaction raises RuntimeError with the ambiguous
conversion transaction message and preserves all directories and their contents.
🪄 Autofix

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: 72169ca5-cb5e-469e-9270-ebb4248f50e4

📥 Commits

Reviewing files that changed from the base of the PR and between ed546ec and 7b0ed7c.

📒 Files selected for processing (2)
  • modelopt/torch/puzzletron/stages/convert.py
  • tests/unit/torch/puzzletron/test_convert_anymodel.py

Comment thread modelopt/torch/puzzletron/stages/convert.py
Signed-off-by: Johannes Rausch <jrausch@nvidia.com>
@j-rausch

j-rausch commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Signed-off-by: Johannes Rausch <jrausch@nvidia.com>
@j-rausch

j-rausch commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants