niels-gpt-app: inference, token by token

A chat interface that streams, beside each token, the probabilities and attention that produced it.

niels-gpt-app is a chat interface over my from-scratch model that shows, for every generated token, why that token. I had trained the model; I wanted to watch it choose, not just read its output.

A FastAPI backend downloads the v1 checkpoint from Hugging Face at startup and streams POST /chat/stream as server-sent events. Each generated token arrives as two events: the token, and a trace carrying the top-k candidate probabilities, the entropy of the next-token distribution, and one attention row for a layer the client selects. A second endpoint returns the full t-by-t attention matrix for one layer and head. The Next.js frontend renders all of it: an inspector with per-token replay, top-k bubbles, an entropy indicator, a heatmap modal, and an ASCII/UTF-8 toggle, because byte-level tokens are not always printable. An in-repo explainer documents how to read the display.

Two decisions carry the app. Streaming is SSE over POST with a hand-rolled fetch parser, because the browser EventSource API cannot POST; the alternatives were WebSockets or putting the prompt in a GET query. And the trace exists only because the model code keeps attention as an explicit softmax in every path instead of calling a fused kernel — the fused alternative is faster and returns no probability matrix to show.

The guardrails are small and concrete: a 16KB prompt cap returning 413, a token bucket at 10 requests per minute with burst 3 per IP returning 429, and a bounds check on the requested trace layer returning 422.

Numbers: 8 commits, 2025-12-16 to 2025-12-19; the API and the web UI both landed on the first day. The API has 14 test functions across 3 files, including the SSE protocol; the web app has zero tests, and its README's stated verification is npm run build.

What is wrong with it. Both documented deploy URLs returned 404 on 2026-08-09 — the Render API and the Vercel frontend are dead, so the charter goal of hosting this on my site is currently false. The API pins the model code to a git URL that now redirects to niels-gpt-2, whose interfaces are incompatible, so a fresh install builds against the wrong code. The README calls the model "256-token context, 4-layer," which matches neither v1's defaults nor v2's.

The model is small. Watching it choose is the entire point.