[doc] standardize diffusion cookbook model pages (#34247)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Mick
2026-08-21 10:25:40 +08:00
committed by GitHub
co-authored by Claude Opus 5
parent 7e80e889a2
commit e0cf75d9bd
32 changed files with 2712 additions and 602 deletions
+20 -3
View File
@@ -32,6 +32,7 @@ lacks, and replace the EXAMPLE cells with verified recipes. DeepSeek-V4 is a pop
- [references/mintlify-authoring.md](references/mintlify-authoring.md) — MDX rules (forbidden syntax, JSX tables, labeled fences) + invocation-example patterns. Read before writing §1–§3 prose.
- [references/engine-axis.md](references/engine-axis.md) — adding a new Playground feature axis (rare engine work).
- [references/vendor-logo.md](references/vendor-logo.md) — new-vendor card logo: ask the user for the brand logo, then generate the icon-only 940×525 RGBA PNG (spec + Pillow recipe + `git add -f`).
- [references/diffusion-authoring.md](references/diffusion-authoring.md) — required opening, tag, command-picker, and feature-overlay contract for diffusion model pages. Read before editing any `docs/cookbook/diffusion/<Vendor>/<Model>.mdx` page.
## Architecture at a glance
@@ -68,9 +69,12 @@ playground reads it), the **`sglang-deploy-sel` custom event** (deploy dispatche
every change; playground listens — `replaceState` doesn't fire `hashchange`), and the
shared **`sglang-deploy-env` localStorage key** (HOST/PORT placeholders).
> The template is **autoregressive**. Diffusion / omni pages follow their own category
> structure — don't force the config-driven template on them; still obey the Mintlify /
> NEW-tag / docs.json / category-card / validation rules below.
> The main template is **autoregressive**. Diffusion pages use
> `templates/diffusion-page.mdx.tmpl` plus
> [references/diffusion-authoring.md](references/diffusion-authoring.md); do not force the
> autoregressive deployment matrix on them. Omni pages follow their own category structure.
> All categories still obey the Mintlify / NEW-tag / docs.json / category-card / validation
> rules below.
---
@@ -131,6 +135,15 @@ this table (RTX PRO 6000, GH200, future chips) goes in the model's own `config.h
## Phase 2 — Instantiate the template
For a diffusion model, instantiate `templates/diffusion-page.mdx.tmpl` and keep the
shared `DiffusionModelTags` component, plus `templates/diffusion-config.jsx.tmpl` for the
opt-in scoped command builder. Put the compact install command and builder in §1 Quick
start. The first two paragraphs in §2 Model capabilities are not generic filler: they must
state the model's capability range, strongest differentiator, when to choose it, and at
least one real deployment or capability boundary. Put orthogonal runtime features in
`scope: "serve"` or `scope: "request"`, not in the base recipe; use the schema from
`references/diffusion-authoring.md`.
1. **Copy** the three template files to their target paths (above). Note the two
vendor-folder conventions: under `configs/` the folder is the **HuggingFace org**
(`deepseek-ai`); under `cookbook/` it's the **display vendor** (`DeepSeek`).
@@ -206,6 +219,10 @@ user notes: §1 Model Introduction (description, links, params, license, variant
Tool-Calling / HiCache — keep only what applies; match the reasoning example to the
parser's output shape; each runnable block gets an `**Output Example:**`).
For diffusion pages, follow the category-specific Quick start and capability contract in
`references/diffusion-authoring.md`. Run `node docs/scripts/check_cookbook_configs.mjs` to
verify the tag widget and introduction structure before rendering the page.
## Phase 6 — Review
```
@@ -0,0 +1,99 @@
# Diffusion cookbook authoring contract
Use this contract for every model page under
`docs/cookbook/diffusion/<Vendor>/<Model>.mdx`.
## Opening structure
Import and render the shared tag widget immediately after frontmatter:
```mdx
import { DiffusionModelTags } from '/src/snippets/diffusion/model-tags.jsx';
<DiffusionModelTags tags={["video + audio", "text-to-video", "reference control", "4–15 seconds"]} />
```
Use 4–6 tags, ordered from broad to specific:
1. output modality or product class;
2. primary request modes;
3. the capability that differentiates the model;
4. an important scale, latency, duration, resolution, or architecture fact.
Do not spend tags on generic claims such as `native`, `fast`, `high quality`, or
`SGLang`. Attention backends, Cache-DiT, and online quantization are feature overlays,
not model identity, unless a published checkpoint is intrinsically tied to that format.
The page must start with `## 1. Quick start`: keep installation to one runnable
command, add at most one short orientation paragraph, and render the scoped command
builder before detailed capability tables or deployment commentary. A reader should
reach a generated Serve command without scrolling through model background first.
Follow it with `## 2. Model capabilities` and 2–3 short paragraphs:
- paragraph 1: what the model does and where it is genuinely strong;
- paragraph 2: when to choose it and the most important limitation or tradeoff;
- optional paragraph/table: checkpoint or mode routing that a user must understand before serving.
Keep the capability lead between roughly 45 and 180 words. Replace marketing superlatives with
concrete capabilities. A reader should learn more than “this is a powerful image/video
model,” but should not have to read the architecture section to choose the right model.
## Scoped command builder
New diffusion pages use `templates/diffusion-config.jsx.tmpl` and opt into the shared
`commandBuilder` renderer. Setup, Server, and Request choices share one semantic selection and
one command composer; do not create a second command engine or assemble fragments in MDX.
Classify every dimension by lifecycle:
- `scope: "base"`: the visible Setup tab—hardware-independent required decisions such as
checkpoint weights and request mode. Hardware, Nodes × GPUs/node, and the recommended
verified deployment are supplied by the shared builder.
- `scope: "serve"`: startup flags such as placement, attention, precision, encoder scheduling,
and graph execution. They modify only the complete Serve command.
- `scope: "request"`: sampling fields such as quality and outputs. They modify only the complete
Request command.
Keep the topology registry small and honest. `verifiedRecipes` contains only exact end-to-end
runs on that hardware and resource shape. `autoTopology(selection)` may construct a legal custom
shape, but `resolveDeployment` must mark it `unverified` unless it exactly matches a recipe.
`validateTopology` returns static errors for impossible world-size, head, partition, or placement
combinations; errors disable both Copy actions. Never silently label a nearby GPU or topology as
verified.
Expose topology-dependent best values explicitly. A Server row may remain `Auto`, but its summary
and generated flag must show the effective policy—for example, encoder `auto` resolving to
`replicate` across nodes. Reserve `disabled` for combinations that cannot work (a kernel the
platform does not ship, a mode the checkpoint cannot serve); an option that runs but has not
been through a verification round should declare `soft` instead, which keeps it selectable and
labels the pick as unverified. Keep `torch.compile` and similarly narrow experiments in the
detailed prose until they have a broadly compatible recipe.
Each dimension should provide a concise `description`, an optional quality label, and a
`learnMore` anchor. Each option should provide at most two lines of decision-relevant explanation,
its exact `flags`/`stripPrefixes`/`env`/`hints`, and a `disabled` (with `disableReason`), `soft`
(with `softReason`), or `verifiedWhen` predicate when support is conditional — the reason strings
are user-facing: blocked options flash theirs under the row on tap and expose it as a tooltip.
The builder stores all semantic choices in the URL hash; active scope, expanded state, head
address, and node rank stay local.
Legacy configs without `commandBuilder` continue to use the old matrix renderer. Do not migrate
an existing page opportunistically; use the new schema for new diffusion models and deliberate
model-by-model migrations.
## Review checklist
- tags render before section 1 and describe the model rather than the runtime;
- Quick start puts installation and the generated commands before detailed model background;
- the capability section explains strength and boundary without marketing filler;
- checkpoint variants and request modes are unambiguous;
- Setup keeps both commands visible as a deployment overview; Server and Request each show only
the command controlled by that scope;
- command bodies grow naturally up to their collapsed limit and do not reserve empty height;
- topology-dependent recommended defaults are explicit in the setting summary and generated command;
- legal custom topologies are Unverified and copyable; statically illegal combinations block Copy;
- attention, quantization, caching, compile, and similar orthogonal features have explicit
quality contracts and verified scopes;
- unverified hardware or performance claims are absent;
- `node docs/scripts/check_cookbook_configs.mjs` and Mintlify validation pass.
@@ -0,0 +1,173 @@
// Diffusion command-builder config template. Replace every __TOKEN__, keep only
// verified hardware/features, and adapt the topology divisibility contract to
// the model architecture.
export const config = {
modelName: "__MODEL_DISPLAY__",
supportedHardware: ["__DEFAULT_HW__"],
groupHardware: false,
matchDims: [],
overlayDims: [
{
id: "weights",
title: "Checkpoint weights",
scope: "base",
description: "Choose the checkpoint partition required by this request mode.",
default: "default",
options: [{ id: "default", label: "Default", flags: [] }],
},
{
id: "mode",
title: "Request mode",
scope: "base",
default: "text",
options: [{ id: "text", label: "Text" }],
},
{
id: "placement",
title: "Placement",
scope: "serve",
description: "Keep weights resident unless a verified capacity path requires sharding or offload.",
default: "resident",
options: [
{ id: "resident", label: "Resident", flags: ["--performance-mode speed"], recommended: true },
{ id: "fsdp", label: "FSDP", flags: ["--use-fsdp-inference true"], disabled: true },
{ id: "offload", label: "Layerwise offload", disabled: true },
],
},
{
id: "attention",
title: "Attention",
scope: "serve",
description: "Use the platform default unless another backend was measured end to end.",
default: "platform",
options: [{ id: "platform", label: "Platform default", recommended: true }],
},
{
id: "precision",
title: "Precision",
scope: "serve",
default: "native",
options: [{ id: "native", label: "Native mixed precision", recommended: true }],
},
{
id: "encoder",
title: "Encoder",
scope: "serve",
default: "auto",
options: [{ id: "auto", label: "Auto", flags: ["--encoder-parallel auto"], recommended: true }],
},
{
id: "execution",
title: "Execution",
scope: "serve",
default: "eager",
options: [{ id: "eager", label: "Eager", recommended: true }],
},
{
id: "quality",
title: "Quality",
scope: "request",
default: "lossless",
options: [{ id: "lossless", label: "Lossless", recommended: true }],
},
{
id: "outputs",
title: "Outputs",
scope: "request",
kind: "number",
min: 1,
max: 10,
unit: "outputs per prompt",
default: 1,
options: [],
},
],
commandBuilder: {
defaultSelection: {
hw: "__DEFAULT_HW__",
nodes: 1,
gpus_per_node: __DEFAULT_GPUS__,
topology_mode: "auto",
tp_size: 1,
ulysses_degree: __DEFAULT_GPUS__,
ring_degree: 1,
},
resource: {
limits: {
nodes: { min: 1, max: __MAX_NODES__ },
gpus_per_node: { min: 1, max: __MAX_GPUS_PER_NODE__ },
},
verifiedRecipes: [{
id: "__DEFAULT_HW__-default",
hw: "__DEFAULT_HW__",
nodes: 1,
gpus_per_node: __DEFAULT_GPUS__,
placement: "resident",
tp_size: 1,
ulysses_degree: __DEFAULT_GPUS__,
ring_degree: 1,
encoder: "auto",
default: true,
}],
autoTopology: (s) => ({
tp_size: 1,
ulysses_degree: Number(s.gpus_per_node),
ring_degree: Number(s.nodes),
}),
validateTopology: (s, topology) => {
const world = Number(s.nodes) * Number(s.gpus_per_node);
const product = Number(topology.tp_size) * Number(topology.ulysses_degree) * Number(topology.ring_degree);
return world === product ? [] : [`World size ${world} must equal TP × Ulysses × Ring (${product}).`];
},
},
resolveDeployment: (s) => {
const resource = config.commandBuilder.resource;
const topology = s.topology_mode === "manual"
? { tp_size: Number(s.tp_size), ulysses_degree: Number(s.ulysses_degree), ring_degree: Number(s.ring_degree) }
: resource.autoTopology(s);
const errors = resource.validateTopology(s, topology);
const recipe = resource.verifiedRecipes.find((entry) => entry.hw === s.hw
&& entry.nodes === Number(s.nodes)
&& entry.gpus_per_node === Number(s.gpus_per_node)
&& entry.placement === s.placement
&& entry.tp_size === topology.tp_size
&& entry.ulysses_degree === topology.ulysses_degree
&& entry.ring_degree === topology.ring_degree);
const world = Number(s.nodes) * Number(s.gpus_per_node);
const flags = ["--model-path {{MODEL_NAME}}", `--num-gpus ${world}`];
if (topology.tp_size > 1) flags.push(`--tp-size ${topology.tp_size}`);
flags.push(`--ulysses-degree ${topology.ulysses_degree}`);
if (topology.ring_degree > 1) flags.push(`--ring-degree ${topology.ring_degree}`);
flags.push("--host {{HOST_IP}}", "--port {{PORT}}");
const verified = !!recipe && errors.length === 0;
return {
match: { hw: s.hw },
nnodes: Number(s.nodes),
verified,
flags,
builder: {
topology,
topologySummary: `TP ${topology.tp_size} · Ulysses ${topology.ulysses_degree} · Ring ${topology.ring_degree}`,
errors,
warnings: verified ? [] : ["Valid custom topology; exact end-to-end verification is pending."],
verification: { serve: verified ? "verified" : "unverified", request: verified ? "verified" : "unverified" },
},
};
},
},
modelNames: { default: "__MODEL_ID__" },
placeholders: {
HOST_IP: { target: "command", label: "Bind host", default: "0.0.0.0" },
PORT: { target: "command", label: "Bind port", default: "30010" },
CURL_HOST: { target: "curl", label: "Server host", default: "localhost" },
CURL_PORT: { target: "curl", label: "Server port", default: "30010" },
},
curl: (s) => `curl -sS -X POST http://{{CURL_HOST}}:{{CURL_PORT}}/__REQUEST_PATH__ \\
-H 'Content-Type: application/json' \\
-d '${JSON.stringify({ model: "{{MODEL_NAME}}", prompt: "__PROMPT__", quality: s.quality, num_outputs_per_prompt: Number(s.outputs) }, null, 2)}'`,
cells: [],
};
@@ -0,0 +1,44 @@
---
title: __MODEL_DISPLAY__
description: "Deploy __MODEL_DISPLAY__ with SGLang Diffusion."
metatags:
description: "Serve __MODEL_DISPLAY__ for __PRIMARY_CAPABILITY__ with SGLang Diffusion."
---
import { DiffusionModelTags } from '/src/snippets/diffusion/model-tags.jsx';
import { Deployment } from '/src/snippets/_deployment.jsx';
import { config } from '/src/snippets/configs/__HF_ORG__/__MODEL_SLUG__.jsx';
<DiffusionModelTags tags={["__MODALITY__", "__PRIMARY_TASK__", "__DIFFERENTIATOR__", "__IMPORTANT_BOUNDARY__"]} />
## 1. Quick start
Install with `uv pip install "sglang[diffusion]" --prerelease=allow`, then choose
a verified recipe below.
<Deployment config={config} />
## 2. Model capabilities
[__MODEL_DISPLAY__](__MODEL_URL__) is __CONCRETE_MODEL_DESCRIPTION__. Its strongest use case is __MEASURED_OR_DOCUMENTED_STRENGTH__.
Choose it when __SELECTION_GUIDANCE__. The main tradeoff is __CAPABILITY_OR_DEPLOYMENT_BOUNDARY__.
| Checkpoint or mode | Best fit | Important boundary |
| --- | --- | --- |
| `__MODEL_ID__` | __USE_CASE__ | __LIMIT__ |
## 3. Deployment details
Document topology-dependent defaults, platform-specific installation details,
and only the hardware recipes that need explanation beyond the builder.
## 4. Request examples
__REQUEST_EXAMPLES__
## 5. Feature details
Document quality contracts, installation requirements, and benchmark scope for
the Server and Request choices exposed in the builder. Keep `torch.compile` and
other experimental controls here until they have a broadly compatible recipe.