cookbook-migrate-model

Migrate a legacy-template SGLang cookbook page (monolithic per-model generator under docs/src/snippets/autoregressive/) onto the config-driven template (shared _deployment.jsx / _playground.jsx engines + per-model config). Use when asked to migrate, convert, or port an existing cookbook page — NOT for brand-new models (use cookbook-add-model for those). Run with /cookbook-migrate-model <Model page name, e.g. GLM-5.1>.

Install
npx skills add 'https://github.com/sgl-project/sglang/tree/main/.claude/skills/cookbook-migrate-model'
Download bundle ↓
main · a9fb1c3Scanned 2026-09-17

Contributors

GitHub-linked commit authors for this SKILL.md at the saved revision. Co-authors and history before file renames are not included.

File history ↗

SKILL.md

SKILL.mdBrowse 2 files
View on GitHub
---name: cookbook-migrate-modeldescription: Migrate a legacy-template SGLang cookbook page (monolithic per-model generator under docs/src/snippets/autoregressive/) onto the config-driven template (shared _deployment.jsx / _playground.jsx engines + per-model config). Use when asked to migrate, convert, or port an existing cookbook page — NOT for brand-new models (use cookbook-add-model for those). Run with /cookbook-migrate-model <Model page name, e.g. GLM-5.1>.--- # Cookbook Migrate Model Convert one legacy cookbook page to the config-driven format, faithfully. Thelegacy page — its generator widget and its measured benchmark blocks — is the**single source of truth**. You are transcribing it into the new data model,not improving it. Reuses the `cookbook-add-model` skill's assets (read them on demand):- `../cookbook-add-model/templates/config.jsx.tmpl`, `page.mdx.tmpl`, `benchmarks.jsx.tmpl`- `../cookbook-add-model/references/authoring-reference.md` (config/cells/playground contract)- `../cookbook-add-model/references/mintlify-authoring.md` (MDX rules) Migration-specific references in this skill:- [references/dimension-mapping.md](references/dimension-mapping.md) — legacy-control → new-dimension mapping rules, command rewrite table, per-family strategy sets, and the Qwen3.5 pilot as a worked example (PR #27848). The round's per-model inventory (scope, batch order, quirks, measured-datasurvey) is tracked by the migration maintainer outside the repo — expect it inyour dispatch prompt, or ask for it. ## Hard rules (non-negotiable) 1. **Never modernize.** Env vars, flags, TP values, docker tags, version strings   are copied verbatim from the legacy page — even when today's defaults differ   (e.g. a flag whose behavior has since become the default; keep it anyway). The recipe   that was verified is the recipe as written. Allowed normalizations are ONLY   the five alias rewrites in dimension-mapping.md §2 (`launch_server`→`sglang   serve`, `--model`→`--model-path`, `--tp-size`→`--tp`, abbreviated   `--speculative-algo`→`--speculative-algorithm`,   `--expert-parallel-size`→`--ep`). **Accuracy-degrading flags**   (`--kv-cache-dtype fp8_e4m3`, W4A4-style runtime quant) follow a   deterministic rule — enforced in migration, no asking: offered as a   legacy **selectable option** → never select it (cells mirror the   accuracy-safe side), and the option **survives as a Playground axis** —   an existing one where it fits, else add one via a separate prior engine   PR (rule 4); a legacy choice never degrades to a tips mention. Baked   into the recipe's **default/unconditional command** → keep it verbatim   (the recipe was measured with it, and fp8 KV halves KV memory —   stripping could OOM it). See dimension-mapping.md §2 caveats.2. **Never invent versions or numbers.** Benchmark numbers only from the   legacy page's measured blocks, and a result migrates ONLY when its   `sglang_version` is a **reproducible anchor** — the bar is reproducibility,   not "must be a release":   - ✅ release tag/version (`v0.5.9` / `0.5.9`), commit hash, OR — for     **Day-0 support** (the enabling PR isn't merged and no release is cut     yet) — a specific **PR (`PR #27944`) or commit** you can `gh pr checkout`     / `git checkout <sha>`. Commit is most precise; a PR pin is fine for day-0.   - ❌ a moving ref — `"main branch"`, `"main (2026-06-11)"`, open-ended     `"0.5.8+"` — is NOT reproducible: **drop the WHOLE result (speed AND     accuracy)**, not just speed. Keep `benchmarkCommands` so ⚡Reproduce still     guides re-measurement against a pinned build.   **Never inherit cross-model numbers** — measurements the legacy page   attributes to a *different model* (e.g. a K2.6 page carrying K2.5-measured   speed) are dropped regardless of version. When kept, `sglang_version` is the   legacy page's string verbatim. Docker tags only the ones the legacy page   pinned (unmapped hw falls back to `:dev`).3. **Verified policy (strictest tier).** `verified: true` ONLY when (a) the   legacy page has concrete measured data for that exact 5-dim combo AND   (b) the cell's flags equal the deployment command used for that measurement   — modulo `{{HOST_IP}}`/`{{PORT}}`, the five alias rewrites, and **parser   flags**: `--reasoning-parser`/`--tool-call-parser` are stripped from every   cell (Playground-only feature; when the measured run had them on, say so in   the benchmarks file header). When the measured command diverges from the   generator default, **the verified cell follows the measured command**; the   generator default stays as the sibling strategy/cell or a tips note. Everything else is unverified (yellow) —   including combos that look memory-infeasible; keep them verbatim and list   them in the PR body for the re-verification track.4. **Engines are read-only.** `_deployment.jsx` / `_playground.jsx` must not   change in a migration PR. Model-specific features are config DATA consumed   by generic axis handlers (MegaMoE precedent), so they need NO engine change.   A **titled single-select that strips a flag family** — KV Cache DType   (`--kv-cache-dtype`), mamba (`--mamba-radix-cache-strategy`), … — is already   covered by the merged generic **`flagSelects`** axis: declare it in the   config (a list of `{ id, title, stripPrefixes, options }`; see the Qwen3.5   mamba example), **no engine PR**. Only a genuinely new control *shape* that   `flagSelects` can't express would need a one-time generic primitive (never a   model-named handler) on a separate prior PR (engine-axis.md).5. **`github.cookbookModel` must be set** (`<hf-org>/<page-slug>`, e.g.   `qwen/qwen3.5`) and the block never pruned — without it Submit ↗ mislabels   as deepseek-v4. The issue template itself needs NO edits (free-form input).6. **Strategy tiers are signal-driven.** A cell goes under `low-latency` /   `high-throughput` ONLY on a signal present in the legacy source (an   explicit performance toggle, a named recipe, or prose stating the   operating point); **no signal → `balanced`**. Never derive a slant from   your own hardware intuition — re-tiering on measured evidence is the   hardware owner's follow-up PR, not part of a migration   (dimension-mapping.md §4). ## Workflow (one model = one PR) ### 1. Inventory the legacy assets- Read the legacy generator (`docs/src/snippets/autoregressive/<slug>-deployment.jsx`)  end-to-end: every option dimension (radio vs checkbox vs dynamic), every  gate/SUPPORT matrix, the full emitted command per reachable combo (env  prefixes, `# Error` pseudo-commands included).- Read the legacy MDX: §2 install docker tags → `dockerImages` (pinned, not  upgraded); §3.2 tips → new §2; §4 invocation examples → new §3 (keep real  Output Examples verbatim); §5 benchmark blocks → transcribe each measured  block: deploy command used, bench command (dataset/isl/osl/num-prompts/  concurrency), P50 (median) TTFT/TPOT, output tok/s, hardware, version string.- Inbound-anchor sweep: `grep -rn "<PageName>" docs/ --include='*.mdx'` —  find links/`#fragments` into this page (`mint broken-links` does NOT check  fragments). Fix referrers or add `<a id="old-anchor" />` shims in the same PR.- Check the maintainer-provided inventory notes for this model's known quirks —  but treat them (and the §4 family table) as a **survey snapshot**: re-verify  every dimension against the live legacy files before mapping. Pages keep  receiving updates (precedent: Kimi-K2.6's live generator has a speculative  toggle the 2026-06-10 survey notes lack). ### 2. Design the 5-dim mappingApply [references/dimension-mapping.md](references/dimension-mapping.md). Keydecision — which legacy toggle becomes the `strategies` dimension: a togglethat **changes other parts of the command** (TP, mem) must (the Playgroundcan't do coupled changes), and so does a toggle the legacy page itself labelswith operating-point words — e.g. a `dpattention` radio whose options aresubtitled "Low Latency" / "High Throughput" (GLM-5.1 / Kimi-K2.6 pattern) —even when its flags are uncoupled (`--dp N --enable-dp-attention` is a pureflag add). Any other toggle that only adds/removes its own flags becomes aPlayground axis with the flags baked into cells when the legacy default wasON — EXCEPT parsers:`--reasoning-parser`/`--tool-call-parser` are NEVER baked into cells, they arePlayground-only (DSv4 convention). **Every legacy control survives as aninteractive control** — a dimension or a Playground axis, never a tips-onlymention — and a model-specific control is **config data, not engine code**(MegaMoE W4A4 is all DSv4 config on the existing `moe` axis). It's pureconfig whenever it fits an existing axis's data schema. A **titledsingle-select that strips a flag family** (Nemotron3's "KV Cache DType",mamba `--mamba-radix-cache-strategy`, …) fits the merged generic **`flagSelects`**axis — so it too is config-only (declare a `flagSelects` list). Only a controlwhose *shape* `flagSelects` still can't express would need a ONE-TIME genericprimitive (never a model-named handler) on a separate PRIOR engine PR, keepingthe migration PR data-only (hard rule 4, engine-axis.md). The strategy count follows the page'soperating points: **one recipe → a single `balanced`; two → `low-latency` +`high-throughput`; three → the full trio (the ideal)**. The tiers apply per(hw × variant × quant) combination — a single-recipe combination on amulti-strategy page parks under its semantically honest tier (nolatency/throughput slant → `balanced`; the page's list is the union). When thelegacy toggle is MTP / speculative decoding, the direction is a deterministicdefault — apply without asking: **MTP on → `low-latency`, MTP off →`high-throughput`** (reversed only with maintainer confirmation). Tierplacement is signal-driven (hard rule 6). Never invent a recipe just to fillstrategy chips (see dimension-mapping.md §4). Record the outcome as a**strategy mapping table** for the PR body — one row per group ofcombinations sharing the same legacy signal (e.g. "all GPU combos: MTPtoggle → low-latency / high-throughput"; "xeon: (none) → balanced"), with aone-line rationale each; don't enumerate 60 identical rows. The table is whathardware owners sign off on at review. ### 3. Generate the config (codegen, then audit)- For >~30 cells, port the legacy `generateCommand()` into a throwaway Node  script that enumerates combos and emits the `cells:[...]` literal (output  must stay a pure literal — Mintlify forbids runtime spreads/calls). Apply the  verified-cell override in the script. See the pilot scripts embedded in the  worked example of dimension-mapping.md §5.- **Independent equivalence audit (required):** extract the ORIGINAL generator  from git (`git show main:<path>` — NOT `HEAD:`, the migration branch deletes  the file, see dimension-mapping.md §5 item 7), stub React hooks, run it for  every combo, and diff token-by-token against the new cells. Expected deltas  only: the appended `--host {{HOST_IP}}`/`--port {{PORT}}`, the  engine-injected multi-node trio, the §2 alias rewrites (the entrypoint  rewrite doesn't appear in cell tokens — cells hold flags only; the audit  script normalizes it on the legacy side), and the intentional verified-cell  override. Paste the PASS count + the audit script in the PR body  (collapsed `<details>`).- Hand-author the non-cells fields per authoring-reference.md. Structural  self-checks: every cell resolves a `modelNames` key; no `--nnodes/--node-rank/  --dist-init-addr/--host/--port` literals; every `{{KEY}}` declared; every  `supportedHardware` id has ≥1 cell. ### 4. Benchmarks fileOne entry per measured block only (cells without entries already render"pending" — bare `{match}` stubs are unnecessary). `tokens_per_sec_per_gpu` =total (in+out) tok/s/GPU = `output tok/s ÷ (tp × nnodes) ×(isl+osl)/osl` — stored directly (the card shows it as-is). TTFT/TPOTtake the P50 (median) rows; set `config.latencyPercentile` (default `"P50"`; use`"Mean"` only for legacy Mean-recorded data — temporary, being migrated to P50; anentry-level `latencyPercentile` overrides the page value per cell).Put the workload's`num_prompts` into `workload`. **`config.accuracyLabels` is required wheneverthe benchmarks carry accuracy data** — the engine ships no default eval set(#27842), so missing labels means the accuracy rows silently don't render;extra context (sample counts, suites that don't fit) goes in the entry's`notes`. Zero-measured-data pages: skip the file and the `benchmarks` propentirely, but keep `benchmarkCommands` so ⚡Reproduce still guides users. ### 5. Rewrite the MDXFrom `page.mdx.tmpl`: keep the original `title` (nav identity), write a freshSEO `description` (top-level — delete any legacy `metatags.description`), **no`tag: NEW`** (a migration is not a launch), **no `mode:`**. Install accordioncarries the legacy install content + pinned images. Keep the template'sDSv4-style strategy bullets — serving semantics first (single-user chat /typical multi-user / batch throughput), trimmed to the strategies the pageships, plus at most a one-line note on what each strategy changes on thismodel; do NOT rewrite them as toggle-/migration-centric explanations.Legacy §5 benchmark prose is deleted (numbers → benchmark card, commands →⚡Reproduce); legacy prose deploy commands are deleted (doc↔config parity —fold their unique flags into §2 tips). Invocation examples + real outputs carryover verbatim, but **wrapped in Accordions** — §3 commands and outputs arecollapsible (required, DeepSeek-V4 pattern): code in an`<Accordion title="… (Python)">`, output in a following`<Accordion title="Example Output">`; legacy pages kept them inline. ### 6. Delete the legacy generatorRemove `docs/src/snippets/autoregressive/<slug>-deployment.jsx` and itsimport. `grep -rn "<slug>-deployment" docs/` must return nothing (configprovenance comments must not name the deleted path). Site wiring needs **nochanges**: docs.json path/title unchanged, vendor card + logo already exist. ### 7. Validate- `grep -rn '__[A-Z_]*__'` on the new files (no template tokens).- `cd docs && mint validate && mint broken-links` (pre-existing breaks on  main are not yours — say so in the PR).- `mint dev` browser smoke: initial selection = the verified cell (first in  `cells[]`) with green badge; multi-node cells show the injected trio +  header; AMD cells show env prefixes; Docker mode wraps with the pinned image  and passes cell env as `--env`; condition-hidden combos grey out; benchmark  card values; NO parser flags in any Deploy command; Playground parser  toggles ADD the parser flags (green additions) while spec toggles strike  the baked spec flags (red); Submit ↗ prefills this model. **Probe pitfall:** drive at most  ONE programmatic click per evaluation and wait for React to settle —  multiple clicks in one synchronous script batch and read stale DOM.- Token-level audit from step 3 passes. ### 8. PR + reviewOne PR per model. PR body: migration framing, verified policy applied, thestrategy mapping table (step 2), the audit PASS count + script, anyinherited-infeasible combos flagged for re-verification. Then run `/cookbook-review-pr <N>` and fix findings.FYI: docs previews only build for in-repo (`sgl-project/sglang`) branches —a fork-headed PR is perfectly fine but renders no preview; a maintainer canre-push the branch in-repo if a preview is wanted for review. ### 9. Keep this skill currentAny new convention, engine behavior, or pitfall you discover while migrating(naming decisions, audit-script gotchas, review-rule conflicts, …) MUST be fedback into this skill — same PR if it's skill-file-only, or an immediatefollow-up commit on the skill's branch/PR. The next agent runs on what'swritten here, not on your session's context. 
Discovery context

Discovered by repository scan. No exact path reference found in the snapshot’s root docs/AGENTS.md.