Checklist
Describe the bug
For DeepseekV4ForCausalLM, enabling speculative decoding without explicitly passing --max-running-requests leaves the effective value at 256.
This contradicts the DeepSeek-V4 cookbook:
Speculative decoding (MTP) is on — SGLang resets --max-running-requests to 48 when it is not set.
Cookbook: https://docs.sglang.io/cookbook/autoregressive/DeepSeek/DeepSeek-V4
It also contradicts the warning and intended default in the speculative decoding hook:
|
if server_args.max_running_requests is None: |
|
server_args.max_running_requests = 48 |
|
logger.warning( |
|
"Max running requests is reset to 48 for speculative decoding. You can override this by explicitly setting --max-running-requests." |
|
) |
The cause is default resolution order:
- The DeepSeek-V4 model hook runs first and changes
max_running_requests from None to 256:
|
if server_args.max_running_requests is None: |
|
server_args.max_running_requests = 256 |
|
logger.warning( |
|
f"Setting max_running_requests to {server_args.max_running_requests} for {model_arch}." |
|
) |
- The speculative hook runs later, but only sets
48 when the field is still None.
- The field is already
256, so the speculative default never applies.
The DeepSeek-V4 hook comment says that the speculative hook is a later writer of this field, but the is None guard means it cannot overwrite the model default:
|
def apply_deepseek_v4_defaults(server_args: ServerArgs, model_arch: str) -> None: |
|
"""Residual imperative arm of the DeepSeek V4 defaults. |
|
|
|
The attention/page/window/MoE-runner declarations moved to the override |
|
registry (arg_groups/overrides.py: _deepseek_v4_overrides) and the |
|
kv-cache dtype default to the resolution pipeline |
|
(_deepseek_v4_kv_cache_dtype, invoked below at its legacy slot). This |
|
keeps, at the legacy slot: the ROCm env fill (env-write policy), the |
|
max_running_requests fill (the speculative hook is a later writer of |
|
that field) and the validations. |
Explicit user input must keep its current precedence. Only the model-provided default should yield to the speculative-decoding default.
Reproduction
Start DeepSeek-V4 with speculative decoding and omit --max-running-requests, as in a cookbook-generated low-latency command:
sglang serve \
--trust-remote-code \
--model-path deepseek-ai/DeepSeek-V4-Flash \
--tp 4 \
--moe-runner-backend flashinfer_mxfp4 \
--speculative-algorithm EAGLE \
--speculative-num-steps 3 \
--speculative-eagle-topk 1 \
--speculative-num-draft-tokens 4
The same issue applies to --speculative-algorithm DSPARK, whose handler has the same is None condition.
Expected effective value:
max_running_requests = 48
Actual effective value:
max_running_requests = 256
Passing --max-running-requests 48 explicitly works around the issue.
Environment
- SGLang source: current
main, commit ae848116662ece923501131ce773a4602223237e
- Model architecture:
DeepseekV4ForCausalLM
- Reproduces through deterministic argument post-processing before GPU execution; it is not hardware-specific.
Checklist
main(ae848116662ece923501131ce773a4602223237e).Describe the bug
For
DeepseekV4ForCausalLM, enabling speculative decoding without explicitly passing--max-running-requestsleaves the effective value at256.This contradicts the DeepSeek-V4 cookbook:
Cookbook: https://docs.sglang.io/cookbook/autoregressive/DeepSeek/DeepSeek-V4
It also contradicts the warning and intended default in the speculative decoding hook:
sglang/python/sglang/srt/arg_groups/speculative_hook.py
Lines 396 to 400 in ae84811
The cause is default resolution order:
max_running_requestsfromNoneto256:sglang/python/sglang/srt/arg_groups/deepseek_v4_hook.py
Lines 141 to 145 in ae84811
48when the field is stillNone.256, so the speculative default never applies.The DeepSeek-V4 hook comment says that the speculative hook is a later writer of this field, but the
is Noneguard means it cannot overwrite the model default:sglang/python/sglang/srt/arg_groups/deepseek_v4_hook.py
Lines 106 to 115 in ae84811
Explicit user input must keep its current precedence. Only the model-provided default should yield to the speculative-decoding default.
Reproduction
Start DeepSeek-V4 with speculative decoding and omit
--max-running-requests, as in a cookbook-generated low-latency command:The same issue applies to
--speculative-algorithm DSPARK, whose handler has the sameis Nonecondition.Expected effective value:
Actual effective value:
Passing
--max-running-requests 48explicitly works around the issue.Environment
main, commitae848116662ece923501131ce773a4602223237eDeepseekV4ForCausalLM