| # Low-Level Design (LLD) |
|
|
| ## Module Details |
|
|
| ### s02_tokenizer.py β REMI Tokenizer |
| |
| **Vocabulary Layout** (485 tokens total): |
| ``` |
| [0] PAD |
| [1] BOS (Beginning of Sequence) |
| [2] EOS (End of Sequence) |
| [3] SEP (Separator) |
| [4-131] NoteOn (MIDI pitch 0-127) |
| [132-259] NoteOff (MIDI pitch 0-127) |
| [260-291] Velocity (32 bins, each = 4 MIDI velocity units) |
| [292-391] TimeShift (10ms steps, 10ms-1000ms) |
| [392-451] Tempo (40-200 BPM, 60 bins) |
| [452-483] Position (32 positions per bar) |
| [484] Bar (bar delimiter) |
| ``` |
| |
| **Encoding Algorithm**: |
| 1. Collect all non-drum notes across instruments |
| 2. Sort by onset time, then pitch |
| 3. For each note: emit [TimeShift, Position, Velocity, NoteOn, TimeShift(duration), NoteOff] |
| 4. Insert Bar tokens at measure boundaries |
| 5. Wrap with BOS/EOS |
| |
| ### s04_model.py β MusicTransformer |
|
|
| **Layer Stack** (per block): |
| ``` |
| Input β RMSNorm β GQA (with RoPE) β Residual Add |
| β RMSNorm β SwiGLU FFN β Residual Add β Output |
| ``` |
|
|
| **Grouped Query Attention**: |
| - 8 query heads, 4 key-value heads |
| - Each KV head serves 2 query heads (n_rep = 2) |
| - Head dim = 256/8 = 32 |
| - Uses PyTorch 2.0 `scaled_dot_product_attention` (Flash Attention backend when available) |
|
|
| **RoPE Implementation**: |
| - Precompute sin/cos frequencies: `freq[i] = 1 / (ΞΈ^(2i/d))` |
| - Apply rotation: `q' = q * cos + rotate_half(q) * sin` |
| - Device-compatible real-valued implementation (no complex tensors) |
|
|
| **SwiGLU FFN**: |
| - `output = W2(SiLU(W1(x)) * W3(x))` |
| - Hidden dim = 448 (nearest multiple of 64 to `2/3 * 4 * 256`) |
|
|
| ### s05_trainer.py β Training Loop |
| |
| **Optimization Details**: |
| - AdamW: Ξ²β=0.9, Ξ²β=0.95, wd=0.1 |
| - LR schedule: linear warmup (200 steps) β cosine decay to 1e-6 |
| - Gradient accumulation: 4 steps (effective batch = 4 Γ 4 = 16) |
| - Max gradient norm: 1.0 |
| |
| **Memory Budget (estimated for 512 seq len)**: |
| | Component | Memory | |
| |------------------------|-----------| |
| | Model weights (FP32) | ~20MB | |
| | Gradients | ~20MB | |
| | Optimizer states | ~40MB | |
| | Activations (w/ ckpt) | ~50MB | |
| | Data batch | ~4MB | |
| | **Total** | **~134MB**| |
| |
| ### s06_generator.py β Inference |
|
|
| **Decoding Pipeline**: |
| ``` |
| logits β temperature_scale β repetition_penalty β top_k_filter β top_p_filter β softmax β multinomial_sample |
| ``` |
|
|
| **KV-Cache**: |
| - Each layer stores (K, V) tensors after each forward pass |
| - New tokens only compute attention against cached KV + new KV |
| - Reset between generations to prevent cross-contamination |
|
|
| ## Class Diagram |
|
|
| ``` |
| MusicTokenizer MusicTransformer Trainer |
| βββ midi_to_tokens() βββ TransformerBlock (Γ6) βββ _train_epoch() |
| βββ tokens_to_midi() β βββ GroupedQueryAttention βββ _validate() |
| βββ decode_token() β β βββ wq, wk, wv, wo βββ _save_checkpoint() |
| βββ save()/load() β β βββ RoPE application βββ load_checkpoint() |
| β β β βββ KV-cache |
| βββ Token constants β βββ SwiGLU FFN |
| β βββ RMSNorm (Γ2) |
| βββ token_emb (weight-tied) |
| βββ output projection |
| βββ forward() / from_config() |
| ``` |
|
|