Spaces:
Running on Zero
Running on Zero
| """Reference voice compressor: Q-Former-style bottleneck that turns a | |
| variable-length stack of codec codes into K learnable "speaker" tokens consumed | |
| by the decoder as a prefix. | |
| Architecture: | |
| Input pipeline: | |
| packed_or_unfolded [B, T_ref, C_in] | |
| βββ (optional) unfold_tokens β [B, T_ref, C_total] if dataset is packed | |
| βββ dequantize_codes β [B, T_ref, C_total] float in [-1, 1] | |
| βββ Linear(C_total β d_model)β [B, T_ref, d_model] | |
| βββ + sinusoidal PE β ref_feats [B, T_ref, d_model] | |
| Queries: | |
| nn.Parameter(K, d_model), batch-expanded to [B, K, d_model] | |
| For each of L Q-Former blocks (pre-norm RMSNorm + SwiGLU FFN): | |
| q = q + SelfAttn(RMSNorm(q)) # bidirectional | |
| q = q + CrossAttn(RMSNorm(q), kv=ref_feats, | |
| key_padding_mask=ref_mask) | |
| q = q + SwiGLU_FFN(RMSNorm(q)) | |
| Output: [B, K, d_model] β decoder prefix | |
| """ | |
| from __future__ import annotations | |
| import math | |
| from typing import List, Optional, Tuple | |
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| from .codec_ops import dequantize_codes, unfold_tokens | |
| class RMSNorm(nn.Module): | |
| """Classic RMSNorm with stable behavior under bf16 autocast | |
| (compute norm in fp32 then cast back).""" | |
| def __init__(self, dim: int, eps: float = 1e-6): | |
| super().__init__() | |
| self.weight = nn.Parameter(torch.ones(dim)) | |
| self.eps = eps | |
| def forward(self, x: torch.Tensor) -> torch.Tensor: | |
| orig_dtype = x.dtype | |
| x32 = x.float() | |
| rms = x32.pow(2).mean(dim=-1, keepdim=True).add(self.eps).rsqrt() | |
| return (x32 * rms).to(orig_dtype) * self.weight | |
| class SwiGLU(nn.Module): | |
| """SwiGLU FFN β two gated projections + one output projection.""" | |
| def __init__(self, d_model: int, hidden_dim: int, dropout: float = 0.0): | |
| super().__init__() | |
| self.gate_proj = nn.Linear(d_model, hidden_dim, bias=False) | |
| self.up_proj = nn.Linear(d_model, hidden_dim, bias=False) | |
| self.down_proj = nn.Linear(hidden_dim, d_model, bias=False) | |
| self.dropout = nn.Dropout(dropout) if dropout > 0 else nn.Identity() | |
| def forward(self, x: torch.Tensor) -> torch.Tensor: | |
| return self.dropout(self.down_proj(F.silu(self.gate_proj(x)) * self.up_proj(x))) | |
| class SinusoidalPositionalEncoding(nn.Module): | |
| """Standard Transformer sinusoidal PE, lazily extended as needed.""" | |
| def __init__(self, d_model: int, max_len: int = 2048): | |
| super().__init__() | |
| self.d_model = d_model | |
| self.register_buffer("_pe", self._build(max_len, d_model), persistent=False) | |
| def _build(length: int, dim: int) -> torch.Tensor: | |
| pe = torch.zeros(length, dim, dtype=torch.float32) | |
| pos = torch.arange(length, dtype=torch.float32).unsqueeze(1) | |
| div = torch.exp( | |
| torch.arange(0, dim, 2, dtype=torch.float32) * (-math.log(10000.0) / dim) | |
| ) | |
| pe[:, 0::2] = torch.sin(pos * div) | |
| pe[:, 1::2] = torch.cos(pos * div) | |
| return pe | |
| def forward(self, x: torch.Tensor) -> torch.Tensor: | |
| """x: [B, T, d] β x + PE[:T]""" | |
| T = x.shape[1] | |
| if self._pe.shape[0] < T: | |
| self._pe = self._build(T, self.d_model).to(self._pe.device) | |
| return x + self._pe[:T].to(dtype=x.dtype, device=x.device) | |
| class MultiHeadAttentionBlock(nn.Module): | |
| """Thin wrapper around scaled_dot_product_attention with separate q / kv paths. | |
| Supports both self-attention (pass same tensor as q and kv) and | |
| cross-attention (pass queries as q, ref_feats as kv). Key-padding masks on | |
| kv go through as a 4D bool tensor (True = keep, False = mask). | |
| """ | |
| def __init__(self, d_model: int, num_heads: int, dropout: float = 0.0): | |
| super().__init__() | |
| if d_model % num_heads != 0: | |
| raise ValueError(f"d_model {d_model} must be divisible by num_heads {num_heads}") | |
| self.d_model = d_model | |
| self.num_heads = num_heads | |
| self.head_dim = d_model // num_heads | |
| self.q_proj = nn.Linear(d_model, d_model, bias=False) | |
| self.k_proj = nn.Linear(d_model, d_model, bias=False) | |
| self.v_proj = nn.Linear(d_model, d_model, bias=False) | |
| self.out_proj = nn.Linear(d_model, d_model, bias=False) | |
| self.attn_dropout_p = float(dropout) | |
| self.resid_dropout = nn.Dropout(dropout) if dropout > 0 else nn.Identity() | |
| def forward( | |
| self, | |
| q_in: torch.Tensor, # [B, Tq, d] | |
| kv_in: torch.Tensor, # [B, Tkv, d] | |
| kv_mask: Optional[torch.Tensor] = None, # [B, Tkv] bool, True = keep | |
| ) -> torch.Tensor: | |
| B, Tq, _ = q_in.shape | |
| Tkv = kv_in.shape[1] | |
| q = self.q_proj(q_in).view(B, Tq, self.num_heads, self.head_dim).transpose(1, 2) | |
| k = self.k_proj(kv_in).view(B, Tkv, self.num_heads, self.head_dim).transpose(1, 2) | |
| v = self.v_proj(kv_in).view(B, Tkv, self.num_heads, self.head_dim).transpose(1, 2) | |
| # SDPA attn_mask: broadcastable bool. True = attend. | |
| if kv_mask is not None: | |
| attn_mask = kv_mask.view(B, 1, 1, Tkv) | |
| else: | |
| attn_mask = None | |
| out = F.scaled_dot_product_attention( | |
| q, k, v, | |
| attn_mask=attn_mask, | |
| dropout_p=self.attn_dropout_p if self.training else 0.0, | |
| is_causal=False, | |
| ) # [B, H, Tq, head_dim] | |
| out = out.transpose(1, 2).contiguous().view(B, Tq, self.d_model) | |
| return self.resid_dropout(self.out_proj(out)) | |
| class QFormerBlock(nn.Module): | |
| """One Q-Former block: SelfAttn(q) β CrossAttn(q, ref) β FFN, all pre-norm.""" | |
| def __init__( | |
| self, | |
| d_model: int, | |
| num_heads: int, | |
| ffn_hidden: int, | |
| dropout: float = 0.1, | |
| ): | |
| super().__init__() | |
| self.norm_self = RMSNorm(d_model) | |
| self.self_attn = MultiHeadAttentionBlock(d_model, num_heads, dropout) | |
| self.norm_cross = RMSNorm(d_model) | |
| self.cross_attn = MultiHeadAttentionBlock(d_model, num_heads, dropout) | |
| self.norm_ffn = RMSNorm(d_model) | |
| self.ffn = SwiGLU(d_model, ffn_hidden, dropout) | |
| def forward( | |
| self, | |
| q: torch.Tensor, # [B, K, d] | |
| ref_feats: torch.Tensor, # [B, T_ref, d] | |
| ref_mask: Optional[torch.Tensor] = None, # [B, T_ref] bool | |
| ) -> torch.Tensor: | |
| # Self-attn on queries (bidirectional, no mask β queries are always valid). | |
| h = self.norm_self(q) | |
| q = q + self.self_attn(h, h, kv_mask=None) | |
| # Cross-attn: queries attend to ref_feats, masked on ref padding. | |
| h = self.norm_cross(q) | |
| q = q + self.cross_attn(h, ref_feats, kv_mask=ref_mask) | |
| # FFN | |
| q = q + self.ffn(self.norm_ffn(q)) | |
| return q | |
| class RefCompressor(nn.Module): | |
| """Q-Former-style compressor of codec codes into K speaker tokens. | |
| Args: | |
| codec: Codec geometry β any object with ``num_layers``, ``fsq_levels`` | |
| and ``do_unfold`` attributes. Determines ``C_total`` and whether | |
| the forward pass unfolds packed layers or assumes already-unfolded | |
| input. | |
| compressor_cfg: Hyperparameters β any object with ``num_queries``, | |
| ``num_layers``, ``num_heads``, ``d_model``, | |
| ``ffn_hidden_size_multiplier``, ``dropout``, ``queries_init_std``. | |
| backbone_hidden_size: Fallback for ``d_model`` when | |
| ``compressor_cfg.d_model`` is None. | |
| """ | |
| def __init__( | |
| self, | |
| codec, | |
| compressor_cfg, | |
| backbone_hidden_size: int, | |
| ): | |
| super().__init__() | |
| self.num_layers_codec = int(codec.num_layers) | |
| self.fsq_levels: List[int] = list(codec.fsq_levels) | |
| do_unfold_on_disk = bool(codec.do_unfold) | |
| # If the dataset is already unfolded on disk, skip unfold in forward. | |
| self.do_unfold_in_forward = not do_unfold_on_disk | |
| self.c_total = self.num_layers_codec * len(self.fsq_levels) | |
| self.d_model = int(compressor_cfg.d_model) if compressor_cfg.d_model else backbone_hidden_size | |
| self.num_queries = int(compressor_cfg.num_queries) | |
| self.num_blocks = int(compressor_cfg.num_layers) | |
| self.num_heads = int(compressor_cfg.num_heads) | |
| self.ffn_hidden = self.d_model * int(compressor_cfg.ffn_hidden_size_multiplier) | |
| self.dropout = float(compressor_cfg.dropout) | |
| self.input_proj = nn.Linear(self.c_total, self.d_model, bias=True) | |
| self.pos_enc = SinusoidalPositionalEncoding(self.d_model) | |
| self.queries = nn.Parameter( | |
| torch.randn(self.num_queries, self.d_model) * float(compressor_cfg.queries_init_std) | |
| ) | |
| self.blocks = nn.ModuleList([ | |
| QFormerBlock( | |
| d_model=self.d_model, | |
| num_heads=self.num_heads, | |
| ffn_hidden=self.ffn_hidden, | |
| dropout=self.dropout, | |
| ) | |
| for _ in range(self.num_blocks) | |
| ]) | |
| # Final norm so the prefix's scale matches other inputs into the decoder. | |
| # The learnable scalar starts at 1/sqrt(d_model) so the initial output | |
| # L2 β 1. Shape [1], not scalar [] β matches published checkpoints | |
| # after normalize_scalar_shapes. | |
| self.final_norm = RMSNorm(self.d_model) | |
| self.output_scale = nn.Parameter(torch.tensor([1.0 / math.sqrt(self.d_model)])) | |
| def forward( | |
| self, | |
| ref_codes: torch.Tensor, # [B, T_ref, C_in] long | |
| ref_mask: Optional[torch.Tensor] = None, # [B, T_ref] bool, True = real frame | |
| ) -> Tuple[torch.Tensor, torch.Tensor]: | |
| """Returns (prefix_out, q_normed): | |
| prefix_out: [B, K, d_model] β output_scale * RMSNorm(q), what the decoder consumes. | |
| q_normed: [B, K, d_model] β RMSNorm(q) before output_scale (RMS=1 per token). | |
| """ | |
| if ref_codes.dim() != 3: | |
| raise ValueError(f"ref_codes must be [B, T_ref, C_in]; got {tuple(ref_codes.shape)}") | |
| # 1. Unfold only if the dataset is packed on disk. | |
| if self.do_unfold_in_forward: | |
| # unfold_tokens expects [B, C, T], but we have [B, T, C] β transpose. | |
| x = unfold_tokens(ref_codes.transpose(1, 2), self.fsq_levels).transpose(1, 2) | |
| else: | |
| x = ref_codes # already [B, T, C_total] | |
| # 2. Dequantize to [-1, 1] floats; cast with the module dtype. | |
| x = dequantize_codes(x, self.fsq_levels, self.num_layers_codec) | |
| x = x.to(dtype=self.input_proj.weight.dtype) | |
| # 3. Linear project to d_model, add sinusoidal PE. | |
| x = self.input_proj(x) | |
| x = self.pos_enc(x) | |
| # 4. Expand learnable queries across the batch. | |
| B = x.shape[0] | |
| q = self.queries.to(dtype=x.dtype, device=x.device).unsqueeze(0).expand(B, -1, -1) | |
| # 5. Run Q-Former blocks; queries attend to ref_feats with the ref mask. | |
| for block in self.blocks: | |
| q = block(q, ref_feats=x, ref_mask=ref_mask) | |
| q_normed = self.final_norm(q) # RMS=1 per token | |
| return self.output_scale * q_normed, q_normed | |