Skip to content

[Feature][MRV2] Adapt extract_hidden_states for Model Runner V2 - #14699

Open
yjyang62 wants to merge 4 commits into
vllm-project:mainfrom
yjyang62:mrv2-extract-hidden-states-5b6a
Open

[Feature][MRV2] Adapt extract_hidden_states for Model Runner V2#14699
yjyang62 wants to merge 4 commits into
vllm-project:mainfrom
yjyang62:mrv2-extract-hidden-states-5b6a

Conversation

@yjyang62

@yjyang62 yjyang62 commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

What this PR does / why we need it?

Upstream vLLM PR #49811 added Model Runner V2 support for extract_hidden_states. Ascend already supports this method on Model Runner V1, but Ascend MRV2 previously raised NotImplementedError in init_speculator, and the Ascend V2 KV allocate/reshape path treated HiddenStateCacheSpec like MLA K/V (split tensors).

This PR adapts Ascend MRV2:

  • thin-wraps upstream ExtractHiddenStatesSpeculator as AscendExtractHiddenStatesSpeculator and dispatches it from Ascend init_speculator (depends on upstream PR #49811 / a vLLM build that ships that module)
  • forces use_aux_hidden_state_outputs=True for extract_hidden_states in NPUModelRunner when the pinned vLLM omits the method from the GPU allow-list
  • keeps HiddenStateCacheSpec / cache_only_layers on a single-tensor allocate + reshape path in MRV2 attn_utils
  • adds MRV2 e2e cases and documents VLLM_USE_V2_MODEL_RUNNER=1

Does this PR introduce any user-facing change?

Yes. With VLLM_USE_V2_MODEL_RUNNER=1, users can run extract_hidden_states on Model Runner V2 (once the Ascend image/vLLM includes PR #49811).

How was this patch tested?

  • Unit tests (CPU), 6 passed:
    • tests/ut/worker/test_extract_hidden_states_speculator_v2.py
    • tests/ut/worker/test_attn_utils_v2.py::test_mrv2_allocates_and_reshapes_hidden_state_cache
  • E2E cases added in tests/e2e/pull_request/one_card/spec_decode/test_extract_hidden_states.py (dense_eager_mrv2, hybrid_dummy_eager_mrv2). NPU e2e was not run in the cloud agent environment (no Ascend device); please verify on Atlas hardware.
pytest -sv tests/ut/worker/test_extract_hidden_states_speculator_v2.py \
  tests/ut/worker/test_attn_utils_v2.py::test_mrv2_allocates_and_reshapes_hidden_state_cache

export VLLM_USE_V2_MODEL_RUNNER=1
pytest -sv tests/e2e/pull_request/one_card/spec_decode/test_extract_hidden_states.py -k mrv2

- vLLM version: v0.27.1
- vLLM main: https://github.com/vllm-project/vllm/commit/58d3918e3ea0a544ffedadad2ba84559e9c51d8f

@yjyang62
yjyang62 requested review from LCAIZJ and Yikun as code owners August 21, 2026 02:22
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enables extract_hidden_states functionality for Model Runner V2 on Ascend hardware. It integrates upstream vLLM changes by creating an Ascend-specific wrapper for the speculator, ensuring correct NPU memory handling for hidden state caches, and enforcing necessary configuration flags to support the feature when running in V2 mode.

Highlights

  • Model Runner V2 Support: Implemented support for extract_hidden_states in Model Runner V2 by wrapping the upstream ExtractHiddenStatesSpeculator as AscendExtractHiddenStatesSpeculator.
  • NPU Memory Management: Forced use_aux_hidden_state_outputs=True in NPUModelRunner and ensured HiddenStateCacheSpec maintains a single-tensor allocation and reshape path in MRV2.
  • Testing and Documentation: Added unit tests for the new speculator and NPU memory allocation, along with E2E cases and updated user documentation for enabling MRV2.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@cursor
cursor Bot force-pushed the mrv2-extract-hidden-states-5b6a branch 3 times, most recently from 66db379 to f9b2fc6 Compare August 21, 2026 02:23

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

Suggested PR Title:\n\nmarkdown\n[Attention][Feature] Support Model Runner V2 for extract_hidden_states speculative decoding on Ascend\n\n\nSuggested PR Summary:\n\nmarkdown\n### What this PR does / why we need it?\nThis pull request adds support for Model Runner V2 (MRV2) for the `extract_hidden_states` speculative decoding mode on Ascend. It thin-wraps upstream vLLM's `ExtractHiddenStatesSpeculator`, adds dispatching in `init_speculator`, ensures auxiliary hidden state outputs are enabled, and handles allocation and reshaping for `HiddenStateCacheSpec` on a single-tensor path.\n\nFeedback on the changes suggests reusing the existing helper function `_allocate_int8_cache_tensor` in `vllm_ascend/worker/v2/attn_utils.py` to avoid duplicating aligned/unaligned tensor allocation logic.\n\n### Does this PR introduce _any_ user-facing change?\nYes, users can now enable Model Runner V2 for `extract_hidden_states` on Ascend by setting the environment variable `VLLM_USE_V2_MODEL_RUNNER=1`.\n\n### How was this patch tested?\nThe changes were tested with new end-to-end tests in `test_extract_hidden_states.py` covering dense and hybrid models with MRV2, as well as unit tests in `test_attn_utils_v2.py` and `test_extract_hidden_states_speculator_v2.py`.\n

Comment on lines +649 to +678
if vllm_config.kv_transfer_config is None:
tensor = torch.zeros(kv_cache_tensor.size, dtype=torch.int8, device=device)
else:
tensor = torch.zeros(
kv_cache_tensor.size + alignment,
dtype=torch.int8,
device=device,
)
tensor = _align_memory(tensor, alignment)[: kv_cache_tensor.size]

if has_mamba and has_hidden:
# Keep Mamba and hidden-state dumps on separate physical buffers
# so float32 SSM writes cannot corrupt bfloat16 hidden states.
for layer_name in kv_cache_tensor.shared_by:
if is_hidden_state_cache_spec(layer_kv_cache_spec[layer_name]):
if vllm_config.kv_transfer_config is None:
hidden_tensor = torch.zeros(kv_cache_tensor.size, dtype=torch.int8, device=device)
else:
hidden_tensor = torch.zeros(
kv_cache_tensor.size + alignment,
dtype=torch.int8,
device=device,
)
hidden_tensor = _align_memory(hidden_tensor, alignment)[: kv_cache_tensor.size]
kv_cache_raw_tensors[layer_name] = hidden_tensor
else:
kv_cache_raw_tensors[layer_name] = tensor
else:
for layer_name in kv_cache_tensor.shared_by:
kv_cache_raw_tensors[layer_name] = tensor

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Instead of duplicating the aligned/unaligned tensor allocation logic for tensor and hidden_tensor, you can reuse the existing helper function _allocate_int8_cache_tensor defined in the same file. This improves code maintainability and readability.

            tensor = _allocate_int8_cache_tensor(kv_cache_tensor.size, alignment, device)

            if has_mamba and has_hidden:
                # Keep Mamba and hidden-state dumps on separate physical buffers
                # so float32 SSM writes cannot corrupt bfloat16 hidden states.
                for layer_name in kv_cache_tensor.shared_by:
                    if is_hidden_state_cache_spec(layer_kv_cache_spec[layer_name]):
                        hidden_tensor = _allocate_int8_cache_tensor(kv_cache_tensor.size, alignment, device)
                        kv_cache_raw_tensors[layer_name] = hidden_tensor
                    else:
                        kv_cache_raw_tensors[layer_name] = tensor
            else:
                for layer_name in kv_cache_tensor.shared_by:
                    kv_cache_raw_tensors[layer_name] = tensor

@github-actions github-actions Bot added documentation Improvements or additions to documentation module:tests labels Aug 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

👋 Hi! Thank you for contributing to the vLLM Ascend project. The following points will speed up your PR merge:‌‌

  • A PR should do only one thing, smaller PRs enable faster reviews.
  • Every PR should include unit tests and end-to-end tests ‌to ensure it works and is not broken by other future PRs.
  • Write the commit message by fulfilling the PR description to help reviewer and future developers understand.

If CI fails, you can run linting and testing checks locally according Contributing and Testing.

@cursor
cursor Bot force-pushed the mrv2-extract-hidden-states-5b6a branch from f9b2fc6 to 10bcc54 Compare August 21, 2026 02:25
Port upstream vLLM PR #49811 so Ascend NPUModelRunner V2 can dispatch
extract_hidden_states, request aux hidden outputs, and keep
HiddenStateCacheSpec on a single-tensor allocate/reshape path.

Signed-off-by: yjyang62 <yangjinyang5@huawei.com>
Drop the vendored propose/load implementation and thin-wrap upstream
vLLM PR #49811 so Ascend only owns dispatch, aux enabling, and NPU KV
layout for HiddenStateCacheSpec.

Signed-off-by: yjyang62 <yangjinyang5@huawei.com>
@yjyang62
yjyang62 force-pushed the mrv2-extract-hidden-states-5b6a branch from 10bcc54 to 4bddca1 Compare August 21, 2026 02:35
@yjyang62 yjyang62 changed the title [Feat][MRV2] Adapt extract_hidden_states for Model Runner V2 [Feature][MRV2] Adapt extract_hidden_states for Model Runner V2 Aug 21, 2026
yjyang62 and others added 2 commits August 21, 2026 03:01
Signed-off-by: yjyang62 <yangjinyang5@huawei.com>
Upstream vLLM PR #49811 is not in the CI pin yet, so mypy fails with
import-not-found on the thin Ascend wrapper. Mark the import until the
module lands in the pinned vLLM tree.

Signed-off-by: yjyang62 <yangjinyang5@huawei.com>

Co-authored-by: yjyang62 <yjyang62@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation module:tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant