Skip to content

[Feat]: Support Dspark - #1849

Merged
h-guo18 merged 1 commit into
mainfrom
haoguo/dpsark
Jul 7, 2026
Merged

[Feat]: Support Dspark#1849
h-guo18 merged 1 commit into
mainfrom
haoguo/dpsark

Conversation

@h-guo18

@h-guo18 h-guo18 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Type of change: New feature

Adds DSpark (DeepSeek-AI, "Confidence-Scheduled Speculative Decoding with Semi-Autoregressive Generation") as a third head in the DFlash family. DSpark keeps the parallel DFlash backbone for speed and adds a lightweight sequential Markov head that injects the intra-block causal dependency the parallel backbone lacks (mitigating suffix acceptance decay), plus an optional confidence head. The Markov head adds a prefix-dependent transition bias B_k to the backbone base logits, inducing a causal block distribution p_k(x_k | x_<k) = softmax(U_k + B_k).

  • Reuses the DFlash mode/pipeline; selected via dflash_architecture_config.projector_type=dspark.
  • Three head variants: vanilla (memoryless low-rank transition), gated (hidden-gated), rnn (GRU-like, full-prefix).
  • Trained with a three-term loss: ce_alpha·CE + l1_alpha·TVD + conf_alpha·confidence_BCE.
  • Export preserves the upstream DeepSpec submodule names so checkpoints stay portable.

New files: plugins/hf_dspark.py, plugins/modeling_dspark.py, recipe dspark.yaml, unit tests. Also touches config.py (loss-weight / head fields), dflash/conversion.py, plugins/__init__.py, and hf_spec_export.py (export support).

Usage

# modelopt_recipes/general/speculative_decoding/dspark.yaml (key fields)
dflash:
  dflash_architecture_config:
    projector_type: dspark          # select the DSpark head
  dflash_ce_loss_alpha: 0.1
  dflash_l1_loss_alpha: 0.9         # L1/TVD-dominant (DeepSpec default)
  dflash_confidence_head_alpha: 1.0 # 0 disables the confidence head

Testing

tests/unit/torch/speculative/plugins/test_hf_dspark.py covers: convert, all three head variants, confidence-head build/grads, forward loss + metrics + grads, exported weight-key layout, and that plain DFlash mode is unaffected. Train / export / AR-generate smoke-validated end-to-end.

Before your PR is "Ready for review"

Make sure you read and follow Contributor guidelines and your commits are signed (git commit -s -S).

Make sure you read and follow the Security Best Practices (e.g. avoiding hardcoded trust_remote_code=True, torch.load(..., weights_only=False), pickle, etc.).

  • Is this change backward compatible?: ✅
  • 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?: ❌ / N/A
  • Did you get Claude approval on this PR?: ❌ / N/A

Additional Information

Related: #1846 — DSpark shares the DFlash offline base-logit reconstruction path (final-norm fix); rebase on top of #1846 once it merges.

Summary by CodeRabbit

  • New Features

    • Added support for a new DSpark speculative decoding mode.
    • Introduced additional head options and an optional confidence output for more flexible generation behavior.
    • Exported DSpark models now include the needed DSpark-specific settings automatically.
  • Bug Fixes

    • Improved training and generation handling for DSpark configurations.
    • Added validation to catch missing or inconsistent DSpark settings earlier.

@copy-pr-bot

copy-pr-bot Bot commented Jun 29, 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 Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

An error occurred during the review process. Please try again later.

📝 Walkthrough

Walkthrough

Adds DSpark, a new projector type built on DFlash, including config fields for DSpark loss weights, conversion routing to a dedicated registry, a DSparkModule implementing vanilla/gated/rnn Markov heads and an optional confidence head, an HFDSparkModel training/generation plugin, a DSparkExporter, and unit tests.

Changes

DSpark Speculative Decoding

Layer / File(s) Summary
Config fields and conversion routing
modelopt/torch/speculative/config.py, modelopt/torch/speculative/dflash/conversion.py, modelopt/torch/speculative/plugins/__init__.py
Adds DSpark loss-weight fields to DFlashConfig, introduces DSparkDMRegistry, routes projector_type=="dspark" conversions to it, updates the unsupported-projector error message, and re-exports the hf_dspark plugin.
DSparkModule Markov head architecture
modelopt/torch/speculative/plugins/modeling_dspark.py
Defines DSparkModule (subclass of DFlashModule) with vanilla, gated, and rnn Markov head variants, explicit weight init, previous-token embedding lookup, block-level and single-step transition bias computation, and an optional confidence head.
HFDSparkModel training and generation plugin
modelopt/torch/speculative/plugins/hf_dspark.py
Implements HFDSparkModel registered with DSparkDMRegistry, _tvd_per_token chunked TVD helper, modify() validation, Markov head application, three-term DSpark loss computation (CE, TVD/L1, confidence BCE), training forward(), and no-grad pseudo_speculative_generate().
DSpark exporter
modelopt/torch/export/plugins/hf_spec_export.py
Adds DSparkExporter (subclass of DFlashExporter) overriding _export_config() to include DSpark head fields in exported config.
Unit tests
tests/unit/torch/speculative/plugins/test_hf_dspark.py
Adds tests covering conversion routing, Markov head variants, confidence head wiring, training forward/backward, and exporter output correctness.

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

Sequence Diagram(s)

sequenceDiagram
  participant Trainer
  participant HFDSparkModel
  participant BaseModel
  participant DSparkModule
  Trainer->>HFDSparkModel: forward(input_ids, labels)
  HFDSparkModel->>BaseModel: run for teacher logits
  HFDSparkModel->>DSparkModule: build draft hidden states
  DSparkModule-->>HFDSparkModel: hidden states and backbone logits
  HFDSparkModel->>HFDSparkModel: apply Markov head
  HFDSparkModel->>HFDSparkModel: compute CE, TVD/L1, confidence BCE
  HFDSparkModel-->>Trainer: ModelOutput with loss and metrics
Loading
sequenceDiagram
  participant Caller
  participant HFDSparkModel
  participant BaseModel
  participant DSparkModule
  Caller->>HFDSparkModel: pseudo_speculative_generate(input_ids)
  HFDSparkModel->>BaseModel: compute anchor token
  HFDSparkModel->>DSparkModule: run masked block context
  loop draft positions
    DSparkModule->>DSparkModule: markov_step(prev_token, hidden, state)
    DSparkModule-->>HFDSparkModel: corrected logits
    HFDSparkModel->>HFDSparkModel: argmax next draft token
  end
  HFDSparkModel-->>Caller: anchor token and draft tokens
Loading

Suggested reviewers: mxinO, kinjalpatel27

🚥 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 matches the main change: adding DSpark support across plugins, export, config, and tests.
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 Scans of all changed Python files found no torch.load(weights_only=False), numpy.load(allow_pickle=True), trust_remote_code=True, eval/exec, nosec, or new deps.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch haoguo/dpsark

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

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-07-07 10:32 UTC

@h-guo18 h-guo18 self-assigned this Jun 29, 2026
@codecov

codecov Bot commented Jun 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.61194% with 60 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.08%. Comparing base (bc5bc1a) to head (e5a35a5).

Files with missing lines Patch % Lines
modelopt/torch/speculative/plugins/hf_dspark.py 71.26% 50 Missing ⚠️
...elopt/torch/speculative/plugins/modeling_dspark.py 87.65% 10 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1849      +/-   ##
==========================================
- Coverage   77.69%   77.08%   -0.61%     
==========================================
  Files         517      519       +2     
  Lines       57535    57803     +268     
==========================================
- Hits        44699    44556     -143     
- Misses      12836    13247     +411     
Flag Coverage Δ
examples 43.02% <16.04%> (-0.25%) ⬇️
gpu 57.75% <16.41%> (-0.87%) ⬇️
regression 14.95% <16.41%> (+0.12%) ⬆️
unit 55.26% <77.61%> (+0.10%) ⬆️

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.

@h-guo18
h-guo18 marked this pull request as ready for review July 3, 2026 01:43
@h-guo18
h-guo18 requested review from a team as code owners July 3, 2026 01:43
@h-guo18
h-guo18 requested review from ChenhanYu and realAsma July 3, 2026 01:43
@h-guo18

h-guo18 commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

/claude review

@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

♻️ Duplicate comments (1)
modelopt/torch/speculative/plugins/hf_dspark.py (1)

1-51: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Same duplicate/inconsistent license header issue as modeling_dspark.py.

This file has the identical problem: a standalone Apache-2.0 header (lines 1-14, 2026) duplicated on top of the correctly combined "Apache-2.0 AND MIT" header (lines 37-50, 2024) that wraps the DeepSpec attribution (lines 16-35). The reference link also points to blob/main/...loss.py instead of a pinned commit hash.

As per coding guidelines: "The file which has code copied from another third-party GitHub repository should have the following in order: 1. A reference link (with commit hash)... 2. The original repository's Copyright/License. 3. The NVIDIA Apache 2.0 Copyright/License header," and copied files should be excluded from the insert-license pre-commit hook.

📄 Proposed fix
-# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-# SPDX-License-Identifier: Apache-2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Adapted from https://github.com/deepseek-ai/DeepSpec/blob/main/deepspec/modeling/dspark/loss.py
+# Adapted from https://github.com/deepseek-ai/DeepSpec/blob/<commit-sha>/deepspec/modeling/dspark/loss.py
 # Copyright (c) 2026 The DeepSpec Authors
🤖 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/speculative/plugins/hf_dspark.py` around lines 1 - 51, The
file has a duplicated and inconsistent license header, so keep only the
correctly ordered combined notice and remove the extra standalone Apache-2.0
block at the top. Ensure the DeepSpec attribution in this header uses a pinned
commit-hash reference instead of a branch-based link, and preserve the expected
order in this plugin file: reference link, original third-party
copyright/license, then the NVIDIA Apache-2.0 header. Also make sure this copied
file is excluded from the insert-license pre-commit hook so the header is not
rewritten again.

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 `@modelopt/torch/speculative/plugins/modeling_dspark.py`:
- Around line 1-51: The file has duplicated and inconsistent license headers
because the generic NVIDIA Apache-2.0 header was auto-inserted on top of the
copied DeepSpec header. Update modeling_dspark.py to keep the required header
order for copied third-party code: pinned DeepSpec reference link, original
DeepSpec copyright/license text, then the NVIDIA Apache-2.0 header, and remove
the duplicate SPDX block. Also add this file to the insert-license hook exclude
list in .pre-commit-config.yaml so the header is not re-added, and reference the
existing DeepSpec attribution section and SPDX-License-Identifier lines when
editing.

---

Duplicate comments:
In `@modelopt/torch/speculative/plugins/hf_dspark.py`:
- Around line 1-51: The file has a duplicated and inconsistent license header,
so keep only the correctly ordered combined notice and remove the extra
standalone Apache-2.0 block at the top. Ensure the DeepSpec attribution in this
header uses a pinned commit-hash reference instead of a branch-based link, and
preserve the expected order in this plugin file: reference link, original
third-party copyright/license, then the NVIDIA Apache-2.0 header. Also make sure
this copied file is excluded from the insert-license pre-commit hook so the
header is not rewritten again.
🪄 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: d9c9750f-27de-43e0-90d1-d82c8fd1efb7

📥 Commits

Reviewing files that changed from the base of the PR and between f335459 and 133f22f.

📒 Files selected for processing (8)
  • modelopt/torch/export/plugins/hf_spec_export.py
  • modelopt/torch/speculative/config.py
  • modelopt/torch/speculative/dflash/conversion.py
  • modelopt/torch/speculative/plugins/__init__.py
  • modelopt/torch/speculative/plugins/hf_dspark.py
  • modelopt/torch/speculative/plugins/modeling_dspark.py
  • modelopt_recipes/general/speculative_decoding/dspark.yaml
  • tests/unit/torch/speculative/plugins/test_hf_dspark.py

Comment on lines +1 to +51
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Adapted from https://github.com/deepseek-ai/DeepSpec/blob/main/deepspec/modeling/dspark/markov_head.py
# Copyright (c) 2026 The DeepSpec Authors
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 AND MIT
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Duplicate/inconsistent license headers — likely missing pre-commit exclude entry.

This file has two separate NVIDIA header blocks: a plain Apache-2.0 header (lines 1-14, copyright 2026) and a second combined "Apache-2.0 AND MIT" header (lines 37-50, copyright 2024) wrapping the DeepSpec attribution/MIT text (lines 16-35). The mismatched years and duplicated SPDX-License-Identifier lines indicate the insert-license pre-commit hook re-added a generic header on top because this file wasn't added to its exclude list. Also, the DeepSpec reference link points at blob/main/... rather than a pinned commit hash.

As per coding guidelines: "The file which has code copied from another third-party GitHub repository should have the following in order: 1. A reference link (with commit hash)... 2. The original repository's Copyright/License. 3. The NVIDIA Apache 2.0 Copyright/License header" and "Exclude copied files from the license pre-commit hook so it doesn't auto-add the NVIDIA Apache 2.0 license on top of the file."

📄 Proposed fix: remove duplicate header, pin commit hash
-# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
-# SPDX-License-Identifier: Apache-2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Adapted from https://github.com/deepseek-ai/DeepSpec/blob/main/deepspec/modeling/dspark/markov_head.py
+# Adapted from https://github.com/deepseek-ai/DeepSpec/blob/<commit-sha>/deepspec/modeling/dspark/markov_head.py
 # Copyright (c) 2026 The DeepSpec Authors

Then add this file's path to the insert-license hook's exclude list in .pre-commit-config.yaml.

Run the following to confirm the exclude list and check for other files sharing this pattern:

#!/bin/bash
rg -n "exclude" .pre-commit-config.yaml -A5
rg -n "insert-license" .pre-commit-config.yaml -A15
rg -nP "SPDX-License-Identifier" modelopt/torch/speculative/plugins/modeling_dspark.py modelopt/torch/speculative/plugins/hf_dspark.py
🤖 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/speculative/plugins/modeling_dspark.py` around lines 1 - 51,
The file has duplicated and inconsistent license headers because the generic
NVIDIA Apache-2.0 header was auto-inserted on top of the copied DeepSpec header.
Update modeling_dspark.py to keep the required header order for copied
third-party code: pinned DeepSpec reference link, original DeepSpec
copyright/license text, then the NVIDIA Apache-2.0 header, and remove the
duplicate SPDX block. Also add this file to the insert-license hook exclude list
in .pre-commit-config.yaml so the header is not re-added, and reference the
existing DeepSpec attribution section and SPDX-License-Identifier lines when
editing.

Source: Coding guidelines



def _tvd_per_token(final_logits, teacher_logits, chunk_size=1024):
"""Total-variation distance ||softmax(a)-softmax(b)||_1 / ... per token, memory-lean.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[SUGGESTION] _tvd_per_token is named/documented as the "total-variation distance" but actually returns the L1 distance ||softmax(a)-softmax(b)||_1, which is 2·TVD (TVD = ½·L1). The math downstream is internally consistent — l1_loss uses the raw L1, and accept_rate = 1 - 0.5*l1_per_token correctly yields 1 - TVD — but the naming is a latent footgun: a future maintainer who "corrects" this to return an actual TVD (0.5 * ||·||_1) would silently break the accept_rate target (→ 1 - 0.25·L1) and halve the confidence supervision signal.

Suggest either renaming to _l1_per_token (documenting the return as L1 = 2·TVD), or keeping the name but returning 0.5 * ... and updating the accept_rate/l1_loss call sites. The former is the smaller, safer change.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude review passed — no blocking issues found. LGTM

SCOPE
PR is additive: introduces DSpark as a third head in the DFlash family, selected via dflash_architecture_config.projector_type=dspark, reusing the existing DFlash mode/pipeline/registry. 8 files changed. I reviewed all of the PRs own files (plugins/hf_dspark.py, plugins/modeling_dspark.py, config.py, dflash/conversion.py, plugins/init.py, export/plugins/hf_spec_export.py, the dspark.yaml recipe, and the unit test) and cross-checked the DFlash parent (hf_dflash.py) for the integration/shape contracts. Note: a two-dot diff against origin/main surfaces ~20 commits of unrelated churn because the branch is behind main; those files are not part of this PR and were not reviewed.

FINDINGS

  • CRITICAL: 0
  • IMPORTANT: 0
  • SUGGESTION: 1 — _tvd_per_token returns L1 (= 2*TVD) despite its total-variation-distance name; internally consistent today but a rename footgun. Non-blocking.

ASSESSMENT
Low risk. The algorithm is coherent end-to-end:

  • Alignment is consistent between training and generation — shift_label next-token alignment (position k conditions on the prev token at anchor+k, predicts anchor+k+1; position 0s predecessor is the anchor) matches across _apply_markov_head/_compute_dspark_loss and pseudo_speculative_generate.
  • Confidence target 1 - 0.5*L1 = 1 - TVD is the correct speculative-sampling acceptance probability.
  • DDP/grad flow is handled (dummy loss flows through all draft params; recipe sets ddp_find_unused_parameters=true for the disabled-confidence-head case), and confidence_head_alpha>0 without a built head is validated in modify.
  • Mode/registry: own DSparkDMRegistry avoids clobbering HFDFlashModel; convert_to_dflash_model routes correctly and the error message lists the new option.
  • Export: markov head weights ride the inherited dflash_module. stripping; extra loader config fields added, mirroring DominoExporter.
  • Backward compat: new dflash_*_alpha config fields are optional with defaults and inert unless projector_type==dspark; DFlash/EAGLE/Domino paths untouched.

The single SUGGESTION is a naming/maintainability nit and does not block.



def _tvd_per_token(final_logits, teacher_logits, chunk_size=1024):
"""Total-variation distance ||softmax(a)-softmax(b)||_1 / ... per token, memory-lean.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[SUGGESTION] _tvd_per_token is named/documented as the "total-variation distance" but actually returns the L1 distance ||softmax(a)-softmax(b)||_1, which is 2·TVD (TVD = ½·L1). The math downstream is internally consistent — l1_loss uses the raw L1, and accept_rate = 1 - 0.5*l1_per_token correctly yields 1 - TVD — but the naming is a latent footgun: a future maintainer who "corrects" this function to return an actual TVD (0.5 * ||·||_1) would silently break the accept_rate target (it would become 1 - 0.25·L1) and halve the confidence supervision signal.

Suggest either renaming to _l1_per_token (and describing the return as the L1 distance = 2·TVD), or keeping the name but returning 0.5 * ... and updating the accept_rate/l1_loss call sites accordingly. The former is the smaller, safer change.

@copy-pr-bot

copy-pr-bot Bot commented Jul 7, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

Signed-off-by: h-guo18 <67671475+h-guo18@users.noreply.github.com>
@h-guo18
h-guo18 merged commit d290839 into main Jul 7, 2026
53 checks passed
@h-guo18
h-guo18 deleted the haoguo/dpsark branch July 7, 2026 10:32
h-guo18 added a commit that referenced this pull request Jul 9, 2026
Adds modelopt_recipes/general/speculative_decoding/dspark.yaml, which selects
the DSpark head via dflash_architecture_config.projector_type=dspark and sets
the three-term loss weights (ce/l1/confidence).

Stacked on the DSpark feature PR (#1849): the recipe uses the config fields
added there, so this PR is based on that branch and should merge after it.

Signed-off-by: h-guo18 <67671475+h-guo18@users.noreply.github.com>
h-guo18 added a commit that referenced this pull request Jul 10, 2026
### What does this PR do?

**Type of change:** New feature (recipe + examples)

Adds the DSpark training recipe and Kimi launcher examples for streaming
speculative-decoding training. Split out of #1849 to keep that PR
focused on the DSpark head implementation.

**Files added (5, all additive — no code changes):**

1. `modelopt_recipes/general/speculative_decoding/dspark.yaml` — the
DSpark training recipe. Selects the DSpark head via
`dflash_architecture_config.projector_type=dspark` (DFlash backbone +
lightweight sequential/Markov head + optional confidence head) and sets
the three-term loss weights (`dflash_ce_loss_alpha` /
`dflash_l1_loss_alpha` / `dflash_confidence_head_alpha`).

2–5.
`tools/launcher/examples/moonshotai/{Kimi-K2.6,Kimi-K2.7-Code}/hf_streaming_{dflash,dspark}_multi_node.yaml`
— four multi-node streaming launcher examples mirroring the existing
Kimi-K2.5 streaming format (`common/eagle3/train_eagle_streaming.sh`).
They carry the Kimi-specific base path, draft dims, capture ids, and
mask token; the DSpark examples build on `dspark.yaml` and override only
the Kimi-specific fields (draft dims, `dflash_block_size=8`, mask
token). K2.7-Code shares the K2.6 architecture (`kimi_k25`, 61 layers),
so the draft config is identical.

### Dependency

**Stacked on #1849.** The recipe uses the config fields
(`dflash_ce_loss_alpha`, `dflash_l1_loss_alpha`,
`dflash_confidence_head_alpha`) added in #1849, so this PR is based on
that branch and must merge **after** it. GitHub will auto-retarget the
base to `main` once #1849 merges.

### Testing

- `dspark.yaml` passes the `validate modelopt recipes` schema check
(against the #1849 config schema).
- The launcher examples ship a placeholder `container:
<vllm-image-with-aux-capture-fix>` and are meant to be adapted per
cluster (image, account, partition), not run verbatim in CI.

- Backward compatible?: ✅ (additive recipe + example files only)

🤖 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**
* Added a DSpark speculative-decoding training recipe with configurable
draft, optional per-position confidence, and Markov head components.
* Added new multi-node streaming training example workflows for
Kimi-K2.6 using DSpark/DFlash, including dataset preparation plus
coordinated serve/train settings.
* Configured answer-only loss options, masking behavior, training
hyperparameters, checkpoint/log cadence, and capture-id wiring with
sensible default runtime timeouts.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: h-guo18 <67671475+h-guo18@users.noreply.github.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.

2 participants