LensLapse: Watching Language Models Learn with an In-Browser Logit Lens over Training Checkpoints

Tatsuki Okada

Nara Institute of Science and Technology (NAIST)

Scrub across Pythia's public training checkpoints and watch next-token predictions crystallize from noise into knowledge β€” layer by layer, with zero backend.

Abstract

The logit lens is a standard instrument for inspecting how a transformer's next-token prediction forms across layers β€” yet every hosted lens tool inspects a single finished model. LensLapse turns training time into a first-class axis of token-level interpretability: scrub a slider across 38 public checkpoints of Pythia-70M and watch per-layer, per-position lens predictions crystallize from early frequency bias into factual knowledge. Curated prompts render instantly from precomputed data, while any free-text prompt is probed live in the browser via WebGPU/WASM ONNX inference β€” no server, no API key, and your prompt never leaves your device. The in-browser lens matches fp32 PyTorch with 100% top-1 agreement on our evaluation suite (where int8 quantization degrades to as low as 52%), and warm probes complete in 63–316 ms on Chromium/WebKit across three model sizes (14M–160M).

Highlights

A time axis for the logit lens

Existing lens tools show one finished model. LensLapse scrubs 38 checkpoints of Pythia-70M (step 0 β†’ 143k) with exact P(token) trajectories β€” revealing fact acquisition that is visibly non-monotone: learned, lost, and sometimes relearned.

Fully in-browser, zero backend

Free-text prompts run as a single forward pass via onnxruntime-web (WebGPU, with WASM fallback). A static site plus versioned weights on the HF Hub means unlimited concurrent users at zero hosting cost β€” the demo cannot rot.

Your checkpoints, one pip install

pip install then lenslapse server serves the app and the probe API on one local port. Point it at any HF model or a local Trainer run β€” no ONNX conversion, no config files. The recipe is architecture-generic: GPT-NeoX, GPT-2, and Llama-style RMSNorm all pass the parity check.

Fidelity you can verify

By construction, lens(hL) equals the model's logits β€” asserted per checkpoint at export. fp16 weight storage keeps 100% top-1 agreement with fp32 PyTorch on our evaluation suite; dynamic int8 drops to 52%, so we do not ship it.

Watchable by design

One click plays the whole time-lapse, cells flashing as their top-1 changes. A top-10 bar race and the classic p-vs-layer profile animate at the pinned cell; an acquisition map shows when each cell first learned its final answer, a diff view shows what changed since any reference checkpoint, and a compare mode renders a second model in lockstep.

Scriptable end to end

The core actions have CLI twins β€” lenslapse probe/trace/models β€” and the app can copy the exact CLI or cURL command that reproduces the current view. Track any token across training, share permalinks, or embed a live grid anywhere with ?embed.

Screenshots

The full LensLapse interface: logit-lens grid, training-step slider, trajectory panel, and emergence stories
The full interface at step 8,000 (Pythia-70M): the logit-lens grid with its view toggles (left), the log-scale training-step slider with the play button (top), and β€” for the pinned cell β€” exact probability trajectories, the p-vs-layer profile, and the top-10 race (right), above curated emergence stories.
Logit-lens grid at training step 8,000 where the token Tokyo first reaches top-1 at the last layer
The lens grid for β€œThe capital of Japan is the city of” at step 8,000 β€” β€œ Tokyo” first reaches top-1 at the last layer, while lower layers still predict echoed or generic continuations.

How it works

Each checkpoint is exported once into a pair of ONNX graphs: a backbone that returns the pre-layer-norm residual stream after the embedding and every block, and a small lens head (final layer norm + unembedding) applicable to any layer's hidden state. Curated prompts are precomputed with fp32 PyTorch into static JSON shards; a live prompt is tokenized in the browser and probed with one forward pass, pushing every (layer, position) hidden state through the lens head in a single batched matmul. Weights are stored fp16 and cast to fp32 at session load.

Pythia checkpoint (HF Hub, revision step{N})
   β”œβ”€ backbone.f16.onnx   input_ids β†’ hidden states [L+1, T, H]
   β”œβ”€ lens.f16.onnx       hidden [N, H] β†’ logits [N, V]
   └─ precompute          β†’ static JSON shards (top-10 per cell + trajectories)

browser (static site, no backend)
   β”œβ”€ precomputed mode: JSON shard β†’ canvas grid + SVG trajectories
   └─ live mode: onnxruntime-web (WebGPU β†’ WASM) + transformers.js tokenizer

BibTeX

@misc{okada2026lenslapse,
  title  = {LensLapse: Watching Language Models Learn with an In-Browser Logit Lens over Training Checkpoints},
  author = {Tatsuki Okada},
  year   = {2026},
  url    = {https://github.com/iamtatsuki05/lenslapse}
}