Prompt48 commited on
Commit
36ac01c
·
verified ·
1 Parent(s): 58e7ae6

Upload edit\Qwen3-TTS-test\.venv\Lib\site-packages\transformers\models\granite_speech\modeling_granite_speech.py with huggingface_hub

Browse files
edit//Qwen3-TTS-test//.venv//Lib//site-packages//transformers//models//granite_speech//modeling_granite_speech.py ADDED
@@ -0,0 +1,577 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ # Copyright 2025 The HuggingFace Inc. team.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ import math
17
+ from dataclasses import dataclass
18
+ from typing import Optional, Union
19
+
20
+ import torch
21
+ import torch.nn.functional as F
22
+ from torch import nn
23
+
24
+ from ...cache_utils import Cache
25
+ from ...generation import GenerationMixin
26
+ from ...modeling_outputs import ModelOutput
27
+ from ...modeling_utils import PreTrainedModel
28
+ from ...utils import auto_docstring, is_peft_available, logging
29
+ from ..auto import AutoModel, AutoModelForCausalLM
30
+ from .configuration_granite_speech import GraniteSpeechConfig, GraniteSpeechEncoderConfig
31
+
32
+
33
+ logger = logging.get_logger(__name__)
34
+
35
+
36
+ @dataclass
37
+ @auto_docstring(
38
+ custom_intro="""
39
+ Base class for LlavaNext causal language model (or autoregressive) outputs.
40
+ """
41
+ )
42
+ class GraniteSpeechCausalLMOutputWithPast(ModelOutput):
43
+ r"""
44
+ loss (`torch.FloatTensor` of shape `(1,)`, *optional*, returned when `labels` is provided):
45
+ Language modeling loss (for next-token prediction).
46
+ logits (`torch.FloatTensor` of shape `(batch_size, sequence_length, config.vocab_size)`):
47
+ Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax).
48
+ past_key_values (`Cache`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
49
+ It is a [`~cache_utils.Cache`] instance. For more details, see our [kv cache guide](https://huggingface.co/docs/transformers/en/kv_cache).
50
+
51
+ Contains pre-computed hidden-states (key and values in the self-attention blocks) that can be used (see
52
+ `past_key_values` input) to speed up sequential decoding.
53
+ """
54
+
55
+ loss: Optional[torch.FloatTensor] = None
56
+ logits: Optional[torch.FloatTensor] = None
57
+ past_key_values: Optional[Cache] = None
58
+ hidden_states: Optional[tuple[torch.FloatTensor]] = None
59
+ attentions: Optional[tuple[torch.FloatTensor]] = None
60
+
61
+
62
+ ### Projector
63
+ class GraniteSpeechEncoderProjector(nn.Module):
64
+ def __init__(self, config: GraniteSpeechConfig):
65
+ super().__init__()
66
+ self.hidden_size = config.projector_config.hidden_size
67
+ self.downsample_rate = config.downsample_rate
68
+ self.window_size = config.window_size
69
+ self.num_queries = config.window_size // config.downsample_rate
70
+
71
+ self.query = nn.Parameter(torch.zeros(1, self.num_queries, config.projector_config.hidden_size))
72
+ self.query.data.normal_(mean=0.0, std=1.0)
73
+
74
+ # By default, this will be a blip_2_qformer config
75
+ self.qformer = AutoModel.from_config(config.projector_config)
76
+ self.linear = nn.Linear(config.projector_config.hidden_size, config.text_config.hidden_size)
77
+
78
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
79
+ batch_size, seq_len, dim = hidden_states.size()
80
+ nblocks = math.ceil(seq_len / self.window_size)
81
+ pad = nblocks * self.window_size - seq_len
82
+ hidden_states = nn.functional.pad(hidden_states, (0, 0, 0, pad), "constant", 0)
83
+ hidden_states = hidden_states.view(batch_size * nblocks, self.window_size, dim)
84
+
85
+ query_output = self.qformer(
86
+ query_embeds=self.query,
87
+ encoder_hidden_states=hidden_states,
88
+ encoder_attention_mask=None,
89
+ return_dict=True,
90
+ )
91
+ query_proj = self.linear(
92
+ query_output.last_hidden_state.view(batch_size, nblocks * self.window_size // self.downsample_rate, -1)
93
+ )
94
+ return query_proj
95
+
96
+
97
+ ### Encoder - conformer is adapted from: https://github.com/lucidrains/conformer.git
98
+ class GraniteSpeechConformerFeedForward(nn.Module):
99
+ """Feedforward module for conformer encoder blocks."""
100
+
101
+ def __init__(self, config: GraniteSpeechEncoderConfig):
102
+ super().__init__()
103
+ self.pre_norm = nn.LayerNorm(config.hidden_dim)
104
+ self.up_proj = nn.Linear(config.hidden_dim, config.hidden_dim * config.feedforward_mult)
105
+ self.silu = nn.SiLU()
106
+ self.dropout = nn.Dropout(config.dropout)
107
+ self.down_proj = nn.Linear(config.hidden_dim * config.feedforward_mult, config.hidden_dim)
108
+
109
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
110
+ hidden_states = self.pre_norm(hidden_states)
111
+ hidden_states = self.up_proj(hidden_states)
112
+ hidden_states = self.dropout(self.silu(hidden_states))
113
+ hidden_states = self.down_proj(hidden_states)
114
+ hidden_states = self.dropout(hidden_states)
115
+ return hidden_states
116
+
117
+
118
+ class GraniteSpeechConformerAttention(nn.Module):
119
+ """Attention for conformer blocks using Shaw's relative positional embeddings.
120
+ See the following [paper](https://huggingface.co/papers/1803.02155) for more details.
121
+ """
122
+
123
+ def __init__(self, config: GraniteSpeechEncoderConfig):
124
+ super().__init__()
125
+
126
+ inner_dim = config.dim_head * config.num_heads
127
+ self.max_pos_emb = config.max_pos_emb
128
+ self.context_size = config.context_size
129
+ self.num_heads = config.num_heads
130
+ self.dim_head = config.dim_head
131
+ self.scale = self.dim_head**-0.5
132
+ self.pre_norm = nn.LayerNorm(config.hidden_dim)
133
+ self.to_q = nn.Linear(config.hidden_dim, inner_dim, bias=False)
134
+ self.to_kv = nn.Linear(config.hidden_dim, inner_dim * 2, bias=False)
135
+ self.to_out = nn.Linear(inner_dim, config.hidden_dim)
136
+ self.rel_pos_emb = nn.Embedding(2 * self.max_pos_emb + 1, self.dim_head)
137
+ self.dropout = nn.Dropout(config.dropout)
138
+
139
+ if self.context_size <= 0 or self.context_size > self.max_pos_emb:
140
+ raise ValueError("Context size is either less than 0 or exceeds the max_pos_emb")
141
+
142
+ def forward(self, hidden_states: torch.Tensor, attention_dists: torch.Tensor) -> torch.Tensor:
143
+ hidden_states = self.pre_norm(hidden_states)
144
+ bsz, num_features, _ = hidden_states.shape
145
+
146
+ num_blocks = math.ceil(num_features / self.context_size)
147
+ remainder = num_features % self.context_size
148
+ if remainder > 0:
149
+ # right padding to reach block size
150
+ hidden_states = torch.nn.functional.pad(hidden_states, (0, 0, 0, self.context_size - remainder))
151
+
152
+ query_states = self.to_q(hidden_states)
153
+ key_states, value_states = self.to_kv(hidden_states).chunk(2, dim=-1)
154
+
155
+ query_states = query_states.reshape(bsz, num_blocks, self.context_size, self.num_heads, -1).transpose(2, 3)
156
+ key_states = key_states.reshape(bsz, num_blocks, self.context_size, self.num_heads, -1).transpose(2, 3)
157
+ value_states = value_states.reshape(bsz, num_blocks, self.context_size, self.num_heads, -1).transpose(2, 3)
158
+
159
+ # shaw's relative positional embedding
160
+ rel_pos_emb = self.rel_pos_emb(attention_dists)
161
+ # alternative computation of `pos_attn` - for readability
162
+ # rel_pos_emb_expanded = rel_pos_emb.view([1, 1, 1] + list(rel_pos_emb.shape))
163
+ # pos_attn = torch.sum(query_states.unsqueeze(-2) * rel_pos_emb_expanded, dim=-1) * self.scale
164
+ # einsum implementation of pos_attn - gives x30 speedup over the alternative
165
+ # TODO (@avihu111) find a fast alternative to einsum
166
+ pos_attn = torch.einsum("b m h c d, c r d -> b m h c r", query_states, rel_pos_emb) * self.scale
167
+
168
+ if remainder > 0:
169
+ # masked attention in the extended block
170
+ mask = torch.ones(self.context_size, self.context_size, dtype=bool, device=hidden_states.device)
171
+ mask[:remainder, :remainder] = 0
172
+ mask_value = -torch.finfo(pos_attn.dtype).max
173
+ pos_attn[:, -1, :].masked_fill_(mask, mask_value)
174
+
175
+ with torch.nn.attention.sdpa_kernel(torch.nn.attention.SDPBackend.MATH):
176
+ out = F.scaled_dot_product_attention(
177
+ query_states, key_states, value_states, attn_mask=pos_attn, scale=self.scale
178
+ )
179
+ out = out.transpose(2, 3).reshape(bsz, hidden_states.shape[1], -1)
180
+ out = self.to_out(out[:, :num_features, :])
181
+ return self.dropout(out)
182
+
183
+
184
+ class GraniteSpeechConformerDepthWiseConv1d(nn.Module):
185
+ """Wrapper for padded 1D pointwise convolution."""
186
+
187
+ def __init__(self, chan_in: int, chan_out: int, kernel_size: int):
188
+ super().__init__()
189
+ # Padding for the 1D conv is symmetric or close (i.e., offset by one).
190
+ pad = kernel_size // 2
191
+ pad_offset = (kernel_size + 1) % 2
192
+ self.padding = (pad, pad - pad_offset)
193
+
194
+ self.conv = nn.Conv1d(chan_in, chan_out, kernel_size, groups=chan_in, bias=False)
195
+
196
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
197
+ hidden_states = F.pad(hidden_states, self.padding)
198
+ return self.conv(hidden_states)
199
+
200
+
201
+ class GraniteSpeechConformerConvModule(nn.Module):
202
+ """Conformer conv module consisting of several 1D/depthwise 1D convolutional layers."""
203
+
204
+ def __init__(self, config: GraniteSpeechEncoderConfig):
205
+ super().__init__()
206
+ inner_dim = config.hidden_dim * config.conv_expansion_factor
207
+
208
+ self.norm = nn.LayerNorm(config.hidden_dim)
209
+ self.up_conv = nn.Conv1d(config.hidden_dim, inner_dim * 2, 1)
210
+ self.glu = nn.GLU(dim=1)
211
+ self.depth_conv = GraniteSpeechConformerDepthWiseConv1d(
212
+ inner_dim,
213
+ inner_dim,
214
+ kernel_size=config.conv_kernel_size,
215
+ )
216
+ self.silu = nn.SiLU()
217
+ self.batch_norm = nn.BatchNorm1d(inner_dim)
218
+ self.down_conv = nn.Conv1d(inner_dim, config.hidden_dim, 1)
219
+ self.dropout = nn.Dropout(config.dropout)
220
+
221
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
222
+ hidden_states = self.norm(hidden_states)
223
+ hidden_states = self.up_conv(hidden_states.permute(0, 2, 1))
224
+ hidden_states = self.glu(hidden_states)
225
+ hidden_states = self.depth_conv(hidden_states)
226
+ hidden_states = self.silu(self.batch_norm(hidden_states))
227
+ hidden_states = self.down_conv(hidden_states).permute(0, 2, 1)
228
+ hidden_states = self.dropout(hidden_states)
229
+ return hidden_states
230
+
231
+
232
+ class GraniteSpeechConformerBlock(nn.Module):
233
+ """Conformer block, consisting largely of linear layers, attention, and convolutional layers."""
234
+
235
+ def __init__(self, config: GraniteSpeechEncoderConfig):
236
+ super().__init__()
237
+ self.ff1 = GraniteSpeechConformerFeedForward(config)
238
+ self.attn = GraniteSpeechConformerAttention(config)
239
+ self.conv = GraniteSpeechConformerConvModule(config)
240
+ self.ff2 = GraniteSpeechConformerFeedForward(config)
241
+ self.post_norm = nn.LayerNorm(config.hidden_dim)
242
+
243
+ def forward(self, hidden_states: torch.Tensor, attention_dists: torch.Tensor) -> torch.Tensor:
244
+ hidden_states = 0.5 * self.ff1(hidden_states) + hidden_states
245
+ hidden_states = self.attn(hidden_states, attention_dists=attention_dists) + hidden_states
246
+ hidden_states = self.conv(hidden_states) + hidden_states
247
+ hidden_states = 0.5 * self.ff2(hidden_states) + hidden_states
248
+ hidden_states = self.post_norm(hidden_states)
249
+ return hidden_states
250
+
251
+
252
+ class GraniteSpeechCTCEncoder(nn.Module):
253
+ def __init__(self, config: GraniteSpeechEncoderConfig):
254
+ super().__init__()
255
+ self.config = config
256
+
257
+ # Precompute clamped relative positional encoding distances
258
+ seq = torch.arange(config.context_size)
259
+ relpos_dist = seq.view(-1, 1) - seq.view(1, -1)
260
+ attention_dists = torch.clamp(relpos_dist, -config.context_size, config.context_size) + config.max_pos_emb
261
+ self.register_buffer("attention_dists", attention_dists, persistent=False)
262
+ self.input_linear = nn.Linear(config.input_dim, config.hidden_dim, bias=True)
263
+ self.layers = nn.ModuleList([GraniteSpeechConformerBlock(config) for _ in range(config.num_layers)])
264
+
265
+ self.out = nn.Linear(config.hidden_dim, config.output_dim, bias=True)
266
+ self.out_mid = nn.Linear(config.output_dim, config.hidden_dim, bias=True)
267
+ self.num_layers = config.num_layers
268
+
269
+ def forward(self, hidden_states: torch.Tensor):
270
+ hidden_states = self.input_linear(hidden_states)
271
+ for idx, layer in enumerate(self.layers, start=1):
272
+ hidden_states = layer(hidden_states, attention_dists=self.attention_dists)
273
+
274
+ if idx == self.num_layers // 2:
275
+ hidden_states_mid = hidden_states.clone()
276
+ hidden_states_mid = self.out(hidden_states_mid)
277
+ hidden_states += self.out_mid(nn.Softmax(dim=-1)(hidden_states_mid))
278
+ return hidden_states
279
+
280
+
281
+ @auto_docstring
282
+ class GraniteSpeechPreTrainedModel(PreTrainedModel):
283
+ config: GraniteSpeechConfig
284
+
285
+ _supports_flash_attn = False # `blip_2_qformer` dependency does not allow for this
286
+ _supports_sdpa = True
287
+
288
+ def _init_weights(self, module: nn.Module):
289
+ """Initialize the weights."""
290
+ std = self.config.initializer_range
291
+
292
+ if isinstance(module, (nn.Linear, nn.Conv1d)):
293
+ module.weight.data.normal_(mean=0.0, std=std)
294
+ if module.bias is not None:
295
+ module.bias.data.zero_()
296
+ elif isinstance(module, nn.Embedding):
297
+ module.weight.data.normal_(mean=0.0, std=std)
298
+ if module.padding_idx is not None:
299
+ module.weight.data[module.padding_idx].zero_()
300
+ elif isinstance(module, (nn.LayerNorm, nn.BatchNorm1d)):
301
+ module.weight.data.fill_(1.0)
302
+ module.bias.data.zero_()
303
+ elif isinstance(module, GraniteSpeechEncoderProjector):
304
+ module.query.data.normal_()
305
+
306
+
307
+ @auto_docstring(
308
+ custom_intro="""
309
+ The Granite Speech model, which consists of an audio encoder, projector, and language model.
310
+ """
311
+ )
312
+ class GraniteSpeechForConditionalGeneration(GraniteSpeechPreTrainedModel, GenerationMixin):
313
+ def __init__(self, config: GraniteSpeechConfig):
314
+ super().__init__(config)
315
+ # NOTE: It doesn't matter when we initialize from config, but we should be careful
316
+ # to make sure this does not pick up the adapter_config if in the future we use
317
+ # from_pretrained or something similar, since that should be set by the composite
318
+ # model; don't need to consider it twice
319
+ self.language_model = AutoModelForCausalLM.from_config(config.text_config)
320
+
321
+ if self.language_model._tied_weights_keys is not None:
322
+ self._tied_weights_keys = [f"language_model.{k}" for k in self.language_model._tied_weights_keys]
323
+
324
+ self.encoder = GraniteSpeechCTCEncoder(config.encoder_config)
325
+ self.projector = GraniteSpeechEncoderProjector(config)
326
+
327
+ if config.has_lora_adapter and not is_peft_available():
328
+ logger.warning(
329
+ "Config indicates that a lora adapter should be present, but "
330
+ "peft is not installed; this will cause the model to perform "
331
+ "incorrectly when audio inputs are provided. Please install "
332
+ "peft and reload the model!"
333
+ )
334
+
335
+ self.post_init()
336
+
337
+ def set_input_embeddings(self, value):
338
+ self.language_model.set_input_embeddings(value)
339
+
340
+ def set_output_embeddings(self, new_embeddings):
341
+ self.language_model.set_output_embeddings(new_embeddings)
342
+
343
+ def get_input_embeddings(self):
344
+ return self.language_model.get_input_embeddings()
345
+
346
+ def get_output_embeddings(self):
347
+ return self.language_model.get_output_embeddings()
348
+
349
+ def get_audio_features(self, input_features: torch.Tensor) -> torch.Tensor:
350
+ """Get the audio features to merged into the multimodal embeddings."""
351
+ encoder_embeds = self.encoder(input_features)
352
+ projected_embeds = self.projector(encoder_embeds)
353
+ return projected_embeds
354
+
355
+ @auto_docstring
356
+ def forward(
357
+ self,
358
+ input_ids: Optional[torch.LongTensor] = None,
359
+ input_features: Optional[torch.FloatTensor] = None,
360
+ input_features_mask: Optional[torch.Tensor] = None,
361
+ attention_mask: Optional[torch.Tensor] = None,
362
+ position_ids: Optional[torch.LongTensor] = None,
363
+ past_key_values: Optional[Cache] = None,
364
+ inputs_embeds: Optional[torch.FloatTensor] = None,
365
+ labels: Optional[torch.LongTensor] = None,
366
+ use_cache: Optional[bool] = None,
367
+ output_attentions: Optional[bool] = None,
368
+ output_hidden_states: Optional[bool] = None,
369
+ return_dict: Optional[bool] = None,
370
+ cache_position: Optional[torch.LongTensor] = None,
371
+ logits_to_keep: Union[int, torch.Tensor] = 0,
372
+ **lm_kwargs,
373
+ ) -> Union[tuple[torch.Tensor], GraniteSpeechCausalLMOutputWithPast]:
374
+ r"""
375
+ input_features_mask (`torch.Tensor`, *optional*):
376
+ Mask to be applied to audio features prior to scattering into the language embeddings.
377
+ labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
378
+ Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
379
+ config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
380
+ (masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.
381
+ """
382
+ # TODO (@alex-jw-brooks) add an example to this docstring once models are released
383
+ output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
384
+ output_hidden_states = (
385
+ output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
386
+ )
387
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
388
+
389
+ if (input_ids is None) ^ (inputs_embeds is not None):
390
+ raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
391
+
392
+ if input_features is not None and inputs_embeds is not None:
393
+ raise ValueError(
394
+ "You cannot specify both input_features and inputs_embeds at the same time, and must specify either one"
395
+ )
396
+
397
+ if inputs_embeds is None:
398
+ # Get the base embeddings; set all audio tokens to 0 index
399
+ # to avoid out of vocabulary issues with the LLM embedding.
400
+ # Audio features will be masked into is_audio_idx indices later.
401
+ is_audio_idx = input_ids == self.config.audio_token_id
402
+ llm_input_ids = input_ids.clone()
403
+ llm_input_ids[is_audio_idx] = 0
404
+ inputs_embeds = self.get_input_embeddings()(llm_input_ids)
405
+
406
+ if input_features is not None:
407
+ if input_features.dtype != self.dtype:
408
+ input_features = input_features.to(self.dtype)
409
+ # Get the audio features from the encoder / projector
410
+ audio_embeds = self.get_audio_features(input_features)
411
+
412
+ # Merge the audio features into the LLM embeddings
413
+ inputs_embeds = self.get_merged_audio_embeddings(
414
+ input_ids=input_ids,
415
+ audio_features=audio_embeds,
416
+ input_features_mask=input_features_mask,
417
+ )
418
+
419
+ outputs = self.language_model(
420
+ attention_mask=attention_mask,
421
+ position_ids=position_ids,
422
+ past_key_values=past_key_values,
423
+ inputs_embeds=inputs_embeds,
424
+ use_cache=use_cache,
425
+ output_attentions=output_attentions,
426
+ output_hidden_states=output_hidden_states,
427
+ return_dict=return_dict,
428
+ cache_position=cache_position,
429
+ logits_to_keep=logits_to_keep,
430
+ **lm_kwargs,
431
+ )
432
+ logits = outputs[0]
433
+
434
+ loss = None
435
+ if labels is not None:
436
+ # Shift so that tokens < n predict n
437
+ if attention_mask is not None:
438
+ # we use the input attention mask to shift the logits and labels, because it is 2D.
439
+ # we also crop attn mask in case it is longer, which happens in PrefixTuning with peft
440
+ shift_attention_mask = attention_mask[:, -(logits.shape[1] - 1) :].to(logits.device)
441
+ shift_logits = logits[..., :-1, :][shift_attention_mask.to(logits.device) != 0].contiguous()
442
+ shift_labels = labels[..., 1:][shift_attention_mask.to(labels.device) != 0].contiguous()
443
+ else:
444
+ shift_logits = logits[..., :-1, :].contiguous()
445
+ shift_labels = labels[..., 1:].contiguous()
446
+ # Flatten the tokens
447
+ loss_fct = nn.CrossEntropyLoss()
448
+ loss = loss_fct(
449
+ shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1).to(shift_logits.device)
450
+ )
451
+
452
+ if not return_dict:
453
+ output = (logits,) + outputs[1:]
454
+ return (loss,) + output if loss is not None else output
455
+
456
+ return GraniteSpeechCausalLMOutputWithPast(
457
+ loss=loss,
458
+ logits=logits,
459
+ past_key_values=outputs.past_key_values,
460
+ hidden_states=outputs.hidden_states,
461
+ attentions=outputs.attentions,
462
+ )
463
+
464
+ def prepare_inputs_for_generation(
465
+ self,
466
+ input_ids,
467
+ past_key_values=None,
468
+ inputs_embeds=None,
469
+ input_features=None,
470
+ attention_mask=None,
471
+ cache_position=None,
472
+ logits_to_keep=None,
473
+ **kwargs,
474
+ ):
475
+ # Overwritten -- in specific circumstances we don't want to forward audio inputs to the model
476
+
477
+ model_inputs = self.language_model.prepare_inputs_for_generation(
478
+ input_ids,
479
+ past_key_values=past_key_values,
480
+ inputs_embeds=inputs_embeds,
481
+ attention_mask=attention_mask,
482
+ cache_position=cache_position,
483
+ logits_to_keep=logits_to_keep,
484
+ **kwargs,
485
+ )
486
+
487
+ # If we're in cached decoding stage, input_features should be None because
488
+ # input ids do not contain special audio token anymore Otherwise we need
489
+ # input feature values to be passed to the model
490
+ if cache_position[0] == 0:
491
+ model_inputs["input_features"] = input_features
492
+ return model_inputs
493
+
494
+ def get_merged_audio_embeddings(
495
+ self, input_ids: torch.Tensor, audio_features: torch.Tensor, input_features_mask: Optional[torch.Tensor] = None
496
+ ) -> torch.Tensor:
497
+ """
498
+ Adds the audio token to the model's LLM vocabulary so that we can pass it
499
+ through the tokenizer; it's assumed that the embeddings corresponding to the
500
+ <|audio|> token will be clobbered with speech features.
501
+
502
+ Args:
503
+ input_ids (`torch.Tensor`):
504
+ Input IDs containing one or more audio tokens.
505
+ audio_features (`torch.Tensor`):
506
+ Audio features to be masked into the language embeddings to form multimodal embeddings.
507
+ input_features_mask (`torch.Tensor`, *optional*, defaults to `None`)
508
+ Mask to be applied to audio features prior to scattering into the language embeddings.
509
+ """
510
+ is_audio_index = input_ids == self.config.audio_token_id
511
+ llm_input_ids = torch.where(is_audio_index, 0, input_ids)
512
+ inputs_embeds = self.language_model.get_input_embeddings()(llm_input_ids) # [bsz, # features, hidden size]
513
+
514
+ # Mask the audio features into the text embeddings
515
+ special_audio_mask = is_audio_index.unsqueeze(-1)
516
+ audio_features = audio_features.to(inputs_embeds.device, inputs_embeds.dtype)
517
+ if input_features_mask is not None:
518
+ if torch.all(is_audio_index.int().sum(dim=1) != input_features_mask.int().sum(dim=1)).item():
519
+ raise ValueError("Number of audio tokens does not match number of audio features")
520
+
521
+ audio_features = audio_features[input_features_mask]
522
+
523
+ inputs_embeds = inputs_embeds.masked_scatter(
524
+ special_audio_mask,
525
+ audio_features,
526
+ )
527
+ return inputs_embeds
528
+
529
+ def generate(self, *args, **kwargs) -> torch.LongTensor:
530
+ # This model is expected to have a lora adapter, which is only
531
+ # enabled when considering audio inputs. As such, we override generate
532
+ # to conditionally enable / disable the lora adapter based on whether
533
+ # or not any input features were provided.
534
+
535
+ input_features = kwargs.pop("input_features", None)
536
+ if is_peft_available and self._hf_peft_config_loaded:
537
+ if input_features is not None:
538
+ self.enable_adapters()
539
+ else:
540
+ self.disable_adapters()
541
+ return super().generate(*args, input_features=input_features, **kwargs)
542
+
543
+ def save_pretrained(self, save_directory, *args, **kwargs):
544
+ # overwrite save_pretrained to first save the adapter if we have one
545
+ if is_peft_available and self._hf_peft_config_loaded:
546
+ adapter_name = self._get_adapter_name()
547
+ self.peft_config[adapter_name].base_model_name_or_path = save_directory
548
+ super().save_pretrained(save_directory, *args, **kwargs)
549
+ # Then save the base model afterwards
550
+ prev_val = self._hf_peft_config_loaded
551
+ self._hf_peft_config_loaded = False
552
+ super().save_pretrained(save_directory, *args, **kwargs)
553
+ self._hf_peft_config_loaded = prev_val
554
+
555
+ @staticmethod
556
+ def _fix_state_dict_key_on_save(key) -> tuple[str, bool]:
557
+ # save the model with the original weights format
558
+ return key.replace(".base_layer", ""), False
559
+
560
+ def _fix_state_dict_keys_on_save(self, state_dict):
561
+ if is_peft_available and self._hf_peft_config_loaded:
562
+ # state dict is only adapter, should keep the same
563
+ return state_dict
564
+ # rename back the base model state dict
565
+ return {
566
+ self._fix_state_dict_key_on_save(key)[0]: value for key, value in state_dict.items() if ".lora_" not in key
567
+ }
568
+
569
+ def _get_adapter_name(self):
570
+ return list(self.peft_config.keys())[0]
571
+
572
+
573
+ __all__ = [
574
+ "GraniteSpeechCTCEncoder",
575
+ "GraniteSpeechForConditionalGeneration",
576
+ "GraniteSpeechPreTrainedModel",
577
+ ]