diff --git a/docs/source/_static/announcements.css b/docs/source/_static/announcements.css new file mode 100644 index 00000000000..13c1df7e0f6 --- /dev/null +++ b/docs/source/_static/announcements.css @@ -0,0 +1,142 @@ +/* Scoped announcement styles for the Sphinx RTD theme. */ + +#announcements > h1, +#announcements > p, +#announcements > .announcement-toolbar, +#announcements > .announcement-grid, +#announcements > .announcement-empty, +#announcements > .announcement-pager, +#announcements > .toctree-wrapper { + max-width: 860px; + margin-left: auto; + margin-right: auto; +} + +.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..be03c9b3bd5 --- /dev/null +++ b/docs/source/_static/announcements.js @@ -0,0 +1,105 @@ +document.addEventListener('DOMContentLoaded', () => { + const trimAnnouncementPostSidebar = () => { + if (!window.location.pathname.includes('/announcements/')) { + return; + } + + const menu = document.querySelector('.wy-menu-vertical'); + if (!menu) { + return; + } + + menu.innerHTML = ` +

Announcements

+ + `; + }; + + trimAnnouncementPostSidebar(); + + 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) => tag.classList.toggle('is-active', tag === button)); + 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..1c11570c3ea --- /dev/null +++ b/docs/source/announcements/dspark-vs-domino.rst @@ -0,0 +1,107 @@ +:orphan: + +DSpark vs Domino: Same DFlash Backbone, Different Correction Heads +################################################################## + +:Author: ModelOpt Team +:Date: June 29, 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. + +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. + +Links +***** + +* `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..191c74dd627 --- /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/`` and link it from the announcements toctree in ``docs/source/index.rst``. 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..58577af35ac 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,7 +1,52 @@ -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 +63,7 @@ Welcome to Model Optimizer (ModelOpt) documentation! Quick Start: Sparsity .. toctree:: + :hidden: :glob: :maxdepth: 1 :caption: Guides @@ -25,6 +71,7 @@ Welcome to Model Optimizer (ModelOpt) documentation! guides/[0-9]* .. toctree:: + :hidden: :glob: :maxdepth: 1 :caption: Deployment @@ -32,14 +79,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 +95,7 @@ Welcome to Model Optimizer (ModelOpt) documentation! reference/[0-9]* .. toctree:: + :hidden: :glob: :maxdepth: 1 :caption: Support