Repository navigation
build(docker): bump SGLang to v0.5.23 - #4548
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…23 home SGLang v0.5.23 (sgl-project/sglang#45112) moved fused_k_norm_rope_flashmla from ops/attention/dsv4/elementwise.py to norm_rope.py and renamed dequantize_k_cache_paged to dequantize_k_cache_paged_dsv4. Both keep their signatures, and fused_k_norm_rope_flashmla's body is unchanged, so the FP8 KV round-trip the DeepSeek-V4.1 bridge simulates stays the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…23 removed SGLang v0.5.23 (sgl-project/sglang#45315) deleted encoding_dsv4.py and encoding_dsv41.py and renders DeepSeek-V4/V4.1 chat prompts through deepseek-recipe instead, which changes the rendered prompt in a dozen documented cases (effort profile, tool schema order, developer and mid-conversation system messages, ...). miles imported both encoders, so importing miles failed on the new stack. Vendor them unchanged from sglang-miles 29b34bc6f7, the way encoding_dsv32 already is, so DeepSeek-V4/V4.1 training prompts and TITO input ids stay exactly what they were. The three V4.1 helpers the bridge used from sglang's chat_encoding move into the bridge unchanged. The test_template DSv4 cases compared the TITO render with sglang's serving_chat prompt ids. The server now renders with deepseek-recipe, and TITO sessions send miles-rendered input_ids that the server uses as-is, so that parity no longer holds by design; they are removed. The bridge stays pinned to the vendored encoders by test_deepseek_v4 / test_deepseek_v4_1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n the stub test_template builds OpenAIServingChat with object.__new__ and sets only what _process_messages reads. v0.5.23 added is_minimax_m3, the _encoding_adapter (None for the Jinja and dsv32 paths tested here) and the _template_reads_reasoning_content probe; its render path now reads the reasoning detector __init__ builds from reasoning_parser; and it renders through template_manager.python_chat_template when one is loaded, which the MagicMock template manager would wrongly select. Without these, every SGLang comparison failed or compared against an empty prompt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rverArgs fields SGLang v0.5.23 added ServerArgs.aux_hidden_state_capture, resolved from --enable-return-aux-hidden-states and --speculative-algorithm and declared Arg(no_cli=True). Like the other resolved fields, it has no option to render; miles never sets it, so engine argv rendering is unaffected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he parity test SGLang v0.5.23 keeps the client's tool key order with strict unset (sgl-project/sglang#46133), and its Anthropic converter now writes name, description, parameters and strict (sgl-project/sglang#45254). The OpenAI side of the Anthropic/OpenAI parity test must spell tools the way the codec does for the two routes to render identical input_ids. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…faults The helm launch snapshot and the miles-run chart snapshots record args.sglang.base_args, the full SGLang ServerArgs default set. v0.5.23 adds fields (enable_return_aux_hidden_states, enable_paged_experts, prefill_decode_interval_min_bs, ...), drops speculative_skip_dp_mlp_sync, and turns enable_tf32_matmul, mm_enable_dp_encoder, enable_fused_qk_norm_rope and enable_decoder_swa_bounded_replay into auto-resolved None defaults. Regenerated with MILES_UPDATE_LAUNCH_SCRIPT_SNAPSHOTS=1 on the new stack (helm v4.2.3, as in CI); only the lines carrying base_args change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rouped MoE SGLang v0.5.23 (sgl-project/sglang#43556) added a grouped_moe flag to should_deepgemm_weight_requant_ue8m0: on SM120 dense block-FP8 GEMMs keep fp32 scales, but the grouped MoE GEMM runs on DeepGEMM and SGLang now requantizes expert scales to UE8M0 when loading. miles asked without the flag, so on SM120 it sent fp32 scales for expert weights that SGLang holds in UE8M0, and a weight update would write them in the wrong format. Pass grouped_moe for expert weights, as SGLang's own MoE call does. Other GPUs are unaffected: there the flag does not change the answer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… v0.5.23 SGLang v0.5.23 (sgl-project/sglang#44403) turned enable_decoder_swa_bounded_replay into Optional[bool] and resolves an unset value to on for DeepSeek-V4.1 on CUDA. Bounded replay runs the layers after the last kv_source layer over only the prompt tail; SGLang's own help says it is not numerically equivalent to full prefill and to disable it for RL rollouts whose logprobs must match the trainer. miles never set it, so a default DSv4.1 run would have drifted from the trainer, and replayed routing for those layers would no longer line up with the prompt rows. When the user leaves it unset, pass False so every engine keeps full prefill; an explicit --sglang-enable-decoder-swa-bounded-replay and a per-group override still win. On v0.5.22 the field defaults to False, so nothing changes there. The chart snapshots gain the rendered --no-enable-decoder-swa-bounded-replay flag. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The V4 encoder renders each tool dict verbatim, and the bridge built those dicts with sglang's Tool.model_dump(). SGLang v0.5.23 (sgl-project/sglang#46133) made Function keep the client's key order and drop an unset strict, so even with the vendored encoder every tool-bearing V4 prompt changed. dsv4_tool_payload rebuilds the v0.5.22 shape (declared order, strict defaulting to False). V4.1 already sends its own payload, and V3.2 keeps following Tool.model_dump(), which sglang's dsv32 serving path also uses. Checked by rendering 108 V4 and 108 V4.1 cases (tool spellings, system and tool turns, thinking on/off, generation prompt on/off) with miles main on the old stack and with this branch on the new one: identical, where V4 differed in all 96 tool-bearing cases before this change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3919333 to
79ee402
Compare
…uses SGLang v0.5.23 (sgl-project/sglang#45893) depends on sgl-flash-mla==1.0.0 and calls decode APIs only that build has (get_mla_decoding_metadata, fused_norm_rope_attn_rope_cast, the legacy SM90 kernels). The image installed the wheels release's FlashMLA nv_dev over it under the same `flash_mla` name, so SGLang's DSA paths failed at warmup: "module 'flash_mla' has no attribute 'get_mla_decoding_metadata'" (run 41189133939, both stage-c-b200 GLM-5.2 NVFP4 jobs) and "flash_mla_sparse_fwd() got an unexpected keyword argument 'use_legacy'" (the H200 DeepSeek-V4.1 job). Dropping nv_dev is not an option: Megatron's CSA forward passes `indexer_topk` on every call, and miles' DSA kernel runs the sparse prefill on SM90 and with 576-dim heads. sgl-flash-mla has neither (its current kernels are V4.1 on SM100 only), so the trainer would fail instead. Keep nv_dev as `flash_mla`, so the trainer stays exactly as on main, and move the base image's sgl-flash-mla package to `sgl_flash_mla`, which sglang-miles imports first. The two builds load their kernels differently (a CPython extension vs STABLE_TORCH_LIBRARY ops), so both can live in one process. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The grouped_moe fix for SGLang v0.5.23 (sgl-project/sglang#43556) passes `grouped_moe` to should_deepgemm_weight_requant_ue8m0 for every FP8 weight. The ROCm image stays on sglang-miles-v0.5.22-final, whose function has no such parameter, so after this bump merges every ROCm FP8 weight update (e.g. tests/e2e/megatron/test_qwen3_30B_A3B/test_amd_moriep_fp8_bridge.py) would raise TypeError. PR CI does not show it: with the ci-sglang-pr pin, the ROCm job installs the v0.5.23 stack over its image. The SGLang compat module now drops `grouped_moe` when the installed function does not take it, which is exactly the call main makes today. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.
Tip: disable this comment in your organization's Code Review settings.
|
@claude review |
| from sglang.kernels.ops.attention.dsv4.dequant_k_cache import dequantize_k_cache_paged_dsv4 | ||
| from sglang.kernels.ops.attention.dsv4.norm_rope import fused_k_norm_rope_flashmla |
There was a problem hiding this comment.
🔴 If DeepSeek-V4.1 training runs on the ROCm image, it can now fail with ImportError in the KV-cache roundtrip, where the base imports worked. The ROCm image stays on sglang-miles-v0.5.22-final, which has only the old names dequantize_k_cache_paged and dsv4.elementwise.fused_k_norm_rope_flashmla. Fix: resolve the kernels with a v0.5.23-first fallback to the v0.5.22 locations, the same way _accept_grouped_moe handles the ROCm stack, so both images import. That covers the 2 sites (kvnorm.py:22-23, kvnorm.py:57).
Why this was flagged
Docker/Dockerfile.rocm now pins SGLANG_BRANCH=sglang-miles-v0.5.22-final. The base code imported dequantize_k_cache_paged from sglang.kernels.ops.attention.dsv4.dequant_k_cache and fused_k_norm_rope_flashmla from sglang.kernels.ops.attention.dsv4.elementwise. That shows those were the v0.5.22 names, and the PR says sgl-project/sglang#45112 renamed and moved them in v0.5.23. kvnorm.py:22-23 and kvnorm.py:57 now import only the v0.5.23 names dequantize_k_cache_paged_dsv4 and dsv4.norm_rope. These imports are lazy, inside kv_cache_roundtrip and compressed_kv_cache_roundtrip. They are reached on every DSv4.1 forward through kv_norm_rope_fp8, called at deepseek_v4_1.py:516, and through the compressed path. On a ROCm build that runs DSv4.1 with these kernels, every forward raises ImportError, where the base imported successfully. The PR adds a compat shim for grouped_moe but none for these renamed kernels. The trigger depends on these kernels actually running on ROCm, which cannot be confirmed from this checkout.
Verification: docker/Dockerfile.rocm now pins ARG SGLANG_BRANCH=sglang-miles-v0.5.22-final. kvnorm.py line 22, line 23 and line 57 now import only the v0.5.23 names, and nothing falls back to the old names. deepseek_v4_1.py:516 calls kv_norm_rope_fp8(...) unconditionally, so on the ROCm stack every DSv4.1 forward would raise ImportError. _accept_grouped_moe covers this ROCm skew but not this rename.
sglang-miles now carries the validated v0.5.23 stack (b0ed761650), so the CUDA image goes back to the stable branch name and the ROCm image follows it instead of the frozen sglang-miles-v0.5.22-final. ROCm keeps its v0.5.22 base image and is not covered by CI here. With the ROCm image's SGLang source on v0.5.23, should_deepgemm_weight_requant_ue8m0 always takes grouped_moe, so the compat wrapper and its test are no longer needed.
What
v0.5.23(lmsysorg/sglang:v0.5.23) with the rebased patch stack fromsglang-miles-v0.5.23. The ROCm image keeps itsv0.5.22ROCm base image and checks out the samesglang-milesstack. ROCm CI did not run on it.v0.5.23APIs and behaviour changes listed below. Without them miles does not import on the new stack, or it silently changes rollouts.Why
SGLang
v0.5.23keeps torch2.14.1and transformers5.19.0, so thecu130-torch214wheels and the Transformer Engine2.17.0+milestriplet carry over. The base image movesflashinfer0.7.1 -> 0.7.2 andsglang-kernel0.4.9 -> 0.4.10.These
v0.5.23changes reach miles:encoding_dsv4.py/encoding_dsv41.pyand renders DeepSeek-V4/V4.1 throughdeepseek-recipechat_template_utils/deepseek.pyfails to import, and so does all of milesencoding_dsv32already is), and move the three V4.1 helpers into the bridgeFunctionkeeps the client's key order and drops an unsetstrictdsv4_tool_payloadrebuilds the v0.5.22 tool dict for V4enable_decoder_swa_bounded_replaybecomesOptionaland resolves to on for DeepSeek-V4.1Falsewhen the user leaves it unset. An explicit flag or a per-group override still winsshould_deepgemm_weight_requant_ue8m0(..., grouped_moe=)grouped_moefor expert weights.T.Pipelined-loops over a runtime trip countDowncast from tirx.Sub to ir.IntImm failed), and Qwen3-Next rollouts hang on 503s[28/76], which already makes the sameT.serialchange for the older sibling kernel in that filesgl-flash-mla==1.0.0wheel, which installs asflash_mlano attribute 'get_mla_decoding_metadata',unexpected keyword argument 'use_legacy'). Dropping nv_dev instead breaks the trainer: Megatron's CSA forward passesindexer_topk, and miles' DSA kernel runs the sparse prefill on SM90, which sgl-flash-mla only has for SM100flash_mla, so the trainer is unchanged frommain. The base image's package moves tosgl_flash_mla, which SGLang imports first ([76/76])There are also test-only adaptations to new
OpenAIServingChatattributes, a new no-CLIServerArgsfield, the Anthropic codec's tool spelling, and the recordedServerArgsdefaults in the launch and chart snapshots.One known behaviour change is not a defect: tool JSON for HF chat templates and DeepSeek-V3.2 now keeps the client's key order and no injected
"strict": false. Thev0.5.23server renders it the same way, and miles stays aligned with the server.The PR was validated with
SGLANG_BRANCHand aci-sglang-pr:pin onsglang-miles-v0.5.23. Right before merge,sglang-milesmoved to that same commit, both images'SGLANG_BRANCHpoint atsglang-miles, and the pin was removed.SGLang stack (
sglang-miles-v0.5.23=b0ed761650)sglang-mileswere cherry-picked onto thev0.5.23tag (297e54fd10). Five were dropped because the tag already contains them. That leaves[1/76]-[69/76]([28/76]also carries the TileLang 0.1.14 change for the new QSA kernel), followed by:[70/76]: the stack'sServerArgsfields go after upstream's pinned positional slots.[71/76]: DeepSeek-V4.1 with LoRA stays off the FlashMLA MegaAttention backend, which has no LoRA path.[72/76]: MegaGate records hash-layer routed experts for R3.[73/76]: an unset diffusion--scheduler-portbinds port 0 and reports the bound port.[74/76]: a diffusion shutdown test fake getsscheduler_endpoint.[75/76]: RL: Read byte ranges of output store fields into caller memory sgl-project/sglang#47320, which landed onsglang-milesafter the freeze, cherry-picked unchanged.[76/76]: SGLang's FlashMLA interface importssgl_flash_mlawhen it exists and falls back toflash_mla, so miles' image can ship both FlashMLA builds.sglang-miles-v0.5.22-final(a5701d958b).sglang-milesmoved from29b34bc6f7tob0ed761650right before merge. The rollback point is29b34bc6f7, not-final, which predates RL: Read byte ranges of output store fields into caller memory sgl-project/sglang#47320.pre-commit run --all-filespasses on every commit.Validation
lmsysorg/sglang:v0.5.23) with the stack checked out: 172 files. Every bump-caused failure was fixed in the commit that caused it. The remaining failures also fail on thev0.5.23tag or on the old stack.29b34bc6f7vs new865cb6486d) found the fixes above. It covered:ServerArgsfields (onlyspeculative_skip_dp_mlp_syncwas removed; miles does not use it);meta_infofields miles reads;load_weightsmappings, parser names, env vars and dependencies;stage-a-cpu,stage-b-cpu) were replayed on a devbox the way the hosted job runs them: Python 3.12 withrequirements.txt+tests/ci/requirements-ci-cpu.txt, and SGLang/Megatron onPYTHONPATH. The runs were compared test by test withmainon the old stack. No test fails on this branch that passes on the baseline:stage-a-cpu20407 passed / 11 failed / 235 errors andstage-b-cpu770 passed / 1 failed / 158 errors, with every failure and error also present on the baseline (devbox environment only: Ray tests need the GPUs hidden, and the SGLang Anthropic contract needssgl_kernelonce a GPU is visible). SGLang's own Anthropic tests, which that contract runs, pass on the new stack on their own (100 passed). Helm-gated chart tests ran with helm 4.2.3 and pass.mainon the old stack and this branch on the new stack:1afbc6328(treed7098cd47) withsglang-miles-v0.5.23=b0ed761650(tree83d2da6956). The finalize commit only points both images'SGLANG_BRANCHatsglang-milesand drops the ROCm-onlygrouped_moecompat wrapper (a pass-through onv0.5.23, whose function takesgrouped_moe), so the merged code can be checked against these trees. PR Test (ROCm) never ran: no MI350 runner picked up its jobs, and the run was cancelled after 3 h. The ROCm image (v0.5.22ROCm base with thev0.5.23stack) is untested.Files
docker/Dockerfile:SGLANG_IMAGE_TAG=v0.5.23; both FlashMLA builds, with a build-time check that the moved package no longer importsflash_mla.docs/developer/versions.md,requirements.txt: version notes.miles/utils/chat_template_utils/templates/encoding_dsv4.py,encoding_dsv41.py: vendored, unchanged apart from a provenance line.deepseek.py: the vendored encoders, the V4.1 helpers anddsv4_tool_payload.miles/backends/sglang_utils/sglang_engine.py: keeps full prefill for DeepSeek-V4.1 unless the user opts in.miles/backends/megatron_utils/megatron_to_hf/processors/quantizer_fp8.py:grouped_moefor expert scales.miles_plugins/models/deepseek_v4_1/ops/kvnorm.py: kernel imports.tests/:test_templatestub, the no-CLI field registry and the Anthropic parity spelling;.pre-commit-config.yaml: excludes the vendored encoders, likeencoding_dsv32.Checklist
pre-commitpasses (Miles: changed files; SGLang stack:--all-filesper commit)pytest -xis green (pinned GPU CI run 41219496557: all 59 NVIDIA jobs; CPU suites also replayed, see Validation)python3 train.py --helpstill parses (no miles flags changed)