| from __future__ import annotations |
|
|
| import torch |
| from torch import nn |
| from transformers.models.cohere2.modeling_cohere2 import Cohere2ForCausalLM |
|
|
| from .configuration_tinyaya import TinyAyaConfig |
|
|
|
|
| class TinyAyaForCausalLM(Cohere2ForCausalLM): |
| config_class = TinyAyaConfig |
|
|
| def __init__(self, config): |
| super().__init__(config) |
| hidden = int(config.hidden_size) |
| self.stop_predictor = nn.Sequential( |
| nn.LayerNorm(hidden), |
| nn.Linear(hidden, max(64, hidden // 4)), |
| nn.GELU(), |
| nn.Linear(max(64, hidden // 4), 1), |
| ) |
|
|
| @staticmethod |
| def _sample(scores, do_sample, temperature, top_k): |
| if not do_sample: |
| return scores.argmax(dim=-1, keepdim=True) |
| scores = scores / max(float(temperature), 1e-5) |
| if int(top_k) > 0: |
| k = min(int(top_k), scores.shape[-1]) |
| cutoff = torch.topk(scores, k, dim=-1).values[:, -1:] |
| scores = scores.masked_fill(scores < cutoff, torch.finfo(scores.dtype).min) |
| return torch.multinomial(torch.softmax(scores.float(), dim=-1), 1) |
|
|
| @torch.inference_mode() |
| def generate_audio( |
| self, |
| input_ids, |
| attention_mask, |
| allowed_ids, |
| max_new_tokens=2048, |
| min_new_tokens=8, |
| temperature=0.8, |
| top_k=30, |
| do_sample=True, |
| ): |
| out = self( |
| input_ids=input_ids, |
| attention_mask=attention_mask, |
| use_cache=True, |
| output_hidden_states=True, |
| return_dict=True, |
| ) |
| emitted = input_ids |
| cache = out.past_key_values |
| scores = out.logits[:, -1, :] |
| hidden = out.hidden_states[-1][:, -1:, :] |
| mask = attention_mask |
| allowed_ids = allowed_ids.to(scores.device) |
| audio_end_id = int(self.config.audio_end_token_id) |
| for step in range(int(max_new_tokens)): |
| if step >= int(min_new_tokens): |
| stop = torch.sigmoid(self.stop_predictor(hidden).squeeze(-1)) |
| if bool((stop > 0.5).all()): |
| eos = input_ids.new_full((input_ids.shape[0], 1), audio_end_id) |
| return torch.cat((emitted, eos), dim=1) |
| restricted = torch.full_like(scores, torch.finfo(scores.dtype).min) |
| restricted.index_copy_(1, allowed_ids, scores.index_select(1, allowed_ids)) |
| if step < int(min_new_tokens): |
| restricted[:, audio_end_id] = torch.finfo(scores.dtype).min |
| token = self._sample(restricted, do_sample, temperature, top_k) |
| emitted = torch.cat((emitted, token), dim=1) |
| if bool((token == audio_end_id).all()): |
| break |
| mask = torch.cat((mask, torch.ones_like(token)), dim=1) |
| out = self( |
| input_ids=token, |
| attention_mask=mask, |
| past_key_values=cache, |
| use_cache=True, |
| output_hidden_states=True, |
| return_dict=True, |
| ) |
| cache = out.past_key_values |
| scores = out.logits[:, -1, :] |
| hidden = out.hidden_states[-1][:, -1:, :] |
| return emitted |
|
|