CoolFace
Apppublic

honey126/VoxAI

sourceHugging Facemitupdated 9mo agoView on Hugging Face
0likes
modules.py582 linesDownload Raw Back to model
1"""2ein notation:3b - batch4n - sequence5nt - text sequence6nw - raw wave length7d - dimension8"""9 10from __future__ import annotations11from typing import Optional12import math13 14import torch15from torch import nn16import torch.nn.functional as F17import torchaudio18 19from x_transformers.x_transformers import apply_rotary_pos_emb20 21 22# raw wav to mel spec23 24 25class MelSpec(nn.Module):26    def __init__(27        self,28        filter_length=1024,29        hop_length=256,30        win_length=1024,31        n_mel_channels=100,32        target_sample_rate=24_000,33        normalize=False,34        power=1,35        norm=None,36        center=True,37    ):38        super().__init__()39        self.n_mel_channels = n_mel_channels40 41        self.mel_stft = torchaudio.transforms.MelSpectrogram(42            sample_rate=target_sample_rate,43            n_fft=filter_length,44            win_length=win_length,45            hop_length=hop_length,46            n_mels=n_mel_channels,47            power=power,48            center=center,49            normalized=normalize,50            norm=norm,51        )52 53        self.register_buffer("dummy", torch.tensor(0), persistent=False)54 55    def forward(self, inp):56        if len(inp.shape) == 3:57            inp = inp.squeeze(1)  # 'b 1 nw -> b nw'58 59        assert len(inp.shape) == 260 61        if self.dummy.device != inp.device:62            self.to(inp.device)63 64        mel = self.mel_stft(inp)65        mel = mel.clamp(min=1e-5).log()66        return mel67 68 69# sinusoidal position embedding70 71 72class SinusPositionEmbedding(nn.Module):73    def __init__(self, dim):74        super().__init__()75        self.dim = dim76 77    def forward(self, x, scale=1000):78        device = x.device79        half_dim = self.dim // 280        emb = math.log(10000) / (half_dim - 1)81        emb = torch.exp(torch.arange(half_dim, device=device).float() * -emb)82        emb = scale * x.unsqueeze(1) * emb.unsqueeze(0)83        emb = torch.cat((emb.sin(), emb.cos()), dim=-1)84        return emb85 86 87# convolutional position embedding88 89 90class ConvPositionEmbedding(nn.Module):91    def __init__(self, dim, kernel_size=31, groups=16):92        super().__init__()93        assert kernel_size % 2 != 094        self.conv1d = nn.Sequential(95            nn.Conv1d(dim, dim, kernel_size, groups=groups, padding=kernel_size // 2),96            nn.Mish(),97            nn.Conv1d(dim, dim, kernel_size, groups=groups, padding=kernel_size // 2),98            nn.Mish(),99        )100 101    def forward(self, x: float["b n d"], mask: bool["b n"] | None = None):  # noqa: F722102        if mask is not None:103            mask = mask[..., None]104            x = x.masked_fill(~mask, 0.0)105 106        x = x.permute(0, 2, 1)107        x = self.conv1d(x)108        out = x.permute(0, 2, 1)109 110        if mask is not None:111            out = out.masked_fill(~mask, 0.0)112 113        return out114 115 116# rotary positional embedding related117 118 119def precompute_freqs_cis(dim: int, end: int, theta: float = 10000.0, theta_rescale_factor=1.0):120    # proposed by reddit user bloc97, to rescale rotary embeddings to longer sequence length without fine-tuning121    # has some connection to NTK literature122    # https://www.reddit.com/r/LocalLLaMA/comments/14lz7j5/ntkaware_scaled_rope_allows_llama_models_to_have/123    # https://github.com/lucidrains/rotary-embedding-torch/blob/main/rotary_embedding_torch/rotary_embedding_torch.py124    theta *= theta_rescale_factor ** (dim / (dim - 2))125    freqs = 1.0 / (theta ** (torch.arange(0, dim, 2)[: (dim // 2)].float() / dim))126    t = torch.arange(end, device=freqs.device)  # type: ignore127    freqs = torch.outer(t, freqs).float()  # type: ignore128    freqs_cos = torch.cos(freqs)  # real part129    freqs_sin = torch.sin(freqs)  # imaginary part130    return torch.cat([freqs_cos, freqs_sin], dim=-1)131 132 133def get_pos_embed_indices(start, length, max_pos, scale=1.0):134    # length = length if isinstance(length, int) else length.max()135    scale = scale * torch.ones_like(start, dtype=torch.float32)  # in case scale is a scalar136    pos = (137        start.unsqueeze(1)138        + (torch.arange(length, device=start.device, dtype=torch.float32).unsqueeze(0) * scale.unsqueeze(1)).long()139    )140    # avoid extra long error.141    pos = torch.where(pos < max_pos, pos, max_pos - 1)142    return pos143 144 145# Global Response Normalization layer (Instance Normalization ?)146 147 148class GRN(nn.Module):149    def __init__(self, dim):150        super().__init__()151        self.gamma = nn.Parameter(torch.zeros(1, 1, dim))152        self.beta = nn.Parameter(torch.zeros(1, 1, dim))153 154    def forward(self, x):155        Gx = torch.norm(x, p=2, dim=1, keepdim=True)156        Nx = Gx / (Gx.mean(dim=-1, keepdim=True) + 1e-6)157        return self.gamma * (x * Nx) + self.beta + x158 159 160# ConvNeXt-V2 Block https://github.com/facebookresearch/ConvNeXt-V2/blob/main/models/convnextv2.py161# ref: https://github.com/bfs18/e2_tts/blob/main/rfwave/modules.py#L108162 163 164class ConvNeXtV2Block(nn.Module):165    def __init__(166        self,167        dim: int,168        intermediate_dim: int,169        dilation: int = 1,170    ):171        super().__init__()172        padding = (dilation * (7 - 1)) // 2173        self.dwconv = nn.Conv1d(174            dim, dim, kernel_size=7, padding=padding, groups=dim, dilation=dilation175        )  # depthwise conv176        self.norm = nn.LayerNorm(dim, eps=1e-6)177        self.pwconv1 = nn.Linear(dim, intermediate_dim)  # pointwise/1x1 convs, implemented with linear layers178        self.act = nn.GELU()179        self.grn = GRN(intermediate_dim)180        self.pwconv2 = nn.Linear(intermediate_dim, dim)181 182    def forward(self, x: torch.Tensor) -> torch.Tensor:183        residual = x184        x = x.transpose(1, 2)  # b n d -> b d n185        x = self.dwconv(x)186        x = x.transpose(1, 2)  # b d n -> b n d187        x = self.norm(x)188        x = self.pwconv1(x)189        x = self.act(x)190        x = self.grn(x)191        x = self.pwconv2(x)192        return residual + x193 194 195# AdaLayerNormZero196# return with modulated x for attn input, and params for later mlp modulation197 198 199class AdaLayerNormZero(nn.Module):200    def __init__(self, dim):201        super().__init__()202 203        self.silu = nn.SiLU()204        self.linear = nn.Linear(dim, dim * 6)205 206        self.norm = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)207 208    def forward(self, x, emb=None):209        emb = self.linear(self.silu(emb))210        shift_msa, scale_msa, gate_msa, shift_mlp, scale_mlp, gate_mlp = torch.chunk(emb, 6, dim=1)211 212        x = self.norm(x) * (1 + scale_msa[:, None]) + shift_msa[:, None]213        return x, gate_msa, shift_mlp, scale_mlp, gate_mlp214 215 216# AdaLayerNormZero for final layer217# return only with modulated x for attn input, cuz no more mlp modulation218 219 220class AdaLayerNormZero_Final(nn.Module):221    def __init__(self, dim):222        super().__init__()223 224        self.silu = nn.SiLU()225        self.linear = nn.Linear(dim, dim * 2)226 227        self.norm = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)228 229    def forward(self, x, emb):230        emb = self.linear(self.silu(emb))231        scale, shift = torch.chunk(emb, 2, dim=1)232 233        x = self.norm(x) * (1 + scale)[:, None, :] + shift[:, None, :]234        return x235 236 237# FeedForward238 239 240class FeedForward(nn.Module):241    def __init__(self, dim, dim_out=None, mult=4, dropout=0.0, approximate: str = "none"):242        super().__init__()243        inner_dim = int(dim * mult)244        dim_out = dim_out if dim_out is not None else dim245 246        activation = nn.GELU(approximate=approximate)247        project_in = nn.Sequential(nn.Linear(dim, inner_dim), activation)248        self.ff = nn.Sequential(project_in, nn.Dropout(dropout), nn.Linear(inner_dim, dim_out))249 250    def forward(self, x):251        return self.ff(x)252 253 254# Attention with possible joint part255# modified from diffusers/src/diffusers/models/attention_processor.py256 257 258class Attention(nn.Module):259    def __init__(260        self,261        processor: JointAttnProcessor | AttnProcessor,262        dim: int,263        heads: int = 8,264        dim_head: int = 64,265        dropout: float = 0.0,266        context_dim: Optional[int] = None,  # if not None -> joint attention267        context_pre_only=None,268    ):269        super().__init__()270 271        if not hasattr(F, "scaled_dot_product_attention"):272            raise ImportError("Attention equires PyTorch 2.0, to use it, please upgrade PyTorch to 2.0.")273 274        self.processor = processor275 276        self.dim = dim277        self.heads = heads278        self.inner_dim = dim_head * heads279        self.dropout = dropout280 281        self.context_dim = context_dim282        self.context_pre_only = context_pre_only283 284        self.to_q = nn.Linear(dim, self.inner_dim)285        self.to_k = nn.Linear(dim, self.inner_dim)286        self.to_v = nn.Linear(dim, self.inner_dim)287 288        if self.context_dim is not None:289            self.to_k_c = nn.Linear(context_dim, self.inner_dim)290            self.to_v_c = nn.Linear(context_dim, self.inner_dim)291            if self.context_pre_only is not None:292                self.to_q_c = nn.Linear(context_dim, self.inner_dim)293 294        self.to_out = nn.ModuleList([])295        self.to_out.append(nn.Linear(self.inner_dim, dim))296        self.to_out.append(nn.Dropout(dropout))297 298        if self.context_pre_only is not None and not self.context_pre_only:299            self.to_out_c = nn.Linear(self.inner_dim, dim)300 301    def forward(302        self,303        x: float["b n d"],  # noised input x  # noqa: F722304        c: float["b n d"] = None,  # context c  # noqa: F722305        mask: bool["b n"] | None = None,  # noqa: F722306        rope=None,  # rotary position embedding for x307        c_rope=None,  # rotary position embedding for c308    ) -> torch.Tensor:309        if c is not None:310            return self.processor(self, x, c=c, mask=mask, rope=rope, c_rope=c_rope)311        else:312            return self.processor(self, x, mask=mask, rope=rope)313 314 315# Attention processor316 317 318class AttnProcessor:319    def __init__(self):320        pass321 322    def __call__(323        self,324        attn: Attention,325        x: float["b n d"],  # noised input x  # noqa: F722326        mask: bool["b n"] | None = None,  # noqa: F722327        rope=None,  # rotary position embedding328    ) -> torch.FloatTensor:329        batch_size = x.shape[0]330 331        # `sample` projections.332        query = attn.to_q(x)333        key = attn.to_k(x)334        value = attn.to_v(x)335 336        # apply rotary position embedding337        if rope is not None:338            freqs, xpos_scale = rope339            q_xpos_scale, k_xpos_scale = (xpos_scale, xpos_scale**-1.0) if xpos_scale is not None else (1.0, 1.0)340 341            query = apply_rotary_pos_emb(query, freqs, q_xpos_scale)342            key = apply_rotary_pos_emb(key, freqs, k_xpos_scale)343 344        # attention345        inner_dim = key.shape[-1]346        head_dim = inner_dim // attn.heads347        query = query.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2)348        key = key.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2)349        value = value.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2)350 351        # mask. e.g. inference got a batch with different target durations, mask out the padding352        if mask is not None:353            attn_mask = mask354            attn_mask = attn_mask.unsqueeze(1).unsqueeze(1)  # 'b n -> b 1 1 n'355            attn_mask = attn_mask.expand(batch_size, attn.heads, query.shape[-2], key.shape[-2])356        else:357            attn_mask = None358 359        x = F.scaled_dot_product_attention(query, key, value, attn_mask=attn_mask, dropout_p=0.0, is_causal=False)360        x = x.transpose(1, 2).reshape(batch_size, -1, attn.heads * head_dim)361        x = x.to(query.dtype)362 363        # linear proj364        x = attn.to_out[0](x)365        # dropout366        x = attn.to_out[1](x)367 368        if mask is not None:369            mask = mask.unsqueeze(-1)370            x = x.masked_fill(~mask, 0.0)371 372        return x373 374 375# Joint Attention processor for MM-DiT376# modified from diffusers/src/diffusers/models/attention_processor.py377 378 379class JointAttnProcessor:380    def __init__(self):381        pass382 383    def __call__(384        self,385        attn: Attention,386        x: float["b n d"],  # noised input x  # noqa: F722387        c: float["b nt d"] = None,  # context c, here text # noqa: F722388        mask: bool["b n"] | None = None,  # noqa: F722389        rope=None,  # rotary position embedding for x390        c_rope=None,  # rotary position embedding for c391    ) -> torch.FloatTensor:392        residual = x393 394        batch_size = c.shape[0]395 396        # `sample` projections.397        query = attn.to_q(x)398        key = attn.to_k(x)399        value = attn.to_v(x)400 401        # `context` projections.402        c_query = attn.to_q_c(c)403        c_key = attn.to_k_c(c)404        c_value = attn.to_v_c(c)405 406        # apply rope for context and noised input independently407        if rope is not None:408            freqs, xpos_scale = rope409            q_xpos_scale, k_xpos_scale = (xpos_scale, xpos_scale**-1.0) if xpos_scale is not None else (1.0, 1.0)410            query = apply_rotary_pos_emb(query, freqs, q_xpos_scale)411            key = apply_rotary_pos_emb(key, freqs, k_xpos_scale)412        if c_rope is not None:413            freqs, xpos_scale = c_rope414            q_xpos_scale, k_xpos_scale = (xpos_scale, xpos_scale**-1.0) if xpos_scale is not None else (1.0, 1.0)415            c_query = apply_rotary_pos_emb(c_query, freqs, q_xpos_scale)416            c_key = apply_rotary_pos_emb(c_key, freqs, k_xpos_scale)417 418        # attention419        query = torch.cat([query, c_query], dim=1)420        key = torch.cat([key, c_key], dim=1)421        value = torch.cat([value, c_value], dim=1)422 423        inner_dim = key.shape[-1]424        head_dim = inner_dim // attn.heads425        query = query.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2)426        key = key.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2)427        value = value.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2)428 429        # mask. e.g. inference got a batch with different target durations, mask out the padding430        if mask is not None:431            attn_mask = F.pad(mask, (0, c.shape[1]), value=True)  # no mask for c (text)432            attn_mask = attn_mask.unsqueeze(1).unsqueeze(1)  # 'b n -> b 1 1 n'433            attn_mask = attn_mask.expand(batch_size, attn.heads, query.shape[-2], key.shape[-2])434        else:435            attn_mask = None436 437        x = F.scaled_dot_product_attention(query, key, value, attn_mask=attn_mask, dropout_p=0.0, is_causal=False)438        x = x.transpose(1, 2).reshape(batch_size, -1, attn.heads * head_dim)439        x = x.to(query.dtype)440 441        # Split the attention outputs.442        x, c = (443            x[:, : residual.shape[1]],444            x[:, residual.shape[1] :],445        )446 447        # linear proj448        x = attn.to_out[0](x)449        # dropout450        x = attn.to_out[1](x)451        if not attn.context_pre_only:452            c = attn.to_out_c(c)453 454        if mask is not None:455            mask = mask.unsqueeze(-1)456            x = x.masked_fill(~mask, 0.0)457            # c = c.masked_fill(~mask, 0.)  # no mask for c (text)458 459        return x, c460 461 462# DiT Block463 464 465class DiTBlock(nn.Module):466    def __init__(self, dim, heads, dim_head, ff_mult=4, dropout=0.1):467        super().__init__()468 469        self.attn_norm = AdaLayerNormZero(dim)470        self.attn = Attention(471            processor=AttnProcessor(),472            dim=dim,473            heads=heads,474            dim_head=dim_head,475            dropout=dropout,476        )477 478        self.ff_norm = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)479        self.ff = FeedForward(dim=dim, mult=ff_mult, dropout=dropout, approximate="tanh")480 481    def forward(self, x, t, mask=None, rope=None):  # x: noised input, t: time embedding482        # pre-norm & modulation for attention input483        norm, gate_msa, shift_mlp, scale_mlp, gate_mlp = self.attn_norm(x, emb=t)484 485        # attention486        attn_output = self.attn(x=norm, mask=mask, rope=rope)487 488        # process attention output for input x489        x = x + gate_msa.unsqueeze(1) * attn_output490 491        norm = self.ff_norm(x) * (1 + scale_mlp[:, None]) + shift_mlp[:, None]492        ff_output = self.ff(norm)493        x = x + gate_mlp.unsqueeze(1) * ff_output494 495        return x496 497 498# MMDiT Block https://arxiv.org/abs/2403.03206499 500 501class MMDiTBlock(nn.Module):502    r"""503    modified from diffusers/src/diffusers/models/attention.py504 505    notes.506    _c: context related. text, cond, etc. (left part in sd3 fig2.b)507    _x: noised input related. (right part)508    context_pre_only: last layer only do prenorm + modulation cuz no more ffn509    """510 511    def __init__(self, dim, heads, dim_head, ff_mult=4, dropout=0.1, context_pre_only=False):512        super().__init__()513 514        self.context_pre_only = context_pre_only515 516        self.attn_norm_c = AdaLayerNormZero_Final(dim) if context_pre_only else AdaLayerNormZero(dim)517        self.attn_norm_x = AdaLayerNormZero(dim)518        self.attn = Attention(519            processor=JointAttnProcessor(),520            dim=dim,521            heads=heads,522            dim_head=dim_head,523            dropout=dropout,524            context_dim=dim,525            context_pre_only=context_pre_only,526        )527 528        if not context_pre_only:529            self.ff_norm_c = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)530            self.ff_c = FeedForward(dim=dim, mult=ff_mult, dropout=dropout, approximate="tanh")531        else:532            self.ff_norm_c = None533            self.ff_c = None534        self.ff_norm_x = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)535        self.ff_x = FeedForward(dim=dim, mult=ff_mult, dropout=dropout, approximate="tanh")536 537    def forward(self, x, c, t, mask=None, rope=None, c_rope=None):  # x: noised input, c: context, t: time embedding538        # pre-norm & modulation for attention input539        if self.context_pre_only:540            norm_c = self.attn_norm_c(c, t)541        else:542            norm_c, c_gate_msa, c_shift_mlp, c_scale_mlp, c_gate_mlp = self.attn_norm_c(c, emb=t)543        norm_x, x_gate_msa, x_shift_mlp, x_scale_mlp, x_gate_mlp = self.attn_norm_x(x, emb=t)544 545        # attention546        x_attn_output, c_attn_output = self.attn(x=norm_x, c=norm_c, mask=mask, rope=rope, c_rope=c_rope)547 548        # process attention output for context c549        if self.context_pre_only:550            c = None551        else:  # if not last layer552            c = c + c_gate_msa.unsqueeze(1) * c_attn_output553 554            norm_c = self.ff_norm_c(c) * (1 + c_scale_mlp[:, None]) + c_shift_mlp[:, None]555            c_ff_output = self.ff_c(norm_c)556            c = c + c_gate_mlp.unsqueeze(1) * c_ff_output557 558        # process attention output for input x559        x = x + x_gate_msa.unsqueeze(1) * x_attn_output560 561        norm_x = self.ff_norm_x(x) * (1 + x_scale_mlp[:, None]) + x_shift_mlp[:, None]562        x_ff_output = self.ff_x(norm_x)563        x = x + x_gate_mlp.unsqueeze(1) * x_ff_output564 565        return c, x566 567 568# time step conditioning embedding569 570 571class TimestepEmbedding(nn.Module):572    def __init__(self, dim, freq_embed_dim=256):573        super().__init__()574        self.time_embed = SinusPositionEmbedding(freq_embed_dim)575        self.time_mlp = nn.Sequential(nn.Linear(freq_embed_dim, dim), nn.SiLU(), nn.Linear(dim, dim))576 577    def forward(self, timestep: float["b"]):  # noqa: F821578        time_hidden = self.time_embed(timestep)579        time_hidden = time_hidden.to(timestep.dtype)580        time = self.time_mlp(time_hidden)  # b d581        return time582