Text Generation
TensorRT
Safetensors
PyTorch
English
llama
code
developer-agent
blackwell
rtx-5070
slm
conversational
Instructions to use Vivid86/MiniTransformer-91M with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- TensorRT
How to use Vivid86/MiniTransformer-91M with TensorRT:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
Download model/attention.py from Vivid86/MiniTransformer-91M: direct link, hf CLI and curl.
- Browser
- Download file 6.55 kB
-
https://huggingface.co/Vivid86/MiniTransformer-91M/resolve/main/model/attention.py
- Command line
-
hf download hf://Vivid86/MiniTransformer-91M/model/attention.py
-
curl -L -o attention.py https://huggingface.co/Vivid86/MiniTransformer-91M/resolve/main/model/attention.py
6.55 kB
| """ | |
| CausalSelfAttention | |
| ββββββββββββββββββββ | |
| Modern causal self-attention with: | |
| 1. SCALED DOT-PRODUCT ATTENTION (SDPA) | |
| torch.nn.functional.scaled_dot_product_attention dispatches to Flash | |
| Attention 2 on CUDA automatically. Flash Attention rewrites the standard | |
| O(NΒ²) memory algorithm as a tiled, IO-efficient kernel β peak memory is | |
| O(N) instead of O(NΒ²), enabling much longer contexts on the same GPU. | |
| 2. ROTARY POSITION EMBEDDINGS (RoPE) | |
| Applied to Q and K before attention. Encodes relative position as a | |
| rotation in head-dimension space β see positional_encoding.py. | |
| 3. GROUPED-QUERY ATTENTION (GQA) | |
| Standard MHA uses n_heads Q, K, V projections. | |
| GQA shares fewer KV heads across multiple Q heads: | |
| - n_kv_heads == n_heads β standard MHA (original Transformer) | |
| - n_kv_heads < n_heads β GQA (Llama 3, Mistral) | |
| - n_kv_heads == 1 β MQA (one shared KV pair) | |
| GQA reduces KV-cache memory at inference by a factor of (n_heads / n_kv_heads) | |
| with minimal quality loss. | |
| 4. KV-CACHE | |
| During autoregressive inference, we only ever process one new token but | |
| recompute all previous K, V from scratch if we run the full sequence each | |
| step. The KV-cache stores previous K, V tensors and appends the new ones, | |
| reducing each inference step from O(TΒ²) to O(T) compute. | |
| 5. BIAS-FREE PROJECTIONS | |
| All linear projections use bias=False, matching Llama/Mistral practice. | |
| Biases provide negligible benefit in large models and waste memory. | |
| """ | |
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| from model.positional_encoding import apply_rotary_emb | |
| class CausalSelfAttention(nn.Module): | |
| """ | |
| Multi-head causal self-attention with RoPE, GQA, SDPA, and KV-cache. | |
| Args: | |
| d_model: Model hidden dimension. | |
| n_heads: Number of query attention heads. | |
| n_kv_heads: Number of key/value heads (β€ n_heads). For standard MHA | |
| set n_kv_heads == n_heads. | |
| dropout: Attention dropout probability (0.0 recommended at scale). | |
| """ | |
| def __init__( | |
| self, | |
| d_model: int, | |
| n_heads: int, | |
| n_kv_heads: int, | |
| dropout: float = 0.0, | |
| ): | |
| super().__init__() | |
| assert d_model % n_heads == 0, ( | |
| f"d_model ({d_model}) must be divisible by n_heads ({n_heads})" | |
| ) | |
| assert n_heads % n_kv_heads == 0, ( | |
| f"n_heads ({n_heads}) must be divisible by n_kv_heads ({n_kv_heads})" | |
| ) | |
| self.n_heads = n_heads | |
| self.n_kv_heads = n_kv_heads | |
| self.head_dim = d_model // n_heads | |
| self.dropout = dropout | |
| self.kv_groups = n_heads // n_kv_heads # how many Q heads share each KV head | |
| # Separate Q/K/V projections β sizes differ for GQA | |
| self.q_proj = nn.Linear(d_model, n_heads * self.head_dim, bias=False) | |
| self.k_proj = nn.Linear(d_model, n_kv_heads * self.head_dim, bias=False) | |
| self.v_proj = nn.Linear(d_model, n_kv_heads * self.head_dim, bias=False) | |
| self.o_proj = nn.Linear(d_model, d_model, bias=False) | |
| def forward( | |
| self, | |
| x: torch.Tensor, | |
| cos: torch.Tensor, | |
| sin: torch.Tensor, | |
| past_kv: tuple[torch.Tensor, torch.Tensor] | None = None, | |
| ) -> tuple[torch.Tensor, tuple[torch.Tensor, torch.Tensor]]: | |
| """ | |
| Args: | |
| x: Input, shape [B, T, d_model]. | |
| cos: RoPE cosines, shape [1, 1, T, head_dim]. | |
| sin: RoPE sines, shape [1, 1, T, head_dim]. | |
| past_kv: Optional cached (k, v) from previous decode steps. | |
| - None β training / first inference step (is_causal=True) | |
| - tuple β incremental decode step (append to cache) | |
| Returns: | |
| out: Attention output, shape [B, T, d_model]. | |
| present_kv: Updated (k, v) cache tuple for use in the next step. | |
| """ | |
| B, T, _ = x.shape | |
| # ββ Project Q, K, V ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| q = self.q_proj(x).view(B, T, self.n_heads, self.head_dim).transpose(1, 2) | |
| k = self.k_proj(x).view(B, T, self.n_kv_heads, self.head_dim).transpose(1, 2) | |
| v = self.v_proj(x).view(B, T, self.n_kv_heads, self.head_dim).transpose(1, 2) | |
| # Shapes after transpose: [B, heads, T, head_dim] | |
| # ββ Apply Rotary Embeddings βββββββββββββββββββββββββββββββββββββββββββ | |
| q, k = apply_rotary_emb(q, k, cos, sin) | |
| # ββ KV-Cache (inference only) βββββββββββββββββββββββββββββββββββββββββ | |
| # Append new K/V to the cached history so we never recompute old tokens. | |
| if past_kv is not None: | |
| k = torch.cat([past_kv[0], k], dim=2) # grow along sequence axis | |
| v = torch.cat([past_kv[1], v], dim=2) | |
| present_kv = (k, v) # return updated cache | |
| # ββ GQA: broadcast KV heads to match Q heads βββββββββββββββββββββββββ | |
| # Each group of (n_heads/n_kv_heads) Q heads attends to the same KV pair. | |
| if self.kv_groups > 1: | |
| k = k.repeat_interleave(self.kv_groups, dim=1) # [B, n_heads, S, head_dim] | |
| v = v.repeat_interleave(self.kv_groups, dim=1) | |
| # ββ Scaled Dot-Product Attention ββββββββββββββββββββββββββββββββββββββ | |
| # is_causal=True β auto-builds a causal mask (training / first step) | |
| # is_causal=False β no mask (KV-cache handles causality by construction) | |
| # PyTorch dispatches this to Flash Attention 2 on CUDA when available. | |
| is_causal = past_kv is None | |
| attn_out = F.scaled_dot_product_attention( | |
| q, k, v, | |
| dropout_p = self.dropout if self.training else 0.0, | |
| is_causal = is_causal, | |
| ) | |
| # ββ Merge heads and project βββββββββββββββββββββββββββββββββββββββββββ | |
| out = attn_out.transpose(1, 2).contiguous().view(B, T, -1) | |
| return self.o_proj(out), present_kv | |