gguf-neuron-explorer · parts list

Monkey-level explainer: what each part does for Jax

  1. Span gating ("when") — a volume pedal with a timer. Today the lace is on for every token. This lets us say: monkey loud while he introduces himself, monkey quiet while he does arithmetic, monkey off while he reads the question. Their trick: cook each chunk of the chat separately so the earlier chunks keep the state they were cooked with. It is the "which tokens" half of the conductor.
  2. Gain (multiply, not add) — a dimmer instead of a flashlight. Our pushes add a fixed amount whether or not the neuron was firing. Gain multiplies what the neuron already does: 0 silences it only where it was active, 2 doubles it, negative flips it. That is the "hold a neuron at its usual level" and "mute the doubt neuron only when it fires" tool we did not have.
  3. Reverse lookup — ask the answers which neurons made them. Take Jax's answers and the plain answers, subtract, and score every neuron by how well its write-direction lines up with the difference. Astra ran it: our hand-picked L34 N6111 came out rank 1 of 1.1 million. So the method is trusted, and the next 200 are the extra bars of the song.
  4. Contrast directions — the same idea packaged as one steerable thing: instead of 16 neurons, one direction built from a pile of "this persona" vs "not this persona" examples. A direction can be a note in a lace just like a neuron.
  5. Directional ablation — surgery instead of steering: remove one direction from every place the model writes it, so the behaviour cannot happen. Permanent, not reversible at inference. Useful for the Qwen reflex later; not for persona work now.
  6. Side-effect eval — their version of our reasoning suite plus persona score, with better scorers: exact answers, format, language mixing, and a persona-novelty rule that only counts new words appearing in two or more prompts, so one lucky "Ming" does not count as a persona.
  7. Random-direction null — a fairness test for rankings. Push random directions alongside real neurons and only trust a neuron that beats the randoms. Our monkey-word counts have no such null yet.
  8. Map layouts — how they draw the brain: layers as slabs along depth, neurons on a sheet placed by similarity, overlays for which neurons fire on pasted text, wiring lines between neurons. Same shape as our Unity slabs; worth copying the placement math.
  9. MCP tools — a menu of verbs an agent can call: overview, neuron dossier, search, steer, fires, reverse, highlight in the UI. A template for John's verbs; their rule that the agent must beat the null before reporting a find is worth stealing too.
  10. Logit lens — read a neuron's output without running anything: its write-direction through the final layer tells you which words it promotes. The "pirate neuron" trick from the post you saw. Cheap pre-filter: before pushing a candidate, check it actually writes toward monkey words.

What we leave: anything that exports to llama.cpp file formats, their 8-token ramp (a workaround for their engine), and their "shippable" thresholds as pass/fail truth.

gguf-neuron-explorer (gne) — parts list for our stack (Haiku inventory + Terra porting plan, 2026-10-28)

Repo: github.com/balaena01/gguf-neuron-explorer, MIT (c) 2026 balaena01, ~15.4k lines Python + vendored three.js

(own license). Credits lyramakesmusic/neuron-explorer; from-scratch reimplementation. Nothing executed here.

Haiku = mechanism inventory (file:line). Terra = port order, effort, pitfalls (gne-terra-porting-plan.md).

Take, in this order

  1. Span-gated steering (when) — gne/when.py:46 parse_when (all / gen / assistant / after:<text> / ramp:a-b), :60 chat_segments (token-prefix-stable span split, one-token boundary tolerance :100), :132 generate_when (prefill per span with pos0 so earlier KV keeps its state; vector only on assistant spans + the generation prompt; gen = unsteered prefill then vector from step 0; after = detokenize each step and switch on first match, O(n^2), one-step lag; ramp every 8 tokens). Port: copy the span logic + per-span prefill; replace set_cvec with our per-token gain hook; drop the 8-token ramp cadence (llama.cpp adapter-switch workaround) and the O(n^2) after. This is the conductor's "which tokens" half. 12-20 h.
  2. Multiplicative gain — gne/gain.py:33: a_n = silu(gate)*up, scale W_up row n by k -> k*a_n*W_down[:,n]; k=0 removes, negative inverts; acts only where the neuron fires. For us: scale the down_proj input column n by k at the hook (no LoRA). This is "hold at usual level" / mute without additive dose. 8-16 h.
  3. Reverse lookup — gne/reverse.py:83 contrastive_directions (prefill sets A/B, mean(A)-mean(B) per layer on residual out and on ffn_down inputs), :159 cos_by_layer (divide residual dims by their std first = massive- activation guard), :183 combine_scores (percentile-rank average of |cos|, sign-aligned activation diff, steer KL), :197 top-200 across all layers. Math reusable as-is; capture adapts. Finds the Jax direction / Qwen chord without a sweep. 16-28 h.
  4. Contrast directions as units — gne/direction.py:44 load_contrast (YAML + validate regex), :138 select_layer (ablate mode: projection removed, behaviour drop, KL<=0.1, distinct>=0.8), :295 response_directions; steer.py:262 direction units (raw/rel). 16-28 h.
  5. Directional ablation — gne/ablate.py:48 residual_writers, :239 _project W -= s*outer(r, r@W); LoRA/bake writers are llama.cpp-specific. Take the projection math. 16-32 h.
  6. Side-effect eval harness — gne/evalx.py:263 evaluate (dose 0 baseline + doses, same when path for all rows), :93 exact (answer words in first line), :112 format (json keys / line count / language), :139 mix (script contamination), :149 persona (novelty vs baseline + new words in >=2 prompts, distinct-4, length), ppl teacher-forced; thresholds capability_drop 5 pt / ppl 10 % / mix 0; optional 1-5 judge :238. Take the scorers as-is into lace_sweep; keep our claim/loop/doubt metrics beside them. 12-24 h.
  7. Sweep statistics — gne/sweep.py:64 random-direction controls interleaved (seeded per layer, shared pool); gne/rank.py:42 word mass = sum of top-5 positive z over baseline-subtracted once-per-rollout word counts, z = (cnt-mean)/sqrt(mean+0.5); null_pct = fraction of control masses below the unit's. Pure numpy on rollouts: reuse as-is as a null for our monkey-density counts.
  8. Map + layouts — gne/layout.py:50 compute_layout (W_down columns -> PCA-50 -> UMAP cosine -> 2D, snap_to_grid :18; or lens-based sparse vectors), ui/static/layout.js GEOM (x = depth L*0.9, per-layer mixer slab + MLP sheet, neurons on the sheet by index or UMAP), overlays (sweep mass, steer KL, logit |z|, activations, fires, search), connections.py:87 top-k up/downstream by weight similarity through the FFN norm. Web: adapt (keep vendored three.js, honor its license). Unity VR: idea-only — the GEOM layout, wiring and overlays map 1:1 onto our slabs. 20-40 h.
  9. MCP tool surface — gne/mcp_server.py:58: model_overview, layer_summary, neuron, search, steer, steer_lens, fires, reverse, direction, recipe_save, eval_recipe, job_start/status/cancel, ui_highlight/ui_note/ui_open; its instructions make the agent check null_pct / kl_null_p95 before reporting. Template for John's verbs. 16-32 h.
  10. Logit lens / steer lens — gne/lens.py:105 (W_down column x out-norm x unembedding, z over vocab) and :199 (KL(base||steered) on fixed contexts vs random controls, kl_null_p95). Adapt; cheap first passes.

Leave

GGUF export, .cvec control vectors, bias baking, LoRA adapters (llama.cpp-specific); the 8-token ramp cadence; the

"shippable" thresholds as release criteria; a single regex/judge as ground truth (their own playbook: "distrust cheap

effects such as a changed self-name").

Formats worth copying

rollout JSONL (kind, neuron, layer, dose, rel_push, token_ids, logprob, finish) + units.jsonl + meta.json per run;

per-layer npz for lens/stats; recipes and contrast sets as YAML with when / sampling / ablate / units.