LoRA & QLoRA
The first module of Pillar 2 — where you do your first real fine-tune. LoRA decomposes a weight update into W = W0 + BA (frozen base + tiny trainable B,A); QLoRA freezes the base at 4-bit so a 7B model trains on a 24GB consumer card. The four LoRA knobs, QLoRA's three innovations, the full train-and-merge workflow, and the modern all-linear target default.
LoRA's low-rank decomposition W = W0 + BA — where W0 is frozen and B (zero-init), A (random-init) are tiny trainable matrices — works because steering is intrinsically low-rank. The intrinsic dimension hypothesis (Aghajanyan 2020, arXiv:2007.07784) showed useful fine-tuning changes live in a low-rank subspace; you can fine-tune to within 90% of full-FT by training ~0.5% of params. This is the FT00 thesis made rigorous — steering is low-rank, knowledge injection would be high-rank. B's zero-init makes the adapter a residual steer that cannot degrade the base at step zero (a guarantee full FT lacks).
A LoRA adapter is four knobs: rank r (default 16), alpha α (convention α≈2×r, so the effective magnitude is stable across rank and you don't retune the LR), target modules (MODERN default = ALL attention + ALL MLP projections: q,k,v,o_proj + gate,up,down_proj — NOT attention-only), and dropout (0.05). Target modules is the single biggest quality lever: all-linear beats attention-only (the 2021 default) at comparable trainable-param budgets because behavior steering lives in the MLP feature pathway too, not just attention.
QLoRA (Dettmers 2023, arXiv:2305.14314) freezes the base at 4-bit via three innovations, each necessary: (1) NF4 (NormalFloat 4-bit) — quantile bins matched to the normal distribution, information-theoretically optimal for Gaussian weights; (2) double quantization — quantize the quantization constants themselves to 8-bit, saving ~0.37 bits/param; (3) paged optimizers — NVIDIA Unified Memory pages optimizer state to CPU to absorb the OOM spikes during checkpointing (the killer that crashes runs sized to steady-state). Together they fit 7B on a 24GB card at ~10–14 GB — a ~10× spread vs full FT's ~100–160 GB.
The full workflow is five steps: load base in 4-bit (BitsAndBytesConfig, nf4, double_quant, bf16) → prepare_model_for_kbit_training (the forgotten step) → get_peft_model with the LoraConfig (print_trainable_parameters → expect <1%) → train adapters only (4-bit base never moves) → merge_and_unload() to bake the adapter into the base for deployment (one artifact, then re-quantize to GGUF/AWQ), OR keep the adapter separate for hot-swapping (one base, many adapters). Merge = deploy default; keep separate = experimentation/multi-tenant default.