main
py 639 lines 25 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 from collections.abc import Sequence
5 from dataclasses import dataclass
6
7 import torch
8 import torch.nn.functional as F
9 from torch.nn.parameter import Parameter
10
11 import vllm.envs as envs
12 from vllm import _custom_ops as ops
13 from vllm.distributed import (
14 GroupCoordinator,
15 divide,
16 get_tensor_model_parallel_rank,
17 get_tensor_model_parallel_world_size,
18 tensor_model_parallel_all_reduce,
19 )
20 from vllm.model_executor.custom_op import PluggableLayer
21 from vllm.model_executor.determinism.batch_invariant import (
22 linear_batch_invariant,
23 )
24 from vllm.model_executor.layers.quantization.base_config import (
25 QuantizationConfig,
26 QuantizeMethodBase,
27 method_has_implemented_embedding,
28 resolve_quant_method,
29 )
30 from vllm.model_executor.layers.utils import dispatch_unquantized_gemm
31 from vllm.model_executor.parameter import BasevLLMParameter
32 from vllm.model_executor.utils import set_weight_attrs
33 from vllm.platforms import current_platform
34
35 DEFAULT_VOCAB_PADDING_SIZE = 64
36
37
38 class UnquantizedEmbeddingMethod(QuantizeMethodBase):
39 """Unquantized method for embeddings."""
40
41 supports_pre_processed_weights = True
42
43 def create_weights(
44 self,
45 layer: torch.nn.Module,
46 input_size_per_partition: int,
47 output_partition_sizes: list[int],
48 input_size: int,
49 output_size: int,
50 params_dtype: torch.dtype,
51 **extra_weight_attrs,
52 ):
53 """Create weights for embedding layer."""
54 weight = Parameter(
55 torch.empty(
56 sum(output_partition_sizes),
57 input_size_per_partition,
58 dtype=params_dtype,
59 ),
60 requires_grad=False,
61 )
62 set_weight_attrs(weight, {"input_dim": 1, "output_dim": 0})
63 layer.register_parameter("weight", weight)
64 set_weight_attrs(weight, extra_weight_attrs)
65
66 def process_weights_after_loading(self, layer: torch.nn.Module) -> None:
67 if current_platform.is_cpu():
68 from vllm.model_executor.layers.utils import dispatch_cpu_unquantized_gemm
69
70 dispatch_cpu_unquantized_gemm(layer, remove_weight=False)
71
72 def apply(
73 self,
74 layer: torch.nn.Module,
75 x: torch.Tensor,
76 bias: torch.Tensor | None = None,
77 ) -> torch.Tensor:
78 if envs.VLLM_BATCH_INVARIANT and (
79 current_platform.is_cuda_alike() or current_platform.is_xpu()
80 ):
81 return linear_batch_invariant(x, layer.weight, bias)
82 return dispatch_unquantized_gemm()(layer, x, layer.weight, bias)
83
84 def embedding(self, layer: torch.nn.Module, input_: torch.Tensor) -> torch.Tensor:
85 return F.embedding(input_, layer.weight)
86
87 def tie_weights(
88 self, layer: torch.nn.Module, embed_tokens: "VocabParallelEmbedding"
89 ):
90 layer.weight = embed_tokens.weight
91 return layer
92
93
94 def pad_vocab_size(vocab_size: int, pad_to: int = DEFAULT_VOCAB_PADDING_SIZE) -> int:
95 """Pad the vocab size to the given value."""
96 return ((vocab_size + pad_to - 1) // pad_to) * pad_to
97
98
99 def vocab_range_from_per_partition_vocab_size(
100 per_partition_vocab_size: int, rank: int, offset: int = 0
101 ) -> Sequence[int]:
102 index_f = rank * per_partition_vocab_size
103 index_l = index_f + per_partition_vocab_size
104 return index_f + offset, index_l + offset
105
106
107 def vocab_range_from_global_vocab_size(
108 global_vocab_size: int, rank: int, world_size: int, offset: int = 0
109 ) -> Sequence[int]:
110 per_partition_vocab_size = divide(global_vocab_size, world_size)
111 return vocab_range_from_per_partition_vocab_size(
112 per_partition_vocab_size, rank, offset=offset
113 )
114
115
116 @dataclass
117 class VocabParallelEmbeddingShardIndices:
118 """Indices for a shard of a vocab parallel embedding."""
119
120 padded_org_vocab_start_index: int
121 padded_org_vocab_end_index: int
122 padded_added_vocab_start_index: int
123 padded_added_vocab_end_index: int
124
125 org_vocab_start_index: int
126 org_vocab_end_index: int
127 added_vocab_start_index: int
128 added_vocab_end_index: int
129
130 @property
131 def num_org_elements(self) -> int:
132 return self.org_vocab_end_index - self.org_vocab_start_index
133
134 @property
135 def num_added_elements(self) -> int:
136 return self.added_vocab_end_index - self.added_vocab_start_index
137
138 @property
139 def num_org_elements_padded(self) -> int:
140 return self.padded_org_vocab_end_index - self.padded_org_vocab_start_index
141
142 @property
143 def num_added_elements_padded(self) -> int:
144 return self.padded_added_vocab_end_index - self.padded_added_vocab_start_index
145
146 @property
147 def num_org_vocab_padding(self) -> int:
148 return self.num_org_elements_padded - self.num_org_elements
149
150 @property
151 def num_added_vocab_padding(self) -> int:
152 return self.num_added_elements_padded - self.num_added_elements
153
154 @property
155 def num_elements_padded(self) -> int:
156 return self.num_org_elements_padded + self.num_added_elements_padded
157
158 def __post_init__(self):
159 # sanity checks
160 assert self.padded_org_vocab_start_index <= self.padded_org_vocab_end_index
161 assert self.padded_added_vocab_start_index <= self.padded_added_vocab_end_index
162
163 assert self.org_vocab_start_index <= self.org_vocab_end_index
164 assert self.added_vocab_start_index <= self.added_vocab_end_index
165
166 assert self.org_vocab_start_index <= self.padded_org_vocab_start_index
167 assert self.added_vocab_start_index <= self.padded_added_vocab_start_index
168 assert self.org_vocab_end_index <= self.padded_org_vocab_end_index
169 assert self.added_vocab_end_index <= self.padded_added_vocab_end_index
170
171 assert self.num_org_elements <= self.num_org_elements_padded
172 assert self.num_added_elements <= self.num_added_elements_padded
173
174
175 @torch.compile(dynamic=True, backend=current_platform.simple_compile_backend)
176 def get_masked_input_and_mask(
177 input_: torch.Tensor,
178 org_vocab_start_index: int,
179 org_vocab_end_index: int,
180 num_org_vocab_padding: int,
181 added_vocab_start_index: int,
182 added_vocab_end_index: int,
183 ) -> tuple[torch.Tensor, torch.Tensor]:
184 # torch.compile will fuse all of the pointwise ops below
185 # into a single kernel, making it very fast
186 org_vocab_mask = (input_ >= org_vocab_start_index) & (input_ < org_vocab_end_index)
187 added_vocab_mask = (input_ >= added_vocab_start_index) & (
188 input_ < added_vocab_end_index
189 )
190 added_offset = (
191 added_vocab_start_index
192 - (org_vocab_end_index - org_vocab_start_index)
193 - num_org_vocab_padding
194 )
195 valid_offset = (org_vocab_start_index * org_vocab_mask) + (
196 added_offset * added_vocab_mask
197 )
198 vocab_mask = org_vocab_mask | added_vocab_mask
199 input_ = vocab_mask * (input_ - valid_offset)
200 return input_, ~vocab_mask
201
202
203 # --8<-- [start:vocab_parallel_embedding]
204 @PluggableLayer.register("vocab_parallel_embedding")
205 class VocabParallelEmbedding(PluggableLayer):
206 """Embedding parallelized in the vocabulary dimension.
207
208 Adapted from torch.nn.Embedding, note that we pad the vocabulary size to
209 make sure it is divisible by the number of model parallel GPUs.
210
211 In order to support various loading methods, we ensure that LoRA-added
212 embeddings are always at the end of TP-sharded tensors. In other words,
213 we shard base embeddings and LoRA embeddings separately (both padded),
214 and place them in the same tensor.
215 In this example, we will have the original vocab size = 1010,
216 added vocab size = 16 and padding to 64. Therefore, the total
217 vocab size with padding will be 1088 (because we first pad 1010 to
218 1024, add 16, and then pad to 1088).
219 Therefore, the tensor format looks like the following:
220 TP1, rank 0 (no sharding):
221 |< --------BASE-------- >|< -BASE PADDING-- >|< -----LORA------ >|< -LORA PADDING-- >|
222 corresponding token_id: | 0 | 1 | ... | 1009 | -1 | ... | -1 | 1010 | ... | 1025 | -1 | ... | -1 |
223 index: | 0 | 1 | ... | 1009 | 1010 | ... | 1023 | 1024 | ... | 1039 | 1040 | ... | 1087 |
224
225 TP2, rank 0:
226 |< --------------------BASE--------------------- >|< -----LORA------ >|< -LORA PADDING- >|
227 corresponding token_id: | 0 | 1 | 2 | ... | 497 | 498 | ... | 511 | 1010 | ... | 1025 | -1 | ... | -1 |
228 index: | 0 | 1 | 2 | ... | 497 | 498 | ... | 511 | 512 | ... | 527 | 528 | ... | 543 |
229 TP2, rank 1:
230 |< -----------BASE----------- >|< -BASE PADDING- >|< -----------LORA PADDING----------- >|
231 corresponding token_id: | 512 | 513 | 514 | ... | 1009 | -1 | ... | -1 | -1 | ... | -1 | -1 | ... | -1 |
232 index: | 0 | 1 | 2 | ... | 497 | 498 | ... | 511 | 512 | ... | 527 | 528 | ... | 543 |
233
234 Args:
235 num_embeddings: vocabulary size.
236 embedding_dim: size of hidden state.
237 params_dtype: type of the parameters.
238 org_num_embeddings: original vocabulary size (without LoRA).
239 padding_size: padding size for the vocabulary.
240 quant_config: quant config for the layer
241 prefix: full name of the layer in the state dict
242 disable_tp: If true, tensor parallelism will be disabled for this layer.
243 quant_method: Preselected quantization method for model-specific layers.
244 parallel_group: Process group used to shard and reduce the embedding.
245
246 """ # noqa: E501
247
248 # --8<-- [end:vocab_parallel_embedding]
249
250 def __init__(
251 self,
252 num_embeddings: int,
253 embedding_dim: int,
254 params_dtype: torch.dtype | None = None,
255 org_num_embeddings: int | None = None,
256 padding_size: int = DEFAULT_VOCAB_PADDING_SIZE,
257 quant_config: QuantizationConfig | None = None,
258 prefix: str = "",
259 *,
260 disable_tp: bool = False,
261 quant_method: QuantizeMethodBase | None = None,
262 parallel_group: GroupCoordinator | None = None,
263 ):
264 super().__init__()
265
266 # Keep the input dimensions.
267 self.disable_tp = disable_tp
268 self.parallel_group = parallel_group
269 if disable_tp:
270 tp_rank, self.tp_size = 0, 1
271 elif parallel_group is not None:
272 tp_rank = parallel_group.rank_in_group
273 self.tp_size = parallel_group.world_size
274 else:
275 tp_rank = get_tensor_model_parallel_rank()
276 self.tp_size = get_tensor_model_parallel_world_size()
277 self.tp_rank = tp_rank
278 self.num_embeddings = num_embeddings
279 self.padding_size = padding_size
280 self.org_vocab_size = org_num_embeddings or num_embeddings
281 self.num_added_embeddings = num_embeddings - self.org_vocab_size
282 self.org_vocab_size_padded = pad_vocab_size(
283 self.org_vocab_size, self.padding_size
284 )
285 self.num_embeddings_padded = pad_vocab_size(
286 self.org_vocab_size_padded + self.num_added_embeddings, self.padding_size
287 )
288 assert self.org_vocab_size_padded <= self.num_embeddings_padded
289
290 self.shard_indices = self._get_indices(
291 self.num_embeddings_padded,
292 self.org_vocab_size_padded,
293 self.num_embeddings,
294 self.org_vocab_size,
295 tp_rank,
296 self.tp_size,
297 )
298 self.embedding_dim = embedding_dim
299 # Divide the weight matrix along the vocabulary dimension.
300 self.num_embeddings_per_partition = divide(
301 self.num_embeddings_padded, self.tp_size
302 )
303
304 # Quantization methods share the same weight factory as linear layers,
305 # so setup standard linear metadata.
306 self.input_size = self.input_size_per_partition = embedding_dim
307 self.output_size = self.num_embeddings_padded
308 self.output_size_per_partition = self.num_embeddings_per_partition
309 self.output_partition_sizes = [self.output_size_per_partition]
310 self.prefix = prefix
311
312 # Avoid overriding a preselected model-specific method with generic
313 # config-based dispatch.
314 if quant_method is None and quant_config is not None:
315 quant_method = resolve_quant_method(quant_config, self, prefix=prefix)
316 if quant_method is None:
317 quant_method = UnquantizedEmbeddingMethod()
318
319 # If we are making an embedding layer, then our quantization linear
320 # method must implement the embedding operation. If we are another
321 # layer type like ParallelLMHead, this is not important.
322 is_embedding_layer = not isinstance(self, ParallelLMHead)
323 quant_method_implements_embedding = method_has_implemented_embedding(
324 type(quant_method)
325 )
326 if is_embedding_layer and not quant_method_implements_embedding:
327 raise NotImplementedError(
328 f"The class {type(quant_method).__name__} must implement "
329 "the 'embedding' method, see UnquantizedEmbeddingMethod."
330 )
331
332 self.quant_method: QuantizeMethodBase = quant_method
333
334 if params_dtype is None:
335 params_dtype = torch.get_default_dtype()
336 self.params_dtype = params_dtype
337 assert (
338 self.shard_indices.num_elements_padded == self.num_embeddings_per_partition
339 )
340 self.num_org_embeddings_per_partition = (
341 self.shard_indices.org_vocab_end_index
342 - self.shard_indices.org_vocab_start_index
343 )
344 self.num_added_embeddings_per_partition = (
345 self.shard_indices.added_vocab_end_index
346 - self.shard_indices.added_vocab_start_index
347 )
348
349 # The fused kernel masks, shifts and gathers in one pass; it assumes a
350 # plain row-major shard, so it only applies to unquantized weights.
351 self.use_fused_embedding = (
352 self.tp_size > 1
353 and current_platform.is_cuda()
354 and isinstance(quant_method, UnquantizedEmbeddingMethod)
355 )
356
357 self.quant_method.create_weights(
358 self,
359 self.input_size_per_partition,
360 self.output_partition_sizes,
361 self.input_size,
362 self.output_size,
363 params_dtype=params_dtype,
364 weight_loader=self.weight_loader,
365 )
366 self.update_param_tp_status()
367
368 def update_param_tp_status(self):
369 for param in self.parameters():
370 if isinstance(param, BasevLLMParameter):
371 param.tp_rank = self.tp_rank
372 param.tp_size = self.tp_size
373
374 @classmethod
375 def _get_indices(
376 cls,
377 vocab_size_padded: int,
378 org_vocab_size_padded: int,
379 vocab_size: int,
380 org_vocab_size: int,
381 tp_rank: int,
382 tp_size: int,
383 ) -> VocabParallelEmbeddingShardIndices:
384 """Get start and end indices for vocab parallel embedding, following the
385 layout outlined in the class docstring, based on the given tp_rank and
386 tp_size."""
387 num_added_embeddings_padded = vocab_size_padded - org_vocab_size_padded
388 padded_org_vocab_start_index, padded_org_vocab_end_index = (
389 vocab_range_from_global_vocab_size(org_vocab_size_padded, tp_rank, tp_size)
390 )
391 padded_added_vocab_start_index, padded_added_vocab_end_index = (
392 vocab_range_from_global_vocab_size(
393 num_added_embeddings_padded, tp_rank, tp_size, offset=org_vocab_size
394 )
395 )
396 # remove padding
397 org_vocab_start_index = min(padded_org_vocab_start_index, org_vocab_size)
398 org_vocab_end_index = min(padded_org_vocab_end_index, org_vocab_size)
399 added_vocab_start_index = min(padded_added_vocab_start_index, vocab_size)
400 added_vocab_end_index = min(padded_added_vocab_end_index, vocab_size)
401 return VocabParallelEmbeddingShardIndices(
402 padded_org_vocab_start_index,
403 padded_org_vocab_end_index,
404 padded_added_vocab_start_index,
405 padded_added_vocab_end_index,
406 org_vocab_start_index,
407 org_vocab_end_index,
408 added_vocab_start_index,
409 added_vocab_end_index,
410 )
411
412 def get_sharded_to_full_mapping(self) -> list[int] | None:
413 """Get a mapping that can be used to reindex the gathered
414 logits for sampling.
415
416 During sampling, we gather logits from all ranks. The relationship
417 of index->token_id will follow the same format as outlined in the class
418 docstring. However, after the gather, we want to reindex the final
419 logits tensor to map index->token_id one-to-one (the index is always
420 equal the token_id it corresponds to). The indices returned by this
421 method allow us to do that.
422 """
423 if self.tp_size < 2:
424 return None
425
426 base_embeddings: list[int] = []
427 added_embeddings: list[int] = []
428 padding: list[int] = []
429 for tp_rank in range(self.tp_size):
430 shard_indices = self._get_indices(
431 self.num_embeddings_padded,
432 self.org_vocab_size_padded,
433 self.num_embeddings,
434 self.org_vocab_size,
435 tp_rank,
436 self.tp_size,
437 )
438 range_start = self.num_embeddings_per_partition * tp_rank
439 range_end = self.num_embeddings_per_partition * (tp_rank + 1)
440 base_embeddings.extend(
441 range(range_start, range_start + shard_indices.num_org_elements)
442 )
443 padding.extend(
444 range(
445 range_start + shard_indices.num_org_elements,
446 range_start + shard_indices.num_org_elements_padded,
447 )
448 )
449 added_embeddings.extend(
450 range(
451 range_start + shard_indices.num_org_elements_padded,
452 range_start
453 + shard_indices.num_org_elements_padded
454 + shard_indices.num_added_elements,
455 )
456 )
457 padding.extend(
458 range(
459 range_start
460 + shard_indices.num_org_elements_padded
461 + shard_indices.num_added_elements,
462 range_start
463 + shard_indices.num_org_elements_padded
464 + shard_indices.num_added_elements_padded,
465 )
466 )
467 assert (
468 range_start
469 + shard_indices.num_org_elements_padded
470 + shard_indices.num_added_elements_padded
471 == range_end
472 )
473 ret = base_embeddings + added_embeddings + padding
474 assert len(ret) == self.num_embeddings_padded
475 return ret
476
477 def weight_loader(self, param: Parameter, loaded_weight: torch.Tensor):
478 output_dim = getattr(param, "output_dim", None)
479 packed_dim = getattr(param, "packed_dim", None)
480
481 # Parameters without an output dimension are copied onto all GPUs.
482 if output_dim is None:
483 if (
484 loaded_weight.ndim == 0
485 and param.data.ndim == 1
486 and param.data.numel() == 1
487 ):
488 loaded_weight = loaded_weight.reshape(1)
489 assert param.data.shape == loaded_weight.shape
490 param.data.copy_(loaded_weight)
491 return
492
493 # Shard indexes for loading the weight
494 start_idx = self.shard_indices.org_vocab_start_index
495 shard_size = self.shard_indices.org_vocab_end_index - start_idx
496
497 # If param packed on the same dim we are sharding on, then
498 # need to adjust offsets of loaded weight by pack_factor.
499 if packed_dim is not None and packed_dim == output_dim:
500 packed_factor = (
501 param.packed_factor
502 if isinstance(param, BasevLLMParameter)
503 else param.pack_factor
504 )
505 assert loaded_weight.shape[output_dim] == (
506 self.org_vocab_size // param.packed_factor
507 )
508 start_idx = start_idx // packed_factor
509 shard_size = shard_size // packed_factor
510 else:
511 assert loaded_weight.shape[output_dim] == self.org_vocab_size
512
513 # Copy the data. Select chunk corresponding to current shard.
514 loaded_weight = loaded_weight.narrow(output_dim, start_idx, shard_size)
515 param[: loaded_weight.shape[0]].data.copy_(loaded_weight)
516 param[loaded_weight.shape[0] :].data.fill_(0)
517
518 def forward(self, input_):
519 if self.tp_size == 1:
520 return self.quant_method.embedding(self, input_.long())
521
522 if self.use_fused_embedding:
523 output_parallel = ops.vocab_parallel_embedding(
524 input_ if input_.ndim == 1 else input_.reshape(-1),
525 self.weight,
526 self.shard_indices.org_vocab_start_index,
527 self.shard_indices.org_vocab_end_index,
528 self.shard_indices.num_org_vocab_padding,
529 self.shard_indices.added_vocab_start_index,
530 self.shard_indices.added_vocab_end_index,
531 )
532 if input_.ndim != 1:
533 output_parallel = output_parallel.view(
534 *input_.shape, self.embedding_dim
535 )
536 else:
537 masked_input, input_mask = get_masked_input_and_mask(
538 input_,
539 self.shard_indices.org_vocab_start_index,
540 self.shard_indices.org_vocab_end_index,
541 self.shard_indices.num_org_vocab_padding,
542 self.shard_indices.added_vocab_start_index,
543 self.shard_indices.added_vocab_end_index,
544 )
545 output_parallel = self.quant_method.embedding(self, masked_input.long())
546 if output_parallel.dtype in (
547 torch.float8_e4m3fn,
548 torch.float8_e5m2,
549 ):
550 # Each vocab token has one owner, so FP8 bytes can use int8 SUM.
551 comm_output = output_parallel.view(torch.int8)
552 comm_output.masked_fill_(input_mask.unsqueeze(-1), 0)
553 output = (
554 self.parallel_group.all_reduce(comm_output)
555 if self.parallel_group is not None
556 else tensor_model_parallel_all_reduce(comm_output)
557 )
558 return output.view(output_parallel.dtype)
559 output_parallel.masked_fill_(input_mask.unsqueeze(-1), 0)
560 # Reduce across all the model parallel GPUs.
561 if self.parallel_group is not None:
562 return self.parallel_group.all_reduce(output_parallel)
563 return tensor_model_parallel_all_reduce(output_parallel)
564
565 def extra_repr(self) -> str:
566 s = f"num_embeddings={self.num_embeddings}"
567 s += f", num_embeddings_per_partition={self.num_embeddings_per_partition}"
568 s += f", embedding_dim={self.embedding_dim}"
569 s += f", org_vocab_size={self.org_vocab_size}"
570 s += f", num_embeddings_padded={self.num_embeddings_padded}"
571 s += f", tp_size={self.tp_size}"
572 return s
573
574
575 # --8<-- [start:parallel_lm_head]
576 @PluggableLayer.register("parallel_lm_head")
577 class ParallelLMHead(VocabParallelEmbedding):
578 """Parallelized LM head.
579
580 Output logits weight matrices used in the Sampler. The weight and bias
581 tensors are padded to make sure they are divisible by the number of
582 model parallel GPUs.
583
584 Args:
585 num_embeddings: vocabulary size.
586 embedding_dim: size of hidden state.
587 bias: whether to use bias.
588 params_dtype: type of the parameters.
589 org_num_embeddings: original vocabulary size (without LoRA).
590 padding_size: padding size for the vocabulary.
591 disable_tp: If true, tensor parallelism will be disabled for this layer.
592
593 """
594
595 # --8<-- [end:parallel_lm_head]
596
597 def __init__(
598 self,
599 num_embeddings: int,
600 embedding_dim: int,
601 bias: bool = False,
602 params_dtype: torch.dtype | None = None,
603 org_num_embeddings: int | None = None,
604 padding_size: int = DEFAULT_VOCAB_PADDING_SIZE,
605 quant_config: QuantizationConfig | None = None,
606 prefix: str = "",
607 *,
608 disable_tp: bool = False,
609 ):
610 self.has_bias = bias
611 super().__init__(
612 num_embeddings,
613 embedding_dim,
614 params_dtype,
615 org_num_embeddings,
616 padding_size,
617 quant_config,
618 prefix,
619 disable_tp=disable_tp,
620 )
621 self.quant_config = quant_config
622 if bias:
623 self._register_bias()
624 else:
625 self.register_parameter("bias", None)
626
627 def _register_bias(self):
628 data = torch.empty(self.num_embeddings_per_partition, dtype=self.params_dtype)
629 self.bias = Parameter(data, requires_grad=False)
630 weight_attrs = dict(output_dim=0, weight_loader=self.weight_loader)
631 set_weight_attrs(weight=self.bias, weight_attrs=weight_attrs)
632
633 def tie_weights(self, embed_tokens: VocabParallelEmbedding):
634 """Tie the weights with word embeddings."""
635 return self.quant_method.tie_weights(self, embed_tokens)
636
637 def forward(self, input_):
638 del input_
639 raise RuntimeError("LMHead's weights should be used in the sampler.")