Skip to content

feat(vindex3): the true logit lens through the executor's own head (V3-LENS-1) - #487

Merged
chrishayuk merged 3 commits into
mainfrom
lens-1
Sep 20, 2026
Merged

chrishayuk merged 3 commits into
mainfrom
lens-1

Conversation

@chrishayuk

Copy link
Copy Markdown
Owner

What

V3-LENS-1, rung 3 above V3-OBS-1 (#484) and V3-STREAM-1 (#485), stacked on the observe verb (#486; retargets to main once that merges).

  • One head path. PreparedOperands::head_logits (prepared final norm, then the prepared output head with multiplier and softcap) and head_over_normed. The decode exit and all four batch exits now call them; the private batch helper is gone. A lens at the last layer is therefore the executor's logits by construction, not by agreement.
  • The lens is a consumer. LogitLens reads the layer output (layer_scale × after) at declared sites (all, every:<k>, a list; FFN and/or attention), records each declared token's log-probability and rank under a full f64 log-softmax plus the top-k, counts its head passes, and records its first failure instead of panicking in a callback. LensReader lets the run record hold any reader.
  • On the record. EventKind::Readout, sequenced between a write's stats and its structural event; head_passes and lens_failure on the receipt.
  • CLI. vindex3 observe --lens-tokens … [--lens-layers …] [--lens-attention] [--lens-top-k …], plus stepping wall time and a per-depth table for the final position.

Evidence (docs/v3-lens-1-logit-lens.md, frozen before implementation)

LP1 parity with the lens armed on every site, both CPU backends. LP2 anchor: the last FFN site's lens is bit-identical to the executor's logits on both backends and through the Gemma 4 miniature's layer scale. LP3: every decode/batch/observed parity gate bit-identical after the exit refactor. LP4: proper distributions at every depth. LP6: readouts replay equal; a failing lens is named on the receipt. LP7, Gemma 3 4B IT, The capital of France is, final prompt position: Paris rank 14055 at L0 → 10 at L23 → 1 at L24 (logp −0.36) → near-certain by L26; France peaks around rank 400–900 in L16–20 and never leads; the exit row equals the executor's top-1. LP5 cost, single runs: Granite 183.5 → 1305.7 ms/position with all 40 FFN sites armed (7.1×), Gemma 134.0 → 4132.0 ms/position with 34 (30.8×); the forecast's "several times" was an underestimate and is recorded as such.

Gates

fmt, clippy (larql-vindex, larql-inference, larql-cli), doc references, larql-vindex lib 4781, larql-inference lib 1544, larql-cli 917.

…3-LENS-1)

One head path: PreparedOperands::head_logits (prepared final norm, then
the prepared output head with its multiplier and softcap) and
head_over_normed; the decode exit and all four batch exits call them, so
a lens at the last layer is the executor's logits by construction.
LogitLens is a consumer of the carrier tap that reads the layer output
(layer scale applied) at declared sites, records each declared token's
log-probability and rank under the full log-softmax, and counts its head
passes. Readouts ride on the run record with their price on the receipt;
`vindex3 observe` gains --lens-tokens/--lens-layers/--lens-attention/
--lens-top-k and prints stepping time and a per-depth table.

Witnessed: parity with the lens armed everywhere on both CPU backends;
the last-layer anchor bit-identical, including through the Gemma 4
miniature's layer scale; proper distributions at every depth. Gemma 3 4B,
"The capital of France is": " Paris" rank 14055 at L0, 10 at L23, 1 at
L24, near-certain by L26. Cost measured: 7.1x the forward on Granite,
30.8x on Gemma (one head pass costs a forward there), so sites must be
declared. Freeze, amendments and results in docs/v3-lens-1-logit-lens.md.
…mary as lines

The coverage gate found the LensReader impl unreached by larql-vindex's
own tests (only the inference crate used it); the mutants job found the
CLI's summary and lens table unassertable because they printed straight
to stdout. The reader now has a trait-object witness, and the summary is
built as lines a test reads before they are printed.
@chrishayuk
chrishayuk merged commit 0197af4 into main Sep 20, 2026
32 of 33 checks passed
@chrishayuk
chrishayuk deleted the lens-1 branch September 20, 2026 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant