main
py 680 lines 23.6 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 # Copyright 2025 The vLLM team.
5 # Copyright 2025 NVIDIA CORPORATION and the HuggingFace Inc. team. All rights
6 # reserved.
7 #
8 # Licensed under the Apache License, Version 2.0 (the "License");
9 # you may not use this file except in compliance with the License.
10 # You may obtain a copy of the License at
11 #
12 # http://www.apache.org/licenses/LICENSE-2.0
13 #
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS,
16 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 # See the License for the specific language governing permissions and
18 # limitations under the License.
19
20 from collections.abc import Iterable, Mapping, Sequence, Sized
21 from typing import Annotated, Any, Literal, TypeAlias
22
23 import torch
24 import torch.nn as nn
25 from transformers import BatchFeature, PreTrainedConfig
26 from transformers.models.audioflamingo3 import (
27 AudioFlamingo3Config,
28 AudioFlamingo3Processor,
29 )
30 from transformers.models.qwen2_audio import Qwen2AudioEncoder
31
32 from vllm.config import VllmConfig
33 from vllm.config.multimodal import MultiModalDummyOptions
34 from vllm.inputs import ModalityData, MultiModalDataDict
35 from vllm.model_executor.layers.activation import get_act_fn
36 from vllm.model_executor.models.module_mapping import MultiModelKeys
37 from vllm.multimodal import MULTIMODAL_REGISTRY
38 from vllm.multimodal.inputs import (
39 MultiModalFieldConfig,
40 MultiModalKwargsItems,
41 )
42 from vllm.multimodal.parse import (
43 DictEmbeddingItems,
44 ModalityDataItems,
45 MultiModalDataItems,
46 MultiModalDataParser,
47 )
48 from vllm.multimodal.processing import (
49 BaseDummyInputsBuilder,
50 BaseMultiModalProcessor,
51 BaseProcessingInfo,
52 PromptReplacement,
53 PromptUpdate,
54 PromptUpdateDetails,
55 )
56 from vllm.sequence import IntermediateTensors
57 from vllm.utils.gpu_sync_debug import gpu_sync_allowed
58 from vllm.utils.tensor_schema import TensorSchema, TensorShape
59
60 from .interfaces import (
61 MultiModalEmbeddings,
62 SupportsLoRA,
63 SupportsMultiModal,
64 SupportsPP,
65 )
66 from .utils import (
67 AutoWeightsLoader,
68 init_vllm_registered_model,
69 maybe_prefix,
70 )
71
72
73 class AudioFlamingo3FeatureInputs(TensorSchema):
74 """Dimensions:
75 - num_chunks: Number of audio chunks (flattened)
76 - nmb: Number of mel bins
77 - num_audios: Number of original audio files
78 """
79
80 type: Literal["audio_features"]
81 input_features: Annotated[
82 torch.Tensor | list[torch.Tensor],
83 TensorShape("num_chunks", "nmb", 3000),
84 ]
85
86 feature_attention_mask: Annotated[
87 torch.Tensor,
88 TensorShape("num_chunks", 3000),
89 ]
90
91 chunk_counts: Annotated[
92 torch.Tensor,
93 TensorShape("num_audios"),
94 ]
95
96
97 class AudioFlamingo3EmbeddingInputs(TensorSchema):
98 """Dimensions:
99 - bn: Batch size
100 - naf: Number of audio features
101 - hs: Hidden size (must match the hidden size of language model
102 backbone)
103 """
104
105 type: Literal["audio_embeds"] = "audio_embeds"
106
107 audio_embeds: Annotated[
108 list[torch.Tensor],
109 TensorShape("bn", "naf", "hs", dynamic_dims={"naf"}),
110 ]
111
112
113 AudioFlamingo3Inputs: TypeAlias = (
114 AudioFlamingo3FeatureInputs | AudioFlamingo3EmbeddingInputs
115 )
116
117
118 class AudioFlamingo3Encoder(Qwen2AudioEncoder):
119 def __init__(
120 self,
121 config: PreTrainedConfig,
122 ):
123 super().__init__(config)
124 self.avg_pooler = nn.AvgPool1d(kernel_size=2, stride=2)
125
126 def forward(
127 self,
128 input_features: torch.Tensor | list[torch.Tensor],
129 attention_mask: torch.Tensor = None,
130 ):
131 if isinstance(input_features, list):
132 input_features = torch.stack(input_features)
133
134 hidden_states = nn.functional.gelu(self.conv1(input_features))
135 hidden_states = nn.functional.gelu(self.conv2(hidden_states))
136 hidden_states = hidden_states.transpose(-1, -2)
137 hidden_states = (
138 hidden_states + self.embed_positions.weight[: hidden_states.size(-2), :]
139 ).to(hidden_states.dtype)
140
141 for layer in self.layers:
142 layer_outputs = layer(hidden_states, attention_mask)
143 hidden_states = (
144 layer_outputs[0] if isinstance(layer_outputs, tuple) else layer_outputs
145 )
146
147 hidden_states = hidden_states.permute(0, 2, 1)
148 hidden_states = self.avg_pooler(hidden_states)
149 hidden_states = hidden_states.permute(0, 2, 1)
150 hidden_states = self.layer_norm(hidden_states)
151
152 return hidden_states
153
154 def _get_feat_extract_output_lengths(self, input_lengths: torch.Tensor):
155 """Computes the output length of the convolutional layers and the output length
156 of the audio encoder
157 """
158 input_lengths = (input_lengths - 1) // 2 + 1
159 output_lengths = (input_lengths - 2) // 2 + 1
160 return input_lengths, output_lengths
161
162
163 class AudioFlamingo3MultiModalProjector(nn.Module):
164 def __init__(self, config: PreTrainedConfig):
165 super().__init__()
166 self.linear_1 = nn.Linear(
167 config.audio_config.hidden_size,
168 config.text_config.hidden_size,
169 bias=config.projector_bias,
170 )
171 self.act = get_act_fn(config.projector_hidden_act)
172 self.linear_2 = nn.Linear(
173 config.text_config.hidden_size,
174 config.text_config.hidden_size,
175 bias=config.projector_bias,
176 )
177
178 def forward(self, audio_features):
179 hidden_states = self.linear_1(audio_features)
180 hidden_states = self.act(hidden_states)
181 hidden_states = self.linear_2(hidden_states)
182 return hidden_states
183
184
185 class AudioFlamingo3ProcessingInfo(BaseProcessingInfo):
186 def get_hf_config(self):
187 return self.ctx.get_hf_config(AudioFlamingo3Config)
188
189 def get_hf_processor(self, **kwargs: object):
190 return self.ctx.get_hf_processor(AudioFlamingo3Processor, **kwargs)
191
192 def get_feature_extractor(self, **kwargs: object):
193 return self.get_hf_processor(**kwargs).feature_extractor
194
195 def get_data_parser(self) -> MultiModalDataParser:
196 feature_extractor = self.get_feature_extractor()
197 return AudioFlamingo3MultiModalDataParser(
198 target_sr=feature_extractor.sampling_rate,
199 expected_hidden_size=self._get_expected_hidden_size(),
200 allow_missing_mm_embeddings=self.allow_missing_mm_embeddings,
201 )
202
203 def get_supported_mm_limits(self) -> Mapping[str, int | None]:
204 return {"audio": 1}
205
206
207 class AudioFlamingo3DummyInputsBuilder(
208 BaseDummyInputsBuilder[AudioFlamingo3ProcessingInfo]
209 ):
210 def get_dummy_text(self, mm_counts: Mapping[str, int]) -> str:
211 num_audios = mm_counts.get("audio", 0)
212 hf_processor = self.info.get_hf_processor()
213 audio_token = hf_processor.audio_token
214 return audio_token * num_audios
215
216 def get_dummy_mm_data(
217 self,
218 seq_len: int,
219 mm_counts: Mapping[str, int],
220 mm_options: MultiModalDummyOptions,
221 ) -> MultiModalDataDict:
222 hf_processor = self.info.get_hf_processor()
223 feature_extractor = self.info.get_feature_extractor()
224 sampling_rate = feature_extractor.sampling_rate
225 audio_len = int(hf_processor.max_audio_len * sampling_rate)
226
227 return {
228 "audio": self._get_dummy_audios(
229 length=audio_len,
230 num_audios=mm_counts.get("audio", 0),
231 overrides=mm_options.get("audio"),
232 )
233 }
234
235
236 def _audioflamingo3_field_config(hf_inputs: Mapping[str, torch.Tensor]):
237 chunk_counts = hf_inputs.get("chunk_counts")
238 if chunk_counts is not None:
239 return dict(
240 audio_embeds=MultiModalFieldConfig.batched("audio"),
241 audio_num_tokens=MultiModalFieldConfig.batched("audio", keep_on_cpu=True),
242 input_features=MultiModalFieldConfig.flat_from_sizes(
243 "audio", chunk_counts, dim=0
244 ),
245 feature_attention_mask=MultiModalFieldConfig.flat_from_sizes(
246 "audio", chunk_counts, dim=0
247 ),
248 chunk_counts=MultiModalFieldConfig.batched("audio", keep_on_cpu=True),
249 )
250 return dict(
251 audio_embeds=MultiModalFieldConfig.batched("audio"),
252 audio_num_tokens=MultiModalFieldConfig.batched("audio", keep_on_cpu=True),
253 input_features=MultiModalFieldConfig.batched("audio"),
254 feature_attention_mask=MultiModalFieldConfig.batched("audio"),
255 chunk_counts=MultiModalFieldConfig.batched("audio", keep_on_cpu=True),
256 )
257
258
259 def _get_audio_post_pool_output_lengths(input_lengths: torch.Tensor) -> torch.Tensor:
260 conv_lengths = (input_lengths - 1) // 2 + 1
261 return (conv_lengths - 2) // 2 + 1
262
263
264 def _build_audio_encoder_attention_mask(
265 feature_attention_mask: torch.Tensor,
266 *,
267 dtype: torch.dtype,
268 device: torch.device,
269 ) -> torch.Tensor:
270 input_lengths = feature_attention_mask.sum(-1).to(torch.long)
271 conv_lengths = (input_lengths - 1) // 2 + 1
272
273 batch_size, max_mel_seq_len = feature_attention_mask.shape
274 max_seq_len = (max_mel_seq_len - 1) // 2 + 1
275
276 seq_range = (
277 torch.arange(
278 max_seq_len,
279 dtype=conv_lengths.dtype,
280 device=conv_lengths.device,
281 )
282 .unsqueeze(0)
283 .expand(batch_size, max_seq_len)
284 )
285 padding_mask = seq_range >= conv_lengths[:, None]
286
287 attention_mask = padding_mask.view(batch_size, 1, 1, max_seq_len).expand(
288 batch_size, 1, max_seq_len, max_seq_len
289 )
290 attention_mask = attention_mask.to(dtype=dtype, device=device)
291 attention_mask.masked_fill_(padding_mask[:, None, None, :], float("-inf"))
292
293 return attention_mask
294
295
296 def _flatten_valid_audio_embeddings(
297 audio_embeddings: torch.Tensor,
298 feature_attention_mask: torch.Tensor,
299 ) -> tuple[torch.Tensor, torch.Tensor]:
300 input_lengths = feature_attention_mask.sum(-1).to(torch.long)
301 output_lengths = _get_audio_post_pool_output_lengths(input_lengths)
302 valid_mask = (
303 torch.arange(audio_embeddings.shape[1], device=output_lengths.device)[None, :]
304 < output_lengths[:, None]
305 )
306
307 # Boolean-mask indexing has a data-dependent output shape, so the count
308 # has to come back to the host.
309 with gpu_sync_allowed():
310 return audio_embeddings[valid_mask], output_lengths
311
312
313 def _count_audio_tokens_from_mask(
314 feature_attention_mask: torch.Tensor | list[torch.Tensor],
315 chunk_counts: torch.Tensor | list[torch.Tensor] | list[int] | None,
316 item_idx: int,
317 ) -> int:
318 if chunk_counts is not None:
319 if isinstance(chunk_counts, torch.Tensor):
320 counts = chunk_counts.tolist()
321 elif chunk_counts and isinstance(chunk_counts[0], torch.Tensor):
322 counts = [int(count) for count in chunk_counts]
323 else:
324 counts = chunk_counts
325
326 start_idx = sum(counts[:item_idx])
327 count = counts[item_idx]
328 end_idx = start_idx + count
329
330 if isinstance(feature_attention_mask, list):
331 sample_mask = feature_attention_mask[start_idx:end_idx]
332 if len(sample_mask) == 0:
333 raise ValueError("Expected non-empty audio mask slice.")
334 if isinstance(sample_mask[0], torch.Tensor):
335 sample_mask = torch.stack(sample_mask)
336 else:
337 sample_mask = torch.tensor(sample_mask)
338 else:
339 sample_mask = feature_attention_mask[start_idx:end_idx]
340 else:
341 if isinstance(feature_attention_mask, list):
342 sample_mask = feature_attention_mask[item_idx]
343 else:
344 sample_mask = feature_attention_mask[item_idx]
345
346 if sample_mask.ndim == 1:
347 sample_input_lengths = sample_mask.sum().unsqueeze(0)
348 else:
349 # Match the HF processor, which derives placeholder lengths from the
350 # total pre-encoder feature length for each original audio sample.
351 sample_input_lengths = sample_mask.sum().reshape(1)
352
353 post_lengths = _get_audio_post_pool_output_lengths(
354 sample_input_lengths.to(torch.long)
355 )
356 return int(post_lengths[0].item())
357
358
359 class AudioFlamingo3MultiModalDataParser(MultiModalDataParser):
360 embedding_fields = {
361 "audio": {"audio_embeds": "values", "audio_num_tokens": "metadata"},
362 }
363
364 def _parse_audio_data(
365 self,
366 data: dict[str, torch.Tensor] | ModalityData[Any],
367 ) -> ModalityDataItems[Any, Any] | None:
368 if isinstance(data, dict) and "audio_num_tokens" not in data:
369 return DictEmbeddingItems(
370 data,
371 modality="audio",
372 required_fields={"audio_embeds"},
373 fields_factory=_audioflamingo3_field_config,
374 )
375 return super()._parse_audio_data(data)
376
377
378 class AudioFlamingo3MultiModalProcessor(
379 BaseMultiModalProcessor[AudioFlamingo3ProcessingInfo]
380 ):
381 def _get_hf_mm_text(self, mm_counts: Mapping[str, int]) -> str:
382 return self.dummy_inputs.get_dummy_text(mm_counts)
383
384 def _postprocess_hf_mm_data(
385 self,
386 mm_data: Mapping[str, object],
387 hf_processor_mm_kwargs: Mapping[str, object],
388 processed_data: BatchFeature,
389 ) -> BatchFeature:
390 if "input_features_mask" in processed_data:
391 processed_data["feature_attention_mask"] = processed_data.pop(
392 "input_features_mask"
393 )
394
395 audio_data = mm_data.get("audio")
396 if audio_data is None:
397 return processed_data
398
399 audio_list = audio_data if isinstance(audio_data, list) else [audio_data]
400 if len(audio_list) == 0:
401 return processed_data
402
403 processor = self.info.get_hf_processor(**hf_processor_mm_kwargs)
404 feature_extractor = processor.feature_extractor
405 sampling_rate = feature_extractor.sampling_rate
406 chunk_length = feature_extractor.chunk_length
407 window_size = int(sampling_rate * chunk_length)
408 max_windows = int(processor.max_audio_len // chunk_length)
409
410 chunk_counts = []
411 for audio in audio_list:
412 # audio is numpy array or list
413 assert isinstance(audio, Sized)
414 n_samples = len(audio)
415
416 n_win = max(1, (n_samples + window_size - 1) // window_size)
417 if n_win > max_windows:
418 n_win = max_windows
419 chunk_counts.append(n_win)
420
421 processed_data["chunk_counts"] = torch.tensor(chunk_counts, dtype=torch.long)
422
423 return processed_data
424
425 def _get_mm_fields_config(
426 self,
427 hf_inputs: BatchFeature,
428 hf_processor_mm_kwargs: Mapping[str, object],
429 ) -> Mapping[str, MultiModalFieldConfig]:
430 return _audioflamingo3_field_config(hf_inputs)
431
432 def _get_prompt_updates(
433 self,
434 mm_items: MultiModalDataItems,
435 hf_processor_mm_kwargs: Mapping[str, object],
436 out_mm_kwargs: MultiModalKwargsItems,
437 ) -> Sequence[PromptUpdate]:
438 processor = self.info.get_hf_processor(**hf_processor_mm_kwargs)
439 tokenizer = self.info.get_tokenizer()
440 vocab = tokenizer.get_vocab()
441
442 audio_token = getattr(processor, "audio_token", "<sound>")
443 audio_token_id = vocab.get(audio_token)
444 if audio_token_id is None:
445 audio_token_id = processor.audio_token_id
446
447 out_mm_data = out_mm_kwargs.get_data()
448 feature_attention_mask = out_mm_data.get("feature_attention_mask")
449 chunk_counts = out_mm_data.get("chunk_counts")
450
451 def get_replacement_audioflamingo3(item_idx: int):
452 if "audio_num_tokens" in out_mm_data:
453 counts = out_mm_data["audio_num_tokens"]
454 assert isinstance(counts, torch.Tensor)
455 num_features = int(counts[item_idx])
456 elif feature_attention_mask is not None:
457 num_features = _count_audio_tokens_from_mask(
458 feature_attention_mask,
459 chunk_counts,
460 item_idx,
461 )
462 else:
463 audio_embeds = out_mm_data["audio_embeds"][item_idx]
464 assert isinstance(audio_embeds, torch.Tensor)
465 num_features = audio_embeds.shape[0]
466
467 if num_features == 0:
468 raise ValueError("Audio is too short")
469
470 audio_tokens = [audio_token_id] * int(num_features)
471 return PromptUpdateDetails.select_token_id(
472 audio_tokens,
473 embed_token_id=audio_token_id,
474 )
475
476 return [
477 PromptReplacement(
478 modality="audio",
479 target=[audio_token_id],
480 replacement=get_replacement_audioflamingo3,
481 )
482 ]
483
484
485 @MULTIMODAL_REGISTRY.register_processor(
486 AudioFlamingo3MultiModalProcessor,
487 info=AudioFlamingo3ProcessingInfo,
488 dummy_inputs=AudioFlamingo3DummyInputsBuilder,
489 )
490 class AudioFlamingo3ForConditionalGeneration(
491 nn.Module, SupportsMultiModal, SupportsPP, SupportsLoRA
492 ):
493 packed_modules_mapping = {
494 "qkv_proj": ["q_proj", "k_proj", "v_proj"],
495 "gate_up_proj": ["gate_proj", "up_proj"],
496 }
497
498 def get_mm_mapping(self) -> MultiModelKeys:
499 """Get the module prefix in multimodal models."""
500 return MultiModelKeys.from_string_field(
501 language_model="language_model.",
502 connector="multi_modal_projector.",
503 tower_model="audio_tower.",
504 )
505
506 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
507 super().__init__()
508 config = vllm_config.model_config.hf_config
509 quant_config = vllm_config.quant_config
510 multimodal_config = vllm_config.model_config.multimodal_config
511 self.config = config
512 self.multimodal_config = multimodal_config
513 self.quant_config = quant_config
514
515 with self._mark_tower_model(vllm_config, "audio"):
516 self.audio_tower = AudioFlamingo3Encoder(
517 config.audio_config,
518 )
519 self.multi_modal_projector = AudioFlamingo3MultiModalProjector(config)
520
521 with self._mark_language_model(vllm_config):
522 self.language_model = init_vllm_registered_model(
523 vllm_config=vllm_config,
524 hf_config=config.text_config,
525 prefix=maybe_prefix(prefix, "language_model"),
526 architectures=["Qwen2ForCausalLM"],
527 )
528
529 self.make_empty_intermediate_tensors = (
530 self.language_model.make_empty_intermediate_tensors
531 )
532
533 def _parse_and_validate_audio_input(
534 self, **kwargs: object
535 ) -> AudioFlamingo3Inputs | None:
536 input_features = kwargs.pop("input_features", None)
537 audio_embeds = kwargs.pop("audio_embeds", None)
538 feature_attention_mask = kwargs.pop("feature_attention_mask", None)
539 chunk_counts = kwargs.pop("chunk_counts", None)
540
541 if input_features is None and audio_embeds is None:
542 return None
543
544 if audio_embeds is not None:
545 return AudioFlamingo3EmbeddingInputs(
546 type="audio_embeds", audio_embeds=audio_embeds
547 )
548
549 if input_features is not None:
550 return AudioFlamingo3FeatureInputs(
551 type="audio_features",
552 input_features=input_features,
553 feature_attention_mask=feature_attention_mask,
554 chunk_counts=chunk_counts,
555 )
556
557 raise AssertionError("This line should be unreachable.")
558
559 def _process_audio_input(
560 self, audio_input: AudioFlamingo3Inputs
561 ) -> torch.Tensor | tuple[torch.Tensor, ...]:
562 if audio_input.type == "audio_embeds":
563 audio_embeds = audio_input.audio_embeds
564 return tuple(audio_embeds)
565
566 (
567 input_features,
568 feature_attention_mask,
569 chunk_counts,
570 ) = self._normalize_audio_feature_inputs(audio_input)
571 audio_hidden_states = self._encode_audio_features(
572 input_features,
573 feature_attention_mask,
574 )
575 audio_features = self.multi_modal_projector(audio_hidden_states)
576 return self._group_audio_embeddings(
577 audio_features,
578 feature_attention_mask,
579 chunk_counts,
580 )
581
582 def _normalize_audio_feature_inputs(
583 self, audio_input: AudioFlamingo3FeatureInputs
584 ) -> tuple[torch.Tensor, torch.Tensor, list[int]]:
585 input_features = audio_input["input_features"]
586 feature_attention_mask = audio_input["feature_attention_mask"]
587 chunk_counts = audio_input.get("chunk_counts")
588
589 if isinstance(input_features, list):
590 input_features = torch.cat(input_features, dim=0)
591 feature_attention_mask = torch.cat(feature_attention_mask, dim=0)
592
593 if chunk_counts is None:
594 chunk_counts = [1] * input_features.shape[0]
595 elif isinstance(chunk_counts, torch.Tensor):
596 chunk_counts = chunk_counts.tolist()
597 elif (
598 isinstance(chunk_counts, list)
599 and chunk_counts
600 and isinstance(chunk_counts[0], torch.Tensor)
601 ):
602 chunk_counts = [count.item() for count in chunk_counts]
603
604 return input_features, feature_attention_mask, chunk_counts
605
606 def _encode_audio_features(
607 self,
608 input_features: torch.Tensor,
609 feature_attention_mask: torch.Tensor,
610 ) -> torch.Tensor:
611 input_features = input_features.to(
612 dtype=self.audio_tower.conv1.weight.dtype,
613 device=self.audio_tower.conv1.weight.device,
614 )
615 audio_attention_mask = _build_audio_encoder_attention_mask(
616 feature_attention_mask,
617 dtype=self.audio_tower.conv1.weight.dtype,
618 device=self.audio_tower.conv1.weight.device,
619 )
620
621 return self.audio_tower(input_features, attention_mask=audio_attention_mask)
622
623 def _group_audio_embeddings(
624 self,
625 audio_features: torch.Tensor,
626 feature_attention_mask: torch.Tensor,
627 chunk_counts: list[int],
628 ) -> tuple[torch.Tensor, ...]:
629 masked_audio_features, audio_output_lengths = _flatten_valid_audio_embeddings(
630 audio_features,
631 feature_attention_mask,
632 )
633 # `split` needs Python int sizes.
634 with gpu_sync_allowed():
635 split_sizes = audio_output_lengths.tolist()
636 chunk_embeddings = torch.split(masked_audio_features, split_sizes)
637
638 grouped_embeddings = []
639 current_idx = 0
640 for count in chunk_counts:
641 audio_chunks = chunk_embeddings[current_idx : current_idx + count]
642 grouped_embeddings.append(torch.cat(audio_chunks, dim=0))
643 current_idx += count
644 return tuple(grouped_embeddings)
645
646 def embed_multimodal(self, **kwargs: object) -> MultiModalEmbeddings:
647 audio_input = self._parse_and_validate_audio_input(**kwargs)
648 if audio_input is None:
649 return []
650 masked_audio_features = self._process_audio_input(audio_input)
651 return masked_audio_features
652
653 def forward(
654 self,
655 input_ids: torch.Tensor,
656 positions: torch.Tensor,
657 intermediate_tensors: IntermediateTensors | None = None,
658 inputs_embeds: torch.Tensor | None = None,
659 **kwargs: object,
660 ) -> torch.Tensor | IntermediateTensors:
661 if intermediate_tensors is not None:
662 inputs_embeds = None
663
664 hidden_states = self.language_model.model(
665 input_ids,
666 positions,
667 intermediate_tensors,
668 inputs_embeds=inputs_embeds,
669 )
670 return hidden_states
671
672 def compute_logits(
673 self,
674 hidden_states: torch.Tensor,
675 ) -> torch.Tensor | None:
676 return self.language_model.compute_logits(hidden_states)
677
678 def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
679 loader = AutoWeightsLoader(self)
680 return loader.load_weights(weights)