Skip to content

Latest commit

Β 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

README.md

training/distill

Stage 1 of the training pipeline: distill a small ternary student from a frozen teacher. Produces a .pt checkpoint that training/pack/ consumes.

Quickstart

# install uv if needed: curl -LsSf https://astral.sh/uv/install.sh | sh
cd training/distill
uv venv
source .venv/bin/activate
uv pip install -r requirements.txt

# 1. One-time: build the cached training dataset
python prep/prepare.py --config configs/micro.yaml

# 2. Train (uses GPU if available)
python train.py --config configs/micro.yaml

# 3. Run go/no-go eval suite on the final checkpoint
python evaluate.py --checkpoint runs/micro-qat-1M-60ep/checkpoint_ep60.pt

Layout

distill/
β”œβ”€β”€ prep/                  Phase 1 β€” data preparation (one-time setup)
β”‚   β”œβ”€β”€ prepare.py             entry point: read config, build cache
β”‚   └── ingest.py              helpers: loaders, dedup, tokenize, encode, split, manifest, stats
β”œβ”€β”€ train.py               Phase 2/3 entry point: parse args, load config, run training
β”œβ”€β”€ trainer.py             Trainer class (warmup β†’ QAT controlled by config, not by file)
β”œβ”€β”€ model.py               StudentEncoder + attention + FFN + transformer block
β”‚                          (explicit Q/K/V Linear layers β€” BitLinear-reachable)
β”œβ”€β”€ quantization.py        BitLinear swap, embedding ternarization, zero-frac health
β”œβ”€β”€ loss.py                distillation (cosine) + contrastive (within-batch guardrail)
β”œβ”€β”€ evaluate.py            Phase 4 entry point: load checkpoint, run Tasks 1/2/3, emit verdict
β”œβ”€β”€ data.py                cross-phase: TernDataset, collate_fn, save_cache, load_cache
β”œβ”€β”€ config.py              cross-phase: pydantic schemas + YAML loader
β”œβ”€β”€ configs/               per-tier configs
β”‚   β”œβ”€β”€ micro.yaml             d_model=256, full QAT run
β”‚   β”œβ”€β”€ micro-fp32.yaml        float32 baseline (the ruler for QAT)
β”‚   β”œβ”€β”€ small.yaml             d_model=384 fallback
β”‚   └── smoke.yaml             tiny config for CI / quick local check
β”œβ”€β”€ corpora/               local eval data (jsonl) β€” review/edit without touching Python
β”‚   β”œβ”€β”€ general.jsonl
β”‚   └── tech.jsonl
└── requirements.txt

prep/ is the only sub-package β€” it's a discrete one-time setup phase with multiple files. The training files (model, trainer, loss, quantization) stay flat at root because they're tightly coupled to one another. data.py and config.py are cross-phase contracts.

Training pipeline

The pipeline has four phases. Phases 2 and 3 are both invoked through train.py; the only difference is which config you pass.

Phase Action Entry point Key knobs
1. Data prep Multi-source mix β†’ tokenize β†’ teacher encode β†’ .pt cache prep/prepare.py --config <yaml> source mix, sample count, teacher id
2. Float32 baseline Distillation in pure fp32. Establishes the architecture ceiling. train.py --config configs/micro-fp32.yaml epochs, batch size, LR
3. QAT training Float32 warmup β†’ BitLinear ternary. Same distillation loss + contrastive guardrail. train.py --config configs/micro.yaml warmup_epochs, lambda schedule, loss weights
4. Post-train eval Apply ternary projection to embedding, run Tasks 1/2/3, emit GO/MARGINAL/NO-GO. evaluate.py --checkpoint <run>/checkpoint_ep<N>.pt quant_embedding (default on)

Phase 2 is the ruler, phase 3 is the ship: phase 3 is what we deliver, phase 2 only exists so we can measure how much QAT costs vs. an unconstrained architecture.

Post-training evaluation (Phase 4)

evaluate.py runs three tasks against a checkpoint. Critically, the embedding table is post-train ternarized first β€” nn.Embedding is untouched during QAT, but the shipped .bin is ternary, so eval has to apply the same projection to be honest.

Task What it tests Source Pass threshold
1. Teacher Alignment Per-sample cosine sim vs. teacher 2,000 held-out MS MARCO queries mean > 0.75
2. STS-B Ranking Does the model rank pairs like humans? mteb/stsbenchmark-sts test (1,379 pairs) AUC > 0.80
3. Recall@3 End-to-end retrieval corpora/general.jsonl, corpora/tech.jsonl min(general, tech) R@3 > 0.70

Decision table:

  • Any FAIL β†’ NO-GO; rethink architecture
  • Any MARGINAL with no FAIL β†’ retry with configs/small.yaml (d_model=384)
  • All PASS β†’ GO; proceed to training/pack/ for the .bin export

Math reference

Forward pass, backprop, loss formulation, why each design choice was made β€” all in ../../docs/training/model-internals.md. The Phase 2 postmortem (../../docs/training/postmortem-bitlinear-asymmetry.md) covers what the real BitLinear forward pass computes β€” relevant when modifying quantization.py because the same math has to apply identically in training/pack/pack.py and engine/src/inference.rs.

Status

Pre-alpha β€” code migration from tern-distill-prototype/poc/ pending.