Cookbook renovation (#26885)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
zijiexia
2026-06-07 22:04:54 -07:00
committed by GitHub
co-authored by Claude Opus 4.8
parent 6365d6faee
commit d1777d1f6d
16 changed files with 6692 additions and 1693 deletions
+219
View File
@@ -0,0 +1,219 @@
---
name: cookbook-add-model
description: Add a new model to the SGLang Cookbook (docs_new/, Mintlify), config-driven format — instantiate the model-agnostic template into a per-model config (+ benchmarks) JSX under src/snippets/configs/, an MDX page, the docs.json nav entry, NEW-tag hygiene, and the homepage vendor card. Interactive, multi-phase. Run with /cookbook-add-model.
disable-model-invocation: true
---
# Add a model to the SGLang Cookbook
The cookbook is **config-driven**: two shared engines contain NO model-specific code —
`docs_new/src/snippets/_deployment.jsx` (the 5-dim deploy matrix) and
`_playground.jsx` (the diff-based override Playground). Adding a model = adding **data**:
a per-model `config` (+ optional `benchmarks`) consumed by both engines, plus an MDX page
that imports them. No engine edits.
**Instantiate the model-agnostic template** (NOT a clone of any live cookbook — the
template is decoupled and covers all hardware + all axes):
- `templates/config.jsx.tmpl``docs_new/src/snippets/configs/<hf-org>/<model-slug>.jsx`
- `templates/benchmarks.jsx.tmpl``…/<model-slug>-benchmarks.jsx` (skip if no numbers)
- `templates/page.mdx.tmpl``docs_new/cookbook/<category>/<Vendor>/<ModelName>.mdx`
The template uses explicit `__TOKEN__` placeholders; you fill them, prune what the model
lacks, and replace the EXAMPLE cells with verified recipes. DeepSeek-V4 is a populated
*instance* you can consult, but is not the template.
**Deep references (read on demand, don't inline):**
- [references/authoring-reference.md](references/authoring-reference.md) — field-by-field config / cells / playground / MDX contract.
- [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`).
## Architecture at a glance
```
┌─────────────────────────────────────────────────────────────────┐
│ cookbook/<category>/<Vendor>/<Model>.mdx │
│ import { Deployment } from "/src/snippets/_deployment.jsx"; │
│ import { Playground } from "/src/snippets/_playground.jsx"; │
│ import { config } from "/src/snippets/configs/.../X.jsx"; │
│ <Deployment config={config} /> <Playground config={config} />│
└─────────────────────────────────────────────────────────────────┘
│ (config passed as React prop)
┌─────────────────────────────────────────────────────────────────┐
│ src/snippets/configs/<vendor>/<model>.jsx │
│ export const config = { │
│ supportedHardware, variants, quantizations, strategies, ... │
│ cells: [ { match:{hw,variant,quant,strategy,nodes}, │
│ env:[...], flags:[...] }, ... ], // 5-dim matrix │
│ playgroundFeatures: { attention, moe, parsers, ... }, │
│ }; │
└─────────────────────────────────────────────────────────────────┘
│ (consumed by BOTH engines — no model code in engines)
┌──────────────────────────────────┬──────────────────────────────┐
│ _deployment.jsx │ _playground.jsx │
│ Renders the verified matrix; │ Renders override chips + │
│ one cell → its env/flags. │ diff against the cell. │
└──────────────────────────────────┴──────────────────────────────┘
```
The two widgets stay in sync via: the **URL hash** (deploy mirrors its selection;
playground reads it), the **`sglang-deploy-sel` custom event** (deploy dispatches on
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.
---
**Interactive, multi-step workflow. Collect inputs incrementally — don't ask for
everything upfront.** The real work is the verified `cells[]` recipes + measured
benchmarks (Phases 2 + 4); everything else is filling the template.
## Phase 1 — Collect inputs
1. **Model card** — HuggingFace repo/URL. **Fetch the page** and extract description,
param count, architecture, context length, **license**. (Fetching guards factual bugs
like an off-by-a-few-B param count.) If the model isn't public, ask the user.
2. **Variants / quantizations** — keep separate: variants are size/mode (e.g. Flash/Pro,
Instruct/Thinking); quantizations come from the HF card / linked repos (BF16/FP8/FP4/…).
Default to BF16 when a full-precision repo exists.
3. **Tested hardware + parallelism** — which platforms are actually tested, and TP/EP/DP
for each. List only tested hw (unlisted greys out).
4. **Verified launch recipes** — the full `sglang serve` flags per
(hw × variant × quant × strategy × nodes) combo → these become `cells[]`. Rewrite any
`python -m sglang.launch_server` to `sglang serve` form.
5. **sglang version / image tag** — ask which sglang build the recipes + benchmarks ran on
(a release like `0.5.x`, or `main`/nightly). **Never guess or hallucinate it.** This one
tag fills `dockerImages` and the benchmarks' `sglang_version`; when the user is unsure,
default the image to `lmsysorg/sglang:dev` (nightly) rather than inventing a release.
6. **Pre-flight**: `gh pr list --repo sgl-project/sglang --search "<model>"` (dup check).
**Hardware reference** (the shared `HARDWARE_CATALOG` in `_deployment.jsx`). A GPU **not** in
this table (RTX PRO 6000, GH200, future chips) goes in the model's own `config.hardware`
(`{id,label,vram,vendor}`) — the engine merges it in; don't edit the engine catalog:
| Platform | Vendor | VRAM | Docker image |
|---|---|---|---|
| H100 | NVIDIA | 80GB | `lmsysorg/sglang:<ver>` |
| H200 | NVIDIA | 141GB | `lmsysorg/sglang:<ver>` |
| B200 | NVIDIA | 192GB | `lmsysorg/sglang:<ver>` |
| B300 | NVIDIA | 288GB | `lmsysorg/sglang:<ver>` (or `-cu130` when required) |
| GB200 | NVIDIA | 192GB | `lmsysorg/sglang:<ver>` (or `-cu130`) |
| GB300 | NVIDIA | 288GB | `lmsysorg/sglang:<ver>` (or `-cu130`) |
| MI300X | AMD | 192GB | `lmsysorg/sglang:<ver>-rocm720-mi30x` |
| MI325X | AMD | 256GB | `lmsysorg/sglang:<ver>-rocm720-mi30x` |
| MI350X | AMD | 288GB | `lmsysorg/sglang:<ver>-rocm720-mi35x` |
| MI355X | AMD | 288GB | `lmsysorg/sglang:<ver>-rocm720-mi35x` |
- **Image tag (`<ver>`)**: don't guess — ask the user for the tag the recipes ran on, or
default to `dev` (nightly). The same tag goes in `dockerImages` and benchmarks'
`sglang_version`; the engine falls back to `lmsysorg/sglang:dev` for any unmapped hw.
- **TP sizing** (sanity-check recipes): `weight_GB / gpu_mem`, round up to a power of 2,
~2030% headroom. BF16 ≈ params×2 GB, FP8 ≈ ×1, FP4 ≈ ×0.5. MoE → **total** weight, not
active params. FP4 is Blackwell-only (B200/B300/GB200/GB300). GB200/GB300 single-node
hosts are typically **4 GPUs** (TP=4 ceiling).
- **Platform flags**: Blackwell may need `--attention-backend trtllm_mha`; AMD typically
needs `--attention-backend triton` + env `SGLANG_USE_AITER=1` /
`SGLANG_ROCM_FUSED_DECODE_MLA=0` (check AITER TP constraints, e.g. `heads_per_gpu % 16 == 0`).
- **EP** (MoE): 8-GPU NVIDIA `--tp 8 --ep 8`; AMD `EP = TP`; small NVIDIA (TP≤4) omit
`--ep` unless benchmarked. (The template's AMD example cell shows these.)
## Phase 2 — Instantiate the template
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`).
2. **Replace every `__TOKEN__`**: `__MODEL_DISPLAY__`, `__MODEL_SLUG__`, `__HF_ORG__`,
`__HF_REPO__`, `__REASONING_PARSER__`, `__TOOLCALL_PARSER__`, `__ONE_LINER__`. Verify
none remain: `grep -rn '__[A-Z_]*__' <new files>`.
3. **Prune** to what the model supports (delete, don't stub) — using
[references/authoring-reference.md](references/authoring-reference.md):
- `supportedHardware` + the EXAMPLE cells: keep your tested families; **delete the
`mi*` ids + AMD example cell if no AMD recipe**, etc. A GPU not in the shared catalog
(e.g. RTX PRO 6000) → declare it in `config.hardware` and add its id here.
- `playgroundFeatures` axes: delete `megamoe` (non-Blackwell-MoE), `hisparse`
(non-DSA), `pdDisagg`/`router` (no PD), the `parsers` axis (no parsers), etc.
- `quantizations` / `variants`: drop what the model doesn't ship; collapse `variants`
to single `default` if there's no variant axis (then drop the `variant` half of
`modelNames`/`defaultAccuracy` keys).
4. **Fill `cells[]`** with the verified recipes from Phase 1 (replace every EXAMPLE cell;
set `verified: true` only on tested combos), and `modelNames` with real HF slugs,
`dockerImages` for your hw (use the Phase-1 tag, or default `lmsysorg/sglang:dev` — never
a guessed release), `multiNodeHints` only for fabric-specific hw (e.g. gb200).
### Site-wiring (do all three)
- **`docs_new/docs.json`** — add the page under Cookbook → `<category>``<Vendor>`, at
the **top** of that vendor's `pages` (root-relative, no `.mdx`:
`cookbook/<category>/<Vendor>/<Model>`). New vendor group → insert in the section's
local ordering.
- **NEW-tag hygiene** — the new page keeps `tag: NEW` (from the template). Scan the
vendor dir for existing NEW and strip it from siblings; verify ≤1:
`grep -rn 'tag: NEW' docs_new/cookbook/<category>/<Vendor>/` → at most one result. (Scan
files; don't assume the first `docs.json` entry holds NEW.)
- **Homepage card** — `docs_new/cookbook/<category>/intro.mdx`: if the org already has a
`<Card>`, update only its `href` (keep `img`). If the org is **new**, add a `<Card>`
(title = nav-group name; keep card order aligned with `docs.json`) **and create its logo**:
ask the user for the brand logo, then generate the conforming **icon-only 940×525 RGBA
transparent** PNG → `docs_new/cards/logos/<org-slug>.png` per
[references/vendor-logo.md](references/vendor-logo.md) (track with `git add -f``*.png`
is gitignored repo-wide). Never invent or copy a logo.
## Phase 3 — Validate
```bash
cd docs_new
mint validate # frontmatter, missing nav entries, MDX/JSX errors
mint broken-links
mint dev # visual smoke test at http://localhost:3000/cookbook/<category>/<Vendor>/<Model>
```
Spot-check: cells render sensible commands; URL-hash nav persists across reload; the
Playground inherits the Deploy selection live; each axis toggle produces the expected
diff; Docker mode wraps in `docker run` with the right image; multi-node cells emit the
hints + `--nnodes N`; cURL resolves the model name; the NEW badge shows on the new page
and is gone from same-vendor siblings; the homepage card points to the new model.
## Phase 4 — Interactive testing
The user deploys each cell, runs the benches, and pastes results; you fill the data:
- mark each tested `cells[]` entry `verified: true` (absent = yellow/unverified badge);
- fill the `<model>-benchmarks.jsx` entries (one per cell `match`) with measured
speed/accuracy + the `sglang_version` the user reports (don't invent one — the template's
`0.0.0` is a deliberate TODO); set model-level `defaultAccuracy` per variant. Leave a
cell's entry as a bare `match` stub if it has no numbers yet (the card shows "pending").
## Phase 5 — Prose & config tips
**Read [references/mintlify-authoring.md](references/mintlify-authoring.md) first** (it
carries the parser-output-shape / thinking-mode / Output-Example / no-hardcoded-sampling
rules + the Mintlify forbidden-syntax list). Then rewrite the MDX prose from the HF card +
user notes: §1 Model Introduction (description, links, params, license, variants table),
§2 Configuration Tips (hw-specific tuning, caveats), §3 Advanced Usage (Reasoning /
Tool-Calling / HiCache — keep only what applies; match the reasoning example to the
parser's output shape; each runnable block gets an `**Output Example:**`).
## Phase 6 — Review
```
/cookbook-review-pr <PR number>
```
## Git workflow
Always branch — never commit to main directly.
```bash
git checkout -b add-<model>-cookbook
git add docs_new/src/snippets/configs/<hf-org>/<slug>.jsx \
docs_new/src/snippets/configs/<hf-org>/<slug>-benchmarks.jsx \
docs_new/cookbook/<category>/<Vendor>/<Model>.mdx \
docs_new/docs.json docs_new/cookbook/<category>/intro.mdx
git commit -m "Add <Display-Name> cookbook"
git push -u origin add-<model>-cookbook
gh pr create --title "Add <Display-Name> cookbook" --body "..."
```
@@ -0,0 +1,220 @@
# Cookbook config reference (fields · cells · playground · MDX)
Loaded on demand by the `cookbook-add-model` skill. This is the field-by-field
contract for when the clone needs more than a rename. The two engine files are
the canonical specs — read their headers first:
- [`_deployment.jsx`](../../../../docs_new/src/snippets/_deployment.jsx) — the 5-dim matrix widget; lists every config field.
- [`_playground.jsx`](../../../../docs_new/src/snippets/_playground.jsx) — the diff-based override widget; lists the `playgroundFeatures` axes + the `AXIS_HANDLERS` interface.
Engine extension (adding a new playground axis) lives in [engine-axis.md](engine-axis.md).
---
## 2.1 Create the config file
**Path**: `docs_new/src/snippets/configs/<vendor>/<model>.jsx`. The vendor folder is
the HuggingFace org (`deepseek-ai`, `Qwen`, `moonshotai`, ...); the file
name is a short hyphenated model id (`deepseek-v4`, `qwen3.5`, ...).
**Shape**: must be a single `export const config = { ... }` literal. Do not
use function calls, spreads, fragment refs, or IIFE — Mintlify re-evaluates
this export at hydration time with module-level identifiers out of scope,
and any non-literal value crashes with `ReferenceError`.
**Required fields** (engine reads these — see the `_deployment.jsx` header for
the full contract):
| Field | Type | Purpose |
|---|---|---|
| `modelName` | string | Display label only. Not used for HF slug — see `modelNames`. |
| `supportedHardware` | `string[]` | Which hw ids appear in the catalog. Subset of `HARDWARE_CATALOG` (in `_deployment.jsx`) `config.hardware`. Listing an id makes its button appear; if no cell uses it, the engine greys it out automatically. |
| `hardware` | `{id,label,vram,vendor}[]` | Optional. GPUs the shared `HARDWARE_CATALOG` doesn't carry (workstation / desktop / future chips, e.g. RTX PRO 6000). The engine merges these into the catalog, so a model-specific GPU is config data — **no engine-catalog edit**. Also add the id to `supportedHardware`. |
| `variants` | `{id, label, subtitle?}[]` | 2nd-dim option list. Use `default` / single-element if the model has no variant axis. |
| `quantizations` | `{id, label}[]` | 3rd-dim option list. |
| `strategies` | `{id, label}[]` | 4th-dim option list. Common ids: `low-latency`, `balanced`, `high-throughput`. |
| `nodesOptions` | `{id, label}[]` | 5th-dim option list. The `id` MUST be `single` or `multi-N` — the engine parses N from the id for `--nnodes`. |
| `cells` | `{match, verified?, env, flags}[]` | One per supported (hw × variant × quant × strategy × nodes) combination. See §2.2. |
| `modelNames` | `{[key]: string}` | HF slug lookup. Keys are either `hw\|variant\|quant` (most specific) or `variant\|quant` (fallback). |
| `placeholders` | `{[key]: {target, label, default?}}` | `{{KEY}}` interpolation map for command + curl. `target` is `'command'` or `'curl'`. Editable through the Env modal. |
| `curl` | string | cURL template. Uses `{{MODEL_NAME}}` + placeholder keys. |
**Optional fields**:
| Field | Type | Purpose |
|---|---|---|
| `multiNodeHints` | `{[hwId]: string[]}` | Lines prepended as `# ...` comments to multi-node commands (env-var hints). Per-hw, and only for hw whose **cluster fabric needs manual NIC config** (e.g. `gb200` NVL72/MNNVL → NVSHMEM/Gloo hints). NOT every multi-N hw needs an entry — standard-IB DeepEP (h200) auto-detects the HCA, and Marlin multi-node (h100) uses no DeepEP/NVSHMEM at all. |
| `dockerImages` | `{[hwId]: string}` | Per-hw image name for `docker run` framing. **Ask the user which sglang build the recipes ran on; don't guess a supporting release.** Falls back to `lmsysorg/sglang:dev` if missing — also the sensible default when unsure. |
| `playgroundFeatures` | `{[axisId]: {...}}` | Opts into the Playground widget. See §2.3. |
| `benchmarkCommands` | `{speed: string, accuracy: {[accKey]: string \| {[variant]: string}}, numPromptsByConc?: {[c]: number}}` | Powers the benchmark card's **"⚡ Reproduce"** modal. `speed` is ONE `bench_serving` template; the engine fills `{{DATASET}}`/`{{ISL}}`/`{{OSL}}` from each cell's `speed[].workload`, the chip-picked `{{MAX_CONCURRENCY}}`, and `{{NUM_PROMPTS}}` (resolved `workload.num_prompts ?? numPromptsByConc[c] ?? max(c*2, 200)`). `accuracy` maps an accuracy field (e.g. `gsm8k_pct`) to a per-eval template — a string, OR a `{flash, pro, …}` object keyed by variant when the command differs per variant (e.g. GPQA/AIME `--max-tokens`). The modal renders a chip per eval (one command area, like Speed). Both also use `{{MODEL_NAME}}` + `{{CURL_HOST}}`/`{{CURL_PORT}}` like `curl`. Optional; the button only appears when this AND `benchmarks` are present. |
| `defaultAccuracy` | `{[variant]: {[accKey]: number}}` | Model-level accuracy applied to **every** cell of a variant (e.g. GPQA Diamond / AIME25 — hardware-independent). Merged UNDER each cell's measured `accuracy` (a per-cell value wins), so you set a variant's score once instead of copying it onto every benchmark entry. Keys must match `ACCURACY_LABELS` + `benchmarkCommands.accuracy`. |
| `github` | `{owner?, repo?, issueTemplate?, cookbookModel?}` | Overrides for the "Submit verified cell" CTA in the playground. Defaults: `sgl-project/sglang` + `3-playground-verified-cell.yml` + `"deepseek-ai/deepseek-v4"`. Set `cookbookModel` to the value that matches the `model` dropdown in your issue template so it's pre-selected when the issue opens. |
## 2.2 Author the 5-dim matrix (`cells[]`)
Each cell describes one verified (or auto-estimated) launch recipe.
```js
{
match: { hw: "b200", variant: "flash", quant: "fp4",
strategy: "low-latency", nodes: "single" },
verified: true, // green "Verified" badge; absence = yellow
env: [
"SGLANG_DEEPEP_NUM_MAX_DISPATCH_TOKENS_PER_RANK=1024",
],
flags: [
"--trust-remote-code",
"--model-path {{MODEL_NAME}}", // {{MODEL_NAME}} resolves from modelNames
"--tp 4",
"--moe-runner-backend flashinfer_mxfp4",
"--host {{HOST_IP}}",
"--port {{PORT}}",
],
},
```
**Rules**:
- `match` MUST contain exactly the 5 keys: `hw`, `variant`, `quant`,
`strategy`, `nodes`. The engine looks up cells by tuple equality.
- `env` and `flags` are FLAT literals. The engine does NOT expand
fragments, aliases, or templates — it consumes them verbatim
(only `{{PLACEHOLDER}}` substitutions happen at render time).
- DO NOT include `--nnodes` / `--node-rank` / `--dist-init-addr` in
`cell.flags` for multi-node cells. The renderer injects them
automatically from `match.nodes` (`multi-N` → N nodes).
- DO NOT include `--host` / `--port` literally — use `{{HOST_IP}}` /
`{{PORT}}` placeholders so users can override through the Env modal.
- Order flags as: `--model-path` first (after any `--trust-remote-code`),
then parallelism (`--tp`, `--dp`, `--enable-dp-attention`), then MoE
flags, then tuning knobs, with `--host` / `--port` last. The playground
engine assumes this ordering when inserting overrides (its anchors target
`--model-path` / `--tp` / etc., and inserts before the `--host` tail).
**Cells are denormalized on purpose** — common flags repeat across cells.
This makes each cell self-contained and easy to verify. When sweeping a
common change, edit every cell.
**Avoid premature cells**: only add a cell for a (hw × variant × quant ×
strategy × nodes) combination if you have a recipe that has been tested or
at least sanity-checked. The engine greys out un-listed combinations
automatically.
## 2.3 Configure `playgroundFeatures` (optional)
The Playground widget is opt-in per axis. Add only the axes that make sense
for this model. Recognised axis keys and their schemas (full reference in
the `_playground.jsx` header):
| Axis key | Widget | Use when |
|---|---|---|
| `attention` | TP / CP / DP-Attention sub-knobs (DP-Attention is a combined knob: its value is the DP degree AND toggles `--enable-dp-attention`) | Model exposes parallelism knobs in its cells (§2.2) and you want users to override them. |
| `moe` | Backend select + EP knob | Model is MoE and supports multiple `--moe-*-backend` choices. |
| `parsers` | Multi-toggle | Model has reasoning / tool-call parsers. |
| `speculative` | Single-select chip group | Model has spec-decoding presets you want to expose. |
| `pdDisagg` | Mode + transfer backend (+ optional per-backend env via `envWhen` hw-gate) + IB device + optional `router{port, command}` | Model supports prefill/decode disaggregation. When a PD role is active and `router` is set, the playground shows the router (SGLang Model Gateway) launch command as a separate companion block and retargets the cURL modal to `router.port` (clients hit the router, not the role servers). |
| `hicache` | Enable + storage + write policy | Model is large enough that hierarchical KV cache matters. |
| `hisparse` | Enable + host-ratio select; whole card gated on the live PD-Disagg mode being `decode` | DSA-style model (DeepSeek-V3.2 / V4, GLM-5) that supports decode-side hierarchical sparse attention. |
| `megamoe` | Single-select with hw/strategy gating | Blackwell-only kernel fusion variant. |
**Per-chip constraints**: any chip entry in any axis can be wrapped with
`hide` / `disable` constraint objects:
```js
{ value: 16, disable: { nodes: ["single"] },
disableReason: "TP=16 requires 16 ranks — switch the Deploy panel's Nodes to Multi-Nodes first." }
```
- `hide` — chip omitted entirely (use for hard impossibilities).
- `disable` — chip greyed out with tooltip (soft warning).
- Constraints are AND across keys, OR within each key's array.
- Bare `disabled: true` / `disable: true` is a static always-disabled form
(used for "Coming soon" chips).
## 2.4 Create the MDX page
Path: `docs_new/cookbook/<category>/<Vendor>/<Model>.mdx`. Import both widgets and
the per-model config, render them inside the relevant sections:
```mdx
## Deployment
import { Deployment } from "/src/snippets/_deployment.jsx";
import { config } from "/src/snippets/configs/<vendor>/<model>.jsx";
import { benchmarks } from "/src/snippets/configs/<vendor>/<model>-benchmarks.jsx";
{/* Install is a PREREQUISITE — keep it compact + collapsed at the top of the
Deploy section (NOT a numbered section). Tabs mirror the widget's
Python/Docker toggle. */}
<a id="install" />
<Accordion title="Install SGLang">
<Tabs>
<Tab title="Python (pip / uv)">…pip / uv install…</Tab>
<Tab title="Docker">…docker pull + a `docker run … sglang serve` example…</Tab>
</Tabs>
</Accordion>
<Deployment config={config} benchmarks={benchmarks} />
[model-specific tuning notes, caveats, links]
## Playground
import { Playground } from "/src/snippets/_playground.jsx";
<Playground config={config} />
```
**Heading slugs matter** — the two widgets cross-link by scrolling to each
other's section id (Mintlify auto-slugs headings: lowercase, spaces →
hyphens, punctuation dropped). The engines look up:
- the **Deploy** panel by id `deployment` (falls back to `deploy`) — used
by the Playground's "↑ Switch base" button and by deep-link scroll-on-
load. Title the section `## Deployment` (or `## Deploy`).
- the **Playground** by id `playground` — used by `_deployment.jsx`'s
"Open the Playground →" link. Title the section `## Playground`.
Avoid numbered headings like `## 3. Model Deployment` (slug
`3-model-deployment`) for these two sections — the cross-links would break.
The Playground reads the Deploy selection live via the URL hash + the
`sglang-deploy-sel` custom event, so the two can live in different parts
of the page.
The `benchmarks` prop is **optional**. It points at a sibling
`<model>-benchmarks.jsx` file (one entry per cell, keyed by the same
`match` tuple) that renders an accuracy + speed sub-card under the command
box; omit the import and the prop if the cookbook has no measured numbers
yet. See the `_deployment.jsx` header and `deepseek-v4-benchmarks.jsx` for
the full speed/accuracy schema.
To let users *reproduce* those numbers, add a `benchmarkCommands` block to
the config (§2.1, next to `curl`). When present alongside `benchmarks`, the
benchmark card grows a **"⚡ Reproduce"** button that opens a modal listing
the runnable commands for the current cell — one `bench_serving` command for
Speed (with concurrency chips that rewrite `--max-concurrency`) plus an
Accuracy command with a chip per eval. No separate benchmark section needed.
---
## Pitfalls (authoring)
**Stale URL hash hydration** — If a user shares a link from an old cell
catalog and the hash names an impossible combination, `_deployment.jsx`'s
`validateSelection` snaps to the nearest real cell. The Playground reads
the hash too — make sure cookbook removals don't leave dangling shared
links pointing at hardware/quant combos that no longer exist.
**Mintlify constraints** — Module-level statements are stripped. The config
MUST be a single `export const config = { ... }` literal — no function calls,
spreads, fragment refs, or IIFE (Mintlify re-evaluates the export at hydration
with module-level identifiers out of scope; any non-literal crashes with
`ReferenceError`). In MDX, capitalized JSX tags get rebound — use the built-in
Mintlify components (`<Accordion>`, `<Tabs>`, `<Card>`, ...) as documented.
Avoid `!(x in y)` anywhere (Mintlify's AST walker crashes on it) — use
`obj.key === undefined`.
**Per-cell denormalization** — Cells repeat common flags on purpose. Do
not factor them into a shared `commonFlags` array — Mintlify will fail
to inline the reference. If you need to sweep a flag across cells, do it
with a global find-replace in the config file.
@@ -0,0 +1,242 @@
# Engine extension: add a new playground feature axis
Loaded on demand by the `cookbook-add-model` skill. **Rare** — adding a model
cookbook is data-only and never needs this. The current 8 built-in axes
(`attention`, `moe`, `parsers`, `speculative`, `pdDisagg`, `hicache`,
`hisparse`, `megamoe`) already cover the SGLang feature surface most cookbooks
need. Only add a new axis if a real cookbook needs it and the feature does not
fit any existing axis. Touches `_playground.jsx` only.
For the per-model config/cells/MDX reference see [authoring-reference.md](authoring-reference.md).
---
## 3.1 Decide
Before touching the engine, confirm:
- The feature is a STABLE part of the SGLang CLI surface (will appear in
multiple cookbooks, not one-off).
- The feature cannot be expressed as a new option inside an existing axis
(e.g. a new MoE backend belongs in `moe.backend.options`, not a new
axis).
- The feature has a clean strip-prefix → emit-flag pattern.
If unsure, add it as data first (in one cookbook's config under an
existing axis) before promoting it to a built-in axis.
## 3.2 Pick the axis id and state shape
The axis id is the key in both `config.playgroundFeatures` and the
internal `deltas` object. Use camelCase, descriptive but short:
`mambaCache`, `attentionBackend`, `kvCacheDtype`.
The state shape is whatever `initState` returns. Common shapes:
- Single-select: a string sentinel (e.g. `"disabled"` / `"current"` / an
option id).
- Multi-toggle: `{[itemId]: bool}`.
- Sub-knobs: `{[knobId]: value | null}`.
- Compound (axis with its own internal sub-state, like PD-Disagg's
`{mode, ibDevice}`): a plain object.
Pick ONE "inherit base" sentinel and document it in the handler comment.
## 3.3 Implement the handler
Add one entry to `AXIS_HANDLERS` in `_playground.jsx`.
The handler owns everything: state init, apply (strip+insert), hidden-revert,
AND the JSX render. Engine main loop iterates `AXIS_HANDLERS` and calls each
method by name — adding a new axis is genuinely a one-place change.
Template:
```js
// ---- Axis: <Title> ----------------------------------------------------
// <one-paragraph description of what this axis controls and why it
// exists. Mention the SGLang feature it wraps and the strip/insert
// policy.>
<axisId>: {
initState: (fc) => /* initial state value */,
// Called when base cell changes. Return new value if the picked option
// is now hidden by a constraint; otherwise return value unchanged.
// Disabled picks are intentionally NOT auto-reverted (soft warning).
revertHidden: (value, fc, base, h) => {
// ... return value or a new value
return value;
},
// Pure function. Receives the current (flags, env) and returns the next
// (flags, env). Do NOT mutate inputs. The `value` argument is whatever
// initState returned. The `fc` argument is config.playgroundFeatures[axisId].
// The `sel` argument is the current base cell selection. The `h`
// argument is the helpers bundle (strip/insert primitives + anchors).
apply: ({ flags, env, value, fc, sel, h, derived }) => {
if (/* value is the inherit-base sentinel */) return { flags, env };
flags = h.stripFlagsByFirstToken(flags, [/* prefixes this axis owns */]);
if (/* an option is picked */) {
flags = h.insertAfter(flags, h.ANCHOR_NEAR_<X>, [/* new flags */]);
// or: flags = h.insertBeforeTail(flags, [/* new flags */]);
// if the axis mutates env:
// env = h.stripEnvByPrefix(env, fc.stripEnv || []);
// env = [...env, /* additional env vars */];
}
return { flags, env };
},
// Optional: read the base cell's flag array back into the same shape
// initState/apply use. Render shows this as the default selection
// (dropdown option or checked chip) when the state slot is the inherit
// sentinel — so the user sees the cell's actual --tp / MoE backend /
// spec preset instead of an opaque "Auto." When derive returns a real
// value, the inherit-sentinel option is hidden from the control. Apply
// also receives the derived
// value (as `derived`) and may use it as a no-op shortcut when the
// user's pick matches base. Skip when your axis owns flags that never
// appear in base cells (PD-Disagg / HiCache / MegaMoE).
// deriveFromBase: (cell, fc, h) => ({ ... }) | null,
// Optional: hints for the renderer. Currently only pdDisagg uses this
// to report its role banner. Omit if not needed.
// getRenderHints: (value, fc) => ({ pdMode: ... }) | null,
// Returns the axis card JSX. The outer div MUST have key={axisId} so
// React can track it in the engine's map loop. Return null for
// axis-level gating (e.g. MegaMoE on Hopper). Lay out as a single
// compact horizontal row: title on the left, fields after.
render: ({ axisId, value, setValue, fc, base, s, h, renderChip, renderSelect, derived }) => {
if (/* axis-level gating fails */) return null;
return (
<div key={axisId} style={s.card}>
<div style={s.compactRow}>
<span style={s.axisTitle}>Axis Title</span>
{/* For multi-option fields, use renderSelect(...) — the default.
For on/off toggles or single-select chip groups, use
renderChip instead (see "Control choice" in the conventions
below). Read state from `value`; write via `setValue(next)`
(replaces the whole axis slot). */}
<span style={s.field}>
<span style={s.fieldLabel}>Field</span>
{renderSelect(value.slot, fc.entries, (v) =>
setValue({ ...value, slot: v }), base)}
</span>
</div>
</div>
);
},
},
```
**Important conventions**:
- Insert the entry in the position you want it rendered. `AXIS_HANDLERS`
is iterated in insertion order for both render and apply.
- Use `h.ANCHOR_NEAR_*` constants for insertion. Add a new anchor to the
helpers bundle if your axis needs to land somewhere new in the flag
block.
- Use lowercase HTML JSX tags only. Capitalized tags get rebound by
Mintlify.
- Inside `render`, read state via `value` (the slice for this axis).
Write state via `setValue(next)` (replaces the whole slice). For
compound axes, do `setValue({ ...value, [k]: nextK })`.
- Layout: one `s.compactRow` per axis card, `s.axisTitle` for the
leading label, one `s.field` per (label + input) pair.
- Control choice — `renderSelect` vs `renderChip`:
- `renderSelect(current, entries, onPick, base, labelFor?, opts?)` is
the **default** compact control (a `<select>` dropdown). It filters
hidden chips and disables greyed-out ones internally — no per-chip
`evaluateChip` loop needed in the render body. Most axes use it
(attention, moe, pdDisagg, hisparse, hicache, megamoe). Pass
`{ hideValues: [<sentinel>] }` when your `deriveFromBase` resolved to
a real value, so the inherit-sentinel ("Auto" / "Inherited" /
"current") doesn't clutter the dropdown.
- `renderChip(label, current, value, onPick, { disabled?, disabledReason? })`
renders a **button** instead of a dropdown row. Use it for a chip
group when you want the options laid out as buttons. It serves two
shapes:
- **Multi-toggle** (Parsers) — one independent on/off chip per item;
`current` is that item's effective bool, `value` is `true`, so the
chip is "checked" when the item is on.
- **Single-select** (Speculative) — a radio-style group; pass the
group's effective value as `current` and each option's id as
`value`, so exactly one chip is checked (`current === value`).
Chip groups own their visibility/disable filtering: loop
`h.evaluateChip(opt, base)` in the render body, skip `c.hidden`,
filter the inherit-sentinel yourself when `deriveFromBase` resolved
to a real value, and forward `c.disabled` / `c.disableReason` into
`renderChip`'s opts (this is what surfaces a disabled chip's tooltip,
e.g. a "Coming soon" entry).
- Selected chips use the same terracotta (`#D45D44`) as the Deploy
panel's selected button, so both widgets read as one
visual system. Don't introduce a per-axis accent color.
- Default-from-base: if your axis can be read out of base cells'
flags, implement `deriveFromBase` and have your render show the
derived value when state is the sentinel (e.g.
`const eff = value.tp !== null ? value.tp : (derived && derived.tp)`).
This is what makes a fresh playground load show the user's actual
recipe instead of "auto." Flag-parsing helpers on `h`:
`parseIntFlag`, `hasFlag`, `findFlagArg`.
- **Avoid the `in` operator wrapped in unary** (`!(x in y)`). Mintlify's
AST walker crashes on it (`TypeError: this[e] is not a function`). Use
`obj.key === undefined` or `obj.id !== undefined` instead. Bare
`if (key in obj)` (no surrounding `!`) is fine.
## 3.4 Document the per-cookbook schema
Edit the file header in `_playground.jsx` to add your new axis to the
"Recognised keys" list, with a one-line description of its schema.
Optionally add a paragraph below explaining its strip/insert policy.
Update the §2.3 axis table in [authoring-reference.md](authoring-reference.md) to list the new axis.
## 3.5 Migrate cookbooks that need it
For each cookbook that should expose this axis, add a
`playgroundFeatures.<axisId>` entry to its config. Verify the chip group
renders, options apply correctly, and the diff matches expectations.
---
## Pitfalls (engine work)
**Insertion anchor misses**`insertAfter` falls back to right-after
`--model-path` if none of its anchor prefixes are present. If your axis
emits flags that should land somewhere specific, include the most likely
anchor prefixes in your call. Order doesn't matter (set semantics).
**Conditional strips** — Some axes strip ONLY when overridden
(`attention.tp`, `moe.backend`, `speculative`, `megamoe`). Others strip
UNCONDITIONALLY whenever declared (`parsers`, `pdDisagg`, `hicache`). The
header comment in `AXIS_HANDLERS` documents which policy each axis uses;
follow the same pattern when adding a new axis. If unsure, prefer
conditional strip — it preserves base behavior when the user does not
opt in.
**Closure of `AXIS_HANDLERS`** — Inside a handler method, you can
reference `AXIS_HANDLERS.<otherAxis>` for cross-handler calls (megamoe
does this for `_gateOpen`). This works because `AXIS_HANDLERS` is in
lexical scope. Do NOT use this for general logic — it tightly couples
handlers. Reserve it for one handler's helpers shared between its own
`render` and `revertHidden`.
---
## Review checklist for a new-axis PR
- [ ] `AXIS_HANDLERS` is the ONLY place that mentions the new axis id
(apart from per-cookbook config). No `if (axisId === '<new>')`
branches anywhere in the engine.
- [ ] `initState` is deterministic and idempotent (does not depend on
the base cell).
- [ ] `apply` is pure — does not mutate inputs.
- [ ] `revertHidden` returns the same reference when nothing changed
(avoids unnecessary re-renders).
- [ ] `render` returns `null` when axis-level gating fails (whole card
hidden) — does not render an empty placeholder.
- [ ] `render` sets `key={axisId}` on its outer element.
- [ ] No `!(x in y)` patterns introduced (Mintlify AST walker crashes).
- [ ] File header lists the new axis in "Recognised keys".
- [ ] The §2.3 table in `authoring-reference.md` lists the new axis.
- [ ] One existing cookbook config is updated to consume the new axis,
and visual verification shows the diff is correct.
@@ -0,0 +1,107 @@
# MDX authoring rules (Mintlify) + invocation-example patterns
Loaded on demand by the `cookbook-add-model` skill (Phase 5, writing the page prose).
These are model-agnostic Mintlify hygiene rules — the most common review findings.
The cookbook is **Mintlify**, not Docusaurus.
## Mintlify syntax
**Allowed components**: `<Card>`, `<CardGroup>`, `<Note>`, `<Tip>`, `<Warning>`,
`<Info>`, `<Accordion>`, `<AccordionGroup>`, `<Steps>`, `<Step>`, `<Tabs>`, `<Tab>`,
`<CodeGroup>`, `<Frame>`, `<Icon>`.
**Forbidden** (flag every occurrence):
- Docusaurus admonitions (`:::note` / `:::warning` / …) — use `<Note>` / `<Warning>`.
- `@site/...` / `@theme/...` imports — use absolute `/src/snippets/...`.
- GitHub alert blocks (`> [!NOTE]`, `> [!WARNING]`).
- **Markdown pipe tables** on new pages — use JSX `<table>` (see below).
- Inline `<details>` / `<summary>` — use `<Accordion>`.
- Unknown / non-Mintlify components.
- `<CardGroup>` / `<Card>` on individual model pages — those are for category `intro.mdx` only.
**Code fences**: always labeled — ` ```python Example `, ` ```bash Command `,
` ```shell Command `, ` ```text Output `. When nesting a fenced block inside another,
the **outer** fence uses four backticks.
**Internal links**: root-relative, no extension (`/cookbook/<category>/<Vendor>/<Model>`);
`docs.sglang.io` is canonical. Flag `.md`/`.mdx` extensions and `../`-relative page links
in body prose. (Existing cookbook pages do use `../../../docs/...` for cross-links into
the non-cookbook docs tree — that's the established exception; don't introduce new ones.)
## JSX tables (required for all tables on new pages)
```jsx
<table style={{width: "100%", borderCollapse: "collapse", tableLayout: "fixed"}}>
<thead>
<tr style={{borderBottom: "2px solid #d55816"}}>
<th style={{textAlign: "left", padding: "10px 12px", fontWeight: 700}}>Col</th>
</tr>
</thead>
<tbody>
<tr><td style={{padding: "9px 12px"}}>cell</td></tr>
</tbody>
</table>
```
Alternate column background colors (`rgba(255,255,255,0.02)` / `0.05`) for readability;
adjust `<colgroup>` widths for 3- or 5-column tables. The DeepSeek-V4 page §1 variants
table is a live reference.
## Invocation-example patterns (§3 Advanced Usage)
- **Reasoning-parser output shape must match the example**:
- *Separate-field* parsers (most qwen/glm, `kimi_k2`, `deepseek-v4`): thinking lands
in `message.reasoning_content`, answer in `message.content` — print both.
- *Inline-tag* parsers (e.g. `minimax-append-think`): thinking is wrapped in
`<think>...</think>` **inside** `message.content` — the client parses the tags; for
streaming, buffer and split on the markers.
Pick the pattern from the model card / SGLang docs for that specific parser.
- **Hybrid reasoning models**: show both thinking-on (default) and thinking-off
(`extra_body={"chat_template_kwargs": {"thinking": False}}` or `enable_thinking: False`).
- **Tool-call follow-up on thinking models**: the final assistant turn may put text in
`reasoning_content` instead of (or with) `content` — print both so the output isn't a
misleading `None`.
- **Every runnable block** is immediately followed by `**Output Example:**` + a
` ```text Output ` block with **real** server output (verbatim, not paraphrased).
`Pending update...` is acceptable only with the user's explicit acknowledgement.
- **Do not hardcode sampling params** (`temperature`, `top_p`) in sample code — SGLang
uses `generation_config.json` defaults. Listing "Recommended generation" in §1 is fine.
- Format raw API objects (`ChatCompletionMessage(...)`) into readable Reasoning /
Content / Tool Calls blocks.
## Frontmatter
- **Top-level `description:`** is the canonical field — it sets the page's SEO meta
description (`og:`/`twitter:description` fall back to it) AND renders as the visible
**subtitle** under the title, filling the header band before the first heading. Give every
page a one-line top-level `description` (a lede / value prop) — without it, a page that
opens straight into `## Deployment` shows an empty gap under the title (the title and
`## Deployment` are the same size, so they read as two bare headings). Do **not** put the
description inside a `metatags` block — `metatags` is for other/custom tags, and
`metatags.description` is redundant with (and non-canonical vs) the top-level field.
- **Write it for SEO** (it doubles as the search-result snippet): front-load the exact
model name + intent — e.g. `Deploy <Model> with SGLang — …` — aim for ~150160 chars, and
pack secondary keywords (variants + sizes, `Mixture-of-Experts` / architecture, target
GPUs). Phrase it as a value prop, not a generic "`<Model>` is a … model" intro.
- Frontmatter MUST be the first thing in the file — no comment or blank line before the
opening `---`.
## Commands & ports
- **Deploy/launch** commands use `sglang serve --model-path …` — never
`python -m sglang.launch_server` / `python3 -m sglang.launch_server` (deprecated).
- **Benchmark workload** commands use `python3 -m sglang.bench_serving …` (never bare
`python -m`); built-in accuracy scripts use `python3 benchmark/...`.
- Port **30000** everywhere on a page — launch, curl, client `base_url`, and bench must
agree. Keep one canonical deploy command (the Deploy widget) and don't re-paste launch
commands across sections; the documented command must match the widget's output for the
same selection (doc ↔ config parity).
## Factual hygiene
- License must match the actual HuggingFace license (don't copy from another model).
- HF URLs resolve to a real model; Docker images from `lmsysorg/sglang`.
- No Google-Drive image links (they don't render); host images in the repo.
- Shell placeholders are `export VAR=<value>`, not `export VAR=${VAR}` (a bash no-op).
- `tag: NEW` is sparing — at most one per `<category>/<Vendor>/` dir (the newest); strip
it from siblings when adding a new NEW page.
@@ -0,0 +1,76 @@
# Vendor card logo (new brand only)
A new vendor/brand in the cookbook landing grid needs a card logo at
`docs_new/cards/logos/<org-slug>.png`. **Ask the user for the brand's logo, then generate
the conforming PNG** — never invent, copy, or hallucinate one, and never ship a
non-conforming file. Reference: PR #27400 (added `tencent.png` + `poolside.png`).
If the org already has a card/logo, do nothing here — only update the `<Card href>`.
## Spec (match the existing logos exactly)
| Property | Value |
|---|---|
| Path | `docs_new/cards/logos/<org-slug>.png` — lowercase, matches the `img=` in the `<Card>` |
| Canvas | **940 × 525** px |
| Mode | **RGBA**, fully **transparent** background |
| Content | **Icon-only** — the brand glyph/mark (the "swirl"), **no wordmark text** |
| Placement | centered; glyph ≈ 0.33 × width and ≈ 0.50 × height of the canvas |
Why icon-only + transparent: cards render on both light and dark backgrounds, so a baked-in
(usually black) wordmark vanishes on dark. `deepseek.png` / `ernie.png` are 940×525 RGBA
exemplars — eyeball your output against them.
## 1. Get the source
Ask the user for the brand logo (SVG preferred → crisp + already transparent; else a high-res
transparent PNG, or a link to the official press/brand asset). Prefer an **icon-only** source;
if they only have a full lockup, ask them to crop the glyph, or crop it yourself.
If the user **pasted** an image inline, it may not be on disk — recover the base64 `image`
block from the session transcript (`~/.claude/projects/<slug>/*.jsonl`) and decode it to a file.
## 2. Generate (Pillow)
There's no system Pillow — use a venv:
```bash
python3 -m venv /tmp/logo-venv && /tmp/logo-venv/bin/pip install -q Pillow
```
```python
from PIL import Image
src = Image.open("SOURCE").convert("RGBA") # icon-only, already transparent
W, H = 940, 525
target_h = round(H * 0.50) # glyph ≈ half the canvas height
scale = target_h / src.height
glyph = src.resize((round(src.width * scale), target_h), Image.LANCZOS)
canvas = Image.new("RGBA", (W, H), (0, 0, 0, 0)) # transparent
canvas.paste(glyph, ((W - glyph.width) // 2, (H - glyph.height) // 2), glyph)
canvas.save("docs_new/cards/logos/<org-slug>.png")
```
Notes:
- **Wordmark present?** Crop to the glyph first (or ask the user for an icon-only asset). Don't
ship text in the logo.
- **Solid background?** Don't auto-strip it (risky) — ask the user for a transparent source.
- **SVG source?** Rasterize at high res first (`cairosvg` / `rsvg-convert`), then run the above.
- If the glyph is much wider than tall, cap by width instead (≈ 0.33 × W) so it doesn't overflow.
## 3. Verify
```bash
sips -g pixelWidth -g pixelHeight -g hasAlpha docs_new/cards/logos/<org-slug>.png
# → pixelWidth: 940 pixelHeight: 525 hasAlpha: yes
```
## 4. Wire + track + validate
```bash
# Card in the landing grid (keep card order aligned with the docs.json nav order):
# <Card title="<NavGroup>" mode="card"
# href="/cookbook/<category>/<Vendor>/<Model>"
# img="/cards/logos/<org-slug>.png" />
git add -f docs_new/cards/logos/<org-slug>.png # root .gitignore ignores *.png repo-wide
cd docs_new && mint validate && mint broken-links # confirms the card href + img resolve
```
@@ -0,0 +1,29 @@
// TEMPLATE — instantiate via the cookbook-add-model skill. NOT a live cookbook.
// Copy to docs_new/src/snippets/configs/<hf-org>/<model-slug>-benchmarks.jsx and
// fill measured numbers — OR delete this file entirely if you have none yet (the
// MDX simply omits the `benchmarks` import/prop).
//
// One entry per cell `match` tuple (same 5 keys as config cells). The card stays
// "pending" until an entry has a non-null speed metric or accuracy. Speed shape:
// speed: [{ workload: {dataset, isl, osl, max_concurrency}, ttft_ms, tpot_ms,
// tokens_per_sec_per_gpu }, ...] // interactivity is derived (1000/TPOT)
// Per-cell `accuracy: { <key>: <pct> }` overrides the config's defaultAccuracy.
export const benchmarks = [
// EXAMPLE — one filled entry showing the shape; replace numbers, add one per cell.
{
match: { hw: "b200", variant: "default", quant: "fp4", strategy: "low-latency", nodes: "single" },
sglang_version: "0.0.0", // TODO: ASK the user for the sglang version these numbers were measured on — don't invent one
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 1 },
ttft_ms: null, tpot_ms: null, tokens_per_sec_per_gpu: null },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 16 },
ttft_ms: null, tpot_ms: null, tokens_per_sec_per_gpu: null },
],
},
// Bare-match stubs (no data yet) are fine — the card shows "pending" for these.
{ match: { hw: "h200", variant: "default", quant: "fp8", strategy: "balanced", nodes: "single" } },
{ match: { hw: "h100", variant: "default", quant: "fp4", strategy: "high-throughput", nodes: "single" } },
{ match: { hw: "mi300x", variant: "default", quant: "bf16", strategy: "balanced", nodes: "single" } },
{ match: { hw: "b200", variant: "default", quant: "fp4", strategy: "high-throughput", nodes: "multi-2" } },
];
@@ -0,0 +1,374 @@
// TEMPLATE — instantiate via the cookbook-add-model skill. NOT a live cookbook.
// Copy to docs_new/src/snippets/configs/<hf-org>/<model-slug>.jsx, then:
// 1. replace every __TOKEN__,
// 2. fill cells[] with your verified recipes (the examples below show the shape),
// 3. DELETE the hardware / playground axes / quantizations your model lacks.
//
// Instantiation tokens (skill fills these; distinct from the engine's runtime
// {{PLACEHOLDER}} which MUST survive verbatim into the output):
// __MODEL_DISPLAY__ display name, e.g. "DeepSeek-V4"
// __MODEL_SLUG__ file slug, e.g. "deepseek-v4"
// __HF_ORG__ HuggingFace org, e.g. "deepseek-ai"
// __HF_REPO__ HuggingFace repo, e.g. "DeepSeek-V4-Flash"
// __REASONING_PARSER__ e.g. "deepseek-v4" (delete the parsers axis if none)
// __TOOLCALL_PARSER__ e.g. "deepseekv4" (delete the parsers axis if none)
//
// Mintlify: single `export const config = {...}` literal — no spreads/calls/IIFE,
// no `!(x in y)`. Cells are denormalized: no --nnodes/--node-rank/--dist-init-addr/
// --host/--port literals (the engine injects them).
export const config = {
modelName: "__MODEL_DISPLAY__",
// List ONLY hardware you ship a cell for; unlisted ids auto-grey-out. The full
// catalog is below — delete the families your model doesn't support (e.g. drop
// every `mi*` if there's no AMD recipe).
supportedHardware: [
"h100", "h200", "b200", "b300", "gb200", "gb300",
"mi300x", "mi325x", "mi350x", "mi355x",
],
// OPTIONAL — declare GPUs the shared HARDWARE_CATALOG (in _deployment.jsx) doesn't
// carry (workstation / desktop / future chips). The engine merges these in, so a
// model-specific GPU is config data, never an engine-catalog edit. Add the id to
// supportedHardware above too. Delete if you only use catalog GPUs.
// hardware: [
// { id: "rtx6000", label: "RTX PRO 6000", vram: "96GB", vendor: "nvidia" },
// ],
// 2nd dim. Single-element `default` if the model has no variant axis; else list
// real variants (e.g. {id:"flash",...},{id:"pro",...}) and key modelNames/
// defaultAccuracy by them.
variants: [
{ id: "default", label: "Default" },
],
// 3rd dim. Keep only what your model ships (BF16 / FP8 / FP4 / …).
quantizations: [
{ id: "bf16", label: "BF16" },
{ id: "fp8", label: "FP8" },
{ id: "fp4", label: "FP4" },
],
strategies: [
{ id: "low-latency", label: "Low-Latency" },
{ id: "balanced", label: "Balanced" },
{ id: "high-throughput", label: "High-Throughput" },
],
// `multi-N` id carries the node count for `--nnodes N`.
nodesOptions: [
{ id: "single", label: "Single Node" },
{ id: "multi-2", label: "Multi-Nodes" },
],
// HF slug lookup. Key by `variant|quant` (or `hw|variant|quant` for a per-hw
// repackaging, e.g. an FP8 conversion only valid on one platform).
modelNames: {
"default|bf16": "__HF_ORG__/__HF_REPO__",
"default|fp8": "__HF_ORG__/__HF_REPO__",
"default|fp4": "__HF_ORG__/__HF_REPO__",
},
placeholders: {
HOST_IP: { target: "command", label: "Bind host", default: "0.0.0.0" },
PORT: { target: "command", label: "Bind port", default: "30000" },
NODE0_IP: { target: "command", label: "Head node IP", default: "<node0-ip>" },
NODE_RANK: { target: "command", label: "This node rank", default: "<node-rank>" },
HF_TOKEN: { target: "command", label: "HF token (Docker)", default: "<your-hf-token>" },
CURL_HOST: { target: "curl", label: "Server host", default: "localhost" },
CURL_PORT: { target: "curl", label: "Server port", default: "30000" },
},
curl: `curl http://{{CURL_HOST}}:{{CURL_PORT}}/v1/chat/completions \\
-H 'Content-Type: application/json' \\
-d '{ "model": "{{MODEL_NAME}}", "messages": [{"role":"user","content":"Hello"}] }'`,
// OPTIONAL — powers the benchmark card's "⚡ Reproduce" modal. Delete the whole
// block (and the benchmarks file) if you have no measured numbers yet.
benchmarkCommands: {
speed:
`python3 -m sglang.bench_serving \\
--backend sglang \\
--host {{CURL_HOST}} --port {{CURL_PORT}} \\
--model {{MODEL_NAME}} \\
--dataset-name {{DATASET}} \\
--random-input-len {{ISL}} --random-output-len {{OSL}} \\
--num-prompts {{NUM_PROMPTS}} --max-concurrency {{MAX_CONCURRENCY}}`,
// One entry per accuracy field. A value is a string, OR a {[variant]: string}
// object when the command differs per variant. Keys must match ACCURACY_LABELS
// in _deployment.jsx + the per-cell/defaultAccuracy keys.
accuracy: {
gsm8k_pct:
`# To install sgl-eval: pip install git+https://github.com/sgl-project/sgl-eval
sgl-eval run gsm8k \\
--base-url http://{{CURL_HOST}}:{{CURL_PORT}}/v1 \\
--num-threads 32`,
},
// {{NUM_PROMPTS}} fallback per concurrency (else max(c*2, 200)).
numPromptsByConc: { 1: 8, 16: 32, 64: 128, 256: 512, 1024: 2048, 4096: 4096 },
},
// OPTIONAL — per-variant accuracy applied to EVERY cell of a variant (hardware-
// independent, e.g. GPQA/AIME). Per-cell `accuracy` overrides. Keys must match
// ACCURACY_LABELS + benchmarkCommands.accuracy. Delete if no numbers yet.
defaultAccuracy: {
default: { gsm8k_pct: null },
},
// OPTIONAL — `# ...` hint lines prepended to multi-node commands, ONLY for hw
// whose fabric needs manual NIC env (e.g. gb200 NVL72/MNNVL). NOT every multi-N
// hw needs this — standard-IB DeepEP / Marlin multi-node don't. Delete if unused.
multiNodeHints: {
gb200: [
"The following env vars may be needed depending on your cluster:",
" GLOO_SOCKET_IFNAME=<your-nic>",
" NVSHMEM_ENABLE_NIC_PE_MAPPING=1",
" NVSHMEM_HCA_LIST=<your-hca-list>",
],
},
// Per-hw image for `docker run` framing. ASK the user which sglang build the recipes ran
// on; don't guess a supporting release. Default below is :dev (nightly) — replace the tag
// with the user's release if they give one. NVIDIA share one image; AMD uses ROCm tags.
// GB200/GB300/B300 may need a `-cu130` (CUDA 13) tag — confirm per release.
dockerImages: {
h100: "lmsysorg/sglang:dev",
h200: "lmsysorg/sglang:dev",
b200: "lmsysorg/sglang:dev",
b300: "lmsysorg/sglang:dev",
gb200: "lmsysorg/sglang:dev",
gb300: "lmsysorg/sglang:dev",
mi300x: "lmsysorg/sglang:dev-rocm720-mi30x",
mi325x: "lmsysorg/sglang:dev-rocm720-mi30x",
mi350x: "lmsysorg/sglang:dev-rocm720-mi35x",
mi355x: "lmsysorg/sglang:dev-rocm720-mi35x",
},
// Pre-selects the issue template's `model` dropdown on "Submit verified cell".
// Must match that dropdown's value (usually `<hf-org>/<model-slug>`).
github: {
cookbookModel: "__HF_ORG__/__MODEL_SLUG__",
},
// Opt-in per axis. DELETE any axis your model doesn't expose (don't leave a stub).
playgroundFeatures: {
// ----- Card: "Attention Parallelism" ----- KEEP if the model exposes TP/CP/DP
// knobs. DP-Attention is a combined knob: value = DP degree AND toggles `--enable-dp-attention`.
attention: {
knobs: [
{ id: "tp", label: "TP", values: [
null, 1, 2, 4, 8,
{ value: 16, disable: { nodes: ["single"] },
disableReason: "TP=16 requires 16 ranks — switch the Deploy panel's Nodes to Multi-Nodes first." },
]},
{ id: "cp", label: "CP", values: [null, 1, 2, 4] },
{ id: "dpAttn", label: "DP-Attention",
values: [
null, false, 1, 2, 4, 8,
{ value: 16, disable: { nodes: ["single"] },
disableReason: "DP-Attention=16 requires 16 ranks — switch the Deploy panel's Nodes to Multi-Nodes first." },
],
labels: { "auto": "Auto", "false": "Off" } },
],
},
// ----- Card: "MoE Parallelism" ----- KEEP if MoE + multiple `--moe-*-backend`
// choices. DELETE for dense models.
moe: {
backend: {
options: [
{ id: null, label: "Inherited" },
{ id: "deepep", label: "DeepEP", flags: ["--moe-a2a-backend deepep"] },
{ id: "flashinfer_mxfp4", label: "FlashInfer (MXFP4)", flags: ["--moe-runner-backend flashinfer_mxfp4"] },
{ id: "marlin", label: "Marlin (W4A16)", flags: ["--moe-runner-backend marlin"] },
],
},
ep: { label: "EP", values: [
null, 1, 2, 4, 8,
{ value: 16, disable: { nodes: ["single"] },
disableReason: "EP=16 requires 16 ranks — switch the Deploy panel's Nodes to Multi-Nodes first." },
]},
},
// ----- Card: "Parsers" ----- KEEP if the model has reasoning / tool-call
// parsers (set the slugs below). DELETE the axis if neither applies.
parsers: {
items: [
{ id: "reasoning", label: "Reasoning Parser", flag: "--reasoning-parser __REASONING_PARSER__" },
{ id: "toolCall", label: "Tool Call Parser", flag: "--tool-call-parser __TOOLCALL_PARSER__" },
],
},
// ----- Card: "Speculative Decoding" ----- KEEP if the model has spec-decoding
// presets. Drop options the model doesn't support.
speculative: {
options: [
{ id: "current", label: "Inherited from base" },
{ id: "off", label: "Off (greedy)" },
{ id: "mtp", label: "EAGLE / MTP",
flags: ["--speculative-algorithm EAGLE", "--speculative-num-steps 3",
"--speculative-eagle-topk 1", "--speculative-num-draft-tokens 4"] },
{ id: "ngram", label: "NGRAM",
flags: ["--speculative-algorithm NGRAM",
"--speculative-num-draft-tokens 16",
"--speculative-ngram-max-bfs-breadth 10"],
disable: { dpAttnOn: [true] },
disableReason: "NGRAM is incompatible with DP-Attention. Turn DP-Attention off in the Attention card above to use NGRAM." },
],
},
// ----- Card: "PD Disaggregation" ----- KEEP if the model supports prefill/
// decode disaggregation. Delete `router` if you have no router topology.
pdDisagg: {
modes: [
{ id: "off", label: "Off" },
{ id: "prefill", label: "Prefill role" },
{ id: "decode", label: "Decode role" },
],
transferBackends: [
{ id: "mooncake", label: "Mooncake",
env: ["NCCL_MNNVL_ENABLE=1", "NCCL_CUMEM_ENABLE=1"],
envWhen: { hw: ["gb200", "gb300"] } },
{ id: "nixl", label: "NiXL" },
],
// `auto` is a sentinel (emits no --disaggregation-ib-device flag).
ibDevices: [{ id: "auto", label: "Auto" }, "mlx5_0", "mlx5_7"],
// Router fronting prefill + decode; substitute <prefill-host>/<decode-host>.
router: {
port: 8000,
command:
`python3 -m sglang_router.launch_router \\
--pd-disaggregation \\
--prefill http://<prefill-host>:30000 \\
--decode http://<decode-host>:30001 \\
--host 0.0.0.0 --port 8000 \\
--disable-circuit-breaker \\
--health-check-interval-secs 999999`,
},
},
// ----- Card: "Hierarchical KV Cache" ----- KEEP if the model is large enough
// that hierarchical KV caching matters.
hicache: {
backends: [
{ id: null, label: "Auto" },
{ id: "file", label: "File" },
{ id: "mooncake", label: "Mooncake" },
{ id: "hf3fs", label: "HF3FS" },
{ id: "nixl", label: "NiXL" },
],
writePolicies: [
{ id: "auto", label: "Auto" },
{ id: "write_through", label: "Write-through" },
{ id: "write_back", label: "Write-back" },
{ id: "write_through_selective", label: "Write-through (selective)" },
],
},
// ----- Card: "HiSparse" ----- KEEP only for DSA-style sparse-attention models
// (DeepSeek-V3.2/V4, GLM-5). Decode-only: shown when live PD-Disagg mode is `decode`.
hisparse: {
requiredFlags: ["--disable-radix-cache"],
config: { top_k: 2048, device_buffer_size: 6144 },
hostRatios: [
{ id: 5, label: "5 (~1TB host)" },
{ id: 10, label: "10 (~2TB host)" },
],
defaultHostRatio: 10,
},
// ----- Card: "MegaMoE" ----- KEEP only for Blackwell MoE kernel-fusion models.
megamoe: {
requiresHw: ["b200", "b300", "gb200", "gb300"],
excludesStrategy: ["low-latency", "balanced"],
stripEnv: ["SGLANG_DEEPEP_NUM_MAX_DISPATCH_TOKENS_PER_RANK"],
options: [
{ id: "disabled", label: "Disabled" },
{ id: "w4a8", label: "W4A8",
flags: ["--moe-a2a-backend megamoe"],
env: ["SGLANG_OPT_DEEPGEMM_MEGA_MOE_NUM_MAX_TOKENS_PER_RANK=8320"] },
],
},
},
// EXAMPLE cells — one per hardware family to show the shape. REPLACE each with
// your model's verified recipe, or DELETE families you don't support. `match`
// MUST have exactly the 5 keys; env/flags are flat literals.
cells: [
// ==== NVIDIA Blackwell + FP4 (single node) ====
{
match: { hw: "b200", variant: "default", quant: "fp4", strategy: "low-latency", nodes: "single" },
verified: true, // EXAMPLE — set false / replace with your verified recipe
env: [],
flags: [
"--trust-remote-code",
"--model-path {{MODEL_NAME}}",
"--tp 4",
"--moe-runner-backend flashinfer_mxfp4",
"--host {{HOST_IP}}",
"--port {{PORT}}",
],
},
// ==== NVIDIA Hopper + FP8 (single node, DP-attention + DeepEP) ====
{
match: { hw: "h200", variant: "default", quant: "fp8", strategy: "balanced", nodes: "single" },
verified: true, // EXAMPLE
env: ["SGLANG_DEEPEP_NUM_MAX_DISPATCH_TOKENS_PER_RANK=256"],
flags: [
"--trust-remote-code",
"--model-path {{MODEL_NAME}}",
"--tp 4",
"--dp 4",
"--enable-dp-attention",
"--moe-a2a-backend deepep",
"--host {{HOST_IP}}",
"--port {{PORT}}",
],
},
// ==== NVIDIA Hopper + FP4 (single node, Marlin W4A16 — Hopper has no FP4 runner) ====
{
match: { hw: "h100", variant: "default", quant: "fp4", strategy: "high-throughput", nodes: "single" },
verified: true, // EXAMPLE
env: [],
flags: [
"--trust-remote-code",
"--model-path {{MODEL_NAME}}",
"--tp 8",
"--moe-runner-backend marlin",
"--host {{HOST_IP}}",
"--port {{PORT}}",
],
},
// ==== AMD + BF16 (single node) — Triton attention + AITER; EP == TP for MoE ====
{
match: { hw: "mi300x", variant: "default", quant: "bf16", strategy: "balanced", nodes: "single" },
verified: true, // EXAMPLE
env: ["SGLANG_USE_AITER=1", "SGLANG_ROCM_FUSED_DECODE_MLA=0"],
flags: [
"--trust-remote-code",
"--model-path {{MODEL_NAME}}",
"--tp 8",
"--ep 8",
"--attention-backend triton",
"--host {{HOST_IP}}",
"--port {{PORT}}",
],
},
// ==== Multi-node example (2 nodes, TP=16) — engine injects --nnodes/--node-rank/
// --dist-init-addr from match.nodes; do NOT add them here. ====
{
match: { hw: "b200", variant: "default", quant: "fp4", strategy: "high-throughput", nodes: "multi-2" },
verified: true, // EXAMPLE
env: [],
flags: [
"--trust-remote-code",
"--model-path {{MODEL_NAME}}",
"--tp 16",
"--dp 16",
"--enable-dp-attention",
"--moe-a2a-backend deepep",
"--host {{HOST_IP}}",
"--port {{PORT}}",
],
},
],
};
@@ -0,0 +1,148 @@
---
title: __MODEL_DISPLAY__
description: "__ONE_LINER__"
tag: NEW
mode: wide
---
{/* TEMPLATE — instantiate via the cookbook-add-model skill, then DELETE this banner.
(Frontmatter MUST stay the first thing in the file, so this note lives below it.)
Replace every __TOKEN__, fill the TODO prose, delete the §3 subsections your model
lacks. Tokens: __MODEL_DISPLAY__ __ONE_LINER__ __HF_ORG__ __MODEL_SLUG__ __HF_REPO__
__REASONING_PARSER__ __TOOLCALL_PARSER__. MDX rules (JSX tables, labeled fences, no
Docusaurus/@site/GitHub-alert/pipe-tables):
.claude/skills/cookbook-add-model/references/mintlify-authoring.md */}
## Deployment
<a id="install" />
<Accordion title="Install SGLang">
For all methods and hardware platforms, see the [official SGLang installation guide](../../../docs/get-started/install). The two paths below match the **Python / Docker** toggle in the command panel.
<Tabs>
<Tab title="Python (pip / uv)">
```bash Command
pip install --upgrade pip
pip install uv
uv pip install sglang
```
Then run the **Python** output of the command panel below in that environment.
</Tab>
<Tab title="Docker">
```bash Command
docker pull lmsysorg/sglang:latest
```
For how to launch the image, see [Install → Method 3: Using Docker](../../../docs/get-started/install#method-3-using-docker). Substitute the inner `sglang serve ...` with what the command generator below produces.
</Tab>
</Tabs>
</Accordion>
Pick your hardware + recipe to generate the launch command. The three serving strategies cover the common operating points:
- **Low-Latency** — fastest reply for a single user. Pick for chat.
- **Balanced** — good speed with several users at once. Use for typical multi-user serving.
- **High-Throughput** — most tokens per second across many users. Best for batch jobs.
import { Deployment } from "/src/snippets/_deployment.jsx";
import { config } from "/src/snippets/configs/__HF_ORG__/__MODEL_SLUG__.jsx";
import { benchmarks } from "/src/snippets/configs/__HF_ORG__/__MODEL_SLUG__-benchmarks.jsx";
<Deployment config={config} benchmarks={benchmarks} />
## Playground
The Playground is where you experiment with **SGLang features beyond the verified matrix**. The Deploy panel above only emits combinations the SGLang team has signed off on; the Playground lets you turn on additional knobs on top of whichever cell the Deploy panel is currently showing.
import { Playground } from "/src/snippets/_playground.jsx";
<Playground config={config} />
## 1. Model Introduction
{/* TODO: 1-2 paragraph intro from the HF card — what the model is, release date,
license, architecture highlights, context length. Keep it lean. */}
**__MODEL_DISPLAY__** is __ONE_LINER__.
{/* TODO: variants table (JSX, NOT a markdown pipe table). Drop the table if there's
a single variant and inline the HF link in the intro paragraph above instead. */}
<table style={{width: "100%", borderCollapse: "collapse", tableLayout: "fixed"}}>
<thead>
<tr style={{borderBottom: "2px solid #d55816"}}>
<th style={{textAlign: "left", padding: "10px 12px", fontWeight: 700}}>Variant</th>
<th style={{textAlign: "right", padding: "10px 12px", fontWeight: 700}}>Total params</th>
<th style={{textAlign: "left", padding: "10px 12px", fontWeight: 700}}>Use</th>
</tr>
</thead>
<tbody>
<tr>
<td style={{padding: "9px 12px"}}><strong><a href="https://huggingface.co/__HF_ORG__/__HF_REPO__">__MODEL_DISPLAY__</a></strong></td>
<td style={{padding: "9px 12px", textAlign: "right"}}>TODO</td>
<td style={{padding: "9px 12px"}}>TODO</td>
</tr>
</tbody>
</table>
**Recommended generation:** {/* TODO e.g. `temperature=1.0`, `top_p=1.0` (informational; do NOT hardcode in sample code) */}
**Resources:** [HuggingFace](https://huggingface.co/__HF_ORG__/__HF_REPO__).
## 2. Configuration Tips
{/* TODO: model/hardware-specific tuning notes, caveats, known issues. Delete if none. */}
## 3. Advanced Usage
{/* Keep only the subsections that apply. Each runnable block is followed by an
**Output Example:** + a ```text Output block with REAL server output. */}
### 3.1 Reasoning
Enable the `__REASONING_PARSER__` reasoning parser (toggle **Reasoning Parser** in the **Parsers** card of the [Playground above](#playground)) to separate thinking from the final answer.
{/* This example assumes a SEPARATE-FIELD parser (thinking → `reasoning_content`,
answer → `content`). If your parser emits inline `<think>...</think>` tags inside
`content`, parse the tags from `content` instead. */}
```python Example
from openai import OpenAI
client = OpenAI(base_url="http://localhost:30000/v1", api_key="EMPTY")
resp = client.chat.completions.create(
model="__HF_ORG__/__HF_REPO__",
messages=[{"role": "user", "content": "What is 15% of 240?"}],
extra_body={"chat_template_kwargs": {"thinking": True}},
)
msg = resp.choices[0].message
print("Reasoning:", getattr(msg, "reasoning_content", None))
print("Answer:", msg.content)
```
**Output Example:**
```text Output
TODO: paste real server output here.
```
### 3.2 Tool Calling
Enable the `__TOOLCALL_PARSER__` tool-call parser (toggle **Tool Call Parser** in the **Parsers** card of the [Playground above](#playground)) to surface structured tool calls via `message.tool_calls`.
{/* TODO: tool-calling example + **Output Example:**. On thinking-mode models the
follow-up may put text in `reasoning_content`; print both that and `content`. */}
### 3.3 HiCache (Hierarchical KV Caching)
{/* TODO: keep only if the model is large enough for hierarchical KV caching; link
the HiCache card in the Playground. Otherwise delete this subsection. */}
+177
View File
@@ -0,0 +1,177 @@
---
name: cookbook-review-pr
description: Review a pull request against the SGLang Cookbook (docs_new/, Mintlify) contribution checklist — the config-driven format (per-model config + benchmarks JSX consumed by the shared _deployment.jsx / _playground.jsx engines). Run with /cookbook-review-pr <PR number>.
---
# Cookbook Review PR
Fetch the diff, run the checklist, report what you find. The cookbook is **config-driven**:
shared engines (`_deployment.jsx`, `_playground.jsx`) with NO model-specific code; each
model is a data `config` (+ optional `benchmarks`) under `src/snippets/configs/<vendor>/`
plus an MDX page. This checklist targets that layout. Field-schema detail lives in
`.claude/skills/cookbook-add-model/references/authoring-reference.md` — defer to it rather
than restating.
## Usage
```
/cookbook-review-pr <PR number>
```
## Steps
1. `gh pr view <N> --repo sgl-project/sglang --json title,body,files,author,baseRefName,headRefName,commits,reviews`
2. `gh pr diff <N> --repo sgl-project/sglang`
3. `gh pr list --repo sgl-project/sglang --state open --search "<model name>"` (duplicate check)
4. Run every checklist item against the diff.
5. Output per-file verdicts + overall recommendation.
## Checklist
### 1. File hygiene
- A cookbook PR should only touch: `docs_new/src/snippets/configs/<vendor>/*.jsx`
(config + benchmarks), `docs_new/cookbook/**/*.mdx`, `docs_new/docs.json`,
`docs_new/cookbook/<category>/intro.mdx` (vendor card), `docs_new/cards/logos/<vendor>.png`
(new vendor only). Flag stray files (`settings.local.json`, lockfiles, IDE configs).
- Pages must be `.mdx`, not `.md`. Files end with a trailing newline. Check commit history
for unrelated commits accidentally included.
- **Engines untouched**: `_deployment.jsx` / `_playground.jsx` should NOT change in a
model-add PR (adding a model is data-only). Engine edits = a separate axis/feature PR
(see `cookbook-add-model/references/engine-axis.md`); review them against that checklist.
### 2. Config quality (the per-model `config`)
- Single `export const config = { ... }` literal — **no** function calls, spreads,
fragment refs, or IIFE (Mintlify re-evals at hydration → `ReferenceError`).
- No `!(x in y)` anywhere (Mintlify AST walker crashes) — use `obj.key === undefined`.
- `supportedHardware``HARDWARE_CATALOG` (in `_deployment.jsx`) `config.hardware`. A
model-specific GPU the shared catalog lacks must be declared in `config.hardware`
(`{id,label,vram,vendor}`), **not** added to the engine catalog.
- `placeholders` declares every `{{KEY}}` used in `curl` or any cell.
- `modelNames` covers every cell (by `hw|variant|quant` triple or `variant|quant` pair).
- `dockerImages` covers the hw ids that have cells (else users hit the `:dev` fallback).
- `multiNodeHints` present ONLY for hw whose fabric needs manual NIC env (e.g. `gb200`
NVL72) — NOT every `multi-N` hw (standard-IB DeepEP / Marlin multi-node don't need it).
- `github.cookbookModel` matches the issue-template `model` dropdown value.
- `playgroundFeatures` axes are pruned to what the model supports — no empty/stub axes
(`megamoe` only on Blackwell MoE; `hisparse` only DSA-style; `pdDisagg.router` only with
a PD topology).
- **No leftover `__TOKEN__`** — the config was stamped from the template and every
placeholder is filled (`grep -rn '__[A-Z_]*__'` on the new config/benchmarks/MDX returns
nothing).
- **All-hardware considered**: every `supportedHardware` id (from the catalog or `config.hardware`) has ≥1 cell OR is a deliberate
greyed "coming soon"; AMD was pruned or kept on purpose (not a leftover template family).
### 3. Cells / 5-dim matrix
- Every cell `match` has EXACTLY the 5 keys (`hw`, `variant`, `quant`, `strategy`, `nodes`).
- `env` / `flags` are flat literals (only `{{PLACEHOLDER}}` subst) — no shared
`commonFlags` reference (Mintlify won't inline it).
- NO `--nnodes` / `--node-rank` / `--dist-init-addr` literals in multi-node cells
(the renderer injects them from `match.nodes`).
- NO literal `--host` / `--port` — use `{{HOST_IP}}` / `{{PORT}}`.
- Flag order: `--model-path` first, then parallelism, then MoE, then tuning, `--host`/`--port`
last (the playground's insert anchors assume this).
- TP/memory sanity: `model_weight_GB / (tp × gpu_mem)` fits with ~2030% headroom
(BF16 ≈ params×2 GB, FP8 ≈ ×1, FP4 ≈ ×0.5; MoE uses **total** weight, not active params).
### 4. Benchmarks
- Each `benchmarks[]` entry's `match` tuple corresponds to a real cell.
- `defaultAccuracy` keys ∈ `ACCURACY_LABELS` (and `benchmarkCommands.accuracy`).
- A benchmark's quantization must match a variant actually listed — `(BF16)` on a model
that only released FP8/FP4 is a factual bug.
- `benchmarkCommands.speed` is `python3 -m sglang.bench_serving` (the workload), separate
from the `sglang serve` deploy command.
- `sglang_version` is a real build the author ran (a release, or `dev`/nightly) — not a
guessed/placeholder value (no leftover `0.0.0`).
### 5. Doc ↔ config parity (the #1 finding)
- Any `sglang serve` command shown in MDX prose (config tips, benchmark section) must
equal what the engine emits from the corresponding cell — same flags, same order. Drift
here is the most common review miss.
### 6. Commands / port
- Launch uses `sglang serve` — flag any `python -m sglang.launch_server` /
`python3 -m sglang.launch_server` (deprecated). The engine already emits `sglang serve`;
guard against prose/cells reintroducing the old launcher.
- Port `30000` everywhere (launch, curl, client `base_url`, bench) — flag `8000`.
Launch port must match client/curl port on the same page.
### 7. Frontmatter
- Every new MDX page has `title:` and `metatags.description:` (a real one-line value prop,
not copied from another vendor).
- `tag: NEW` only for genuine new launches; when one is added, stale `tag: NEW` on older
pages should be dropped in the same PR (`grep -RlE "^tag: NEW" docs_new/cookbook/`).
- MDX imports BOTH `Deployment` and `Playground` from `/src/snippets/...` (absolute).
- Deploy heading slugs to `deployment` (or `deploy`), Playground to `playground` — so
"↑ Switch base" and "Open the Playground →" scroll. No numbered headings for these two.
### 8. Navigation & homepage
- New page → `docs_new/docs.json` updated: under the right vendor group inside
`navigation` → Cookbook → Autoregressive Models, root-relative, **no `.mdx`**:
`cookbook/<category>/<Vendor>/<Model>`.
- Homepage `<Card href>` in `docs_new/cookbook/<category>/intro.mdx` points to the vendor's
flagship; new vendors get a new `<Card>` + a logo at `docs_new/cards/logos/<vendor>.png`
**940×525 RGBA transparent, icon-only (no wordmark)**, lowercase filename, tracked via
`git add -f` (`*.png` is gitignored repo-wide). Card order matches the `docs.json` nav order.
- Don't change `docs_new/cookbook/intro.mdx` for individual model adds (top-level only).
### 9. Links & factual
- HuggingFace URLs resolve to a real model. License section matches the actual HF license
(don't copy from another model). Docker images from `lmsysorg/sglang`; no `sgl-project-dev`.
The image **tag** is a real build (a release the author ran, or `:dev`/nightly) — not a
guessed version.
- Internal links root-relative, no extension (`/cookbook/.../<Model>`); flag `.md`/`.mdx`
or `../`-relative links. `docs.sglang.io` is canonical.
- No Google-Drive image links (don't render). Shell placeholders are `export VAR=<value>`,
not `${VAR}` (a bash no-op).
### 9b. MDX authoring (Mintlify) — detail in `cookbook-add-model/references/mintlify-authoring.md`
- **Forbidden syntax**: no Docusaurus admonitions (`:::`), `@site`/`@theme`, GitHub alert
blocks (`> [!NOTE]`), markdown **pipe tables** (use JSX `<table>`), inline `<details>`,
or unknown components. `<CardGroup>`/`<Card>` only on category `intro.mdx`, not model pages.
- Code fences are **labeled** (e.g. `python Example` / `bash Command` / `text Output` after
the opening fence); a fenced block nested inside another uses four backticks outside.
- Every runnable invocation block is followed by `**Output Example:**` + a `text Output`
fenced block (real output, or `Pending update...` only with user acknowledgement).
- Reasoning-parser example matches the parser's **output shape**: separate-field
(`reasoning_content` + `content`) vs inline `<think>` tags parsed out of `content`.
- No hardcoded sampling params (`temperature` / `top_p`) in sample code (SGLang uses
`generation_config.json` defaults); listing them in §1 informationally is fine.
### 10. Quantization rules
- FP4 is Blackwell-only (B200/B300/GB300) — never AMD; AMD FP4 chips must be `disabled`.
- BF16 / FP8 work on NVIDIA and AMD. FP8 configs adding `--kv-cache-dtype fp8_e4m3` should
note the accuracy trade-off.
### 11. Scope
- Changes match the PR title. Flag global changes hiding behind a platform-specific title
(e.g. an "H200 FP8" PR that adds a flag to ALL cells). Unmentioned side-fixes belong in
the PR body.
### 12. Duplicate PRs
- Another open PR for the same model? Flag it; compare completeness; note merge-conflict
risk on `docs.json` + the vendor card; flag a superseded older PR by the same author.
### 13. Build / validate
```bash
cd docs_new
mint validate
mint broken-links
```
Optional: `mint dev` for a visual smoke test.
### 14. Reviewer feedback
- `gh api repos/sgl-project/sglang/pulls/<N>/comments` — have prior reviewer requests been
addressed? Unresolved requested-changes should be flagged.
### 15. Grammar & spelling
- Check added/changed prose for typos and grammar (e.g. "recommend" vs "recommended").
Flag each with the exact wrong text + correction.
## Output
Per file:
- ✅ PASS
- ⚠️ ISSUE: \<what\>
- 🔴 BLOCK: \<what\>
Overall: **APPROVE** / **REQUEST CHANGES** / **BLOCKED**
@@ -0,0 +1,109 @@
name: 🧪 Playground - Verified Cell Submission
description: Submit a deployment recipe you verified in the cookbook Playground. A maintainer will review and promote it into the cell catalog via PR.
title: "[Playground] Verified cell: <fill from playground>"
labels: ["cookbook", "playground-submission"]
body:
- type: markdown
attributes:
value: |
Thanks for verifying a deployment recipe!
The cookbook **Playground** section of each model page pre-fills this
form. When your overrides diverge from the verified cell, click
**Submit ↗**, confirm the SGLang version / benchmark / notes in the
**Submit verified cell** dialog and tick the attestations, then
**Open submission on GitHub →**. The model, combination, proposed cell
snippet, and existing cell are filled automatically — please double-check
the snippet matches what you ran.
Once a maintainer with access to the listed hardware reproduces the
recipe, they'll convert this issue into a PR against the cookbook cell
catalog and close this issue.
- type: dropdown
id: model
attributes:
label: Cookbook model
description: Which model's cookbook does this cell belong to?
options:
- deepseek-ai/deepseek-v4
validations:
required: true
- type: input
id: combination
attributes:
label: Combination
description: "Format: hw / variant / quant / strategy / nodes (auto-filled by the playground)."
placeholder: "b200 / flash / fp4 / low-latency / single"
validations:
required: true
- type: textarea
id: cell-snippet
attributes:
label: Proposed cell snippet
description: |
The cell object exactly as it should land in the `cells: [...]` array
of the cookbook config. Auto-generated by the playground — please do not
hand-edit unless you're sure.
render: javascript
validations:
required: true
- type: textarea
id: existing-cell
attributes:
label: Existing cell at this match (for diff)
description: |
The current verified cell at the same `match` tuple, if any. The
playground fills this so the maintainer can see exactly what changed.
Leave empty if no cell yet exists at this match.
render: javascript
validations:
required: false
- type: input
id: sglang-version
attributes:
label: SGLang version
description: Version, tag, or git SHA you tested against.
placeholder: "sglang==0.5.4 (or git SHA abc1234)"
validations:
required: true
- type: textarea
id: bench-result
attributes:
label: Benchmark result (optional but encouraged)
description: |
One-line perf numbers (TTFT, TPOT, tokens/sec, accepted-rate, etc.).
Helps maintainers decide whether this recipe should replace the
existing one or be added as an alternative.
placeholder: "TTFT 95 ms / TPOT 18 ms / 1820 tok/s @ bs=64"
validations:
required: false
- type: textarea
id: notes
attributes:
label: Notes / caveats
description: |
Anything unusual: cluster config, env-var quirks, NIC mappings,
multi-node bootstrap details, etc.
validations:
required: false
- type: checkboxes
id: attestation
attributes:
label: Attestation
description: All three must be ticked. We trust contributors but maintainers will still re-verify before merging.
options:
- label: I ran this exact command on the listed hardware.
required: true
- label: The server reached READY and answered a cURL request successfully.
required: true
- label: Output looked correct on at least one prompt.
required: true
@@ -1,10 +1,104 @@
---
title: DeepSeek-V4
metatags:
description: "Deploy DeepSeek-V4 with SGLang — a next-generation MoE model from DeepSeek."
description: "Deploy DeepSeek-V4 with SGLang — verified launch commands, benchmarks, and tuning for the Flash (284B) and Pro (1.6T) Mixture-of-Experts models."
tag: NEW
mode: wide
---
## Deployment
<a id="install" />
<Accordion title="Install SGLang">
For all methods and hardware platforms, see the [official SGLang installation guide](../../../docs/get-started/install). The two paths below match the **Python / Docker** toggle in the command panel.
<Tabs>
<Tab title="Python (pip / uv)">
```bash Command
pip install --upgrade pip
pip install uv
uv pip install sglang
```
Then run the **Python** output of the command panel below in that environment.
</Tab>
<Tab title="Docker">
A single image — `lmsysorg/sglang:latest` — covers the **datacenter GPUs** in this cookbook (B200 / B300 / GB200 / GB300 / H100 / H200). For **RTX PRO 6000 (SM120)**, use the nightly `lmsysorg/sglang:dev` instead — SM120 support isn't in `:latest` yet (see the RTX PRO 6000 note below).
```bash Command
docker pull lmsysorg/sglang:latest
```
For how to launch the image, see [Install → Method 3: Using Docker](../../../docs/get-started/install#method-3-using-docker). A minimal example (substitute the inner `sglang serve ...` with whatever the command generator below produces):
```bash Command
docker run --gpus all \
--shm-size 32g \
-p 30000:30000 \
-v ~/.cache/huggingface:/root/.cache/huggingface \
--env "HF_TOKEN=<your-hf-token>" \
--ipc=host \
lmsysorg/sglang:latest \
sglang serve <use args below>
```
</Tab>
</Tabs>
</Accordion>
Pick your hardware + recipe to generate the launch command. The three serving strategies cover the common operating points:
- **Low-Latency** — fastest reply for a single user. Pick for chat.
- **Balanced** — good speed with several users at once. Use for typical multi-user serving.
- **High-Throughput** — most tokens per second across many users. Best for batch jobs.
import { Deployment } from "/src/snippets/_deployment.jsx";
import { config } from "/src/snippets/configs/deepseek-ai/deepseek-v4.jsx";
import { benchmarks } from "/src/snippets/configs/deepseek-ai/deepseek-v4-benchmarks.jsx";
<Deployment config={config} benchmarks={benchmarks} />
<div style={{fontSize: "0.85em", lineHeight: "1.55", color: "#6b7280", margin: "0.5rem 0 1rem 0"}}>
<p style={{margin: "0 0 0.3rem 0"}}><strong>Panel controls</strong> (top of the command box):</p>
<ul style={{margin: 0, paddingLeft: "1.25rem"}}>
<li style={{marginBottom: "0.2rem"}}><strong>Python / Docker</strong> — bare <code>sglang serve …</code> for an existing SGLang env, or a <code>docker run … sglang serve …</code> wrap against the per-hardware image from the <a href="#install">Install SGLang</a> panel above.</li>
<li style={{marginBottom: "0.2rem"}}><strong>⧉ Copy</strong> — copies the current command (with whichever framing is active) to your clipboard.</li>
<li style={{marginBottom: "0.2rem"}}><strong>$ cURL</strong> — a sample request against <code>localhost:30000</code> to confirm the server is up.</li>
<li style={{marginBottom: "0.2rem"}}><strong>⚙ Env</strong> — edits the placeholders (<code>HOST_IP</code>, <code>PORT</code>, <code>HF_TOKEN</code>, <code>NODE_RANK</code>, <code>NODE0_IP</code>) the command and cURL share. Persists in localStorage across cookbooks.</li>
<li><strong>Verified / Not Verified</strong> badge — green when the <code>(hw, variant, quant, strategy, nodes)</code> combo has been run end-to-end on real hardware; yellow when auto-derived from a neighbor and not yet re-checked.</li>
</ul>
</div>
## Playground
The Playground is where you experiment with **SGLang features beyond the verified matrix**. The Deploy panel above only emits combinations the SGLang team has signed off on; the Playground lets you turn on additional knobs on top of whichever cell the Deploy panel is currently showing. The base is read live from your Deploy selection — only your overrides change.
The knobs come in two flavors:
- **Built-in SGLang features** — parallelism overrides (TP / CP / DP-Attention — DP-Attention's value is the DP degree, with `off` to disable), MoE backend + EP, reasoning / tool-call parsers, speculative-decoding presets, prefill/decode disaggregation, HiCache tiers, and HiSparse hierarchical sparse attention (decode-role only — the card appears once PD-Disagg mode is set to decode).
- **DeepSeek-V4 specific features** — MegaMoE W4A8 / W4A4 fused kernel (Blackwell only).
Lines highlighted **green** are added by your overrides; lines with **red strikethrough** were in the verified base but stripped by an override. When no override differs from the base cell, the playground inherits the base's **Verified** badge; any actual change flips it to **Not Verified** until the new configuration is run end-to-end and submitted back.
import { Playground } from "/src/snippets/_playground.jsx";
<Playground config={config} />
<div style={{fontSize: "0.85em", lineHeight: "1.55", color: "#6b7280", margin: "0.5rem 0 1rem 0"}}>
<p style={{margin: "0 0 0.3rem 0"}}><strong>Panel controls</strong> reuse <strong>Python / Docker</strong> · <strong>⧉ Copy</strong> · <strong>$ cURL</strong> · <strong>⚙ Env</strong> from the Deploy panel, plus one extra:</p>
<ul style={{margin: 0, paddingLeft: "1.25rem"}}>
<li><strong>Submit ↗</strong> — opens a pre-filled GitHub issue so you can land your override combo as a new verified cookbook cell. Shown only while the badge says <strong>Not Verified</strong>; click it once you've actually run the command on your hardware and confirmed it works.</li>
</ul>
</div>
## 1. Model Introduction
**DeepSeek-V4** is the next-generation Mixture-of-Experts model from DeepSeek, released 2026-04-24 under an **MIT License**. It ships as two Instruct repos (one per variant) plus matching Base repos:
@@ -29,76 +123,26 @@ tag: NEW
<td style={{padding: "9px 12px", fontWeight: 500, backgroundColor: "rgba(255,255,255,0.02)"}}><strong><a href="https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash">DeepSeek-V4-Flash</a></strong></td>
<td style={{padding: "9px 12px", textAlign: "right", backgroundColor: "rgba(255,255,255,0.05)"}}><strong>284B</strong></td>
<td style={{padding: "9px 12px", textAlign: "right", backgroundColor: "rgba(255,255,255,0.02)"}}>13B</td>
<td style={{padding: "9px 12px", backgroundColor: "rgba(255,255,255,0.05)"}}>single-node serving: B200 / GB200 / GB300 / H200 on 4 GPUs</td>
<td style={{padding: "9px 12px", backgroundColor: "rgba(255,255,255,0.05)"}}>single-node serving on B200 / B300 / GB200 / GB300 / H200 (TP=4); H100 (TP=8)</td>
</tr>
<tr>
<td style={{padding: "9px 12px", fontWeight: 500, backgroundColor: "rgba(255,255,255,0.02)"}}><strong><a href="https://huggingface.co/deepseek-ai/DeepSeek-V4-Pro">DeepSeek-V4-Pro</a></strong></td>
<td style={{padding: "9px 12px", textAlign: "right", backgroundColor: "rgba(255,255,255,0.05)"}}><strong>1.6T</strong></td>
<td style={{padding: "9px 12px", textAlign: "right", backgroundColor: "rgba(255,255,255,0.02)"}}>49B</td>
<td style={{padding: "9px 12px", backgroundColor: "rgba(255,255,255,0.05)"}}>high-capacity: B200 8 GPU / GB200 8 GPU (2 nodes) / GB300 4 GPU / H200 8 GPU (FP4) or 16 GPU (SGLang FP8)</td>
<td style={{padding: "9px 12px", backgroundColor: "rgba(255,255,255,0.05)"}}>high-capacity: B200 / B300 (TP=8) · GB300 (TP=4) · H200 FP4 (TP=8) · GB200 (2-node, TP=8) · H200 FP8 (2-node, TP=16) · H100 (2-node, TP=16)</td>
</tr>
</tbody>
</table>
The Instruct repos ship **FP4 MoE experts + FP8 attention / dense** (one mixed-precision checkpoint covers all GPUs that support FP4). The Base (pre-trained only) variants — `DeepSeek-V4-Flash-Base`, `DeepSeek-V4-Pro-Base` — ship pure FP8 mixed and are **not** for chat / tool calling.
Both Instruct repos ship as **FP4 MoE experts + FP8 attention / dense** (one mixed-precision checkpoint covers every FP4-capable GPU). Matching `*-Base` repos ship pure FP8 mixed and are for further pre-training only — not for chat or tool calling.
**Key Features** (per the official model card):
**Highlights:** hybrid CSA + HCA attention (~27% inference FLOPs / ~10% KV cache vs DSv3.2 at 1M context), manifold-constrained hyper-connections (mHC), Muon optimizer, **1M-token context** (32T+ pre-training tokens), three reasoning modes (*Non-think* / *Think High* / *Think Max* — use ≥ 384K context for Think Max), and a dedicated `encoding_dsv4.encode_messages` Python encoder + DSML tool-call grammar.
- **Hybrid Attention Architecture** — combines Compressed Sparse Attention (CSA) and Heavily Compressed Attention (HCA) for long-context efficiency. At 1M-token context, DeepSeek-V4-Pro uses only ~27% of per-token inference FLOPs and ~10% of KV cache compared with DeepSeek-V3.2.
- **Manifold-Constrained Hyper-Connections (mHC)** — strengthens residual connections, improving signal-propagation stability across layers while preserving expressivity.
- **Muon optimizer** — faster convergence and greater training stability.
- **Context length: 1M tokens**; pre-trained on 32T+ diverse, high-quality tokens.
- **Three reasoning modes**: *Non-think* (fast, intuitive responses), *Think High* (conscious logical analysis, slower but more accurate), *Think Max* (push reasoning to its fullest extent). Recommend a ≥ 384K context window when running Think Max.
- Ships with a dedicated `encoding_dsv4.encode_messages` Python encoder + DSML tool-call grammar (`<DSMLtool_calls>` / `<DSMLinvoke>` / `<DSMLparameter>`).
**Recommended generation:** `temperature=1.0`, `top_p=1.0`.
**Recommended Generation Parameters:** `temperature=1.0`, `top_p=1.0` (per the official model card).
**Resources:** HuggingFace · [Flash](https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash) · [Pro](https://huggingface.co/deepseek-ai/DeepSeek-V4-Pro) · ModelScope · [Flash](https://modelscope.cn/models/deepseek-ai/DeepSeek-V4-Flash) · [Pro](https://modelscope.cn/models/deepseek-ai/DeepSeek-V4-Pro).
**License:** MIT.
**Resources:**
- HuggingFace: [DeepSeek-V4-Flash](https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash), [DeepSeek-V4-Pro](https://huggingface.co/deepseek-ai/DeepSeek-V4-Pro)
- ModelScope: [DeepSeek-V4-Flash](https://modelscope.cn/models/deepseek-ai/DeepSeek-V4-Flash), [DeepSeek-V4-Pro](https://modelscope.cn/models/deepseek-ai/DeepSeek-V4-Pro)
## 2. SGLang Installation
SGLang offers multiple installation methods. Choose based on your hardware platform.
Please refer to the [official SGLang installation guide](../../../docs/get-started/install) for installation instructions.
**Docker Image:** Use `lmsysorg/sglang:latest` for all supported hardware platforms (B300 / B200 / GB200 / GB300 / H200 / H100).
```bash Command
docker pull lmsysorg/sglang:latest
```
For how to actually launch the image, see [Install → Method 3: Using Docker](../../../docs/get-started/install#method-3-using-docker). A minimal example (substitute the inner `sglang serve ...` with whatever the [command generator](#3-model-deployment) below produces):
```bash Command
docker run --gpus all \
--shm-size 32g \
-p 30000:30000 \
-v ~/.cache/huggingface:/root/.cache/huggingface \
--env "HF_TOKEN=<your-hf-token>" \
--ipc=host \
lmsysorg/sglang:latest \
sglang serve <use args below>
```
## 3. Model Deployment
SGLang supports three main serving recipes for DeepSeek-V4 with different latency/throughput trade-offs (`low-latency`, `balanced`, `max-throughput`), plus specialized recipes for long-context (`cp`, prefill context-parallel) and prefill/decode disaggregation (`pd-disagg`). The interactive generator below emits the exact launch command for any `(hardware, variant, recipe)` combination.
### 3.1 Basic Configuration
**Interactive Command Generator**: Use the selector below to generate the deployment command for your hardware + recipe combination.
import { DeepSeekV4Deployment } from "/src/snippets/autoregressive/deepseek-v4-deployment.jsx";
<DeepSeekV4Deployment />
### 3.2 Configuration Tips
## 2. Configuration Tips
{/* TODO: expand this section as more recipes are validated end-to-end. */}
@@ -112,8 +156,8 @@ The generator currently picks values on the **conservative** side (mirroring an
- `low-latency`: steps=3, draft-tokens=4 → largest win at bs=1.
- `balanced`: steps=1, draft-tokens=2 → gentler MTP, reduces throughput hit at higher batch.
- `max-throughput`: MTP disabled — at saturation the verify step costs more than it saves.
- MTP currently requires `SGLANG_ENABLE_SPEC_V2=1`.
- `high-throughput`: MTP disabled — at saturation the verify step costs more than it saves.
- MTP runs on the v2 speculative path (`SGLANG_ENABLE_SPEC_V2`, enabled by default).
**EPLB + DeepEP Waterfill (Experimental)**
@@ -161,8 +205,9 @@ requires `--moe-a2a-backend deepep`.
DeepSeek-V4 uses the default indexer path unless `--enable-deepseek-v4-fp4-indexer` is set. Enable this flag to use the experimental FP4 C4 indexer on SM100 GPUs with DeepGEMM FP4 indexer support. This path is intended for decode-heavy long-context workloads where reducing indexer cache bandwidth is beneficial.
```bash Command
# Please use latest main branch for this feature
sglang serve deepseek-ai/DeepSeek-V4-Flash \
# Please use the latest main branch for this feature.
sglang serve \
--model-path deepseek-ai/DeepSeek-V4-Flash \
--tp 4 \
--moe-runner-backend flashinfer_mxfp4 \
--enable-deepseek-v4-fp4-indexer
@@ -170,25 +215,31 @@ sglang serve deepseek-ai/DeepSeek-V4-Flash \
<a id="hopper-note" />
**Hopper (H200) note**
**Hopper (H100 / H200) note**
We provide two different options for running DeepSeek-V4 models on Hopper devices (H200)
- Original FP4 checkpoints: To run original FP4 checkpoints, we provide two different options for w4a16 MoE kernels: Marlin (`--moe-runner-backend marlin`) and Flashinfer (`--moe-runner-backend flashinfer_mxfp4`). For this variant we only support Tensor Parallelism. Complete Pro model can be run on a single H200 node with this option.
- Converted FP8 checkpoints: We also provide pre-converted FP8 checkpoints (`sgl-project/DeepSeek-V4-Flash-FP8`, `sgl-project/DeepSeek-V4-Pro-FP8`), which support more parallelism and features.
Two options are available for running DeepSeek-V4 on Hopper:
- **Original FP4 checkpoints** — apply the W4A16 MoE kernels (Marlin) as the command generator picks for Hopper cells. This path works on both H100 and H200 and is the only option for H100 (no FP8 path). It is TP-only; on H200 the Pro variant fits on a single 8-GPU node, while H100 Pro needs 2 nodes (TP=16).
- **Converted FP8 checkpoints** (H100 and H200 only) — pre-repackaged FP8 weights at [`sgl-project/DeepSeek-V4-Flash-FP8`](https://huggingface.co/sgl-project/DeepSeek-V4-Flash-FP8) and [`sgl-project/DeepSeek-V4-Pro-FP8`](https://huggingface.co/sgl-project/DeepSeek-V4-Pro-FP8) unlock DP-attention + DeepEP and richer parallelism (e.g. Pro TP=16 across 2 nodes).
PD-Disagg recipes on H200 may require `docker run --privileged --ulimit memlock=-1`
(or `--device /dev/infiniband:/dev/infiniband --cap-add IPC_LOCK`) so mooncake
can discover the IB HCAs; without IB exposure mooncake silently falls back to
TCP, which can lead to garbled KV transfer on large checkpoints.
**RTX PRO 6000 (SM120 / Blackwell Desktop) note**
RTX PRO 6000 (96 GB) runs **Flash only** — V4-Pro doesn't fit on 8× 96 GB. It uses the
**low-latency / TP-only** recipe (TP=4, single node) with the **Marlin** W4A16 MoE runner and
`--mem-fraction-static 0.70`; the Deploy panel greys out the other recipes for this card.
HiCache and MegaMoE are **not** supported on RTX PRO 6000. For Docker, use the nightly `lmsysorg/sglang:dev` image — SM120 support isn't in `lmsysorg/sglang:latest` yet (the Deploy panel's Docker mode already points this card at `:dev`).
**MegaMoE**
MegaMoE fuses expert dispatch + GEMM into a single kernel for higher throughput
on MoE layers. To enable it, use the **MegaMoE** toggle in the
[command generator above](#3-model-deployment) — the generator will swap
`--moe-a2a-backend deepep` for `--moe-a2a-backend megamoe` and add the
relevant env vars automatically.
on MoE layers. To enable it, use the **MegaMoE** chip in the Playground
below — the playground will swap `--moe-a2a-backend deepep` for
`--moe-a2a-backend megamoe` and add the relevant env vars automatically.
Two variants are exposed:
- **W4A8** — default MegaMoE kernel (FP4 weights, FP8 activations).
@@ -198,8 +249,10 @@ Two variants are exposed:
(~89.5 GPQA on Pro).
Notes:
- MegaMoE is **not** supported on Hopper (H100 / H200) nor on the `low-latency` / `balanced` / `cp` settings — it is only wired into the `max-throughput` recipe on Blackwell. When running MegaMoE, don't set `--moe-runner-backend` manually.
- Adjust `SGLANG_OPT_DEEPGEMM_MEGA_MOE_NUM_MAX_TOKENS_PER_RANK` based on your workload and memory usage. Setting higher number of tokens for MegaMoE requires more HBM space. (recommended: 8320 for max-throughput).
- MegaMoE is **only supported on Blackwell GPUs** (B200 / B300 / GB200 / GB300). The chip is hidden when the Deploy panel's base cell sits on Hopper (H100 / H200).
- MegaMoE is **only wired into the `high-throughput` recipe** on Blackwell (per [sgl-project/sglang#26451](https://github.com/sgl-project/sglang/pull/26451)). The chip is hidden on `low-latency` and `balanced` — switch to `high-throughput` to expose it.
- When running MegaMoE, don't set `--moe-runner-backend` manually.
- Adjust `SGLANG_OPT_DEEPGEMM_MEGA_MOE_NUM_MAX_TOKENS_PER_RANK` based on your workload and memory usage. Setting higher number of tokens for MegaMoE requires more HBM space (recommended: 8320 for high-throughput).
**GB300 PD-Disagg cross-pod MNNVL**
@@ -208,32 +261,11 @@ fail with `nvlink_transport.cpp:497 Requested address ... not found!`. If
this happens, prepend `MC_FORCE_MNNVL=1 NCCL_MNNVL_ENABLE=1 NCCL_CUMEM_ENABLE=1`
to both prefill and decode `sglang serve` commands.
## 4. Model Invocation
## 3. Advanced Usage
### 4.1 Basic Usage
### 3.1 Reasoning
For basic API usage and request examples, see:
- [Basic API Usage](../../../docs/basic_usage/send_request)
Once the server is running (for example via the command generator above), send a request:
```shell Command
curl http://localhost:30000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-ai/DeepSeek-V4-Flash",
"messages": [{"role": "user", "content": "What is 15% of 240?"}]
}'
```
> **PD-Disagg note**: if you deployed with the `pd-disagg` recipe from the generator above, the prefill server is on port `30000`, the decode server on `30001`, and the **router** on port `8000` — client traffic should target `http://localhost:8000`, not `:30000`.
### 4.2 Advanced Usage
#### 4.2.1 Reasoning Parser
Enable the `deepseek-v4` reasoning parser (check the box in the [command panel above](#3-model-deployment)) to separate thinking from the final answer into `reasoning_content` vs `content`.
Enable the `deepseek-v4` reasoning parser (toggle **Reasoning Parser** in the **Parsers** card of the [Playground above](#playground)) to separate thinking from the final answer into `reasoning_content` vs `content`.
<Accordion title="Streaming with Thinking Process (Python)">
@@ -305,9 +337,9 @@ Multiply the decimal form by 240:
</Accordion>
#### 4.2.2 Tool Calling
### 3.2 Tool Calling
Enable the `deepseekv4` tool-call parser (check the box in the [command panel above](#3-model-deployment)) to surface structured tool calls via `message.tool_calls`.
Enable the `deepseekv4` tool-call parser (toggle **Tool Call Parser** in the **Parsers** card of the [Playground above](#playground)) to surface structured tool calls via `message.tool_calls`.
<Accordion title="Python Example with Thinking Process">
@@ -401,339 +433,15 @@ The user wants to know the weather in Beijing. I'll use the get_weather function
</Accordion>
#### 4.2.3 HiCache (Hierarchical KV Caching)
### 3.3 HiCache (Hierarchical KV Caching)
HiCache enables multi-tier KV cache offloading (GPU → CPU → Storage), significantly expanding effective context capacity for long-context and multi-turn scenarios. Combined with UnifiedRadixTree, it provides intelligent prefix caching across all tiers.
To enable HiCache, use the **HiCache** toggle in the [command generator above](#3-model-deployment):
To enable HiCache, open the **HiCache** card in the [Playground above](#playground) and flip **Enable**:
- **L2 (GPU + CPU):** Offloads cold KV pages to CPU memory. Enables `SGLANG_ENABLE_UNIFIED_RADIX_TREE=1` for intelligent hierarchical prefix caching.
- **L3 (GPU + CPU + Storage):** Coming soon.
- **L2 (GPU + CPU)** — leave Storage on `auto` (default). Cold KV pages spill to CPU pinned memory only.
- **L3 (GPU + CPU + Storage)** — pick a Storage backend (`file` / `mooncake` / `hf3fs` / `nixl`); the Playground emits the canonical `page_first_direct` mem-layout + `direct` IO backend + `wait_complete` prefetch policy, matching the [HiCache best-practices recipe](../../../docs/advanced_features/hicache_best_practices).
The Write policy knob defaults to `write_through` (the upstream default); switch to `write_back` / `write_through_selective` to trade durability for write speed when the storage tier is slow.
For more details, see the [HiCache documentation](../../../docs/advanced_features/hicache).
## 5. Benchmark
### 5.1 Accuracy Benchmark
For accuracy benchmarking on DeepSeek-V4 models, please make sure that:
- `SGLANG_DEFAULT_THINKING=1 SGLANG_REASONING_EFFORT=max` are set when launching model.
- For GPQA and AIME25 benchmarks, run at least 16 turns to reduce randomness.
#### 5.1.1 GSM8K Benchmark
- **Benchmark Command:**
```shell Command
python3 -m sglang.test.few_shot_gsm8k --num-questions 200 --port 30000
```
- **Test Results:**
- DeepSeek-V4-Pro (FP4, B300, low-latency)
```
Accuracy: 0.965
Invalid: 0.000
```
- DeepSeek-V4-Pro (FP4, H200, low-latency)
```
Accuracy: 0.975
Invalid: 0.000
```
#### 5.1.2 GPQA Diamond Benchmark
For GPQA Diamond benchmark, we recommend applying [sgl-eval](https://github.com/sgl-project/sgl-eval) as the benchmark tool.
```shell Command
# Install
pip install git+https://github.com/sgl-project/sgl-eval
# For Flash model, reference accuracy: 88.1%
sgl-eval run gpqa --model deepseek-ai/DeepSeek-V4-Flash --api-key <api-key> --n-repeats 16 --max-tokens 200000 --temperature 1.0 --top-p 1.0 --thinking --out-dir /sgl-workspace/logs --base-url http://localhost:30000/v1
# For Pro model, reference accuracy: 90.1%
sgl-eval run gpqa --model deepseek-ai/DeepSeek-V4-Pro --api-key <api-key> --n-repeats 16 --max-tokens 400000 --temperature 1.0 --top-p 1.0 --thinking --out-dir /sgl-workspace/logs --base-url http://localhost:30000/v1
```
#### 5.1.3 AIME25 Benchmark
For AIME25 benchmark, we recommend applying [sgl-eval](https://github.com/sgl-project/sgl-eval) as the benchmark tool.
```shell Command
# Install
pip install git+https://github.com/sgl-project/sgl-eval
# For Flash model, reference accuracy: ~95%
sgl-eval run aime25 --model deepseek-ai/DeepSeek-V4-Flash --api-key <api-key> --n-repeats 16 --max-tokens 200000 --temperature 1.0 --top-p 1.0 --thinking --out-dir /sgl-workspace/logs --base-url http://localhost:30000/v1
# For Pro model, reference accuracy: ~97.5%
sgl-eval run aime25 --model deepseek-ai/DeepSeek-V4-Pro --api-key <api-key> --n-repeats 16 --max-tokens 400000 --temperature 1.0 --top-p 1.0 --thinking --out-dir /sgl-workspace/logs --base-url http://localhost:30000/v1
```
### 5.2 Speed Benchmark
We use SGLang's built-in benchmarking tool with its `random` dataset — real prompts sampled from [ShareGPT_Vicuna_unfiltered](https://huggingface.co/datasets/anon8231489123/ShareGPT_Vicuna_unfiltered) and then truncated/padded to a controlled length. This dataset contains real conversation data and can better reflect performance in actual use scenarios. To simulate real-world usage patterns, we configure each request with 1024 input tokens and 1024 output tokens, representing typical medium-length conversations with detailed responses.
#### 5.2.1 Hopper
**Test Environment:**
- Hardware: NVIDIA H200 GPU (4x)
- Model: DeepSeek-V4-Flash (FP4)
- Tensor Parallelism: 4
- sglang version: 0.5.12
##### Latency-Sensitive Benchmark
- **Model Deployment Command:** H200 · DeepSeek-V4-Flash · FP4 · Low-Latency. See the [command panel above](#3-model-deployment).
- Benchmark Command:
```shell Command
python3 -m sglang.bench_serving \
--backend sglang \
--host 127.0.0.1 \
--port 30000 \
--model deepseek-ai/DeepSeek-V4-Flash \
--dataset-name random \
--random-input-len 1024 \
--random-output-len 1024 \
--num-prompts 10 \
--max-concurrency 1
```
- **Test Results:**
```text Output
============ Serving Benchmark Result ============
Backend: sglang
Traffic request rate: inf
Max request concurrency: 1
Successful requests: 10
Benchmark duration (s): 15.98
Total input tokens: 6101
Total input text tokens: 6101
Total generated tokens: 4220
Total generated tokens (retokenized): 4220
Request throughput (req/s): 0.63
Input token throughput (tok/s): 381.86
Output token throughput (tok/s): 264.13
Peak output token throughput (tok/s): 324.00
Peak concurrent requests: 3
Total token throughput (tok/s): 645.98
Concurrency: 1.00
Accept length: 2.96
----------------End-to-End Latency----------------
Mean E2E Latency (ms): 1596.65
Median E2E Latency (ms): 1274.48
P90 E2E Latency (ms): 2950.70
P99 E2E Latency (ms): 3333.18
---------------Time to First Token----------------
Mean TTFT (ms): 147.26
Median TTFT (ms): 132.22
P99 TTFT (ms): 181.37
-----Time per Output Token (excl. 1st token)------
Mean TPOT (ms): 3.50
Median TPOT (ms): 3.48
P99 TPOT (ms): 4.18
---------------Inter-Token Latency----------------
Mean ITL (ms): 3.44
Median ITL (ms): 3.36
P95 ITL (ms): 5.06
P99 ITL (ms): 5.15
Max ITL (ms): 35.31
==================================================
```
##### Throughput-Sensitive Benchmark
- **Model Deployment Command:** H200 · DeepSeek-V4-Flash · FP4 · Max-Throughput. See the [command panel above](#3-model-deployment).
- Benchmark Command:
```shell Command
python3 -m sglang.bench_serving \
--backend sglang \
--host 127.0.0.1 \
--port 30000 \
--model deepseek-ai/DeepSeek-V4-Flash \
--dataset-name random \
--random-input-len 1024 \
--random-output-len 1024 \
--num-prompts 1000 \
--max-concurrency 100
```
- **Test Results:**
```text Output
============ Serving Benchmark Result ============
Backend: sglang
Traffic request rate: inf
Max request concurrency: 100
Successful requests: 1000
Benchmark duration (s): 198.42
Total input tokens: 512842
Total input text tokens: 512842
Total generated tokens: 510855
Total generated tokens (retokenized): 510765
Request throughput (req/s): 5.04
Input token throughput (tok/s): 2584.65
Output token throughput (tok/s): 2574.64
Peak output token throughput (tok/s): 4400.00
Peak concurrent requests: 110
Total token throughput (tok/s): 5159.28
Concurrency: 96.21
----------------End-to-End Latency----------------
Mean E2E Latency (ms): 19090.29
Median E2E Latency (ms): 18328.71
P90 E2E Latency (ms): 35698.68
P99 E2E Latency (ms): 39161.43
---------------Time to First Token----------------
Mean TTFT (ms): 302.41
Median TTFT (ms): 131.35
P99 TTFT (ms): 2172.03
-----Time per Output Token (excl. 1st token)------
Mean TPOT (ms): 37.46
Median TPOT (ms): 37.72
P99 TPOT (ms): 55.72
---------------Inter-Token Latency----------------
Mean ITL (ms): 36.85
Median ITL (ms): 21.75
P95 ITL (ms): 107.64
P99 ITL (ms): 134.58
Max ITL (ms): 1930.74
==================================================
```
#### 5.2.2 Blackwell
**Test Environment:**
- Hardware: NVIDIA B200 GPU (4x)
- Model: DeepSeek-V4-Flash (FP4)
- Tensor Parallelism: 4
- sglang version: 0.5.12
##### Latency-Sensitive Benchmark
- **Model Deployment Command:** B200 · DeepSeek-V4-Flash · FP4 · Low-Latency. See the [command panel above](#3-model-deployment).
- Benchmark Command:
```shell Command
python3 -m sglang.bench_serving \
--backend sglang \
--host 127.0.0.1 \
--port 30000 \
--model deepseek-ai/DeepSeek-V4-Flash \
--dataset-name random \
--random-input-len 1024 \
--random-output-len 1024 \
--num-prompts 10 \
--max-concurrency 1
```
- **Test Results:**
```text Output
============ Serving Benchmark Result ============
Backend: sglang
Traffic request rate: inf
Max request concurrency: 1
Successful requests: 10
Benchmark duration (s): 15.25
Total input tokens: 6101
Total input text tokens: 6101
Total generated tokens: 4220
Total generated tokens (retokenized): 4220
Request throughput (req/s): 0.66
Input token throughput (tok/s): 400.06
Output token throughput (tok/s): 276.72
Peak output token throughput (tok/s): 308.00
Peak concurrent requests: 2
Total token throughput (tok/s): 676.78
Concurrency: 1.00
Accept length: 2.73
----------------End-to-End Latency----------------
Mean E2E Latency (ms): 1523.83
Median E2E Latency (ms): 1173.50
P90 E2E Latency (ms): 2770.33
P99 E2E Latency (ms): 3233.82
---------------Time to First Token----------------
Mean TTFT (ms): 102.72
Median TTFT (ms): 85.94
P99 TTFT (ms): 134.79
-----Time per Output Token (excl. 1st token)------
Mean TPOT (ms): 3.40
Median TPOT (ms): 3.42
P99 TPOT (ms): 4.00
---------------Inter-Token Latency----------------
Mean ITL (ms): 3.38
Median ITL (ms): 3.06
P95 ITL (ms): 4.60
P99 ITL (ms): 4.95
Max ITL (ms): 34.64
==================================================
```
##### Throughput-Sensitive Benchmark
- **Model Deployment Command:** B200 · DeepSeek-V4-Flash · FP4 · Max-Throughput (MegaMoE W4A4). See the [command panel above](#3-model-deployment) — flip the **MegaMoE** toggle to **W4A4** to reproduce these numbers; the default Max-Throughput recipe uses `--moe-a2a-backend deepep` and runs slower.
- Benchmark Command:
```shell Command
python3 -m sglang.bench_serving \
--backend sglang \
--host 127.0.0.1 \
--port 30000 \
--model deepseek-ai/DeepSeek-V4-Flash \
--dataset-name random \
--random-input-len 1024 \
--random-output-len 1024 \
--num-prompts 1000 \
--max-concurrency 100
```
- **Test Results:**
```text Output
============ Serving Benchmark Result ============
Backend: sglang
Traffic request rate: inf
Max request concurrency: 100
Successful requests: 1000
Benchmark duration (s): 105.10
Total input tokens: 512842
Total input text tokens: 512842
Total generated tokens: 510855
Total generated tokens (retokenized): 510682
Request throughput (req/s): 9.51
Input token throughput (tok/s): 4879.44
Output token throughput (tok/s): 4860.54
Peak output token throughput (tok/s): 6600.00
Peak concurrent requests: 117
Total token throughput (tok/s): 9739.98
Concurrency: 94.34
----------------End-to-End Latency----------------
Mean E2E Latency (ms): 9915.50
Median E2E Latency (ms): 9521.19
P90 E2E Latency (ms): 17726.66
P99 E2E Latency (ms): 24910.72
---------------Time to First Token----------------
Mean TTFT (ms): 349.95
Median TTFT (ms): 68.23
P99 TTFT (ms): 4581.26
-----Time per Output Token (excl. 1st token)------
Mean TPOT (ms): 19.86
Median TPOT (ms): 17.96
P99 TPOT (ms): 61.58
---------------Inter-Token Latency----------------
Mean ITL (ms): 18.76
Median ITL (ms): 13.23
P95 ITL (ms): 44.79
P99 ITL (ms): 88.25
Max ITL (ms): 2499.49
==================================================
```
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,306 @@
// DeepSeek-V4 per-cell benchmark numbers, keyed by the same `match` tuple as
// deepseek-v4.jsx cells. See _deployment.jsx for the speed/accuracy schema.
// Measured on sglang v0.5.12.post1.
export const benchmarks = [
// ====================================================================
// B200 + FP4
// ====================================================================
{
match: { hw: "b200", variant: "flash", quant: "fp4", strategy: "low-latency", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 1 },
ttft_ms: 428, tpot_ms: 3.53, tokens_per_sec_per_gpu: 44 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 16 },
ttft_ms: 3111, tpot_ms: 23.82, tokens_per_sec_per_gpu: 121 },
],
},
{
match: { hw: "b200", variant: "flash", quant: "fp4", strategy: "balanced", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 64 },
ttft_ms: 4228, tpot_ms: 60.98, tokens_per_sec_per_gpu: 225 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 256 },
ttft_ms: 4628, tpot_ms: 88.25, tokens_per_sec_per_gpu: 643 },
],
},
{
match: { hw: "b200", variant: "flash", quant: "fp4", strategy: "high-throughput", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 1024 },
ttft_ms: 105918, tpot_ms: 70.73, tokens_per_sec_per_gpu: 881 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 4096 },
ttft_ms: 273356, tpot_ms: 71.61, tokens_per_sec_per_gpu: 889 },
],
},
{
match: { hw: "b200", variant: "pro", quant: "fp4", strategy: "low-latency", nodes: "single" },
},
{
match: { hw: "b200", variant: "pro", quant: "fp4", strategy: "balanced", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 64 },
ttft_ms: 2326, tpot_ms: 69.9, tokens_per_sec_per_gpu: 99 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 256 },
ttft_ms: 7242, tpot_ms: 152.09, tokens_per_sec_per_gpu: 192 },
],
},
{
match: { hw: "b200", variant: "pro", quant: "fp4", strategy: "high-throughput", nodes: "single" },
},
// ====================================================================
// B300 + FP4
// ====================================================================
{
match: { hw: "b300", variant: "flash", quant: "fp4", strategy: "low-latency", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 1 },
ttft_ms: 205, tpot_ms: 3.43, tokens_per_sec_per_gpu: 54 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 16 },
ttft_ms: 1856, tpot_ms: 14.82, tokens_per_sec_per_gpu: 205 },
],
},
{
match: { hw: "b300", variant: "flash", quant: "fp4", strategy: "balanced", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 64 },
ttft_ms: 2363, tpot_ms: 34.4, tokens_per_sec_per_gpu: 402 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 256 },
ttft_ms: 2812, tpot_ms: 51.65, tokens_per_sec_per_gpu: 1092 },
],
},
{
match: { hw: "b300", variant: "flash", quant: "fp4", strategy: "high-throughput", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 1024 },
ttft_ms: 82556, tpot_ms: 55.37, tokens_per_sec_per_gpu: 1130 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 4096 },
ttft_ms: 207987, tpot_ms: 54.05, tokens_per_sec_per_gpu: 1171 },
],
},
{
match: { hw: "b300", variant: "pro", quant: "fp4", strategy: "low-latency", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 1 },
ttft_ms: 239, tpot_ms: 5.04, tokens_per_sec_per_gpu: 24 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 16 },
ttft_ms: 830, tpot_ms: 15.55, tokens_per_sec_per_gpu: 101 },
],
},
{
match: { hw: "b300", variant: "pro", quant: "fp4", strategy: "balanced", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 64 },
ttft_ms: 1866, tpot_ms: 54.48, tokens_per_sec_per_gpu: 139 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 256 },
ttft_ms: 6325, tpot_ms: 123.95, tokens_per_sec_per_gpu: 237 },
],
},
{
match: { hw: "b300", variant: "pro", quant: "fp4", strategy: "high-throughput", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 1024 },
ttft_ms: 99139, tpot_ms: 44.37, tokens_per_sec_per_gpu: 476 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 4096 },
ttft_ms: 241544, tpot_ms: 43.51, tokens_per_sec_per_gpu: 492 },
],
},
// ====================================================================
// GB200 + FP4
// ====================================================================
{
match: { hw: "gb200", variant: "flash", quant: "fp4", strategy: "low-latency", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 1 },
ttft_ms: 335, tpot_ms: 3.67, tokens_per_sec_per_gpu: 47 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 16 },
ttft_ms: 2440, tpot_ms: 15.95, tokens_per_sec_per_gpu: 163 },
],
},
{
match: { hw: "gb200", variant: "flash", quant: "fp4", strategy: "balanced", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 64 },
ttft_ms: 2560, tpot_ms: 39.71, tokens_per_sec_per_gpu: 342 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 256 },
ttft_ms: 3995, tpot_ms: 82.56, tokens_per_sec_per_gpu: 718 },
],
},
{
match: { hw: "gb200", variant: "flash", quant: "fp4", strategy: "high-throughput", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 1024 },
ttft_ms: 128397, tpot_ms: 84.95, tokens_per_sec_per_gpu: 757 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 4096 },
ttft_ms: 330479, tpot_ms: 86.7, tokens_per_sec_per_gpu: 741 },
],
},
{
match: { hw: "gb200", variant: "pro", quant: "fp4", strategy: "low-latency", nodes: "multi-2" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 1 },
ttft_ms: 343, tpot_ms: 6.47, tokens_per_sec_per_gpu: 18 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 16 },
ttft_ms: 1345, tpot_ms: 23.85, tokens_per_sec_per_gpu: 65 },
],
},
{
match: { hw: "gb200", variant: "pro", quant: "fp4", strategy: "balanced", nodes: "multi-2" },
},
{
match: { hw: "gb200", variant: "pro", quant: "fp4", strategy: "high-throughput", nodes: "multi-2" },
},
// ====================================================================
// GB300 + FP4
// ====================================================================
{
match: { hw: "gb300", variant: "flash", quant: "fp4", strategy: "low-latency", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 1 },
ttft_ms: 380, tpot_ms: 4.4, tokens_per_sec_per_gpu: 38 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 16 },
ttft_ms: 2960, tpot_ms: 21.26, tokens_per_sec_per_gpu: 125 },
],
},
{
match: { hw: "gb300", variant: "flash", quant: "fp4", strategy: "balanced", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 64 },
ttft_ms: 2671, tpot_ms: 45.88, tokens_per_sec_per_gpu: 299 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 256 },
ttft_ms: 4823, tpot_ms: 94.04, tokens_per_sec_per_gpu: 637 },
],
},
{
match: { hw: "gb300", variant: "flash", quant: "fp4", strategy: "high-throughput", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 1024 },
ttft_ms: 146954, tpot_ms: 97.24, tokens_per_sec_per_gpu: 662 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 4096 },
ttft_ms: 368557, tpot_ms: 99.33, tokens_per_sec_per_gpu: 651 },
],
},
{
match: { hw: "gb300", variant: "pro", quant: "fp4", strategy: "low-latency", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 1 },
ttft_ms: 363, tpot_ms: 6.53, tokens_per_sec_per_gpu: 36 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 16 },
ttft_ms: 1275, tpot_ms: 20.75, tokens_per_sec_per_gpu: 152 },
],
},
{
match: { hw: "gb300", variant: "pro", quant: "fp4", strategy: "balanced", nodes: "single" },
},
{
match: { hw: "gb300", variant: "pro", quant: "fp4", strategy: "high-throughput", nodes: "single" },
},
// ====================================================================
// H200 + FP8
// ====================================================================
{
match: { hw: "h200", variant: "flash", quant: "fp8", strategy: "low-latency", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 1 },
ttft_ms: 204, tpot_ms: 3.38, tokens_per_sec_per_gpu: 68 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 16 },
ttft_ms: 538, tpot_ms: 11.42, tokens_per_sec_per_gpu: 264 },
],
},
{
match: { hw: "h200", variant: "flash", quant: "fp8", strategy: "balanced", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 64 },
ttft_ms: 738, tpot_ms: 36.27, tokens_per_sec_per_gpu: 385 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 256 },
ttft_ms: 39806, tpot_ms: 80.13, tokens_per_sec_per_gpu: 393 },
],
},
{
match: { hw: "h200", variant: "flash", quant: "fp8", strategy: "high-throughput", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 1024 },
ttft_ms: 195293, tpot_ms: 130.35, tokens_per_sec_per_gpu: 493 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 4096 },
ttft_ms: 502615, tpot_ms: 130.31, tokens_per_sec_per_gpu: 490 },
],
},
{
match: { hw: "h200", variant: "pro", quant: "fp8", strategy: "low-latency", nodes: "multi-2" },
},
{
match: { hw: "h200", variant: "pro", quant: "fp8", strategy: "balanced", nodes: "multi-2" },
},
{
match: { hw: "h200", variant: "pro", quant: "fp8", strategy: "high-throughput", nodes: "multi-2" },
},
// ====================================================================
// H200 + FP4
// ====================================================================
{
match: { hw: "h200", variant: "flash", quant: "fp4", strategy: "low-latency", nodes: "single" },
sglang_version: "0.5.12.post1",
speed: [
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 1 },
ttft_ms: 193, tpot_ms: 3.38, tokens_per_sec_per_gpu: 67 },
{ workload: { dataset: "random", isl: 8192, osl: 1024, max_concurrency: 16 },
ttft_ms: 598, tpot_ms: 10.46, tokens_per_sec_per_gpu: 308 },
],
},
{
match: { hw: "h200", variant: "flash", quant: "fp4", strategy: "balanced", nodes: "single" },
},
{
match: { hw: "h200", variant: "flash", quant: "fp4", strategy: "high-throughput", nodes: "single" },
},
{
match: { hw: "h200", variant: "pro", quant: "fp4", strategy: "low-latency", nodes: "single" },
},
{
match: { hw: "h200", variant: "pro", quant: "fp4", strategy: "balanced", nodes: "single" },
},
{
match: { hw: "h200", variant: "pro", quant: "fp4", strategy: "high-throughput", nodes: "single" },
},
// ====================================================================
// H100 + FP4
// ====================================================================
{
match: { hw: "h100", variant: "flash", quant: "fp4", strategy: "low-latency", nodes: "single" },
},
{
match: { hw: "h100", variant: "flash", quant: "fp4", strategy: "balanced", nodes: "single" },
},
{
match: { hw: "h100", variant: "flash", quant: "fp4", strategy: "high-throughput", nodes: "single" },
},
{
match: { hw: "h100", variant: "pro", quant: "fp4", strategy: "low-latency", nodes: "multi-2" },
},
{
match: { hw: "h100", variant: "pro", quant: "fp4", strategy: "balanced", nodes: "multi-2" },
},
{
match: { hw: "h100", variant: "pro", quant: "fp4", strategy: "high-throughput", nodes: "multi-2" },
},
];
File diff suppressed because it is too large Load Diff