main
py 182 lines 6.27 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 import math
5 from collections.abc import Iterable
6
7 import torch
8 import torch.nn as nn
9
10 from vllm.config import VllmConfig
11 from vllm.model_executor.layers.logits_processor import LogitsProcessor
12 from vllm.model_executor.layers.vocab_parallel_embedding import (
13 ParallelLMHead,
14 VocabParallelEmbedding,
15 )
16 from vllm.model_executor.model_loader.weight_utils import default_weight_loader
17
18 from .utils import maybe_prefix
19
20
21 class MLPSpeculatorLayerNorm(nn.Module):
22 """A L2 normalization implementation
23 ...
24
25 Args:
26 ----
27 normalized_shape : int
28 Dimensionality of input data (size of final tensor axis)
29 eps : float
30 Safety term to prevent division by zero. Make sure the chosen value
31 fits in the range of your encoding scheme
32 (i.e. fp16 requires eps >= 6e-8).
33 elementwise_scale_and_shift : bool
34 Include a learned scaling and shift term after normalization.
35
36 """
37
38 def __init__(
39 self,
40 normalized_shape,
41 eps=1e-06,
42 elementwise_scale_and_shift=True,
43 ):
44 super().__init__()
45 self.elementwise_scale_and_shift = elementwise_scale_and_shift
46 if self.elementwise_scale_and_shift:
47 self.weight = nn.Parameter(torch.empty(normalized_shape))
48 self.bias = nn.Parameter(torch.empty(normalized_shape))
49 self.eps = eps
50
51 def forward(self, x):
52 xf = x
53 xf = xf * torch.rsqrt(xf.pow(2).mean(-1, keepdim=True) + self.eps)
54 x = xf.type_as(x)
55 if self.elementwise_scale_and_shift:
56 x = self.weight * x
57 x = x + self.bias
58 return x
59
60
61 class MLPSpeculator(nn.Module):
62 """An implementation of the speculative models introduced in
63 "Accelerating Production LLMs with Combined Token/Embedding
64 Speculators"
65 https://arxiv.org/pdf/2404.19124
66
67 Trained speculators of this type are available on HF hub at:
68 https://huggingface.co/ibm-ai-platform and https://huggingface.co/ibm-granite
69 """
70
71 def __init__(self, *, vllm_config: VllmConfig, prefix: str = "") -> None:
72 super().__init__()
73 config = vllm_config.model_config.hf_config
74 self.n_predict = config.n_predict
75 self.vocab_size = config.vocab_size
76 self.emb_dim = config.emb_dim
77 self.inner_dim = config.inner_dim if config.inner_dim != 0 else config.emb_dim
78
79 self.max_speculative_tokens = config.num_lookahead_tokens
80
81 self.tie_weights = config.tie_weights
82 self.scale_input = config.scale_input
83
84 if self.tie_weights:
85 assert self.n_predict > 1, (
86 "You cannot tie weights between stages when only 1 exists"
87 )
88 embedding = VocabParallelEmbedding(
89 config.vocab_size, self.inner_dim, org_num_embeddings=config.vocab_size
90 )
91 self.emb = nn.ModuleList([embedding] * self.max_speculative_tokens)
92
93 # the initial projection from the base model may
94 # have a different size, so that stays separate.
95 proj_first = nn.Linear(self.emb_dim, self.inner_dim, bias=False)
96 proj_tied = nn.Linear(self.inner_dim, self.inner_dim, bias=False)
97 self.proj = nn.ModuleList(
98 [proj_first] + [proj_tied] * (self.max_speculative_tokens - 1)
99 )
100
101 self.head = nn.ModuleList(
102 [
103 ParallelLMHead(
104 self.vocab_size,
105 self.inner_dim,
106 bias=False,
107 prefix=maybe_prefix(prefix, f"head.{i}"),
108 )
109 for i in range(self.max_speculative_tokens)
110 ]
111 )
112
113 ln = MLPSpeculatorLayerNorm(
114 self.inner_dim, elementwise_scale_and_shift=True
115 )
116 self.ln = nn.ModuleList([ln] * self.max_speculative_tokens)
117
118 else:
119 self.emb = nn.ModuleList(
120 [
121 VocabParallelEmbedding(
122 config.vocab_size,
123 self.inner_dim,
124 )
125 for _ in range(self.max_speculative_tokens)
126 ]
127 )
128
129 self.proj = nn.ModuleList(
130 [
131 nn.Linear(
132 (self.emb_dim if i == 0 else self.inner_dim),
133 self.inner_dim,
134 bias=False,
135 )
136 for i in range(self.max_speculative_tokens)
137 ]
138 )
139
140 self.head = nn.ModuleList(
141 [
142 ParallelLMHead(
143 self.vocab_size,
144 self.inner_dim,
145 bias=False,
146 prefix=maybe_prefix(prefix, f"head.{i}"),
147 )
148 for i in range(self.max_speculative_tokens)
149 ]
150 )
151 self.ln = nn.ModuleList(
152 [
153 MLPSpeculatorLayerNorm(
154 self.inner_dim, elementwise_scale_and_shift=True
155 )
156 for _ in range(self.max_speculative_tokens)
157 ]
158 )
159 if self.scale_input:
160 self.ln0 = MLPSpeculatorLayerNorm(
161 self.emb_dim, elementwise_scale_and_shift=False
162 )
163
164 self.state_weight = 0.5 ** (0.5 / config.n_predict)
165 self.emb_weight = math.sqrt((1 - self.state_weight**2) * (self.inner_dim / 2))
166 self.activation = nn.GELU()
167 self.config = config
168 self.logits_processor = LogitsProcessor(
169 config.vocab_size, config.vocab_size, 1.0
170 )
171
172 def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
173 params_dict = dict(self.named_parameters())
174 loaded_params: set[str] = set()
175 for name, loaded_weight in weights:
176 name = name.replace("speculator.", "")
177 param = params_dict.get(name)
178 if param is not None:
179 weight_loader = getattr(param, "weight_loader", default_weight_loader)
180 weight_loader(param, loaded_weight)
181 loaded_params.add(name)
182 return loaded_params