main
py 96 lines 2.87 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 import functools
4 from copy import copy
5
6 import torch
7
8 from vllm.config import CacheConfig
9 from vllm.config.vllm import VllmConfig
10 from vllm.model_executor.layers.attention import Attention
11 from vllm.v1.attention.backend import (
12 AttentionBackend,
13 AttentionMetadata,
14 AttentionType,
15 CommonAttentionMetadata,
16 subclass_attention_backend,
17 )
18 from vllm.v1.attention.selector import get_attn_backend
19 from vllm.v1.kv_cache_interface import KVCacheSpec
20
21
22 @functools.lru_cache
23 def create_encoder_only_attention_backend(
24 underlying_attn_backend: type[AttentionBackend],
25 ) -> type[AttentionBackend]:
26 prefix = "EncoderOnlyAttention_"
27 underlying_builder = underlying_attn_backend.get_builder_cls()
28
29 class EncoderOnlyAttentionBuilder(underlying_builder): # type: ignore
30 def build(
31 self,
32 common_prefix_len: int,
33 common_attn_metadata: CommonAttentionMetadata,
34 fast_build: bool = False,
35 ) -> AttentionMetadata:
36 new_common_attn_metadata = copy(common_attn_metadata)
37 new_common_attn_metadata.causal = False
38 return super().build(
39 common_prefix_len, new_common_attn_metadata, fast_build
40 )
41
42 attn_backend = subclass_attention_backend(
43 name_prefix=prefix,
44 attention_backend_cls=underlying_attn_backend,
45 builder_cls=EncoderOnlyAttentionBuilder,
46 )
47
48 return attn_backend
49
50
51 class EncoderOnlyAttention(Attention):
52 """Encoder attention is a special case that doesn't need a KV Cache."""
53
54 def __init__(
55 self,
56 num_heads: int,
57 head_size: int,
58 scale: float,
59 cache_config: CacheConfig | None = None,
60 attn_type: str | None = None,
61 **kwargs,
62 ):
63 dtype = torch.get_default_dtype()
64
65 if cache_config is not None:
66 kv_cache_dtype = cache_config.cache_dtype
67 else:
68 kv_cache_dtype = "auto"
69
70 underlying_attn_backend = get_attn_backend(
71 head_size,
72 dtype,
73 kv_cache_dtype,
74 attn_type=AttentionType.ENCODER_ONLY,
75 )
76
77 attn_backend = create_encoder_only_attention_backend(underlying_attn_backend)
78
79 if attn_type is not None:
80 assert attn_type == AttentionType.ENCODER_ONLY, (
81 "EncoderOnlyAttention only supports AttentionType.ENCODER_ONLY"
82 )
83
84 super().__init__(
85 num_heads=num_heads,
86 head_size=head_size,
87 scale=scale,
88 cache_config=cache_config,
89 attn_backend=attn_backend,
90 attn_type=AttentionType.ENCODER_ONLY,
91 **kwargs,
92 )
93
94 def get_kv_cache_spec(self, vllm_config: VllmConfig) -> KVCacheSpec | None:
95 # Does not need KV cache
96 return None