# modified from https://github.com/feng-yufei/shared_debugging_code/blob/main/model/t2s_model.py import torch from tqdm import tqdm from AR.models.utils import make_pad_mask from AR.models.utils import topk_sampling,sample,logits_to_probs,multinomial_sample_one_no_sync from AR.modules.embedding import SinePositionalEmbedding from AR.modules.embedding import TokenEmbedding from AR.modules.transformer import LayerNorm from AR.modules.transformer import TransformerEncoder from AR.modules.transformer import TransformerEncoderLayer from torch import nn from torch.nn import functional as F from torchmetrics.classification import MulticlassAccuracy default_config = { "embedding_dim": 512, "hidden_dim": 512, "num_head": 8, "num_layers": 12, "num_codebook": 8, "p_dropout": 0.0, "vocab_size": 1024 + 1, "phoneme_vocab_size": 512, "EOS": 1024 } class Text2SemanticDecoder(nn.Module): def __init__(self, config, norm_first=False, top_k=3): super(Text2SemanticDecoder, self).__init__() self.model_dim = config['model']["hidden_dim"] self.embedding_dim = config['model']["embedding_dim"] self.num_head = config['model']["head"] self.num_layers = config['model']["n_layer"] self.norm_first = norm_first self.vocab_size = config['model']["vocab_size"] self.phoneme_vocab_size = config['model']["phoneme_vocab_size"] self.p_dropout = config['model']["dropout"] self.EOS = config['model']["EOS"] self.norm_first = norm_first assert self.EOS == self.vocab_size - 1 # should be same as num of kmeans bin # assert self.EOS == 1024 self.bert_proj = nn.Linear(1024, self.embedding_dim) self.ar_text_embedding = TokenEmbedding( self.embedding_dim, self.phoneme_vocab_size, self.p_dropout) self.ar_text_position = SinePositionalEmbedding( self.embedding_dim, dropout=0.1, scale=False, alpha=True) self.ar_audio_embedding = TokenEmbedding( self.embedding_dim, self.vocab_size, self.p_dropout) self.ar_audio_position = SinePositionalEmbedding( self.embedding_dim, dropout=0.1, scale=False, alpha=True) self.h = TransformerEncoder( TransformerEncoderLayer( d_model=self.model_dim, nhead=self.num_head, dim_feedforward=self.model_dim * 4, dropout=0.1, batch_first=True, norm_first=norm_first, ), num_layers=self.num_layers, norm=LayerNorm(self.model_dim) if norm_first else None, ) self.ar_predict_layer = nn.Linear( self.model_dim, self.vocab_size, bias=False) self.loss_fct = nn.CrossEntropyLoss(reduction='sum') self.ar_accuracy_metric = MulticlassAccuracy( self.vocab_size, top_k=top_k, average="micro", multidim_average="global", ignore_index=self.EOS, ) def forward(self, x, x_lens, y, y_lens, bert_feature): ''' x: phoneme_ids y: semantic_ids ''' x = self.ar_text_embedding(x) x = x + self.bert_proj(bert_feature.transpose(1,2)) x = self.ar_text_position(x) x_mask = make_pad_mask(x_lens) y_mask = make_pad_mask(y_lens) y_mask_int = y_mask.type(torch.int64) codes = y.type(torch.int64) * (1 - y_mask_int) # Training # AR Decoder y, targets = self.pad_y_eos(codes, y_mask_int, eos_id=self.EOS) x_len = x_lens.max() y_len = y_lens.max() y_emb = self.ar_audio_embedding(y) y_pos = self.ar_audio_position(y_emb) xy_padding_mask = torch.concat([x_mask, y_mask], dim=1) ar_xy_padding_mask = xy_padding_mask x_attn_mask = F.pad( torch.zeros((x_len, x_len), dtype=torch.bool, device=x.device), (0, y_len), value=True, ) y_attn_mask = F.pad( torch.triu( torch.ones(y_len, y_len, dtype=torch.bool, device=x.device), diagonal=1, ), (x_len, 0), value=False, ) xy_attn_mask = torch.concat([x_attn_mask, y_attn_mask], dim=0) bsz, src_len = x.shape[0], x_len + y_len _xy_padding_mask = (ar_xy_padding_mask.view(bsz, 1, 1, src_len) .expand(-1, self.num_head, -1, -1) .reshape(bsz * self.num_head, 1, src_len)) xy_attn_mask = xy_attn_mask.logical_or(_xy_padding_mask) new_attn_mask = torch.zeros_like(xy_attn_mask, dtype=x.dtype) new_attn_mask.masked_fill_(xy_attn_mask, float("-inf")) xy_attn_mask = new_attn_mask # x 和完整的 y 一次性输入模型 xy_pos = torch.concat([x, y_pos], dim=1) xy_dec, _ = self.h( (xy_pos, None), mask=xy_attn_mask, ) logits = self.ar_predict_layer(xy_dec[:, x_len:]).permute(0, 2, 1) # loss # from feiteng: 每次 duration 越多, 梯度更新也应该更多, 所以用 sum loss = F.cross_entropy(logits, targets, reduction='sum') acc = self.ar_accuracy_metric(logits.detach(), targets).item() return loss, acc # 需要看下这个函数和 forward 的区别以及没有 semantic 的时候 prompts 输入什么 def infer(self, x, x_lens, prompts, bert_feature, top_k: int=-100, early_stop_num: int=-1, temperature: float=1.0): x = self.ar_text_embedding(x) x = x + self.bert_proj(bert_feature.transpose(1,2)) x = self.ar_text_position(x) # AR Decoder y = prompts prefix_len = y.shape[1] x_len = x.shape[1] x_attn_mask = torch.zeros((x_len, x_len), dtype=torch.bool) stop = False for _ in tqdm(range(1500)): y_emb = self.ar_audio_embedding(y) y_pos = self.ar_audio_position(y_emb) # x 和逐渐增长的 y 一起输入给模型 xy_pos = torch.concat([x, y_pos], dim=1) y_len = y.shape[1] x_attn_mask_pad = F.pad( x_attn_mask, (0, y_len), value=True, ) y_attn_mask = F.pad( torch.triu( torch.ones(y_len, y_len, dtype=torch.bool), diagonal=1), (x_len, 0), value=False, ) xy_attn_mask = torch.concat( [x_attn_mask_pad, y_attn_mask], dim=0).to(y.device) xy_dec, _ = self.h( (xy_pos, None), mask=xy_attn_mask, ) logits = self.ar_predict_layer(xy_dec[:, -1]) samples = topk_sampling( logits, top_k=top_k, top_p=1.0, temperature=temperature) if early_stop_num != -1 and (y.shape[1] - prefix_len ) > early_stop_num: print("use early stop num:", early_stop_num) stop = True if torch.argmax( logits, dim=-1)[0] == self.EOS or samples[0, 0] == self.EOS: # print(torch.argmax(logits, dim=-1)[0] == self.EOS, samples[0, 0] == self.EOS) stop = True if stop: if prompts.shape[1] == y.shape[1]: y = torch.concat([y, torch.zeros_like(samples)], dim=1) print('bad zero prediction') print(f"T2S Decoding EOS [{prefix_len} -> {y.shape[1]}]") break # 本次生成的 semantic_ids 和之前的 y 构成新的 y # print(samples.shape)#[1,1]#第一个1是bs # import os # os._exit(2333) y = torch.concat([y, samples], dim=1) return y def pad_y_eos(self, y, y_mask_int, eos_id): targets = F.pad( y, (0, 1), value=0) + eos_id * F.pad( y_mask_int, (0, 1), value=1) # 错位 return targets[:, :-1], targets[:, 1:] def infer_panel(self, x,#####全部文本token x_lens, prompts,####参考音频token bert_feature, top_k: int=-100, early_stop_num: int=-1, temperature: float=1.0): x = self.ar_text_embedding(x) x = x + self.bert_proj(bert_feature.transpose(1,2)) x = self.ar_text_position(x) # AR Decoder y = prompts prefix_len = y.shape[1] x_len = x.shape[1] x_attn_mask = torch.zeros((x_len, x_len), dtype=torch.bool) stop = False # print(1111111,self.num_layers) cache={ "all_stage":self.num_layers, "k":[None]*self.num_layers,###根据配置自己手写 "v":[None]*self.num_layers, # "xy_pos":None,##y_pos位置编码每次都不一样的没法缓存,每次都要重新拼xy_pos.主要还是写法原因,其实是可以历史统一一样的,但也没啥计算量就不管了 "y_emb":None,##只需要对最新的samples求emb,再拼历史的就行 # "logits":None,###原版就已经只对结尾求再拼接了,不用管 # "xy_dec":None,###不需要,本来只需要最后一个做logits "first_infer":1, "stage":0 } for idx in tqdm(range(1500)): if(cache["first_infer"]==1): y_emb = self.ar_audio_embedding(y) else: y_emb = torch.cat([cache["y_emb"],self.ar_audio_embedding(y[:,-1:])],1) cache["y_emb"]=y_emb y_pos = self.ar_audio_position(y_emb) # x 和逐渐增长的 y 一起输入给模型 if(cache["first_infer"]==1): xy_pos = torch.concat([x, y_pos], dim=1) else: xy_pos=y_pos[:,-1:] y_len = y_pos.shape[1] ###以下3个不做缓存 if (cache["first_infer"] == 1): x_attn_mask_pad = F.pad( x_attn_mask, (0, y_len),###xx的纯0扩展到xx纯0+xy纯1,(x,x+y) value=True, ) y_attn_mask = F.pad(###yy的右上1扩展到左边xy的0,(y,x+y) torch.triu( torch.ones(y_len, y_len, dtype=torch.bool), diagonal=1), (x_len, 0), value=False, ) xy_attn_mask = torch.concat( [x_attn_mask_pad, y_attn_mask], dim=0).to(y.device) else: ###最右边一列(是错的) # xy_attn_mask=torch.ones((1, x_len+y_len), dtype=torch.bool,device=xy_pos.device) # xy_attn_mask[:,-1]=False ###最下面一行(是对的) xy_attn_mask = torch.zeros((1, x_len + y_len), dtype=torch.bool, device=xy_pos.device) # pdb.set_trace() ###缓存重头戏 # print(1111,xy_pos.shape,xy_attn_mask.shape,x_len,y_len) xy_dec, _ = self.h( (xy_pos, None), mask=xy_attn_mask,cache=cache ) logits = self.ar_predict_layer(xy_dec[:, -1])##不用改,如果用了cache的默认就是只有一帧,取最后一帧一样的 # samples = topk_sampling(logits, top_k=top_k, top_p=1.0, temperature=temperature) samples = sample(logits[0], y, top_k=top_k, top_p=1.0, repetition_penalty=1.35)[0].unsqueeze(0) if early_stop_num != -1 and (y.shape[1] - prefix_len ) > early_stop_num: print("use early stop num:", early_stop_num) stop = True if torch.argmax( logits, dim=-1)[0] == self.EOS or samples[0, 0] == self.EOS: # print(torch.argmax(logits, dim=-1)[0] == self.EOS, samples[0, 0] == self.EOS) stop = True if stop: if prompts.shape[1] == y.shape[1]: y = torch.concat([y, torch.zeros_like(samples)], dim=1) print('bad zero prediction') print(f"T2S Decoding EOS [{prefix_len} -> {y.shape[1]}]") break # 本次生成的 semantic_ids 和之前的 y 构成新的 y # print(samples.shape)#[1,1]#第一个1是bs y = torch.concat([y, samples], dim=1) cache["first_infer"]=0 return y,idx