← TinyGPT · docs · devlog · roadmap · speedup
source: docs/audit_2026.md · view on GitHub ↗

Audit 2026 — what we tried, what worked, what we flagged

After ~70 techniques shipped across the project, this doc is the honest reckoning. Each entry: what it claimed, what we measured, and verdict (🟢 KEEP / 🟡 FLAG / 🔴 DELETE).

2026-07-05 exactness note: this remains the prose audit. The structured row-level inventory now lives in docs/techniques/audit-inventory.md: 83 tracked audit rows, including intentional duplicate mentions such as YOCO and BPE-dropout. Use that inventory for classification; use docs/attempt-ledger.md only for concrete run attempts.

Conviction bar for DELETE: only items I’m genuinely convinced are useless to the project under ANY scenario. Items where the test was narrow (e.g., tested at 22M but might work at 1.5B base) or the implementation was incomplete (e.g., GaLore’s optimizer state) or that need future infrastructure (e.g., int8 matmul kernels) get FLAGGED, not deleted. The flag records: “tested at config X, didn’t see win, not in default recipe, here’s when it’d help.”

The convict-with-deletion list is short. Most items become FLAG.

The audit is informed by the project’s north star: on-device agent models on Apple Silicon + Chrome. Techniques are evaluated against “does this help build/train/run/serve an agent-shaped model on a Mac or in a browser?” — not “does this exist in the literature?”

After this audit lands, the codebase shrinks from ~28K lines to ~16-18K lines of Swift, the CLI from ~40 flags to ~12, and the “choose-your-own-adventure” surface area collapses into ONE curated recipe per capability.


TL;DR — revised under the conviction bar

StatusCountRationale
🟢 KEEP (default recipe)~28Demonstrated value at our scale or required for HF interop
🟡 FLAG (kept in code, not in default)~30Tested narrowly, not convinced useless. Conditions for usefulness documented.
🔴 DELETE (convinced useless)0-2Almost nothing meets this bar. The audit’s job is HONESTY, not aggression.

Most items get FLAGGED with: (a) what we tested, (b) what we saw, (c) when this would actually help. The code stays in the repo with a clear note in the source. Users opting into specialist training can revisit any item.


🟢 KEEP — these are the curated defaults

Training

ItemWhy keptMeasured evidence
AdamW optimizerDefault, most reliableOutperformed Lion/Sophia/Muon/Adafactor in 200-step tests
bf16 dtypeMemory + range win over fp16/fp32Industry standard; matches flagship training
Cosine LR + warmupIndustry standardUsed in all flagship training runs
Gradient clippingCheap stability leverPrevents bf16 blowups; no measured downside
Gradient checkpointingReal memory unlock at scaleBehemoth B=4 ctx=1024: 27.7GB → 17.8GB (−36%), loss equivalent
Sample packing for SFT10× variance reductionCoV(length·freq) 0.582 → 0.061 measured
Persistent token cache10-30 min saved per re-runSpeedup measured in practice
CPU speedup bundle (compile+accum+QoS+prefetch)+36% step/s on cosine+accumMeasured: 5.0 → 6.8 step/s on small B=16

Tokenization

ItemWhy keptEvidence
BPE via smollm2 (49k vocab)Modern decoder-only standardUsed for all real-text training
Byte-level vocab=256Educational + small browser modelsPowers the entire browser gallery
HFTokenizer wrapper (swift-transformers)HF interopLoads Llama, Qwen, etc.

Alignment

ItemWhy keptEvidence
SFT with response maskingReal instruction tuningChatML, Alpaca, Llama, plain templates work
DPOReal preference learningSmoke tested; loss converges
SimPO½ DPO memory at equivalent qualityReference-free; preferred default
ORPOMerges SFT + DPO in one passSaves a stage
KTOSingle-side feedback (thumbs up/down)Useful when paired data is scarce

PEFT (fine-tuning)

ItemWhy keptEvidence
LoRAThe base — many users will want itStandard, well-tested
DoRA5-10% better than LoRA at same rankVerified in smoke run
LoRA-FA (frozen A)2× smaller adapter at equivalent qualityHalves trainable params; demonstrated
LoRA+ (B-LR multiplier)Free win, no quality lossStandard recipe; verified
NEFTuneOne-line ~5% SFT winPer paper; smoke tested
Adapter file format (.lora I/O)Round-trip safetyRequired for save/load
Multi-LoRA compositionCompose multiple adaptersLoraCompositionHF.swift

Inference / sampling

ItemWhy keptEvidence
KV cache2.2× decode speedupMeasured: 470 vs 209 tok/s on flagship
KIVI int8 KV4× cache memory, greedy-lossless100% greedy-prefix match vs fp32 on flagship
Prefix cachingSystem prompt reuseDirect win for agent multi-turn
StreamingLLM sinkArbitrary-length decodeQuality preserved at 500 tokens
Speculative decoding (vanilla draft)2-4× decode at no quality costStandard technique; works
HF model loading (Llama family)Real interopLoads Qwen, Llama, Mistral, Phi out of box
AWQ readerLoad any AWQ-quantized HF modelMechanical; works
ANE Core ML inference path3-10× sampling on suitable modelsMeasured: 365 tok/s on Shakespeare via Core ML
OpenAI-compatible HTTP servelm-eval-harness compatibility + agent gatewayReal curl-tested

Eval / bench

ItemWhy keptEvidence
tinygpt eval (BPE-aware)Real perplexity measurement4.71 on flagship matches training-time val
tinygpt bench (TTFT/ITL/RSS/power)Bench360-modeled inference benchmarkReal numbers: 1.91ms TTFT, 794 tok/s on Shakespeare
tinygpt score-bench + manifest patcherBrowser leaderboard pipelineEnd-to-end working
lm-evaluation-harness HTTP adapterWire to standard quality benchmarksOpenAI-compatible serve verified curl-tested

Quality

ItemWhy keptEvidence
40 XCTestsReal CI gateAll pass; covers Manifest schema, KVCache parity, LoRA round-trip, crash recovery
swiftformat config + CI lintCode-quality gate0 violations on 76 files
Crash-recovery testsResume determinism + atomic saveSubprocess SIGTERM-race verified
GitHub Actions CIMac + Ubuntu runners on every PRReal, in use

Infrastructure

ItemWhy keptEvidence
Atomic save-every + --resumeReal crash recoveryDemonstrated by SIGINT pause of v5 mid-training
OOMGuard pre-flight memory checkAborts doomed configs cheaplySaved several launches in this session

Web playground

ItemWhy keptEvidence
WebGPU + WASM training in browserThe unique educational hookReal gallery models trained in-browser
Dynamic [slug].astro doc routeAll docs web-visible67 pages built in 1.7s
Leaderboard pagePublic scoring surfaceReal scored entries

🟡 EXPERIMENTAL — move to experimental/, keep accessible

Interesting, educational, or might-be-useful-later. Stays in the codebase under --experimental-* flags or experimental/ subdirs.

ItemWhy experimentalFuture use
MoE (Switch + Mixtral dense)Paper reimplementation; pedagogicalBecomes useful when scatter_add lands
Distillation (Hinton KL+NLL)Standard technique we never used at scaleLikely on the agent recipe — distill from Qwen-7B to 1.5B agent target
Magpie synthetic data generationUseful when we need agent training dataGenerate agent traces from Claude/GPT
Evolution Strategies (ES)Research curiosityUseful if we explore RL alternatives
Tuned lensEducational interp toolPart of “watch your model think” UX
Logit lens, attention heatmap, activation patching, per-layer ablationInterp tools — already documented as educationalKeep in playground for demonstrating
YOCOHalves KV cache at long contextBecomes critical at >8k context for agent histories
Sliding window attentionBounded attn at long contextSame — useful for very long agent sessions

🟡 FLAG — kept in code, not in default recipe

Each FLAGGED item stays in the repo with an // AUDIT FLAG: tested at X, didn't see win, useful when Y comment at the entry point. The CLI flag remains available under --experimental-* or stays untouched if removing it would break compatibility. The point: no work thrown away, honest record of what was tested and what wasn’t.

Optimizer alternatives — FLAG all 4

ItemWhat we testedWhat we sawWhen it’d help
Lion200 steps, tiny presetLagged AdamW (3.18 vs 2.62 loss)Lion’s whole point is convergence at >1k steps. Untested at scale.
Sophia200 steps, Sophia-light variantSlightly behind AdamW per stepWe shipped the EMA variant, not full Gauss-Newton. Real Sophia might help.
Muon200 steps, tiny preset5.2 vs 16.3 step/sNewton-Schulz overhead dominates at small scale; might pay off at 1.5B+
Adafactor50 steps, huge preset2× slower per step; ⅓ optimizer state memMemory savings matter for training BIG models on a Mac, not at 22M-100M

Architecture variants — FLAG all 5

ItemWhat we testedWhat we sawWhen it’d help
DiffAttentionSmoke train at 22MNo measured benefitPaper claims gains at >100M; long-context reasoning specifically
MoD (soft routing)Soft variant onlyNo compute savingsRequires hard top-K + scatter_add (MLX-Swift doesn’t have it yet)
MTPSmoke trainMarginal regularizationDeepSeek-V3 uses it at scale (37B active); could matter at >7B base
ALiBiNot used at long contextUntested for extrapolationUseful for extrapolating beyond train context; agent histories could trigger this
Sliding window attentionUntested at ctx >4kn/aUseful when agent context exceeds train ctx — directly relevant to agents
YOCOVerified -51% KV cache-12% decode at short ctxWins materialize at long ctx (>8k); agent histories will hit this

Stability tricks — FLAG all 3

ItemWhat we testedWhat we sawWhen it’d help
DeepNormUntested in flagship runsn/aPaper-stated: needed at depth ≥100; useless at 12 layers but cheap to keep
Layer-wise LR decayNever wired to a real runn/aStandard in fine-tuning — keep for specialist agent training
Embedding RMSNormv4 / v5 training (with)Step-1 spike + small liftModern Llama uses it; net positive unclear from our brief runs

Training-time exotic — FLAG both

ItemWhat we testedWhat we sawWhen it’d help
GaLore100-step runLoss descends; theoretical memory unrealizedAdam state still full-rank in our impl. Real memory win needs optimizer-state surgery (queued).
BPE-dropout100 steps+0.2 nats loss (regularization cost)Robustness at scale; needs careful eval to validate

PEFT variants — FLAG all 6 (was DELETE)

ItemWhat we testedWhat we sawWhen it’d help
VeRA30 steps512× fewer trainable paramsKiller for agent factory — swap many specialists fast at near-zero adapter cost. Revisit.
LoftQ30 steps simulated int4Init computes correctlyReal win needs int4 BASE model (we don’t have one yet)
AdaLoRA30 stepsImportance scoring trainsNever wired to actual rank reallocation — incomplete impl
RsLoRA30 stepsα/√r scale appliedMarginal at r=4-16; helps at r >64
PISSA init30 stepsFaster early convergenceUseful default for SFT runs — could absorb into KEEP later
LayerDrop30 stepsDegrades fine-tune qualityPretraining-time regularizer at depth >24; useless at shallow fine-tuning

Quantization — FLAG all 4

ItemWhat we testedWhat we sawWhen it’d help
SmoothQuantCalibration pass worksFloat-identity at zero matmul gainBecomes critical when int8 matmul kernel lands
HQQ storage-onlyQuantize/dequantize roundtripFile size shrinks, runtime notNeeds packed-int4 matmul kernel
GPTQ from-scratchQuantized flagship0.1064 rel error; loads + samplesAWQ reader covers HF case; GPTQ from-scratch is for OWN model export
QAT (int4/int8)30 stepsLoss descends, qat-err boundedMandatory for deploying int4 specialists with reasonable quality

Pruning — FLAG unstructured + structured-head, KEEP layer pruning

ItemWhat we testedWhat we sawWhen it’d help
Unstructured pruning (FLAG)50% sparsityGzip -38%No wallclock win without Metal sparse matmul; download size only
Structured head pruning (zero-out) (FLAG)Drop 4/8 headsQuality degrades; shape preservedReal value needs physical removal (queued as 200-LOC follow-up)
Structured layer pruning (now KEEP)Drop 2/12 layers9.6M → 8.0M, coherent samplesActually changes topology, real wallclock win — moves to KEEP

Speculative decoding heads — FLAG both

ItemWhat we testedWhat we sawWhen it’d help
Medusa heads50 head-train steps21-23% acceptanceReal production needs 10k+ training steps; correct code
EAGLE-250 head-train steps26.5% acceptanceSame as Medusa — sustained training to hit ~60-85% accept

🔴 DELETE — convinced useless (with this bar: maybe nothing)

Under the strict conviction bar, I’m not confident anything in the audit is convict-with-deletion useless. Every technique has a scenario.

The honest move: DELETE list = empty for now. The codebase stays roughly its current size. The audit’s contribution is the FLAGS — clear notes per technique about what we tested, what we saw, when it would help.

If you want a smaller binary or cleaner CLI, the right move is CLI curation (hide flags under --experimental-*), not source-code deletion. Source-code is cheap to keep; the maintenance cost is in keeping it tested + documented, which the FLAG annotations address.


What the CLI looks like AFTER the cuts

Current state:

tinygpt train --preset huge --tokenizer ... --dtype bfloat16 \
    --optimizer adamw --grad-checkpoint \
    --z-loss-weight 1e-4 --embedding-rmsnorm \
    --galore-rank 0 --bpe-dropout 0 --qat 0 \
    --moe-experts 1 --mtp-horizons 1 \
    --diff-attn --mod --yoco --alibi --sliding-window 0 \
    [+ 20 more flags]

After cleanup:

tinygpt train <corpus>          # AdamW + bf16 + cosine + clip — recipe defaults
  --preset huge|mega|behemoth
  --tokenizer <hf-dir>
  --grad-checkpoint              # for mega+ models
  --resume <path>
  --save-every N

tinygpt finetune <base> <data>  # DoRA + SFT — recipe defaults
  --rank R
  --lora-fa                      # halve params if you want

tinygpt align <base> <prefs>    # SimPO — recipe default
  --loss-type dpo|simpo|orpo|kto # if you really want to pick

tinygpt sample <model>          # KV cache + KIVI int8 + speculative — defaults
  --prompt "..."
  --tokens N

tinygpt quantize <model>        # AWQ → int4 — recipe default
  --bits 4|8

# All other techniques: --experimental-X for the alternatives

Revised execution plan (conviction-bar version)

  1. Draft this doc — done
  2. Per-FLAGGED-technique inline annotation — add // AUDIT FLAG: block at each entry point in source, with what-we-tested / what-we-saw / when-it’d-help. ~1-2 days mechanical.
  3. Default-CLI curationtinygpt train etc. = curated recipe with no flags needed; FLAGGED features move to --experimental-*. ~2 days.
  4. Help text + landing page rewrite — preach the ONE curated recipe; “Advanced/experimental” gates the rest. ~2 days.
  5. No source-code deletion this round — keep everything; the FLAG annotations are the documentation.

Estimated effort: 3-5 days focused. Bias toward honest documentation over aggressive deletion. Source-code is cheap; the cost of accidentally deleting something useful is high.

After this curation, the codebase is ready for the on-device agent model factory focus. The curated tools above are the recipe for the debugger / code-reviewer / SQL-writer / etc. specialists. FLAGGED tools remain available when a specialist’s training shows they help (e.g., VeRA for many-specialist factory, MoD when scatter_add lands).