CoolFace
Modelpublic

CAMB-AI/MARS5-TTS

sourceHugging Faceagpl-3.0updated 2y agoView on Hugging Face
480likes76downloads
model.py345 linesDownload Raw Back to mars5
1import math2from typing import Optional3 4import torch5import torch.nn as nn6import torch.nn.functional as F7from torch import Tensor8 9from .nn_future import (FNNSwiGLU, MistralTransformer, ModelArgs,10                        RotatingBufferCache, SinePositionalEmbedding)11from .utils import construct_padding_mask, length_to_mask12 13LAYERNORM_EPS = 4e-514 15# ------------------------16# Code adapted from OpenAI guided diffusion repo17 18def timestep_embedding(timesteps, dim, max_period=10000, dtype=torch.float32):19    """20    Create sinusoidal timestep embeddings.21    :param timesteps: a 1-D Tensor of N indices, one per batch element.22                      These may be fractional.23    :param dim: the dimension of the output.24    :param max_period: controls the minimum frequency of the embeddings.25    :return: an [N x dim] Tensor of positional embeddings.26    """27    half = dim // 228    freqs = torch.exp(29        -math.log(max_period) * torch.arange(start=0, end=half) / half30    ).to(device=timesteps.device)31    args = timesteps[:, None].float() * freqs[None]32    embedding = torch.cat([torch.cos(args), torch.sin(args)], dim=-1).to(dtype)33    if dim % 2:34        embedding = torch.cat([embedding, torch.zeros_like(embedding[:, :1])], dim=-1)35    return embedding36 37 38# --------------------------------39# autoregressive codec language model40 41 42class CodecLM(nn.Module):43 44    def __init__(self, n_vocab, dim=1536, nhead=24, n_layers=26, n_spk_layers=2, dim_ff_scale=None, sliding_window=3000) -> None:45        super().__init__()46 47        if dim_ff_scale is None: hidden_dim = int(dim*4*(3/4))48        else: hidden_dim = int(dim*dim_ff_scale)49 50        self.cfg = ModelArgs(n_vocab, dim=dim, n_layers=n_layers, n_heads=nhead, n_kv_heads=nhead, hidden_dim=hidden_dim, sliding_window=sliding_window)51        self.ar = MistralTransformer(self.cfg)52 53        self.embed = nn.Embedding(n_vocab, dim)54 55        # --- spk embedding network56        dim_ff = int(dim*4*(3/4))57        self.pos_embedding = SinePositionalEmbedding(dim, scale=False, alpha=True)58        self.ref_chunked_emb = ChunkedEmbedding(1024 + 1, 8, dim) # add 1 for pad idx59        self.spk_identity_emb = nn.Embedding(1, dim)60        # define custom decoder61        encoder_layer = nn.TransformerEncoderLayer(dim, nhead, dim_ff,62                                                activation=FNNSwiGLU(dim, dim_ff), dropout=0,63                                                batch_first=True, norm_first=True, layer_norm_eps=LAYERNORM_EPS)64        encoder_layer.linear1 = nn.Identity()65        self.spk_encoder = nn.TransformerEncoder(encoder_layer, n_spk_layers, norm=nn.LayerNorm(dim, eps=LAYERNORM_EPS))66        # monkeypatch for broken copy.deepcopy of nn.Modules in nn.TransformerDecoder67        for l in self.spk_encoder.layers: l.activation = FNNSwiGLU(dim, dim_ff)68 69 70    @torch.inference_mode71    def get_spk_embedding(self, spk_reference, c_codes_lengths=None) -> Tensor:72        """ Gets speaker reference embeddings using `spk_reference` codes of shape (bs, seq_len, n_codebooks). """73        bs = spk_reference.shape[0]74        if bs != 1:75            raise AssertionError(f"Speaker embedding extraction only implemented using for bs=1 currently.")76        spk_seq = self.ref_chunked_emb(spk_reference) # (bs, sl, dim)77        spk_ref_emb = self.spk_identity_emb.weight[None].expand(bs, -1, -1) # (bs, 1, dim)78 79        spk_seq = torch.cat([spk_ref_emb, spk_seq], dim=1) # (bs, 1+sl, dim)80        # add pos encoding81        spk_seq = self.pos_embedding(spk_seq)82        # codebook goes from indices 0->1023, padding is idx 1024 (the 1025th entry)83        src_key_padding_mask = construct_padding_mask(spk_reference[:, :, 0], 1024) 84        src_key_padding_mask = torch.cat((85                                            # append a zero here since we DO want to attend to initial position.86                                            torch.zeros(src_key_padding_mask.shape[0], 1, dtype=bool, device=src_key_padding_mask.device), 87                                            src_key_padding_mask88                                            ), 89                                            dim=1)90        # pass through transformer91        res = self.spk_encoder(spk_seq, is_causal=False, src_key_padding_mask=src_key_padding_mask)[:, :1] # select first element -> now (bs, 1, dim).92        return res.squeeze(1)93 94 95    def forward(self, x: Tensor, x_padding_mask: Optional[Tensor] = None, spk_reference: Optional[Tensor] = None,96                cache: Optional[RotatingBufferCache] = None, counter: int = 0) -> Tensor:97        """ Inputs:98            - `x`: (bs, seq_len, vocab_size) 99            - `x_padding_mask`: (bs, seq_len) mask for each input, True for positions to *ignore*, False otherwise.100                Note that since this is an autoregressive model, this doesn't actually matter for infernece, so it is ignored at inference. 101            - `spk_reference`: (bs, seq_len, n_codebooks) corresponding to the speaker reference to clone from.102            - `cache` and `counter`: used for kv caching, optional.103 104            Returns `x` of same shape (bs, seq_len, dim)105        """106        x = self.embed(x)107 108        # --- speaker reference/embedding109        if spk_reference is not None:110            # compute ref111            bs = spk_reference.shape[0]112            spk_seq = self.ref_chunked_emb(spk_reference) # (bs, sl, dim)113            spk_ref_emb = self.spk_identity_emb.weight[None].expand(bs, -1, -1) # (bs, 1, dim)114 115            spk_seq = torch.cat([spk_ref_emb, spk_seq], dim=1) # (bs, 1+sl, dim)116            # add pos encoding117            spk_seq = self.pos_embedding(spk_seq)118            # codebook goes from indices 0->1023, padding is idx 1024 (the 1025th entry)119            src_key_padding_mask = construct_padding_mask(spk_reference[:, :, 0], 1024) 120            src_key_padding_mask = torch.cat((121                                                # append a zero here since we DO want to attend to initial position.122                                                torch.zeros(src_key_padding_mask.shape[0], 1, dtype=bool, device=src_key_padding_mask.device), 123                                                src_key_padding_mask124                                             ), 125                                             dim=1)126            # pass through transformer127            res = self.spk_encoder(spk_seq, is_causal=False, src_key_padding_mask=src_key_padding_mask)[:, :1] # select first element -> now (bs, 1, dim).128            129            x = torch.cat([res, x], dim=1)130 131        positions = torch.arange(0, x.shape[1], device=x.device, dtype=torch.long)132        if cache is not None and counter != 1:133            # using only the last token to predict the next one134            x = x[:,-1,:].unsqueeze(1)135            positions = positions[-1:]136 137        x = self.ar(x, positions, cache) # (bs, seq_len, vocab)138        if spk_reference is not None and (cache is None or counter == 1):139            x = x[:, 1:] # strip out the first output token corresponding to the speaker embedding token.140 141        return x142 143 144# -------------------------145# residual discrete diffusion model146 147class ChunkedEmbedding(nn.Module):148 149    def __init__(self, codebook_size: int, n_quantizer: int, dim: int) -> None:150        super().__init__()151        assert dim % n_quantizer == 0, f"ChunkedEmbedding output dim ({dim}) must be divisible by n_quant {n_quantizer}"152        self.embs = nn.ModuleList([nn.Embedding(codebook_size, dim//n_quantizer) for _ in range(n_quantizer)])153 154    def forward(self, x: Tensor) -> Tensor:155        """ Embeds each codebook index in `x` (bs, seq_len, n_quantizer) to an embedding vector, concatenating results.156        Returns output of shape (bs, seq_len, dim)157        """158        y = torch.cat([self.embs[i](x[..., i]) for i in range(x.shape[-1])], dim=-1)159        return y160 161 162 163class ResidualTransformer(nn.Module):164 165    def __init__(self, n_text_vocab, n_quant=1024, dim=1024, nhead=16, 166                 enc_layers=8, dec_layers=16, n_spk_layers=3,167                 c_quant_levels=8, pred_quant_levels=8, 168                 t_emb_dim=1024, norm_first=True, p_cond_drop=0.1, dropout=0) -> None:169        super().__init__()170 171        self.cond_pos_embedding = SinePositionalEmbedding(dim, scale=False, alpha=True)172        self.pos_embedding = SinePositionalEmbedding(dim, scale=False, alpha=True)173 174        # *4 from heuristic, *2/3 from swiglu, since there are 3 linear matrices not 2.175        # so we must keep # params the same.176        dim_ff = int(dim*4*(3/4))177 178        # define custom encoder179        encoder_layer = nn.TransformerEncoderLayer(dim, nhead, dim_ff,180                            activation=FNNSwiGLU(dim, dim_ff), dropout=dropout,181                            batch_first=True, norm_first=norm_first, layer_norm_eps=LAYERNORM_EPS)182        encoder_layer.linear1 = nn.Identity()183        encoder = nn.TransformerEncoder(encoder_layer, enc_layers, norm=nn.LayerNorm(dim, eps=LAYERNORM_EPS) if norm_first else None)184 185        # define custom decoder186        decoder_layer = nn.TransformerDecoderLayer(dim, nhead, dim_ff,187                                                activation=FNNSwiGLU(dim, dim_ff), dropout=dropout,188                                                batch_first=True, norm_first=norm_first, layer_norm_eps=LAYERNORM_EPS)189        decoder_layer.linear1 = nn.Identity()190        decoder = nn.TransformerDecoder(decoder_layer, dec_layers, norm=nn.LayerNorm(dim, eps=LAYERNORM_EPS) if norm_first else None)191 192        # monkeypatch for broken copy.deepcopy of nn.Modules in nn.TransformerDecoder193        for l in decoder.layers: l.activation = FNNSwiGLU(dim, dim_ff)194 195        self.tfm = nn.Transformer(dim, nhead, dim_feedforward=dim_ff, batch_first=True, 196            norm_first=norm_first,197            num_encoder_layers=enc_layers,198            num_decoder_layers=dec_layers,199            custom_encoder=encoder,200            custom_decoder=decoder,201            layer_norm_eps=LAYERNORM_EPS,202            dropout=dropout203        )204        # Timestep embedding network205        self.t_emb_dim = t_emb_dim206        self.timestep_encoder_emb = nn.Sequential(207            nn.Linear(t_emb_dim, dim),208            nn.SiLU(),209            nn.Linear(dim, dim)210        )211        self.timestep_decoder_emb = nn.Sequential(212            nn.Linear(t_emb_dim, dim),213            nn.SiLU(),214            nn.Linear(dim, dim)215        )216 217        self.text_embed = nn.Embedding(n_text_vocab, dim)218 219        ## ----> reference / conditioning encoder:220        self.ref_embedder = ChunkedEmbedding(n_quant, c_quant_levels, dim)221        self.ref_pos_embedding = SinePositionalEmbedding(dim, scale=False, alpha=True)222        self.spk_identity_emb = nn.Embedding(1, dim)223        spk_encoder_layer = nn.TransformerEncoderLayer(dim, nhead, dim_ff,224                                                activation=FNNSwiGLU(dim, dim_ff), dropout=dropout,225                                                batch_first=True, norm_first=True, layer_norm_eps=LAYERNORM_EPS)226        spk_encoder_layer.linear1 = nn.Identity()227        self.spk_encoder = nn.TransformerEncoder(spk_encoder_layer, n_spk_layers, norm=nn.LayerNorm(dim, eps=LAYERNORM_EPS))228        # monkeypatch for broken copy.deepcopy of nn.Modules in nn.TransformerDecoder229        for l in self.spk_encoder.layers: l.activation = FNNSwiGLU(dim, dim_ff)230        # ----> end speaker encoder network231 232        # self.residual_encoder = nn.Embedding(n_quant, dim) # only encode first quantization level of decoder input.233        self.residual_encoder = ChunkedEmbedding(n_quant, c_quant_levels, dim)234 235        self.residual_decoder = nn.ModuleList([236            nn.Sequential(237                nn.LayerNorm(dim),238                nn.Linear(dim, n_quant)239            ) for i in range(pred_quant_levels)240        ])241        self.n_quantizer = pred_quant_levels242        self.p_cond_drop = p_cond_drop243 244 245    @torch.inference_mode246    def get_spk_embedding(self, c_codes, c_codes_length) -> Tensor:247        """ Obtain speaker embedding vectors using `c_codes` from reference encodec sequences, and `c_codes_length` of lengths for each sequence """248        bs = c_codes.shape[0]249        spk_seq = self.ref_embedder(c_codes) # (bs, sl, dim)250        spk_ref_emb = self.spk_identity_emb.weight[None].expand(bs, -1, -1) # (bs, 1, dim)251        spk_seq = torch.cat([spk_ref_emb, spk_seq], dim=1) # (bs, 1+sl, dim)252        # add pos encoding253        spk_seq = self.ref_pos_embedding(spk_seq)254 255        # add 1 to c_codes_length to account for the fact that we concatenate the spk_ref_emb to it. 256        src_key_padding_mask = length_to_mask(c_codes_length+1, torch.zeros_like(c_codes_length), max_len=spk_seq.shape[1])257        src_key_padding_mask = src_key_padding_mask.to(dtype=torch.bool, device=spk_seq.device)258 259        # pass through transformer260        res = self.spk_encoder(spk_seq, is_causal=False, src_key_padding_mask=src_key_padding_mask)[:, :1] # select first element -> now (bs, 1, dim).261        return res.squeeze(1)262 263 264    def forward(self, c_text: Tensor, c_codes: Tensor, c_texts_length: Tensor, c_codes_length: Tensor, 265                x: Tensor, x_padding_mask: Tensor, t: Tensor, drop_cond=False):266        """ Input:267            - `c_text`: (bs, seq_len1) the prompt text (BPE encoded)268            - `c_codes`: (bs, seq_len2, n_quant) the full tokenized codes of the reference speech269            - `c_texts_length`: (bs, ) the length of the codes in the text prompt270            - `c_codes_length`: (bs, ) the length of the prompt acoustic token codes in `c_codes`.271            - `x`: (bs, seq_len3) L0 residual codes272            - `x`: (bs, seq_len3, n_quant) L0 residual codes273            - `x_padding_mask`: (bs, seq_len3) masking for residual codes274            - `t`: (bs) timestep275            - `drop_cond`: bool, whether or not to forcibly drop the conditioning information.276        Returns:277            - outs: (bs, seq_len, n_quantizer, codebook_size)278        """279        280        c_text = self.text_embed(c_text) # (bs, seq_len1, dim)281 282        ## ----> reference / conditioning encoder:283        bs = c_codes.shape[0]284 285        286        if self.training:287            zero_cond_inds = torch.rand_like(t, dtype=c_text.dtype) < self.p_cond_drop288        else:289            # never randomly zero when in eval mode290            zero_cond_inds = torch.zeros_like(t, dtype=torch.bool)291            if drop_cond:292                # force drop conditioning293                zero_cond_inds = torch.ones_like(t, dtype=torch.bool)294        295        c_codes_length[zero_cond_inds] = 0296        c_codes[zero_cond_inds] = 1024297 298        spk_seq = self.ref_embedder(c_codes) # (bs, sl, dim)299        spk_ref_emb = self.spk_identity_emb.weight[None].expand(bs, -1, -1) # (bs, 1, dim)300        spk_seq = torch.cat([spk_ref_emb, spk_seq], dim=1) # (bs, 1+sl, dim)301        # add pos encoding302        spk_seq = self.ref_pos_embedding(spk_seq)303 304        # add 1 to c_codes_length to account for the fact that we concatenate the spk_ref_emb to it. 305        src_key_padding_mask = length_to_mask(c_codes_length+1, torch.zeros_like(c_codes_length), max_len=spk_seq.shape[1])306        src_key_padding_mask = src_key_padding_mask.to(dtype=torch.bool, device=spk_seq.device)307 308        # pass through transformer309        res = self.spk_encoder(spk_seq, is_causal=False, src_key_padding_mask=src_key_padding_mask)[:, :1] # select first element -> now (bs, 1, dim).310        c_codes = res # (bs, 1, dim)311        c_codes_lengths_extract = torch.ones_like(c_codes_length) # manually override all the code lengths to equal 1, since we only have 1 spk embedding. 312        ## ----> end reference / conditioning encoder:313 314        ## ----> timestep embeddings and parsing315        t_emb = timestep_embedding(t, self.t_emb_dim, dtype=c_text.dtype)316        t_emb_encoder = self.timestep_encoder_emb(t_emb) # (bs, t_dim)317        t_emb_decoder = self.timestep_decoder_emb(t_emb)318        319        ## ----> concatenating text/phone inputs and implicit speaker embedding. 320        c_phones_unpacked = nn.utils.rnn.unpad_sequence(c_text, c_texts_length.cpu(), batch_first=True)321        c_codes_unpacked = nn.utils.rnn.unpad_sequence(c_codes, c_codes_lengths_extract.cpu(), batch_first=True)322        # >>> Concat [speaker codes, text codes]323        assert all(b.shape[0] == 1 for b in c_codes_unpacked)324        c_joined = [torch.cat((b, a), dim=0) for a, b in zip(c_phones_unpacked, c_codes_unpacked)]325 326        c = nn.utils.rnn.pad_sequence(c_joined, batch_first=True)327        c_joined_lengths = torch.tensor([p.shape[0] for p in c_joined], device=c.device, dtype=torch.long)328        c_padding_mask = length_to_mask(c_joined_lengths, torch.zeros_like(c_joined_lengths))329        c = self.cond_pos_embedding(c)330 331        ## Format input:332        x = self.residual_encoder(x) # (bs, seq_len3, dim)333 334        x = self.pos_embedding(x)335 336        x = x + t_emb_decoder[:, None]337        c = c + t_emb_encoder[:, None]338        ## Perform prediction:339        output = self.tfm(c, x, src_key_padding_mask=c_padding_mask, 340                          tgt_key_padding_mask=x_padding_mask,341                          memory_key_padding_mask=c_padding_mask) # (bs, seq_len, dim)342        outs = torch.stack([self.residual_decoder[i](output) for i in range(self.n_quantizer)], dim=-1) # (bs, seq_len, logit_dim, n_quant)343        return outs344 345