Files
sglang/docs/src/snippets/_deployment.jsx
T

2623 lines
112 KiB
React
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ENGINE half of the SGLang cookbook deployment-command generator. Reads a
// per-model `config` prop (no model-specific code here). Full field semantics
// (resolution rules, key layering) live in the cookbook-add-model skill:
// .claude/skills/cookbook-add-model/references/authoring-reference.md.
//
// Config fields the engine reads:
// modelName display label
// supportedHardware hw ids shown in the catalog (subset of HARDWARE_CATALOG config.hardware)
// hardware optional — per-model GPUs the shared HARDWARE_CATALOG lacks:
// {id, label, vram, vendor}[] merged into the catalog at render
// (so a model-specific GPU never needs an engine-catalog edit);
// vendor picks the selector group: blackwell | hopper | amd | npu.
// `multiNodeDockerFlags: string[]` (either source) adds
// `docker run` flags the platform's fabric needs
// groupHardware optional — set false to show one flat hardware row
// variants/quantizations/strategies/nodesOptions LEGACY 4-dim option lists,
// used when `matchDims` is absent (nodesOptions id is
// `single` or `multi-N` → --nnodes N)
// matchDims optional — replaces the legacy four. {id, title, options}[]
// where each option is {id, label, showWhen?(sel), disabled?,
// disableReason?, soft?, softReason?}. `hw` is always the
// implicit first dim. Cells are then keyed on (hw × <these
// ids>). `disabled` is for combinations that cannot work;
// an option that runs but sits outside the verified matrix
// should declare `soft` instead — it stays selectable and
// announces itself as unverified (tooltip + in-cell note).
// Blocked options flash their disableReason under the row
// when tapped, so the reason also reaches touch readers.
// overlayDims optional — rows that do NOT participate in cell lookup; the
// picked option layers onto the matched cell, so an orthogonal
// knob does not multiply the cell count. Same option shape plus
// `flags` / `env` / `hints` (each a literal array or a function
// of the whole selection), and a row-level `default` / `showWhen`.
// `hints` render as `# ...` lines above the command.
// Builder-aware dimensions may additionally declare
// `scope: "base" | "serve" | "request"`, `description`,
// `quality`, `verifiedWhen`, and `learnMore`. Legacy configs
// omit these fields and keep the original renderer.
// commandBuilder optional — opts this config into the responsive diffusion
// builder while reusing this engine's overlay composition and
// command rendering. Shape:
// {defaultSelection, resource: {limits, verifiedRecipes,
// autoTopology(sel), validateTopology(sel)},
// resolveDeployment(sel)}. The resolver returns a cell plus
// `builder` metadata (topologySummary, errors, warnings,
// verification, resolvedSettings). UI-only scope/expand and
// local head-address/rank state never enter the URL hash.
// cells {match, verified?, verificationStatus?, nnodes?, warn?, redirect?,
// env, flags}[] — one per
// (hw × match dims); env/flags are flat literals, only
// {{PLACEHOLDER}} subst applied. `nnodes` supplies the node
// count for configs with no `nodes` dim (default 1). `warn`
// renders as a ⚠️ banner under the cell's command; it may
// embed [label](#anchor) links. `redirect: true` renders the
// banner ALONE — no command, header, or copy buttons — for
// cells that only point somewhere else.
// `verified` is the boolean badge baseline.
// `verificationStatus` overrides it with a third state —
// "verified" | "in-progress" | "unverified" — for a recipe
// whose verification round is open rather than absent. It
// may also be a function of the selection, for a cell whose
// verification depends on an overlay pick (e.g. one
// speculative option still being validated).
// modelNames HF slug lookup, `hw|variant|quant`, `variant|quant`,
// `hw|quant`, `quant`, `hw`, then `default`
// placeholders {{KEY}} → {target: 'command'|'curl', label, default?}
// curl cURL template (uses {{MODEL_NAME}} + placeholders), or
// `(selection, cell) => template` when the request payload
// depends on a custom match/overlay dimension
// benchmarkCommands optional — powers the "⚡ Reproduce" modal (speed +
// per-eval accuracy templates)
// defaultAccuracy optional — per-variant accuracy merged under cell.accuracy
// accuracyLabels [key, label, unit][] — the eval set shown in the
// benchmark card + "⚡ Reproduce". NO engine default:
// required whenever benchmarks carry accuracy data
// latencyPercentile optional, TEMPORARY — "Mean" | "P50" (default "P50"); the
// percentile the TTFT/TPOT values are, shown as "TTFT (<pct>)".
// A benchmarks entry may carry its own latencyPercentile to
// override the page value per cell (entry → config → "P50").
// Legacy "Mean" data is being re-measured to P50; drop once done
// multiNodeHints optional — {[hwId]: string[]} prepended as `# ...` lines
// dockerImages optional — `docker run` image, keyed by
// `hw|quant|strategy` then `hw|quant` then `hw`;
// falls back to `lmsysorg/sglang:dev`
// dockerHostNetworkWhen optional — `(selection, {flags, env}) => boolean`
// dockerMounts optional — additional `-v` mount specs
// dockerRunCommand optional — command placed after the image and before
// generated server flags; string or `(selection) => string`
// runModes optional — command output tabs to show (`python` and/or
// `docker`), as an array or `(selection) => array`;
// defaults to both, in that order
// showPlaygroundLink optional — false hides the "Open the Playground" footer
// for cookbooks that only expose the deployment matrix
// github optional — "Submit verified cell" issue-template overrides
// playgroundFeatures optional — consumed by _playground.jsx (see its header)
//
// Mintlify caveats this file routes around:
// - Module-level statements are stripped — everything lives inside the
// wrapper function body.
// - Capitalized JSX tags get rebound by _provideComponents() — lowercase
// HTML tags only; factor into helper functions, not sub-components.
// - Import plain-data config from the MDX file, pass through as a prop.
export const Deployment = ({ config, benchmarks }) => {
if (!config) {
return <div style={{padding: 12, color: "#b91c1c"}}>Deployment: missing <code>config</code> prop</div>;
}
// ==== 1. Hardware catalog (shared across cookbooks) ====
// VRAM is per-GPU on-chip memory, not per-module.
const HARDWARE_CATALOG = {
blackwell: [
{ id: "b300", label: "B300", vram: "288GB" },
{ id: "gb300", label: "GB300", vram: "288GB" },
{ id: "b200", label: "B200", vram: "192GB" },
{ id: "gb200", label: "GB200", vram: "192GB" },
// GB10 Grace Blackwell — 128 GB coherent unified system memory (not discrete VRAM).
// Multi-node runs over ConnectX-7 RDMA (pinned memory + IB passthrough).
{ id: "dgx-spark", label: "DGX Spark", vram: "128GB",
multiNodeDockerFlags: [
"--ulimit memlock=-1:-1", "--cap-add IPC_LOCK", "--device /dev/infiniband",
] },
],
hopper: [
{ id: "h200", label: "H200", vram: "141GB" },
{ id: "h100", label: "H100", vram: "80GB" },
{ id: "h20-3e", label: "H20-3e", vram: "141GB" },
{ id: "h800", label: "H800", vram: "80GB" },
],
amd: [
{ id: "mi300x", label: "MI300X", vram: "192GB" },
{ id: "mi325x", label: "MI325X", vram: "256GB" },
{ id: "mi350x", label: "MI350X", vram: "288GB" },
{ id: "mi355x", label: "MI355X", vram: "288GB" },
],
// Atlas 800I A3 (910C): 1 card = 2 dies, so --tp-size is 2× the card
// count (32 cards -> --tp-size 64).
npu: [
{ id: "a3", label: "Atlas 800I A3", vram: "64GB/die" },
],
};
// ==== 2. Style helper (dark-mode-aware) ====
const makeStyles = (isDark) => ({
container: { maxWidth: "900px", margin: "0 auto", display: "flex", flexDirection: "column", gap: "3px" },
card: {
padding: "5px 10px",
border: `1px solid ${isDark ? "#374151" : "#e5e7eb"}`,
borderLeft: `3px solid ${isDark ? "#E85D4D" : "#D45D44"}`,
borderRadius: "4px",
display: "flex", alignItems: "center", gap: "10px",
background: isDark ? "#1f2937" : "#fff",
},
cardColumn: {
padding: "5px 10px",
border: `1px solid ${isDark ? "#374151" : "#e5e7eb"}`,
borderLeft: `3px solid ${isDark ? "#E85D4D" : "#D45D44"}`,
borderRadius: "4px",
display: "flex", flexDirection: "column", gap: "4px",
background: isDark ? "#1f2937" : "#fff",
},
title: { fontSize: "12px", fontWeight: "600", minWidth: "108px", flexShrink: 0, color: isDark ? "#e5e7eb" : "inherit" },
vendorRow: { display: "flex", alignItems: "center", gap: "6px" },
// Fixed width so every row's chips start at the same x regardless of the
// group name ("BLACKWELL" is the widest).
vendorLabel: {
fontSize: "10px", fontWeight: "600",
color: isDark ? "#9ca3af" : "#6b7280",
width: "68px", flexShrink: 0, textTransform: "uppercase", letterSpacing: "0.04em",
},
// auto-fit + a real min width: columns wrap on narrow screens instead of
// shrinking below their label (the old minmax(0,1fr) let buttons overlap on
// mobile). `cols` no longer needed — auto-fit never exceeds the item count.
itemsGrid: () => ({
display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(72px, 1fr))",
gap: "4px", flex: 1,
}),
labelBase: {
padding: "2px 8px",
border: `1px solid ${isDark ? "#9ca3af" : "#d1d5db"}`,
borderRadius: "3px", cursor: "pointer",
display: "inline-flex", flexDirection: "column",
alignItems: "center", justifyContent: "center",
fontWeight: "500", fontSize: "12px",
transition: "all 0.2s", userSelect: "none",
minHeight: "26px", textAlign: "center",
background: isDark ? "#374151" : "#fff",
color: isDark ? "#e5e7eb" : "inherit",
},
checked: { background: "#D45D44", color: "white", borderColor: "#D45D44" },
disabled: { cursor: "not-allowed", opacity: 0.4 },
subtitle: { display: "block", fontSize: "9px", marginTop: "1px", lineHeight: "1.1", opacity: 0.7 },
commandWrap: {
position: "relative", flex: 1,
background: isDark ? "#111827" : "#f5f5f5",
borderRadius: "6px",
border: `1px solid ${isDark ? "#374151" : "#e5e7eb"}`,
overflow: "hidden",
},
commandHeader: {
display: "flex", flexWrap: "wrap", justifyContent: "space-between", alignItems: "center",
gap: "6px 10px",
padding: "6px 10px",
borderBottom: `1px solid ${isDark ? "#374151" : "#e5e7eb"}`,
background: isDark ? "#1f2937" : "#fafafa",
},
commandPre: {
padding: "12px 16px",
fontFamily: "'Menlo', 'Monaco', 'Courier New', monospace",
fontSize: "12px", lineHeight: "1.5",
color: isDark ? "#e5e7eb" : "#374151",
whiteSpace: "pre-wrap", overflowX: "auto", margin: 0,
},
// Amber callout under the command when speculative decoding (MTP, DSpark, ...)
// is on but --max-running-requests isn't set (SGLang then caps it at 48).
mtpWarn: {
margin: "8px 0 0", padding: "8px 12px", borderRadius: "8px",
fontSize: "12px", lineHeight: "1.45",
background: isDark ? "#78350f" : "#fef3c7",
color: isDark ? "#fde68a" : "#92400e",
border: `1px solid ${isDark ? "#92400e" : "#fcd34d"}`,
},
// Takes either a boolean (legacy `cell.verified`) or a status id — see
// VERIFY_LABEL / verifyStatusOf in section 3.
badge: (status) => ({
display: "inline-flex", alignItems: "center", gap: "6px",
padding: "2px 8px", borderRadius: "10px",
background: {
verified: isDark ? "#064e3b" : "#d1fae5",
"in-progress": isDark ? "#1e3a8a" : "#dbeafe",
unverified: isDark ? "#78350f" : "#fef3c7",
}[verifyStatusOf(status)],
color: {
verified: isDark ? "#a7f3d0" : "#065f46",
"in-progress": isDark ? "#bfdbfe" : "#1e40af",
unverified: isDark ? "#fde68a" : "#92400e",
}[verifyStatusOf(status)],
// The in-progress label is long; keep the pill on one line and let the
// header row wrap around it instead of breaking the text mid-badge.
fontSize: "11px", fontWeight: 600, whiteSpace: "nowrap",
}),
badgeDot: (status) => ({
width: "8px", height: "8px", borderRadius: "50%",
background: { verified: "#10b981", "in-progress": "#3b82f6", unverified: "#f59e0b" }[
verifyStatusOf(status)
],
}),
iconButton: {
padding: "4px 10px",
border: `1px solid ${isDark ? "#4b5563" : "#d1d5db"}`,
borderRadius: "4px",
background: isDark ? "#1f2937" : "#fff",
color: isDark ? "#e5e7eb" : "#374151",
fontSize: "11px", fontWeight: 500, cursor: "pointer",
display: "inline-flex", alignItems: "center", gap: "4px",
},
iconRow: { display: "inline-flex", flexWrap: "wrap", gap: "6px" },
runModeWrap: {
display: "inline-flex",
border: `1px solid ${isDark ? "#4b5563" : "#d1d5db"}`,
borderRadius: "10px",
overflow: "hidden",
fontSize: "11px",
fontWeight: 600,
userSelect: "none",
},
runModeChip: (active) => ({
padding: "2px 10px",
cursor: "pointer",
background: active
? (isDark ? "#1f2937" : "#fff")
: "transparent",
color: active
? (isDark ? "#e5e7eb" : "#111827")
: (isDark ? "#9ca3af" : "#6b7280"),
borderRight: `1px solid ${isDark ? "#4b5563" : "#d1d5db"}`,
}),
runModeChipLast: (active) => ({
padding: "2px 10px",
cursor: "pointer",
background: active
? (isDark ? "#1f2937" : "#fff")
: "transparent",
color: active
? (isDark ? "#e5e7eb" : "#111827")
: (isDark ? "#9ca3af" : "#6b7280"),
}),
headerLeft: { display: "inline-flex", flexWrap: "wrap", alignItems: "center", gap: "8px" },
modalBackdrop: {
position: "fixed", inset: 0,
background: "rgba(0,0,0,0.5)",
display: "flex", alignItems: "center", justifyContent: "center",
zIndex: 9999,
},
modalBox: {
background: isDark ? "#1f2937" : "#fff",
color: isDark ? "#e5e7eb" : "#111827",
borderRadius: "8px", padding: "20px",
maxWidth: "720px", width: "92%", maxHeight: "85vh", overflowY: "auto",
border: `1px solid ${isDark ? "#374151" : "#e5e7eb"}`,
boxShadow: "0 10px 25px rgba(0,0,0,0.25)",
},
modalHeader: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "12px" },
modalTitle: { fontSize: "15px", fontWeight: 600 },
modalCloseBtn: {
background: "transparent", border: "none", color: "inherit",
fontSize: "20px", cursor: "pointer", padding: "0 6px", lineHeight: 1,
},
formField: { display: "flex", flexDirection: "column", gap: "4px", marginBottom: "10px" },
formLabel: { fontSize: "12px", fontWeight: 500, color: isDark ? "#9ca3af" : "#4b5563" },
formInput: {
padding: "6px 10px", fontSize: "13px",
border: `1px solid ${isDark ? "#4b5563" : "#d1d5db"}`,
borderRadius: "4px",
background: isDark ? "#111827" : "#fff",
color: isDark ? "#e5e7eb" : "#111827",
fontFamily: "'Menlo', 'Monaco', 'Courier New', monospace",
},
sectionHeading: {
fontSize: "12px", fontWeight: 600, textTransform: "uppercase",
letterSpacing: "0.04em",
color: isDark ? "#9ca3af" : "#6b7280",
margin: "12px 0 6px 0",
},
primaryBtn: {
padding: "6px 14px", background: "#D45D44", color: "white",
border: "none", borderRadius: "4px", cursor: "pointer",
fontSize: "13px", fontWeight: 500,
},
benchCard: {
padding: "8px 12px",
border: `1px solid ${isDark ? "#374151" : "#e5e7eb"}`,
borderLeft: `3px solid ${isDark ? "#E85D4D" : "#D45D44"}`,
borderRadius: "4px",
background: isDark ? "#1f2937" : "#fff",
display: "flex", flexDirection: "column", gap: "8px",
},
benchHeader: {
display: "flex", flexWrap: "wrap", alignItems: "baseline", justifyContent: "space-between",
gap: "6px 12px",
},
benchTitle: {
fontSize: "13px", fontWeight: 600,
color: isDark ? "#e5e7eb" : "inherit",
},
benchVersion: {
fontSize: "11px",
color: isDark ? "#9ca3af" : "#6b7280",
},
benchHeaderRight: {
display: "flex", flexWrap: "wrap", alignItems: "center", gap: "6px 10px", flexShrink: 0,
},
benchChipRow: {
display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap",
margin: "2px 0 8px",
},
benchChip: {
padding: "2px 10px", fontSize: "12px", cursor: "pointer",
border: `1px solid ${isDark ? "#4b5563" : "#d1d5db"}`,
borderRadius: "4px",
background: isDark ? "#1f2937" : "#fff",
color: isDark ? "#e5e7eb" : "#374151",
fontFamily: "'Menlo', 'Monaco', 'Courier New', monospace",
},
benchChipActive: { background: "#D45D44", color: "white", borderColor: "#D45D44" },
benchBlock: {
border: `1px solid ${isDark ? "#374151" : "#e5e7eb"}`,
borderRadius: "4px",
padding: "8px 10px",
background: isDark ? "#111827" : "#fafafa",
},
benchBlockTitle: {
fontSize: "11px", fontWeight: 600, textTransform: "uppercase",
letterSpacing: "0.04em",
color: isDark ? "#9ca3af" : "#6b7280",
marginBottom: "4px",
},
benchWorkload: {
fontSize: "11px", fontStyle: "italic",
color: isDark ? "#9ca3af" : "#6b7280",
marginBottom: "6px",
lineHeight: "1.3",
},
benchRow: {
display: "flex", justifyContent: "space-between",
fontSize: "12px", padding: "2px 0",
},
benchKey: { color: isDark ? "#9ca3af" : "#6b7280" },
benchVal: {
color: isDark ? "#e5e7eb" : "#111827",
fontFamily: "'Menlo', 'Monaco', 'Courier New', monospace",
fontWeight: 500,
},
benchNotes: {
fontSize: "11px", fontStyle: "italic",
color: isDark ? "#9ca3af" : "#6b7280",
},
benchLegend: {
fontSize: "10px", fontStyle: "italic",
color: isDark ? "#6b7280" : "#9ca3af",
marginTop: "6px",
fontFamily: "'Menlo', 'Monaco', 'Courier New', monospace",
},
benchEmpty: {
fontSize: "12px", fontStyle: "italic",
color: isDark ? "#9ca3af" : "#6b7280",
},
// grid (not <table>) — Mintlify wraps <table> with scroll wrappers.
// gridTemplateColumns set inline (depends on measurements.length).
benchTable: {
display: "grid",
// columnGap 0 so cells' bottom borders form one continuous line.
columnGap: 0,
rowGap: "3px",
marginTop: "4px",
alignItems: "baseline",
},
benchTableHead: {
textAlign: "right",
fontWeight: 500, fontSize: "11px",
color: isDark ? "#9ca3af" : "#6b7280",
paddingLeft: "16px",
paddingBottom: "4px",
whiteSpace: "nowrap",
},
benchTableCornerHead: {
paddingBottom: "4px",
},
// Header underline — one div spanning all columns (continuous line).
benchTableSeparator: {
gridColumn: "1 / -1",
height: "1px",
background: isDark ? "#374151" : "#e5e7eb",
marginTop: "-3px", // negate the rowGap so it hugs the header row
},
benchTableLabel: {
textAlign: "left", fontSize: "12px",
color: isDark ? "#9ca3af" : "#6b7280",
whiteSpace: "nowrap",
},
benchTableValue: {
textAlign: "right", fontSize: "12px",
color: isDark ? "#e5e7eb" : "#111827",
fontFamily: "'Menlo', 'Monaco', 'Courier New', monospace",
fontWeight: 500,
paddingLeft: "16px",
whiteSpace: "nowrap",
},
benchTableValueMissing: {
color: isDark ? "#6b7280" : "#9ca3af",
},
});
// ==== 3. Pure helpers (no React state) ====
// Verification badge state. A cell's boolean `verified` is the baseline;
// `cell.verificationStatus` overrides it, which is how a recipe whose
// verification round is open reports that instead of collapsing into the flat
// Verified / Not Verified pair.
const VERIFY_LABEL = {
verified: "Verified",
"in-progress": "Final Verification In Progress",
unverified: "Not Verified",
};
// Booleans keep their historical meaning; an unrecognized status id falls
// back to "unverified" rather than to truthiness (a typo must never read as
// a green Verified badge).
const verifyStatusOf = (v) =>
typeof v === "string"
? (VERIFY_LABEL[v] ? v : "unverified")
: (v ? "verified" : "unverified");
const cellVerifyStatus = (c, sel) => {
if (!c) return "unverified";
const v =
typeof c.verificationStatus === "function"
? c.verificationStatus(sel)
: c.verificationStatus;
return verifyStatusOf(v ?? c.verified);
};
// Two kinds of selector row:
// match dims participate in cell lookup (cell.match[dim] === sel[dim])
// overlay dims never touch cell lookup; the picked option contributes flags
// on top of the matched cell (so an orthogonal knob like
// speculative decoding does not multiply the cell count)
// A config that declares neither keeps the legacy fixed 5-dim shape, so model
// pages written before this existed render unchanged.
const LEGACY_MATCH_DIMS = [
{ id: "variant", title: "Model Variant", optionsKey: "variants" },
{ id: "quant", title: "Quantization", optionsKey: "quantizations" },
{ id: "strategy", title: "Strategy", optionsKey: "strategies" },
{ id: "nodes", title: "Nodes", optionsKey: "nodesOptions" },
];
// `hw` is always the first match dim; it has its own vendor-grouped renderer.
const matchDimSpecs = (config.matchDims || LEGACY_MATCH_DIMS).map((d) => ({
...d,
options: d.options || config[d.optionsKey] || [],
}));
const overlayDimSpecs = config.overlayDims || [];
const commandBuilder = config.commandBuilder || null;
// DIMENSIONS is ordered by priority — higher-index dims adapt to lower-index
// picks, never the reverse. Drives the grey-out/snap logic below.
const DIMENSIONS = ["hw", ...matchDimSpecs.map((d) => d.id)];
// An option is visible when it declares no `showWhen`, or its predicate accepts
// the current selection. Hidden options are excluded from snapping and from the
// grey-out scan, so a stale pick can never survive a dependent-row switch.
// ==== MIRROR in _playground.jsx — keep the two copies identical ====
// Snippets cannot import each other, so the overlay-resolution rule is written
// twice. A divergence makes the Deploy command and the playground base disagree,
// which shows up as phantom +/- lines in the diff and no error anywhere.
// Guarded by docs/scripts/check_cookbook_configs.mjs.
const optionVisible = (opt, sel) =>
typeof opt.showWhen !== "function" || opt.showWhen(sel);
const optionDisabled = (opt, sel) =>
typeof opt.disabled === "function" ? opt.disabled(sel) : !!opt.disabled;
const visibleOptions = (spec, sel) =>
(spec.options || []).filter((o) => optionVisible(o, sel));
const rowVisible = (spec, sel) =>
(typeof spec.showWhen !== "function" || spec.showWhen(sel)) &&
visibleOptions(spec, sel).length > 0;
const overlayPick = (sel) => {
const picked = [];
for (const spec of (config.overlayDims || [])) {
if (!rowVisible(spec, sel)) continue;
const opt = (spec.options || []).find((o) => o.id === sel[spec.id]);
if (opt && !optionDisabled(opt, sel)) picked.push(opt);
}
return picked;
};
const overlayPart = (sel, key) => {
const out = [];
for (const opt of overlayPick(sel)) {
const add = typeof opt[key] === "function" ? opt[key](sel) : opt[key];
if (add) out.push(...add);
}
return out;
};
// An overlay option may also REMOVE cell flags, declared as `stripPrefixes`
// (a static list, or a function of the selection). L3 uses it to drop the
// whole DCP operating point, which the server rejects with an L3 backend.
//
// Overlay flags append, except a flag whose family the same overlay stripped:
// that one is spliced back where the stripped flag was, so a rewritten
// parallelism block (DSPARK folding a pipeline flat) stays put instead of
// landing past the --host/--port tail with the multi-node trio behind it.
const overlayCompose = (cellFlags, sel) => {
const strip = overlayPart(sel, "stripPrefixes");
const add = overlayPart(sel, "flags");
if (!strip.length) return [...(cellFlags || []), ...add];
const used = new Set();
// Consumed once, so a family the cell carries twice is not emitted twice.
const replacementsFor = (tok) => {
const out = [];
add.forEach((f, i) => {
if (used.has(i) || f.split(/[\s=]/)[0] !== tok) return;
used.add(i);
out.push(f);
});
return out;
};
const out = [];
for (const f of (cellFlags || [])) {
const tok = f.split(/[\s=]/)[0];
if (!strip.includes(tok)) out.push(f);
else out.push(...replacementsFor(tok));
}
add.forEach((f, i) => { if (!used.has(i)) out.push(f); });
return out;
};
// ==== end MIRROR ====
// `soft` marks an option that is plausible but outside the verified matrix:
// it stays selectable (the status badge reports verification separately),
// where `disabled` is reserved for combinations that cannot work at all.
const optionSoft = (opt, sel) =>
typeof opt.soft === "function" ? opt.soft(sel) : !!opt.soft;
const findCell = (cells, sel) =>
cells.find((c) => DIMENSIONS.every((d) => c.match[d] === sel[d]));
// Entries may also key on overlay dims (e.g. kvDsaPair): an entry applies
// only when every declared key equals the selection, and the most specific
// match wins, so plain hw×strategy entries stay the fallback.
const findBenchmark = (list, sel) => {
const hits = (list || []).filter((b) =>
Object.entries(b.match || {}).every(([k, v]) => sel[k] === v));
return hits.sort((a, b) => Object.keys(b.match).length - Object.keys(a.match).length)[0] || null;
};
// Accepts a single measurement object or an array; always returns an array.
const normalizeSpeed = (speed) => {
if (!speed) return [];
return Array.isArray(speed) ? speed : [speed];
};
// Variant default accuracy merged UNDER per-cell measured accuracy — but ONLY when
// a benchmark entry exists for the cell. A cell with no entry was never measured, so
// it shows the empty/"pending" state instead of borrowing the variant's accuracy.
const effectiveAccuracy = (entry, sel) =>
entry
? {
...((config.defaultAccuracy && config.defaultAccuracy[sel.variant]) || {}),
...(entry.accuracy || {}),
}
: {};
// Empty = every speed measurement null-only AND accuracy null-only. `workload`
// is metadata, not a measurement — skip it so a workload-only stub stays empty.
const benchmarkIsEmpty = (entry, accuracy) => {
for (const m of normalizeSpeed(entry && entry.speed)) {
if (m && typeof m === "object") {
for (const [key, v] of Object.entries(m)) {
if (key === "workload") continue;
if (v !== null && v !== undefined) return false;
}
}
}
if (accuracy && typeof accuracy === "object") {
for (const v of Object.values(accuracy)) {
if (v !== null && v !== undefined) return false;
}
}
return true;
};
// Grey-out predicate: (dim, value) is enabled iff some cell matches every
// HIGHER-priority dim in `sel` AND has dim === value. Lower dims may differ
// (snapToValidCell adapts them on click).
const isOptionAvailable = (cells, sel, dim, value) => {
const idx = DIMENSIONS.indexOf(dim);
const higher = DIMENSIONS.slice(0, idx);
return cells.some(
(c) => c.match[dim] === value && higher.every((d) => c.match[d] === sel[d]),
);
};
// Snap to a real cell on click: higher dims stay locked, `dim` := value,
// lower dims adopt the best-fit cell (the one preserving the most lower picks).
const snapToValidCell = (cells, sel, dim, value) => {
const idx = DIMENSIONS.indexOf(dim);
const higher = DIMENSIONS.slice(0, idx);
const lower = DIMENSIONS.slice(idx + 1);
let best = null, bestLowerMatches = -1;
for (const c of cells) {
if (c.match[dim] !== value) continue;
if (!higher.every((d) => c.match[d] === sel[d])) continue;
let s = 0;
for (const d of lower) if (c.match[d] === sel[d]) s++;
if (s > bestLowerMatches) { bestLowerMatches = s; best = c; }
}
if (!best) return sel; // defensive — shouldn't be reachable
const next = { ...sel, [dim]: value };
for (const d of lower) next[d] = best.match[d];
return next;
};
// Snap a parsed (possibly stale) URL-hash selection to a real cell, walking
// dims in priority order and falling back per-dim to the first consistent cell.
const validateSelection = (cells, parsed) => {
const valid = {};
for (const dim of DIMENSIONS) {
const want = parsed[dim];
const works = cells.some(
(c) =>
c.match[dim] === want &&
DIMENSIONS.slice(0, DIMENSIONS.indexOf(dim)).every((d) => c.match[d] === valid[d]),
);
if (works) {
valid[dim] = want;
} else {
const fallback = cells.find((c) =>
DIMENSIONS.slice(0, DIMENSIONS.indexOf(dim)).every((d) => c.match[d] === valid[d]),
);
valid[dim] = fallback ? fallback.match[dim] : want;
}
}
// Overlay dims ride along: they never key cells, so snapping must not drop
// them (it did — a strict-mode hash round-trip lost the spec default).
// Keep the parsed value when it names a real option, else the row default.
// A hash can also name an option that showWhen hides (or a rule disables)
// for the composed selection; snap those like an interactive reseat would.
for (const spec of overlayDimSpecs) {
const want = parsed[spec.id];
const opts = spec.options || [];
const picked = opts.some((o) => o.id === want)
? want
: spec.default ?? (opts[0] && opts[0].id) ?? "";
const withPick = { ...valid, [spec.id]: picked };
const usable = visibleOptions(spec, withPick).filter((o) => !optionDisabled(o, withPick));
valid[spec.id] = usable.some((o) => o.id === picked)
? picked
: (usable[0] && usable[0].id) ?? picked;
}
return valid;
};
// Lookup walks most-specific to least so a config that drops the variant/quant
// dims can key its HF slug on `hw` alone, or on the single "default" entry.
// The `hw|quant` and bare `quant` rungs cover a `matchDims` config that declares
// no variant dim at all — there `sel.variant` is undefined, so the two leading
// keys can never hit.
const resolveModelName = (sel) => {
const keys = [
`${sel.hw}|${sel.variant}|${sel.quant}`,
`${sel.variant}|${sel.quant}`,
`${sel.hw}|${sel.quant}`,
sel.quant,
sel.hw,
"default",
];
for (const k of keys) {
const hit = config.modelNames[k];
if (hit) return hit;
}
return "";
};
const interpolate = (text, env, modelName) =>
text.replace(/{{(\w+)}}/g, (_, key) =>
key === "MODEL_NAME" ? modelName : (env[key] ?? `{{${key}}}`));
// Node count comes from the `nodes` dim when the config has one; without that
// dim it is a property of the cell itself (`nnodes`), since the deployment
// shape is then fixed by the hardware rather than picked by the reader.
const parseNnodes = (id) => {
if (Number.isInteger(id)) return id;
if (/^\d+$/.test(id || "")) return parseInt(id, 10);
if (id === "single") return 1;
const m = /^multi-(\d+)$/.exec(id || "");
return m ? parseInt(m[1], 10) : 1;
};
const cellNnodes = (cell, sel) =>
sel.nodes !== undefined ? parseNnodes(sel.nodes) : (cell.nnodes || 1);
// Role-specific serving ports for PD deployments — keep in sync with PD_PORTS
// in _playground.jsx, which the generated router command targets. Each role
// derives 5 ZMQ/dist ports from its --port, so the serve ports are spaced 100
// apart to keep those ranges from overlapping on a same-host deployment.
const PD_SERVE_PORTS = { prefill: 30000, decode: 30100 };
// `flags` / `env` / `hints` may each be a function of the whole selection, so an
// "Auto" option can resolve against another row (draft tokens per strategy).
const overlayEnv = (sel) => overlayPart(sel, "env");
const overlayHints = (sel) => overlayPart(sel, "hints");
// python mode → bare `sglang serve`; docker mode → wrapped in `docker run`.
const renderCommand = (cell, sel, envValues, mode = "python") => {
if (!cell) return "# No command available for the current selection.";
const modelName = resolveModelName(sel);
const nnodes = cellNnodes(cell, sel);
const multinode = nnodes > 1;
const cellEnv = [...(cell.env || []), ...overlayEnv(sel)];
const flags = overlayCompose(cell.flags, sel);
if (multinode) {
// Insert the multi-node trio after the last parallelism flag,
// falling back to right after --model-path.
const PARALLELISM_ANCHORS = new Set([
"--enable-dp-attention", "--dp-size", "--dp", "--tp-size", "--tp",
"--sp-degree", "--ulysses-degree", "--ring-degree",
]);
let i = flags.reduce(
(last, flag, index) => PARALLELISM_ANCHORS.has(flag.split(/[\s=]/)[0]) ? index : last,
-1,
);
if (i === -1) i = flags.findIndex((f) => f.startsWith("--model-path"));
flags.splice(i + 1, 0,
`--nnodes ${nnodes}`,
`--node-rank {{NODE_RANK}}`,
`--dist-init-addr {{NODE0_IP}}:20000`);
}
const pdServePort = PD_SERVE_PORTS[sel.pdMode];
if (pdServePort !== undefined) {
for (let j = 0; j < flags.length; j++) {
if (flags[j].split(/[\s=]/)[0] === "--port") {
flags[j] = `--port ${pdServePort}`;
}
}
}
let cmd;
if (mode === "docker") {
// Image keyed by `hw|quant|strategy` (most specific), then `hw|quant`,
// then `hw`; `:dev` if unmapped. The strategy key covers a tier that
// needs its own build (e.g. a spec-decoding preview image).
const di = config.dockerImages || {};
const image = di[`${sel.hw}|${sel.quant}|${sel.strategy}`]
|| di[`${sel.hw}|${sel.quant}`] || di[sel.hw] || "lmsysorg/sglang:dev";
const dockerRunCommand = typeof config.dockerRunCommand === "function"
? config.dockerRunCommand(sel)
: (config.dockerRunCommand || "sglang serve");
const portFlag = flags.find((x) => x.split(/[\s=]/)[0] === "--port");
const servePort = portFlag ? portFlag.slice("--port".length).trim() : "{{PORT}}";
const hostNetwork = multinode || (typeof config.dockerHostNetworkWhen === "function"
&& config.dockerHostNetworkWhen(sel, { flags, env: cellEnv }));
const vendorOf = (hwId) => {
for (const [vendor, list] of Object.entries(HARDWARE_CATALOG)) {
if (list.some((h) => h.id === hwId)) return vendor;
}
const extra = (config.hardware || []).find((h) => h.id === hwId);
return (extra && extra.vendor) || "nvidia";
};
// `config.hardware` overrides by id, as in buildHardwareGroups.
const fabricFlagsOf = (hwId) => {
const extra = (config.hardware || []).find((h) => h.id === hwId);
if (extra) return extra.multiNodeDockerFlags || [];
for (const list of Object.values(HARDWARE_CATALOG)) {
const hit = list.find((h) => h.id === hwId);
if (hit) return hit.multiNodeDockerFlags || [];
}
return [];
};
const gpuAccessLines = vendorOf(sel.hw) === "amd"
? [
"docker run",
" --device=/dev/kfd --device=/dev/dri",
" --group-add video",
" --cap-add=SYS_PTRACE --security-opt seccomp=unconfined",
" --shm-size 32g",
]
: vendorOf(sel.hw) === "npu"
? [
// NPU: --privileged grants the davinci devices (16 dies on an
// 8-card Atlas 800I A3 node); the host CANN driver/firmware/state
// must be mounted in.
"docker run --privileged --shm-size=16g",
" --device=/dev/davinci0 --device=/dev/davinci1 --device=/dev/davinci2 --device=/dev/davinci3",
" --device=/dev/davinci4 --device=/dev/davinci5 --device=/dev/davinci6 --device=/dev/davinci7",
" --device=/dev/davinci8 --device=/dev/davinci9 --device=/dev/davinci10 --device=/dev/davinci11",
" --device=/dev/davinci12 --device=/dev/davinci13 --device=/dev/davinci14 --device=/dev/davinci15",
" --device=/dev/davinci_manager",
" --device=/dev/hisi_hdc",
" -v /usr/local/sbin:/usr/local/sbin",
" -v /usr/local/Ascend/driver:/usr/local/Ascend/driver",
" -v /usr/local/Ascend/firmware:/usr/local/Ascend/firmware",
" -v /etc/ascend_install.info:/etc/ascend_install.info",
" -v /var/queue_schedule:/var/queue_schedule",
" -v ~/.cache/:/root/.cache/",
]
: [
"docker run --gpus all",
" --shm-size 32g",
];
const dockerLines = [
...gpuAccessLines,
// Multi-node needs host networking so the cross-node rendezvous port
// (--dist-init-addr) and NCCL/GLOO traffic are reachable; single-node
// just maps the serve port.
hostNetwork ? " --network host" : ` -p ${servePort}:${servePort}`,
...(multinode ? fabricFlagsOf(sel.hw).map((f) => " " + f) : []),
// The NPU device block already mounts ~/.cache/.
...(vendorOf(sel.hw) === "npu"
? [] : [" -v ~/.cache/huggingface:/root/.cache/huggingface"]),
...(config.dockerMounts || []).map((mount) => ` -v ${mount}`),
// HF token only for gated checkpoints — configs that declare an HF_TOKEN placeholder.
...(config.placeholders && config.placeholders.HF_TOKEN
? [` --env "HF_TOKEN={{HF_TOKEN}}"`] : []),
...cellEnv.map((e) => ` --env ${e}`),
" --ipc=host",
` ${image}`,
` ${dockerRunCommand}`,
...flags.map((f) => " " + f),
];
cmd = dockerLines.join(" \\\n");
} else {
const flagBlock = flags.map((f) => " " + f).join(" \\\n");
const envBlock = cellEnv.length ? cellEnv.join(" \\\n") + " \\\n" : "";
cmd = `${envBlock}sglang serve \\\n${flagBlock}`;
}
const hintLines = [
...overlayHints(sel),
...(multinode && config.multiNodeHints && config.multiNodeHints[sel.hw]
? config.multiNodeHints[sel.hw]
: []),
];
if (hintLines.length) {
const hint = hintLines
.map((line) => (line.length ? "# " + line : "#")).join("\n");
cmd = `${hint}\n${cmd}`;
}
cmd = interpolate(cmd, envValues, modelName);
if (multinode) {
const header =
`# Multi-node (${nnodes} nodes). Run the same command on every node with:\n` +
`# <node-rank> = 0 on the head node, 1..${nnodes - 1} on the others\n` +
`# <node0-ip> = IP of the head node (reachable from all others)`;
cmd = `${header}\n${cmd}`;
}
return cmd;
};
// Accuracy labels: [field-key, display-label, unit]. Declared per model via
// `config.accuracyLabels` — the engine ships NO default eval set. A config
// without it renders no accuracy rows (and no Accuracy section in the
// "⚡ Reproduce" modal). Keys must match the `accuracy` fields in the
// benchmarks file + `benchmarkCommands.accuracy`.
const ACCURACY_LABELS = config.accuracyLabels || [];
const renderBenchmarkCard = (entry) => {
// [key, label, unit, compute?]. Optional compute(measurement) supplies
// derived metrics (preferred over measurement[key] when present).
const pct = (entry && entry.latencyPercentile) || config.latencyPercentile || "P50";
const SPEED_LABELS = [
["ttft_ms", `TTFT (${pct})`, "ms"],
["tpot_ms", `TPOT (${pct})`, "ms"],
// throughput per gpu = total(input+output)/elapsed/GPU;
// stored directly in the benchmarks file (= output tok/s/GPU × (isl+osl)/osl).
["tokens_per_sec_per_gpu", "throughput per gpu", "tok/s"],
["interactivity", "interactivity", "tokens/s/user",
(m) => (m.tpot_ms != null && m.tpot_ms !== 0)
? Math.round((1000 / m.tpot_ms) * 10) / 10
: null],
];
const WORKLOAD_KEYS = ["dataset", "isl", "osl", "max_concurrency"];
const fmt = (val, unit) => {
if (val === null || val === undefined) return null;
return `${val}${unit ? " " + unit : ""}`;
};
// Format a subset of workload keys into a comma-separated phrase.
const formatWorkloadParts = (workload, keys) => {
if (!workload) return "";
const parts = [];
if (keys.has("dataset") && workload.dataset) parts.push(workload.dataset);
// in/out rendered as one token even if only one of isl/osl is present.
if (keys.has("isl") || keys.has("osl")) {
if (workload.isl != null || workload.osl != null) {
parts.push(`in/out=${workload.isl != null ? workload.isl : "?"}/${workload.osl != null ? workload.osl : "?"}`);
}
}
if (keys.has("max_concurrency") && workload.max_concurrency != null) {
parts.push(`max-concurrency=${workload.max_concurrency}`);
}
return parts.join(", ");
};
// Split workload fields into shared (uniform → context line) vs differing
// (→ per-column header). max_concurrency is always per-column.
const ALWAYS_PER_COLUMN = new Set(["max_concurrency"]);
const partitionWorkload = (measurements) => {
const shared = new Set();
const differing = new Set();
for (const k of WORKLOAD_KEYS) {
const seen = new Set();
let anyPresent = false;
for (const m of measurements) {
const v = m && m.workload ? m.workload[k] : undefined;
if (v != null) anyPresent = true;
seen.add(v);
}
if (!anyPresent) continue;
if (ALWAYS_PER_COLUMN.has(k) || seen.size > 1) differing.add(k);
else shared.add(k);
}
return { shared, differing };
};
const renderBenchTable = ({ title, sharedText, colHeaders, rows, colCount, legend }) => {
if (rows.length === 0) return null;
const showColHeaders = colHeaders.length > 0
&& colHeaders.some((h) => h !== "");
return (
<div style={s.benchBlock}>
<div style={s.benchBlockTitle}>{title}</div>
{sharedText && (
<div style={s.benchWorkload}>{sharedText}</div>
)}
<div
style={{
...s.benchTable,
gridTemplateColumns:
`max-content repeat(${colCount}, minmax(0, 1fr))`,
}}
>
{showColHeaders && (
<div key="corner" style={s.benchTableCornerHead}></div>
)}
{showColHeaders && colHeaders.map((h, i) => (
<div key={`hdr-${i}`} style={s.benchTableHead}>{h}</div>
))}
{showColHeaders && (
<div key="sep" style={s.benchTableSeparator}></div>
)}
{rows.map((r) => [
<div key={`lbl-${r.label}`} style={s.benchTableLabel}>{r.label}</div>,
...r.values.map((v, i) => (
<div key={`val-${r.label}-${i}`} style={
v === null
? { ...s.benchTableValue, ...s.benchTableValueMissing }
: s.benchTableValue
}>
{v !== null ? v : "—"}
</div>
)),
])}
</div>
{legend && (
<div style={s.benchLegend}>
{(Array.isArray(legend) ? legend : [legend]).map((line, i) => (
<div key={`legend-${i}`}>{line}</div>
))}
</div>
)}
</div>
);
};
// All four metric rows always render (unmeasured cells show "—") so the
// table shape is identical across every cell.
const buildSpeedTable = (measurements) => {
if (measurements.length === 0) return null;
const { shared, differing } = partitionWorkload(measurements);
const sharedText = formatWorkloadParts(
measurements[0] && measurements[0].workload, shared);
const colHeaders = measurements.map((m) =>
formatWorkloadParts(m && m.workload, differing));
const rows = SPEED_LABELS.map((tup) => {
const [key, label, unit, compute] = tup;
const values = measurements.map((m) => {
const raw = compute ? compute(m) : m[key];
return fmt(raw, unit);
});
return { label, values };
});
return { title: "Speed", sharedText, colHeaders, rows,
colCount: measurements.length,
legend: [
`throughput per gpu = (input+output tokens)/elapsed/GPU`,
`interactivity = 1000/TPOT(ms) (tokens/s/user)`,
] };
};
// One row per ACCURACY_LABELS entry with a non-null value; single value column.
const buildAccuracyTable = (accuracy) => {
if (!accuracy) return null;
const rows = ACCURACY_LABELS
.map(([key, label, unit]) => {
const v = fmt(accuracy[key], unit);
if (v === null) return null;
return { label, values: [v] };
})
.filter((r) => r !== null);
if (rows.length === 0) return null;
return { title: "Accuracy", sharedText: null, colHeaders: [],
rows, colCount: 1 };
};
const accuracy = effectiveAccuracy(entry, sel);
const isEmpty = benchmarkIsEmpty(entry, accuracy);
const measurements = !isEmpty ? normalizeSpeed(entry && entry.speed) : [];
const accuracyTable = !isEmpty ? buildAccuracyTable(accuracy) : null;
const speedTable = !isEmpty ? buildSpeedTable(measurements) : null;
const hasBenchCmds = !isEmpty && buildBenchCommands(entry, sel) !== null;
return (
<div style={s.benchCard}>
<div style={s.benchHeader}>
<div style={s.benchTitle}>Benchmark</div>
<div style={s.benchHeaderRight}>
{!isEmpty && entry && entry.sglang_version && (
<div style={s.benchVersion}>measured on sglang <code>{entry.sglang_version}</code></div>
)}
{hasBenchCmds && (
<button style={s.iconButton} onClick={() => setModal("bench")}> Reproduce</button>
)}
</div>
</div>
{isEmpty ? (
<div style={s.benchEmpty}>
Benchmark data pending for this combination submit yours via the Playground's Submit ↗ button.
</div>
) : (
<>
{accuracyTable && renderBenchTable(accuracyTable)}
{speedTable && renderBenchTable(speedTable)}
{entry && entry.notes && (
<div style={s.benchNotes}>{entry.notes}</div>
)}
</>
)}
</div>
);
};
// Build "⚡ Reproduce" modal data (raw templates + fill metadata). The {{...}}
// interpolation happens in the modal where `env` is in scope. Returns null
// when nothing is renderable (caller hides the button).
const buildBenchCommands = (entry, sel) => {
const bc = config.benchmarkCommands;
if (!bc) return null;
// One entry per eval with a value AND a template. A template is a string,
// or a {[variant]: string} object resolved by sel.variant.
const acc = effectiveAccuracy(entry, sel);
const accuracy = [];
if (bc.accuracy) {
for (const [key, label] of ACCURACY_LABELS) {
if (acc[key] == null) continue;
const tmpl = bc.accuracy[key];
const resolved = (typeof tmpl === "string")
? tmpl
: (tmpl && tmpl[sel.variant]) || null;
if (resolved) accuracy.push({ key, label, template: resolved });
}
}
let speed = null;
if (bc.speed && entry) {
const ms = normalizeSpeed(entry.speed)
.filter((m) => m && m.workload && m.workload.max_concurrency != null);
const concurrencies = [...new Set(ms.map((m) => m.workload.max_concurrency))]
.sort((a, b) => a - b);
if (concurrencies.length) {
speed = {
template: bc.speed,
concurrencies,
workload: ms[0].workload,
// {{NUM_PROMPTS}} priority: per-row override → numPromptsByConc[c]
// → max(c*2, 200).
numPromptsOf: (c) => {
const m = ms.find((x) => x.workload.max_concurrency === c);
if (m && m.workload.num_prompts != null) return m.workload.num_prompts;
const tbl = bc.numPromptsByConc;
if (tbl && tbl[c] != null) return tbl[c];
return Math.max(c * 2, 200);
},
};
}
}
if (accuracy.length === 0 && !speed) return null;
return { accuracy, speed };
};
const buildHardwareGroups = () => {
const supported = new Set(config.supportedHardware);
// Effective catalog = shared common GPUs + the model's own `config.hardware`
// (model-specific / desktop / future GPUs the shared catalog doesn't carry).
// A model-specific GPU is therefore pure config data — no engine-catalog edit.
const catalog = {};
for (const [vendor, list] of Object.entries(HARDWARE_CATALOG)) catalog[vendor] = [...list];
for (const hw of (config.hardware || [])) {
const vendor = hw.vendor || "nvidia";
const list = catalog[vendor] || (catalog[vendor] = []);
const entry = { id: hw.id, label: hw.label, vram: hw.vram };
const i = list.findIndex((x) => x.id === hw.id);
if (i >= 0) list[i] = entry; else list.push(entry); // config overrides by id
}
const groups = [];
for (const [vendor, list] of Object.entries(catalog)) {
const items = list.filter((hw) => supported.has(hw.id))
.map((hw) => ({ id: hw.id, label: hw.label, subtitle: hw.vram }));
if (items.length) groups.push({ label: vendor.toUpperCase(), items });
}
if (config.groupHardware === false) {
return [{ label: null, items: groups.flatMap((group) => group.items) }];
}
return groups;
};
// Match dims seed from the first cell (authoring convention: put the flagship
// verified cell first). Overlay dims seed from their own `default`, or the
// first option, since no cell carries them.
const initialSelectionFromCells = () => {
const first = (config.cells || [])[0];
const sel = Object.fromEntries(
DIMENSIONS.map((d) => [d, first ? first.match[d] : ""]),
);
for (const spec of overlayDimSpecs) {
const opts = spec.options || [];
sel[spec.id] = spec.default ?? (opts[0] && opts[0].id) ?? "";
}
if (!commandBuilder) return sel;
return {
...sel,
hw: commandBuilder.defaultSelection?.hw || config.supportedHardware?.[0] || "",
...(commandBuilder.defaultSelection || {}),
};
};
// Builder hashes are semantic rather than cell ids. Keep known dimension
// values, clamp bounded resources, and discard stale topology overrides.
// UI state (active scope, expanded cards, head IP, node rank) is deliberately
// absent from this object, so shared links stay portable and credential-free.
const normalizeBuilderSelection = (parsed) => {
const out = { ...initialSelectionFromCells(), ...parsed };
if (!(config.supportedHardware || []).includes(out.hw)) {
out.hw = commandBuilder.defaultSelection?.hw || config.supportedHardware?.[0] || "";
}
for (const spec of overlayDimSpecs) {
if (spec.kind === "number") {
const value = Number.parseInt(out[spec.id], 10);
out[spec.id] = Math.min(
spec.max,
Math.max(spec.min, Number.isFinite(value) ? value : Number(spec.default ?? spec.min)),
);
continue;
}
const options = spec.options || [];
if (!options.some((option) => option.id === out[spec.id])) {
out[spec.id] = spec.default ?? options[0]?.id ?? "";
}
}
for (const [key, bounds] of Object.entries(commandBuilder.resource?.limits || {})) {
const fallback = Number(commandBuilder.defaultSelection?.[key] ?? bounds.min ?? 1);
const value = Number.parseInt(out[key], 10);
out[key] = Math.min(bounds.max, Math.max(bounds.min, Number.isFinite(value) ? value : fallback));
}
for (const key of ["tp_size", "ulysses_degree", "ring_degree"]) {
const value = Number.parseInt(out[key], 10);
out[key] = Number.isFinite(value) && value > 0 ? value : 1;
}
out.topology_mode = out.topology_mode === "manual" ? "manual" : "auto";
return out;
};
const placeholderDefaults = (schema) => {
const out = {};
for (const [k, v] of Object.entries(schema || {})) out[k] = v.default ?? "";
return out;
};
// ==== 4. React state + effects ====
const [isDark, setIsDark] = useState(false);
useEffect(() => {
const check = () => {
const html = document.documentElement;
setIsDark(
html.classList.contains("dark") ||
html.getAttribute("data-theme") === "dark" ||
html.style.colorScheme === "dark"
);
};
check();
const observer = new MutationObserver(check);
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ["class", "data-theme", "style"],
});
return () => observer.disconnect();
}, []);
const STORAGE_KEY = "sglang-deploy-env";
const [env, setEnv] = useState(() => placeholderDefaults(config.placeholders));
useEffect(() => {
try {
const raw = window.localStorage.getItem(STORAGE_KEY);
if (raw) {
const parsed = JSON.parse(raw);
setEnv({ ...placeholderDefaults(config.placeholders), ...parsed });
}
} catch {}
}, []);
const saveEnv = (next) => {
setEnv(next);
try { window.localStorage.setItem(STORAGE_KEY, JSON.stringify(next)); } catch {}
};
const [sel, setSel] = useState(() => initialSelectionFromCells());
const INTERNAL_HASH_STATE_KEY = "__sglangDeployInternalHash";
const DEPLOYMENT_COMPONENT_ID = "deployment-configurator";
useEffect(() => {
const hydrate = () => {
const raw = window.location.hash.replace(/^#/, "");
if (!raw) return;
const params = new URLSearchParams(raw);
const initial = initialSelectionFromCells();
const parsed = { ...initial };
let touched = false;
params.forEach((value, key) => {
if (key in parsed) { parsed[key] = value; touched = true; }
});
if (!touched) return;
// Cell configs snap to a real recipe; builders normalize their semantic
// resource state without forcing a custom-but-valid topology to a preset.
setSel(
commandBuilder
? normalizeBuilderSelection(parsed)
: validateSelection(config.cells, parsed),
);
const historyState = window.history.state;
const isInternalHash =
historyState &&
typeof historyState === "object" &&
historyState[INTERNAL_HASH_STATE_KEY] === `#${raw}`;
if (isInternalHash) return;
// External selection hashes land on the interactive configurator. Hashes
// written internally while initializing or changing chips do not scroll.
const el = document.getElementById(DEPLOYMENT_COMPONENT_ID);
if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
};
hydrate();
window.addEventListener("hashchange", hydrate);
return () => window.removeEventListener("hashchange", hydrate);
}, []);
// history.replaceState does NOT fire hashchange — dispatch a custom event so
// the Playground hears chip-click selection changes.
useEffect(() => {
const target = "#" + new URLSearchParams(sel).toString();
if (window.location.hash !== target) {
const historyState =
window.history.state && typeof window.history.state === "object"
? window.history.state
: {};
window.history.replaceState(
{ ...historyState, [INTERNAL_HASH_STATE_KEY]: target },
"",
target
);
}
window.dispatchEvent(new CustomEvent("sglang-deploy-sel", { detail: sel }));
}, [sel]);
const [modal, setModal] = useState(null); // 'curl' | 'env' | 'bench' | null
useEffect(() => {
if (modal === null) return;
const onKey = (e) => { if (e.key === "Escape") setModal(null); };
const prev = document.body.style.overflow;
document.body.style.overflow = "hidden";
window.addEventListener("keydown", onKey);
return () => {
window.removeEventListener("keydown", onKey);
document.body.style.overflow = prev;
};
}, [modal]);
const [copied, setCopied] = useState(false);
const [curlCopied, setCurlCopied] = useState(false);
const [envDraft, setEnvDraft] = useState(env);
// "⚡ Reproduce" modal: chip-selected concurrency / eval / last-copied block.
// null falls back to the first option in the render.
const [benchConc, setBenchConc] = useState(null);
const [benchAcc, setBenchAcc] = useState(null);
const [benchCopied, setBenchCopied] = useState(null);
const configuredRunModes = typeof config.runModes === "function"
? config.runModes(sel)
: config.runModes;
const runModes = configuredRunModes || ["python", "docker"];
const [runMode, setRunMode] = useState(runModes[0]); // "python" | "docker"
const [builderScope, setBuilderScope] = useState("base");
const [builderServerSetting, setBuilderServerSetting] = useState(null);
const [builderAdvanced, setBuilderAdvanced] = useState(false);
const [serveExpanded, setServeExpanded] = useState(false);
const [requestExpanded, setRequestExpanded] = useState(false);
const [builderHeadAddress, setBuilderHeadAddress] = useState("<head-node-ip>");
const [builderNodeRank, setBuilderNodeRank] = useState(0);
// Tapping a disabled option surfaces its reason under the row — hover-only
// tooltips never reach touch readers. {dim, reason}; each note clears only
// itself, so a newer note is never cut short by an older timer.
const [blockedNote, setBlockedNote] = useState(null);
const flashBlockedNote = (dim, reason) => {
const note = { dim, reason };
setBlockedNote(note);
setTimeout(() => setBlockedNote((cur) => (cur === note ? null : cur)), 4000);
};
useEffect(() => {
if (builderNodeRank >= Number(sel.nodes || 1)) setBuilderNodeRank(0);
}, [sel.nodes, builderNodeRank]);
const hasRunMode = runModes.includes(runMode);
const fallbackRunMode = runModes[0];
const activeRunMode = hasRunMode ? runMode : fallbackRunMode;
useEffect(() => {
if (!hasRunMode) setRunMode(fallbackRunMode);
}, [hasRunMode, fallbackRunMode]);
useEffect(() => { if (modal === "env") setEnvDraft(env); }, [modal, env]);
// Live --mamba-full-memory-ratio from the ratio calculator (K3 pages):
// pool sizing is consolidated into this one flag, computed from the
// calculator's request length plus the current panel selection.
const [mambaRatio, setMambaRatio] = useState(null);
useEffect(() => {
// Deploy shows base flags only, so it takes the base-config ratio (the
// effective one belongs to the playground's composed command).
const onRatio = (e) =>
setMambaRatio((e.detail && (e.detail.baseRatio || e.detail.ratio)) || null);
window.addEventListener("sglang-k3-mamba-ratio", onRatio);
return () => window.removeEventListener("sglang-k3-mamba-ratio", onRatio);
}, []);
// ==== 5. Derived values ====
const s = makeStyles(isDark);
const cell = commandBuilder
? commandBuilder.resolveDeployment(sel)
: findCell(config.cells, sel);
const builderMeta = (cell && cell.builder) || {};
const verifyStatus = cellVerifyStatus(cell, sel);
// Pin the calculator-computed ratio into the rendered command (before the
// host/port tail); cells themselves stay ratio-free. Cells sizing the pool
// with --max-mamba-cache-size opt out.
const cellWithRatio = (() => {
if (!cell || !mambaRatio) return cell;
if (cell.flags.some((f) =>
f.startsWith("--mamba-full-memory-ratio") || f.startsWith("--max-mamba-cache-size"))) return cell;
const flags = [...cell.flags];
const line = `--mamba-full-memory-ratio ${mambaRatio}`;
const i = flags.findIndex((f) => f.startsWith("--host"));
if (i >= 0) flags.splice(i, 0, line);
else flags.push(line);
return { ...cell, flags };
})();
const commandEnv = commandBuilder
? {
...env,
NODE_RANK: String(builderNodeRank),
NODE0_IP: builderHeadAddress || "<head-node-ip>",
}
: env;
const command = renderCommand(cellWithRatio, sel, commandEnv, activeRunMode);
// Speculative-decoding hint on the EFFECTIVE flags — speculation can arrive via
// the Spec Decode overlay as well as the cell. SGLang resets
// --max-running-requests to 48 when spec is on and it's unset; verified for both
// EAGLE/MTP and DSPARK (server_args reports max_running_requests=48 either way).
const effFlags = cell ? overlayCompose(cell.flags, sel) : [];
const specAlgoFlag = effFlags.find(
(f) => f.split(/[\s=]/)[0] === "--speculative-algorithm");
const specMrrFlag = effFlags.find(
(f) => f.split(/[\s=]/)[0] === "--max-running-requests");
// Two cases, both worth surfacing when speculation is on:
// mtpHint — the flag is MISSING, so SGLang silently caps at 48 (a hazard)
// specPinnedHint— the recipe PINS it, which is safe but is a fixed number the
// reader still has to match to their own concurrency
const mtpHint = !!specAlgoFlag && !specMrrFlag;
const specPinnedHint = !!specAlgoFlag && !!specMrrFlag;
const specMrrValue = specMrrFlag
? (specMrrFlag.split(/[\s=]/).filter(Boolean)[1] || "")
: "";
// Name the algorithm in the banner rather than hardcoding "MTP" — the same reset
// applies to DSpark and friends, and a DSpark user reading "(MTP)" would be
// misled. The cookbook calls the EAGLE-based path MTP, so keep that mapping.
const SPEC_ALGO_LABEL = {
EAGLE: "MTP", EAGLE3: "MTP", FROZEN_KV_MTP: "MTP",
DSPARK: "DSpark", DFLASH: "DFlash", NGRAM: "N-gram",
STANDALONE: "standalone draft",
};
const specAlgoName = (() => {
if (!specAlgoFlag) return "MTP";
const v = specAlgoFlag.split(/[\s=]/).filter(Boolean)[1] || "";
return SPEC_ALGO_LABEL[v.toUpperCase()] || v || "MTP";
})();
// cell.warn may embed [label](#anchor) links — rendered as scrollIntoView
// buttons, not hrefs, so the hash (which carries the selection) isn't overwritten.
const renderWarn = (text) => {
const out = [];
const re = /\[([^\]]+)\]\(#([^)]+)\)/g;
let last = 0;
for (let m; (m = re.exec(text)); last = m.index + m[0].length) {
if (m.index > last) out.push(text.slice(last, m.index));
const anchor = m[2];
out.push(
<button
key={m.index}
type="button"
onClick={() => {
const el = document.getElementById(anchor);
if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
}}
style={{
background: "transparent",
border: "none",
padding: 0,
color: isDark ? "#FDBA74" : "#C2410C",
cursor: "pointer",
font: "inherit",
fontWeight: 600,
textDecoration: "underline",
textUnderlineOffset: "2px",
}}
>
{m[1]}
</button>
);
}
if (last < text.length) out.push(text.slice(last));
return out;
};
const modelName = resolveModelName(sel);
const curlTemplate =
typeof config.curl === "function" ? config.curl(sel, cell) : config.curl;
const curlText = interpolate(curlTemplate || "", env, modelName);
const hwGroups = buildHardwareGroups();
const benchEntry = benchmarks ? findBenchmark(benchmarks, sel) : null;
// Overlay dims have no cells to constrain them, so an option is selectable
// unless it says otherwise; only match dims get the grey-out scan.
const isOverlayDim = (dim) => overlayDimSpecs.some((d) => d.id === dim);
const findOption = (dim, value) => {
const spec = [...matchDimSpecs, ...overlayDimSpecs].find((d) => d.id === dim);
return spec && (spec.options || []).find((o) => o.id === value);
};
const isEnabled = (dim, value) => {
const opt = findOption(dim, value);
if (opt && optionDisabled(opt, sel)) return false;
if (commandBuilder && dim === "hw") return true;
return isOverlayDim(dim) || isOptionAvailable(config.cells || [], sel, dim, value);
};
// Switching a match dim can hide the option a dependent row currently holds
// (Strategy's option set differs per PD mode). Re-seat any overlay/match pick
// that just became invisible onto the first visible option of its row.
const reseatHiddenPicks = (next) => {
let out = next;
for (const spec of [...matchDimSpecs, ...overlayDimSpecs]) {
const opts = visibleOptions(spec, out).filter((o) => !optionDisabled(o, out));
if (!opts.length) continue;
if (!opts.some((o) => o.id === out[spec.id])) {
out = { ...out, [spec.id]: opts[0].id };
}
}
return out;
};
const recommendedBuilderRecipe = (hw) => {
const recipes = commandBuilder.resource?.verifiedRecipes || [];
return recipes.find((entry) => entry.hw === hw && entry.default)
|| recipes.find((entry) => entry.hw === hw);
};
const handleSelect = (dim, value) => {
if (commandBuilder) {
setSel((prev) => {
let next = { ...prev, [dim]: value };
if (dim === "hw") {
const currentRecipe = recommendedBuilderRecipe(prev.hw);
const nextRecipe = recommendedBuilderRecipe(value);
const resourcesFollowPlatformDefault = !!currentRecipe
&& Number(prev.nodes) === Number(currentRecipe.nodes)
&& Number(prev.gpus_per_node) === Number(currentRecipe.gpus_per_node);
next = {
...next,
nodes: resourcesFollowPlatformDefault
? (nextRecipe?.nodes ?? next.nodes)
: next.nodes,
gpus_per_node: resourcesFollowPlatformDefault
? (nextRecipe?.gpus_per_node ?? next.gpus_per_node)
: next.gpus_per_node,
topology_mode: "auto",
tp_size: resourcesFollowPlatformDefault
? (nextRecipe?.tp_size ?? 1)
: next.tp_size,
ulysses_degree: resourcesFollowPlatformDefault
? (nextRecipe?.ulysses_degree ?? 1)
: next.ulysses_degree,
ring_degree: resourcesFollowPlatformDefault
? (nextRecipe?.ring_degree ?? 1)
: next.ring_degree,
// Placement and encoder are per-hardware recipe facts just like
// the resource shape: keeping the previous card's picks produces
// a command the new card cannot run (e.g. a resident 61.7 GB DiT
// on a single consumer GPU) shown as "unverified".
placement: resourcesFollowPlatformDefault
? (nextRecipe?.placement || "auto")
: next.placement,
encoder: resourcesFollowPlatformDefault
? (nextRecipe?.encoder || "auto")
: next.encoder,
};
}
return reseatHiddenPicks(normalizeBuilderSelection(next));
});
return;
}
setSel((prev) =>
reseatHiddenPicks(
isOverlayDim(dim)
? { ...prev, [dim]: value }
: snapToValidCell(config.cells, prev, dim, value),
),
);
};
const commitBuilderNumber = (event, currentValue, bounds, commit) => {
const parsed = Number(event.currentTarget.value);
if (!Number.isInteger(parsed)) {
event.currentTarget.value = String(currentValue);
return;
}
const value = Math.min(bounds.max, Math.max(bounds.min, parsed));
event.currentTarget.value = String(value);
commit(value);
};
const renderBuilderNumberInput = ({ identity, value, min, max, label, onCommit }) => (
<input
key={identity}
type="number"
inputMode="numeric"
min={min}
max={max}
step="1"
defaultValue={value}
aria-label={label}
onFocus={(event) => event.currentTarget.select()}
onBlur={(event) => commitBuilderNumber(
event,
value,
{ min, max },
onCommit,
)}
onKeyDown={(event) => {
if (event.key === "Enter") event.currentTarget.blur();
}}
/>
);
const updateBuilderResource = (key, delta) => {
if (!commandBuilder) return;
const bounds = commandBuilder.resource?.limits?.[key] || { min: 1, max: 8 };
setSel((prev) => {
const value = Math.min(bounds.max, Math.max(bounds.min, Number(prev[key]) + delta));
return normalizeBuilderSelection({ ...prev, [key]: value, topology_mode: "auto" });
});
};
const setBuilderResource = (key, rawValue) => {
if (!commandBuilder) return;
const value = Number.parseInt(rawValue, 10);
if (!Number.isFinite(value)) return;
const bounds = commandBuilder.resource?.limits?.[key] || { min: 1, max: 8 };
setSel((prev) => normalizeBuilderSelection({
...prev,
[key]: Math.min(bounds.max, Math.max(bounds.min, value)),
topology_mode: "auto",
}));
};
const editBuilderTopology = (key, value) => {
if (!commandBuilder) return;
setSel((prev) => normalizeBuilderSelection({
...prev,
topology_mode: "manual",
[key]: Number.parseInt(value, 10) || 1,
}));
};
const handleCopy = () => {
navigator.clipboard.writeText(command);
setCopied(true);
setTimeout(() => setCopied(false), 1200);
};
const copyCurl = () => {
navigator.clipboard.writeText(curlText);
setCurlCopied(true);
setTimeout(() => setCurlCopied(false), 1200);
};
// `key` identifies which Reproduce-modal block flashed "✓ Copied".
const copyBench = (key, text) => {
navigator.clipboard.writeText(text);
setBenchCopied(key);
setTimeout(() => setBenchCopied(null), 1200);
};
// Group placeholders by `target` for the Env modal.
const placeholderGroups = (() => {
const out = { command: [], curl: [] };
for (const [key, meta] of Object.entries(config.placeholders || {})) {
(out[meta.target] || (out[meta.target] = [])).push({ key, ...meta });
}
return out;
})();
// ==== 6. JSX render ====
const renderButton = (item, dim, selectedId) => {
const checked = selectedId === item.id;
const disabled = !isEnabled(dim, item.id);
return (
<label
key={item.id}
className="sg-command-visualizer-choice"
role="radio"
aria-checked={checked}
aria-disabled={disabled}
tabIndex={disabled ? -1 : 0}
style={{
...s.labelBase,
...(checked ? s.checked : {}),
...(disabled ? s.disabled : {}),
}}
title={
disabled
? (typeof item.disableReason === "function"
? item.disableReason(sel)
: item.disableReason) || "Not supported for current selection"
: ""
}
onClick={(e) => {
if (disabled) { e.preventDefault(); return; }
handleSelect(dim, item.id);
}}
onKeyDown={(e) => {
if (disabled || (e.key !== "Enter" && e.key !== " ")) return;
e.preventDefault();
handleSelect(dim, item.id);
}}
>
<input type="radio" checked={checked} disabled={disabled} readOnly style={{ display: "none" }} />
<span>{item.label}</span>
{item.subtitle && (
<small style={{ ...s.subtitle, color: checked ? "rgba(255,255,255,0.85)" : "inherit" }}>
{item.subtitle}
</small>
)}
</label>
);
};
const renderFlatSection = (title, options, dim, selectedId) => (
<div style={s.card}>
<div style={s.title}>{title}</div>
<div style={s.itemsGrid(options.length)}>
{options.map((item) => renderButton(item, dim, selectedId))}
</div>
</div>
);
const maxHwCols = Math.max(...hwGroups.map((x) => x.items.length));
if (commandBuilder) {
const scopeLabel = { base: "Setup", serve: "Server", request: "Request" };
const scopedDims = (scope) => overlayDimSpecs.filter((dim) => {
if ((dim.scope || "base") !== scope) return false;
if (dim.kind === "number") {
return typeof dim.showWhen !== "function" || dim.showWhen(sel);
}
return rowVisible(dim, sel);
});
const baseDims = scopedDims("base");
const serveDims = scopedDims("serve");
const requestDims = scopedDims("request");
const errors = builderMeta.errors || [];
const warnings = builderMeta.warnings || [];
const invalid = errors.length > 0;
const totalGpus = Number(sel.nodes) * Number(sel.gpus_per_node);
const topology = builderMeta.topology || {};
const verification = builderMeta.verification || {};
const scopeIsVerified = (scope) => scopedDims(scope).every((dim) => {
const option = (dim.options || []).find((entry) => entry.id === sel[dim.id]);
// A pick whose `soft` predicate is active is by definition outside the
// verified matrix — the scope badge must not keep reading Verified.
if (option && optionSoft(option, sel)) return false;
const predicate = option?.verifiedWhen ?? dim.verifiedWhen;
return typeof predicate === "function" ? !!predicate(sel) : predicate !== false;
});
const serveStatus = invalid
? "error"
: (scopeIsVerified("serve") ? (verification.serve || verifyStatus) : "unverified");
const requestStatus = invalid
? "error"
: (scopeIsVerified("request") ? (verification.request || verifyStatus) : "unverified");
const statusText = (status) => ({
verified: "Verified",
unverified: "Unverified",
"in-progress": "Verification in progress",
error: "Invalid configuration",
}[status] || "Unverified");
const activeServerSetting = serveDims.find((dim) => dim.id === builderServerSetting) || serveDims[0];
const selectedOption = (dim) => (dim.options || []).find((option) => option.id === sel[dim.id]);
const effectiveSetting = (dim) =>
builderMeta.resolvedSettings?.[dim.id]
|| selectedOption(dim)?.label
|| sel[dim.id]
|| "—";
const recommendedRecipe = recommendedBuilderRecipe(sel.hw);
const recommendedInUse = !!recommendedRecipe
&& Number(sel.nodes) === recommendedRecipe.nodes
&& Number(sel.gpus_per_node) === recommendedRecipe.gpus_per_node
&& sel.topology_mode === "auto"
&& ["auto", recommendedRecipe.placement].includes(sel.placement)
&& sel.attention === "platform"
&& sel.precision === "native"
&& ["auto", recommendedRecipe.encoder].includes(sel.encoder)
&& sel.execution === "eager";
const restoreRecommendedRecipe = () => {
if (!recommendedRecipe) return;
setSel((prev) => reseatHiddenPicks(normalizeBuilderSelection({
...prev,
nodes: recommendedRecipe.nodes,
gpus_per_node: recommendedRecipe.gpus_per_node,
topology_mode: "auto",
tp_size: recommendedRecipe.tp_size,
ulysses_degree: recommendedRecipe.ulysses_degree,
ring_degree: recommendedRecipe.ring_degree,
placement: recommendedRecipe.placement || "auto",
attention: "platform",
precision: "native",
encoder: recommendedRecipe.encoder || "auto",
execution: "eager",
})));
};
const renderBuilderChoice = (item, dim) => {
const checked = sel[dim.id] === item.id;
const disabled = !isEnabled(dim.id, item.id);
const soft = !disabled && optionSoft(item, sel);
const reason = disabled
? item.disableReason || "Not available for this configuration"
: soft
? item.softReason || "Runs, but this combination is not a verified recipe yet."
: "";
// aria-disabled instead of the disabled attribute: the control stays
// focusable and hoverable, so the reason is reachable by tooltip, by
// keyboard, and by the tap-feedback note below the row.
return (
<button
key={item.id}
type="button"
className="sgd-builder-choice"
data-selected={checked ? "true" : "false"}
data-blocked={disabled ? "true" : undefined}
data-soft={soft ? "true" : undefined}
aria-disabled={disabled}
aria-pressed={checked}
title={reason}
onClick={() => {
if (disabled) { flashBlockedNote(dim.id, reason); return; }
handleSelect(dim.id, item.id);
}}
>
<span className="sgd-builder-choice-dot" aria-hidden="true" />
<span>{item.label}</span>
{item.subtitle && <small>{item.subtitle}</small>}
</button>
);
};
const renderBuilderDimension = (dim) => (
<section className="sgd-builder-section" key={dim.id}>
<div className="sgd-builder-section-heading">
<span>{dim.title}</span>
{dim.description && <small>{dim.description}</small>}
</div>
<div className="sgd-builder-choice-grid" data-density={(dim.options || []).length > 5 ? "compact" : "normal"}>
{visibleOptions(dim, sel).map((option) => renderBuilderChoice(option, dim))}
</div>
{blockedNote && blockedNote.dim === dim.id && (
<p className="sgd-builder-blocked-note" role="status">{blockedNote.reason}</p>
)}
</section>
);
const renderStepper = (key, label, detail) => {
const bounds = commandBuilder.resource?.limits?.[key] || { min: 1, max: 8 };
return (
<div className="sgd-builder-stepper-field">
<div>
<span>{label}</span>
{detail && <small>{detail}</small>}
</div>
<div className="sgd-builder-stepper" aria-label={label}>
<button
type="button"
aria-label={`Decrease ${label}`}
disabled={Number(sel[key]) <= bounds.min}
onClick={() => updateBuilderResource(key, -1)}
></button>
{renderBuilderNumberInput({
identity: `${key}-${sel[key]}`,
value: sel[key],
min: bounds.min,
max: bounds.max,
label,
onCommit: (value) => setBuilderResource(key, value),
})}
<button
type="button"
aria-label={`Increase ${label}`}
disabled={Number(sel[key]) >= bounds.max}
onClick={() => updateBuilderResource(key, 1)}
>+</button>
</div>
</div>
);
};
const renderBaseScope = () => (
<div className="sgd-builder-scope-panel" data-scope="base">
{recommendedRecipe && (
<section className="sgd-builder-recipe">
<div>
{/* This is the verified operating point, not sizing advice — a
hardware whose validation ran on 8 GPUs is not "recommending"
8 over a smaller deployment. */}
<span>{recommendedRecipe.unverified ? "Derived recipe" : "Verified recipe"} · {sel.hw.toUpperCase()}</span>
<strong>
{[
`${recommendedRecipe.nodes * recommendedRecipe.gpus_per_node} GPUs`,
recommendedRecipe.tp_size > 1 && `TP ${recommendedRecipe.tp_size}`,
`Ulysses ${recommendedRecipe.ulysses_degree}`,
recommendedRecipe.ring_degree > 1 && `Ring ${recommendedRecipe.ring_degree}`,
{ resident: "Resident", fsdp: "FSDP", offload: "Layerwise offload" }[recommendedRecipe.placement],
].filter(Boolean).join(" · ")}
</strong>
</div>
<div>
{renderStatus(recommendedRecipe.unverified ? "unverified" : "verified")}
{recommendedInUse
? <small>In use</small>
: <button type="button" className="sgd-builder-text-action" onClick={restoreRecommendedRecipe}>{recommendedRecipe.unverified ? "Use derived recipe" : "Use verified recipe"}</button>}
</div>
</section>
)}
<section className="sgd-builder-section">
<div className="sgd-builder-section-heading"><span>Hardware</span></div>
<div className="sgd-builder-hardware-grid">
{hwGroups.flatMap((group) => group.items).map((item) => {
const selected = sel.hw === item.id;
return (
<button
key={item.id}
type="button"
className="sgd-builder-hardware"
data-selected={selected ? "true" : "false"}
aria-pressed={selected}
onClick={() => handleSelect("hw", item.id)}
>
<span className="sgd-builder-choice-dot" aria-hidden="true" />
<strong>{item.label}</strong>
<small>{item.subtitle}</small>
</button>
);
})}
</div>
</section>
{/* Topology lives with Resources: its summary is the heading's detail
line, so the two rows that used to repeat each other are one
section. The advanced editor and its messages stay here too. */}
<section className="sgd-builder-section">
<div className="sgd-builder-section-heading">
<span>Resources</span>
<small>{builderMeta.topologySummary || "No valid topology"}</small>
</div>
<div className="sgd-builder-resource-grid">
{renderStepper("nodes", "Nodes")}
{renderStepper("gpus_per_node", "GPUs / node")}
</div>
{Number(sel.nodes) > 1 && (
<p className="sgd-builder-resource-summary">
{sel.nodes} nodes × {sel.gpus_per_node} {sel.hw.toUpperCase()} = {totalGpus} GPUs
</p>
)}
<button
type="button"
className="sgd-builder-text-action sgd-builder-topology-toggle"
aria-expanded={builderAdvanced}
onClick={() => setBuilderAdvanced((open) => !open)}
>
Advanced topology <span aria-hidden="true">{builderAdvanced ? "↗" : "↘"}</span>
</button>
{builderAdvanced && (
<div className="sgd-builder-advanced">
<p>Auto uses an exact verified recipe when one exists; manual values are allowed when the model constraints remain valid.</p>
<div className="sgd-builder-topology-inputs">
{[
["tp_size", "Tensor parallel", [1, 2, 4, 8]],
["ulysses_degree", "Ulysses", [1, 2, 4, 8, 16]],
["ring_degree", "Ring", [1, 2, 4, 8]],
].map(([key, label, values]) => (
<label key={key}>
<span>{label}</span>
<select
value={sel.topology_mode === "manual" ? sel[key] : (topology[key] || 1)}
onChange={(event) => editBuilderTopology(key, event.target.value)}
>
{values.map((value) => <option value={value} key={value}>{value}</option>)}
</select>
</label>
))}
</div>
<button
type="button"
className="sgd-builder-text-action"
disabled={sel.topology_mode === "auto"}
onClick={() => setSel((prev) => normalizeBuilderSelection({ ...prev, topology_mode: "auto" }))}
>Use automatic topology</button>
</div>
)}
{(errors.length > 0 || warnings.length > 0) && (
<div className="sgd-builder-messages" data-state={errors.length ? "error" : "warning"}>
{(errors.length ? errors : warnings).map((message, index) => <p key={index}>{message}</p>)}
</div>
)}
</section>
{baseDims.map(renderBuilderDimension)}
</div>
);
const renderSettingEditor = (dim, className = "", direct = false) => {
if (!dim) return null;
const options = visibleOptions(dim, sel);
const currentOption = selectedOption(dim);
return (
<section className={`sgd-builder-context ${className}`} aria-live={direct ? undefined : "polite"}>
<div className="sgd-builder-context-heading">
<div>
<span>{direct ? dim.title : `${dim.title} options`}</span>
{dim.description && <p>{dim.description}</p>}
</div>
{dim.quality && <small>{dim.quality}</small>}
</div>
{dim.kind === "number" ? (
<div className="sgd-builder-request-stepper">
<button
type="button"
aria-label={`Decrease ${dim.title}`}
disabled={Number(sel[dim.id]) <= dim.min}
onClick={() => setSel((prev) => ({
...prev,
[dim.id]: Math.max(dim.min, Number(prev[dim.id]) - 1),
}))}
></button>
{renderBuilderNumberInput({
identity: `${dim.id}-${sel[dim.id]}`,
value: sel[dim.id],
min: dim.min,
max: dim.max,
label: dim.title,
onCommit: (value) => setSel((prev) => ({ ...prev, [dim.id]: value })),
})}
<button
type="button"
aria-label={`Increase ${dim.title}`}
disabled={Number(sel[dim.id]) >= dim.max}
onClick={() => setSel((prev) => ({
...prev,
[dim.id]: Math.min(dim.max, Number(prev[dim.id]) + 1),
}))}
>+</button>
<span>{dim.unit || "outputs"}</span>
</div>
) : (
<div className="sgd-builder-context-options">
{options.map((option) => renderBuilderChoice(option, dim))}
</div>
)}
{blockedNote && blockedNote.dim === dim.id && (
<p className="sgd-builder-blocked-note" role="status">{blockedNote.reason}</p>
)}
{(currentOption?.description || dim.learnMore) && (
<div className="sgd-builder-context-note">
{currentOption?.description && <p>{currentOption.description}</p>}
{/* Icons name the destination: section lines = an anchor on
this page, book = the runtime documentation. */}
{dim.learnMore && (
<a href={dim.learnMore}>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true"><line x1="4" y1="6" x2="20" y2="6" /><line x1="4" y1="12" x2="16" y2="12" /><line x1="4" y1="18" x2="11" y2="18" /></svg>
Learn more
</a>
)}
{dim.docsHref && (
<a href={dim.docsHref}>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20" /><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z" /></svg>
SGLang docs
</a>
)}
</div>
)}
</section>
);
};
const renderServerScope = () => (
<div className="sgd-builder-scope-panel" data-scope="serve">
<div className="sgd-builder-setting-layout">
<div className="sgd-builder-setting-list">
{serveDims.map((dim) => {
const isActive = dim.id === activeServerSetting?.id;
const option = selectedOption(dim);
const recommended = typeof option?.recommendedWhen === "function"
? option.recommendedWhen(sel)
: !!option?.recommended;
return (
<div className="sgd-builder-setting-item" key={dim.id}>
<button
type="button"
className="sgd-builder-setting-row"
data-active={isActive ? "true" : "false"}
aria-expanded={isActive}
onClick={() => setBuilderServerSetting(dim.id)}
>
<span>{dim.title}</span>
<strong>{effectiveSetting(dim)}</strong>
{recommended && <small>Recommended</small>}
<span aria-hidden="true">{isActive ? "⌄" : ""}</span>
</button>
{isActive && renderSettingEditor(dim, "sgd-builder-context--inline")}
</div>
);
})}
</div>
{renderSettingEditor(activeServerSetting, "sgd-builder-context--rail")}
</div>
</div>
);
const renderRequestScope = () => (
<div className="sgd-builder-scope-panel sgd-builder-request-direct" data-scope="request">
{requestDims.map((dim) => (
<div className="sgd-builder-request-setting" key={dim.id}>
{renderSettingEditor(dim, "", true)}
</div>
))}
</div>
);
const renderScopeControls = () => {
if (builderScope === "base") return renderBaseScope();
if (builderScope === "serve") return renderServerScope();
return renderRequestScope();
};
const renderStatus = (status) => (
<span className="sgd-builder-status" data-status={status}>
<span aria-hidden="true" />{statusText(status)}
</span>
);
const renderOutputCard = (type) => {
const serve = type === "serve";
const text = serve ? command : curlText;
const canExpand = text.split("\n").length > 9;
const expanded = serve ? serveExpanded : requestExpanded;
const setExpanded = serve ? setServeExpanded : setRequestExpanded;
const status = serve ? serveStatus : requestStatus;
const emphasized = builderScope === "base" || builderScope === type;
return (
<section
className="sgd-builder-output"
data-output={type}
data-emphasized={emphasized ? "true" : "false"}
>
<header>
<div className="sgd-builder-output-index">{serve ? "1" : "2"}</div>
<div className="sgd-builder-output-title">
<strong>{serve ? "Serve" : "Request"}</strong>
<span>
{serve
? `${sel.hw.toUpperCase()} · ${activeRunMode === "docker" ? "Docker" : "Python"}`
: "cURL"}
</span>
</div>
{renderStatus(status)}
</header>
{serve && runModes.length > 1 && (
<div className="sgd-builder-output-tabs" role="tablist" aria-label="Serve command format">
{runModes.map((mode) => (
<button
type="button"
role="tab"
aria-selected={activeRunMode === mode}
data-selected={activeRunMode === mode ? "true" : "false"}
key={mode}
onClick={() => setRunMode(mode)}
>{mode === "docker" ? "Docker" : "Python"}</button>
))}
</div>
)}
{serve && Number(sel.nodes) > 1 && (
<div className="sgd-builder-node-fields">
<label>
<span>Head address</span>
<input value={builderHeadAddress} onChange={(event) => setBuilderHeadAddress(event.target.value)} />
</label>
<label>
<span>Node rank</span>
{renderBuilderNumberInput({
identity: `node-rank-${builderNodeRank}-${sel.nodes}`,
value: builderNodeRank,
min: 0,
max: Number(sel.nodes) - 1,
label: "Node rank",
onCommit: setBuilderNodeRank,
})}
</label>
</div>
)}
<div className="sgd-builder-code">
<pre className={expanded ? "is-expanded" : ""}><code>{text}</code></pre>
<button
type="button"
className="sgd-builder-copy"
disabled={invalid}
aria-label={(serve ? copied : curlCopied) ? "Copied" : "Copy command"}
data-copied={(serve ? copied : curlCopied) ? "true" : undefined}
onClick={serve ? handleCopy : copyCurl}
>
<svg className="sgd-builder-copy-glyph" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><rect x="9" y="9" width="12" height="12" rx="2.5" /><path d="M15 5v-.25A2.75 2.75 0 0 0 12.25 2h-7.5A2.75 2.75 0 0 0 2 4.75v7.5A2.75 2.75 0 0 0 4.75 15H5" /></svg>
<svg className="sgd-builder-copy-check" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>
</button>
</div>
{invalid && <div className="sgd-builder-output-error">{errors[0]}</div>}
<footer>
{canExpand && (
<button type="button" className="sgd-builder-text-action" onClick={() => setExpanded(!expanded)}>
{expanded ? "Collapse" : "Expand"}
</button>
)}
<div>
<button type="button" className="sgd-builder-text-action" onClick={() => setModal("env")}>Variables</button>
</div>
</footer>
</section>
);
};
return (
<section
id={DEPLOYMENT_COMPONENT_ID}
className="not-prose sg-command-visualizer sgd-command-builder"
style={{ scrollMarginTop: "104px" }}
aria-label={`${config.modelName} command builder`}
>
<nav className="sgd-builder-scope-tabs" role="tablist" aria-label="Command builder scope">
{["base", "serve", "request"].map((scope) => (
<button
type="button"
role="tab"
key={scope}
aria-label={scopeLabel[scope]}
aria-selected={builderScope === scope}
aria-controls={`${DEPLOYMENT_COMPONENT_ID}-controls`}
data-active={builderScope === scope ? "true" : "false"}
onClick={() => setBuilderScope(scope)}
>
{scopeLabel[scope]}
</button>
))}
</nav>
<div className="sgd-builder-main" data-scope={builderScope}>
<div
id={`${DEPLOYMENT_COMPONENT_ID}-controls`}
className="sgd-builder-controls"
role="tabpanel"
aria-label={`${scopeLabel[builderScope]} settings`}
>
{renderScopeControls()}
</div>
<div className="sgd-builder-output-rail">
{builderScope !== "request" && renderOutputCard("serve")}
{builderScope !== "serve" && renderOutputCard("request")}
</div>
</div>
{modal === "env" && (
<div style={s.modalBackdrop} onClick={() => setModal(null)}>
<div style={s.modalBox} onClick={(event) => event.stopPropagation()}>
<div style={s.modalHeader}>
<div style={s.modalTitle}>Command variables</div>
<button style={s.modalCloseBtn} onClick={() => setModal(null)} aria-label="Close">×</button>
</div>
{["command", "curl"].map((target) => placeholderGroups[target].length > 0 && (
<div key={target}>
<div style={s.sectionHeading}>{target === "command" ? "Serve" : "Request"}</div>
{placeholderGroups[target].map(({ key, label }) => (
<div key={key} style={s.formField}>
<label style={s.formLabel}>{label}</label>
<input
style={s.formInput}
value={envDraft[key] ?? ""}
onChange={(event) => setEnvDraft({ ...envDraft, [key]: event.target.value })}
/>
</div>
))}
</div>
))}
<div style={{ display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }}>
<button style={{ ...s.iconButton, padding: "6px 14px" }} onClick={() => setModal(null)}>Cancel</button>
<button style={s.primaryBtn} onClick={() => { saveEnv(envDraft); setModal(null); }}>Save</button>
</div>
</div>
</div>
)}
</section>
);
}
return (
<div
id={DEPLOYMENT_COMPONENT_ID}
style={{ ...s.container, scrollMarginTop: "104px" }}
className="not-prose sg-command-visualizer"
>
{/* Hardware section (2 vendor rows in one card, equal-width grid) */}
<div style={s.cardColumn}>
<div style={{ ...s.title, marginBottom: "2px" }}>Hardware Platform</div>
{hwGroups.map((g) => (
<div key={g.label || "hardware"} style={s.vendorRow}>
{g.label && <div style={s.vendorLabel}>{g.label}</div>}
<div style={s.itemsGrid(maxHwCols)}>
{g.items.map((item) => renderButton(item, "hw", sel.hw))}
{Array.from({ length: maxHwCols - g.items.length }).map((_, i) => (
<div key={`pad-${i}`} />
))}
</div>
</div>
))}
</div>
{matchDimSpecs
.filter((d) => rowVisible(d, sel))
.map((d) => (
<div key={d.id}>
{renderFlatSection(d.title, visibleOptions(d, sel), d.id, sel[d.id])}
</div>
))}
{overlayDimSpecs
.filter((d) => rowVisible(d, sel))
.map((d) => (
<div key={d.id}>
{renderFlatSection(d.title, visibleOptions(d, sel), d.id, sel[d.id])}
</div>
))}
{/* Command box */}
<div style={s.card}>
<div style={s.title}>Command:</div>
<div style={s.commandWrap}>
{cell && cell.redirect ? (
cell.warn && <div style={s.mtpWarn}>⚠️ {renderWarn(cell.warn)}</div>
) : (<>
<div style={s.commandHeader}>
<div style={s.headerLeft}>
<div style={s.badge(verifyStatus)}>
<span style={s.badgeDot(verifyStatus)} />
{VERIFY_LABEL[verifyStatus]}
</div>
<div style={s.runModeWrap} role="tablist" aria-label="Output format">
{runModes.map((mode, index) => (
<span
key={mode}
className="sg-command-visualizer-tab"
style={{
...(index === runModes.length - 1
? s.runModeChipLast(activeRunMode === mode)
: s.runModeChip(activeRunMode === mode)),
...(runModes.length === 1 ? { borderRadius: 7 } : {}),
}}
onClick={() => setRunMode(mode)}
onKeyDown={(e) => {
if (e.key !== "Enter" && e.key !== " ") return;
e.preventDefault();
setRunMode(mode);
}}
role="tab"
tabIndex={0}
aria-selected={activeRunMode === mode}
>
{mode === "docker" ? "Docker" : "Python"}
</span>
))}
</div>
</div>
<div style={s.iconRow}>
<button style={s.iconButton} onClick={handleCopy}>
{copied ? "✓ Copied" : "⧉ Copy"}
</button>
<button style={s.iconButton} onClick={() => setModal("curl")}>$ cURL</button>
<button style={s.iconButton} onClick={() => setModal("env")}> Env</button>
</div>
</div>
<pre style={s.commandPre}>{command}</pre>
{cell && cell.warn && <div style={s.mtpWarn}>⚠️ {renderWarn(cell.warn)}</div>}
{mtpHint && (
<div style={s.mtpWarn}>
⚠️ Speculative decoding ({specAlgoName}) is on SGLang resets <code>--max-running-requests</code> to <strong>48</strong> when it isn't set. Add <code>--max-running-requests &lt;N&gt;</code> sized for your target concurrency.
</div>
)}
{specPinnedHint && (
<div style={s.mtpWarn}>
️ Speculative decoding ({specAlgoName}) is on and this recipe pins <code>--max-running-requests</code> to <strong>{specMrrValue}</strong>. Adjust it to match your target concurrency — if you remove the flag, SGLang falls back to <strong>48</strong>.
</div>
)}
</>)}
</div>
</div>
{/* Benchmark card (only with a `benchmarks` prop + matched cell). */}
{benchmarks && cell && renderBenchmarkCard(benchEntry)}
{/* Playground link — scrollIntoView, not an href, so the hash (which
carries the selection) isn't overwritten. */}
{config.showPlaygroundLink !== false && (
<div
style={{
padding: "6px 12px",
fontSize: "12px",
color: isDark ? "#9ca3af" : "#6b7280",
display: "flex",
alignItems: "center",
gap: "6px",
}}
>
<span>Need to go beyond the verified matrix?</span>
<button
type="button"
onClick={() => {
const el = document.getElementById("playground");
if (el) el.scrollIntoView({ behavior: "smooth", block: "start" });
}}
style={{
background: "transparent",
border: "none",
padding: 0,
color: isDark ? "#FDBA74" : "#C2410C",
cursor: "pointer",
fontSize: "12px",
fontWeight: 600,
textDecoration: "underline",
textUnderlineOffset: "2px",
}}
>
Open the Playground
</button>
</div>
)}
{/* cURL modal */}
{modal === "curl" && (
<div style={s.modalBackdrop} onClick={() => setModal(null)}>
<div style={s.modalBox} onClick={(e) => e.stopPropagation()}>
<div style={s.modalHeader}>
<div style={s.modalTitle}>cURL example</div>
<button style={s.modalCloseBtn} onClick={() => setModal(null)} aria-label="Close">×</button>
</div>
<div style={s.commandWrap}>
<div style={s.commandHeader}>
<div style={{ fontSize: 11, opacity: 0.7 }}>
Model: <code>{modelName || "(unresolved)"}</code>
</div>
<button style={s.iconButton} onClick={copyCurl}>
{curlCopied ? "✓ Copied" : "⧉ Copy"}
</button>
</div>
<pre style={s.commandPre}>{curlText}</pre>
</div>
<p style={{ fontSize: 11, opacity: 0.7, marginTop: 8 }}>
Edit <code>CURL_HOST</code> / <code>CURL_PORT</code> in the Env panel.
</p>
</div>
</div>
)}
{/* Env modal */}
{modal === "env" && (
<div style={s.modalBackdrop} onClick={() => setModal(null)}>
<div style={s.modalBox} onClick={(e) => e.stopPropagation()}>
<div style={s.modalHeader}>
<div style={s.modalTitle}>Env / placeholder values</div>
<button style={s.modalCloseBtn} onClick={() => setModal(null)} aria-label="Close">×</button>
</div>
{placeholderGroups.curl.length > 0 && (
<div>
<div style={s.sectionHeading}>cURL placeholders</div>
{placeholderGroups.curl.map(({ key, label }) => (
<div key={key} style={s.formField}>
<label style={s.formLabel}>
{label} <code style={{ opacity: 0.6 }}>{`{{${key}}}`}</code>
</label>
<input
style={s.formInput}
value={envDraft[key] ?? ""}
onChange={(e) => setEnvDraft({ ...envDraft, [key]: e.target.value })}
/>
</div>
))}
</div>
)}
{placeholderGroups.command.length > 0 && (
<div>
<div style={s.sectionHeading}>Command placeholders</div>
{placeholderGroups.command.map(({ key, label }) => (
<div key={key} style={s.formField}>
<label style={s.formLabel}>
{label} <code style={{ opacity: 0.6 }}>{`{{${key}}}`}</code>
</label>
<input
style={s.formInput}
value={envDraft[key] ?? ""}
onChange={(e) => setEnvDraft({ ...envDraft, [key]: e.target.value })}
/>
</div>
))}
</div>
)}
<div style={{ display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }}>
<button style={{ ...s.iconButton, padding: "6px 14px" }} onClick={() => setModal(null)}>Cancel</button>
<button style={s.primaryBtn} onClick={() => { saveEnv(envDraft); setModal(null); }}>Save</button>
</div>
<p style={{ fontSize: 11, opacity: 0.7, marginTop: 10 }}>
Values persist in localStorage and are reused the next time you visit any cookbook.
</p>
</div>
</div>
)}
{/* "⚡ Reproduce" modal — benchmark commands for the current selection. */}
{modal === "bench" && benchEntry && (() => {
const bc = buildBenchCommands(benchEntry, sel);
if (!bc) return null;
const selSummary = [
sel.hw && sel.hw.toUpperCase(),
sel.variant,
sel.quant && sel.quant.toUpperCase(),
sel.strategy,
sel.kvDsaPair,
sel.nodes,
]
.filter((part) => part !== undefined && part !== null && part !== "")
.join(" · ");
let selConc = null;
let speedCmd = null;
if (bc.speed) {
selConc = bc.speed.concurrencies.includes(benchConc)
? benchConc : bc.speed.concurrencies[0];
const w = bc.speed.workload;
speedCmd = interpolate(bc.speed.template, {
...env,
DATASET: w.dataset,
ISL: w.isl,
OSL: w.osl,
MAX_CONCURRENCY: selConc,
NUM_PROMPTS: bc.speed.numPromptsOf(selConc),
}, modelName);
}
// Accuracy chip-selected; stale benchAcc falls back to the first eval.
let selAcc = null;
let accCmd = null;
if (bc.accuracy.length > 0) {
selAcc = bc.accuracy.find((a) => a.key === benchAcc) || bc.accuracy[0];
accCmd = interpolate(selAcc.template, env, modelName);
}
return (
<div style={s.modalBackdrop} onClick={() => setModal(null)}>
<div style={s.modalBox} onClick={(e) => e.stopPropagation()}>
<div style={s.modalHeader}>
<div style={s.modalTitle}>Benchmark commands</div>
<button style={s.modalCloseBtn} onClick={() => setModal(null)} aria-label="Close">×</button>
</div>
<p style={{ fontSize: 11, opacity: 0.7, margin: "0 0 12px" }}>
For <code>{selSummary}</code>. Start the server with the Deploy command above, then run these against it.
</p>
{selAcc && (
<div>
<div style={s.sectionHeading}>Accuracy</div>
{bc.accuracy.length > 1 && (
<div style={s.benchChipRow}>
<span style={{ fontSize: 11, opacity: 0.7 }}>benchmark:</span>
{bc.accuracy.map((a) => (
<button
key={a.key}
style={{ ...s.benchChip, ...(a.key === selAcc.key ? s.benchChipActive : {}) }}
onClick={() => setBenchAcc(a.key)}
>
{a.label}
</button>
))}
</div>
)}
<div style={{ ...s.commandWrap, marginBottom: 6 }}>
<div style={s.commandHeader}>
<div style={{ fontSize: 11, opacity: 0.7 }}>{selAcc.label}</div>
<button style={s.iconButton} onClick={() => copyBench("acc", accCmd)}>
{benchCopied === "acc" ? "✓ Copied" : "⧉ Copy"}
</button>
</div>
<pre style={s.commandPre}>{accCmd}</pre>
</div>
{bc.accuracy.length > 1 && (
<p style={{ fontSize: 11, opacity: 0.7, margin: "0 0 4px" }}>
Switch the benchmark chip to see each eval's command.
</p>
)}
</div>
)}
{bc.speed && (
<div>
<div style={s.sectionHeading}>Speed</div>
{bc.speed.concurrencies.length > 1 && (
<div style={s.benchChipRow}>
<span style={{ fontSize: 11, opacity: 0.7 }}>max-concurrency:</span>
{bc.speed.concurrencies.map((c) => (
<button
key={c}
style={{ ...s.benchChip, ...(c === selConc ? s.benchChipActive : {}) }}
onClick={() => setBenchConc(c)}
>
{c}
</button>
))}
</div>
)}
<div style={{ ...s.commandWrap, marginBottom: 6 }}>
<div style={s.commandHeader}>
<div style={{ fontSize: 11, opacity: 0.7 }}>max-concurrency = {selConc}</div>
<button style={s.iconButton} onClick={() => copyBench("speed", speedCmd)}>
{benchCopied === "speed" ? "✓ Copied" : "⧉ Copy"}
</button>
</div>
<pre style={s.commandPre}>{speedCmd}</pre>
</div>
<p style={{ fontSize: 11, opacity: 0.7, margin: "0 0 4px" }}>
One command switch the concurrency chip (or edit <code>--max-concurrency</code>) to reproduce each Speed column.
</p>
</div>
)}
<p style={{ fontSize: 11, opacity: 0.7, marginTop: 12 }}>
Edit <code>CURL_HOST</code> / <code>CURL_PORT</code> in the Env panel.
</p>
</div>
</div>
);
})()}
</div>
);
};