[Frontend] DeepSeek V4 0731 reasoning effort prompts & mappings - #50580
Conversation
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
|
Thanks for adding the 0731 prompt support. I checked the current DeepSeek documentation, an archived pre-0731 documentation snapshot, the checkpoint-bundled encoding, and the behavior at this PR head. There are three distinct contracts here, so could we clarify which one vLLM serving intends to match?
The current DeepSeek Thinking Mode documentation states that thinking is enabled by default with effort The bundled There is also a historical nuance around compatibility aliases. An official page snapshot captured on May 14, 2026 explicitly said that
I suggest keeping the renderer/encoding layer limited to canonical
If the intended target is instead strict checkpoint-encoding parity, then the current |
…rt (#13314) ### What this PR does / why we need it? This is the v0.25.1 release backport of #13313. DeepSeek-V4-Flash-0731 defines three thinking levels with distinct prompt behavior: - `low`: no reasoning-effort prefix - `high`: the existing `Reasoning Effort: Absolute maximum` prefix - `max`: the new `Reasoning Effort: Beyond maximum` prefix The vLLM v0.25.1 tokenizer maps `low` to the old high prompt and maps both `max` and `xhigh` to the old max renderer, whose prompt is now the 0731 high prompt. vLLM Ascend does not include the upstream Rust frontend, so this PR applies the same narrow Python-only monkey patch as #13313 to the active DeepSeek V4 tokenizer and renderer path. The patch keeps the existing OpenAI compatibility aliases (`minimal`/`medium` map to `high`, and `xhigh` maps to `max`) and becomes a no-op once the supported vLLM includes the Python support from vllm-project/vllm#50580. ### Does this PR introduce _any_ user-facing change? Yes. DeepSeek-V4-Flash-0731 requests using `reasoning_effort=low`, `high`, or `max` now render the checkpoint's official prompt for that level on the v0.25.1 release stack. ### How was this patch tested? - Verified imports resolve to the dedicated vLLM `v0.25.1` checkout at commit `752a3a504485790a2e8491cacbb35c137339ad34` and this `releases/v0.25.1rc` worktree. - `python -m pytest -q tests/ut/patch/platform/test_deepseek_v4_thinking.py` - Result: `7 passed` - `bash format.sh ci` - Result: all configured checks passed, including ruff, codespell, typos, markdownlint, gitleaks, and repository-local checks. - The release branch tracks `.github/workflows/scripts/gitleaks.sh` as non-executable, so the check temporarily used an executable mode plus the official `gitleaks v8.30.1 linux_arm64` binary; no unrelated mode change is included. - Loaded the tokenizer from `/models/DeepSeek-V4-Flash-0731` and compared complete rendered prompts with the checkpoint's `encoding/encoding_dsv4.py`: - `low`: exact match, SHA-256 prefix `d02a7a950b48a4b2` - `high`: exact match, SHA-256 prefix `d04fe9cf686e5b67` - `max`: exact match, SHA-256 prefix `146ff5986b6faf8e` - Repeated tokenizer factory calls on vLLM v0.25.1 return distinct dynamic subclasses, confirming the wrapper does not accumulate on one class. vllm-project/vllm@752a3a5 - vLLM version: v0.25.1 - vLLM main: vllm-project/vllm@fe784ff Signed-off-by: QwertyJack <7554089+QwertyJack@users.noreply.github.com> Co-authored-by: QwertyJack <7554089+QwertyJack@users.noreply.github.com>
|
I ran into this when working with DS V4F 0731 myself and am applying this myself. However, semantically I feel |
srinathh
left a comment
There was a problem hiding this comment.
minimal should not fall through to high because semantically that breaks expectation. We can ideally map both minimal and low to low. medium falls through & maps to high which is not unexpected.
| reasoning_effort = None | ||
| elif reasoning_effort in ("max", "xhigh"): | ||
| reasoning_effort = "max" | ||
| elif reasoning_effort == "low": |
There was a problem hiding this comment.
| elif reasoning_effort == "low": | |
| elif reasoning_effort in ("low", "minimal"): |
There was a problem hiding this comment.
| Case | Current DeepSeek V4 Flash API/ 0731 checkpoint encoding | PR |
|---|---|---|
| Omitted thinking/effort | thinking enabled, effort high | thinking enabled, effort high |
| Thinking enabled, effort omitted | high | high |
| low | low | low |
| high | high | high |
| xhigh | high | high |
| max | max | max |
| minimal / medium | low | low |
How about this? @BugenZhao @QwertyJack @srinathh
There was a problem hiding this comment.
Yes this looks good to me. Added a commit to align with that
|
Independent confirmation from a production deployment: the local-inference-lab fork images (v10, r16, r24 lines) all carry this same bug — measured via After applying the corrected mapping (high → "Absolute maximum…", max → the 0731 "Beyond maximum…" prompt from the checkpoint's So the impact is real across both the stock and fork serving paths — every max-effort request on either stack has been getting high. Related fork-side successor with golden tests: local-inference-lab#235. |
Signed-off-by: Bugen Zhao <i@bugenzhao.com>
… vLLM (#13519) ### What this PR does / why we need it? This is a follow-up to #13314 that aligns the v0.25.1 release implementation with the behavior merged in vllm-project/vllm#50580. The vLLM v0.25.1 stack predates that merge, and vLLM Ascend does not include the upstream Rust frontend renderer. This PR updates the existing Python monkey patch so the release stack uses the same request normalization and 0731 renderer behavior: - omitted thinking and effort select thinking with `high` - `minimal`, `medium`, and `low` normalize to `low` - `high`, `xhigh`, and unknown strings normalize to `high` - `max` remains `max` - `none` or explicit thinking disablement selects chat mode The renderer continues to accept canonical `low`, `high`, and `max` values and emits the exact 0731 prefixes introduced by #13314. ### Does this PR introduce _any_ user-facing change? Yes. On the v0.25.1 release stack, DeepSeek-V4-Flash-0731 now defaults to thinking with high effort and its compatibility aliases match upstream vLLM. Explicit thinking disablement continues to override the requested effort. ### How was this patch tested? - Tested against the vLLM `v0.25.1` tag at commit `752a3a504485790a2e8491cacbb35c137339ad34`. - `VLLM_VERSION=0.25.1 python -m pytest -q tests/ut/patch/platform/test_deepseek_v4_thinking.py` - Result: `22 passed` - `bash format.sh ci` - Result: all configured checks passed, including ruff, codespell, typos, markdownlint, gitleaks, and repository-local checks. - Coverage includes omitted options, explicit thinking enable/disable, every supported effort alias, unknown strings, canonical 0731 prompt prefixes, and invalid direct renderer input. vllm-project/vllm@752a3a5 - vLLM version: v0.25.1 - vLLM main: vllm-project/vllm@fe784ff Signed-off-by: QwertyJack <7554089+QwertyJack@users.noreply.github.com> Co-authored-by: QwertyJack <7554089+QwertyJack@users.noreply.github.com>
### What this PR does / why we need it? #### Upgrade baseline - Update the verified vLLM main anchor from [`2e09247c2d7b6b97d13af6e71a85bf8d1271deb6`](vllm-project/vllm@2e09247) to [`58d3918e3ea0a544ffedadad2ba84559e9c51d8f`](vllm-project/vllm@58d3918). The full upstream range is available in this [comparison](vllm-project/vllm@2e09247...58d3918). - Preserve the vLLM `0.26.0` compatibility lane while adapting the main lane to the new upstream contracts. Version gates use `vllm_version_is("0.26.0")` and are limited to real contract differences. - The changes are organized in the same order as the changed files in this PR. Each item identifies the upstream change, the downstream adaptation, and why the adaptation is required. #### Changes by file ##### 1. `.github/vllm-main-verified.commit` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Update anchor to `58d3918e` | Upgrade window [0351e9aa...58d3918e](vllm-project/vllm@0351e9a...58d3918). | Set anchor. | Source of truth for main2main workflow. | ##### 2. `vllm_ascend/patch/platform/patch_fused_moe.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Version-gate FusedMoE → FusedMoEFactory rename | [vllm #44941](vllm-project/vllm#44941) renamed `FusedMoE` to `FusedMoEFactory`. | On main, capture and patch `FusedMoEFactory`; on v0.26.0, also patch legacy `FusedMoE`. | Both lanes need the Ascend runner patch at the correct binding. | ##### 3. `vllm_ascend/models/deepseek_v4.py` / `vllm_ascend/models/minimax_m3/minimax_m3.py` / `vllm_ascend/ops/fused_moe/fused_moe.py` / `vllm_ascend/ops/fused_moe/routed_experts.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Import and use `FusedMoEFactory`; remove dead `FusedMoE` re-export | [vllm #44941](vllm-project/vllm#44941). | Replace `FusedMoE` with `FusedMoEFactory`. | Old symbol no longer exists on main. Remove stale `FusedMoE` re-export from `fused_moe.py` and dead reference in `routed_experts.py` comment. | ##### 4. `tests/ut/models/test_deepseek_v4_moe.py` / `tests/ut/models/minimax_m3/test_minimax_m3.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Update monkeypatch target to `FusedMoEFactory` | [vllm #44941](vllm-project/vllm#44941). | `"FusedMoE"` → `"FusedMoEFactory"`. | Must match the symbol imported by models. | ##### 5. `vllm_ascend/worker/model_runner_v1.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Version-gate `calculate_kv_scales` removal | [vllm #49389](vllm-project/vllm#49389) removed runtime KV-scale calculation. | Add `vllm_version_is("0.26.0")` guard. | Ascend MRV1 still supports it on v0.26.0; attribute absent on main. | | Version-gate `clear_buffer()` removal | [vllm #50721](vllm-project/vllm#50721) removed `clear_buffer()` from `RoutedExpertsCapturer`. | Wrap in `vllm_version_is("0.26.0")` guard. | On main, each routed layer overwrites current step's token rows. | ##### 6. `vllm_ascend/models/layer/attention/layer.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Remove dead `Q/K/V_SCALE_CONSTANT` references | [vllm #49389](vllm-project/vllm#49389) removed env var registrations. Module-level constants still exist. | Remove unused `q_range`/`k_range`/`v_range` initializations and dead `import envs`. | Dead-code cleanup; `DSAAttention.forward()` never used these attributes. | ##### 7. `tests/ut/patch/platform/test_deepseek_v4_thinking.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Version-gate reasoning effort expectations | [vllm #50580](vllm-project/vllm#50580) maps `low`/`minimal`/`medium` → `low`. | `vllm_version_is("0.26.0")` guard. | v0.26.0 keeps old mapping; main uses new. | ##### 8. `tests/e2e/pull_request/one_card/spec_decode/test_extract_hidden_states.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Enable `chunked_prefill` for hybrid model | [vllm #50991](vllm-project/vllm#50991) enabled prefix cache by default for Mamba/hybrid models. | `False` → `True`. | Hybrid model now requires chunked prefill. | ##### 9. `vllm_ascend/patch/platform/patch_vision.py` (new) + `vllm_ascend/patch/platform/__init__.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Patch `FusedInputNorm.forward` eps=0.0 → eps=1e-5 | [vllm #50411](vllm-project/vllm#50411) added `FusedInputNorm` with `F.batch_norm(eps=0.0)`. | Monkey-patch forward to use `eps=1e-5`; guarded with `contextlib.suppress(ImportError)`. | Upstream PyTorch 2.13.0 allows eps >= 0 for inference; vllm-ascend PyTorch 2.10.0 requires eps > 0 always. Release wheels lack `FusedInputNorm`. Remove this patch once bundled PyTorch >= 2.13.0. | ##### 10. `vllm_ascend/ops/triton/mamba/postprocess.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Add kernel signature parameters | [vllm #50432](vllm-project/vllm#50432) changed signature. | Add `CONV_STATE_DIM_FIRST`, `HAS_IDX_MAPPING`, `PRECOMPUTED_NEW_COMPUTED`, `state_dim_row_count/stride`, `idx_mapping_ptr` parameters, and `num_loops` for DS conv copy. | Must match upstream kernel contract. | ##### 11. `tests/e2e/conftest.py` / `tests/ut/spec_decode/test_speculators_vwn_eagle3.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | HunyuanVL placeholder version gate; remove unused `maybe_calc_kv_scales` mock | [vllm #49691](vllm-project/vllm#49691), #49389. | Version gate and dead-mock removal. | Adapt to upstream contract changes. | ##### 12. `vllm_ascend/patch/__init__.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Document FusedMoE → FusedMoEFactory rename and new patch_vision entry | — | Update patch registry documentation. | Keep the patch manifest in sync with reality. | #### Compatibility and review notes - Version gates use `vllm_version_is("0.26.0")` exclusively; no `hasattr` fallbacks beyond the explicitly justified `clear_buffer` guard (where the upstream change is a method removal, not a rename). - The `FusedMoE` → `FusedMoEFactory` rename is applied consistently across all call sites: `deepseek_v4.py`, `minimax_m3.py`, `fused_moe.py`, `routed_experts.py`, and `patch_fused_moe.py`. - The `layer.py` `Q/K/V_SCALE_CONSTANT` removal is a dead-code cleanup: the `DSAAttention` class initialized these tensors from `envs` module-level constants (which still exist), but never used them in `forward()`. ### Does this PR introduce _any_ user-facing change? No. This is a compatibility update; no new Ascend-specific public API is introduced. ### How was this patch tested? CI on the branch. See Buildkite workflow run for detailed results. - vLLM version: v0.26.0 - vLLM main: vllm-project/vllm@0351e9a --------- Signed-off-by: liaoqidan <1107297340@qq.com>
…rt (#13993) ### What this PR does / why we need it? This ports #13313 to the v0.26 release branch and follows the behavior already merged for v0.25.1 in #13519. The release branch is paired with vLLM `v0.26.0` at commit `568afb3a13806beb53bb2e6bd518269357b237c0`, which predates vllm-project/vllm#50580. vLLM Ascend also does not use the upstream Rust frontend renderer, so this PR adds the equivalent behavior to the active Python tokenizer and renderer path: - omitted thinking and effort select thinking with `high` - `minimal`, `medium`, and `low` normalize to `low` - `high`, `xhigh`, and unknown strings normalize to `high` - `max` remains `max` - `none` or explicit thinking disablement selects chat mode The renderer accepts canonical `low`, `high`, and `max` values and emits the exact DeepSeek-V4-Flash-0731 prompt prefixes. The patch is guarded and becomes a no-op once the supported vLLM version contains the upstream implementation. The latest vLLM main was also reviewed at commit `a311916a291c1fed3dbfb72e60f74cd778c8419d`. Since the upstream merge, the only Python tokenizer change is the unrelated vocab-size fix in vllm-project/vllm#51727; the reasoning-effort mapping and prompt rendering remain unchanged. ### Does this PR introduce _any_ user-facing change? Yes. On the v0.26 release stack, DeepSeek-V4-Flash-0731 now defaults to thinking with high effort, compatibility aliases match upstream vLLM, and explicit thinking disablement continues to override the requested effort. ### How was this patch tested? - Tested against the vLLM `v0.26.0` tag at commit `568afb3a13806beb53bb2e6bd518269357b237c0`. - `VLLM_VERSION=0.26.0 python -m pytest -q tests/ut/patch/platform/test_deepseek_v4_thinking.py` - Result: `22 passed` - `uvx --from pre-commit==4.0.1 pre-commit run --all-files --hook-stage manual` - Result: all configured hooks passed, including ruff, codespell, typos, markdownlint, gitleaks, and repository-local checks. - `python -m py_compile` on all changed Python files and `git diff --check` passed. - An isolated guard probe against vLLM main commit `a311916a291c1fed3dbfb72e60f74cd778c8419d` confirmed that both tokenizer and renderer function identities remain unchanged when upstream support exists. Coverage includes omitted options, explicit thinking enable/disable, every supported effort alias, unknown strings, canonical 0731 prompt prefixes, and invalid direct renderer input. The real checkpoint was not served through the OpenAI API in this validation, so this PR does not claim real-weight NPU HTTP end-to-end sign-off. - vLLM version: v0.26.0 - vLLM main: vllm-project/vllm@d02df74 Signed-off-by: QwertyJack <7554089+QwertyJack@users.noreply.github.com> Co-authored-by: QwertyJack <7554089+QwertyJack@users.noreply.github.com>
### What this PR does / why we need it? #### Upgrade baseline - Update the verified vLLM main anchor from [`2e09247c2d7b6b97d13af6e71a85bf8d1271deb6`](vllm-project/vllm@2e09247) to [`58d3918e3ea0a544ffedadad2ba84559e9c51d8f`](vllm-project/vllm@58d3918). The full upstream range is available in this [comparison](vllm-project/vllm@2e09247...58d3918). - Preserve the vLLM `0.26.0` compatibility lane while adapting the main lane to the new upstream contracts. Version gates use `vllm_version_is("0.26.0")` and are limited to real contract differences. - The changes are organized in the same order as the changed files in this PR. Each item identifies the upstream change, the downstream adaptation, and why the adaptation is required. #### Changes by file ##### 1. `.github/vllm-main-verified.commit` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Update anchor to `58d3918e` | Upgrade window [0351e9aa...58d3918e](vllm-project/vllm@0351e9a...58d3918). | Set anchor. | Source of truth for main2main workflow. | ##### 2. `vllm_ascend/patch/platform/patch_fused_moe.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Version-gate FusedMoE → FusedMoEFactory rename | [vllm #44941](vllm-project/vllm#44941) renamed `FusedMoE` to `FusedMoEFactory`. | On main, capture and patch `FusedMoEFactory`; on v0.26.0, also patch legacy `FusedMoE`. | Both lanes need the Ascend runner patch at the correct binding. | ##### 3. `vllm_ascend/models/deepseek_v4.py` / `vllm_ascend/models/minimax_m3/minimax_m3.py` / `vllm_ascend/ops/fused_moe/fused_moe.py` / `vllm_ascend/ops/fused_moe/routed_experts.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Import and use `FusedMoEFactory`; remove dead `FusedMoE` re-export | [vllm #44941](vllm-project/vllm#44941). | Replace `FusedMoE` with `FusedMoEFactory`. | Old symbol no longer exists on main. Remove stale `FusedMoE` re-export from `fused_moe.py` and dead reference in `routed_experts.py` comment. | ##### 4. `tests/ut/models/test_deepseek_v4_moe.py` / `tests/ut/models/minimax_m3/test_minimax_m3.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Update monkeypatch target to `FusedMoEFactory` | [vllm #44941](vllm-project/vllm#44941). | `"FusedMoE"` → `"FusedMoEFactory"`. | Must match the symbol imported by models. | ##### 5. `vllm_ascend/worker/model_runner_v1.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Version-gate `calculate_kv_scales` removal | [vllm #49389](vllm-project/vllm#49389) removed runtime KV-scale calculation. | Add `vllm_version_is("0.26.0")` guard. | Ascend MRV1 still supports it on v0.26.0; attribute absent on main. | | Version-gate `clear_buffer()` removal | [vllm #50721](vllm-project/vllm#50721) removed `clear_buffer()` from `RoutedExpertsCapturer`. | Wrap in `vllm_version_is("0.26.0")` guard. | On main, each routed layer overwrites current step's token rows. | ##### 6. `vllm_ascend/models/layer/attention/layer.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Remove dead `Q/K/V_SCALE_CONSTANT` references | [vllm #49389](vllm-project/vllm#49389) removed env var registrations. Module-level constants still exist. | Remove unused `q_range`/`k_range`/`v_range` initializations and dead `import envs`. | Dead-code cleanup; `DSAAttention.forward()` never used these attributes. | ##### 7. `tests/ut/patch/platform/test_deepseek_v4_thinking.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Version-gate reasoning effort expectations | [vllm #50580](vllm-project/vllm#50580) maps `low`/`minimal`/`medium` → `low`. | `vllm_version_is("0.26.0")` guard. | v0.26.0 keeps old mapping; main uses new. | ##### 8. `tests/e2e/pull_request/one_card/spec_decode/test_extract_hidden_states.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Enable `chunked_prefill` for hybrid model | [vllm #50991](vllm-project/vllm#50991) enabled prefix cache by default for Mamba/hybrid models. | `False` → `True`. | Hybrid model now requires chunked prefill. | ##### 9. `vllm_ascend/patch/platform/patch_vision.py` (new) + `vllm_ascend/patch/platform/__init__.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Patch `FusedInputNorm.forward` eps=0.0 → eps=1e-5 | [vllm #50411](vllm-project/vllm#50411) added `FusedInputNorm` with `F.batch_norm(eps=0.0)`. | Monkey-patch forward to use `eps=1e-5`; guarded with `contextlib.suppress(ImportError)`. | Upstream PyTorch 2.13.0 allows eps >= 0 for inference; vllm-ascend PyTorch 2.10.0 requires eps > 0 always. Release wheels lack `FusedInputNorm`. Remove this patch once bundled PyTorch >= 2.13.0. | ##### 10. `vllm_ascend/ops/triton/mamba/postprocess.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Add kernel signature parameters | [vllm #50432](vllm-project/vllm#50432) changed signature. | Add `CONV_STATE_DIM_FIRST`, `HAS_IDX_MAPPING`, `PRECOMPUTED_NEW_COMPUTED`, `state_dim_row_count/stride`, `idx_mapping_ptr` parameters, and `num_loops` for DS conv copy. | Must match upstream kernel contract. | ##### 11. `tests/e2e/conftest.py` / `tests/ut/spec_decode/test_speculators_vwn_eagle3.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | HunyuanVL placeholder version gate; remove unused `maybe_calc_kv_scales` mock | [vllm #49691](vllm-project/vllm#49691), #49389. | Version gate and dead-mock removal. | Adapt to upstream contract changes. | ##### 12. `vllm_ascend/patch/__init__.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Document FusedMoE → FusedMoEFactory rename and new patch_vision entry | — | Update patch registry documentation. | Keep the patch manifest in sync with reality. | #### Compatibility and review notes - Version gates use `vllm_version_is("0.26.0")` exclusively; no `hasattr` fallbacks beyond the explicitly justified `clear_buffer` guard (where the upstream change is a method removal, not a rename). - The `FusedMoE` → `FusedMoEFactory` rename is applied consistently across all call sites: `deepseek_v4.py`, `minimax_m3.py`, `fused_moe.py`, `routed_experts.py`, and `patch_fused_moe.py`. - The `layer.py` `Q/K/V_SCALE_CONSTANT` removal is a dead-code cleanup: the `DSAAttention` class initialized these tensors from `envs` module-level constants (which still exist), but never used them in `forward()`. ### Does this PR introduce _any_ user-facing change? No. This is a compatibility update; no new Ascend-specific public API is introduced. ### How was this patch tested? CI on the branch. See Buildkite workflow run for detailed results. - vLLM version: v0.26.0 - vLLM main: vllm-project/vllm@0351e9a --------- Signed-off-by: liaoqidan <1107297340@qq.com>
The original guard only warned when both `thinking`/`enable_thinking` and `reasoning_effort` were omitted entirely. But vllm-project#50580's regression also fires whenever thinking is explicitly enabled (thinking=True/enable_thinking=True) without an explicit reasoning_effort, since `thinking_enabled` is true either way. Key the warning off `thinking_enabled` instead of the narrower "both unset" condition, and mirror the fix in the Rust renderer by checking the resolved thinking mode rather than whether enable_thinking was passed. Signed-off-by: chelsealong <chelsealong@126.com>
…lt (#14074) ### What this PR does / why we need it? This backports the DeepSeek V4 reasoning parser behavior from vllm-project/vllm#51296 to the v0.26 release branch. PR #13993 (commit `3fd0e217f`) already backported the tokenizer and renderer behavior from vllm-project/vllm#50580. As a result, omitting both thinking controls selects thinking mode with high reasoning effort. The vLLM v0.26 parser, however, still initializes in content mode unless thinking is explicitly enabled. The DeepSeek-V4-Flash-0731 prompt ends with `<think>`, so generated output may start directly with reasoning and emit only the closing `</think>` marker. In the default request case, the parser therefore returned reasoning text in `content` and left `reasoning` empty, while an explicit high-effort request was split correctly. This patch initializes `DeepSeekV4Parser` with thinking enabled only when both `thinking` and `enable_thinking` are omitted. Explicit enablement, explicit disablement, and `reasoning_effort=none` keep their existing behavior. It also adds a state matrix and a regression test for splitting implicit-start output into reasoning and content. ### Does this PR introduce _any_ user-facing change? Yes. For DeepSeek-V4-Flash-0731, a request that omits thinking controls now returns reasoning text in the `reasoning` field and answer text in `content`, matching an explicit thinking request with high reasoning effort. Explicit thinking controls are unchanged. ### How was this patch tested? - Based on the latest `releases/v0.26.0rc` commit `59a272bb5304d69183d5f8a1f0977b476daa9fc0`. - Test machine: Linux 5.10 (`aarch64`), Python 3.12.13, with 8 Ascend NPU devices visible to `npu-smi`. - `VLLM_VERSION=0.26.0 python -m pytest -q tests/ut/patch/platform/test_deepseek_v4_thinking.py` - Result: `31 passed`. - `python -m py_compile` passed for all three changed Python files. - `bash format.sh ci` passed all configured hooks, including ruff, codespell, typos, clang-format, markdownlint, Gitleaks, ShellCheck, and repository-local checks. - `git diff --check` passed. - vLLM version: v0.26.0 - vLLM main: vllm-project/vllm@d02df74 Signed-off-by: Zheng Shoujian <zheng.shoujian@outlook.com>
Backport of vllm-project/vllm#50580 (merged upstream 2026-08-04), which aligns prompt rendering with the hosted Flash API contract. Previously only max/xhigh rendered any effort prefix (the former max text), every other effort silently mapped to a prefix-less "high", and omitted thinking defaulted to chat mode. Per the DSv4-Flash-0731 HF discussion (#39), sessions running without the proper effort prefix gradually stop thinking in agentic histories and enter self-reinforcing reasoning loops (#22). New contract: omitted thinking/effort => thinking with high; high renders the "Absolute maximum" prefix; max renders the new "Beyond maximum" prefix; low/minimal/medium render no prefix; xhigh maps to high; none selects chat mode. Upstream test additions ported; three fork-local generation-prompt tests updated to pin thinking=False where they assert chat-mode tails. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Regression from the vllm-project/vllm#50580 backport (v0.4.0): the template's default flipped to thinking mode for requests with no thinking/enable_thinking kwargs, but the parser still defaulted its state machine to CONTENT. Every such request then streamed the model's reasoning out as content (the prompt ends with an open <think> block), which on agentic clients poisons the conversation history and degrades DSML tool-call emission over long contexts (#22). The parser now mirrors the tokenizer's apply_chat_template default exactly: omitted kwargs mean thinking; explicit thinking=False or reasoning_effort="none" mean chat. Chat-mode parser tests pin thinking=False explicitly; replay samples pin the mode they build. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Backport of vllm-project#50580 (merged upstream 2026-08-04), which aligns prompt rendering with the hosted Flash API contract. Previously only max/xhigh rendered any effort prefix (the former max text), every other effort silently mapped to a prefix-less "high", and omitted thinking defaulted to chat mode. Per the DSv4-Flash-0731 HF discussion (vllm-project#39), sessions running without the proper effort prefix gradually stop thinking in agentic histories and enter self-reinforcing reasoning loops (wtdcode/vllm-backport#22). New contract: omitted thinking/effort => thinking with high; high renders the "Absolute maximum" prefix; max renders the new "Beyond maximum" prefix; low/minimal/medium render no prefix; xhigh maps to high; none selects chat mode. Upstream test additions ported; three fork-local generation-prompt tests updated to pin thinking=False where they assert chat-mode tails. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Regression from the vllm-project#50580 backport (v0.4.0): the template's default flipped to thinking mode for requests with no thinking/enable_thinking kwargs, but the parser still defaulted its state machine to CONTENT. Every such request then streamed the model's reasoning out as content (the prompt ends with an open <think> block), which on agentic clients poisons the conversation history and degrades DSML tool-call emission over long contexts (vllm-project#22). The parser now mirrors the tokenizer's apply_chat_template default exactly: omitted kwargs mean thinking; explicit thinking=False or reasoning_effort="none" mean chat. Chat-mode parser tests pin thinking=False explicitly; replay samples pin the mode they build. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
### What this PR does / why we need it? #### Upgrade baseline - Update the verified vLLM main anchor from [`2e09247c2d7b6b97d13af6e71a85bf8d1271deb6`](vllm-project/vllm@2e09247) to [`58d3918e3ea0a544ffedadad2ba84559e9c51d8f`](vllm-project/vllm@58d3918). The full upstream range is available in this [comparison](vllm-project/vllm@2e09247...58d3918). - Preserve the vLLM `0.26.0` compatibility lane while adapting the main lane to the new upstream contracts. Version gates use `vllm_version_is("0.26.0")` and are limited to real contract differences. - The changes are organized in the same order as the changed files in this PR. Each item identifies the upstream change, the downstream adaptation, and why the adaptation is required. #### Changes by file ##### 1. `.github/vllm-main-verified.commit` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Update anchor to `58d3918e` | Upgrade window [0351e9aa...58d3918e](vllm-project/vllm@0351e9a...58d3918). | Set anchor. | Source of truth for main2main workflow. | ##### 2. `vllm_ascend/patch/platform/patch_fused_moe.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Version-gate FusedMoE → FusedMoEFactory rename | [vllm #44941](vllm-project/vllm#44941) renamed `FusedMoE` to `FusedMoEFactory`. | On main, capture and patch `FusedMoEFactory`; on v0.26.0, also patch legacy `FusedMoE`. | Both lanes need the Ascend runner patch at the correct binding. | ##### 3. `vllm_ascend/models/deepseek_v4.py` / `vllm_ascend/models/minimax_m3/minimax_m3.py` / `vllm_ascend/ops/fused_moe/fused_moe.py` / `vllm_ascend/ops/fused_moe/routed_experts.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Import and use `FusedMoEFactory`; remove dead `FusedMoE` re-export | [vllm #44941](vllm-project/vllm#44941). | Replace `FusedMoE` with `FusedMoEFactory`. | Old symbol no longer exists on main. Remove stale `FusedMoE` re-export from `fused_moe.py` and dead reference in `routed_experts.py` comment. | ##### 4. `tests/ut/models/test_deepseek_v4_moe.py` / `tests/ut/models/minimax_m3/test_minimax_m3.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Update monkeypatch target to `FusedMoEFactory` | [vllm #44941](vllm-project/vllm#44941). | `"FusedMoE"` → `"FusedMoEFactory"`. | Must match the symbol imported by models. | ##### 5. `vllm_ascend/worker/model_runner_v1.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Version-gate `calculate_kv_scales` removal | [vllm #49389](vllm-project/vllm#49389) removed runtime KV-scale calculation. | Add `vllm_version_is("0.26.0")` guard. | Ascend MRV1 still supports it on v0.26.0; attribute absent on main. | | Version-gate `clear_buffer()` removal | [vllm #50721](vllm-project/vllm#50721) removed `clear_buffer()` from `RoutedExpertsCapturer`. | Wrap in `vllm_version_is("0.26.0")` guard. | On main, each routed layer overwrites current step's token rows. | ##### 6. `vllm_ascend/models/layer/attention/layer.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Remove dead `Q/K/V_SCALE_CONSTANT` references | [vllm #49389](vllm-project/vllm#49389) removed env var registrations. Module-level constants still exist. | Remove unused `q_range`/`k_range`/`v_range` initializations and dead `import envs`. | Dead-code cleanup; `DSAAttention.forward()` never used these attributes. | ##### 7. `tests/ut/patch/platform/test_deepseek_v4_thinking.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Version-gate reasoning effort expectations | [vllm #50580](vllm-project/vllm#50580) maps `low`/`minimal`/`medium` → `low`. | `vllm_version_is("0.26.0")` guard. | v0.26.0 keeps old mapping; main uses new. | ##### 8. `tests/e2e/pull_request/one_card/spec_decode/test_extract_hidden_states.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Enable `chunked_prefill` for hybrid model | [vllm #50991](vllm-project/vllm#50991) enabled prefix cache by default for Mamba/hybrid models. | `False` → `True`. | Hybrid model now requires chunked prefill. | ##### 9. `vllm_ascend/patch/platform/patch_vision.py` (new) + `vllm_ascend/patch/platform/__init__.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Patch `FusedInputNorm.forward` eps=0.0 → eps=1e-5 | [vllm #50411](vllm-project/vllm#50411) added `FusedInputNorm` with `F.batch_norm(eps=0.0)`. | Monkey-patch forward to use `eps=1e-5`; guarded with `contextlib.suppress(ImportError)`. | Upstream PyTorch 2.13.0 allows eps >= 0 for inference; vllm-ascend PyTorch 2.10.0 requires eps > 0 always. Release wheels lack `FusedInputNorm`. Remove this patch once bundled PyTorch >= 2.13.0. | ##### 10. `vllm_ascend/ops/triton/mamba/postprocess.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Add kernel signature parameters | [vllm #50432](vllm-project/vllm#50432) changed signature. | Add `CONV_STATE_DIM_FIRST`, `HAS_IDX_MAPPING`, `PRECOMPUTED_NEW_COMPUTED`, `state_dim_row_count/stride`, `idx_mapping_ptr` parameters, and `num_loops` for DS conv copy. | Must match upstream kernel contract. | ##### 11. `tests/e2e/conftest.py` / `tests/ut/spec_decode/test_speculators_vwn_eagle3.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | HunyuanVL placeholder version gate; remove unused `maybe_calc_kv_scales` mock | [vllm #49691](vllm-project/vllm#49691), #49389. | Version gate and dead-mock removal. | Adapt to upstream contract changes. | ##### 12. `vllm_ascend/patch/__init__.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Document FusedMoE → FusedMoEFactory rename and new patch_vision entry | — | Update patch registry documentation. | Keep the patch manifest in sync with reality. | #### Compatibility and review notes - Version gates use `vllm_version_is("0.26.0")` exclusively; no `hasattr` fallbacks beyond the explicitly justified `clear_buffer` guard (where the upstream change is a method removal, not a rename). - The `FusedMoE` → `FusedMoEFactory` rename is applied consistently across all call sites: `deepseek_v4.py`, `minimax_m3.py`, `fused_moe.py`, `routed_experts.py`, and `patch_fused_moe.py`. - The `layer.py` `Q/K/V_SCALE_CONSTANT` removal is a dead-code cleanup: the `DSAAttention` class initialized these tensors from `envs` module-level constants (which still exist), but never used them in `forward()`. ### Does this PR introduce _any_ user-facing change? No. This is a compatibility update; no new Ascend-specific public API is introduced. ### How was this patch tested? CI on the branch. See Buildkite workflow run for detailed results. - vLLM version: v0.26.0 - vLLM main: vllm-project/vllm@0351e9a --------- Signed-off-by: liaoqidan <1107297340@qq.com>
### What this PR does / why we need it? #### Upgrade baseline - Update the verified vLLM main anchor from [`2e09247c2d7b6b97d13af6e71a85bf8d1271deb6`](vllm-project/vllm@2e09247) to [`58d3918e3ea0a544ffedadad2ba84559e9c51d8f`](vllm-project/vllm@58d3918). The full upstream range is available in this [comparison](vllm-project/vllm@2e09247...58d3918). - Preserve the vLLM `0.26.0` compatibility lane while adapting the main lane to the new upstream contracts. Version gates use `vllm_version_is("0.26.0")` and are limited to real contract differences. - The changes are organized in the same order as the changed files in this PR. Each item identifies the upstream change, the downstream adaptation, and why the adaptation is required. #### Changes by file ##### 1. `.github/vllm-main-verified.commit` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Update anchor to `58d3918e` | Upgrade window [0351e9aa...58d3918e](vllm-project/vllm@0351e9a...58d3918). | Set anchor. | Source of truth for main2main workflow. | ##### 2. `vllm_ascend/patch/platform/patch_fused_moe.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Version-gate FusedMoE → FusedMoEFactory rename | [vllm #44941](vllm-project/vllm#44941) renamed `FusedMoE` to `FusedMoEFactory`. | On main, capture and patch `FusedMoEFactory`; on v0.26.0, also patch legacy `FusedMoE`. | Both lanes need the Ascend runner patch at the correct binding. | ##### 3. `vllm_ascend/models/deepseek_v4.py` / `vllm_ascend/models/minimax_m3/minimax_m3.py` / `vllm_ascend/ops/fused_moe/fused_moe.py` / `vllm_ascend/ops/fused_moe/routed_experts.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Import and use `FusedMoEFactory`; remove dead `FusedMoE` re-export | [vllm #44941](vllm-project/vllm#44941). | Replace `FusedMoE` with `FusedMoEFactory`. | Old symbol no longer exists on main. Remove stale `FusedMoE` re-export from `fused_moe.py` and dead reference in `routed_experts.py` comment. | ##### 4. `tests/ut/models/test_deepseek_v4_moe.py` / `tests/ut/models/minimax_m3/test_minimax_m3.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Update monkeypatch target to `FusedMoEFactory` | [vllm #44941](vllm-project/vllm#44941). | `"FusedMoE"` → `"FusedMoEFactory"`. | Must match the symbol imported by models. | ##### 5. `vllm_ascend/worker/model_runner_v1.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Version-gate `calculate_kv_scales` removal | [vllm #49389](vllm-project/vllm#49389) removed runtime KV-scale calculation. | Add `vllm_version_is("0.26.0")` guard. | Ascend MRV1 still supports it on v0.26.0; attribute absent on main. | | Version-gate `clear_buffer()` removal | [vllm #50721](vllm-project/vllm#50721) removed `clear_buffer()` from `RoutedExpertsCapturer`. | Wrap in `vllm_version_is("0.26.0")` guard. | On main, each routed layer overwrites current step's token rows. | ##### 6. `vllm_ascend/models/layer/attention/layer.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Remove dead `Q/K/V_SCALE_CONSTANT` references | [vllm #49389](vllm-project/vllm#49389) removed env var registrations. Module-level constants still exist. | Remove unused `q_range`/`k_range`/`v_range` initializations and dead `import envs`. | Dead-code cleanup; `DSAAttention.forward()` never used these attributes. | ##### 7. `tests/ut/patch/platform/test_deepseek_v4_thinking.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Version-gate reasoning effort expectations | [vllm #50580](vllm-project/vllm#50580) maps `low`/`minimal`/`medium` → `low`. | `vllm_version_is("0.26.0")` guard. | v0.26.0 keeps old mapping; main uses new. | ##### 8. `tests/e2e/pull_request/one_card/spec_decode/test_extract_hidden_states.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Enable `chunked_prefill` for hybrid model | [vllm #50991](vllm-project/vllm#50991) enabled prefix cache by default for Mamba/hybrid models. | `False` → `True`. | Hybrid model now requires chunked prefill. | ##### 9. `vllm_ascend/patch/platform/patch_vision.py` (new) + `vllm_ascend/patch/platform/__init__.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Patch `FusedInputNorm.forward` eps=0.0 → eps=1e-5 | [vllm #50411](vllm-project/vllm#50411) added `FusedInputNorm` with `F.batch_norm(eps=0.0)`. | Monkey-patch forward to use `eps=1e-5`; guarded with `contextlib.suppress(ImportError)`. | Upstream PyTorch 2.13.0 allows eps >= 0 for inference; vllm-ascend PyTorch 2.10.0 requires eps > 0 always. Release wheels lack `FusedInputNorm`. Remove this patch once bundled PyTorch >= 2.13.0. | ##### 10. `vllm_ascend/ops/triton/mamba/postprocess.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Add kernel signature parameters | [vllm #50432](vllm-project/vllm#50432) changed signature. | Add `CONV_STATE_DIM_FIRST`, `HAS_IDX_MAPPING`, `PRECOMPUTED_NEW_COMPUTED`, `state_dim_row_count/stride`, `idx_mapping_ptr` parameters, and `num_loops` for DS conv copy. | Must match upstream kernel contract. | ##### 11. `tests/e2e/conftest.py` / `tests/ut/spec_decode/test_speculators_vwn_eagle3.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | HunyuanVL placeholder version gate; remove unused `maybe_calc_kv_scales` mock | [vllm #49691](vllm-project/vllm#49691), #49389. | Version gate and dead-mock removal. | Adapt to upstream contract changes. | ##### 12. `vllm_ascend/patch/__init__.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Document FusedMoE → FusedMoEFactory rename and new patch_vision entry | — | Update patch registry documentation. | Keep the patch manifest in sync with reality. | #### Compatibility and review notes - Version gates use `vllm_version_is("0.26.0")` exclusively; no `hasattr` fallbacks beyond the explicitly justified `clear_buffer` guard (where the upstream change is a method removal, not a rename). - The `FusedMoE` → `FusedMoEFactory` rename is applied consistently across all call sites: `deepseek_v4.py`, `minimax_m3.py`, `fused_moe.py`, `routed_experts.py`, and `patch_fused_moe.py`. - The `layer.py` `Q/K/V_SCALE_CONSTANT` removal is a dead-code cleanup: the `DSAAttention` class initialized these tensors from `envs` module-level constants (which still exist), but never used them in `forward()`. ### Does this PR introduce _any_ user-facing change? No. This is a compatibility update; no new Ascend-specific public API is introduced. ### How was this patch tested? CI on the branch. See Buildkite workflow run for detailed results. - vLLM version: v0.26.0 - vLLM main: vllm-project/vllm@0351e9a --------- Signed-off-by: liaoqidan <1107297340@qq.com>
DeepSeek V4 defines low as the no-prefix baseline, high with the Absolute maximum prefix, and max with the Beyond maximum prefix. The renderer previously made low and high identical and used the high prompt for max; align the mapping and add exact prompt tests while preserving none as the chat-mode disable sentinel. References: https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash-0731/blob/main/encoding/README.md#reasoning-effort https://api-docs.deepseek.com/guides/thinking_mode vllm-project/vllm#50580 Signed-off-by: Ace Eldeib <aeldeib@coreweave.com>
DeepSeek V4 defines low as the no-prefix baseline, high with the Absolute maximum prefix, and max with the Beyond maximum prefix. The renderer previously made low and high identical and used the high prompt for max; align the mapping and add exact prompt tests while preserving none as the chat-mode disable sentinel. References: https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash-0731/blob/main/encoding/README.md#reasoning-effort https://api-docs.deepseek.com/guides/thinking_mode vllm-project/vllm#50580 Signed-off-by: Ace Eldeib <aeldeib@coreweave.com>
DeepSeek V4 defines low as the no-prefix baseline, high with the Absolute maximum prefix, and max with the Beyond maximum prefix. Align the renderer and pin async-openai to its one-line max-enum fix so Responses requests reach that mapping. References: https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash-0731/blob/main/encoding/README.md#reasoning-effort https://api-docs.deepseek.com/guides/thinking_mode 64bit/async-openai@3f9a127 vllm-project/vllm#50580 Signed-off-by: Ace Eldeib <aeldeib@coreweave.com>
DeepSeek V4 defines low as the no-prefix baseline, high with the Absolute maximum prefix, and max with the Beyond maximum prefix. Align the renderer and pin async-openai to its one-line max-enum fix so Responses requests reach that mapping. References: https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash-0731/blob/main/encoding/README.md#reasoning-effort https://api-docs.deepseek.com/guides/thinking_mode 64bit/async-openai@3f9a127 vllm-project/vllm#50580 Signed-off-by: Ace Eldeib <aeldeib@coreweave.com>
DeepSeek V4 defines low as the no-prefix baseline, high with the Absolute maximum prefix, and max with the Beyond maximum prefix. Align the mapping and add exact prompt tests while preserving none as the chat-mode disable sentinel. References: https://huggingface.co/deepseek-ai/DeepSeek-V4-Flash-0731/blob/main/encoding/README.md#reasoning-effort https://api-docs.deepseek.com/guides/thinking_mode vllm-project/vllm#50580 Signed-off-by: Ace Eldeib <aeldeib@coreweave.com>
### What this PR does / why we need it? #### Upgrade baseline - Update the verified vLLM main anchor from [`2e09247c2d7b6b97d13af6e71a85bf8d1271deb6`](vllm-project/vllm@2e09247) to [`58d3918e3ea0a544ffedadad2ba84559e9c51d8f`](vllm-project/vllm@58d3918). The full upstream range is available in this [comparison](vllm-project/vllm@2e09247...58d3918). - Preserve the vLLM `0.26.0` compatibility lane while adapting the main lane to the new upstream contracts. Version gates use `vllm_version_is("0.26.0")` and are limited to real contract differences. - The changes are organized in the same order as the changed files in this PR. Each item identifies the upstream change, the downstream adaptation, and why the adaptation is required. #### Changes by file ##### 1. `.github/vllm-main-verified.commit` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Update anchor to `58d3918e` | Upgrade window [0351e9aa...58d3918e](vllm-project/vllm@0351e9a...58d3918). | Set anchor. | Source of truth for main2main workflow. | ##### 2. `vllm_ascend/patch/platform/patch_fused_moe.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Version-gate FusedMoE → FusedMoEFactory rename | [vllm #44941](vllm-project/vllm#44941) renamed `FusedMoE` to `FusedMoEFactory`. | On main, capture and patch `FusedMoEFactory`; on v0.26.0, also patch legacy `FusedMoE`. | Both lanes need the Ascend runner patch at the correct binding. | ##### 3. `vllm_ascend/models/deepseek_v4.py` / `vllm_ascend/models/minimax_m3/minimax_m3.py` / `vllm_ascend/ops/fused_moe/fused_moe.py` / `vllm_ascend/ops/fused_moe/routed_experts.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Import and use `FusedMoEFactory`; remove dead `FusedMoE` re-export | [vllm #44941](vllm-project/vllm#44941). | Replace `FusedMoE` with `FusedMoEFactory`. | Old symbol no longer exists on main. Remove stale `FusedMoE` re-export from `fused_moe.py` and dead reference in `routed_experts.py` comment. | ##### 4. `tests/ut/models/test_deepseek_v4_moe.py` / `tests/ut/models/minimax_m3/test_minimax_m3.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Update monkeypatch target to `FusedMoEFactory` | [vllm #44941](vllm-project/vllm#44941). | `"FusedMoE"` → `"FusedMoEFactory"`. | Must match the symbol imported by models. | ##### 5. `vllm_ascend/worker/model_runner_v1.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Version-gate `calculate_kv_scales` removal | [vllm #49389](vllm-project/vllm#49389) removed runtime KV-scale calculation. | Add `vllm_version_is("0.26.0")` guard. | Ascend MRV1 still supports it on v0.26.0; attribute absent on main. | | Version-gate `clear_buffer()` removal | [vllm #50721](vllm-project/vllm#50721) removed `clear_buffer()` from `RoutedExpertsCapturer`. | Wrap in `vllm_version_is("0.26.0")` guard. | On main, each routed layer overwrites current step's token rows. | ##### 6. `vllm_ascend/models/layer/attention/layer.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Remove dead `Q/K/V_SCALE_CONSTANT` references | [vllm #49389](vllm-project/vllm#49389) removed env var registrations. Module-level constants still exist. | Remove unused `q_range`/`k_range`/`v_range` initializations and dead `import envs`. | Dead-code cleanup; `DSAAttention.forward()` never used these attributes. | ##### 7. `tests/ut/patch/platform/test_deepseek_v4_thinking.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Version-gate reasoning effort expectations | [vllm #50580](vllm-project/vllm#50580) maps `low`/`minimal`/`medium` → `low`. | `vllm_version_is("0.26.0")` guard. | v0.26.0 keeps old mapping; main uses new. | ##### 8. `tests/e2e/pull_request/one_card/spec_decode/test_extract_hidden_states.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Enable `chunked_prefill` for hybrid model | [vllm #50991](vllm-project/vllm#50991) enabled prefix cache by default for Mamba/hybrid models. | `False` → `True`. | Hybrid model now requires chunked prefill. | ##### 9. `vllm_ascend/patch/platform/patch_vision.py` (new) + `vllm_ascend/patch/platform/__init__.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Patch `FusedInputNorm.forward` eps=0.0 → eps=1e-5 | [vllm #50411](vllm-project/vllm#50411) added `FusedInputNorm` with `F.batch_norm(eps=0.0)`. | Monkey-patch forward to use `eps=1e-5`; guarded with `contextlib.suppress(ImportError)`. | Upstream PyTorch 2.13.0 allows eps >= 0 for inference; vllm-ascend PyTorch 2.10.0 requires eps > 0 always. Release wheels lack `FusedInputNorm`. Remove this patch once bundled PyTorch >= 2.13.0. | ##### 10. `vllm_ascend/ops/triton/mamba/postprocess.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Add kernel signature parameters | [vllm #50432](vllm-project/vllm#50432) changed signature. | Add `CONV_STATE_DIM_FIRST`, `HAS_IDX_MAPPING`, `PRECOMPUTED_NEW_COMPUTED`, `state_dim_row_count/stride`, `idx_mapping_ptr` parameters, and `num_loops` for DS conv copy. | Must match upstream kernel contract. | ##### 11. `tests/e2e/conftest.py` / `tests/ut/spec_decode/test_speculators_vwn_eagle3.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | HunyuanVL placeholder version gate; remove unused `maybe_calc_kv_scales` mock | [vllm #49691](vllm-project/vllm#49691), #49389. | Version gate and dead-mock removal. | Adapt to upstream contract changes. | ##### 12. `vllm_ascend/patch/__init__.py` | Change | Upstream change | Downstream adaptation | Why | |---|---|---|---| | Document FusedMoE → FusedMoEFactory rename and new patch_vision entry | — | Update patch registry documentation. | Keep the patch manifest in sync with reality. | #### Compatibility and review notes - Version gates use `vllm_version_is("0.26.0")` exclusively; no `hasattr` fallbacks beyond the explicitly justified `clear_buffer` guard (where the upstream change is a method removal, not a rename). - The `FusedMoE` → `FusedMoEFactory` rename is applied consistently across all call sites: `deepseek_v4.py`, `minimax_m3.py`, `fused_moe.py`, `routed_experts.py`, and `patch_fused_moe.py`. - The `layer.py` `Q/K/V_SCALE_CONSTANT` removal is a dead-code cleanup: the `DSAAttention` class initialized these tensors from `envs` module-level constants (which still exist), but never used them in `forward()`. ### Does this PR introduce _any_ user-facing change? No. This is a compatibility update; no new Ascend-specific public API is introduced. ### How was this patch tested? CI on the branch. See Buildkite workflow run for detailed results. - vLLM version: v0.26.0 - vLLM main: vllm-project/vllm@0351e9a --------- Signed-off-by: liaoqidan <1107297340@qq.com>
Purpose
Align DeepSeek V4 Flash prompt rendering with DeepSeek-V4-Flash-0731 and the current hosted API's model-specific effort mapping.
The renderer accepts the canonical 0731 levels:
lowemits no prefix,highemits the "Absolute maximum" prefix, andmaxemits the "Beyond maximum" prefix. DSML parsing and output syntax retain their existing behavior.The request normalization follows the public
deepseek-v4-flash actual mapped efforttable: omitted thinking and effort select thinking withhigh; omitted effort in thinking mode selectshigh;xhighmaps tohigh;low,high, andmaxstay unchanged; andnoneselects chat mode.minimalandmediummap tolowas explicit vLLM compatibility aliases.Root Cause
The existing normalization defaulted to chat mode, mapped
xhightomax, and mappedminimalandmediumtohigh. It also rendered the former max prompt formaxrequests. This PR aligns the Python tokenizer and Rust renderer with the hosted Flash API contract while preserving the checkpoint's canonical prompt text.Test Plan
low, so they continue to validate canonical encoding independently from hosted API normalization.Test Result
PYTHONPATH=. .venv/bin/python -m pytest tests/tokenizers_/test_deepseek_v4.py -q— 26 passed.cargo nextest run -p vllm-chat renderer::deepseek_v4::tests— 13 passed, 272 skipped.pre-commit run ruff-check,pre-commit run ruff-format,cargo fmt --check, andgit diff --check— passed.Duplicate Check
No open PR implements the DeepSeek V4 Flash 0731 prompt update together with the hosted API effort normalization. #43876 covers
wo_eosandcontinue_final_message; #43401 covers generic request-layer reasoning activation; #41241 covers DSML argument parsing; and #48645 tracks parser recovery for a missing</think>.AI Assistance
AI assistance was used to compare the official checkpoint encoding and API documentation, implement the renderer changes, and run the listed checks.