Spaces:
Running on Zero
Running on Zero
| from abc import ABC, abstractmethod | |
| from torch import nn, Tensor | |
| import torch | |
| import x_transformers as xt | |
| from typing import Optional | |
| import config as cfg | |
| class ResidualTokenEmbedding(nn.Module): | |
| def __init__(self, | |
| dim: int, | |
| num_tokens: int, | |
| n_layers: int, | |
| padding_token: Optional[int] = None): | |
| super().__init__() | |
| self.padding_token: Optional[int] = padding_token | |
| self.emb = nn.ModuleList([ | |
| nn.Embedding(num_tokens, dim, padding_idx=self.padding_token) | |
| for _ in range(n_layers) | |
| ]) | |
| for layer in self.emb: | |
| nn.init.kaiming_normal_(layer.weight) | |
| def forward(self, x): | |
| n_res_layers = x.shape[1] | |
| assert n_res_layers == len(self.emb) | |
| token_emb: Tensor = sum( # type: ignore | |
| [self.emb[i](x[:, i]) for i in range(n_res_layers)]) | |
| return token_emb | |
| def create_sin_embedding( | |
| positions: torch.Tensor, | |
| dim: int, | |
| max_period: float = 10000, | |
| dtype: torch.dtype = torch.float32, | |
| ) -> torch.Tensor: | |
| """Create sinusoidal positional embedding, with shape `[B, T, C]`. | |
| Args: | |
| positions (torch.Tensor): LongTensor of positions. | |
| dim (int): Dimension of the embedding. | |
| max_period (float): Maximum period of the cosine/sine functions. | |
| dtype (torch.dtype or str): dtype to use to generate the embedding. | |
| Returns: | |
| torch.Tensor: Sinusoidal positional embedding. | |
| """ | |
| # We aim for BTC format | |
| assert dim % 2 == 0 | |
| half_dim = dim // 2 | |
| positions = positions.to(dtype) | |
| adim = torch.arange(half_dim, device=positions.device, | |
| dtype=dtype).view(1, 1, -1) | |
| max_period_tensor = torch.full([], | |
| max_period, | |
| device=positions.device, | |
| dtype=dtype) # avoid sync point | |
| phase = positions / (max_period_tensor**(adim / (half_dim - 1))) | |
| return torch.cat([torch.cos(phase), torch.sin(phase)], dim=-1) | |
| class ResidualSinusoidalEmbedding(nn.Module): | |
| def __init__(self, dim, theta=10000): | |
| super().__init__() | |
| assert dim % 2 == 0 | |
| self.scale = 1 | |
| self.theta = theta | |
| self.dim = dim | |
| def forward(self, x, pos=None, seq_start_pos=None): | |
| B, K, T = x.shape | |
| positions = (pos if pos is not None else torch.arange( | |
| T, device=x.device).view(1, -1, 1)) | |
| pos_emb = create_sin_embedding(positions, | |
| self.dim, | |
| max_period=self.theta, | |
| dtype=x.dtype) | |
| return pos_emb * self.scale | |
| class ResidualOutputProj(nn.Module): | |
| def __init__(self, input_dim: int, output_dim: int, n_layers: int, | |
| use_bias: bool): | |
| super().__init__() | |
| self.linears = nn.ModuleList([ | |
| nn.Linear(input_dim, output_dim, use_bias) for _ in range(n_layers) | |
| ]) | |
| def forward(self, x): | |
| return torch.stack([layer(x) for layer in self.linears], dim=1) | |
| class TransformerDecoder(ABC, nn.Module): | |
| def forward(x, mask, context, context_mask, prepend_data, prepend_mask, | |
| sum_data) -> Tensor: | |
| ... | |
| class XTransformerDecoder(TransformerDecoder): | |
| def __init__( | |
| self, | |
| num_tokens: int, | |
| max_seq_len: int, | |
| use_abs_pos_emb: bool, | |
| scaled_sinu_pos_emb: bool, | |
| dim: int, | |
| depth: int, | |
| heads: int, | |
| attn_dim_head: int, | |
| attn_flash: bool, | |
| ff_no_bias: bool, | |
| cross_attend: bool, | |
| ): | |
| self.decoder: xt.TransformerWrapper = xt.TransformerWrapper( | |
| num_tokens=self.input_card, | |
| max_seq_len=500, | |
| use_abs_pos_emb=True, | |
| scaled_sinu_pos_emb=True, | |
| attn_layers=xt.Decoder( | |
| dim=self.dim, | |
| depth=self.n_layers, | |
| heads=self.n_heads, | |
| attn_dim_head=64, | |
| attn_flash=True, | |
| ff_no_bias=True, | |
| cross_attend=self.cross_attend, | |
| ), | |
| ) | |
| self.decoder.token_emb = ResidualTokenEmbedding( # type: ignore | |
| self.dim, | |
| self.input_card, | |
| self.n_q, | |
| self.padding_token, | |
| ) | |
| self.decoder.pos_emb = ResidualSinusoidalEmbedding( # type: ignore | |
| dim=self.dim) | |
| self.decoder.to_logits = ResidualOutputProj(self.dim, self.card, | |
| self.n_q, False) | |
| # TODO: this is horrendous, gotta find a fix | |
| if not self.cross_attend: | |
| self.nullwav_embeds = torch.load(cfg.weights_dir() / | |
| "nullwav_embeds.pt")[0] | |
| else: | |
| self.nullwav_embeds = None | |