diff --git a/docs/source/_static/announcements.css b/docs/source/_static/announcements.css new file mode 100644 index 00000000000..c588c9e1961 --- /dev/null +++ b/docs/source/_static/announcements.css @@ -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; +} diff --git a/docs/source/_static/announcements.js b/docs/source/_static/announcements.js new file mode 100644 index 00000000000..aec4feefd36 --- /dev/null +++ b/docs/source/_static/announcements.js @@ -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(); +}); diff --git a/docs/source/announcements/assets/domino_fig.png b/docs/source/announcements/assets/domino_fig.png new file mode 100644 index 00000000000..c228a589636 Binary files /dev/null and b/docs/source/announcements/assets/domino_fig.png differ diff --git a/docs/source/announcements/assets/dspark_domino_al_qwen3_8b.png b/docs/source/announcements/assets/dspark_domino_al_qwen3_8b.png new file mode 100644 index 00000000000..47d87b54bc3 Binary files /dev/null and b/docs/source/announcements/assets/dspark_domino_al_qwen3_8b.png differ diff --git a/docs/source/announcements/assets/dspark_fig1.png b/docs/source/announcements/assets/dspark_fig1.png new file mode 100644 index 00000000000..d98610a9f79 Binary files /dev/null and b/docs/source/announcements/assets/dspark_fig1.png differ diff --git a/docs/source/announcements/assets/dspark_fig7.png b/docs/source/announcements/assets/dspark_fig7.png new file mode 100644 index 00000000000..1c0947e62b6 Binary files /dev/null and b/docs/source/announcements/assets/dspark_fig7.png differ diff --git a/docs/source/announcements/dspark-vs-domino.rst b/docs/source/announcements/dspark-vs-domino.rst new file mode 100644 index 00000000000..e006f91b811 --- /dev/null +++ b/docs/source/announcements/dspark-vs-domino.rst @@ -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 `_, + arXiv:2607.05147, 2026. +* Jianuo Huang et al., `Domino: Decoupling Causal Modeling from Autoregressive Drafting in Speculative Decoding `_, + arXiv:2605.29707, 2026. + +Links +***** + +These public references were checked during review. + +* `DeepSpec / DSpark repo `_ +* `DeepSeek-V4-Pro-DSpark checkpoint `_ +* `Domino repo `_ +* `Domino checkpoint: Qwen3-8B-Domino-b16 `_ +* `ModelOpt PR #1710 `_ diff --git a/docs/source/announcements/github-pages-announcements.rst b/docs/source/announcements/github-pages-announcements.rst new file mode 100644 index 00000000000..7659cf3d573 --- /dev/null +++ b/docs/source/announcements/github-pages-announcements.rst @@ -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. diff --git a/docs/source/conf.py b/docs/source/conf.py index e4b68ce7643..9f24b299fcb 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -116,7 +116,8 @@ html_static_path = ["_static"] html_title = f"Model Optimizer {version}" -html_css_files = ["custom.css"] +html_css_files = ["custom.css", "announcements.css"] +html_js_files = ["announcements.js"] html_permalinks_icon = "#" # default icon not rendering properly # TODO: left here as reference for future diff --git a/docs/source/index.rst b/docs/source/index.rst index 80b27a851df..c079b56fc05 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,7 +1,54 @@ -Welcome to Model Optimizer (ModelOpt) documentation! -#################################################### +Announcements +############# + +Release notes, technical updates, examples, and deployment stories from the Model Optimizer team. + +.. raw:: html + +
+
+ + +
+ + + + +
+
+ +
+ + +
+ + + +
.. toctree:: + :hidden: + :maxdepth: 1 + :caption: Announcements + + self + +.. toctree:: + :hidden: :glob: :maxdepth: 1 :caption: Getting Started @@ -18,6 +65,7 @@ Welcome to Model Optimizer (ModelOpt) documentation! Quick Start: Sparsity .. toctree:: + :hidden: :glob: :maxdepth: 1 :caption: Guides @@ -25,6 +73,7 @@ Welcome to Model Optimizer (ModelOpt) documentation! guides/[0-9]* .. toctree:: + :hidden: :glob: :maxdepth: 1 :caption: Deployment @@ -32,14 +81,15 @@ Welcome to Model Optimizer (ModelOpt) documentation! deployment/[0-9]* .. toctree:: + :hidden: :glob: :maxdepth: 1 :caption: Examples examples/[0-9]* - .. toctree:: + :hidden: :glob: :maxdepth: 1 :caption: Reference @@ -47,6 +97,7 @@ Welcome to Model Optimizer (ModelOpt) documentation! reference/[0-9]* .. toctree:: + :hidden: :glob: :maxdepth: 1 :caption: Support