Model Technical Report
A 1.5B on-device model built for vocabulary teaching: a Qwen2.5-1.5B-Instruct base, domain-finetuned end to end with diverse-corpus SFT and DPO on real failure negatives — with all training done locally on Apple Silicon. Every number on this page is reproducible.
Training window 2026-09-07 ~ 09-09 · Apple Silicon (48GB unified memory, MPS backend, no CUDA)
The value of small-model fine-tuning (+25pp hit rate at the same scale, JSON 82%→100%) and scale-independent zero-shot failure (7B zero-shot: 39.72% hit / 0% JSON) together form the complete evidence chain for why domain fine-tuning is necessary. DPO is statistically on par with SFT (the difference lies within the n=90 noise band), with steadier behavioral convergence and zero reward-hacking regressions — it validates the safety of the alignment recipe, not metric-chasing.
01 · Task
Why 1.5B: it is the smallest engine that passes the quality bar in testing. The target form factor is in-browser on-device inference — works offline, zero marginal cost, and student data never leaves the device.
Every due review word must be embedded naturally in the story
An A2 learner never meets B2 vocabulary
Readable in under a minute per session
Output can be consumed programmatically as-is
02 · Data
The v1 template corpus (510 entries, word-swap skeletons) taught SFT nothing but template memorization — the inflated 98.33% hit rate was itself evidence of overfitting, and the uninformative preference pairs left DPO spinning idle. v2 was rebuilt from scratch.
03 · SFT
Target-word slot injection, CEFR boundary control, and structured JSON output. Control group: v1 template data converged in 93 steps at loss 0.029 — such a low loss is itself hard evidence of template memorization; v2's loss of 0.37 is the learning curve of real generalization.
04 · DPO
Statistically on par with SFT with zero regression — DPO's value lies in behavioral robustness (which shows under distribution shift), not benchmark gains. All four acceptance checks passed, proving the recipe neither idles nor reward-hacks.
⚠ Engineering postmortem · the v1 DPO no-op incident
The first DPO run trained for 1 hour 47 minutes with zero weight change (adapter MD5 byte-identical to SFT). Two root causes:
Fix: merge → fresh LoRA → NoOpGuard fail-fast. Both root causes are fixed and accepted in v2. Also note: the DPO adapter must be loaded on top of the merged base+ΔSFT model; attaching it to the raw base only reaches ≈base-level scores (63.89% — a trap verified by measurement).
05 · Engineering
Completing the full real training pipeline on a 48GB unified-memory Mac without CUDA took a whole set of platform-level workarounds. The segmented-resume scheme is now codified as an orchestrator plus watchdog, running hundreds of steps unattended.
| Problem | Symptom | Root cause & fix |
|---|---|---|
| Linear memory leak | Memory grows ~1.4GB/step in long single-process runs, independent of precision, batch size, grouping, or GC frequency | Platform-level issue in the torch MPS backend → segmented resume: checkpoint and exit every 117/128 steps, relaunch a fresh process from the checkpoint, orchestrator loops until done |
| Memory-cap denominator misunderstanding | Assumed 0.60=28.8GB; actually 22.46GB | The denominator of set_per_process_memory_fraction is the system-recommended 37.4GB, not the physical 48GB → recompute the watermark against the true denominator |
| Variable-length fragmentation | Tensor shapes differ every step; allocator cache reuse is zero | batch=1 + continuously distributed lengths (636~891 tok) → fixed-length padding (896, zero truncation) |
| bf16 autocast leak | bf16 adds a net 1.2GB per step | torch 2.5.1 MPS autocast → dropped bf16 for fp32 (no measured speed difference) |
| Crash fallback | Process dies on OOM | Hard ceiling guardrails → checkpoint every 40 steps + watchdog auto-resume; loss bounded to ≤40 steps |
06 · Benchmark
All metrics are computed by an automated evaluator on the model's real generations (temperature=0); evaluation details and per-prompt outputs live in the repo under outputs/eval/. Target-word hit = share of due review words naturally embedded in the story; out-of-level = share of vocabulary beyond the target CEFR level.
| Model | Hit ↑ | Out-of-level ↓ | JSON ↑ | FKGL | Notes |
|---|---|---|---|---|---|
| Qwen2.5-1.5B base (pre-finetune) | 63.06% | 0.17% | 82.22% | 13.5 | Baseline |
| + domain SFT (v2 corpus) | 88.06% | 0.01% | 100% | 9.82 | Generalization split · this product |
| + DPO preference alignment (v2) | 87.78% | 0.01% | 100% | 9.94 | On par with SFT, steadier behavior |
| Qwen2.5-7B zero-shot | 39.72% | 0.07% | 0% | — | 85/90 degenerate repetition |
| Qwen2.5-7B zero-shot (anti-degeneracy leniency) | 41.67% | 0.12% | 0% | 103.4 | Sampling parameters can't save it |
| DeepSeek-V3 zero-shot (teacher) | 97.78% | 0.01% | 100% | 10.38 | Commercial flagship reference |
| Teacher / Oracle | 98.33% | 0.22% | 100% | — | Upper bound |
* The 7B zero-shot failure is independent of sampling parameters: a rerun with anti-degeneracy leniency still scored 41.67% / 0% JSON. Fine-tuning lets the 1.5B approach the DeepSeek-V3 teacher on the same task (88.06% vs 97.78%; the remaining gap is mainly rhetorical quality in long, complex sentences) and far surpasses an unfine-tuned model 4.7× its size.
07 · Artifacts
| Artifact | Location | MD5 |
|---|---|---|
| SFT v2 adapter (295MB) | outputs/wordlink_edge_sft_v2/ | 1d924802e4e298ae5e8086f0bea6fca3 |
| DPO v2 adapter | outputs/wordlink_lexiconstrain_dpo/ | 73d7d16f93985f4386cd7566a7c4c50d |
| SFT-merged base | outputs/wordlink_edge_sft_v2_merged/ | — |
| Training manifest | outputs/wordlink_edge_sft_v2/training_manifest.json etc. | — |
| Evaluation metrics ×6 | outputs/eval/*_metrics.json | — |
| Training data | data/wordlink_*_train_v2.jsonl + data/bailian/ | — |
08 · Roadmap
near-miss negatives (almost-right outputs off by a single word) + a larger test set (500 prompts) + multi-seed confidence intervals
MLC/WebLLM 4-bit export (compile_mlc.sh, requires the mlc-llm toolchain) or a one-click GPU-server pipeline
Mixed generation with a second teacher to improve stylistic diversity