B.8 — the owned talk-model: AAAA → small talk, measured
B.1–B.7 grew a library around a borrowed model. B.8 finally trains a model that's OURS — a 5M-param decoder, from scratch, no open weights — to do the one conversational tier a tiny model CAN own: small talk. The honest number is a held-out gate: openers the model never trained on, graded by a deterministic rule with no model in the verdict. Headline: 48/50 (96%) valid replies on held-out — it generalized to openers it never saw (in-distribution), it didn't just memorize the trained rows. And the lesson that got it there wasn't size or the GPU; it was real on-target data plus a learned stop.
T.M.B. #8 — a model that’s actually ours. Every earlier bench wrapped an open-weight model in a library. This one trains the model itself: a 5M-param decoder, random init, our architecture, our data, our weights — no pretrained weights loaded. The task is small talk, the one conversational tier a tiny model can own (facts stay in the library). The number is held-out and the grader has no model in it. Frozen; re-run it yourself.
The claim
A from-scratch tiny model cannot be a general conversationalist — that’s a data-scale wall,
and the whole project routes around it (library holds knowledge, model is a cursor). But it
can own small talk: greetings, tone, adjacency pairs — hello → hi, which you fetch,
not invent. So: mint an on-target corpus, train a 5M model, and grade it on held-out openers
it never saw. If it produces valid replies on unseen inputs, it learned the rule; if only the
trained ones work, it memorized. Two things kept honest:
The gate is deterministic —
grade(opener, reply)checks the reply is a clean, recognized turn that validly answers the opener’s kind. No LLM judge (you can’t grade a model with a model). The exact rule grades this model, the corpus, or a future mint identically.How, concretely (no model, all inspectable): (a) classify the opener into a kind (
greeting/how_are_you/thanks/farewell/ …) by whole-word phrase match; (b) clean check — the reply must be non-empty, short (≤14 words), single-line (a run-on fails here, which is how the no-stop run scored 0); (c) recognized turn — the reply must be a registered response in the corpus (exact normalized match); (d) adjacency — that response must be registered as a valid answer to the opener’s kind (a greeting answered with a goodbye fails). It’s a classifier + a corpus-membership table + an adjacency map — no regex-fuzzing, no embeddings, no judge. One honest consequence: because (c) is exact-membership, the gate rewards producing a valid corpus reply to an unseen opener — it measures opener-generalization, not novel-phrasing generation.The split is held-out — 15% of the pairs are removed before training and only used to grade. The number is the learn-vs-memorize gap, not a training-set victory lap.
The setup
- Model: 4.96M-param causal decoder (
n_embd 256 · n_head 8 · n_layer 6), pytorch, from scratch. Same architecture as the numpy weld — only the math engine changed (numpy → torch), so “no open weights” holds exactly as scoped. - Data: 530
(opener → reply)pairs minted from the owned small-talk corpus (not a client corpus — that would only make a domain reader). 451 train / 79 held-out. - Objective: next-token, completion-masked (loss only on the reply) with a learned stop (the reply ends in a stop token so the model halts instead of running on).
Results
| held-out gate | sample | |
|---|---|---|
| the old mint (n=1) | — | AAAAAAAAAAAA… |
| first run (no stop) | 0/50 | Hello, hi. hi. thanks — you? you? you?… (run-on) |
| + learned stop | 48/50 (96%) | hello → "Hi — good to see you." |
Clean replies on openers it never trained on:
hello → Hi — good to see you.
thanks → You're welcome.
how are you → Doing well, thanks. How are you?
see ya → Catch you later, buddy.
Loss 151.8 → 0.37 in 67 seconds on a CPU (1200 steps).
What actually moved the number
Not the size. Not the GPU. Real on-target data + a learned stop. The first run produced
real English words and still scored 0/50 — because it never learned to halt. One line
(end each reply with a stop token) took it from run-on babble to 96% held-out. This is the
same lesson every bench keeps returning: the data is the variable. The 1M-numpy “champion”
(12/19 on the reasoning ladder) and a 1M mint that outputs AAAA are the same architecture —
what separates them is what they were fed.
The honest caveats
- Small talk only. This is tier-1 of the conversation ladder (greetings, tone, sign-offs). It is not a general conversationalist — topic knowledge still comes from the library, not these weights. Fed a real question, it has nothing; that’s by design.
- One wobble (
hey buddy! → "Hello!Hello!") — a doubling the longer-run + bigger corpus should sand off. - 530 pairs is small. 96% is on our splits; robustness to wild phrasings (
yo what's good) needs the corpus teacher-expanded. The GPU’s job next.
The point of B.8 isn’t that small talk is hard. It’s that a model we own, from nothing,
crossed from AAAA to graded, generalizing conversation — and the receipts say data, not
size, is what got it there.