Skip to content

Add DFlash model converter - #617

Merged
shanjiaz merged 7 commits into
vllm-project:mainfrom
guan404ming:feat/dflash-converter
Jun 24, 2026
Merged

Add DFlash model converter#617
shanjiaz merged 7 commits into
vllm-project:mainfrom
guan404ming:feat/dflash-converter

Conversation

@guan404ming

@guan404ming guan404ming commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Purpose

Close #616

External DFlash checkpoints (e.g. z-lab/*-DFlash) had no path into the Speculators format, so they could not be loaded or finetuned via from_pretrained.

Tests

  • add mocked _build_config unit tests
  • test on a real checkpoint: converted z-lab/Qwen3-8B-DFlash-b16 with verifier Qwen/Qwen3-8B, reloaded via from_pretrained with weights bit-identical to source

Checklist

I have filled in:

  • The purpose of the PR, such as "Fix some issue (link existing issues this PR will resolve)".
  • The test plan/results, such as providing test command and pasting the results.
  • (Optional) The necessary documentation update.
  • I (a human) have written or reviewed the code in this pr to the best of my ability.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1dab9309-ba25-4ea3-bbcd-e3f51bfb84a8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds DFlashConverter in a new src/speculators/convert/dflash/ package. The converter builds a SpeculatorsConfig from a DFlash source checkpoint, filters and loads draft weights, injects verifier weights, and optionally validates the output for NaNs. convert_model in entrypoints.py gains a "dflash" dispatch branch. Unit tests cover _build_config behavior.

Changes

DFlash Conversion Support

Layer / File(s) Summary
DFlashConverter: config, save, validate
src/speculators/convert/dflash/__init__.py, src/speculators/convert/dflash/converter.py
Defines the DFlashConverter class. _build_config strips non-transformer keys, validates hidden_size against the base model, derives aux_hidden_state_layer_ids from dflash_config.target_layer_ids with a +1 offset, and builds a SpeculatorsConfig with a greedy proposal method. _save filters out t2d/d2t tensors, loads weights with strict=False, raises on unexpected keys, verifies layers.* weights are present, injects verifier weights, casts dtype, and calls save_pretrained. _validate reloads the checkpoint and checks fc.weight, lm_head.weight, and embed_tokens.weight for NaNs. The package __init__ re-exports DFlashConverter.
convert_model entrypoint: DFlash dispatch
src/speculators/convert/entrypoints.py
Imports DFlashConverter, broadens the algorithm Literal type to include "dflash", extends module and function docstrings with DFlash usage examples and kwargs documentation, and adds an elif algorithm == "dflash" branch invoking DFlashConverter().convert(...).
Unit tests for _build_config
tests/unit/convert/test_dflash_converter.py
Adds TestBuildConfig with four test cases: happy path asserting all derived config fields (verifier path, vocab/mask IDs, speculative token count, aux layer ID offset, dflash_config exclusion from transformer_layer_config), explicit aux_hidden_state_layer_ids override, ValueError on hidden_size mismatch, and ValueError when target_layer_ids is absent.

Possibly related issues

  • [RFC]: Add DFlash model converter #616: This PR directly implements the DFlashConverter class and pipeline integration described in that RFC issue, fulfilling the checkpoint conversion feature request for DFlash.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add DFlash model converter' directly and clearly describes the main change—implementing a DFlash converter to enable loading external DFlash checkpoints into the Speculators format.
Description check ✅ Passed The description is well-related to the changeset, explaining the purpose (enabling DFlash checkpoint conversion), the test approach (unit tests and real checkpoint validation), and providing relevant context about the issue being resolved.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@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: 2

🧹 Nitpick comments (1)
tests/unit/convert/test_dflash_converter.py (1)

33-75: 🏗️ Heavy lift

Expand coverage to _save, _validate, and entrypoint dispatch.

These tests only exercise _build_config; the new conversion logic in _save/_validate and convert_model(..., algorithm="dflash") remains untested. Add focused tests for missing critical keys, NaN validation failure, and DFlash branch wiring.

As per coding guidelines, tests/**/*.py: "Verify that new code paths introduced in the PR are covered."

🤖 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/convert/test_dflash_converter.py` around lines 33 - 75, The test
file currently only covers the _build_config method in the TestBuildConfig
class, leaving critical code paths untested. Add new test methods to cover the
_save method (including scenarios with missing critical keys), the _validate
method (including NaN validation failure cases), and the entrypoint dispatch
logic in convert_model when algorithm="dflash" is specified. Create separate
test methods within TestBuildConfig or new test classes (TestSave, TestValidate,
TestEntrypoint) that mock dependencies appropriately and verify the correct
behavior and error handling for each of these three areas.

Source: Coding guidelines

🤖 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 `@src/speculators/convert/dflash/converter.py`:
- Line 150: The code at line 150 in the converter.py file uses
next(iter(body.values())) to infer the dtype without checking if the body
dictionary is empty. If all keys are filtered out or the checkpoint is
malformed, this will raise a StopIteration exception which is hard to diagnose.
Add a guard condition to check if body is not empty before attempting to infer
the dtype from body.values(), and either skip the dtype conversion or raise a
more informative error message if body is empty.
- Around line 133-143: The critical_missing validation currently only checks for
missing keys that start with "layers.", but other required draft-body weights
like "fc.weight", "hidden_norm.*", and "norm.*" can also be absent and will
silently initialize with default values instead of checkpoint values. Expand the
critical_missing filter to include all required weight patterns in the
DFlashDraftModel, not just "layers.*", by adding additional conditions to check
for missing keys from the "fc", "hidden_norm", and "norm" components, ensuring
that any absent critical weights are caught and raised as an error.

---

Nitpick comments:
In `@tests/unit/convert/test_dflash_converter.py`:
- Around line 33-75: The test file currently only covers the _build_config
method in the TestBuildConfig class, leaving critical code paths untested. Add
new test methods to cover the _save method (including scenarios with missing
critical keys), the _validate method (including NaN validation failure cases),
and the entrypoint dispatch logic in convert_model when algorithm="dflash" is
specified. Create separate test methods within TestBuildConfig or new test
classes (TestSave, TestValidate, TestEntrypoint) that mock dependencies
appropriately and verify the correct behavior and error handling for each of
these three areas.
🪄 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: Pro

Run ID: 0ab64bec-032a-403a-9221-c3a2aee8d1c2

📥 Commits

Reviewing files that changed from the base of the PR and between 04dd376 and 20dc732.

📒 Files selected for processing (4)
  • src/speculators/convert/dflash/__init__.py
  • src/speculators/convert/dflash/converter.py
  • src/speculators/convert/entrypoints.py
  • tests/unit/convert/test_dflash_converter.py

Comment thread src/speculators/convert/dflash/converter.py Outdated
Comment thread src/speculators/convert/dflash/converter.py
@mergify

mergify Bot commented Jun 18, 2026

Copy link
Copy Markdown

The quality checks have failed. Please run make style and make quality under
the root directory to address the lint failures. You will need to install the
dev optional install to get the required linting packages:
https://github.com/vllm-project/speculators/blob/main/CONTRIBUTING.md

@guan404ming
guan404ming force-pushed the feat/dflash-converter branch from 60dff12 to 3548e66 Compare June 19, 2026 00:07
Comment thread src/speculators/convert/dflash/converter.py
Comment thread src/speculators/convert/dflash/converter.py
Comment thread src/speculators/convert/dflash/converter.py
Comment thread src/speculators/model.py
@guan404ming
guan404ming requested a review from shanjiaz June 21, 2026 11:50
@mergify mergify Bot removed the quality-failed label Jun 22, 2026
@guan404ming
guan404ming force-pushed the feat/dflash-converter branch from 0a8f412 to c263a7c Compare June 23, 2026 00:35
@mergify

mergify Bot commented Jun 23, 2026

Copy link
Copy Markdown

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @guan404ming.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Jun 23, 2026
Signed-off-by: Guan-Ming (Wesley) Chiu <105915352+guan404ming@users.noreply.github.com>
Signed-off-by: Guan-Ming (Wesley) Chiu <105915352+guan404ming@users.noreply.github.com>
Signed-off-by: Guan-Ming (Wesley) Chiu <105915352+guan404ming@users.noreply.github.com>
Signed-off-by: Guan-Ming (Wesley) Chiu <105915352+guan404ming@users.noreply.github.com>
Signed-off-by: Guan-Ming (Wesley) Chiu <105915352+guan404ming@users.noreply.github.com>
@guan404ming
guan404ming force-pushed the feat/dflash-converter branch from c263a7c to 3496fd2 Compare June 23, 2026 16:00
@mergify mergify Bot removed the needs-rebase label Jun 23, 2026
@guan404ming

Copy link
Copy Markdown
Contributor Author

Thanks @shanjiaz !

@shanjiaz
shanjiaz enabled auto-merge (squash) June 24, 2026 13:44
@shanjiaz shanjiaz added the ready This PR is ready for review label Jun 24, 2026
@shanjiaz
shanjiaz merged commit 31374a5 into vllm-project:main Jun 24, 2026
9 checks passed
@guan404ming
guan404ming deleted the feat/dflash-converter branch June 25, 2026 01:21
@coderabbitai coderabbitai Bot mentioned this pull request Jun 25, 2026
4 tasks
orestis-z pushed a commit to orestis-z/speculators that referenced this pull request Jun 26, 2026
<!-- markdownlint-disable -->

<!-- PLEASE FILL IN THE PR DESCRIPTION HERE ENSURING ALL CHECKLIST ITEMS
(AT THE BOTTOM) HAVE BEEN CONSIDERED. -->

## Purpose

Close vllm-project#616

External DFlash checkpoints (e.g. z-lab/*-DFlash) had no path into the
Speculators format, so they could not be loaded or finetuned via
from_pretrained.

## Tests

- add mocked _build_config unit tests
- test on a real checkpoint: converted `z-lab/Qwen3-8B-DFlash-b16` with
verifier `Qwen/Qwen3-8B`, reloaded via `from_pretrained` with weights
bit-identical to source

## Checklist

I have filled in:

- [x] The purpose of the PR, such as "Fix some issue (link existing
issues this PR will resolve)".
- [x] The test plan/results, such as providing test command and pasting
the results.
- [ ] (Optional) The necessary documentation update.
- [x] I (a human) have written or reviewed the code in this pr to the
best of my ability.

---------

Signed-off-by: Guan-Ming (Wesley) Chiu <105915352+guan404ming@users.noreply.github.com>
Co-authored-by: shanjiaz <zsjwpianpian@gmail.com>
@coderabbitai coderabbitai Bot mentioned this pull request Jun 26, 2026
4 tasks
shanjiaz pushed a commit that referenced this pull request Jun 26, 2026
<!-- markdownlint-disable -->

> ⚠️ **DO NOT MERGE before #672.** This PR is stacked on #672 (remove
eagle converter) and its base is `remove-eagle-converter`. Merging this
first would pull in #672's changes prematurely and/or land against the
wrong base. Merge order: **#672 first, then this.** Once #672 merges, I
will rebase this onto `main`. The diff here is the 3-line loader change
only.

## Purpose

Fix `TypeError: Eagle3DraftModel.__init__() got an unexpected keyword
argument 'verifier'` raised during draft model construction in
`scripts/train.py --from-pretrained`.

This breaks the EAGLE3 finetuning smoke test:

```
tests/e2e/smoke/test_finetuning_sanity.py::test_finetuning_weight_sanity
TypeError: Eagle3DraftModel.__init__() got an unexpected keyword argument 'verifier'
```

`build_draft_model` passes `verifier=args.verifier_name_or_path` to
`from_pretrained` (for the external-checkpoint auto-convert path added
in #617). `SpeculatorModel.from_pretrained` had no `verifier` parameter,
so it stayed in `**kwargs`, was forwarded to HF's `from_pretrained`, and
reached the model constructor `cls(config, **kwargs)`. Draft models take
only `config` and reject it.

## Fix

Make `verifier` an explicit named parameter of
`SpeculatorModel.from_pretrained` so it is consumed at the loader
boundary (never forwarded into the constructor), used directly for
auto-conversion, and forwarded through the base-class re-dispatch
alongside `t2d`/`d2t`.

With the attachment-style `EagleSpeculator` removed in #672, no model
constructor takes `verifier` anymore, so consuming it is sufficient — no
per-model special-casing needed.

## Tests

- Failing test fixed:
`tests/e2e/smoke/test_finetuning_sanity.py::test_finetuning_weight_sanity`
(covered on CI).
- `make style` / `make quality`: pass.
- `pytest tests/unit/test_model.py
tests/unit/convert/test_entrypoints.py`: 20 passed.

## Checklist

I have filled in:

- [x] The purpose of the PR, such as "Fix some issue (link existing
issues this PR will resolve)".
- [x] The test plan/results, such as providing test command and pasting
the results.
- [ ] (Optional) The necessary documentation update.
- [x] I (a human) have written or reviewed the code in this pr to the
best of my ability.

---------

Signed-off-by: shanjiaz <hezhao@redhat.com>
Signed-off-by: Rahul-Tuli <rtuli@redhat.com>
Co-authored-by: shanjiaz <hezhao@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready This PR is ready for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[RFC]: Add DFlash model converter

2 participants