| # | Topic | Section |
|---|---|---|
| 6 | Scaled Dot-Product Attention | §6 |
| 7 | Multi-Head Attention (MHA) | §7 |
| 8 | Grouped Query Attention (GQA) | §8 |
| 9 | Multi-Head Latent Attention (MLA) | §9 |
| 10 | Sliding Window Attention | §10 |
| 11 | Attention Mask Builder | §11 |
The core operation of all transformers. Each token "queries" all other tokens, computes a relevance score, and takes a weighted average of their values.
Where:
-
$\mathbf{Q} \in \mathbb{R}^{S_q \times d_h}$ — Query matrix (what am I looking for?) -
$\mathbf{K} \in \mathbb{R}^{S_k \times d_h}$ — Key matrix (what do I contain?) -
$\mathbf{V} \in \mathbb{R}^{S_k \times d_h}$ — Value matrix (what do I output?) -
$\sqrt{d_h}$ — scaling factor to prevent softmax saturation
Without scaling, dot products grow proportionally to
- Dot products become very large → softmax pushes to one-hot → gradients vanish
- Scaling keeps variance ≈ 1.0 regardless of
$d_h$
Proof: if
Q = [[1, 0], K = [[1, 0], V = [[1, 2],
[0, 1]] [0, 1], [3, 4],
[1, 1]] [5, 6]]
d_h = 2
Step 1 — Compute QK^T:
[[1×1+0×0, 1×0+0×1, 1×1+0×1], [[1, 0, 1],
[0×1+1×0, 0×0+1×1, 0×1+1×1]] = [0, 1, 1]]
Step 2 — Scale by √2 ≈ 1.414:
[[0.707, 0.000, 0.707],
[0.000, 0.707, 0.707]]
Step 3 — Softmax (per row):
Row 0: exp([0.707, 0.000, 0.707]) = [2.028, 1.000, 2.028]
→ normalize: [0.401, 0.198, 0.401]
Row 1: exp([0.000, 0.707, 0.707]) = [1.000, 2.028, 2.028]
→ normalize: [0.198, 0.401, 0.401]
Step 4 — Multiply by V:
Row 0: 0.401×[1,2] + 0.198×[3,4] + 0.401×[5,6]
= [0.401+0.594+2.005, 0.802+0.792+2.406]
= [3.000, 4.000]
Row 1: 0.198×[1,2] + 0.401×[3,4] + 0.401×[5,6]
= [0.198+1.203+2.005, 0.396+1.604+2.406]
= [3.406, 4.406]
Output: [[3.000, 4.000],
[3.406, 4.406]]
Runs
| Matrix | Shape | Count |
|---|---|---|
| Total |
During autoregressive generation, K and V must be cached for all previous tokens. Memory cost per layer:
For a 128K context with 128 heads × 128 dim in FP16: 4 GB per layer → motivates GQA and MLA.
Reduces KV cache by sharing KV heads across groups of Q heads. APEX-1 uses GQA on local (non-global) layers.
Each KV head is shared by
| Method | KV heads | KV cache size | Relative |
|---|---|---|---|
| MHA | 1.0× | ||
| GQA ( |
8 | 0.0625× (16× smaller) | |
| MQA ( |
1 | 0.0078× |
APEX-1 Large:
H_q = 4, H_kv = 2, G = 4/2 = 2
Q heads: [Q₀, Q₁, Q₂, Q₃]
K heads: [K₀, K₁]
V heads: [V₀, V₁]
Assignment:
Q₀, Q₁ → share K₀, V₀ (group 0)
Q₂, Q₃ → share K₁, V₁ (group 1)
Each Q head computes attention with its assigned K,V:
head₀ = Attn(Q₀, K₀, V₀)
head₁ = Attn(Q₁, K₀, V₀) ← same K,V as head₀
head₂ = Attn(Q₂, K₁, V₁)
head₃ = Attn(Q₃, K₁, V₁) ← same K,V as head₂
Compresses all KV information into a tiny latent vector
KV Compression (input → latent):
KV Decompression (latent → full K, V):
Q Compression (similar):
Positional encoding is applied via separate projections, not through the compressed latent (which would lose position info):
Final Q and K are concatenated:
| Method | What is cached | Size per token | Relative |
|---|---|---|---|
| Standard MHA | Full K + V | 1.0× | |
| GQA | K + V (fewer heads) | ||
| MLA | Only |
APEX-1 Large:
| Matrix | Shape | Purpose |
|---|---|---|
| Compress to KV latent | ||
| Decompress to K | ||
| Decompress to V | ||
| Compress to Q latent | ||
| Decompress to Q | ||
| Q RoPE projection | ||
| K RoPE projection | ||
| Output projection |
Limits attention to the most recent
| Method | Time complexity | Memory | Best for |
|---|---|---|---|
| Full causal | Global reasoning | ||
| Sliding window | Local syntax | ||
| Ratio |
|
For APEX-1 Large:
APEX-1 combines three masking strategies:
| Regime | Positions | Behavior |
|---|---|---|
| Prefix bidirectional | All prefix tokens attend to all prefix tokens | |
| Global causal |
|
Full causal attention over entire history |
| Local causal + window |
|
Causal limited to window |
With
| Layer | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Type | L | L | L | L | L | G | L | L | L | L | L | G |
Global layer (full causal)
Position: 0 1 2 3 4 5 6 7 8 9
0: █ █ █ █ · · · · · · ← prefix bidir
1: █ █ █ █ · · · · · ·
2: █ █ █ █ · · · · · ·
3: █ █ █ █ · · · · · ·
4: █ █ █ █ █ · · · · · ← full causal
5: █ █ █ █ █ █ · · · ·
9: █ █ █ █ █ █ █ █ █ █
Local layer (window=4)
Position: 0 1 2 3 4 5 6 7 8 9
0: █ █ █ █ · · · · · · ← prefix bidir
3: █ █ █ █ · · · · · ·
4: · █ █ █ █ · · · · · ← window only
7: · · · · █ █ █ █ · ·
9: · · · · · · █ █ █ █
| Component | Formula | Cache Size |
|---|---|---|
| SDPA | — | |
| GQA | Share KV across |
|
| MLA compress | $\mathbf{c}{kv} = \mathbf{x} \mathbf{W}{DKV}$ | |
| MLA decompress | $\mathbf{K} = \mathbf{c}{kv} \mathbf{W}{UK}$ | on-the-fly |
| Sliding window | mask: |
|
| Global/local rule |
|
— |
← Part 1: Foundations | Continue to Part 3: FFN, MoE, Skip Gate, Multi-Token →