-
Notifications
You must be signed in to change notification settings - Fork 517
docs: add announcements landing page #1971
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
246efa1
27d3700
c83a0f0
6fbecfa
fa003d8
61352e6
6791ea7
278c3ca
8c7fc05
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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; | ||
| } |
| 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(); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| :orphan: | ||
|
|
||
| DSpark vs Domino: Same DFlash Backbone, Different Correction Heads | ||
| ################################################################## | ||
|
|
||
| :Author: ModelOpt 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 sharply in their token-level correction heads. DSpark uses a stateless VanillaMarkov head that is fast and parallelizable during training; Domino uses a GRU that is more expressive but sequential at inference. | ||
| 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. | ||
| * DSpark defaults to VanillaMarkov: 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``. | ||
| * DSpark adds a hardware-aware prefix scheduler through ``confidence_head``; Domino does not include this mechanism. | ||
|
|
||
| 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. | ||
|
|
||
| .. image:: assets/dspark_fig1.png | ||
| :alt: DSpark overall architecture and decoding cycle | ||
| :width: 100% | ||
|
|
||
| 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 | ||
|
|
||
| .. image:: assets/domino_fig.png | ||
| :alt: Domino pipeline with a DFlash backbone and GRU causal correction head | ||
| :width: 100% | ||
|
|
||
| The figure below compares training acceptance length on Qwen3-8B across the DFlash baseline, Domino GRU, and a DSpark implementation. | ||
|
|
||
| .. image:: assets/dspark_domino_al_qwen3_8b.png | ||
| :alt: Training acceptance length on Qwen3-8B: DFlash baseline vs Domino GRU vs DSpark | ||
| :width: 100% | ||
|
|
||
| Correction Head Overhead | ||
| ************************ | ||
|
|
||
| .. list-table:: | ||
| :header-rows: 1 | ||
|
|
||
| * - System | ||
| - Per-step compute | ||
| - State carried | ||
| * - DSpark VanillaMarkov | ||
| - ``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 difference is per-step cost: VanillaMarkov is much lighter, while the GRU can condition on a richer prefix history. | ||
|
|
||
| Additional DSpark Machinery | ||
| *************************** | ||
|
|
||
| DSpark includes a hardware-aware prefix scheduler through a confidence head. The scheduler estimates acceptance probability and selects how many draft tokens to submit for verification. It is a serving-time throughput optimization, not a draft-quality feature. | ||
|
|
||
| For MoE models, DSpark checkpoints also include manifold-constrained Hyper-Connections. Dense models use the simpler backbone plus Markov-head path. | ||
|
|
||
| .. image:: assets/dspark_fig7.png | ||
| :alt: DSpark throughput and TPS Pareto frontier | ||
| :width: 100% | ||
|
|
||
| Takeaways | ||
| ********* | ||
|
|
||
| #. DFlash draft generation is shared; the correction head is the main differentiator. | ||
| #. VanillaMarkov is cheaper per step than GRU, although both are sequential at inference. | ||
| #. GRU is more expressive, but the extra recurrence may not translate into a large acceptance-rate gain. | ||
| #. DSpark's design is broader: VanillaMarkov, GatedMarkov, and RNN-style heads all fit the same family. | ||
| #. The prefix scheduler affects serving throughput decisions, not correctness. | ||
|
|
||
| .. _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
+106
to
+109
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 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 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 ( |
||
|
|
||
| Links | ||
| ***** | ||
|
|
||
| These public references were checked during review. | ||
|
|
||
| * `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
+106
to
+120
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [SUGGESTION] Since this post publishes to the public |
||
| 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: July 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we user
ModelOpt Teamin some places andModel Optimizer Teamin other places. Can you use same everywhere?