Skip to content

[Transformers backend] Find attention with a fuser and attach vLLM's layer to it - #54941

Merged
hmellor merged 22 commits into
vllm-project:mainfrom
bohnstingl:hf_attn-module
Sep 4, 2026
Merged

hmellor merged 22 commits into
vllm-project:mainfrom
bohnstingl:hf_attn-module

Conversation

@bohnstingl

@bohnstingl bohnstingl commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Purpose

Teach the Transformers modeling backend to find each layer's attention with a fuser, attach
vLLM's attention layer to the HF module that dispatches it, and resolve the softmax scale at
construction. create_attention_instances built one Attention per layer into
self.attention_instances, a plain dict. nn.Module.__setattr__ does not register a dict, so
none of those layers was part of the module tree, and vllm_attention_forward reached its own
with attention_instances[module.layer_idx]. The MLA path already worked around half of this by
attaching its instance as mla_module._vllm_mla_attn, precisely so the layer appeared in
named_modules() and ran its process_weights_after_loading.

AttentionFuser (new). A module dispatches attention if its forward binds
ALL_ATTENTION_FUNCTIONS.get_interface(...) to a local and calls it exactly once. That is read
from the forward's source, not from the fx trace: trace is deliberately partial-tolerant and
returns whatever graph it managed, so a missing interface node does not mean the module has no
dispatch. Keying off self.fusers would be wrong for the same reason a QKV fuser is not the
right handle -- a model can dispatch through the interface without its projections fusing at all.
The fuser also carries the scaling= expression it found, and answers layer_index from the
module's own layer_idx.

Fusers are now plural per module. get_fusers returns every fuser that applies: at most one
that redefines the forward (redefines_forward, mutually exclusive because each rewrite starts
from the original source) plus any number that leave it alone. AttentionFuser is the first of
the latter kind, so a Llama attention comes back as [QKVFuser, AttentionFuser] and a Gemma 4
attention -- whose QKV fusion is rejected -- as [AttentionFuser]. This also drops a special case:
an MLAFuser that fails validate used to be rebuilt as a bare attention marker, and now simply
falls out of the list while the AttentionFuser stands on its own.

This fixes two latent bugs and removes one requirement:

  1. impl.scale was written per forward, which one compiled artifact per layer class cannot
    preserve.
    Every layer was built with the Llama default head_size**-0.5 and corrected from
    the HF module's scaling kwarg on every call. That correction only survives because
    module.layer_idx is an int baked into the graph, so Dynamo compiles the stack layer by
    layer. The moment one artifact is reused across layers -- the point of _USE_LAYERNAME /
    LayerName hoisting -- only the first layer's Python frame runs and layers 1..N silently keep
    the default. Wrong for any model whose scale is not derived from head_size. The scale is now
    read from the scaling= argument the module hands the interface, once, at construction.
    Reading the argument rather than probing module.scaling also matters on its own: OPT applies
    head_size**-0.5 to the query itself and then declares scaling=1.0, so probing the attribute
    would scale twice.
  2. The dict index is itself what costs an artifact per layer. With the instance attached,
    getattr(module, "attn") is the same expression in every layer, so one graph can serve the
    whole stack.
  3. The attention_instances kwarg no longer has to be drilled down. With nothing to pass, the
    registry gate relaxes from is_backend_compatible() (_supports_attention_backend, documented
    upstream as "fully pass the kwargs through all modules up to the Attention layer") to
    _can_set_attn_implementation(), which asks only that the model dispatches through the
    interface.

Attaching also makes the backend's module tree the same shape as an in-tree model's, so anything
that walks it -- process_weights_after_loading, a state dict, model.to(device) -- finds
attention where it expects to. The attribute is attn, the name an in-tree model uses
(LlamaAttention.attn), which is also what maybe_remap_kv_scale_name writes
(.self_attn.attn.{k,v}_scale), so a checkpoint's FP8 KV-cache scales land on it with no mapper
entry. _vllm_mla_attn is gone; it was never read outside create_attention_instances.

Test Plan

New tests in tests/models/transformers/test_backend.py, alongside the device-free ones already
there. They need no accelerator, no weights and no network: the HF stacks are built from
AutoConfig.for_model(...) on the meta device.

pytest -q tests/models/transformers/fusers/
pytest -q tests/models/transformers/test_backend.py \
  -k "attention_dispatch or attention_scale or layer_index"
  • test_attention_dispatch_is_matched -- exactly the decoder layers' attention modules match an
    AttentionFuser, over llama, gemma4_text and deepseek_v3 (MLA).
  • test_attention_layer_index_is_the_modules_own -- LongCat Flash gives each decoder layer two
    attention sublayers numbered 2i and 2i + 1, so num_hidden_layers is twice the length of the
    stack and the enclosing layer's position is not the index the KV cache is keyed by. Also pins
    that validate is what excludes a module whose config was not patched to dispatch to vLLM, which
    is how a vision tower is left to Transformers.
  • test_attention_scale_is_the_declared_one -- the scale is the module's, not the default.
    gemma4_text (learnable per-dim query weight, so it declares 1.0) and deepseek_v3 (yarn
    mscale) are what make this more than a tautology.
  • test_attention_scale_is_the_argument_not_the_attribute -- OPT, where the argument (1.0) and the
    attribute (head_size**-0.5) disagree.

The existing fuser suites cover the registry change; test_linear.py's QKV and packed-QKV numerics
tests now drive the real vllm_attention_forward through the attached .attn.

Test Result

$ pytest -q tests/models/transformers/fusers/
68 passed, 1 skipped in 9.85s

$ pytest -q tests/models/transformers/test_backend.py \
    -k "attention_dispatch or attention_scale or layer_index"
8 passed, 25 deselected in 1.61s

The file's other device-free tests -- embedding replacement and multimodal component marking --
pass alongside them, unchanged (3 passed).

Not yet run, and needed before merge. Everything requiring an accelerator: the rest of
tests/models/transformers/, tests/models/test_initialization.py -k Transformers, and model
evals. This changes attention construction for every model on the backend, so tests/evals/ or
vllm bench results belong here before it is reviewed for correctness. Tensor parallel is also
unexercised.

Notes for reviewers

  • Overlaps with [Bugfix] Apply attention sinks in the Transformers backend #52156 (attention sinks), which makes Attention instances visible to
    named_modules() by registering them in an nn.ModuleList rather than attaching them to the
    module that dispatches. The two need reconciling; attaching is the one that also removes the
    dict index from the traced graph and gives kv-scale remapping the name it expects.
  • Discovery is source-level on purpose. fx_utils already records the interface call as a leaf
    node, which would be the obvious hook, but trace returns a partial graph on failure and a model
    can stop tracing before the dispatch. Reading the forward's source is also what Transformers
    itself does in _can_set_attn_implementation, and it is where the scaling= argument has to come
    from regardless.
  • Deliberately not keyed off the projection fusers. A model can dispatch through the interface
    without its projections fusing at all, in which case it would never have been attached.
  • A layer with no identifiable attention module now raises rather than silently falling back to
    the dict, as does a layer whose modules claim the same layer_idx. The latter was already broken:
    two modules sharing an index would have shared one Attention.
  • AI assistance was used for this change (Claude Code).

Duplicate check

gh pr list --state open --search "transformers backend attention in:title,body" returns no other
PR changing how the backend builds or reaches its attention layers. #52156 is the only related one
and is called out above.


Essential Elements of an Effective PR Description Checklist
  • The purpose of the PR, such as "Fix some issue (link existing issues this PR will resolve)".
  • The test plan, such as providing test command.
  • The test results, such as pasting the results comparison before and after, or e2e results
  • (Optional) The necessary documentation update, such as updating supported_models.md and examples for a new model.

Signed-off-by: Thomas Ortner <boh@zurich.ibm.com>
@bohnstingl
bohnstingl requested a review from hmellor as a code owner September 2, 2026 11:21

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

…ntation`

Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
@mergify

mergify Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Documentation preview: https://vllm--54941.org.readthedocs.build/en/54941/

@mergify mergify Bot added documentation Improvements or additions to documentation new-model Requests to new models labels Sep 2, 2026
Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
@hmellor

hmellor commented Sep 2, 2026

Copy link
Copy Markdown
Member

/ci run

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #86894 for commit 533164e434ac.

@hmellor hmellor changed the title [Transformer Backend] [Transformer Backend[Transformers backend] Find attention with a fuser and attach vLLM's layer to it Sep 2, 2026
@hmellor hmellor changed the title [Transformer Backend[Transformers backend] Find attention with a fuser and attach vLLM's layer to it [Transformers backend] Find attention with a fuser and attach vLLM's layer to it Sep 2, 2026
@mergify

mergify Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @bohnstingl.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
@hmellor

hmellor commented Sep 2, 2026

Copy link
Copy Markdown
Member

/ci run

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #86905 for commit 5aab6ccab034.

@hmellor hmellor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If the CI passes this should be good

@hmellor hmellor added the ready ONLY add when PR is ready to merge/full CI is needed label Sep 2, 2026
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

@bohnstingl, CI is now available for this PR.

  • /ci run starts upstream CI; /amd-ci run starts AMD CI only.
  • /ci retry retries failed jobs in the CI build for the current PR head. If the current head has no CI build, it starts a new CI build for the current head containing only jobs that failed in the latest earlier CI build for this PR.
  • /amd-ci retry retries failed jobs in AMD CI for the current PR head. Use /amd-ci run when the current head has no AMD CI build.
  • /ci cancel cancels scheduled or running CI builds for this PR branch; /amd-ci cancel does the same for AMD CI only.

Signed-off-by: Thomas Ortner <boh@zurich.ibm.com>
@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Team

Run ID: bcc94d66-2217-4807-a942-ca901c8eba89

📥 Commits

Reviewing files that changed from the base of the PR and between 8b6de0e and 12c79f2.

📒 Files selected for processing (14)
  • docs/models/supported_models.md
  • tests/models/transformers/fusers/test_linear.py
  • tests/models/transformers/fusers/test_mla.py
  • tests/models/transformers/fusers/test_rms_norm.py
  • tests/models/transformers/test_backend.py
  • vllm/model_executor/models/registry.py
  • vllm/model_executor/models/transformers/__init__.py
  • vllm/model_executor/models/transformers/base.py
  • vllm/model_executor/models/transformers/fuser.py
  • vllm/model_executor/models/transformers/fusers/__init__.py
  • vllm/model_executor/models/transformers/fusers/attention.py
  • vllm/model_executor/models/transformers/fusers/base.py
  • vllm/model_executor/models/transformers/fusers/mla.py
  • vllm/model_executor/models/transformers/moe.py
🚧 Files skipped from review as they are similar to previous changes (14)
  • vllm/model_executor/models/transformers/fuser.py
  • vllm/model_executor/models/registry.py
  • vllm/model_executor/models/transformers/fusers/mla.py
  • tests/models/transformers/fusers/test_mla.py
  • vllm/model_executor/models/transformers/init.py
  • vllm/model_executor/models/transformers/moe.py
  • docs/models/supported_models.md
  • vllm/model_executor/models/transformers/fusers/init.py
  • tests/models/transformers/fusers/test_rms_norm.py
  • vllm/model_executor/models/transformers/fusers/attention.py
  • tests/models/transformers/test_backend.py
  • vllm/model_executor/models/transformers/base.py
  • vllm/model_executor/models/transformers/fusers/base.py
  • tests/models/transformers/fusers/test_linear.py

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Summary

Summary by CodeRabbit

  • New Features

    • Added attention dispatch support for compatible Transformers models, including MLA architectures.
    • Expanded support for custom models using standardized attention interfaces.
    • Improved handling of attention scaling, layer indexing, and multiple model components.
    • Broadened detection of models supporting configurable attention implementations.
  • Bug Fixes

    • Added validation for missing or duplicate attention dispatchers.
    • Unsupported attention scaling expressions now produce clear validation errors.
  • Documentation

    • Updated guidance for integrating custom models and background loading.

Walkthrough

The Transformers backend now detects attention interface calls, supports multiple fusers per module, tracks dispatchers by layer, derives attention scales, and attaches vLLM attention instances to serving modules. Tests and custom-model documentation cover the updated requirements.

Changes

Transformers attention fusers

Layer / File(s) Summary
Multi-fuser registry and typed lookups
vllm/model_executor/models/transformers/fuser.py, vllm/model_executor/models/transformers/fusers/{base,mla,moe}.py, tests/models/transformers/fusers/*
The registry now returns ordered fuser lists and supports typed lookup. Existing callers and tests use the new API.
Attention interface matching and scale extraction
vllm/model_executor/models/transformers/fusers/attention.py, vllm/model_executor/models/transformers/fusers/__init__.py
AttentionFuser parses the single ALL_ATTENTION_FUNCTIONS call, extracts scaling=, validates the attention implementation, and reports the module layer index.
Backend attention dispatch
vllm/model_executor/models/transformers/base.py, vllm/model_executor/models/transformers/__init__.py, vllm/model_executor/models/registry.py
The backend tracks attention fusers by layer, derives scales, attaches vLLM attention instances to modules, resolves them during standard and MLA execution, and accepts models that can set their attention implementation.
Custom-model contract and validation
docs/models/supported_models.md, tests/models/transformers/test_backend.py
The custom-model example uses get_interface(...), stores attention configuration, passes scaling, and documents _can_set_attn_implementation(). Tests cover matching, layer indices, implementation validation, scaling, and unresolved expressions.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: ⚪ Minimal · up to 12c79

This change adds Transformers attention fusing and scale resolution with targeted test coverage reported. No concrete merge-blocking risk remains in the supplied change context.

Sequence Diagram(s)

sequenceDiagram
  participant TransformersBackend
  participant AttentionFuser
  participant AttentionModule
  participant vllm_attention_forward
  participant VLLMAttention
  TransformersBackend->>AttentionFuser: register attention fuser by layer
  TransformersBackend->>AttentionModule: attach VLLMAttention
  AttentionModule->>vllm_attention_forward: dispatch attention interface
  vllm_attention_forward->>AttentionModule: resolve attached attention
  vllm_attention_forward->>VLLMAttention: execute attention with module inputs
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 65 functions across 13 files. (1 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: using an attention fuser to locate attention modules and attach vLLM attention layers.
Description check ✅ Passed The description is directly related to the changeset. It explains the AttentionFuser, attached attention layers, scaling resolution, fuser changes, tests, and remaining validation work.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 65 functions across 13 files. (1 skipped: 1 unsupported.)


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mergify mergify Bot removed the needs-rebase label Sep 2, 2026
bohnstingl and others added 3 commits September 3, 2026 09:59
@hmellor

hmellor commented Sep 3, 2026

Copy link
Copy Markdown
Member

/ci run

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #87065 for commit b2773c91ba6e.

bohnstingl and others added 3 commits September 3, 2026 10:11
Signed-off-by: Thomas Ortner <boh@zurich.ibm.com>
…ttn-module

Signed-off-by: Thomas Ortner <boh@zurich.ibm.com>
This reverts commit 4cc0f6e.

Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
@hmellor

hmellor commented Sep 3, 2026

Copy link
Copy Markdown
Member

I've added the recursion back because it's necessary

@hmellor

hmellor commented Sep 3, 2026

Copy link
Copy Markdown
Member

/ci run

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #87069 for commit af983c489bc1.

@hmellor

hmellor commented Sep 3, 2026

Copy link
Copy Markdown
Member

/ci run

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #87075 for commit 9d3e54996d8f.

@bohnstingl

Copy link
Copy Markdown
Contributor Author

/ci retry

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

✅ Queued 1 failed job(s) for retry in Buildkite CI #87075.

@hmellor

hmellor commented Sep 4, 2026

Copy link
Copy Markdown
Member

/ci run

@coderabbitai

coderabbitai Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #87250 for commit 12c79f2d9dc8.

@hmellor

hmellor commented Sep 4, 2026

Copy link
Copy Markdown
Member

/ci run

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #87258 for commit 6967ef4b2c4b.

@hmellor
hmellor enabled auto-merge (squash) September 4, 2026 16:04
@hmellor
hmellor merged commit 8ad2076 into vllm-project:main Sep 4, 2026
100 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Shipped in Transformers modeling backend Sep 4, 2026
ItsRoy69 pushed a commit to ItsRoy69/vllm that referenced this pull request Sep 10, 2026
…layer to it (vllm-project#54941)

Signed-off-by: Thomas Ortner <boh@zurich.ibm.com>
Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Co-authored-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Signed-off-by: Jyotirmoy Roy <jyotirmoyroy649@gmail.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 new-model Requests to new models ready ONLY add when PR is ready to merge/full CI is needed

Projects

Development

Successfully merging this pull request may close these issues.

2 participants