---
sidebar:
  order: 202606060
---

# Strategy session — what posttrainllm actually is, what's possible on a Mac

**Date:** 2026-06-06
**Premise:** posttrainllm shouldn't be framed as "small models beat large ones on
benchmarks." The real thesis is: **a Mac app where individuals build a
specialist for their specific task — bring data, pick a teacher, ship a
fast/cheap/comparable-quality model.** Distillation, fine-tuning, and
quantization are the toolkit that makes this actually work.

This doc captures the strategic frame, the memory math, and the product
roadmap implications.

## What posttrainllm is, restated

> **"A Mac app where you bring data, pick a teacher, and ship a
> specialist that runs 15-100× faster than the teacher with comparable
> quality on your specific task."**

Not framework. Not benchmark contender. Not research project. A **platform
for individual task-specialization on consumer hardware.**

The benchmark-beating angle is a *demo* of what the platform can do — not
the product itself.

## Success criterion (refined)

The user explicitly clarified the bar: **comparable quality + 20-150× speed
+ 150× less memory** is a complete win. Then optimize performance further
from there.

That maps to a 3-axis Pareto win:

| Axis | Required against teacher |
|---|---|
| Quality | ≥ 90% of teacher on the specialized task |
| Speed | ≥ 10× tokens/sec on the same Mac |
| Memory | ≤ 1/100 the teacher's footprint |

If a specialist hits this triangle, ship it. Headline-grade "beats teacher
on absolute quality" is a bonus, not a requirement.

## Mac memory math — what's possible at each scale

The 3B "limit" everyone repeats applies *only to pretraining from scratch.*
Different operations have radically different memory footprints, and the
practical ceiling jumps significantly as you go down this table:

| Operation | Cost per param | 48 GB Mac ceiling |
|---|---|---|
| Pretrain from scratch (Adam bf16) | ~6-8 bytes | ~3-4B |
| Full fine-tune (Adam bf16) | ~6-8 bytes | ~3-4B |
| **LoRA fine-tune** | ~2 bytes base + tiny delta | **~13-15B** |
| **QLoRA** (4-bit base + LoRA) | ~0.5 byte base + tiny delta | **~30-40B** |
| Distillation (teacher → student) | Teacher inference + student training (sequential or split) | Teacher up to 30B+; student up to 13B (LoRA) |
| Inference bf16 | 2 bytes | ~20-25B |
| Inference Q8 | 1 byte | ~40B |
| **Inference Q4** | 0.5 byte | **~70-80B** |

**Implications for what the platform should offer:**

- "Train from scratch on your Mac" — only works for ≤3B. Limited niche.
- "Fine-tune a pretrained model on your Mac" — works up to ~13B via LoRA
  (free, fast, no quality loss), up to ~30B via QLoRA (small quality
  trade for memory).
- "Distill from a larger teacher" — teacher can be a downloaded ≤30B model
  OR an API call (Claude, GPT-4). Student is whatever the user wants.
- "Quantize and ship" — final output can target up to 70B at Q4 for
  consumer inference, but most specialists will be ≤7B for real speed.

The real product story is **not** "train tiny models from scratch."
It's **"fine-tune or distill any model up to ~30B on your Mac for your
specific task."**

## Why 4B / 5B / 6B models barely exist (the gap)

Open-weights ecosystem clusters at 1B / 3B / 7B / 13B / 30B / 70B. The
4-6B niche is empty. Reasons:

1. **Consumer GPU memory tier alignment.** 4 GB → 1B; 8 GB → 3B or
   7B-Q8; 16 GB → 13B-Q8. A 5B model awkward — wastes 8 GB headroom,
   doesn't reach 13B-tier quality. Labs pick sizes that match buyers'
   actual hardware.
2. **Training-budget round numbers.** Cluster commit goes 3B → 7B (2×
   compute); 5B is "would rather just do 7B." Economics, not physics.
3. **Mistral 7B anchored the "quality sweet spot."** Every lab now
   benchmarks against 7B to be in the conversation.
4. **Differentiation thin.** 5B isn't meaningfully better than 3B for
   most tasks, worse than 7B. No clean marketing story.
5. **Recipe inheritance.** Most open labs use a Llama-style scaling
   recipe that only varies depth/width to hit Llama-class sizes.

**This is an opportunity, not a constraint.** Distillation lets you
target any size including 4-6B. A posttrainllm-Mega-tuned variant at 5-6B
would slot into "better than 3B, faster than 7B, fits 8 GB GPUs at Q8."
Niche worth investigating once the base recipe works.

## The realistic Mac-specialist sizes

| Student size | Memory (Q4 inference) | Train path on Mac | Likely speed vs 7B teacher |
|---|---|---|---|
| 22M (posttrainllm-Huge — what we're training) | ~12 MB | Pretrain from scratch ✓ | ~50-100× |
| 76M (Mega) | ~38 MB | Pretrain from scratch ✓ | ~30-50× |
| 1B | ~500 MB | Pretrain from scratch or fine-tune ✓ | ~10-20× |
| 3B | ~1.5 GB | Pretrain from scratch (tight) or fine-tune ✓ | ~5-10× |
| 7B | ~3.5 GB | LoRA fine-tune only on Mac | ~2-4× |
| 13B | ~6.5 GB | LoRA fine-tune (tight) | ~1-2× |

The sweet spot for "user's specialized task on their Mac" depends entirely
on the task. Routing/intent → 22M is plenty. Function calling → 76M-1B is
the band. Code completion → 3-7B. The platform's job is to **pick the
right size automatically** based on user data + task type.

## What's already built (status as of 2026-06-06)

| Component | Status |
|---|---|
| Mac app shell (Sample/Train/Fine-tune/Interp/Server tabs) | ✅ shipped |
| CLI: train, sample, sae, eval-*, judge, serve, to-coreml, to-safetensors, gguf-extract | ✅ shipped |
| Multiple presets (Tiny/Small/Huge/Mega) | ✅ shipped |
| HF model downloader (for teacher selection) | ✅ shipped |
| OpenAI-compatible serve (with batched-prompt fix shipped today) | ✅ shipped |
| GGUF + CoreML + safetensors exporters | ✅ shipped |
| 3-view eval comparison (by step/model/task) | ✅ shipped |
| Browser eval-leaderboard + sae-timeline viewers | ✅ shipped |
| Distillation recipe doc | ✅ shipped (today) |
| Quantization (Q5/Q6/Q8) | ✅ shipped |
| LoRA fine-tuning | ✅ shipped (in app's Fine-tune tab) |
| Eval pipeline E0/E1/E2/E3/E5/E7/E8 | ✅ shipped (E0/E3 mine, rest from elf) |

## Working principles (clarified 2026-06-06)

| Principle | Operational meaning |
|---|---|
| **Capture everything, execute by ROI** | Strategy doc holds the full surface; Tier 1-4 backlog ranks by ROI; ideas don't get lost when not yet acted on |
| **One canonical best per slot** | Not 20 distillation variants; one. Not PPO+DPO+GRPO competing; the consensus best per axis. |
| **AI coding flattens effort estimates** | "5 min vs 1 hour" — choosing the right thing matters far more than estimating effort precisely. Don't waste decision time on small effort differences. |
| **Outsider perspective is a feature** | The platform's product framing is being shaped by non-ML-insider thinking. Defers to expert advice on implementation; trusts gut on framing/strategy. Use advisor when committing. |
| **Adopt OSS only when it's the best; reinvent when we materially improve (10%+ quality/perf/integration)** | Default isn't "always adopt." Default is "adopt unless reinvention gives a real, measurable boost." If we're reinventing for nothing, clean it up immediately. |
| **Verify existence before claiming gap** | Before adding any item to a "gap list," grep the dispatch table + source tree. Don't plan to build what's already there. (See 2026-06-06 audit correction — I claimed ~7 gaps that were already shipped.) |
| **Results first; architecturally interesting later** | (Clarified 2026-06-06 EOD.) The user explicitly said: "we will get architecturally interesting. but we need results." The platform's first job is shipping working specialists that beat baselines. BLT-style adaptive tokenization, MoE, Mamba hybrids, music gen, Apple Intelligence integration are all interesting — but they DON'T ship until A1 + Distillation + Eval-tab + Templates + QLoRA all land first. Architecturally-interesting items move to Tier 4 unless directly required by a "results" item. |

## OSS audit — what to adopt vs build

Honest read: **~70% of the Tier 1 backlog has strong existing OSS to adopt.** Work shrinks from "implement from scratch" to "adapt + integrate." Updated effort estimates assume adoption.

### Tier 1 gaps × OSS sources

| Capability | Adopt from | Build effort |
|---|---|---|
| Distillation feature | TRL distillation patterns | 2 days (was 3-4) |
| QLoRA | mlx-lm 4-bit + LoRA primitives (compose, don't rewrite) | 2 days (was 3-5) |
| DPO | TRL `DPOTrainer` loss + ref-model trick (~20 lines) | 1-2 days (was 2-3) |
| Constrained decoding | llama.cpp GBNF format (text grammars, no engine to write) | 2 days (was 2-3) |
| KV cache in serve | Our own `sample` command already has it — port internally | 1-2 days |
| Safetensors loader in serve | mlx-lm architecture mappers (Llama/Qwen/Mistral/Phi/Gemma ready) | 2-3 days (was 3-5) |
| `posttrainllm prep` data CLI | `datatrove` (HF) patterns + our existing MinHash + quality filter | 2 days (was 2-3) |
| `posttrainllm eval-custom` | lm-eval-harness YAML custom-task spec | 1 day (was 2-3) |
| TIES model merging | `mergekit` core algorithm (~100 lines) | 1-2 days (was 2-3) |
| Q4_K_M quantization | llama.cpp dequant code | 1-2 days |
| Tokenizer trainer | HF `tokenizers` (Rust crate) wrapper | 2 days (was 2-3) |
| Domain-adapt SFT | Config preset on existing train loop | 1 day (was 1-2) |

### Tier 2 modality OSS sources

| Modality | Adopt from |
|---|---|
| VLM | MLX-VLM (mlx-community) — Mac-native LLaVA port |
| Whisper | Apple's `ml-whisper` (CoreML, ANE-accelerated) |
| Image gen | Apple's `ml-stable-diffusion` (SDXL Turbo / SD 1.5, ANE-accelerated) |
| TTS | Kokoro-82M (tiny, open, recent) OR F5-TTS |
| Embeddings | sentence-transformers framework + BGE-M3 weights |
| Reranker | BGE rerankers (BAAI) |
| Reward model | TRL training pattern |
| Music gen | MusicGen-small (Meta, open) |

### Multi-model architectures OSS

| Pattern | Adopt from |
|---|---|
| LoRA hot-swap | `peft` adapter registry pattern |
| RAG | LlamaIndex patterns (don't take whole framework) |
| Reranking | BGE rerankers + MTEB eval patterns |
| Phone-a-friend | No specific OSS — build (it's 50 lines) |

### What's actually ours to write from scratch

The integration glue and product UX:
- Local-teacher labeling pipeline (no one has this at this scope)
- Unified `posttrainllm prep` CLI wrapper
- "Create Specialist" app wizard
- Templates for common patterns (router, classifier, JSON-extractor, etc.)
- Quality predictability heuristics
- Mac-specific Apple Intelligence / Shortcuts integration

The rest is **adapt and integrate**, not invent. With this discipline, the Tier 1 estimate revises from 4-6 weeks → **~3 weeks of focused work.**

### Audit as a recurring practice

For each new gap that surfaces in future sessions:
1. **First action**: grep GitHub / awesome-ml-X lists for prior art
2. **Second action**: read the closest 2-3 OSS implementations
3. **Third action**: decide adopt / fork / wrap / build, in that order of preference
4. **Only build from scratch** if nothing usable exists OR the license precludes adoption

The session-doc gap-table format above should be **filled in** for every new capability proposal, not skipped.

## What's missing — the disciplined backlog

### Tier 1 — text-only platform completion (CORRECTED 2026-06-06 after dispatch-table audit)

**Earlier draft of this list claimed ~7 gaps that turned out to be already shipped.** Corrected list below; verify any claimed gap by `grep 'case "X"' native-mac/Sources/TinyGPT/TinyGPT.swift` before adding.

**Already shipped (DO NOT re-plan):** `distill`, `dpo`, `gptq`, `hqq`, `prune-unstructured`, `prune-structured`, `bon`, `agent`, `cloud`, `escalate` (phone-a-friend), `dedupe`, `rome`, `memit`, `patch`, `causal-trace`, plus `ConstrainedGen.swift` (804 lines for constrained decoding) and `KVCache.swift` (885 lines).

**Actual remaining gaps (verified by absence in dispatch / source tree):**

| Gap | One-best impl | Effort (with OSS adoption) |
|---|---|---|
| **QLoRA** | 4-bit base + LoRA training recipe (primitives exist: `gptq`/`hqq` + LoRA — just wire them together) | 2 days |
| **TIES model merging** | Port from mergekit (~100 lines algorithm) | 1-2 days |
| **Safetensors loader for serve** (foreign architectures) | Adopt mlx-lm's architecture mappers | 2-3 days |
| **KV cache wired into `serve`** | `KVCache.swift` exists; needs serve integration | 1-2 days |
| **`posttrainllm prep`** wrapper | Bundle existing `dedupe` + `quality-filter` + extract + format normalize | 1 day |
| **`posttrainllm eval-custom`** | Custom-task YAML on top of existing `run-lm-eval` | 1-2 days |
| **Q4_K_M quantization level** | Port from llama.cpp | 1-2 days |
| **Tokenizer trainer** | Wrap HF `tokenizers` Rust crate | 2 days |
| **Domain-adapt SFT mode** | May already be a `train` flag — verify before building | 0-1 day |
| **App-native "Create Specialist" wizard** | Composes existing CLI subcommands behind GUI | ~1 week |
| **Templates for common patterns** | Router, classifier, JSON-extractor, tool-caller, summarizer | ~1 week |
| **Quality predictability** | Heuristics from prior runs | hard, iterative |

**Revised Tier 1 effort: ~2 weeks of focused work.** Much closer to done than original 4-6 week estimate suggested.

## Reinvention cleanup candidates (audit before removing)

The flip side of "adopt OSS only when best": **audit existing code for places we reinvented without payoff.** Candidates (need verification before action):

| File / area | Possible OSS alternative | Verdict |
|---|---|---|
| `ExtractorData.swift` (525 lines) + `GitHubCorpus.swift` (525 lines) | `datatrove` (HF) | **Investigate** — if our impl predates datatrove and offers no Mac-specific advantage, migrate |
| `Score.swift` (782 lines) | overlaps with `eval-compare` / `run-lm-eval`? | **Investigate** — may be a predecessor that should consolidate into the newer eval stack |
| `Serve.swift` HTTP layer (1258 lines) | swift-nio / Hummingbird / Vapor | **Keep** — requires MLX integration + Ollama + OpenAI + serial inference queue. No good Swift HTTP framework fits. |
| `GGUFReader.swift` (558 lines) | `gguf` crate, llama.cpp's reader | **Keep** — loads directly into MLX tensors; no Swift+MLX alternative |
| 3 Rust crates (parquet, hf-downloader, sandbox) | arrow-rs (used), hf-transfer crate, no Mac sandbox alt | **Keep all three** — parquet uses arrow-rs (correct); hf-downloader replaces Python (justified for speed); sandbox is Mac-specific |

**Highest priority cleanups to investigate this week:** `Score.swift` consolidation into the newer eval stack; `ExtractorData.swift` vs datatrove migration analysis.

### Tier 2 — multimodal (user-confirmed priorities: vision + voice; image gen; video defer)

Each modality is real engineering — substantial scope, not a knob. Ordered by ROI.

| Modality | The one best path | Effort | Notes |
|---|---|---|---|
| **Vision input (VLM)** | **LLaVA-style**: CLIP-ViT encoder → projection → LLM body. LoRA-train the projection + LLM. | ~2-3 weeks | Highest-ROI modality after text. Unlocks specialists for "describe screenshots / extract from PDFs / classify designs / chart QA." |
| **Speech-in (Whisper)** | Bundle CoreML-compiled Whisper-small as audio frontend → text token stream → existing LLM specialist | ~1 week | Easiest win. Apple's own apps already use this. |
| **Image generation** | SDXL or SD 1.5 + LoRA training via Apple's `ml-stable-diffusion` (CoreML) | ~3-4 weeks | Well-trodden Mac path. LoRA fine-tuning for personal style is the killer feature. |
| **TTS / voice cloning** | F5-TTS or XTTS — open weights, voice-cloning support | ~2 weeks | Real accessibility / agent feature. |
| **Video understanding** | Frame sampling (1 fps) → run VLM on each → aggregate | ~1 week after VLM | Trivial once VLM lands. Loses temporal info but useful. |
| **Embeddings** | sentence-transformers-style — small encoder, contrastive training | ~3-5 days | Useful for RAG / retrieval specialists. |
| **Video generation** | Stable Video Diffusion / AnimateDiff / CogVideoX-2B | ~3-4 weeks | **Punt to v3+.** Local quality far below Sora/Veo/Kling; SOTA video needs datacenter GPUs. Not credible to ship in v1-v2. |

### Tier 3 — advanced (defer until Tier 1+2 land)

| Capability | When to revisit |
|---|---|
| Reasoning RL (GRPO / DeepSeek-R1 style) | Only if DPO + distillation + constrained decoding can't close gap on reasoning tasks |
| Mixture of Experts (MoE) | If a 4-6B MoE proves competitive with dense 7B at lower latency |
| Mamba / SSM hybrid | If long-context tasks need >8K tokens efficiently |
| AWQ smarter quantization | If GGUF Q4 quality insufficient for shipping |
| Pruning | Only if specific use case it solves better than quantization |
| **Music generation** (MusicGen / Stable Audio) | Tier 4 modality — real demand but not blocking the v1 platform |

### Tier 4 — explicitly out of scope (or skip / research-only)

| Capability | Why skipped |
|---|---|
| Video generation | Mac quality far below Sora/Veo/Kling; SOTA needs datacenter GPUs |
| 3D generation (DreamGaussian, Instant-NGP) | Niche; only add if target audience asks |
| World models (Dreamer-V3, GENIE) | Research-only; not consumer-facing |
| Diffusion language models | Research-only; not yet useful |
| Time series, graph neural | Different domain, not language-model adjacent |

## Judgment-family models (related but distinct from rerankers)

Beyond generating text, models can *evaluate* text. This unlocks self-refinement, RL data generation, automated eval, and quality gating. Should be a first-class capability slot:

| Model type | What it does | Output shape | Use case |
|---|---|---|---|
| **Judge** (LLM-as-judge) | Evaluate quality of a single output | Score + reasoning | Eval (✅ E7 shipped — pairwise + rate modes), preference data, feedback |
| **Reranker** | Score N candidates, return ranking | Numeric score per candidate | Best-of-N selection, search/retrieval |
| **Verifier** | Check if output is correct (hard signal) | Binary + reasoning | Math, code (compile+run), JSON schema validity |
| **Reward model** | Scalar reward for RL training | Single number | RLHF/DPO data generation. Lets DPO work without preference annotations — judge labels them. |
| **Critic** | Detailed critique for revision | Free-form critique | Self-refinement loops (output → critic → revised output) |
| **Constitutional / principle-based** | Judge against a set of rules | Pass/fail per rule | Safety, style, persona consistency |

**Status for our platform:** judge shipped (E7); the others are gaps. The one-canonical-best per slot:

| Slot | Recommended impl | Effort |
|---|---|---|
| **Verifier** | Task-specific hardcoded checkers (Python sandbox for code, JSON-schema validator, math eval) + a small learned classifier where rules aren't enough | ~3-5 days |
| **Reward model** | Distill a judge into a smaller faster scoring head (reuse the E7 judge as the data labeler) | ~3-5 days |
| **Critic** | LoRA on a small base model with critique-formatted training data, OR prompt a strong judge | ~3 days for prompt-based; longer for trained |
| **Reranker** | Small encoder-only model (BERT-style) trained on (query, candidate, score) triples | ~1 week |

These compose with the multi-model architectures below — e.g., generator → reranker → verifier → output is a high-quality production pattern.

## Multi-model architectures (how multiple models compose at inference)

A specialist doesn't have to be a single model. Several patterns compose multiple models for better quality, lower cost, or new capabilities:

| Pattern | What it does | Status |
|---|---|---|
| **Speculative decoding** | Small draft proposes N tokens; large verifies in one pass. Lossless ~2-3× speedup. | ✅ shipped (B14) |
| **Phone-a-friend / escalation routing** | Small tries; if low-confidence, escalate to large. Saves cost when easy queries dominate. | gap — serve-level addition (~3-5 days) |
| **Cascade / waterfall** | Multi-tier version (cheap → mid → expensive). Each tier handles what the previous couldn't. | gap (extension of phone-a-friend) |
| **Teacher-student distillation** | Big model labels offline; small serves inference. (Bulk of "build a specialist" recipe.) | recipe doc; Tier 1 build |
| **Self-consistency** | Same model N times with different seeds, vote. Free quality boost for math/reasoning. | trivial to add at serve |
| **Ensemble** | N different models in parallel, vote on output. N× cost for quality bump. | trivial |
| **Multi-agent / debate** | Models discuss until consensus. Slow but high quality. | research-y; defer |
| **Tool-augmented agent loop** | Model decides actions, tools execute, results feed back. Browser-use pattern. | A1 specialist enables this |
| **RAG** (retrieval-augmented) | Small model + retrieval over big corpus. "Phone a database." | needs embeddings (Tier 2) + retriever |
| **Hierarchical reasoning** | Planner breaks task → workers solve → coordinator aggregates | application-level |
| **Reranking** | Generator produces N candidates; reranker scores; best wins. | needs reranker model (small) |
| **Verification loop** | Generator → verifier → loop until valid. Math/code use this. | application-level |
| **Sketch + refine** | Small drafts; large polishes. Trades roundtrips for quality. | application-level |
| **LoRA hot-swap** | One base + many LoRA adapters, swap per task. One model serves many specialists. | gap — high-value addition |
| **TIES merging** | Weight-averaging multiple fine-tunes. Often beats any individual. | planned (Tier 1) |
| **Critic-actor** | Actor proposes, critic evaluates. RL inheritance. | research |

**Most valuable for our platform to add:** phone-a-friend / cascade (serve-level), LoRA hot-swap (one base, many specialists), reranking (small encoder for best-of-N selection). All ~3-5 days each.

## Structured output — beyond JSON

JSON is solved because its grammar is well-defined. **The same mechanism (grammar-constrained decoding) handles any format with a definable grammar.** Our Tier-1 "constrained decoding" slot should be **grammar-engine general**, not JSON-specific:

| Format | Grammar | Use case |
|---|---|---|
| JSON | built-in | tool calls, API responses |
| YAML / TOML | Lark grammars | config files |
| XML | grammar | legacy systems |
| **SQL** (per table schema) | schema-derived | text-to-SQL specialists |
| **Protobuf** (per .proto) | schema-derived | binary-format generation, RPC payloads |
| **GraphQL** (per schema) | schema-derived | query generation |
| Cron | small grammar | scheduling DSLs |
| LaTeX (math subset) | partial grammar | math notation generation |
| Markdown with required structure | grammar | structured doc generation |
| CSV / TSV (per schema) | row grammar | tabular output |
| HTML / JSX (constrained) | tree grammar | UI generation |
| Regex pattern enforcement | FSM-direct | phone numbers, dates, IDs |
| Bash / shell | iffy grammar | risky but possible |
| **Custom DSL** | user-provided grammar | domain-specific applications |

**Engine choice (one canonical):** GBNF (llama.cpp grammar format). Reasons: well-documented, expressible enough for any format above, ecosystem familiarity (llama.cpp users know it), text-based grammar files easy to ship. Alternative: xgrammar (NVIDIA, faster) or Outlines (Python, most flexible). Pick GBNF for ecosystem fit.

**For protobuf specifically:** the .proto file IS the grammar. Generator translates .proto → GBNF → constrained decoder that produces byte-perfect serializable protobuf. Feature, not research.

## Diffusion models — speed reality check

| Diffusion type | Status | Speed on Mac |
|---|---|---|
| **Image diffusion (fast variants — SDXL Turbo / Flux Schnell / LCM)** | production-ready | **1-2 sec per image** (1-4 denoising steps). Real-time-feeling. |
| Image diffusion (traditional, 20-50 steps) | available | 3-8 sec per image |
| Audio diffusion | available | ~1-2 sec for short clips |
| **Text diffusion** (Mercury Coder, LLaDA, DiffuLLaMA, SEDD) | early-commercial | **Mercury / Mercury Coder (Inception Labs, 2025)** is the famous example — claims 1000+ tok/sec on H100 by generating tokens in parallel via iterative denoising. Real demo. Open-weights stack still emerging; ecosystem (training tooling, evals) years behind autoregressive. **Status: keep watching, don't build yet.** Revisit when the first strong open-weights diffusion coder ships. |
| Video diffusion | (Tier 4 — skipped) | Slow; quality far below SOTA on Mac |

**For our image-generation slot (Tier 2):** SDXL Turbo or Flux Schnell + LoRA fine-tuning via Apple's `ml-stable-diffusion` (CoreML). Runs on Neural Engine. That's the "fast diffusion on Mac" pitch — real and shippable.

## Inference performance — what's possible on Mac

For context on the "fast and cheap" half of the pitch:

**What Groq / Cerebras / SambaNova do:**

| Vendor | Hardware | Why it's fast |
|---|---|---|
| Groq LPU | Custom inference chip, SRAM-only (230 MB on-die), deterministic execution | Skips DRAM bottleneck. Llama-3-70B at 500+ tok/s. |
| Cerebras WSE-3 | Entire wafer as one chip (900K cores, 44 GB on-die SRAM) | No off-chip memory at all. Llama-3-70B at 1800+ tok/s. |
| SambaNova RDU | Reconfigurable dataflow | Custom dataflow per model |

The win is ~80% hardware (SRAM-only memory hierarchy bypasses GPU's HBM bottleneck), ~20% software co-design.

**What we can stack on Mac:**

Not Groq-fast, but "feels real-time" is achievable:

| Lever | Status | Estimated speedup |
|---|---|---|
| Q4 quantization | ✅ (GGUF) | 4× memory pressure reduction |
| KV cache | ✅ in sample, gap in serve | 5-10× on long sessions |
| Speculative decoding (B14) | ✅ shipped | 2-3× lossless |
| Apple Neural Engine inference (M5) | gap (queued #193) | 3-5× for INT8 workloads |
| Continuous batching | gap | 2-3× under load |
| Compiled kernels (MLX compile) | ✅ available in sample | 1.5-2× |

**The memory-bandwidth ceiling (hard physics):**

Autoregressive inference reads the entire model per token. So:

```
max_tokens_per_second = memory_bandwidth / model_size_in_bytes
```

| Hardware | Bandwidth | 7B Q4 ceiling | 70B Q4 ceiling |
|---|---|---|---|
| M5 Pro Mac (~600 GB/s) | 600 GB/s | ~170 tok/s | ~17 tok/s |
| H100 (3 TB/s HBM3) | 3000 GB/s | ~850 tok/s | ~85 tok/s |
| Groq LPU (~80 TB/s SRAM) | 80,000 GB/s | ~22,000 tok/s | ~2,200 tok/s |
| Cerebras WSE-3 (~125 TB/s on-die) | 125,000 GB/s | ~35,000 tok/s | ~3,500 tok/s |

The Groq/Cerebras advantage is ~130× memory bandwidth (on-chip SRAM vs DRAM). That's where their tok/s wins come from — not magic, not algorithmic.

**Realistic stacked ceiling on M5 Pro (48 GB):**

| Model | Theoretical ceiling | Practical with all levers stacked |
|---|---|---|
| 22M (Huge) at Q4 | 100,000+ tok/s | **~500 tok/s** (overhead dominates at this size) |
| 3B specialist at Q4 | ~170 tok/s | **~80-120 tok/s** |
| 13B (QLoRA fine-tune) at Q4 | ~40 tok/s | **~25-30 tok/s** |
| 70B (inference only) at Q4 | ~17 tok/s | **~10-15 tok/s** (barely fits) |

**What can't be 100×-ed on Mac:** the bandwidth ceiling. You'd need 100× more SRAM bandwidth, which means Groq/Cerebras-class hardware ($10K-100K). Not happening on a laptop.

**What can:** the **size of the specialist itself.** 22M vs 3.8B is already ~150× the param count. Combined with the inference speedups, the "20-150× faster than teacher" claim in the success criterion is achievable.

The platform pitch isn't "as fast as Groq" — it's "fast enough for your specific task, on your own machine, at zero cost." A 300 tok/s specialist locally beats a 1000 tok/s cloud model when you factor in 50-200ms network round-trip + cost + privacy.

## Market landscape (what's out there as of mid-2026)

For situating where posttrainllm fits in the broader inference / specialization market:

| Category | Players | What they sell |
|---|---|---|
| **Fast inference on standard models** | Groq, Cerebras, SambaNova, Together, Fireworks, DeepInfra | Hosted Llama/Mistral/Qwen at 500-1800 tok/s |
| **Embeddings / retrieval** | Voyage AI, Jina, Cohere Embed | Small specialized encoders |
| **Reranking** | Cohere Rerank, Jina Reranker | Cross-encoder models, ~150M, very fast |
| **Speech (ASR)** | Whisper API, Speechmatics, AssemblyAI, Deepgram | Real-time transcription <100ms |
| **TTS / voice cloning** | ElevenLabs, Cartesia, Resemble, PlayHT | Specialized TTS, ultra-low latency for agents |
| **Summarization (specialized)** | Cohere Summarize, AssemblyAI LeMUR, Cresta, NICE | Often not LLMs — sometimes encoder-decoder T5-class |
| **Code-specific** | Cursor, Continue.dev, Codeium, Tabnine, Mercury Coder | Distilled code specialists or routed agents |
| **Diffusion text (emerging)** | Mercury (Inception Labs), LLaDA, SEDD | Parallel-decoding via diffusion, 1000+ tok/s claims |
| **Mobile / on-device** | Apple Intelligence, Gemini Nano, Anthropic-on-iOS | 3B-class distilled for phone CPUs |
| **Specialized agents** | Cognition Devin, browser-use, Stagehand, Cline, Aider | Agent loops over standard models with task-specific scaffolding |
| **Local-Mac inference** | Ollama, LM Studio, MLX-LM, llama.cpp, **posttrainllm** | Run open weights on consumer Mac |

**posttrainllm's positioning:** the only player in "local-Mac inference" that ALSO covers the full build/upgrade lifecycle (data → train → eval → deploy). Ollama / LM Studio run pretrained models; posttrainllm builds and ships specialists end-to-end on the same machine.

### Competitive landscape — deeper research (added 2026-06-06)

#### Direct Mac/local-inference competitors

| Player | What it is | Differentiator |
|---|---|---|
| **LM Studio** | GUI for GGUF/MLX models; no fine-tuning | "LM Studio runs models. posttrainllm *makes* them." |
| **Ollama** | Local inference daemon; loads adapters | Complement — export target. "Bring your fine-tune to Ollama; build it in posttrainllm." |
| **Jan** | OSS ChatGPT desktop, inference-only | Jan = chat client; posttrainllm = factory. |
| **GPT4All** | Inference + LocalDocs RAG | Different lane — RAG vs distilled specialist. |
| **MLX-LM** | Apple library: train + inference on Apple Silicon | **Closest direct competitor.** posttrainllm = product/workflow/eval loop atop MLX-LM as library. |
| **Unsloth + Ollama** | Linux/CUDA fine-tune + export | "Unsloth needs a 4090; posttrainllm runs on your laptop." |

#### Cloud fine-tuning (we don't compete)

| Player | Verdict |
|---|---|
| Together AI ($0.48-$12/M tokens, ≤405B) | Different scale + buyer. Concede. |
| Fireworks (≤16B, $0.50/M tokens) | Same. Potential export target. |
| Anyscale (enterprise HIPAA/SOC2) | Wrong buyer. |
| **OpenAI fine-tune API** | **DEPRECATED May 2026.** Major tailwind. |
| Anthropic fine-tune | Not publicly available. |

#### Eval platforms

| Player | Verdict |
|---|---|
| **lm-eval-harness** (EleutherAI) | Use it; don't rebuild. Already wrapped via E3. |
| **Inspect AI** (UK AISI) | Use for agent/tool evals. |
| **Arize Phoenix** | Complement — they watch prod; we score pre-deploy. |
| LangSmith / Comet / HumanLoop | Wrong buyer; ignore. |

#### Synthetic data / distillation

| Player | Verdict |
|---|---|
| **Distilabel** (HF) | Use as engine; wrap with opinionated recipes. |
| Gretel / Mostly AI | Tabular; ignore. |
| Lilac (Databricks) | Complement; different pipeline stage. |

#### Apple-specific frontier

| Player | Verdict |
|---|---|
| **Apple Foundation Models** (iOS 26) | Both partner and competitor. Same on-device thesis; locked to Apple's base + App Store. |
| **MLX / mlx-community** | Build on it; contribute back. |

### Top 5 positioning statements

1. **"Run-only tools chat with models. posttrainllm *builds* them."** — vs LM Studio / Ollama / Jan / GPT4All.
2. **"Fine-tune on the Mac you already own — no 4090, no cloud bill, no data leaving the device."** — vs Together / Fireworks / Unsloth.
3. **"OpenAI killed their fine-tune API in May 2026. Specialist models shouldn't be a hosted API in the first place."** — market-signal positioning.
4. **"One opinionated path — pick a teacher, bring data, get a fast specialist — wrapped around the best OSS pieces (MLX-LM, lm-eval-harness, Distilabel)."** — honest about adoption; integrated workflow is the differentiator.
5. **"Apple's Foundation Models give you one 3B model locked to iOS. posttrainllm gives you any open base from 22M to 13B, deployable anywhere."** — vs Apple's on-device push; no ecosystem lock-in.

### Where posttrainllm honestly does NOT compete

- 70B+ production fine-tuning — Together/Fireworks win; concede
- LangChain-tied production observability — LangSmith owns it
- RAG-over-my-files chat — GPT4All's LocalDocs is mature
- Tabular synthetic data — Gretel/Mostly own enterprise tabular
- iOS App Store distribution for AI — Apple's Foundation Models wins; export to it

### Wave 2 landscape — AI coding / agents / inference / reasoning / RAG (researched 2026-06-06)

#### AI coding tools

| Player | Verdict | Notes |
|---|---|---|
| Cursor, Cody, Codeium, Augment, Windsurf | **Ignore** (cloud-IDE plays, different surface) | Wrong layer for us |
| **Continue.dev, Aider** | **Complement** — they consume our `serve` endpoint | "Point Continue at a posttrainllm specialist trained on your repo" |
| **Tabnine** | **Direct competitor on "per-repo fine-tune" claim** | They charge enterprise $$, cloud-clone of proprietary. **Tagline: "Tabnine's per-repo fine-tune, but on your Mac, on open weights, free."** |

#### Agent frameworks

| Player | Verdict | Notes |
|---|---|---|
| **LangGraph, smolagents (HF), Pydantic AI** | **Complement, high priority** | Ship cookbook pages — these are zero-effort distribution channels |
| AutoGen, CrewAI | Complement, lower priority | Smaller / less-aligned audiences |
| Magentic | Ignore | Tiny audience |

**Sharp insight:** None of these *produce* specialists. They orchestrate. **posttrainllm is the missing model-producer layer underneath.** Cookbook pages for smolagents + Pydantic AI reach high-intent audiences cheaply.

#### Inference framework wars

| Player | Verdict | Notes |
|---|---|---|
| vLLM, SGLang, TensorRT-LLM | Ignore on Mac (CUDA) | Reference architectures |
| **HF TGI** | **DEAD** (maintenance mode since March 2026) | Strike from reference lists |
| llama.cpp | Compete on Mac | They need GGUF conversion; we serve `.tinygpt` native |
| MLX-LM serve | Direct Mac competitor | We bundle train+eval+serve; they ship serve-only |
| **vllm-mlx** (community fork) | **THREAT** — claims 4.3× throughput over llama.cpp on Apple Silicon w/ continuous batching | See strategic decision below |

#### Reasoning models

| Player | Verdict | Notes |
|---|---|---|
| **DeepSeek-R1-Distill-Qwen-1.5B** | **Default base for `posttrainllm grpo`** (Tier 3) | Only realistic single-Mac GRPO target |
| **QwQ-32B (Q4)** | **Mac flagship reasoning teacher** | 32B fits 48GB at Q4; Apache 2.0 |
| DeepSeek-R1 (671B) | Use as teacher via distillation traces | Not runnable on Mac |
| o1 / o3 / Claude thinking / Gemini thinking | **Forbid as teacher** (our positioning is "no API spend") | — |

**Sharp insight:** Half of HF reasoning model cards mention GRPO; it's table stakes. If we ship `posttrainllm grpo`, DeepSeek-R1-Distill-Qwen-1.5B + GSM8K reward is the recipe.

#### RAG infrastructure

| Player | Verdict |
|---|---|
| **LanceDB** | **Default for posttrainllm RAG** — embedded, no server, matches our "single binary" ethos |
| ChromaDB | Optional default for tutorials |
| Qdrant | Optional (richer filters) |
| Pinecone, Turbopuffer | Ignore (SaaS) |
| Weaviate | Ignore for default (server process) |

**Sharp insight:** Every RAG stack assumes OpenAI embeddings. **None treat "I trained my own 22M embedding specialist" as a first-class workflow.** That's a wedge.

### Three strategic decisions surfaced by wave 2

These warrant explicit decisions, not deferral:

#### Decision 1: How to handle vllm-mlx serve threat

vllm-mlx is claiming 4.3× throughput at 16 concurrent requests on Apple Silicon. Our hand-rolled `serve` has no continuous batching. Three options:

| Option | Effort | Differentiation |
|---|---|---|
| (a) Match vllm-mlx | Months of paged-KV + scheduling work | Strong but eats `results-first` priority |
| (b) Wrap vllm-mlx as backend | ~1-2 weeks | None on serving; differentiate on train/eval loop instead |
| (c) Status quo | 0 | Lose throughput war within 6 months |

**Recommended: (b) — wrap.** Aligns with the `results-first` principle. Our value is train+distill+eval+ship loop, not serve-throughput. Worth a dedicated PRD to evaluate vllm-mlx maturity + plan the integration.

#### Decision 2: Add "specialist embedder" as Tier 2 modality

**New opportunity surfaced:** every RAG stack assumes OpenAI embeddings. A `posttrainllm embed-train` recipe + LanceDB integration is weekend-buildable, reuses our existing specialist-training stack, opens the RAG category without us shipping a vector DB.

**Recommended: yes, add to Tier 2.** Slot between "Speech-in (Whisper)" and "Image gen" by priority. PRD-sized.

#### Decision 3: Distribution strategy — agent frameworks > editor integrations

Cookbook pages for **smolagents** and **Pydantic AI** reach high-intent audiences (people already running local models, already caring about tool-call + structured-output reliability) more cheaply than chasing the Continue.dev / Aider crowd (who already have working models).

**Recommended: write 2 cookbook pages first, before any new editor-integration work.** Each ~1 day. Use the same recipe as the "Tabnine alternative" positioning.

### New positioning statements (from wave 2)

Add to the top 5:
- **"Tabnine's per-repo fine-tune, but on your Mac, on open weights, for free."** (cuts cleanly against the only incumbent with "specialist code model" as a productized story)
- **"Every RAG stack assumes OpenAI embeddings. Train your own."** (wedge into RAG without building a vector DB)

## Flagship example applications

These are **apps built on top of the platform** — not new modalities. They demonstrate what the platform can do:

| Example app | Built on | Notes |
|---|---|---|
| **Browser agent (browser-use / Stagehand style)** | VLM (Tier 2) + tool-call specialist (A1) + Playwright integration (~1 week) | Specialist outputs structured DOM actions (`click[id=42]`, `type[id=87]=text`). VLM disambiguates visual elements. Eval against WebArena / OSWorld / Mind2Web. |
| **Per-language code specialist** | Distillation (Tier 1) + LoRA + custom eval | Distill DeepSeek-Coder-33B / Qwen2.5-Coder-32B into a 3B specialist for ONE language (Rust, TS, Swift, Python, etc.). Match teacher within ~5-10pp on that language, run 5-10× faster. **Killer demo of the platform.** |
| **Voice command → action** | Whisper (Tier 2) + tool-call specialist (A1) | Speak a request → transcribed → routed to specialist → action executed |
| **Personal-image-style generator** | Image gen (Tier 2) + LoRA training | Dreambooth-style: train a LoRA on user's photos, generate in their style |
| **Document QA specialist** | VLM (Tier 2) + custom eval | Read PDF / screenshot of doc → answer questions about it |
| **Local research agent** | Tool-call specialist (A1) + web search tool | Smaller alternative to Perplexity / GPT-4 web browsing |
| **Text-to-SQL specialist** | Tool-call + constrained decoding (per-schema grammar) | Generate valid SQL for the user's actual table schema. Killer feature for analytics-adjacent users. |
| **Protobuf / RPC generator** | Constrained decoding (per-.proto grammar) | Generate valid RPC payloads for the user's services. Specialist for backend devs. |
| **Phone-a-friend smart router** | Local small specialist + cloud / larger-local escalation | App-level pattern: 90% of queries handled locally, 10% escalate. Pareto-optimal cost/quality. |

The platform's value is in being the *substrate* these are built on. Once Tier 1 + 2 land, each of these is ~1-2 weeks of integration work, not a research project.

## Language-specific code distillation — the killer recipe

Concrete recipe (e.g., for a Rust specialist):

| Step | Detail |
|---|---|
| Teacher | DeepSeek-Coder-V2-33B at Q4 (~16 GB) OR Qwen2.5-Coder-32B (similar) — strongest open code models |
| Inputs | 100K-500K target-language prompts: completion contexts, refactor tasks, lint-fix, doc generation. Sources: the-stack-smol (cached), GitHub scrape of target language, synthetic from teacher |
| Labeling | Teacher labels prompts locally — ~2-3 days on Mac at 5 tok/s for 100K examples |
| Student | 3B (fine-tune Qwen2.5-Coder-3B base) OR LoRA on a 7B base. Use Tier-1 distillation feature + QLoRA. |
| Training | 1-2 days on Mac |
| Eval | HumanEval-{lang} + MBPP-{lang} + custom user examples for that language's tricky patterns |
| Outcome | Match teacher within 5-10pp on target language; run 5-10× faster on same Mac |

**Why this works particularly well:**
- Code has hard correctness signal (compiles or doesn't)
- Long-tail language-specific patterns (Rust borrow checker, Swift @MainActor, Python f-strings) are exactly where small specialists shine
- General LLMs (GPT-4, Claude) trained on all languages → mediocre at each specific one
- Per-language specialists are a clean differentiator vs general assistants

## Tokenization — why tokens (not characters / bytes)

Tokens are just contiguous character groups the tokenizer decided to chunk together. Why we use them instead of raw bytes/characters comes down to one number: **attention cost grows as O(N²) in sequence length.** Shorter sequences = exponentially less compute.

| Approach | Vocab | "hello world" | Tokens per KB of English |
|---|---|---|---|
| Byte-level | 256 | 11 | ~5,000 |
| Character-level | ~150 | 11 | ~5,000 |
| **Subword BPE (SmolLM2)** | **49K** | **2** | **~250** |
| WordPiece (BERT) | ~30K | 2 | ~300 |
| Word-level (legacy) | ~50K-1M | 2 (but OOV explodes) | ~200 |
| Patch-based (Megabyte) | byte-level + grouping | 2-3 patches | ~700 |

Subword BPE produces ~20× fewer tokens than byte-level for English. That translates to:
- ~400× less attention compute (O(N²))
- 20× shorter KV cache
- 20× more text fits in the same context window

That's why every production LLM uses subword tokenization. The cost is a larger embedding matrix (49K × d_model extra params) — amortized to nothing per token.

### Tradeoffs

| Approach | Pros | Cons |
|---|---|---|
| **Byte-level (✅ supported)** | 256 vocab; no OOV; multilingual / emoji / typo-robust; no tokenizer to train | 20× longer sequences; 20× slower per doc |
| **BPE / SentencePiece (✅ supported via SmolLM2)** | 20× shorter sequences; mature tooling | Language-biased vocab; rare languages fragment; modality-bound |
| **Patch-based (Megabyte, 2023; BLT, 2024)** | Byte-level robustness + ~80% of BPE speed | New, less mature ecosystem |
| **Hybrid (char encoder → BPE decoder)** | Best of both | Complex, few open implementations |
| **Pixel-based** (render text as image, VLM) | Solves multilingual + visual layout together | Research-only |

### Platform recommendation — when to use which

| Tokenizer | When |
|---|---|
| **Byte-level (built-in)** | Tiny specialists (<50M), narrow tasks, multilingual, robustness-critical |
| **SmolLM2 BPE (49K)** | Default for English / code; compatibility with existing models |
| **Custom BPE (Tier 1 — tokenizer-trainer)** | Domain-specific corpus (medical, legal, code-only) |

### Frontier ideas worth tracking

- **Megabyte** (Meta 2023) — patch transformer over bytes
- **BLT (Byte Latent Transformer)** (Meta 2024) — dynamic byte grouping based on entropy; high-entropy spans get more compute
- **CANINE / ByT5** — pure character/byte transformers, accept the cost
- **Pixel-based** — text-as-image + VLM

The disciplined call: keep BPE as default. Watch BLT — if it becomes mature open weights, byte-with-patches becomes the right answer for multilingual + code + typo-robust specialists.

### Why this is a research frontier (and why posttrainllm is positioned for it)

Tokenization is one of the few hardcoded preprocessing steps left in modern LLMs — everything else (embeddings, attention patterns, position encoding, expert routing) has been "learned" over the past decade. Letting the model learn its own input units is **active 2024-2025 research**.

Known problems with fixed BPE tokenization that motivate this:
- Multilingual fragmentation (non-English languages get split into many tokens)
- Typo brittleness ("the" vs "teh" become unrelated)
- Math breaks ("1+2=3" tokenizes differently than "1 + 2 = 3")
- Code identifier inconsistency (`getUserById` = 1 token or 4?)
- Number reasoning collapses (large numbers get inconsistent splits)
- No morphological awareness inside tokens

**The deeper theme: adaptive compute.** Tokenization is one example of a broader idea — uniform per-token compute is wasteful, concentrate compute where signal is. Related techniques:

| Technique | What's adaptive | Status |
|---|---|---|
| BLT | Patch size (input granularity) | Recent (Meta 2024) |
| Mixture of Experts (MoE) | Which experts process each token | Production |
| Mixture of Recursions (MoR) | Layers per token | Research (2024) |
| Speculative decoding | Speculate easy, verify in bulk | Production (we have) |
| Test-time training | Update weights per input | Research |
| Latent reasoning (Quiet-STaR) | Internal "thinking tokens" | Research |
| Adaptive computation time (ACT) | Compute steps per token | Recently revived |

**posttrainllm's positioning is unusual:** most platforms (HF transformers, llama.cpp, etc.) are BPE-locked. We **already** support byte-level + SmolLM2 BPE as first-class options. Adding BLT-style adaptive patches when open weights mature is **incremental**, not a rewrite. That's a strategic asset worth preserving.

Three honest tiers of involvement:
1. **Conservative (now):** BPE default, byte fallback. Ship the product.
2. **Adopt (12-24 months):** integrate BLT when first strong open-weights release lands. Mac-native multilingual + typo-robust + code/text unified specialists.
3. **Research (12+ months, optional):** implement adaptive tokenization ourselves. Real research contribution if it works on tiny models — small models benefit *disproportionately* from adaptive compute because they have less compute to waste on easy tokens.

## What "upgrading a model" covers

"Build a model" is half the story. "Upgrade an existing model" is the other half. Most have primitives shipped; gap is packaging as canonical upgrade operations:

| Upgrade type | Status | Gap |
|---|---|---|
| Continued pretrain | `--resume` ✓ | — |
| Domain adaptation | gap | `--domain-adapt` mode (Tier 1) |
| Knowledge injection (edit specific facts) | MEMIT ✓ | — |
| Capability injection (add skill via LoRA) | LoRA ✓ | merge-LoRA-into-base for shipping |
| Preference correction | gap | DPO (Tier 1) |
| Quantize for shipping | GGUF Q5/Q6/Q8 ✓ | Q4_K_M (Tier 1) |
| Distill into smaller | recipe doc | feature (Tier 1) |
| Merge with another model | gap | TIES merging (Tier 1) |
| Revert / repair (rollback to checkpoint) | save-history ✓ | `posttrainllm revert --step N` flow |

## Local-teacher architecture (confirmed 2026-06-06)

The product runs entirely offline. No API dependencies.

| Teacher | Q4 size | Mac tokens/sec | 10K-label run | Use when |
|---|---|---|---|---|
| Phi-3-mini-4k | 1.5 GB | ~30-50 | ~30 min | default; strong general teacher |
| Qwen3-7B | 3.5 GB | ~15-25 | ~1 hr | stronger general; instruct-tuned |
| Llama-3.1-8B-Instruct | 4 GB | ~10-15 | ~2 hrs | strong general alternative |
| Qwen3-14B | 7 GB | ~7-10 | ~4-5 hrs | high-end teacher |
| Mixtral 8x7B (MoE) | 15 GB | ~3-5 | ~12 hrs | premium teacher; overnight runs |
| DeepSeek-V2-Lite (16B) | 8 GB | ~10-15 | ~3 hrs | strong + reasonable speed |
| Qwen2.5-32B / Llama-3-30B class | 15-20 GB | ~3-5 | ~12-24 hrs | overnight; near-frontier quality |

**The architectural call:** teacher labeling runs as an overnight or background process. Zero API spend. Users download the teacher once; reuse across all specialists. This is the differentiator.

## Today's PRD ship list (2026-06-06)

Net 14 PRDs in `docs/prds/`. Status snapshot as of end-of-session:

**Shipped by elf today (all marked `status: shipped-2026-06-06`):**
- E1 BFCL, E2 τ-bench, E5 HumanEval+sandbox, E7 judge, E8 train-time hook
- eval-leaderboard.astro, sae-timeline.astro
- Rust hf-downloader, Rust parquet-decoder
- dataset-decode-verify
- **adam-state-persistence** (B12 v2)
- **cleanup-extractordata-datatrove**
- **cleanup-score-consolidation** (`RunBench.swift` + `GenerationUtils.swift` exist)
- **app-train-controls-thermal** (TrainController.swift +174 lines, TrainView.swift +103 lines; some pieces like CLI `--throttle` flag may not be in this batch)

**Shipped by elf today (status: shipped-2026-06-06):**
- **app-eval-tab** — Eval tab in Mac app GUI (drafted + shipped same session)

**Not started — top of the queue:**
- **train-controls-gap-closure** — closes 3 audit-identified gaps (`--throttle` CLI flag + Adam verification + GitHubCorpus delete-after-parity), drafted 2026-06-06 EOD

**Verified via `swift build` + grep:** 839 insertions / 117 deletions across 24 files since the previous elf sync; `--no-save-opt-state` flag visible in `train --help` (confirms Adam state persistence shipped).

## Sequencing

1. **Now**: N02 base finishes → A1 tool-call distillation proves the
   recipe works end-to-end. Without this, building UI on an unproven
   recipe is premature.
2. **Then**: `posttrainllm specialist` CLI subcommand wraps the proven flow
   (data prep → teacher label → SFT/LoRA → eval). Headless API.
3. **Then**: App wizard built on top of the CLI. App = GUI for the
   proven flow.
4. **Then**: Templates for the 5-10 most common patterns ship as
   one-click flows.
5. **Then**: QLoRA path opens 13-30B fine-tuning. App can now offer
   "fine-tune a 13B model for your task on your Mac."

## Honest probability of the full vision landing

Assuming sustained execution at the current pace:

- **A1 tool-call specialist lands within 2 weeks of N02 finishing:** ~70%
- **`posttrainllm specialist` CLI wrapping the proven flow:** ~85% (mostly packaging)
- **App wizard built on the CLI:** ~75% (Mac UI work, real effort)
- **5 production-quality templates:** ~60% (need empirical tuning per template)
- **QLoRA path opens 13-30B fine-tuning:** ~70% (requires real ML engineering)
- **Full vision shipping as a coherent v1 product:** ~50%

The bottleneck is *not* technical capability. It's:
1. Sustained execution against scope creep
2. UX/templates (the unsexy work)
3. Quality predictability (telling users honestly when their task won't work)

## What this changes about today's plans

- Stop framing posttrainllm as "training tiny models from scratch on your Mac."
  That's *one* capability, not the product.
- Start framing it as "**fine-tune or distill any model up to ~30B on
  your Mac for your specific task.**" That's the actual platform.
- The 22M-from-scratch project becomes a *proof of recipe* — it shows the
  pipeline (data → train → eval → ship) works end-to-end at tiny scale.
  Same recipe scales to 76M, 1B, 3B, 7B+LoRA.
- The eval pipeline shipped today is the *measurement infrastructure* for
  any specialist — not just our 22M one. Reusable for every fine-tune.
- The distillation recipe (`docs/recipes/distillation-fc.md`) is the
  *training-side template* for the same product.

## Design principle: laptop-thermal-aware defaults

**Not a new direction — overdue translation.** posttrainllm has been explicitly Mac-first since day one. The audience target has always been the individual on a personal Mac. But the existing build's *defaults* (training loop, throttle behavior, fan-load assumptions) still implicitly inherit datacenter-era assumptions from upstream tools — nanoGPT's "for step in 0..<steps" loop, MLX's "use all the silicon you can" philosophy, ML papers' max-throughput benchmark culture. The platform was Mac-targeted at the API level but hadn't yet retrofitted the *defaults* to reflect "this is running on a laptop."

**This section codifies the overdue fix**: defaults should actively reflect the Mac-laptop audience that's been the thesis from day one.

| Surface | posttrainllm-correct default |
|---|---|
| **App Train tab — throttle slider** | Default position: **75%** or **"Auto"** (thermal-state-driven). NOT 100%. |
| **App Train tab — first-run banner** | "Training runs your Mac at full load. Slide down for cooler operation, or leave on Auto to throttle automatically when heat rises." |
| **CLI `posttrainllm train`** | Default `--throttle 1.0` (CLI users opt in to what they want; no surprise behavior). |
| **App Train tab — auto-throttle toggle** | **On by default.** Maps `ProcessInfo.thermalState` → automatic throttle adjustment (`.nominal` 100% / `.fair` 75% / `.serious` 50% / `.critical` 25%). |
| **Pre-launch confirm for long runs** | Show estimated thermal impact: "This will run at ~50W sustained for ~8 hours. [✓] My Mac is on a hard surface with good airflow." |

This makes posttrainllm the **first** Mac-native ML platform with laptop-aware defaults out of the box. The discipline is: **assume the user's machine is a laptop, not a server.** Every default decision flows from there.

## Maintainer learning roadmap (added 2026-06-06)

Personalized for outsider-perspective + AI-augmented + shipping-while-learning context. Not an academic curriculum — just-in-time depth on what the platform touches.

### Highest-ROI sequence

| Resource | Time | Why |
|---|---|---|
| **Karpathy "Zero to Hero" YouTube series** (6 videos, ~10 hrs) | 1 week of evenings | Best practical ML pedagogy that exists. Builds transformer from scratch. After this, the matmul-stack mental model is locked in. |
| **3blue1brown "Neural Networks" series** (~3 hrs) | 1 evening | Visual intuition for matmul + gradient descent. Pairs with Karpathy. |
| **Read nanoGPT line by line** (~300 lines PyTorch) | 2-3 hrs | Karpathy's reference impl. Once this clicks, ~80% of posttrainllm's `Train.swift` is legible. |
| **The Annotated Transformer (Harvard NLP)** | 2-3 hrs | Original 2017 paper, line-by-line with running code. Canonical reference. |
| **Read your own codebase actively** | ongoing | `TransformerBlock.swift`, `Train.swift`, `Sample.swift`. Best teacher is the system you shipped. |
| **Papers, chronologically, just-in-time** | on-demand | Transformer (2017) → GPT-2 (2019) → Scaling Laws (2020) → Chinchilla (2022) → LLaMA (2023) → DPO (2023) → BLT (2024). Don't pre-read; read when relevant to current work. |

### What NOT to spend time on

- Linear algebra textbooks (don't need matrix calculus by hand)
- PhD-level deep learning courses (Stanford CS224N — too academic)
- ML theory papers (NTK, information bottleneck — interesting but not actionable)
- Following every new paper on Twitter (drowns signal)

### The pattern that works

- **Build, then learn what you needed to build it** — by the time you need to know X deeply, you've already used it pragmatically. Theory comes second.
- **Use advisor as a tutor** — cheap to ask, fast turnaround
- **Just-in-time before commits** — 2-3 hrs reading the relevant paper + strongest blog + one OSS implementation before adding a new capability
- **Read companion docs:** `docs/learn/llm-mechanics-fundamentals.md` is the matmul-first explainer this session produced

## Open questions for future sessions

1. **Should posttrainllm ship its own pretrained 3B base?** Or rely on
   downloaded Qwen3-3B / Phi-3.5-mini as starting points? Argument for:
   architectural consistency, one binary handles everything. Argument
   against: weeks of training, doesn't differentiate from existing
   strong bases.
2. **Where does QLoRA fit?** Implementing 4-bit base + LoRA adapters
   isn't trivial in MLX-Swift. Might require waiting for MLX upstream
   or doing the integration ourselves.
3. **Cloud teacher option.** Allow user to point at Claude / GPT-4 API
   for labeling instead of local teacher? Lower friction, costs $.
4. **App template marketplace?** Other people's specialist recipes
   shareable as JSON configs. Long-term play.
5. **"Teacher RBS" clarification.** User mentioned this in passing during
   2026-06-06 strategy session; acronym unrecognized. Best guesses:
   teacher-reranker-student variant, or a paper-specific term. Treated as
   variant of teacher-student in current architecture list; revisit if
   user confirms a specific pattern.

6. **Should the embedder specialist ship BEFORE the LLM specialist (A1)?**
   (Parked 2026-06-06 EOD — decide after N02 lands.) The embedder track
   has fundamentally tighter eval loops: forward pass is ~10× cheaper
   than autoregressive generation; eval signal is exact (was-the-doc-in-top-K)
   not fuzzy; standard benchmarks (MTEB, BEIR, MS-MARCO) ship labeled
   pairs; eval takes seconds-to-minutes vs minutes-to-hours for LLM evals;
   metrics are cross-comparable (MRR/NDCG/Recall@K are universal).

   **Concretely**: embedder PoC end-to-end in ~1 week vs LLM specialist
   ~2-4 weeks. If "results first" is the operating principle, embedder
   might genuinely beat A1 to the first credible "small beats big on Mac"
   demo.

   **Why parked**: real comparison needs the N02 base done so we can
   score both paths empirically rather than estimate. Decision deferred
   to post-N02 discussion. PRD `docs/prds/specialist-embedder.md` is
   currently `blocked-on-heavy-training-approval` reflecting this gate.

## Related docs (for full context)

- `docs/recipes/distillation-fc.md` — concrete distillation recipe
- `docs/recipes/b25-scaledown.md` — sibling specialist track
- `docs/sessions/2026-06-05-eval-first.md` — yesterday's eval pipeline session
- `docs/PLAN.md` — canonical roadmap
- `../archive/HANDOFF.md` — pickup state for next session

## 2026-06-07 morning addendum — post-mortem + carry-forward

### Lesson from the /tmp incident

Lost ~14 hours of N02 output (best.tinygpt val_loss 4.434, canonical at step 89,901, all step-N history + JSONL) when the Mac rebooted overnight and macOS wiped `/tmp`. Fix: `docs/prds/persistent-training-output.md` (filed 2026-06-07).

**Generalized lesson**: audit all "ephemeral by default" choices in the platform. `/tmp` for outputs, in-memory state without a sync hook, anything that depends on a process staying alive. **Make persistence the default; volatility is the explicit opt-in.** This is a platform-credibility issue — a tool that silently destroys 14 hours of work on reboot is not a tool people trust with serious training.

### What we actually validated yesterday (despite the loss)

Even though we lost the weights, the *recipe* and *learnings* are intact:

1. **Loss trajectory is real signal**: 11.34 → 4.4-4.7 plateau over 90K steps. Honest interpretation: the Huge preset (22M params) + FineWeb-Edu may be under-capacity. Decay phase (180K-200K) might drop loss further, but not dramatically. **Probably need Mega (76M) or distillation-from-bigger-teacher to get a base usable as A1 starting point.**
2. **PowerMonitor auto-pause works** — caught thermal critical, saved checkpoint cleanly. Safety net validated.
3. **App's external-run detection works** — surfaces live + exited training runs, renders loss curve from JSONL, ETA computed.
4. **75% throttle works but isn't enough margin** — sustained 75% still hits thermal critical. **For laptop training, default should be 50% or even 40%** to never hit `.critical`.
5. **JSONL log truncates on `--resume`** (write mode instead of append) — workaround was reconstructing history from text logs. **Real bug; add to gap-closure PRD.**

### Updated default recommendations

| Setting | Old | New (post-2026-06-07) |
|---|---|---|
| `--out` default | `/tmp/<name>.tinygpt` | `~/.cache/posttrainllm/runs/<name>/<name>.tinygpt` |
| App throttle slider default | 75% | 50% |
| Pre-launch confirmation threshold | >30 min | >2 hrs (most users will skip 30-min runs through it without thinking) |
| `--log-jsonl` on `--resume` | write mode (truncates) | append mode (preserves history) |

### Re-prioritization

**Today (2026-06-07) priorities**:
1. **Fix `/tmp` default** (filed PRD) — credibility-critical
2. **App polish pass** — locale formatter ("2,00,000" → "200,000"), throttle row layout, click targets, seed placeholder
3. **N02 re-run tonight** — persistent path, 50% throttle from start
4. **SFT smoke** — even against SmolLM2 baseline if our base doesn't recover in time, just to validate recipe

**Defer**: embedder vs A1 sequencing, vllm-mlx investigation, cookbook content. All blocked on having a real base anyway.

## Related docs (for full context)

- `docs/recipes/distillation-fc.md` — concrete distillation recipe
- `docs/recipes/b25-scaledown.md` — sibling specialist track
- `docs/sessions/2026-06-05-eval-first.md` — eval pipeline session
- `docs/prds/persistent-training-output.md` — 2026-06-07 post-mortem PRD
- `docs/PLAN.md` — canonical roadmap
- `../archive/HANDOFF.md` — pickup state for next session

## TL;DR for myself in 3 months

You decided posttrainllm is **a Mac app for individual task-specialization**.
The product is "bring data → pick teacher → ship a fast specialist."
Distillation + LoRA + QLoRA + Q4 inference lift the ceiling from "3B
trained from scratch" to "30B fine-tuned locally + 70B-class quality via
distillation." The infrastructure is mostly built; the work is packaging,
templates, and honest quality predictability. The A1 specialist landing
is the proof-of-recipe that unblocks the platform pitch.

**One day in 2026-06 we lost 14 hrs of training output to a `/tmp` default.** It taught us the persistence-by-default principle. Don't repeat that lesson.
