diff --git a/python/sglang/srt/models/deepseek_nextn.py b/python/sglang/srt/models/deepseek_nextn.py index 992b5266b..94b2e7f3a 100644 --- a/python/sglang/srt/models/deepseek_nextn.py +++ b/python/sglang/srt/models/deepseek_nextn.py @@ -93,12 +93,28 @@ def _should_drop_nextn_modelopt_fp4_quant_config( """ if quant_config is None or quant_config.get_name() != "modelopt_fp4": return False - backend = get_moe_runner_backend() - keep_fp4 = ( - backend.is_flashinfer_trtllm() - or backend.is_flashinfer_trtllm_routed() - or backend.is_flashinfer_cutedsl() - or backend.is_flashinfer_cutlass() + # The NextN/MTP draft is built by the EAGLE draft worker, where the effective + # MoE runner may be the *speculative* backend (which is AUTO when + # --speculative-moe-runner-backend is unset), not the main runner. Keep fp4 if + # EITHER the main or the speculative runner is a flashinfer fp4 backend. + from sglang.srt.layers.moe.utils import get_speculative_moe_runner_backend + + def _is_fp4_capable(b) -> bool: + return ( + b.is_flashinfer_trtllm() + or b.is_flashinfer_trtllm_routed() + or b.is_flashinfer_cutedsl() + or b.is_flashinfer_cutlass() + ) + + main_backend = get_moe_runner_backend() + spec_backend = get_speculative_moe_runner_backend() + keep_fp4 = _is_fp4_capable(main_backend) or _is_fp4_capable(spec_backend) + logger.warning( + "[NextN-fp4] main_runner=%s spec_runner=%s keep_fp4=%s", + main_backend, + spec_backend, + keep_fp4, ) return not keep_fp4