[docs] DeepSeek-V4 cookbook: balanced MegaMoE cap, H200 Pro FP4 mem-frac, nsa-* compat, PD-disagg fixes (#26164)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
1e59ed7443
commit
81cd338fcc
@@ -119,15 +119,23 @@ export const DeepSeekV4Deployment = () => {
|
|||||||
const MARLIN_EFFHW = new Set(["h200-fp4", "h100"]);
|
const MARLIN_EFFHW = new Set(["h200-fp4", "h100"]);
|
||||||
const MARLIN_LABEL = { "h200-fp4": "H200 (FP4)", h100: "H100 (FP4)" };
|
const MARLIN_LABEL = { "h200-fp4": "H200 (FP4)", h100: "H100 (FP4)" };
|
||||||
|
|
||||||
// MegaMoE is only supported on Blackwell with DeepEP-based recipes
|
// MegaMoE is only wired into the deepep-replacing recipes on Blackwell
|
||||||
// (balanced / max-throughput / pd-disagg). It's disabled on Hopper
|
// (balanced / max-throughput). Disabled on Hopper (H100 / H200, both FP4
|
||||||
// (H100 / H200, both FP4 and FP8) and on low-latency / cp recipes.
|
// and FP8), on low-latency / cp recipes, and on PD-Disagg (the cookbook's
|
||||||
const MEGAMOE_UNSUPPORTED_RECIPES = new Set(["low-latency", "cp"]);
|
// PD command builder doesn't emit the megamoe backend / env vars yet).
|
||||||
|
const MEGAMOE_UNSUPPORTED_RECIPES = new Set(["low-latency", "cp", "pd-disagg"]);
|
||||||
const MEGAMOE_UNSUPPORTED_HARDWARE = new Set(["h100", "h200"]);
|
const MEGAMOE_UNSUPPORTED_HARDWARE = new Set(["h100", "h200"]);
|
||||||
const isMegamoeUnsupported = (vals) =>
|
const isMegamoeUnsupported = (vals) =>
|
||||||
MEGAMOE_UNSUPPORTED_HARDWARE.has(vals.hardware) ||
|
MEGAMOE_UNSUPPORTED_HARDWARE.has(vals.hardware) ||
|
||||||
MEGAMOE_UNSUPPORTED_RECIPES.has(vals.recipe);
|
MEGAMOE_UNSUPPORTED_RECIPES.has(vals.recipe);
|
||||||
|
|
||||||
|
// HiCache works on PD-Disagg in SGLang itself (prefill worker only, per
|
||||||
|
// mooncake_store/README.md), but the cookbook generator doesn't yet emit
|
||||||
|
// the hicache flags into buildPDDisaggCommand. Grey it out for now.
|
||||||
|
const HICACHE_UNSUPPORTED_RECIPES = new Set(["pd-disagg"]);
|
||||||
|
const isHicacheUnsupported = (vals) =>
|
||||||
|
HICACHE_UNSUPPORTED_RECIPES.has(vals.recipe);
|
||||||
|
|
||||||
// H100 + SGLang FP8 only ships a Flash variant — Pro FP8 on H100 isn't
|
// H100 + SGLang FP8 only ships a Flash variant — Pro FP8 on H100 isn't
|
||||||
// covered by the generator yet, so the Pro radio is greyed out there.
|
// covered by the generator yet, so the Pro radio is greyed out there.
|
||||||
const isProDisabledFp8H100 = (vals) =>
|
const isProDisabledFp8H100 = (vals) =>
|
||||||
@@ -155,11 +163,20 @@ export const DeepSeekV4Deployment = () => {
|
|||||||
if (option.name === "megamoe" && vals && isMegamoeUnsupported(vals)) {
|
if (option.name === "megamoe" && vals && isMegamoeUnsupported(vals)) {
|
||||||
const reason = MEGAMOE_UNSUPPORTED_HARDWARE.has(vals.hardware)
|
const reason = MEGAMOE_UNSUPPORTED_HARDWARE.has(vals.hardware)
|
||||||
? "MegaMoE is only supported on Blackwell"
|
? "MegaMoE is only supported on Blackwell"
|
||||||
|
: vals.recipe === "pd-disagg"
|
||||||
|
? "MegaMoE is not yet wired into the PD-Disagg cookbook command"
|
||||||
: "MegaMoE is not supported on this recipe";
|
: "MegaMoE is not supported on this recipe";
|
||||||
return option.items.map((it) =>
|
return option.items.map((it) =>
|
||||||
it.id === "disabled" ? it : { ...it, disabled: true, disabledReason: reason }
|
it.id === "disabled" ? it : { ...it, disabled: true, disabledReason: reason }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (option.name === "hicache" && vals && isHicacheUnsupported(vals)) {
|
||||||
|
return option.items.map((it) =>
|
||||||
|
it.id === "disabled"
|
||||||
|
? it
|
||||||
|
: { ...it, disabled: true, disabledReason: "HiCache is not yet wired into the PD-Disagg cookbook command" }
|
||||||
|
);
|
||||||
|
}
|
||||||
if (option.name === "quantization" && vals && !FP8_SUPPORTED_HARDWARE.has(vals.hardware)) {
|
if (option.name === "quantization" && vals && !FP8_SUPPORTED_HARDWARE.has(vals.hardware)) {
|
||||||
return option.items.map((it) =>
|
return option.items.map((it) =>
|
||||||
it.id === "fp8"
|
it.id === "fp8"
|
||||||
@@ -249,6 +266,15 @@ export const DeepSeekV4Deployment = () => {
|
|||||||
) {
|
) {
|
||||||
next.megamoe = "disabled";
|
next.megamoe = "disabled";
|
||||||
}
|
}
|
||||||
|
// Switching to a recipe that doesn't support HiCache (pd-disagg) while
|
||||||
|
// L2 is selected: fall back to disabled.
|
||||||
|
if (
|
||||||
|
optionName === "recipe" &&
|
||||||
|
next.hicache !== "disabled" &&
|
||||||
|
isHicacheUnsupported(next)
|
||||||
|
) {
|
||||||
|
next.hicache = "disabled";
|
||||||
|
}
|
||||||
// Switching to max-throughput on supported hardware: default MegaMoE to
|
// Switching to max-throughput on supported hardware: default MegaMoE to
|
||||||
// W4A8 if it's currently disabled (best throughput config).
|
// W4A8 if it's currently disabled (best throughput config).
|
||||||
if (
|
if (
|
||||||
@@ -488,7 +514,14 @@ export const DeepSeekV4Deployment = () => {
|
|||||||
fp4Flags.push(" --speculative-eagle-topk 1");
|
fp4Flags.push(" --speculative-eagle-topk 1");
|
||||||
fp4Flags.push(" --speculative-num-draft-tokens 2");
|
fp4Flags.push(" --speculative-num-draft-tokens 2");
|
||||||
}
|
}
|
||||||
if (isBig) fp4Flags.push(" --mem-fraction-static 0.88");
|
// H200 Pro (FP4) low-latency runs MTP 3/1/4 with flashinfer_mxfp4, which
|
||||||
|
// needs more headroom for the draft model + MTP buffers than the
|
||||||
|
// balanced / max-throughput recipes — drop mem-frac to 0.83.
|
||||||
|
if (isBig) {
|
||||||
|
fp4Flags.push(recipe === "low-latency"
|
||||||
|
? " --mem-fraction-static 0.83"
|
||||||
|
: " --mem-fraction-static 0.88");
|
||||||
|
}
|
||||||
if (toolcall === "enabled") fp4Flags.push(" --tool-call-parser deepseekv4");
|
if (toolcall === "enabled") fp4Flags.push(" --tool-call-parser deepseekv4");
|
||||||
if (reasoningParser === "enabled") fp4Flags.push(" --reasoning-parser deepseek-v4");
|
if (reasoningParser === "enabled") fp4Flags.push(" --reasoning-parser deepseek-v4");
|
||||||
if (hicache === "l2") {
|
if (hicache === "l2") {
|
||||||
@@ -762,8 +795,12 @@ export const DeepSeekV4Deployment = () => {
|
|||||||
flags.push(` --tp ${tp}`);
|
flags.push(` --tp ${tp}`);
|
||||||
if (multinode) flags.push(...multiNodeFlags(nnodes));
|
if (multinode) flags.push(...multiNodeFlags(nnodes));
|
||||||
flags.push(" --moe-a2a-backend deepep");
|
flags.push(" --moe-a2a-backend deepep");
|
||||||
flags.push(" --enable-dsa-prefill-context-parallel");
|
// PR #25821 (merged 2026-05-20) renamed these flags from --enable-nsa-* /
|
||||||
flags.push(" --dsa-prefill-cp-mode round-robin-split");
|
// --nsa-prefill-cp-mode to --enable-dsa-* / --dsa-prefill-cp-mode. The
|
||||||
|
// :latest release image predates that PR, so we emit the old nsa-* names
|
||||||
|
// here and surface a note above the command for main-branch users.
|
||||||
|
flags.push(" --enable-nsa-prefill-context-parallel");
|
||||||
|
flags.push(" --nsa-prefill-cp-mode round-robin-split");
|
||||||
flags.push(" --chunked-prefill-size 16384");
|
flags.push(" --chunked-prefill-size 16384");
|
||||||
// GB300 big CP needs higher mem-fraction-static: Pro 1.6T weights at
|
// GB300 big CP needs higher mem-fraction-static: Pro 1.6T weights at
|
||||||
// tp=4 are ~224 GB/card on a 273 GB GB300, so 0.78 leaves a negative
|
// tp=4 are ~224 GB/card on a 273 GB GB300, so 0.78 leaves a negative
|
||||||
@@ -827,6 +864,12 @@ export const DeepSeekV4Deployment = () => {
|
|||||||
if (megamoe !== "disabled" && recipe === "max-throughput") {
|
if (megamoe !== "disabled" && recipe === "max-throughput") {
|
||||||
megamoeEnv.push("SGLANG_OPT_DEEPGEMM_MEGA_MOE_NUM_MAX_TOKENS_PER_RANK=8320");
|
megamoeEnv.push("SGLANG_OPT_DEEPGEMM_MEGA_MOE_NUM_MAX_TOKENS_PER_RANK=8320");
|
||||||
}
|
}
|
||||||
|
// Blackwell balanced always runs with MTP (1/1/2) — when MegaMoE is layered on
|
||||||
|
// top, cap the per-rank dispatch buffer at 4096 to keep MoE memory in budget.
|
||||||
|
// (megamoe is gated to Blackwell by MEGAMOE_UNSUPPORTED_HARDWARE.)
|
||||||
|
if (megamoe !== "disabled" && recipe === "balanced") {
|
||||||
|
megamoeEnv.push("SGLANG_OPT_DEEPGEMM_MEGA_MOE_NUM_MAX_TOKENS_PER_RANK=4096");
|
||||||
|
}
|
||||||
if (megamoe === "w4a4") {
|
if (megamoe === "w4a4") {
|
||||||
megamoeEnv.push("SGLANG_OPT_DEEPGEMM_MEGA_MOE_USE_FP4_ACTS=1");
|
megamoeEnv.push("SGLANG_OPT_DEEPGEMM_MEGA_MOE_USE_FP4_ACTS=1");
|
||||||
megamoeEnv.push("SGLANG_OPT_DEEPGEMM_MEGA_MOE_USE_MXF4_KIND=1");
|
megamoeEnv.push("SGLANG_OPT_DEEPGEMM_MEGA_MOE_USE_MXF4_KIND=1");
|
||||||
@@ -849,6 +892,15 @@ export const DeepSeekV4Deployment = () => {
|
|||||||
// GB200 multinode may need machine-specific NVSHMEM / Gloo env vars;
|
// GB200 multinode may need machine-specific NVSHMEM / Gloo env vars;
|
||||||
// emit them as commented hints above the env block so users know to check.
|
// emit them as commented hints above the env block so users know to check.
|
||||||
let cmd = base;
|
let cmd = base;
|
||||||
|
if (recipe === "cp") {
|
||||||
|
cmd =
|
||||||
|
`# NOTE: --enable-nsa-prefill-context-parallel / --nsa-prefill-cp-mode were\n` +
|
||||||
|
`# renamed to --enable-dsa-prefill-context-parallel / --dsa-prefill-cp-mode\n` +
|
||||||
|
`# in PR #25821 (merged 2026-05-20). The cookbook emits the old nsa-* names\n` +
|
||||||
|
`# because the :latest release image predates that PR. If you're running\n` +
|
||||||
|
`# SGLang built from main, replace nsa- with dsa- in the two flags below.\n` +
|
||||||
|
cmd;
|
||||||
|
}
|
||||||
if (hardware === "gb200" && multinode) {
|
if (hardware === "gb200" && multinode) {
|
||||||
cmd =
|
cmd =
|
||||||
`# The following env vars may be needed depending on your cluster:\n` +
|
`# The following env vars may be needed depending on your cluster:\n` +
|
||||||
@@ -1011,6 +1063,13 @@ export const DeepSeekV4Deployment = () => {
|
|||||||
} else {
|
} else {
|
||||||
flags.push(" --max-running-requests 256");
|
flags.push(" --max-running-requests 256");
|
||||||
}
|
}
|
||||||
|
// Reasoning / tool-call parsers are the OpenAI response formatter
|
||||||
|
// running in serving_chat.py. The PD HTTP router (sgl-model-gateway
|
||||||
|
// pd_router.rs::execute_dual_dispatch) returns the decode server's
|
||||||
|
// response to the client and discards prefill's, so the parsers only
|
||||||
|
// need to be set on decode. Adding them to prefill would be inert.
|
||||||
|
if (values.toolcall === "enabled") flags.push(" --tool-call-parser deepseekv4");
|
||||||
|
if (values.reasoningParser === "enabled") flags.push(" --reasoning-parser deepseek-v4");
|
||||||
}
|
}
|
||||||
flags.push(" --host 0.0.0.0");
|
flags.push(" --host 0.0.0.0");
|
||||||
flags.push(` --port ${port}`);
|
flags.push(` --port ${port}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user