pinecoresystems commited on
Commit
31cd268
·
verified ·
1 Parent(s): 8a5cd11

Mirror modeling_moss_tts.py

Browse files
Files changed (1) hide show
  1. modeling_moss_tts.py +623 -0
modeling_moss_tts.py ADDED
@@ -0,0 +1,623 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # coding=utf-8
2
+ """Modeling code for the MOSS-TTS-Local-Transformer-v1.5 HuggingFace release."""
3
+
4
+ from __future__ import annotations
5
+
6
+ from dataclasses import dataclass
7
+ from typing import Any, Optional, Union
8
+
9
+ import torch
10
+ import torch.nn as nn
11
+ from transformers.modeling_outputs import BaseModelOutputWithPast
12
+ from transformers.modeling_utils import PreTrainedModel
13
+ from transformers.models.gpt2.configuration_gpt2 import GPT2Config
14
+ from transformers.utils import ModelOutput
15
+
16
+ from .configuration_moss_tts import MossTTSLocalConfig
17
+ from .gpt2_decoder import MossTTSNanoGPT2Model
18
+ from .qwen3_decoder import MossQwen3Model
19
+
20
+
21
+ @dataclass
22
+ class MossTTSLocalOutput(ModelOutput):
23
+ last_hidden_state: Optional[torch.FloatTensor] = None
24
+ past_key_values: Optional[tuple[tuple[torch.Tensor, torch.Tensor], ...]] = None
25
+ hidden_states: Optional[tuple[torch.FloatTensor, ...]] = None
26
+ attentions: Optional[tuple[torch.FloatTensor, ...]] = None
27
+
28
+
29
+ def _find_last_equal(input_ids: torch.LongTensor, value: int) -> torch.LongTensor:
30
+ matches = input_ids.eq(int(value))
31
+ if not bool(matches.any(dim=1).all().item()):
32
+ raise ValueError(f"Every sample must contain token id {int(value)}.")
33
+ positions = torch.arange(input_ids.shape[1], device=input_ids.device, dtype=torch.long)
34
+ masked_positions = positions.unsqueeze(0).masked_fill(~matches, -1)
35
+ return masked_positions.max(dim=1).values
36
+
37
+
38
+ class MossTTSLocalPreTrainedModel(PreTrainedModel):
39
+ config_class = MossTTSLocalConfig
40
+ base_model_prefix = "transformer"
41
+ supports_gradient_checkpointing = True
42
+ _no_split_modules = ["MossTTSNanoGPT2Block", "MossQwen3DecoderLayer"]
43
+ _supports_flash_attn_2 = True
44
+ _supports_sdpa = True
45
+ _supports_cache_class = True
46
+
47
+ def _set_gradient_checkpointing(self, module: nn.Module, value: bool = False) -> None:
48
+ if isinstance(module, MossTTSNanoGPT2Model) or isinstance(module, MossQwen3Model):
49
+ module.gradient_checkpointing = value
50
+
51
+
52
+ class MossTTSLocalModel(MossTTSLocalPreTrainedModel):
53
+ _tied_weights_keys = None
54
+
55
+ def __init__(self, config: MossTTSLocalConfig) -> None:
56
+ super().__init__(config)
57
+ self._tied_weights_keys = self._build_tied_weights_keys(config)
58
+
59
+ config.qwen3_config.pad_token_id = config.pad_token_id
60
+ config.qwen3_config._attn_implementation = config.attn_implementation
61
+ local_gpt2_config = config.gpt2_config.to_dict()
62
+ local_gpt2_config["n_layer"] = int(getattr(config, "local_transformer_layers", config.gpt2_config.n_layer))
63
+ local_gpt2_config["n_positions"] = int(config.n_vq) + 1
64
+ local_gpt2_config["n_ctx"] = int(config.n_vq) + 1
65
+ local_gpt2_config = GPT2Config(**local_gpt2_config)
66
+ local_gpt2_config.pad_token_id = config.pad_token_id
67
+ local_gpt2_config._attn_implementation = config.local_transformer_attn_implementation
68
+
69
+ self.transformer = MossQwen3Model(config.qwen3_config)
70
+ self.local_transformer = MossTTSNanoGPT2Model(
71
+ local_gpt2_config,
72
+ attn_implementation=config.local_transformer_attn_implementation,
73
+ )
74
+ self.local_transformer.wte = nn.Identity()
75
+
76
+ hidden_size = int(config.hidden_size)
77
+ self.audio_embeddings = nn.ModuleList(
78
+ [
79
+ nn.Embedding(int(config.audio_codebook_sizes[index]), hidden_size)
80
+ for index in range(config.n_vq)
81
+ ]
82
+ )
83
+ self.text_lm_head = nn.Linear(hidden_size, int(config.vocab_size), bias=False)
84
+ self.audio_lm_heads = nn.ModuleList(
85
+ [
86
+ nn.Linear(hidden_size, int(config.audio_codebook_sizes[index]), bias=False)
87
+ for index in range(config.n_vq)
88
+ ]
89
+ )
90
+ self.local_text_lm_head = (
91
+ nn.Linear(hidden_size, 2, bias=False)
92
+ if self._use_binary_local_text_head()
93
+ else None
94
+ )
95
+
96
+ self.post_init()
97
+ self.tie_weights()
98
+ self.initialize_local_text_lm_head_from_text_lm_head()
99
+
100
+ def can_generate(self) -> bool:
101
+ return True
102
+
103
+ @staticmethod
104
+ def _build_tied_weights_keys(config: MossTTSLocalConfig) -> dict[str, str]:
105
+ tied_weights = {"text_lm_head.weight": "transformer.embed_tokens.weight"}
106
+ tied_weights.update(
107
+ {
108
+ f"audio_lm_heads.{index}.weight": f"audio_embeddings.{index}.weight"
109
+ for index in range(config.n_vq)
110
+ }
111
+ )
112
+ return tied_weights
113
+
114
+ def tie_weights(self, *args, **kwargs) -> None:
115
+ del args, kwargs
116
+ self.text_lm_head.weight = self.transformer.embed_tokens.weight
117
+ for embedding, head in zip(self.audio_embeddings, self.audio_lm_heads):
118
+ head.weight = embedding.weight
119
+
120
+ def get_input_embeddings(self) -> nn.Embedding:
121
+ return self.transformer.embed_tokens
122
+
123
+ def set_input_embeddings(self, value: nn.Embedding) -> None:
124
+ self.transformer.embed_tokens = value
125
+ self.tie_weights()
126
+ self.initialize_local_text_lm_head_from_text_lm_head()
127
+
128
+ def get_output_embeddings(self) -> nn.Linear:
129
+ return self.text_lm_head
130
+
131
+ def set_output_embeddings(self, new_embeddings: nn.Linear) -> None:
132
+ self.text_lm_head = new_embeddings
133
+ self.tie_weights()
134
+ self.initialize_local_text_lm_head_from_text_lm_head()
135
+
136
+ def _use_binary_local_text_head(self) -> bool:
137
+ return str(getattr(self.config, "local_text_head_mode", "full_vocab")).strip().lower() == "binary"
138
+
139
+ def _local_text_candidate_ids(self, device: torch.device) -> torch.LongTensor:
140
+ return torch.tensor(
141
+ [
142
+ int(self.config.audio_assistant_slot_token_id),
143
+ int(self.config.audio_end_token_id),
144
+ ],
145
+ dtype=torch.long,
146
+ device=device,
147
+ )
148
+
149
+ def initialize_local_text_lm_head_from_text_lm_head(self) -> None:
150
+ if not self._use_binary_local_text_head() or self.local_text_lm_head is None:
151
+ return
152
+ candidate_ids = self._local_text_candidate_ids(self.text_lm_head.weight.device)
153
+ with torch.no_grad():
154
+ source_weight = self.text_lm_head.weight.index_select(0, candidate_ids)
155
+ if tuple(source_weight.shape) == tuple(self.local_text_lm_head.weight.shape):
156
+ self.local_text_lm_head.weight.copy_(
157
+ source_weight.to(
158
+ device=self.local_text_lm_head.weight.device,
159
+ dtype=self.local_text_lm_head.weight.dtype,
160
+ )
161
+ )
162
+
163
+ def _resolve_fixed_nq(
164
+ self,
165
+ n_vq_for_inference: Optional[int] = None,
166
+ nq: Optional[int] = None,
167
+ ) -> int:
168
+ requested = n_vq_for_inference if n_vq_for_inference is not None else nq
169
+ config_nq = int(self.config.n_vq)
170
+ if requested is not None and int(requested) != config_nq:
171
+ raise ValueError(
172
+ "This MOSS-TTS-Local-Transformer-v1.5 release is trained with a fixed RVQ depth. "
173
+ f"Expected n_vq={config_nq}, got {int(requested)}."
174
+ )
175
+ return config_nq
176
+
177
+ def _build_inputs_embeds(self, input_ids: torch.LongTensor) -> torch.FloatTensor:
178
+ if input_ids.ndim != 3 or input_ids.shape[-1] != self.config.n_vq + 1:
179
+ raise ValueError(
180
+ f"Expected input_ids shape [batch, seq, {self.config.n_vq + 1}], "
181
+ f"got {tuple(input_ids.shape)}."
182
+ )
183
+ text_ids = input_ids[..., 0]
184
+ inputs_embeds = self.transformer.embed_tokens(text_ids)
185
+ for channel_index, embedding in enumerate(self.audio_embeddings):
186
+ channel_ids = input_ids[..., channel_index + 1]
187
+ valid_mask = channel_ids.ne(self.config.audio_pad_token_id)
188
+ safe_ids = channel_ids.masked_fill(~valid_mask, 0)
189
+ audio_embeds = embedding(safe_ids) * valid_mask.unsqueeze(-1)
190
+ inputs_embeds = inputs_embeds + audio_embeds
191
+ return inputs_embeds
192
+
193
+ def _global_hidden_to_local(self, hidden_states: torch.FloatTensor) -> torch.FloatTensor:
194
+ return hidden_states
195
+
196
+ @staticmethod
197
+ def _local_past_length(past_key_values: Optional[tuple[Any, ...]]) -> int:
198
+ if past_key_values is None or len(past_key_values) == 0:
199
+ return 0
200
+ first_layer_past = past_key_values[0]
201
+ if isinstance(first_layer_past, dict) and bool(first_layer_past.get("static_kv_cache", False)):
202
+ return int(first_layer_past.get("length", 0))
203
+ return int(first_layer_past[0].shape[1])
204
+
205
+ def _new_static_local_past_key_values(
206
+ self,
207
+ batch_size: int,
208
+ max_length: int,
209
+ device: torch.device,
210
+ dtype: torch.dtype,
211
+ ) -> tuple[dict[str, Any], ...]:
212
+ layers = []
213
+ for block in self.local_transformer.h:
214
+ attn = block.attn
215
+ cache_shape = (
216
+ int(batch_size),
217
+ int(max_length),
218
+ int(attn.num_heads),
219
+ int(attn.head_dim),
220
+ )
221
+ layers.append(
222
+ {
223
+ "static_kv_cache": True,
224
+ "key": torch.empty(cache_shape, device=device, dtype=dtype),
225
+ "value": torch.empty(cache_shape, device=device, dtype=dtype),
226
+ "length": 0,
227
+ }
228
+ )
229
+ return tuple(layers)
230
+
231
+ def _decode_local_hidden_states_with_cache(
232
+ self,
233
+ local_inputs_embeds: torch.FloatTensor,
234
+ past_key_values: Optional[tuple[Any, ...]] = None,
235
+ ) -> tuple[torch.FloatTensor, Optional[tuple[Any, ...]]]:
236
+ if (
237
+ past_key_values is None
238
+ and not self.training
239
+ and bool(getattr(self.config, "use_static_local_kv_cache", True))
240
+ ):
241
+ max_length = max(int(getattr(self.config, "n_vq", 0)) + 1, int(local_inputs_embeds.shape[1]))
242
+ past_key_values = self._new_static_local_past_key_values(
243
+ batch_size=int(local_inputs_embeds.shape[0]),
244
+ max_length=max_length,
245
+ device=local_inputs_embeds.device,
246
+ dtype=local_inputs_embeds.dtype,
247
+ )
248
+ past_length = self._local_past_length(past_key_values)
249
+ local_seq_len = int(local_inputs_embeds.shape[1])
250
+ local_position_ids = torch.arange(
251
+ past_length,
252
+ past_length + local_seq_len,
253
+ device=local_inputs_embeds.device,
254
+ dtype=torch.long,
255
+ ).unsqueeze(0)
256
+ if int(local_inputs_embeds.shape[0]) != 1:
257
+ local_position_ids = local_position_ids.expand(int(local_inputs_embeds.shape[0]), -1)
258
+ local_outputs = self.local_transformer(
259
+ input_ids=None,
260
+ past_key_values=past_key_values,
261
+ attention_mask=None,
262
+ position_ids=local_position_ids,
263
+ inputs_embeds=local_inputs_embeds,
264
+ use_cache=True,
265
+ output_attentions=False,
266
+ output_hidden_states=False,
267
+ return_dict=True,
268
+ cu_seqlens=None,
269
+ num_sequences=None,
270
+ )
271
+ return local_outputs.last_hidden_state, local_outputs.past_key_values
272
+
273
+ def forward(
274
+ self,
275
+ input_ids: Optional[torch.LongTensor] = None,
276
+ attention_mask: Optional[torch.Tensor] = None,
277
+ position_ids: Optional[torch.LongTensor] = None,
278
+ past_key_values: Optional[tuple[tuple[torch.Tensor, torch.Tensor], ...]] = None,
279
+ inputs_embeds: Optional[torch.FloatTensor] = None,
280
+ use_cache: Optional[bool] = None,
281
+ output_attentions: Optional[bool] = None,
282
+ output_hidden_states: Optional[bool] = None,
283
+ return_dict: Optional[bool] = True,
284
+ **kwargs,
285
+ ) -> Union[tuple, MossTTSLocalOutput]:
286
+ del kwargs
287
+ if inputs_embeds is None:
288
+ if input_ids is None:
289
+ raise ValueError("Either input_ids or inputs_embeds must be provided.")
290
+ inputs_embeds = self._build_inputs_embeds(input_ids)
291
+ outputs = self.transformer(
292
+ input_ids=None,
293
+ attention_mask=attention_mask,
294
+ position_ids=position_ids,
295
+ past_key_values=past_key_values,
296
+ inputs_embeds=inputs_embeds,
297
+ use_cache=use_cache,
298
+ output_attentions=output_attentions,
299
+ output_hidden_states=output_hidden_states,
300
+ return_dict=True,
301
+ cu_seqlens=None,
302
+ num_sequences=None,
303
+ )
304
+ if not return_dict:
305
+ return (
306
+ outputs.last_hidden_state,
307
+ outputs.past_key_values,
308
+ outputs.hidden_states,
309
+ outputs.attentions,
310
+ )
311
+ return MossTTSLocalOutput(
312
+ last_hidden_state=outputs.last_hidden_state,
313
+ past_key_values=outputs.past_key_values,
314
+ hidden_states=outputs.hidden_states,
315
+ attentions=outputs.attentions,
316
+ )
317
+
318
+ def _decode_local_last_hidden_state(
319
+ self,
320
+ local_inputs_embeds: torch.FloatTensor,
321
+ ) -> torch.FloatTensor:
322
+ local_seq_len = int(local_inputs_embeds.shape[1])
323
+ local_position_ids = torch.arange(
324
+ 0,
325
+ local_seq_len,
326
+ device=local_inputs_embeds.device,
327
+ dtype=torch.long,
328
+ ).unsqueeze(0)
329
+ if int(local_inputs_embeds.shape[0]) != 1:
330
+ local_position_ids = local_position_ids.expand(int(local_inputs_embeds.shape[0]), -1)
331
+ local_outputs = self.local_transformer(
332
+ input_ids=None,
333
+ attention_mask=None,
334
+ position_ids=local_position_ids,
335
+ inputs_embeds=local_inputs_embeds,
336
+ use_cache=False,
337
+ output_attentions=False,
338
+ output_hidden_states=False,
339
+ return_dict=True,
340
+ cu_seqlens=None,
341
+ num_sequences=None,
342
+ )
343
+ return local_outputs.last_hidden_state[:, -1, :]
344
+
345
+ def _filter_logits(
346
+ self,
347
+ logits: torch.FloatTensor,
348
+ top_k: Optional[int],
349
+ top_p: Optional[float],
350
+ ) -> torch.FloatTensor:
351
+ scores = logits
352
+ if top_k is not None and int(top_k) > 0 and int(top_k) < scores.shape[-1]:
353
+ kth = torch.topk(scores, int(top_k), dim=-1).values[..., -1, None]
354
+ scores = scores.masked_fill(scores < kth, -torch.inf)
355
+ if top_p is not None and 0.0 < float(top_p) < 1.0:
356
+ sorted_scores, sorted_indices = torch.sort(scores, descending=True, dim=-1)
357
+ sorted_probs = torch.softmax(sorted_scores, dim=-1)
358
+ cumulative_probs = sorted_probs.cumsum(dim=-1)
359
+ sorted_mask = cumulative_probs > float(top_p)
360
+ sorted_mask[..., 1:] = sorted_mask[..., :-1].clone()
361
+ sorted_mask[..., 0] = False
362
+ remove_mask = torch.zeros_like(scores, dtype=torch.bool)
363
+ remove_mask.scatter_(dim=-1, index=sorted_indices, src=sorted_mask)
364
+ scores = scores.masked_fill(remove_mask, -torch.inf)
365
+ return scores
366
+
367
+ def _apply_repetition_penalty(
368
+ self,
369
+ scores: torch.FloatTensor,
370
+ previous_token_ids: Optional[torch.LongTensor],
371
+ penalty: float,
372
+ ) -> torch.FloatTensor:
373
+ if previous_token_ids is None or float(penalty) == 1.0:
374
+ return scores
375
+ if previous_token_ids.ndim == 1:
376
+ previous_token_ids = previous_token_ids.unsqueeze(0)
377
+ updated = scores.clone()
378
+ for batch_index in range(updated.shape[0]):
379
+ unique_token_ids = torch.unique(previous_token_ids[batch_index])
380
+ unique_token_ids = unique_token_ids[
381
+ (unique_token_ids >= 0) & (unique_token_ids < updated.shape[-1])
382
+ ]
383
+ if unique_token_ids.numel() == 0:
384
+ continue
385
+ token_scores = updated[batch_index].index_select(0, unique_token_ids)
386
+ token_scores = torch.where(
387
+ token_scores < 0,
388
+ token_scores * float(penalty),
389
+ token_scores / float(penalty),
390
+ )
391
+ updated[batch_index].scatter_(0, unique_token_ids, token_scores)
392
+ return updated
393
+
394
+ def _sample_next_token(
395
+ self,
396
+ logits: torch.FloatTensor,
397
+ do_sample: bool,
398
+ temperature: float,
399
+ top_k: Optional[int],
400
+ top_p: Optional[float],
401
+ previous_token_ids: Optional[torch.LongTensor] = None,
402
+ repetition_penalty: float = 1.0,
403
+ ) -> torch.LongTensor:
404
+ scores = logits.float()
405
+ scores = self._apply_repetition_penalty(scores, previous_token_ids, repetition_penalty)
406
+ if not do_sample:
407
+ return torch.argmax(scores, dim=-1)
408
+ if float(temperature) <= 0:
409
+ raise ValueError("temperature must be positive when do_sample=True.")
410
+ scores = scores / float(temperature)
411
+ scores = self._filter_logits(scores, top_k=top_k, top_p=top_p)
412
+ probs = torch.softmax(scores, dim=-1)
413
+ return torch.multinomial(probs, num_samples=1).squeeze(-1)
414
+
415
+ def _sample_next_assistant_text_token(
416
+ self,
417
+ local_hidden_states: torch.FloatTensor,
418
+ do_sample: bool,
419
+ temperature: float,
420
+ top_k: Optional[int],
421
+ top_p: Optional[float],
422
+ ) -> torch.LongTensor:
423
+ if self._use_binary_local_text_head() and self.local_text_lm_head is not None:
424
+ logits = self.local_text_lm_head(local_hidden_states)
425
+ sampled_indices = self._sample_next_token(
426
+ logits=logits,
427
+ do_sample=do_sample,
428
+ temperature=temperature,
429
+ top_k=top_k,
430
+ top_p=top_p,
431
+ )
432
+ candidate_ids = self._local_text_candidate_ids(logits.device)
433
+ return candidate_ids[sampled_indices]
434
+
435
+ candidate_ids = self._local_text_candidate_ids(local_hidden_states.device)
436
+ logits = self.text_lm_head(local_hidden_states).index_select(dim=-1, index=candidate_ids)
437
+ sampled_indices = self._sample_next_token(
438
+ logits=logits,
439
+ do_sample=do_sample,
440
+ temperature=temperature,
441
+ top_k=top_k,
442
+ top_p=top_p,
443
+ )
444
+ return candidate_ids[sampled_indices]
445
+
446
+ def _build_generation_row(
447
+ self,
448
+ batch_size: int,
449
+ device: torch.device,
450
+ audio_token_ids: torch.LongTensor,
451
+ ) -> torch.LongTensor:
452
+ row = torch.full(
453
+ (batch_size, 1, self.config.n_vq + 1),
454
+ int(self.config.audio_pad_token_id),
455
+ dtype=torch.long,
456
+ device=device,
457
+ )
458
+ row[:, :, 0] = int(self.config.audio_assistant_slot_token_id)
459
+ row[:, :, 1:] = audio_token_ids.unsqueeze(1)
460
+ return row
461
+
462
+ @torch.inference_mode()
463
+ def generate(
464
+ self,
465
+ input_ids: torch.LongTensor,
466
+ attention_mask: Optional[torch.Tensor] = None,
467
+ max_new_tokens: Optional[int] = None,
468
+ max_new_frames: Optional[int] = None,
469
+ do_sample: bool = True,
470
+ text_temperature: float = 1.0,
471
+ text_top_p: float = 1.0,
472
+ text_top_k: int = 50,
473
+ audio_temperature: Optional[float] = None,
474
+ audio_top_p: Optional[float] = None,
475
+ audio_top_k: Optional[int] = None,
476
+ audio_repetition_penalty: Optional[float] = None,
477
+ temperature: float = 1.0,
478
+ top_p: float = 0.95,
479
+ top_k: int = 50,
480
+ repetition_penalty: float = 1.0,
481
+ use_kv_cache: bool = True,
482
+ n_vq_for_inference: Optional[int] = None,
483
+ nq: Optional[int] = None,
484
+ **kwargs,
485
+ ) -> list[tuple[int, torch.LongTensor]]:
486
+ del kwargs
487
+ self._resolve_fixed_nq(n_vq_for_inference=n_vq_for_inference, nq=nq)
488
+
489
+ if input_ids.ndim == 2:
490
+ input_ids = input_ids.unsqueeze(0)
491
+ if input_ids.ndim != 3:
492
+ raise ValueError(f"Expected input_ids with 3 dims, got {tuple(input_ids.shape)}.")
493
+ if input_ids.shape[-1] != self.config.n_vq + 1:
494
+ raise ValueError(
495
+ f"Expected {self.config.n_vq + 1} channels from config.n_vq, got {input_ids.shape[-1]}."
496
+ )
497
+ if attention_mask is None:
498
+ attention_mask = torch.ones(input_ids.shape[:2], dtype=torch.bool, device=input_ids.device)
499
+ elif attention_mask.ndim == 1:
500
+ attention_mask = attention_mask.unsqueeze(0)
501
+ attention_mask = attention_mask.to(device=input_ids.device, dtype=torch.bool)
502
+
503
+ frame_budget = max_new_frames if max_new_frames is not None else max_new_tokens
504
+ if frame_budget is None:
505
+ frame_budget = 4096
506
+ frame_budget = int(frame_budget)
507
+
508
+ audio_temperature = float(temperature if audio_temperature is None else audio_temperature)
509
+ audio_top_p = float(top_p if audio_top_p is None else audio_top_p)
510
+ audio_top_k = int(top_k if audio_top_k is None else audio_top_k)
511
+ audio_repetition_penalty = float(
512
+ repetition_penalty if audio_repetition_penalty is None else audio_repetition_penalty
513
+ )
514
+
515
+ batch_size = input_ids.shape[0]
516
+ input_ids_length = input_ids.shape[1]
517
+ current_input_ids = input_ids
518
+ current_attention_mask = attention_mask
519
+ current_model_input_ids = current_input_ids
520
+ generated_frames: list[torch.LongTensor] = []
521
+ finished = torch.zeros(batch_size, dtype=torch.bool, device=input_ids.device)
522
+ past_key_values = None
523
+ local_dtype = self.local_transformer.ln_f.weight.dtype
524
+
525
+ for _ in range(frame_budget):
526
+ generated_audio_history = torch.stack(generated_frames, dim=1) if generated_frames else None
527
+ global_inputs_embeds = self._build_inputs_embeds(current_model_input_ids)
528
+ global_outputs = self.transformer(
529
+ input_ids=None,
530
+ past_key_values=past_key_values,
531
+ attention_mask=current_attention_mask,
532
+ position_ids=None,
533
+ inputs_embeds=global_inputs_embeds,
534
+ use_cache=use_kv_cache,
535
+ output_attentions=False,
536
+ output_hidden_states=False,
537
+ return_dict=True,
538
+ cu_seqlens=None,
539
+ num_sequences=None,
540
+ )
541
+ global_hidden_states = global_outputs.last_hidden_state[:, -1, :]
542
+ local_global_hidden_states = self._global_hidden_to_local(global_hidden_states).to(dtype=local_dtype)
543
+
544
+ local_prefix_hidden_states, local_prefix_past_key_values = self._decode_local_hidden_states_with_cache(
545
+ local_global_hidden_states.unsqueeze(1)
546
+ )
547
+ local_hidden_states = local_prefix_hidden_states[:, -1, :]
548
+ next_text_tokens = self._sample_next_assistant_text_token(
549
+ local_hidden_states=local_hidden_states,
550
+ do_sample=do_sample,
551
+ temperature=text_temperature,
552
+ top_k=text_top_k,
553
+ top_p=text_top_p,
554
+ )
555
+ should_continue = next_text_tokens.eq(int(self.config.audio_assistant_slot_token_id)) & ~finished
556
+ finished = finished | next_text_tokens.eq(int(self.config.audio_end_token_id))
557
+ if not bool(should_continue.any().item()):
558
+ break
559
+
560
+ next_frame_tokens = []
561
+ for channel_index in range(int(self.config.n_vq)):
562
+ channel_logits = self.audio_lm_heads[channel_index](local_hidden_states)
563
+ channel_token = self._sample_next_token(
564
+ logits=channel_logits,
565
+ do_sample=do_sample,
566
+ temperature=audio_temperature,
567
+ top_k=audio_top_k,
568
+ top_p=audio_top_p,
569
+ previous_token_ids=(
570
+ None
571
+ if generated_audio_history is None
572
+ else generated_audio_history[:, :, channel_index]
573
+ ),
574
+ repetition_penalty=audio_repetition_penalty,
575
+ )
576
+ next_frame_tokens.append(channel_token)
577
+ if channel_index + 1 < int(self.config.n_vq):
578
+ current_local_input = self.audio_embeddings[channel_index](channel_token).to(dtype=local_dtype)
579
+ local_token_hidden_states, local_prefix_past_key_values = (
580
+ self._decode_local_hidden_states_with_cache(
581
+ current_local_input.unsqueeze(1),
582
+ past_key_values=local_prefix_past_key_values,
583
+ )
584
+ )
585
+ local_hidden_states = local_token_hidden_states[:, -1, :]
586
+
587
+ next_frame = torch.stack(next_frame_tokens, dim=-1)
588
+ next_frame = next_frame.masked_fill(
589
+ ~should_continue.unsqueeze(-1),
590
+ int(self.config.audio_pad_token_id),
591
+ )
592
+ generated_frames.append(next_frame)
593
+
594
+ next_row = self._build_generation_row(
595
+ batch_size=batch_size,
596
+ device=input_ids.device,
597
+ audio_token_ids=next_frame,
598
+ )
599
+ if bool((~should_continue).any().item()):
600
+ next_row[~should_continue, 0, 0] = int(self.config.pad_token_id)
601
+ next_row[~should_continue, 0, 1:] = int(self.config.audio_pad_token_id)
602
+
603
+ current_input_ids = torch.cat([current_input_ids, next_row], dim=1)
604
+ current_attention_mask = torch.cat(
605
+ [current_attention_mask, should_continue.unsqueeze(1)],
606
+ dim=1,
607
+ )
608
+ if use_kv_cache:
609
+ current_model_input_ids = next_row
610
+ past_key_values = global_outputs.past_key_values
611
+ else:
612
+ current_model_input_ids = current_input_ids
613
+
614
+ start_indices = _find_last_equal(input_ids[..., 0], int(self.config.audio_start_token_id))
615
+ start_lengths = input_ids_length - start_indices - 1
616
+ outputs: list[tuple[int, torch.LongTensor]] = []
617
+ for start_index, start_length, generation_ids in zip(
618
+ start_indices.tolist(),
619
+ start_lengths.tolist(),
620
+ current_input_ids,
621
+ ):
622
+ outputs.append((int(start_length), generation_ids[int(start_index):].detach().cpu()))
623
+ return outputs