Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .agents/review-guidelines/technical-blog.md

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.

Does this file need to be linked in top-level AGENTS.md or its automatically picked up?

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.

You have to mention explicitly. I will add some simple instructions for folks to trigger the technical blog review.

@kevalmorabia97 kevalmorabia97 Aug 13, 2026

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.

Do we want to also require a ModelOpt commit hash / version and container used in case of tutorial blogs / experimental results?

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 think that will be a next step.

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Technical blog review guideline

Use this rubric when a pull-request comment requests a **technical blog** or
**technical announcement** review. It applies to public-facing documentation
such as `docs/source/announcements/` and complements the repository's normal
code-review guidance.

## Review scope

Review the changed announcement and its landing-page card together. Do not
review unrelated source files unless they provide evidence for a claim in the
post.

## Checks

1. **Factual support** — Every technical claim, performance number, and
comparison must be supported by a cited public source, a clearly identified
reproducible measurement, or a qualified statement. Flag claims that
overstate what the cited source establishes.
2. **Citation integrity** — Check that cited papers, repositories, checkpoints,
and issue or PR links exist and match the surrounding claim. Publication
dates must not precede the cited source's availability.
3. **Technical precision** — Preserve meaningful distinctions: measured versus
inferred results, training versus serving behavior, throughput versus
latency, architecture versus implementation detail, and public facts versus
internal context.
4. **Figure provenance** — Images need an accurate alt text and a source or
provenance that makes their public use appropriate. Captions and nearby
text must not imply a result the figure does not show.
5. **Public-release suitability** — Do not expose private infrastructure,
unreleased products, confidential benchmark data, credentials, internal
URLs, or claims that cannot be independently supported by public material.
6. **Reader clarity** — Verify the title, date, author, summary, tags, and
announcement-card metadata agree. Prefer precise terminology over marketing
shorthand when the two could be confused.

## Findings

Raise only material findings. Each finding should identify the exact claim,
explain the public-facing risk, and propose a concrete correction. Do not
duplicate routine style, spelling, or formatting feedback already handled by
CodeRabbit.
142 changes: 142 additions & 0 deletions docs/source/_static/announcements.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/* Scoped announcement styles for the Sphinx RTD theme. */

#announcements > h1,
#announcements > p,
.announcement-section {
max-width: 860px;
margin-left: auto;
margin-right: auto;
}

.announcement-section {
width: 100%;
}

.announcement-toolbar {
border: 1px solid #d6d8dc;
border-radius: 4px;
margin: 1.5rem 0;
padding: 1rem;
background: #f8f9fb;
}

.announcement-search-label {
display: block;
font-weight: 700;
margin-bottom: 0.35rem;
}

.announcement-search {
box-sizing: border-box;
width: 100%;
padding: 0.55rem 0.65rem;
border: 1px solid #b8bdc6;
border-radius: 4px;
font-size: 1rem;
}

.announcement-tags {
display: flex;
flex-wrap: wrap;
gap: 0.45rem;
margin-top: 0.75rem;
}

.announcement-tag {
border: 1px solid #9aa1ad;
border-radius: 999px;
padding: 0.28rem 0.65rem;
background: #fff;
color: #2f343d;
cursor: pointer;
font-size: 0.86rem;
}

.announcement-tag.is-active,
.announcement-tag:hover {
border-color: #76b900;
background: #76b900;
color: #111;
}

.announcement-grid {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 1rem;
margin: 1rem 0 1.25rem;
}

.announcement-card {
border-bottom: 1px solid #d6d8dc;
padding: 0 0 1rem;
}

.announcement-card:last-child {
border-bottom: 0;
}

.announcement-card h2 {
margin-top: 0.25rem;
font-size: 1.2rem;
line-height: 1.35;
}

.announcement-card p {
margin-bottom: 0.75rem;
}

.announcement-card-meta {
color: #6b7280;
font-size: 0.85rem;
}

.announcement-card-tags {
display: flex;
flex-wrap: wrap;
gap: 0.35rem;
}

.announcement-card-tags span {
border: 1px solid #d6d8dc;
border-radius: 999px;
color: #4b5563;
font-size: 0.78rem;
padding: 0.15rem 0.45rem;
}

.announcement-empty {
border-left: 4px solid #76b900;
padding-left: 0.75rem;
}


.announcement-pager {
align-items: center;
display: flex;
gap: 0.75rem;
justify-content: flex-end;
margin: 0 0 2rem;
}

.announcement-page-button {
border: 1px solid #9aa1ad;
border-radius: 4px;
background: #fff;
color: #2f343d;
cursor: pointer;
padding: 0.35rem 0.7rem;
}

.announcement-page-button:disabled {
cursor: not-allowed;
opacity: 0.45;
}

.announcement-page-status {
color: #4b5563;
font-size: 0.9rem;
}

.toctree-wrapper.compound:empty {
display: none;
}
88 changes: 88 additions & 0 deletions docs/source/_static/announcements.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
document.addEventListener('DOMContentLoaded', () => {
const search = document.querySelector('#announcement-search');
const cards = Array.from(document.querySelectorAll('.announcement-card')).sort((left, right) => {
return (right.dataset.date || '').localeCompare(left.dataset.date || '');
});
const tags = Array.from(document.querySelectorAll('.announcement-tag'));
const empty = document.querySelector('#announcement-empty');
const pager = document.querySelector('#announcement-pager');
const prev = document.querySelector('#announcement-prev');
const next = document.querySelector('#announcement-next');
const status = document.querySelector('#announcement-page-status');
const pageSize = 5;

cards.forEach((card) => card.parentNode.appendChild(card));
let activeTag = 'all';
let currentPage = 1;

if (!search || cards.length === 0) {
return;
}

const matchingCards = () => {
const query = search.value.trim().toLowerCase();
return cards.filter((card) => {
const haystack =
[ card.dataset.title, card.dataset.summary, card.dataset.tags ].join(' ').toLowerCase();
const tagMatch =
activeTag === 'all' || (card.dataset.tags || '').split(' ').includes(activeTag);
const searchMatch = !query || haystack.includes(query);
return tagMatch && searchMatch;
});
};

const update = () => {
const matches = matchingCards();
const pageCount = Math.max(1, Math.ceil(matches.length / pageSize));
currentPage = Math.min(currentPage, pageCount);
const start = (currentPage - 1) * pageSize;
const pageCards = new Set(matches.slice(start, start + pageSize));

cards.forEach((card) => { card.hidden = !pageCards.has(card); });

if (empty) {
empty.hidden = matches.length !== 0;
}

if (pager && prev && next && status) {
pager.hidden = matches.length <= pageSize;
prev.disabled = currentPage <= 1;
next.disabled = currentPage >= pageCount;
status.textContent = `Page ${currentPage} of ${pageCount}`;
}
};

tags.forEach((button) => {
button.addEventListener('click', () => {
activeTag = button.dataset.tag || 'all';
currentPage = 1;
tags.forEach((tag) => {
const selected = tag === button;
tag.classList.toggle('is-active', selected);
tag.setAttribute('aria-pressed', selected ? 'true' : 'false');
});
update();
});
});

search.addEventListener('input', () => {
currentPage = 1;
update();
});

if (prev) {
prev.addEventListener('click', () => {
currentPage -= 1;
update();
});
}

if (next) {
next.addEventListener('click', () => {
currentPage += 1;
update();
});
}

update();
});
93 changes: 93 additions & 0 deletions docs/source/announcements/dspark-vs-domino.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
:orphan:

DSpark vs Domino: Same DFlash Backbone, Different Correction Heads
##################################################################

:Author: Model Optimizer Team
:Date: July 13, 2026
:Tags: speculative-decoding, dflash, dspark, domino, architecture

DSpark (DeepSpec) and Domino both build on block-parallel DFlash draft generation but diverge in their token-level correction heads. DSpark's default head is a stateless first-order Markov transition; Domino's is a GRU that conditions on the draft prefix. Both must unroll sequentially at inference, so the tradeoff is per-step cost against how much prefix context the correction can use. During teacher-forced training, DSpark's Markov transition can also be parallelized over positions.
See the DSpark and Domino papers in :ref:`dspark-domino-references` for the original method descriptions.

Highlights
**********

* Both systems share the DFlash block-parallel backbone, so their parallel draft throughput starts from a similar foundation.
* In ModelOpt, DSpark defaults to ``markov_head_type="vanilla"``: stateless ``W1`` and ``W2`` embedding lookups with no hidden state to thread through.
* Domino uses ``nn.GRU`` and carries recurrent state across draft positions.
* Both correction heads are sequential at inference because ``x_{k-1}`` must be sampled before step ``k``.

Shared Foundation: DFlash Block-Parallel Backbone
*************************************************

Both systems use DFlash: a draft backbone that runs a single causal attention forward pass over all draft positions in parallel, producing per-position hidden states and base draft logits. This is the expensive step; the correction head adds token-level adjustment on top of those outputs.

Where They Diverge: The Correction Head
***************************************

DSpark uses a first-order Markov transition. For each draft position ``k``:

.. code-block:: text

e_{k-1} = W1[x_{k-1}]
bias_k = W2 * e_{k-1}
p_k = softmax(U_k + bias_k)
x_k ~ p_k

The correction at position ``k`` depends only on ``x_{k-1}``; no RNN hidden state threads across steps. The dominant work is a table lookup and projection rather than a recurrent rollout.

Domino uses a GRU correction head. A recurrent hidden state accumulates information about the draft prefix and is concatenated at readout:

.. code-block:: text

gru_h_k = GRU(input_k, gru_h_{k-1})
p_k = softmax(U_k + W * [h_k; gru_h_k])
x_k ~ p_k

These descriptions compare the underlying architectures. ModelOpt's Domino support is currently training-only, so it does not apply the correction head in serving.

Correction Head Comparison
**************************

.. list-table::
:header-rows: 1

* - System
- Per-step compute
- State carried
* - DSpark ``markov_head_type="vanilla"``
- ``W1[x_{k-1}]`` plus transition projection
- None
* - Domino GRU
- Full GRU cell over a high-dimensional input
- Recurrent hidden state

Both heads must unroll left-to-right at inference. The practical distinction is qualitative: the vanilla Markov head uses only the prior sampled token, while the GRU carries a prefix-dependent recurrent state.

Takeaways
*********

#. DFlash draft generation is shared; the correction head is the main differentiator.
#. Both default correction heads are sequential at inference; their tradeoff is local transition structure versus prefix-dependent state.
#. ModelOpt exposes the DSpark variants through ``markov_head_type``: ``vanilla`` (the default), ``gated``, and ``rnn``. The ``rnn`` option is the closest analogue to Domino's GRU.
#. Architectural comparisons do not establish a universal quality or throughput ranking; evaluate the chosen head on the target model and serving configuration.

.. _dspark-domino-references:

References
**********

* Xin Cheng et al., `DSpark: Confidence-Scheduled Speculative Decoding with Semi-Autoregressive Generation <https://arxiv.org/abs/2607.05147>`_,
arXiv:2607.05147, 2026.
* Jianuo Huang et al., `Domino: Decoupling Causal Modeling from Autoregressive Drafting in Speculative Decoding <https://arxiv.org/abs/2605.29707>`_,
arXiv:2605.29707, 2026.
Comment on lines +81 to +84

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[IMPORTANT Compatibility] Internal date inconsistency between the post and its citation.

What: The post is dated June 29, 2026 (line 7), but it cites DSpark as arXiv:2607.05147. Under arXiv's YYMM.NNNNN identifier scheme, 2607 decodes to July 2026 — so the post is dated before the paper it references would have been submitted. (Domino's 2605... → May 2026 is consistent with a June post.)

Why it matters: This is a public-facing NVIDIA technical blog. A post that cites a paper dated after its own publication date is an internal contradiction that undercuts the post's credibility, and it's the kind of thing readers notice immediately.

Fix: Reconcile the two — either bump the post :Date: to a date on/after the DSpark submission, or correct the arXiv ID if 2607 is a typo.

Additionally (SUGGESTION): I was unable to verify that the external references resolve (web access wasn't available in this review). Before publishing, please confirm each link actually loads — the two arXiv IDs (2607.05147, 2605.29707), the github.com/deepseek-ai/DeepSpec repo, and the deepseek-ai/DeepSeek-V4-Pro-DSpark / Huang2020/Qwen3-8B-Domino-b16 HF checkpoints. A dead or wrong link on the public docs site is worse than no link.


Resources
*********

* `DeepSpec / DSpark repo <https://github.com/deepseek-ai/DeepSpec>`_
* `DeepSeek-V4-Pro-DSpark checkpoint <https://huggingface.co/deepseek-ai/DeepSeek-V4-Pro-DSpark>`_
* `Domino repo <https://github.com/jianuo-huang/Domino>`_
* `Domino checkpoint: Qwen3-8B-Domino-b16 <https://huggingface.co/Huang2020/Qwen3-8B-Domino-b16>`_
* `ModelOpt PR #1710 <https://github.com/NVIDIA/Model-Optimizer/pull/1710>`_
Comment on lines +81 to +93

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] Since this post publishes to the public NVIDIA.github.io/Model-Optimizer site, it's worth a final manual check that every external reference here resolves before merge: the two arXiv IDs (2607.05147, 2605.29707), the HuggingFace checkpoints (deepseek-ai/DeepSeek-V4-Pro-DSpark, Huang2020/Qwen3-8B-Domino-b16), and the GitHub repos (deepseek-ai/DeepSpec, jianuo-huang/Domino). I couldn't verify these from the review environment. A dead or wrong link on an official NVIDIA announcement is a bad look; a 30-second click-through avoids it.

23 changes: 23 additions & 0 deletions docs/source/announcements/github-pages-announcements.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
:orphan:

Model Optimizer Announcements Are Moving to GitHub Pages
#########################################################

:Author: Model Optimizer Team
:Date: August 13, 2026
:Tags: release, docs, github-pages

The Model Optimizer GitHub Pages site is expanding from API documentation into a lightweight announcement hub. The goal is to make releases, technical notes, examples, and deployment writeups easier to discover without introducing a separate publishing system.

What Changes
************

* Announcements live in the documentation source and are reviewed through pull requests.
* The landing page defaults to announcements.
* Existing API documentation remains available from the Sphinx left navigation.
* Announcement pages support tags, search, filtering, and embedded images.

Authoring Flow
**************

Add a Sphinx page under ``docs/source/announcements/``, add its ``.announcement-card`` metadata and link to ``docs/source/index.rst``, and link it from the announcements toctree when applicable. The GitHub Pages workflow rebuilds the static site from committed source, so every announcement follows the same review path as code and docs.
Loading
Loading