Instructions to use justanurag/maya-mac with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use justanurag/maya-mac with MLX:
# Download the model from the Hub pip install huggingface_hub[hf_xet] hf download justanurag/maya-mac --local-dir maya-mac
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- Atomic Chat
File size: 5,995 Bytes
1eac567 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | """Streaming Mimi decoder for one stream: feed any number of frames at a time, get exactly their audio back.
Arithmetic of upstream serve/fast_codec.StaticMimi (itself a port of the verified streaming reference) without CUDA
graphs or seat slots: causal-convolution history, transposed-convolution overlap tails (bias removed from the stored
tail), and sliding-window attention with absolute RoPE positions (a query at position p sees keys with
p - sliding_window < key_pos <= p). HF sub-modules are only called for their weights.
"""
import torch
import torch.nn.functional as F
from transformers.models.mimi.modeling_mimi import (MimiConv1d, MimiConvTranspose1d, MimiResnetBlock,
apply_rotary_pos_emb, repeat_kv)
class StreamingMimi:
def __init__(self, mimi):
cfg = mimi.config
if not cfg.use_causal_conv or cfg.pad_mode != "constant" or cfg.trim_right_ratio != 1:
raise ValueError("streaming decode requires causal constant padding and trim_right_ratio=1")
self.m = mimi
self.window = int(cfg.sliding_window)
attn = mimi.decoder_transformer.layers[0].self_attn
self.kv_groups, self.head_dim = attn.num_key_value_groups, attn.head_dim
rotary = attn.rotary_emb
self._inv_freq = rotary.inv_freq.detach().float().clone()
self._rope_scale = float(rotary.attention_scaling)
self.reset()
def reset(self):
self.state = {}
self.kv = [None] * len(self.m.decoder_transformer.layers) # [(k, v)] post-RoPE, last window-1 tokens
self.tokens = 0
def _layer(self, module, x, key):
if isinstance(module, MimiConv1d):
if module.conv.stride != (1,):
raise ValueError("only stride-one decoder convolutions are supported")
pad = (module.conv.kernel_size[0] - 1) * module.conv.dilation[0]
if pad:
prev = self.state.get(key)
if prev is None:
prev = x.new_zeros(x.shape[0], x.shape[1], pad)
x = torch.cat((prev, x), dim=-1)
self.state[key] = x[..., -pad:]
return module.conv(x)
if isinstance(module, MimiConvTranspose1d):
y = module.conv(x)
produced = x.shape[-1] * module.conv.stride[0]
if module.padding_right:
tail = y[..., produced:]
if module.conv.bias is not None:
tail = tail - module.conv.bias[None, :, None]
prev = self.state.get(key)
y = y[..., :produced].clone()
if prev is not None:
y[..., :prev.shape[-1]] += prev
self.state[key] = tail
return y
return y[..., :produced]
if isinstance(module, MimiResnetBlock):
shortcut = self._layer(module.shortcut, x, key + ".shortcut")
for i, child in enumerate(module.block):
x = self._layer(child, x, key + f".block.{i}")
return shortcut + x
return module(x)
@staticmethod
def _rvq(rvq, codes):
total = None
for i in range(codes.shape[1]):
e = F.embedding(codes[:, i], rvq.layers[i].codebook.embed).permute(0, 2, 1)
total = e if total is None else total + e
return rvq.output_proj(total) if rvq.output_proj is not None else total
def _quantizer(self, codes):
q = self.m.quantizer
n = q.num_semantic_quantizers
out = self._rvq(q.semantic_residual_vector_quantizer, codes[:, :n])
if codes.shape[1] > n:
out = out + self._rvq(q.acoustic_residual_vector_quantizer, codes[:, n:])
return out
def _transformer(self, h):
B, T, _ = h.shape
pos = torch.arange(self.tokens, self.tokens + T, device=h.device)
freqs = pos[:, None].float() * self._inv_freq.to(h.device)[None]
emb = torch.cat((freqs, freqs), dim=-1)
cos = (emb.cos() * self._rope_scale).to(h.dtype)[None]
sin = (emb.sin() * self._rope_scale).to(h.dtype)[None]
n_past = 0 if self.kv[0] is None else self.kv[0][0].shape[2]
key_pos = torch.arange(self.tokens - n_past, self.tokens + T, device=h.device)
mask = (key_pos[None] <= pos[:, None]) & (key_pos[None] > pos[:, None] - self.window)
for li, layer in enumerate(self.m.decoder_transformer.layers):
attn = layer.self_attn
x = layer.input_layernorm(h)
q = attn.q_proj(x).view(B, T, -1, self.head_dim).transpose(1, 2)
k = attn.k_proj(x).view(B, T, -1, self.head_dim).transpose(1, 2)
v = attn.v_proj(x).view(B, T, -1, self.head_dim).transpose(1, 2)
q, k = apply_rotary_pos_emb(q, k, cos, sin)
if self.kv[li] is not None:
k = torch.cat((self.kv[li][0], k), dim=2)
v = torch.cat((self.kv[li][1], v), dim=2)
keep = self.window - 1
self.kv[li] = (k[:, :, -keep:], v[:, :, -keep:])
a = F.scaled_dot_product_attention(q, repeat_kv(k, self.kv_groups), repeat_kv(v, self.kv_groups),
attn_mask=mask[None, None])
a = attn.o_proj(a.transpose(1, 2).reshape(B, T, -1))
h = h + layer.self_attn_layer_scale(a)
h = h + layer.mlp_layer_scale(layer.mlp(layer.post_attention_layernorm(h)))
self.tokens += T
return h
@torch.inference_mode()
def decode(self, codes):
"""codes: (32, T) long (one stream, T frames) -> float32 numpy (T * 1920,) PCM in [-1, 1]."""
x = self._quantizer(codes[None].long())
x = self._layer(self.m.upsample, x, "upsample")
x = self._transformer(x.transpose(1, 2)).transpose(1, 2)
for i, layer in enumerate(self.m.decoder.layers):
x = self._layer(layer, x, f"decoder.{i}")
return x[0, 0].float().clamp(-1, 1).cpu().numpy()
|