[Config] Unify indexer cache dtype under attention_config.indexer_kv_dtype - #52550
Merged
Conversation
…dtype The DeepSeek sparse indexer and the MiniMax M3 indexer picked their K-cache dtype through two unrelated knobs: `use_fp4_indexer_cache` (bool, read only by DSV4) and `indexer_kv_dtype` (enum, read only by M3). Passing both was accepted and silently resolved in favor of the bool for DSV4, so a config asking for an fp8 indexer could run MXFP4. Make `indexer_kv_dtype` the single knob and deprecate `use_fp4_indexer_cache`: - `indexer_kv_dtype` gains an "auto" default that each model resolves to its own default (fp8 for the DeepSeek sparse indexer, bf16 for M3). The previous "bf16" default was never meaningful for DSV4, whose indexer cache is always quantized. - `use_fp4_indexer_cache` becomes `bool | None`; when set it logs a deprecation warning and maps True to "mxfp4". False is a no-op, since it already selected the model default. Conflicting values raise instead of one silently winning. - `dsa_indexer_uses_fp4()` centralizes resolution and validation for the DeepSeek path, so the model side and the metadata builder cannot disagree. It rejects dtypes the DSA indexer has no kernels for (bf16, nvfp4) and turns the Blackwell check into a ValueError so it survives `python -O`. - The deprecated field is excluded from `compute_hash`, so `use_fp4_indexer_cache=True` and `indexer_kv_dtype=mxfp4` share a compile cache entry. Signed-off-by: Yongye Zhu <zyy1102000@gmail.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
zyongye
requested review from
AndreasKaratzas,
ProExpertProg,
WoosukKwon,
houseroad,
mgoin,
pavanimajety,
robertgshaw2-redhat,
tlrmchlsmth,
vadiklyutiy,
yewentao256 and
youkaichao
as code owners
August 16, 2026 21:06
Member
Author
|
/ci run |
|
✅ Triggered Buildkite CI #84112 for commit |
zyongye
enabled auto-merge (squash)
August 17, 2026 02:01
jeejeelee
approved these changes
Aug 17, 2026
Alessandra005
pushed a commit
to Alessandra005/vllm
that referenced
this pull request
Aug 17, 2026
…dtype (vllm-project#52550) Signed-off-by: Yongye Zhu <zyy1102000@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Alessandra005 <aurib032@fiu.edu>
zyp2014
pushed a commit
to zyp2014/vllm
that referenced
this pull request
Aug 21, 2026
…dtype (vllm-project#52550) Signed-off-by: Yongye Zhu <zyy1102000@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
wyettzeng
pushed a commit
to wyettzeng/vllm
that referenced
this pull request
Aug 21, 2026
…dtype (vllm-project#52550) Signed-off-by: Yongye Zhu <zyy1102000@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Wyett <wyettzeng@gmail.com>
zufangzhu
pushed a commit
to zufangzhu/vllm
that referenced
this pull request
Aug 24, 2026
…dtype (vllm-project#52550) Signed-off-by: Yongye Zhu <zyy1102000@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Zhu, Zufang <zufang.zhu@intel.com>
khushali9
pushed a commit
to khushali9/vllm
that referenced
this pull request
Aug 29, 2026
…dtype (vllm-project#52550) Signed-off-by: Yongye Zhu <zyy1102000@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: khushali9 <khushali.desai9@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
The sparse-attention indexer picked its K-cache dtype through two unrelated knobs:
attention_config.use_fp4_indexer_cacheboolattention_config.indexer_kv_dtypeBecause each model read only one of them, passing both was accepted and quietly
resolved in favor of the bool on the DeepSeek path. A config asking for an fp8
indexer cache (
--attention_config.indexer_kv_dtype fp8) alongside--attention_config.use_fp4_indexer_cache=Trueran MXFP4, with no warning. I hitexactly this in a local DSV4 recipe whose "fp8 indexer" arm had in fact been
running MXFP4 for its whole history.
This PR makes
indexer_kv_dtypethe single knob and deprecatesuse_fp4_indexer_cache.Changes
vllm/config/attention.pyindexer_kv_dtypegains an"auto"default, resolved per model by the newresolve_indexer_kv_dtype(default). The old"bf16"default was nevermeaningful for DeepSeek, whose indexer cache is always quantized;
"auto"means fp8 there and bf16 for M3, preserving both models' current behavior.
use_fp4_indexer_cachebecomesbool | None = None. When set it logs adeprecation warning (removal in v0.19) and maps
True -> "mxfp4".Falseisa no-op because it already selected the model default. Conflicting values now
raise instead of one silently winning.
compute_hash, souse_fp4_indexer_cache=Trueandindexer_kv_dtype=mxfp4share a compilecache entry rather than splitting it.
vllm/v1/attention/backends/mla/indexer.pydsa_indexer_uses_fp4(vllm_config)centralizes resolution + validation forthe DeepSeek path, so the model side and the metadata builder cannot disagree.
It rejects dtypes the DSA indexer has no kernels for (
bf16,nvfp4) insteadof failing later in kernel selection, and turns the existing Blackwell
assertinto aValueErrorso the check survivespython -O.Callers —
models/deepseek_v4/attention.pyandmodels/minimax_m3/nvidia/model.pygo through the shared helpers. DSV4 nowvalidates at model construction too, not only at backend build.
Configs — the two tracked gsm8k eval configs move to
--attention_config.indexer_kv_dtype=mxfp4.Backward compatibility
--attention_config.use_fp4_indexer_cache=Truekeeps working and keepsselecting MXFP4; it just warns. All three CLI spellings were exercised
(
--attention_config.indexer_kv_dtype=mxfp4, the deprecated flag, and JSON--attention-config '{"indexer_kv_dtype": "nvfp4"}').The one intentional behavior change: a config passing both flags with
different values used to silently take the bool, and now raises. That
combination was always a contradiction; on the DeepSeek path it produced a cache
dtype the config did not ask for.
Not a duplicate
Per the duplicate-work checks in
AGENTS.md:Nearest open PRs, all adjacent rather than overlapping — none touches
vllm/config/attention.pyor unifies the two knobs:models/deepseek_v4/attention.py,the one file in common, but adds a feature; no config-surface change.
indexer_kv_dtype, does not change how it is selected.deepseek_v2.py.If #51209 lands first the overlap is a small context conflict in
DeepseekV4Indexer.__init__, trivially rebasable.Testing
The single failure is
test_config_generation.py::test_ray_runtime_env(
ModuleNotFoundError, ray not installed); confirmed pre-existing by rerunningit on a clean stash of
main.Config-resolution matrix verified directly (default ->
auto; deprecatedTrue->mxfp4+ warning; deprecatedFalse->auto; conflict -> raises;auto-> fp8/bf16 per model; hashes of the deprecated and new spellings match).Model evaluation
Real serving run on the DeepSeek path this change is riskiest for — TP8 over
2x GB300 (8 GPUs), DSpark speculative decoding (7 tokens, greedy),
--attention-config.backend FLASHINFER_MLA,--kv-cache-dtype fp8,cudagraph_mode FULL_DECODE_ONLY, driven by the new flag--attention_config.indexer_kv_dtype=mxfp4.Engine log confirms the unified flag drives both consumers to the MXFP4 path:
aime25, 4 epochs, n=120, 0 request errors, temperature 1.0 / top_p 0.95,
thinking enabled, max_tokens 150000:
Caveat worth stating plainly: aime25 is saturated for this checkpoint, so this
result confirms the MXFP4 path is intact end-to-end but cannot by itself
distinguish it from fp8 or from the pre-change build. The stronger evidence for
"no behavior change" is that
"auto"resolves to each model's previous defaultand the resolution matrix above is exhaustive over the flag combinations.
AI assistance
AI assistance (Claude Code) was used for this change. I reviewed every changed
line, ran the tests and the multi-node eval above myself, and can defend the
change end-to-end.