AriaLM / docs /LLD.md
krishnah27's picture
Upload folder using huggingface_hub
30e9297 verified
|
Raw
History Blame Contribute Delete
3.39 kB

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()