[Klaud Cold] glm5.2-fp4-b200-sglang-agentic-mtp: GLM-5.2 NVFP4 B200 AgentX with EAGLE MTP and golden-AL synthetic acceptance / 新增 GLM-5.2 NVFP4 B200 SGLang EAGLE MTP AgentX 配置(黄金 AL 合成接受率) - #2448
Conversation
|
Thanks for the contribution! Please reach out to respective companies' CODEOWNER to fill in the latest PR_REVIEW_CHECKLIST.md before pinging core maintainer on Slack for review. In order for the signoff PR check bot to trigger, you must follow the PR_REVIEW_CHECKLIST.md template correctly, including the phrase For PR verification, add the PR authors are responsible for ensuring that after merging, all GitHub Action jobs fully pass. A lot of the time, failures are just flakes and simply re-running the failed jobs will fix it. See GitHub's docs on re-running failed jobs 感谢你的贡献!请联系相应公司的 CODEOWNER 填写最新的 PR_REVIEW_CHECKLIST.md,然后再在 Slack 上联系核心维护者进行审阅。为了触发 signoff PR 检查机器人,你必须正确遵循 PR_REVIEW_CHECKLIST.md 模板,包括保留英文语句 如需进行 PR 验证,请为此 PR 添加 PR 作者有责任确保合并后所有 GitHub Action 任务完全通过。 很多时候失败只是偶发抖动(flake),重新运行失败的任务即可解决。参见 GitHub 关于重新运行失败任务的文档 |
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
LGTM with two minor nits (inline) — a missing Chinese PR-description section and a stale step-limit override that only affects the optional, ungated EVAL_ONLY accuracy path, not the throughput sweep this PR is wired to run.
Extended reasoning...
Overview
This PR is a straightforward B200 port of the already-reviewed B300 GLM-5.2 AgentX MTP recipe (#2447): one new benchmark script, one new master-config entry, one changelog entry, and one new launcher branch adding glm5.2/fp4 model-path routing to runners/launch_b200-dgxc.sh. The launcher branch follows the exact same probe-then-fallback shape as the existing dsv4 branch immediately above it, and the two B200-specific deltas (mem-fraction-static 0.85→0.83, and keeping HF_MODEL_ID separate from the launcher-rewritten MODEL_PATH) are both narrowly scoped and clearly justified in comments.
Security risks
None. No auth, crypto, or permission-boundary code is touched. The new launcher branch only resolves a local filesystem path for container mounts and creates a directory under an already-writable shared tree (mkdir -p), consistent with sibling branches in the same file.
Level of scrutiny
This warrants light-to-moderate scrutiny: it's a benchmark-recipe addition (not production-serving code) following an established, repeated pattern (Nth SKU port of a model that already has a validated sibling recipe), with diff being additions-only. The two issues found are both nits — one is a PR-description process gap with zero code impact, and the other is confirmed to only affect an eval path that isn't wired into this recipe's actual sweep config (no RUN_EVAL/EVAL_ONLY gating present in the configs/nvidia-master.yaml entry), so it doesn't block or corrupt the throughput sweep results this PR is meant to produce.
Other factors
The author's own PR description is unusually thorough (validation steps, explicit merge-order dependency on #2447, an open question about whether the checkpoint is pre-staged on the cluster). I independently confirmed the step-limit bug report is accurate: benchmark_lib.sh:1194 and utils/evals/EVALS.md:203 both show the real shared default is 250, not 75, so the override in this script (and its unmodified B300 sibling) cuts the budget rather than doubling it — but since this only fires under a manual EVAL_ONLY=true run and not the sweep this PR ships, it doesn't rise to blocking severity.
|
|
||
| - config-keys: | ||
| - glm5.2-fp4-b200-sglang-agentic-mtp | ||
| description: | ||
| - "Add the first GLM-5.2 AgentX (agentic-coding) recipe on B200: GLM-5.2-NVFP4 with SGLang, spec-decoding=mtp only, routed to benchmarks/single_node/agentic/glm5.2_fp4_b200_sglang_mtp.sh. Shipped spec-decode-only per the AgentX policy in MODELS.md -- agentic recipes are run and published with speculative decoding enabled rather than as an STP/MTP A/B, because synthetic acceptance already makes spec-decode results comparable across submissions." | ||
| - "Speculative config is GLM-5.2's built-in nextn head via SGLang EAGLE (no external draft model): --speculative-algorithm EAGLE, --speculative-num-steps 3, --speculative-eagle-topk 1, --speculative-num-draft-tokens 4, i.e. 3 speculative tokens per verification step. Same shape as the B300 sibling and the GLM-5.2 GB300 dynamo-sglang agentic recipes." | ||
| - "Throughput runs pin SGLang simulated acceptance to the committed golden AL: SGLANG_SIMULATE_ACC_LEN=2.99 (GLM-5.2 MTP curve at K=3, thinking_on, golden_al_distribution/glm5.2_mtp.yaml), SGLANG_SIMULATE_ACC_METHOD=match-expected, SGLANG_SIMULATE_ACC_TOKEN_MODE=real-draft-token -- the triple golden_al_distribution/README.md prescribes for SGLang. EVAL_ONLY runs leave simulated acceptance off and keep real verification. The golden curve file itself is committed by the B300 sibling PR #2447, which should merge first." | ||
| - "Image lmsysorg/sglang:v0.5.16-cu130. SGLANG_SIMULATE_ACC_TOKEN_MODE is only read from v0.5.16 (SIMULATE_ACC_LEN / SIMULATE_ACC_METHOD exist further back), so an older image would silently ignore the token-mode half of the AgentX contract; v0.5.16-cu130 is also the tag the B300 GLM-5.2 MTP entry and the GLM-5.2 GB300 dynamo-sglang agentic recipes run." | ||
| - "Serve shape is the B300 GLM-5.2 MTP script with two B200 deltas. --mem-fraction-static drops from 0.85 to 0.83 (overridable via MEM_FRACTION_STATIC): B200's 180 GB HBM3e leaves only 27 GB of non-static headroom at 0.85 against B300's 43 GB, and the EAGLE draft head's verification-batch activations and the extra CUDA-graph capture at 4 draft tokens come out of that pool on top of GLM-5.2's DSA indexer temporaries; 0.83 restores ~31 GB. Everything else is unchanged -- cookbook low-latency TP8 arm (--kv-cache-dtype fp8_e4m3, --bf16-gemm-backend cutedsl, --max-prefill-tokens 8192, --chunked-prefill-size 8192, glm47 tool-call parser, glm45 reasoning parser), HiCache at hicache-ratio 0.75 / write_back / direct / page_first_direct, and the default 1M-context agentic corpus that glm5.2 selects in resolve_trace_source, so the B200 and B300 curves are directly comparable." | ||
| - "Second delta: the checkpoint-resolution guard. runners/launch_b200-dgxc.sh rewrites MODEL to the cluster-local checkpoint path for single-node runs, so `hf download \"$MODEL\"` cannot work there; the script keeps the HF repo id in HF_MODEL_ID and downloads from it only when MODEL_PATH is missing or empty." |
There was a problem hiding this comment.
🟡 AGENTS.md mandates that PR bodies follow the English content with a Chinese translation (e.g. a ## 中文说明 section), but PR #2448's body is entirely English from the description through the Validation section — the bilingual title alone doesn't satisfy this rule. This is a pre-merge, easily-fixed process gap: add a Chinese translation section to the PR description.
Extended reasoning...
What the rule requires. AGENTS.md:7 states, as a mandatory (not aspirational) rule: "PR and GitHub-issue titles & descriptions must be bilingual — include a Simplified Chinese version in addition to English... In the PR/issue body, follow the English content with its Chinese translation (e.g. a ## 中文说明 section mirroring the summary)... This applies to every PR." It explicitly separates the title requirement from the body requirement, which means satisfying one does not satisfy the other.
What's actually in this PR. The title for #2448 is bilingual: ... GLM-5.2 NVFP4 B200 AgentX with EAGLE MTP and golden-AL synthetic acceptance / 新增 GLM-5.2 NVFP4 B200 SGLang EAGLE MTP AgentX 配置(黄金 AL 合成接受率). That satisfies the title half of the rule. But the body — the opening description, the "What's here" table, the "MTP + synthetic acceptance length" section, "The two B200 deltas," "Launcher routing," "Search space," and "Validation," ending in "Sweep results to follow." — is entirely in English. There is no ## 中文说明 section, nor any trailing Chinese paragraph anywhere in the body.
Why this isn't caught elsewhere. The only automated check visible in the PR timeline is the recipe-reminder bot comment, which is itself bilingual but only nudges the author toward the CODEOWNER sign-off checklist and the full-sweep-fail-fast label — it says nothing about verifying a ## 中文说明 section exists, so there's no CI gate that would fail this PR for the omission. It relies entirely on manual reviewer/CODEOWNER diligence, which is exactly the gap this flags.
Step-by-step verification:
- Open
AGENTS.mdat line 7 in this repo: it lays out the bilingual body/title split explicitly, plus a translation-quality bar in the next callout, showing this is a substantive, repo-specific convention, not boilerplate. - Read the full PR [Klaud Cold] glm5.2-fp4-b200-sglang-agentic-mtp: GLM-5.2 NVFP4 B200 AgentX with EAGLE MTP and golden-AL synthetic acceptance / 新增 GLM-5.2 NVFP4 B200 SGLang EAGLE MTP AgentX 配置(黄金 AL 合成接受率) #2448 description as preloaded in this PR's metadata: scan top to bottom — every section header and every paragraph is English only.
- Search the text for
中文,## 中文说明, or any CJK characters in the body content itself (excluding the title): none are present. - Compare against the title, which does correctly follow the
<English title> / <中文标题>format specified in the same AGENTS.md line — confirming the author knows the bilingual convention exists but only applied it to the title, not the body.
Impact and fix. Nothing functional breaks — the benchmark config, launcher routing, and changelog entry are all correct and this doesn't block the sweep from running. The fix is purely editorial: add a ## 中文说明 section to the PR body that mirrors the English summary (per the translation-quality bar in AGENTS.md:9, using natural idiomatic technical Chinese rather than literal machine translation, and preserving English identifiers like model names, hardware SKUs, and flags). Since this is a PR-description edit rather than a code change, it's a nit — worth fixing before merge to stay consistent with the repo's bilingual-documentation policy, but not something that should block or delay the sweep.
| if [ "${EVAL_ONLY}" = "true" ]; then | ||
| # GLM-5.2's chat template defaults to reasoning_effort=Max when the | ||
| # client passes no chat_template_kwargs (mini-swe-agent doesn't), and the | ||
| # heavy thinking burns the default 75-step budget: on the 23-instance | ||
| # slice, 12/23 trajectories exited LimitsExceeded unsubmitted while 10 of | ||
| # the 11 that submitted resolved. Double the step budget for this recipe; | ||
| # other recipes keep the shared 75 default. | ||
| export SWEBENCH_AGENT_STEP_LIMIT=150 | ||
| run_eval --port "$PORT" |
There was a problem hiding this comment.
🟡 In the EVAL_ONLY branch, export SWEBENCH_AGENT_STEP_LIMIT=150 is meant to double the step budget so GLM-5.2's heavy-thinking trajectories avoid LimitsExceeded exits, but the comment's premise is wrong: the real shared default (benchmark_lib.sh:1194) is 250, not 75, and no other recipe overrides this var. So 150 actually cuts the budget by 40% below what every other recipe gets, which is the opposite of the stated intent and will make LimitsExceeded exits worse, not better. This only affects the optional EVAL_ONLY accuracy path, not the throughput sweep this recipe is wired for.
Extended reasoning...
The bug
At benchmarks/single_node/agentic/glm5.2_fp4_b200_sglang_mtp.sh:292-298, the EVAL_ONLY branch does:
# GLM-5.2's chat template defaults to reasoning_effort=Max when the
# client passes no chat_template_kwargs (mini-swe-agent doesn't), and the
# heavy thinking burns the default 75-step budget: on the 23-instance
# slice, 12/23 trajectories exited LimitsExceeded unsubmitted while 10 of
# the 11 that submitted resolved. Double the step budget for this recipe;
# other recipes keep the shared 75 default.
export SWEBENCH_AGENT_STEP_LIMIT=150The stated goal is reasonable — GLM-5.2 with reasoning_effort=Max burns through steps fast, and the author observed a high LimitsExceeded rate on a validation slice, so they wanted to give the agent more room. The mechanism chosen to do that (doubling the step budget from a claimed "shared 75 default" to 150) is where the bug is: the "75 default" premise is factually wrong.
Where the real default lives
utils/evals/run_eval (via benchmarks/benchmark_lib.sh:1194) sets the mini-swe-agent step budget as:
step_limit = int(os.environ.get("SWEBENCH_AGENT_STEP_LIMIT", "250"))and unconditionally applies it (d["agent"]["step_limit"] = step_limit, benchmark_lib.sh:1206). The diagnostic echo at benchmark_lib.sh:1249 confirms the same default: step_limit=${SWEBENCH_AGENT_STEP_LIMIT:-250}. utils/evals/EVALS.md:203 documents it identically: SWEBENCH_AGENT_STEP_LIMIT (250). There is no 75 default anywhere in the codebase — I grepped for it and found nothing. A grep across benchmarks/ also shows no other recipe overrides SWEBENCH_AGENT_STEP_LIMIT, so 250 is in fact what every other recipe runs with today.
Why this slipped through
The comment and value are copied verbatim from the pre-existing benchmarks/single_node/agentic/glm5.2_fp4_b300_sglang.sh (lines ~207-213, per the synthesis notes), where the same mistaken "75 default" claim already exists untouched. This PR is a B200 port of that B300 script, so the bad comment+value pair rode along into a brand-new file rather than being introduced here from scratch — but since this is a new file being added in this PR, the bug is in-scope for this review.
Step-by-step proof
- Assume
SWEBENCH_AGENT_STEP_LIMITis unset (the normal case for every other recipe).run_evalcomputesstep_limit = int(os.environ.get("SWEBENCH_AGENT_STEP_LIMIT", "250"))→250. - In this recipe's
EVAL_ONLYbranch, the script instead runsexport SWEBENCH_AGENT_STEP_LIMIT=150before callingrun_eval --port "$PORT". run_evalnow computesstep_limit = int(os.environ.get("SWEBENCH_AGENT_STEP_LIMIT", "250"))→150, because the env var is now set.150 < 250: the agent gets fewer commands per SWE-bench instance than it would with no override at all — a 40% reduction, not a doubling.- Given the author's own observation that GLM-5.2's
reasoning_effort=Maxtrajectories already burn through steps aggressively enough to hitLimitsExceededat a high rate on a 250-or-higher-equivalent-budget expectation, cutting the budget to 150 will only increase theLimitsExceededrate, further depressing the reported SWE-bench resolved-rate for this recipe's optional accuracy path.
Fix
Since the intent is to increase the budget above the real 250 default (e.g. to roughly double it, matching the comment's stated goal), the value should be something like 500, or the override should simply be dropped so the recipe inherits the already-generous 250 default and the author's tuning effort is redirected to a value that is actually larger than 250.
Scope of impact
This only affects the EVAL_ONLY=true accuracy path (the SWE-bench mini-swe-agent eval), not the throughput sweep that this recipe's master-config entry actually wires up (configs/nvidia-master.yaml's glm5.2-fp4-b200-sglang-agentic-mtp only lists an agentic-coding scenario, no RUN_EVAL/EVAL_ONLY gating visible in the sweep). So merging as-is does not break the throughput sweep CI validated in this PR — it silently produces an artificially low accuracy score if/when someone runs the optional eval path, which is the exact opposite of what the comment promises.
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=30729467646 |
… EAGLE MTP with golden-AL synthetic acceptance
B200 port of glm5.2-fp4-b300-sglang-agentic-mtp, spec-decode only per the
AgentX policy in MODELS.md. Same TP8 + HiCache arm on the same concurrency
grid so the two SKUs are directly comparable.
- benchmarks/single_node/agentic/glm5.2_fp4_b200_sglang_mtp.sh: the B300 MTP
script with two B200 deltas -- --mem-fraction-static 0.83 instead of 0.85
(180 GB HBM3e leaves only 27 GB of non-static headroom at 0.85, and the
EAGLE draft head's activations and 4-draft-token graph capture come out of
it), and an HF_MODEL_ID download guard, since b200-dgxc rewrites MODEL to a
cluster-local path.
- runners/launch_b200-dgxc.sh: glm5.2/fp4 routing, which previously hard-
failed with 'Unsupported model prefix/precision'. Probes the staged trees,
falls back to the sa-shared-writable gharunners path and creates it.
- configs/nvidia-master.yaml: TP8 + HiCache at conc [1, 4, 8, 12, 16] on
lmsysorg/sglang:v0.5.16-cu130, acceptance pinned to golden AL 2.99.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… guard is not a completeness check
All five cells of run 30729467646 died the same way. b200-dgxc already had
/lustre/fsw/gharunners/models/GLM-5.2-NVFP4 holding config.json,
generation_config.json, hf_quant_config.json, chat_template.jinja, README.md
and .quant_summary.txt -- an aborted or metadata-only pull, no weights and no
tokenizer. The `ls -A` emptiness guard accepted it, so every cell skipped the
download and went straight to serve; SGLang parsed config.json fine (it logged
GlmMoeDsa, DSA page size 64, the fp8 KV backends) and then died in
AutoTokenizer.from_pretrained with "Couldn't instantiate the backend
tokenizer". The B300 sibling ran 5/5 green on the same image and the same MTP
+ simulated-acceptance config in run 30729399405, so this is staging only.
- checkpoint_is_complete(): tokenizer_config.json, a tokenizer.json or
tokenizer.model, model.safetensors.index.json, and every shard the index
names. Verified against the exact stub above, a partial shard set, a
complete tree and a missing directory.
- flock on <MODEL_PATH>.download.lock around the download. Each concurrency
is its own allocation against the same Lustre path, so one cell stages the
~433 GB checkpoint and the other four wait rather than five racing writers.
hf download resumes into a partially-populated --local-dir, so it downloads
on top of the stub.
- launcher probe now requires a candidate to hold at least one weight shard,
not merely exist, so a stub in one staged tree cannot win over a real copy
in another.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
b641cd1 to
177593b
Compare
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=30730876284 |
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=30731377478 |
Adds
glm5.2-fp4-b200-sglang-agentic-mtp— the first GLM-5.2 AgentX recipe on B200. Spec-decode only, per the AgentX policy that agentic arms enable speculative decoding rather than running a separate STP baseline (MODELS.md).B200 port of the B300 sibling #2447 (#2447), with the same single arm and concurrency grid so the two SKUs are directly comparable.
What's here
benchmarks/single_node/agentic/glm5.2_fp4_b200_sglang_mtp.shrunners/launch_b200-dgxc.shglm5.2/fp4routing.configs/nvidia-master.yamlperf-changelog.yamlMTP + synthetic acceptance length
GLM-5.2 ships its own nextn head, so SGLang EAGLE runs off the checkpoint with no external draft model —
--speculative-num-steps 3 --speculative-eagle-topk 1 --speculative-num-draft-tokens 4, i.e. 3 speculative tokens per verification step.Throughput runs pin acceptance to the committed golden AL, per
golden_al_distribution/README.md:EVAL_ONLYruns leave it off and keep real verification. Image islmsysorg/sglang:v0.5.16-cu130(verified on Docker Hub) —SGLANG_SIMULATE_ACC_TOKEN_MODEis only read from v0.5.16.The two B200 deltas
--mem-fraction-static0.85 → 0.83 (overridable viaMEM_FRACTION_STATIC). B200's 180 GB HBM3e leaves only 27 GB of non-static headroom at 0.85 against B300's 43 GB, and the EAGLE draft head's verification-batch activations and the extra CUDA-graph capture at 4 draft tokens come out of that pool on top of GLM-5.2's DSA indexer temporaries. 0.83 restores ~31 GB.launch_b200-dgxc.shrewritesMODELto the cluster-local path for single-node runs, sohf download "$MODEL"can't work there. The script keeps the HF repo id inHF_MODEL_IDand downloads from it only whenMODEL_PATHis missing or empty.Everything else is the B300 script unchanged, including the default 1M-context agentic corpus
resolve_trace_sourcepicks forglm5.2— deliberately not switched to the 256k-capped variant, so the two curves measure the same workload.Launcher routing
launch_b200-dgxc.shpreviously hard-failed withUnsupported model prefix/precision: glm5.2/fp4. The new branch probes/lustre/fsw/models/GLM-5.2-NVFP4,/scratch/fsw/models/GLM-5.2-NVFP4,/lustre/fsw/gharunners/models/GLM-5.2-NVFP4in that order (same shape as thedsv4branch above it), falling back to the sa-shared-writable gharunners path and creating it —--container-mountsneeds the host path to exist, and the bench script's download guard populates it on first use.I could not verify from here whether GLM-5.2-NVFP4 is already staged on b200-dgxc. If it isn't, the first job pays a ~433 GB HuggingFace download inside its allocation. The probe handles both cases; if a reviewer knows the staged path, say so and I'll pin it directly.
Search space
- { tp: 8, spec-decoding: mtp, kv-offloading: dram, kv-offload-backend: { name: hicache }, conc-list: [1, 4, 8, 12, 16] }Identical to the B300 sibling. Steps of at least 2 — single-step sampling can't separate configurations by more than run-to-run noise on the agentic corpus — and a hard stop at conc 16. TP8-only for memory as well as comparability: the ~433 GB NVFP4 checkpoint needs ~54 GB/GPU across 8 B200s and doesn't fit below 8. The DEP (attention-DP + EP8) throughput arm isn't wired up for the same reason as on B300 — its frontier peak sits well above the conc-16 cap — but the branch stays in the script, including the
--speculative-moe-a2a-backend none/--speculative-moe-runner-backend tritonpair that GLM-5.2-NVFP4's unquantized bf16 nextn layer (hf_quant_configexcludesmodel.layers.78*) needs under expert parallelism.Validation
bash -nclean on both the bench script and the launcher;perf-changelog.yaml/configs/nvidia-master.yamlparse; diff is additions only.generate_sweep_configs.py test-configandprocess_changelog.pyagainstorigin/mainboth select exactly the 5 expected jobs (glm5.2_tp8_conc{1,4,8,12,16}_kvdram-hicache_spec-mtponcluster:b200-dgxc).benchmarks/single_node/agentic/glm5.2_fp4_b200_sglang_mtp.sh.Sweep results to follow.