diff --git a/demos/Jacobian_Lens_Demo.ipynb b/demos/Jacobian_Lens_Demo.ipynb
new file mode 100644
index 000000000..b14ac1253
--- /dev/null
+++ b/demos/Jacobian_Lens_Demo.ipynb
@@ -0,0 +1,893 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "21aefd10",
+ "metadata": {},
+ "source": [
+ "
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "21a6b3c5",
+ "metadata": {},
+ "source": [
+ "# Jacobian Lens (J-lens) Demo\n",
+ "\n",
+ "The **Jacobian lens** characterizes an intermediate residual-stream activation by its\n",
+ "*first-order causal effect on the model's output*, averaged over a corpus of contexts. For each\n",
+ "layer $\\ell$ it uses a single matrix $J_\\ell = \\mathbb{E}[\\partial h_{\\mathrm{final},t'} /\n",
+ "\\partial h_{\\ell,t}]$ mapping the output of block $\\ell$ to the final block's output, and reads\n",
+ "tokens with the model's own unembedding: $\\mathrm{lens}(h_\\ell) = \\mathrm{softmax}(W_U\\,\n",
+ "\\mathrm{norm}(J_\\ell h_\\ell))$. The logit lens is the special case $J_\\ell = I$; the J-lens is\n",
+ "its causal, corpus-averaged correction, and it surfaces interpretable content at depths where the\n",
+ "logit lens reads noise.\n",
+ "\n",
+ "Introduced in [*Verbalizable Representations Form a Global Workspace in Language Models*](https://transformer-circuits.pub/2026/workspace/index.html)\n",
+ "(Gurnee et al., Transformer Circuits Thread, 2026). Pre-fitted lenses for 38 open models are\n",
+ "published at [`neuronpedia/jacobian-lens`](https://huggingface.co/neuronpedia/jacobian-lens), and\n",
+ "an interactive version lives at [neuronpedia.org/jlens](https://www.neuronpedia.org/jlens).\n",
+ "\n",
+ "This demo, on `gemma-2-2b`:\n",
+ "\n",
+ "1. loads a published lens from the Hub,\n",
+ "2. reads J-lens vs logit-lens tokens on a two-hop prompt with an *unspoken intermediate*,\n",
+ "3. causally swaps one concept for another (France → China) in lens coordinates, and\n",
+ "4. steers with a J-lens direction.\n",
+ "\n",
+ "**Note**: `google/gemma-2-2b` is a gated Hugging Face model — accept its license and authenticate\n",
+ "(`huggingface-cli login` / `HF_TOKEN`) before running. The demo uses ~6 GB of GPU memory\n",
+ "(executed on an 8 GB card), so a free Colab T4 should work."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "454cdfb3",
+ "metadata": {},
+ "source": [
+ "## Setup (Ignore)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "ae487ba2",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2026-07-11T09:06:11.958584Z",
+ "iopub.status.busy": "2026-07-11T09:06:11.958352Z",
+ "iopub.status.idle": "2026-07-11T09:06:12.029888Z",
+ "shell.execute_reply": "2026-07-11T09:06:12.029521Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Running as a Jupyter notebook - intended for development only!\n"
+ ]
+ }
+ ],
+ "source": [
+ "# NBVAL_IGNORE_OUTPUT\n",
+ "# Janky code to do different setup when run in a Colab notebook vs VSCode\n",
+ "import os\n",
+ "\n",
+ "DEVELOPMENT_MODE = False\n",
+ "IN_GITHUB = os.getenv(\"GITHUB_ACTIONS\") == \"true\"\n",
+ "try:\n",
+ " import google.colab\n",
+ "\n",
+ " IN_COLAB = True\n",
+ " print(\"Running as a Colab notebook\")\n",
+ "except ImportError:\n",
+ " IN_COLAB = False\n",
+ " print(\"Running as a Jupyter notebook - intended for development only!\")\n",
+ " DEVELOPMENT_MODE = True\n",
+ " from IPython import get_ipython\n",
+ "\n",
+ " ipython = get_ipython()\n",
+ " ipython.run_line_magic(\"load_ext\", \"autoreload\")\n",
+ " ipython.run_line_magic(\"autoreload\", \"2\")\n",
+ "\n",
+ "if IN_COLAB or IN_GITHUB:\n",
+ " %pip install transformer_lens"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "fe86001d",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2026-07-11T09:06:12.031375Z",
+ "iopub.status.busy": "2026-07-11T09:06:12.031092Z",
+ "iopub.status.idle": "2026-07-11T09:06:27.807249Z",
+ "shell.execute_reply": "2026-07-11T09:06:27.806799Z"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "8b9855cb054f4b06803233534b78ddf9",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "Loading weights: 0%| | 0/288 [00:00, ?it/s]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "loaded gemma-2-2b: 26 layers, d_model=2304, device='cuda'\n"
+ ]
+ }
+ ],
+ "source": [
+ "# NBVAL_IGNORE_OUTPUT\n",
+ "import torch\n",
+ "\n",
+ "from transformer_lens.model_bridge import TransformerBridge\n",
+ "from transformer_lens.tools.analysis import JacobianLens\n",
+ "\n",
+ "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
+ "# Raw HF weights (the Bridge default) — the published lenses are fitted on raw\n",
+ "# activations, and JacobianLens refuses fold_ln / compatibility-mode models.\n",
+ "model = TransformerBridge.boot_transformers(\"google/gemma-2-2b\", dtype=torch.bfloat16, device=device)\n",
+ "model.eval()\n",
+ "print(f\"loaded gemma-2-2b: {model.cfg.n_layers} layers, d_model={model.cfg.d_model}, {device=}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ad038b6e",
+ "metadata": {},
+ "source": [
+ "## 1. Load a published lens\n",
+ "\n",
+ "One artifact per model: a `[d_model, d_model]` matrix for every layer except the last (the final\n",
+ "layer's transport is the identity by construction). `from_pretrained` validates the lens against\n",
+ "the model and fails loudly on dimension or weight-processing mismatches."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "f961d030",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2026-07-11T09:06:27.824146Z",
+ "iopub.status.busy": "2026-07-11T09:06:27.823519Z",
+ "iopub.status.idle": "2026-07-11T09:06:28.209427Z",
+ "shell.execute_reply": "2026-07-11T09:06:28.208823Z"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "JacobianLens(layers=0..24 (25), d_model=2304, n_prompts=454)"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# NBVAL_IGNORE_OUTPUT (download progress)\n",
+ "lens = JacobianLens.from_pretrained(\n",
+ " \"neuronpedia/jacobian-lens\",\n",
+ " filename=\"gemma-2-2b/jlens/Salesforce-wikitext/gemma-2-2b_jacobian_lens.pt\",\n",
+ " model=model,\n",
+ ")\n",
+ "lens"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "64f87b93",
+ "metadata": {},
+ "source": [
+ "## 2. Reading: a two-hop prompt with an unspoken intermediate\n",
+ "\n",
+ "*\"The currency used in the country shaped like a boot\"* requires an intermediate step — **Italy** —\n",
+ "that never appears in the prompt. The J-lens surfaces the intermediate and the answer's concept\n",
+ "band in the middle of the model, while the logit lens at the same layers mostly tracks surface\n",
+ "continuations."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "1b19ec1a",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2026-07-11T09:06:28.217489Z",
+ "iopub.status.busy": "2026-07-11T09:06:28.217204Z",
+ "iopub.status.idle": "2026-07-11T09:06:29.114425Z",
+ "shell.execute_reply": "2026-07-11T09:06:29.113969Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "layer | J-lens top-5 | logit lens top-5\n",
+ " 4 | [' anything', '', ' ï', ' also', ' –'] | [' is', '', ' not', ' are', ' was']\n",
+ " 8 | ['\\n\\n\\n', ' $', ' probably', ',$', '\\n\\n'] | [' is', ' called', ' was', ' are', ' has']\n",
+ " 13 | ['LookAnd', 'RenderAtEndOf', ' famously', 'qrstuvwxyz', 'ⓧ'] | [' is', ' called', ' actually', ' was', ' has']\n",
+ " 17 | ['LookAnd', 'Билгалдахарш', 'RenderAtEndOf', 'BeginContext', 'ftagPool'] | [' called', ' not', ' a', ' the', ' ']\n",
+ " 21 | [' euro', ' currency', ' euros', ' Euros', ' Euro'] | [' called', ' the', ' not', ' a', ' ']\n",
+ " 24 | [' the', ' called', ' euro', ' euros', ' Euro'] | [' the', ' called', ' not', ' known', ' a']\n",
+ " 25 | [' the', ' called', ' not', ' known', ' a'] | [' the', ' called', ' not', ' known', ' a']\n",
+ "model output: the\n"
+ ]
+ }
+ ],
+ "source": [
+ "PROMPT = \"Fact: The currency used in the country shaped like a boot is\"\n",
+ "\n",
+ "result_jlens = lens.readout(model, PROMPT, positions=[-1])\n",
+ "result_logitlens = lens.readout(model, PROMPT, positions=[-1], use_jacobian=False)\n",
+ "\n",
+ "top_j = result_jlens.top_tokens(model.tokenizer, k=5)\n",
+ "top_l = result_logitlens.top_tokens(model.tokenizer, k=5)\n",
+ "print(f\"{'layer':>5} | {'J-lens top-5':<55} | logit lens top-5\")\n",
+ "for layer in [4, 8, 13, 17, 21, 24, 25]:\n",
+ " print(f\"{layer:>5} | {str(top_j[layer][-1]):<55} | {top_l[layer][-1]}\")\n",
+ "print(\"model output:\", top_j[25][-1][0])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "08ac5860",
+ "metadata": {},
+ "source": [
+ "The answer concept (` euro`) and the intermediate's semantic neighborhood dominate the J-lens\n",
+ "readout from the middle of the model onward; the logit lens catches up only in the last few\n",
+ "layers, where $J_\\ell \\to I$ and the two lenses converge. (Early layers are noise under both —\n",
+ "the paper's \"sensory\" band. The recurring code-ish tokens in early J-lens readouts are a known\n",
+ "signature of gemma-2-2b's lens.)\n",
+ "\n",
+ "We can watch each concept's *rank trajectory* across depth:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "2e0887dd",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2026-07-11T09:06:29.118703Z",
+ "iopub.status.busy": "2026-07-11T09:06:29.118453Z",
+ "iopub.status.idle": "2026-07-11T09:06:29.588577Z",
+ "shell.execute_reply": "2026-07-11T09:06:29.588189Z"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAy4AAAGGCAYAAACdY9UBAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzs3XV8E+cfwPFPUnenRmmhxd2d4s5wGLDh7jDYYPyAIYNtuOvQwYbDYGzI8OHuTimUunub5H5/hJaGttBSSYDn/Xr11fZyufteLrk833tMJkmShCAIgiAIgiAIgg6TazsAQRAEQRAEQRCE9xGJiyAIgiAIgiAIOk8kLoIgCIIgCIIg6DyRuAiCIAiCIAiCoPNE4iIIgiAIgiAIgs4TiYsgCIIgCIIgCDpPJC6CIAiCIAiCIOg8kbgIgiAIgiAIgqDzROIiCIIgCIIgCILO+6QSlxMnTiCTyThx4oS2Q9G6H374AZlMRkhISJ7u59GjRzRt2hQrKytkMhl79+7N8TZ79+6Nh4dHjreT1zw8POjdu3ee7ye/zqWgO3x8fJDJZMydO1fboQgfgaxei2QyGT/88EOex5PyXbxz584835eQffXr16dMmTLaDuODbNiwAZlMho+PzzvXS/neTOvtz0nKti5fvpwHkeacrseXVv369alfv36+7OujSVw+phP4OenVqxe3bt3ixx9/ZPPmzVSpUkXbIemUuLg4fvjhB5FM54LevXunuzDKZLIMf5ycnHJ9/8uXL2fDhg0f/HwPD49M4037k5N9CEJ+2rp1KwsXLtR2GDpt1qxZuXJDTxDy08GDB/P8JkdKuT679PMgFuEzER8fz7lz55g0aRLDhw/Pte2uWbMGlUqVa9vTpri4OKZNmwaQb3cjPjdNmjShZ8+eGstMTExyfT/Lly/H3t7+g2vZFi5cSExMTOr/Bw8e5Pfff2fBggXY29unLq9Vq1ZOQxWEDMXHx6Ovn3tf+1u3buX27duMHj0617b5qZk1axadOnWiXbt22g7ls/fgwQPk8o/mfr1WHTx4kGXLlmU5eTl8+HDeBpSGSFy0SKVSkZSUhLGxsbZD+SDBwcEAWFtb5+p2DQwMcnV7wqetWLFifPXVV9oO473eLrgEBATw+++/065du3RNI9/XDOJjEhsbi5mZWbrlkiSRkJCQJ0mmkLGP9bvmc5HZZ0XIHUZGRtoO4ZNlaGiYb/v6LFLPCxcu0Lx5c6ysrDA1NcXb25v//vtPY52U9pCPHz+md+/eWFtbY2VlRZ8+fYiLi9NY98iRI9SpUwdra2vMzc0pXrw433///XvjkMlkDB8+nC1btlC6dGmMjIz4559/AJg7dy61atXCzs4OExMTKleunGH74JRt7N27lzJlymBkZETp0qVTt/Muz58/x8vLizJlyhAYGPjOda9du0aLFi2wtLTE3NycRo0acf78eY3Xy93dHYDx48cjk8ne2S8lpc3ztm3b+P7773FycsLMzIwvvviCFy9eaKz7dh+XtO39V69ejaenJ0ZGRlStWpVLly6le665uTl+fn60a9cOc3NzHBwcGDduHEqlUmNdlUrFwoULKV26NMbGxjg6OjJo0CDCw8M11pMkiZkzZ1KwYEFMTU1p0KABd+7ceefrlxK3g4MDANOmTUttCpT2DsaxY8eoW7cuZmZmWFtb07ZtW+7du/febWd0LiMiIhg9ejRubm4YGRnh5eXFzz//rFF7lZ3XMiAggD59+lCwYEGMjIxwdnambdu2H1WhOqufK4DffvuNatWqYWpqio2NDfXq1Uu9i+Th4cGdO3c4efJk6nlMW4P25MkTnjx5kifH8L7zBHD//n06deqEra0txsbGVKlShT///DNL21epVCxatIiyZctibGyMg4MDzZs3T22Wm/KeyagJ29vv55Tr6N27d+nevTs2NjbUqVMHUL+GrVu35tChQ1SpUgUTExNWrVoF5P57N+U16dKlCw4ODpiYmFC8eHEmTZoEwPHjx5HJZOzZsyfd87Zu3YpMJuPcuXOZvmYZtZ+HjNvfX758mWbNmmFvb4+JiQmFCxemb9++Gs/L62tRiszOV1a+995Wv359/vrrL54/f576mXj7O0ClUvHjjz9SsGBBjI2NadSoEY8fP063rax8R2cmISGBH374gWLFimFsbIyzszMdOnTQ+DzGxsbyzTffpL6/ihcvzty5c5EkKXWdD3mfv+91k8lkxMbGsnHjxtTXKKXGNrPPyvr165HJZFy7di1dHLNmzUJPTw8/P79MX4/o6GhGjx6Nh4cHRkZGFChQgCZNmnD16tV06969e5cGDRpgamqKq6srv/zyi8bjSUlJTJkyhcqVK2NlZYWZmRl169bl+PHjGuul/WwuWLAAd3d3TExM8Pb25vbt2+n2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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import matplotlib.pyplot as plt\n",
+ "\n",
+ "PINNED = [\" euro\", \" Italy\", \" currency\", \" boot\"]\n",
+ "ranks = {token: [] for token in PINNED}\n",
+ "layers = list(range(model.cfg.n_layers))\n",
+ "for token in PINNED:\n",
+ " token_id = model.to_single_token(token)\n",
+ " for layer in layers:\n",
+ " logits = result_jlens.lens_logits[layer][-1]\n",
+ " ranks[token].append(int((logits > logits[token_id]).sum().item()) + 1)\n",
+ "\n",
+ "fig, ax = plt.subplots(figsize=(8, 4))\n",
+ "for token, values in ranks.items():\n",
+ " ax.plot(layers, values, marker=\"o\", markersize=3, label=repr(token))\n",
+ "ax.set(yscale=\"log\", xlabel=\"layer\", ylabel=\"J-lens rank (log)\", title=f\"J-lens rank of pinned tokens — {PROMPT!r}\")\n",
+ "ax.axvline(25, color=\"gray\", ls=\":\", lw=1)\n",
+ "ax.legend()\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b41698de",
+ "metadata": {},
+ "source": [
+ "## 3. Intervening: swap France for China in lens coordinates\n",
+ "\n",
+ "The paper's *flexible generalization* protocol: pick source and target tokens, form\n",
+ "$V = [v_s, v_t]$ from their J-lens vectors, read the activation's lens coordinates $c = V^+ h$\n",
+ "(pseudoinverse), and write back $h \\leftarrow h + \\alpha\\, V(\\sigma(c) - c)$ where $\\sigma$\n",
+ "exchanges the two coordinates — leaving the orthogonal complement of the activation untouched.\n",
+ "The swap is clamped at every token position across an intermediate-layer band (layers 10–24 ≈\n",
+ "the paper's 38–92% workspace band)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "b2359547",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2026-07-11T09:06:29.590963Z",
+ "iopub.status.busy": "2026-07-11T09:06:29.590451Z",
+ "iopub.status.idle": "2026-07-11T09:06:30.101969Z",
+ "shell.execute_reply": "2026-07-11T09:06:30.101589Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "'Most people in France speak'\n",
+ " baseline : [' French', ' English', ' a', ' at', ' the']\n",
+ " swapped : [' Chinese', ' English', ' a', ' some', ' the']\n",
+ "'The capital of France is'\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ " baseline : [' a', ' the', ' one', ' also', ' home']\n",
+ " swapped : [' a', ' the', ' one', ' also', ' home']\n"
+ ]
+ }
+ ],
+ "source": [
+ "def show_next_tokens(prompt, hooks=None, k=5):\n",
+ " tokens = model.to_tokens(prompt)\n",
+ " with torch.no_grad():\n",
+ " if hooks:\n",
+ " with model.hooks(fwd_hooks=hooks):\n",
+ " logits = model(tokens)[0, -1].float()\n",
+ " else:\n",
+ " logits = model(tokens)[0, -1].float()\n",
+ " top = logits.topk(k).indices.tolist()\n",
+ " return [model.tokenizer.decode([t]) for t in top]\n",
+ "\n",
+ "BAND = range(10, 25)\n",
+ "swap = lens.swap_hooks(model, \" France\", \" China\", layers=BAND, alpha=1.0)\n",
+ "\n",
+ "for prompt in [\"Most people in France speak\", \"The capital of France is\"]:\n",
+ " print(f\"{prompt!r}\")\n",
+ " print(\" baseline :\", show_next_tokens(prompt))\n",
+ " print(\" swapped :\", show_next_tokens(prompt, hooks=swap))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "cdc8c44e",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2026-07-11T09:06:30.105260Z",
+ "iopub.status.busy": "2026-07-11T09:06:30.104879Z",
+ "iopub.status.idle": "2026-07-11T09:06:30.422053Z",
+ "shell.execute_reply": "2026-07-11T09:06:30.421595Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "'Most people in France speak': rank of ' Chinese' 347 -> 0\n",
+ "'The capital of France is': rank of ' Beijing' 968 -> 8\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Rank of the China-appropriate answer, before and after the swap\n",
+ "for prompt, answer in [(\"Most people in France speak\", \" Chinese\"), (\"The capital of France is\", \" Beijing\")]:\n",
+ " answer_id = model.to_single_token(answer)\n",
+ " tokens = model.to_tokens(prompt)\n",
+ " with torch.no_grad():\n",
+ " base = model(tokens)[0, -1].float()\n",
+ " with model.hooks(fwd_hooks=swap):\n",
+ " swapped = model(tokens)[0, -1].float()\n",
+ " base_rank = int((base > base[answer_id]).sum().item())\n",
+ " swap_rank = int((swapped > swapped[answer_id]).sum().item())\n",
+ " print(f\"{prompt!r}: rank of {answer!r} {base_rank} -> {swap_rank}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f6506c6a",
+ "metadata": {},
+ "source": [
+ "At $\\alpha=1$ the language template flips top-1 outright (`French` → `Chinese`), and the\n",
+ "China-appropriate answers jump hundreds of ranks on the others — the same swap redirecting\n",
+ "*different* downstream computations, which is the broadcast/workspace claim. (On this small base\n",
+ "model the capital template's top-1 is a filler word even unperturbed; the paper reports 42/48\n",
+ "top-1 success for country swaps on Claude Sonnet 4.5, and that doubling to $\\alpha=2$ recovers\n",
+ "some $\\alpha=1$ failures. On gemma-2-2b we instead observe $\\alpha=2$ overshooting into\n",
+ "verbalizing the injected concept — the swapped prompt's top-1 becomes ` China` itself — so\n",
+ "$\\alpha=1$ is the better default here.)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7020c7b5",
+ "metadata": {},
+ "source": [
+ "## 4. Steering along a J-lens vector\n",
+ "\n",
+ "`steering_hooks` adds a token's unit-normalized lens direction, scaled by the activation's mean\n",
+ "residual norm times `alpha` (the paper's directed-modulation protocol). `ablation_hooks`\n",
+ "(projecting a direction *out*) works the same way."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "89692d80",
+ "metadata": {
+ "execution": {
+ "iopub.execute_input": "2026-07-11T09:06:30.427385Z",
+ "iopub.status.busy": "2026-07-11T09:06:30.427165Z",
+ "iopub.status.idle": "2026-07-11T09:06:30.640333Z",
+ "shell.execute_reply": "2026-07-11T09:06:30.639945Z"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "baseline : [' the', ' a', ' my', ' visit', ' see']\n",
+ "steered : [' paris', ' Paris', 'Paris', ' París', 'paris']\n"
+ ]
+ }
+ ],
+ "source": [
+ "steer = lens.steering_hooks(model, \" Paris\", layers=range(10, 21), alpha=2.0)\n",
+ "prompt = \"This weekend I am planning a trip to\"\n",
+ "print(\"baseline :\", show_next_tokens(prompt))\n",
+ "print(\"steered :\", show_next_tokens(prompt, hooks=steer))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "00df913e",
+ "metadata": {},
+ "source": [
+ "## 5. Fitting your own lens\n",
+ "\n",
+ "For models without a published artifact, `JacobianLens.fit` reproduces the reference estimator on\n",
+ "any hooked model (raw weights) — one forward and `ceil(d_model / dim_batch)` backward passes per\n",
+ "prompt, deterministic. Quality saturates quickly: ~100 prompts of 128 tokens is usable (the\n",
+ "published lenses use up to 1000). Fits parallelize across prompt slices and combine exactly with\n",
+ "`merge`:\n",
+ "\n",
+ "```python\n",
+ "from datasets import load_dataset\n",
+ "\n",
+ "texts = load_dataset(\"Salesforce/wikitext\", \"wikitext-103-raw-v1\", split=\"train\", streaming=True)\n",
+ "prompts = [row[\"text\"] for row in texts.take(500) if len(row[\"text\"]) > 600][:100]\n",
+ "\n",
+ "lens = JacobianLens.fit(model, prompts, dim_batch=16, max_seq_len=128)\n",
+ "lens.save(\"gemma-2-2b_jlens.pt\") # official artifact format (+ provenance metadata)\n",
+ "# ...or shard: JacobianLens.merge([fit(model, chunk) for chunk in chunks])\n",
+ "```\n",
+ "\n",
+ "## References\n",
+ "\n",
+ "- Gurnee et al., [*Verbalizable Representations Form a Global Workspace in Language Models*](https://transformer-circuits.pub/2026/workspace/index.html), Transformer Circuits Thread, 2026\n",
+ "- Reference implementation: [`anthropics/jacobian-lens`](https://github.com/anthropics/jacobian-lens) (Apache-2.0)\n",
+ "- Published lenses: [`neuronpedia/jacobian-lens`](https://huggingface.co/neuronpedia/jacobian-lens) · interactive: [neuronpedia.org/jlens](https://www.neuronpedia.org/jlens)\n",
+ "- The logit lens: [nostalgebraist, 2020](https://www.lesswrong.com/posts/AcKRB8wDpdaN6v6ru/interpreting-gpt-the-logit-lens)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "transformer-lens",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.13"
+ },
+ "widgets": {
+ "application/vnd.jupyter.widget-state+json": {
+ "state": {
+ "1902af979017484c8d9c5a0fe643e833": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "2.0.0",
+ "model_name": "FloatProgressModel",
+ "state": {
+ "_dom_classes": [],
+ "_model_module": "@jupyter-widgets/controls",
+ "_model_module_version": "2.0.0",
+ "_model_name": "FloatProgressModel",
+ "_view_count": null,
+ "_view_module": "@jupyter-widgets/controls",
+ "_view_module_version": "2.0.0",
+ "_view_name": "ProgressView",
+ "bar_style": "success",
+ "description": "",
+ "description_allow_html": false,
+ "layout": "IPY_MODEL_292c5280a9cd49a89d0c2a77ffd4e936",
+ "max": 288.0,
+ "min": 0.0,
+ "orientation": "horizontal",
+ "style": "IPY_MODEL_99333fe6d4aa485bac5b5ec104cc5537",
+ "tabbable": null,
+ "tooltip": null,
+ "value": 288.0
+ }
+ },
+ "292c5280a9cd49a89d0c2a77ffd4e936": {
+ "model_module": "@jupyter-widgets/base",
+ "model_module_version": "2.0.0",
+ "model_name": "LayoutModel",
+ "state": {
+ "_model_module": "@jupyter-widgets/base",
+ "_model_module_version": "2.0.0",
+ "_model_name": "LayoutModel",
+ "_view_count": null,
+ "_view_module": "@jupyter-widgets/base",
+ "_view_module_version": "2.0.0",
+ "_view_name": "LayoutView",
+ "align_content": null,
+ "align_items": null,
+ "align_self": null,
+ "border_bottom": null,
+ "border_left": null,
+ "border_right": null,
+ "border_top": null,
+ "bottom": null,
+ "display": null,
+ "flex": null,
+ "flex_flow": null,
+ "grid_area": null,
+ "grid_auto_columns": null,
+ "grid_auto_flow": null,
+ "grid_auto_rows": null,
+ "grid_column": null,
+ "grid_gap": null,
+ "grid_row": null,
+ "grid_template_areas": null,
+ "grid_template_columns": null,
+ "grid_template_rows": null,
+ "height": null,
+ "justify_content": null,
+ "justify_items": null,
+ "left": null,
+ "margin": null,
+ "max_height": null,
+ "max_width": null,
+ "min_height": null,
+ "min_width": null,
+ "object_fit": null,
+ "object_position": null,
+ "order": null,
+ "overflow": null,
+ "padding": null,
+ "right": null,
+ "top": null,
+ "visibility": null,
+ "width": null
+ }
+ },
+ "8b9855cb054f4b06803233534b78ddf9": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "2.0.0",
+ "model_name": "HBoxModel",
+ "state": {
+ "_dom_classes": [],
+ "_model_module": "@jupyter-widgets/controls",
+ "_model_module_version": "2.0.0",
+ "_model_name": "HBoxModel",
+ "_view_count": null,
+ "_view_module": "@jupyter-widgets/controls",
+ "_view_module_version": "2.0.0",
+ "_view_name": "HBoxView",
+ "box_style": "",
+ "children": [
+ "IPY_MODEL_c2743d998e5841b3b35e40721586659a",
+ "IPY_MODEL_1902af979017484c8d9c5a0fe643e833",
+ "IPY_MODEL_ef3400c12a834c5db3f95519c0b9e78f"
+ ],
+ "layout": "IPY_MODEL_c357c3f6dcb342fa90b16ca6949bcd3e",
+ "tabbable": null,
+ "tooltip": null
+ }
+ },
+ "969321ee62ed49049d01ab89c6724577": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "2.0.0",
+ "model_name": "HTMLStyleModel",
+ "state": {
+ "_model_module": "@jupyter-widgets/controls",
+ "_model_module_version": "2.0.0",
+ "_model_name": "HTMLStyleModel",
+ "_view_count": null,
+ "_view_module": "@jupyter-widgets/base",
+ "_view_module_version": "2.0.0",
+ "_view_name": "StyleView",
+ "background": null,
+ "description_width": "",
+ "font_size": null,
+ "text_color": null
+ }
+ },
+ "99333fe6d4aa485bac5b5ec104cc5537": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "2.0.0",
+ "model_name": "ProgressStyleModel",
+ "state": {
+ "_model_module": "@jupyter-widgets/controls",
+ "_model_module_version": "2.0.0",
+ "_model_name": "ProgressStyleModel",
+ "_view_count": null,
+ "_view_module": "@jupyter-widgets/base",
+ "_view_module_version": "2.0.0",
+ "_view_name": "StyleView",
+ "bar_color": null,
+ "description_width": ""
+ }
+ },
+ "aca2228a9ea14b069bc2d6a5fe9d5bcb": {
+ "model_module": "@jupyter-widgets/base",
+ "model_module_version": "2.0.0",
+ "model_name": "LayoutModel",
+ "state": {
+ "_model_module": "@jupyter-widgets/base",
+ "_model_module_version": "2.0.0",
+ "_model_name": "LayoutModel",
+ "_view_count": null,
+ "_view_module": "@jupyter-widgets/base",
+ "_view_module_version": "2.0.0",
+ "_view_name": "LayoutView",
+ "align_content": null,
+ "align_items": null,
+ "align_self": null,
+ "border_bottom": null,
+ "border_left": null,
+ "border_right": null,
+ "border_top": null,
+ "bottom": null,
+ "display": null,
+ "flex": null,
+ "flex_flow": null,
+ "grid_area": null,
+ "grid_auto_columns": null,
+ "grid_auto_flow": null,
+ "grid_auto_rows": null,
+ "grid_column": null,
+ "grid_gap": null,
+ "grid_row": null,
+ "grid_template_areas": null,
+ "grid_template_columns": null,
+ "grid_template_rows": null,
+ "height": null,
+ "justify_content": null,
+ "justify_items": null,
+ "left": null,
+ "margin": null,
+ "max_height": null,
+ "max_width": null,
+ "min_height": null,
+ "min_width": null,
+ "object_fit": null,
+ "object_position": null,
+ "order": null,
+ "overflow": null,
+ "padding": null,
+ "right": null,
+ "top": null,
+ "visibility": null,
+ "width": null
+ }
+ },
+ "c2743d998e5841b3b35e40721586659a": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "2.0.0",
+ "model_name": "HTMLModel",
+ "state": {
+ "_dom_classes": [],
+ "_model_module": "@jupyter-widgets/controls",
+ "_model_module_version": "2.0.0",
+ "_model_name": "HTMLModel",
+ "_view_count": null,
+ "_view_module": "@jupyter-widgets/controls",
+ "_view_module_version": "2.0.0",
+ "_view_name": "HTMLView",
+ "description": "",
+ "description_allow_html": false,
+ "layout": "IPY_MODEL_aca2228a9ea14b069bc2d6a5fe9d5bcb",
+ "placeholder": "",
+ "style": "IPY_MODEL_969321ee62ed49049d01ab89c6724577",
+ "tabbable": null,
+ "tooltip": null,
+ "value": "Loading weights: 100%"
+ }
+ },
+ "c357c3f6dcb342fa90b16ca6949bcd3e": {
+ "model_module": "@jupyter-widgets/base",
+ "model_module_version": "2.0.0",
+ "model_name": "LayoutModel",
+ "state": {
+ "_model_module": "@jupyter-widgets/base",
+ "_model_module_version": "2.0.0",
+ "_model_name": "LayoutModel",
+ "_view_count": null,
+ "_view_module": "@jupyter-widgets/base",
+ "_view_module_version": "2.0.0",
+ "_view_name": "LayoutView",
+ "align_content": null,
+ "align_items": null,
+ "align_self": null,
+ "border_bottom": null,
+ "border_left": null,
+ "border_right": null,
+ "border_top": null,
+ "bottom": null,
+ "display": null,
+ "flex": null,
+ "flex_flow": null,
+ "grid_area": null,
+ "grid_auto_columns": null,
+ "grid_auto_flow": null,
+ "grid_auto_rows": null,
+ "grid_column": null,
+ "grid_gap": null,
+ "grid_row": null,
+ "grid_template_areas": null,
+ "grid_template_columns": null,
+ "grid_template_rows": null,
+ "height": null,
+ "justify_content": null,
+ "justify_items": null,
+ "left": null,
+ "margin": null,
+ "max_height": null,
+ "max_width": null,
+ "min_height": null,
+ "min_width": null,
+ "object_fit": null,
+ "object_position": null,
+ "order": null,
+ "overflow": null,
+ "padding": null,
+ "right": null,
+ "top": null,
+ "visibility": null,
+ "width": null
+ }
+ },
+ "e6e8ba2cc68e4d6491d62a406a3d4816": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "2.0.0",
+ "model_name": "HTMLStyleModel",
+ "state": {
+ "_model_module": "@jupyter-widgets/controls",
+ "_model_module_version": "2.0.0",
+ "_model_name": "HTMLStyleModel",
+ "_view_count": null,
+ "_view_module": "@jupyter-widgets/base",
+ "_view_module_version": "2.0.0",
+ "_view_name": "StyleView",
+ "background": null,
+ "description_width": "",
+ "font_size": null,
+ "text_color": null
+ }
+ },
+ "ef3400c12a834c5db3f95519c0b9e78f": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_module_version": "2.0.0",
+ "model_name": "HTMLModel",
+ "state": {
+ "_dom_classes": [],
+ "_model_module": "@jupyter-widgets/controls",
+ "_model_module_version": "2.0.0",
+ "_model_name": "HTMLModel",
+ "_view_count": null,
+ "_view_module": "@jupyter-widgets/controls",
+ "_view_module_version": "2.0.0",
+ "_view_name": "HTMLView",
+ "description": "",
+ "description_allow_html": false,
+ "layout": "IPY_MODEL_f3617aa9615142548cfdcf87b0aaccda",
+ "placeholder": "",
+ "style": "IPY_MODEL_e6e8ba2cc68e4d6491d62a406a3d4816",
+ "tabbable": null,
+ "tooltip": null,
+ "value": " 288/288 [00:01<00:00, 125.60it/s]"
+ }
+ },
+ "f3617aa9615142548cfdcf87b0aaccda": {
+ "model_module": "@jupyter-widgets/base",
+ "model_module_version": "2.0.0",
+ "model_name": "LayoutModel",
+ "state": {
+ "_model_module": "@jupyter-widgets/base",
+ "_model_module_version": "2.0.0",
+ "_model_name": "LayoutModel",
+ "_view_count": null,
+ "_view_module": "@jupyter-widgets/base",
+ "_view_module_version": "2.0.0",
+ "_view_name": "LayoutView",
+ "align_content": null,
+ "align_items": null,
+ "align_self": null,
+ "border_bottom": null,
+ "border_left": null,
+ "border_right": null,
+ "border_top": null,
+ "bottom": null,
+ "display": null,
+ "flex": null,
+ "flex_flow": null,
+ "grid_area": null,
+ "grid_auto_columns": null,
+ "grid_auto_flow": null,
+ "grid_auto_rows": null,
+ "grid_column": null,
+ "grid_gap": null,
+ "grid_row": null,
+ "grid_template_areas": null,
+ "grid_template_columns": null,
+ "grid_template_rows": null,
+ "height": null,
+ "justify_content": null,
+ "justify_items": null,
+ "left": null,
+ "margin": null,
+ "max_height": null,
+ "max_width": null,
+ "min_height": null,
+ "min_width": null,
+ "object_fit": null,
+ "object_position": null,
+ "order": null,
+ "overflow": null,
+ "padding": null,
+ "right": null,
+ "top": null,
+ "visibility": null,
+ "width": null
+ }
+ }
+ },
+ "version_major": 2,
+ "version_minor": 0
+ }
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/tests/integration/test_jacobian_lens.py b/tests/integration/test_jacobian_lens.py
new file mode 100644
index 000000000..e542612c8
--- /dev/null
+++ b/tests/integration/test_jacobian_lens.py
@@ -0,0 +1,186 @@
+"""Integration tests for the Jacobian lens tool on gpt2 (cached).
+
+These exercise the real-model paths: loading the published gpt2-small lens from
+the Hugging Face Hub (``neuronpedia/jacobian-lens``, ~13 MB), readout invariants
+(the final-layer row equals the model's own logits; late-layer readouts align
+with the model output), HookedTransformer/TransformerBridge agreement in the raw
+weight basis, an exact fit/merge consistency identity, and a causal steering
+smoke test.
+
+gpt2 is in the CI model cache, so these live in ``integration/`` per
+``tests/AGENTS.md``; the small fits are marked ``slow``.
+"""
+
+import pytest
+import torch
+
+PROMPT = "The Eiffel Tower is in the city of"
+LENS_REPO = "neuronpedia/jacobian-lens"
+LENS_FILE = "gpt2-small/jlens/Salesforce-wikitext/gpt2_jacobian_lens.pt"
+
+# Long enough to clear the default 16-position source skip.
+FIT_PROMPTS = [
+ "The industrial revolution transformed the economies of Europe during the "
+ "nineteenth century, as steam power, railways, and mechanized factories "
+ "reorganized both production and daily life in the growing cities.",
+ "Astronomers studying distant galaxies rely on the redshift of spectral "
+ "lines to estimate how quickly those galaxies recede, which in turn "
+ "constrains the expansion history of the observable universe.",
+]
+
+
+@pytest.fixture(scope="module")
+def ht_gpt2():
+ from transformer_lens import HookedTransformer
+
+ return HookedTransformer.from_pretrained_no_processing("gpt2", device="cpu")
+
+
+@pytest.fixture(scope="module")
+def bridge_gpt2():
+ from transformer_lens.model_bridge import TransformerBridge
+
+ return TransformerBridge.boot_transformers("gpt2", dtype=torch.float32, device="cpu")
+
+
+@pytest.fixture(scope="module")
+def published_lens(ht_gpt2):
+ from transformer_lens.tools.analysis import JacobianLens
+
+ return JacobianLens.from_pretrained(LENS_REPO, filename=LENS_FILE, model=ht_gpt2)
+
+
+def test_published_lens_loads_and_validates(published_lens, ht_gpt2):
+ assert published_lens.d_model == 768
+ assert published_lens.source_layers == list(range(11))
+ assert published_lens.n_prompts > 0
+ assert published_lens.validate_model(ht_gpt2) is published_lens
+
+
+def test_final_layer_readout_equals_model_logits(published_lens, ht_gpt2):
+ result = published_lens.readout(ht_gpt2, PROMPT, layers=[11], positions=[-1])
+ torch.testing.assert_close(result.lens_logits[11], result.model_logits)
+
+
+def test_late_layer_readout_aligns_with_model_output(published_lens, ht_gpt2):
+ """J_l -> I near the output: the rank of the model's top-1 token under the
+ J-lens readout must collapse from thousands early to near zero late.
+ (Top-k overlap is deliberately not asserted mid-stack — there the lens
+ surfaces verbalizable content, not output predictions.)
+
+ Measured on gpt2 for this prompt: rank 8577 at L0, 12 at L10, 0 at L11.
+ """
+ result = published_lens.readout(ht_gpt2, PROMPT, layers=[0, 10, 11], positions=[-1])
+ model_top1 = result.model_logits[-1].argmax().item()
+
+ def rank_of_model_top1(layer):
+ logits = result.lens_logits[layer][-1]
+ return int((logits > logits[model_top1]).sum().item())
+
+ assert rank_of_model_top1(0) >= 1000
+ assert rank_of_model_top1(10) <= 50
+ assert rank_of_model_top1(11) == 0
+
+
+def test_logit_lens_baseline_differs_mid_stack(published_lens, ht_gpt2):
+ """use_jacobian=False is the logit lens; mid-stack the two must diverge
+ (the whole point of the lens) while sharing the identical code path."""
+ lens_result = published_lens.readout(ht_gpt2, PROMPT, layers=[5], positions=[-1])
+ baseline = published_lens.readout(
+ ht_gpt2, PROMPT, layers=[5], positions=[-1], use_jacobian=False
+ )
+ assert not torch.allclose(lens_result.lens_logits[5], baseline.lens_logits[5])
+
+
+def test_bridge_and_ht_readouts_agree(published_lens, ht_gpt2, bridge_gpt2):
+ """Raw-basis Bridge and no-processing HT must produce near-identical
+ readouts (same weights, fp32); allow one near-tie swap in the top-8."""
+ ht_result = published_lens.readout(ht_gpt2, PROMPT, positions=[-1])
+ bridge_result = published_lens.readout(bridge_gpt2, PROMPT, positions=[-1])
+ assert ht_result.tokens.tolist() == bridge_result.tokens.tolist()
+ for layer in published_lens.source_layers:
+ ht_top8 = ht_result.lens_logits[layer][-1].topk(8).indices.tolist()
+ bridge_top8 = bridge_result.lens_logits[layer][-1].topk(8).indices.tolist()
+ assert len(set(ht_top8) & set(bridge_top8)) >= 7, f"layer {layer}"
+ assert ht_top8[0] == bridge_top8[0], f"layer {layer} top-1 mismatch"
+
+
+def test_steering_raises_target_logit(published_lens, ht_gpt2):
+ """Adding a token's J-lens direction mid-stack must raise that token's
+ output logit (directional causal smoke test)."""
+ target = " Paris"
+ target_id = ht_gpt2.to_single_token(target)
+ tokens = ht_gpt2.to_tokens(PROMPT)
+ with torch.no_grad():
+ baseline = ht_gpt2(tokens)[0, -1, target_id].item()
+ hooks = published_lens.steering_hooks(ht_gpt2, target, layers=[6, 7, 8], alpha=6.0)
+ with ht_gpt2.hooks(fwd_hooks=hooks):
+ steered = ht_gpt2(tokens)[0, -1, target_id].item()
+ assert steered > baseline
+
+
+def test_processed_models_are_refused(published_lens):
+ from transformer_lens import HookedTransformer
+ from transformer_lens.tools.analysis import JacobianLens
+
+ processed = HookedTransformer.from_pretrained("gpt2", device="cpu")
+ with pytest.raises(ValueError, match="fold_ln"):
+ published_lens.validate_model(processed)
+ with pytest.raises(ValueError, match="fold_ln"):
+ JacobianLens.fit(processed, FIT_PROMPTS, show_progress=False)
+ # fold_ln=False still centers weights (normalization_type stays "LN"), so the
+ # centered-unembed signature is the marker that must catch it.
+ half_processed = HookedTransformer.from_pretrained("gpt2", fold_ln=False, device="cpu")
+ with pytest.raises(ValueError, match="mean-centered"):
+ published_lens.validate_model(half_processed)
+
+
+@pytest.mark.slow
+def test_fit_merge_consistency_and_finiteness(ht_gpt2):
+ """Exact identity: fitting two prompts jointly equals merging two
+ single-prompt fits (the estimator averages prompts unweighted and merge
+ weights by n_prompts)."""
+ from transformer_lens.tools.analysis import JacobianLens
+
+ kwargs = dict(
+ source_layers=[0, 5, 10],
+ dim_batch=96,
+ max_seq_len=32,
+ show_progress=False,
+ )
+ joint = JacobianLens.fit(ht_gpt2, FIT_PROMPTS, **kwargs)
+ merged = JacobianLens.merge(
+ [JacobianLens.fit(ht_gpt2, [prompt], **kwargs) for prompt in FIT_PROMPTS]
+ )
+ assert joint.n_prompts == merged.n_prompts == 2
+ for layer in joint.source_layers:
+ assert torch.isfinite(joint.jacobians[layer]).all()
+ torch.testing.assert_close(
+ joint.jacobians[layer], merged.jacobians[layer], atol=1e-6, rtol=1e-5
+ )
+
+
+@pytest.mark.slow
+def test_small_fit_converges_toward_published_lens(published_lens, ht_gpt2):
+ """A native 2-prompt fit must already point in the published lens's
+ direction (measured: cosine 0.51 / 0.66 / 0.91 at layers 0 / 5 / 10 vs the
+ n=277 published gpt2 lens) — the estimator converges fast, and any basis
+ or orientation bug would drive these toward zero."""
+ from transformer_lens.tools.analysis import JacobianLens
+
+ fitted = JacobianLens.fit(
+ ht_gpt2,
+ FIT_PROMPTS,
+ source_layers=[0, 5, 10],
+ dim_batch=96,
+ max_seq_len=32,
+ show_progress=False,
+ )
+ cosines = {
+ layer: torch.nn.functional.cosine_similarity(
+ fitted.jacobians[layer].flatten(), published_lens.jacobians[layer].flatten(), dim=0
+ ).item()
+ for layer in fitted.source_layers
+ }
+ assert all(value >= 0.3 for value in cosines.values()), cosines
+ assert cosines[10] >= 0.75, cosines
diff --git a/tests/unit/tools/test_jacobian_lens.py b/tests/unit/tools/test_jacobian_lens.py
new file mode 100644
index 000000000..401ac9426
--- /dev/null
+++ b/tests/unit/tools/test_jacobian_lens.py
@@ -0,0 +1,296 @@
+"""Unit tests for the Jacobian lens: estimator correctness on a closed-form toy
+model, artifact round-trips, merge weighting, and the raw-weights guards.
+
+The toy model's blocks are position-independent linear residual updates
+``h <- h + W h``, so the exact Jacobian from block ``l``'s output to the final
+block's output is the matrix product ``(I + W_{n-1}) ... (I + W_{l+1})`` — the
+fit result can be checked against a closed form, matching the reference
+implementation's own orientation test.
+"""
+
+from types import SimpleNamespace
+from unittest.mock import MagicMock
+
+import pytest
+import torch
+import torch.nn as nn
+
+from transformer_lens import HookedRootModule
+from transformer_lens.hook_points import HookPoint
+from transformer_lens.model_bridge import TransformerBridge
+from transformer_lens.tools.analysis import JacobianLens
+
+D_MODEL = 6
+N_LAYERS = 4
+D_VOCAB = 11
+SEQ_LEN = 9
+SKIP_FIRST = 2
+
+
+class _ToyBlock(nn.Module):
+ def __init__(self, d_model: int):
+ super().__init__()
+ self.linear = nn.Linear(d_model, d_model, bias=False)
+ nn.init.normal_(self.linear.weight, std=0.2)
+ self.hook_resid_post = HookPoint()
+
+ def forward(self, resid):
+ return self.hook_resid_post(resid + self.linear(resid))
+
+
+class _ToyResidModel(HookedRootModule):
+ """Minimal HookedRootModule exposing the surface JacobianLens needs."""
+
+ def __init__(self, normalization_type: str = "LN"):
+ super().__init__()
+ torch.manual_seed(0)
+ self.cfg = SimpleNamespace(
+ n_layers=N_LAYERS,
+ d_model=D_MODEL,
+ d_vocab=D_VOCAB,
+ normalization_type=normalization_type,
+ output_logits_soft_cap=None,
+ model_name="toy",
+ )
+ self.embed = nn.Embedding(D_VOCAB, D_MODEL)
+ self.blocks = nn.ModuleList([_ToyBlock(D_MODEL) for _ in range(N_LAYERS)])
+ self.ln_final = nn.Identity()
+ self.unembed = nn.Linear(D_MODEL, D_VOCAB, bias=False)
+ self.setup()
+
+ @property
+ def W_U(self):
+ return self.unembed.weight.T # [d_model, d_vocab]
+
+ def to_tokens(self, prompt: str):
+ ids = [(3 * i + len(prompt)) % D_VOCAB for i in range(SEQ_LEN)]
+ return torch.tensor([ids], dtype=torch.long)
+
+ def to_single_token(self, string: str) -> int:
+ return len(string) % D_VOCAB
+
+ def forward(self, tokens, return_type="logits"):
+ resid = self.embed(tokens)
+ for block in self.blocks:
+ resid = block(resid)
+ if return_type is None:
+ return None
+ return self.unembed(self.ln_final(resid))
+
+
+def _closed_form_jacobian(model: _ToyResidModel, layer: int) -> torch.Tensor:
+ """Exact d h_final / d h_layer for the linear toy: prod of (I + W_k)."""
+ jacobian = torch.eye(D_MODEL)
+ for k in range(layer + 1, N_LAYERS):
+ jacobian = (torch.eye(D_MODEL) + model.blocks[k].linear.weight) @ jacobian
+ return jacobian
+
+
+@pytest.fixture(scope="module")
+def toy_model():
+ return _ToyResidModel()
+
+
+@pytest.fixture(scope="module")
+def fitted_lens(toy_model):
+ return JacobianLens.fit(
+ toy_model,
+ ["a toy prompt", "another toy prompt"],
+ dim_batch=4, # not a divisor of d_model=6: exercises the partial final pass
+ skip_first_positions=SKIP_FIRST,
+ show_progress=False,
+ )
+
+
+def test_fit_recovers_closed_form_jacobians(toy_model, fitted_lens):
+ assert fitted_lens.source_layers == [0, 1, 2]
+ assert fitted_lens.n_prompts == 2
+ for layer in fitted_lens.source_layers:
+ expected = _closed_form_jacobian(toy_model, layer)
+ torch.testing.assert_close(fitted_lens.jacobians[layer], expected, atol=1e-5, rtol=1e-4)
+
+
+def test_transport_orientation(toy_model, fitted_lens):
+ resid = torch.randn(3, D_MODEL)
+ expected = resid @ _closed_form_jacobian(toy_model, 2).T
+ torch.testing.assert_close(fitted_lens.transport(resid, 2), expected, atol=1e-4, rtol=1e-3)
+
+
+def test_readout_final_layer_matches_model_output(toy_model, fitted_lens):
+ result = fitted_lens.readout(toy_model, "a toy prompt")
+ torch.testing.assert_close(result.lens_logits[N_LAYERS - 1], result.model_logits)
+
+
+def test_transported_readout_approximates_model_output(toy_model, fitted_lens):
+ # The toy is exactly linear, so transporting from ANY layer must reproduce
+ # the model's own logits.
+ result = fitted_lens.readout(toy_model, "a toy prompt", layers=[0, 2])
+ for layer in (0, 2):
+ torch.testing.assert_close(
+ result.lens_logits[layer], result.model_logits, atol=1e-3, rtol=1e-3
+ )
+
+
+def test_save_load_roundtrip(tmp_path, fitted_lens):
+ path = str(tmp_path / "lens.pt")
+ fitted_lens.save(path)
+ loaded = JacobianLens.load(path)
+ assert loaded.source_layers == fitted_lens.source_layers
+ assert loaded.n_prompts == fitted_lens.n_prompts
+ assert loaded.d_model == fitted_lens.d_model
+ assert loaded.metadata["model_name"] == "toy"
+ for layer in loaded.source_layers:
+ # fp16 storage round-trip tolerance, matching the reference tests.
+ torch.testing.assert_close(
+ loaded.jacobians[layer], fitted_lens.jacobians[layer], atol=2e-3, rtol=2e-3
+ )
+ assert loaded.jacobians[layer].dtype == torch.float32
+
+
+def test_load_official_format_without_metadata(tmp_path):
+ path = str(tmp_path / "official.pt")
+ torch.save(
+ {
+ "J": {0: torch.eye(D_MODEL, dtype=torch.float16)},
+ "n_prompts": 7,
+ "source_layers": [0],
+ "d_model": D_MODEL,
+ },
+ path,
+ )
+ lens = JacobianLens.load(path)
+ assert lens.n_prompts == 7
+ assert lens.metadata == {}
+ assert lens.jacobians[0].dtype == torch.float32
+
+
+def test_load_rejects_fit_checkpoints(tmp_path):
+ path = str(tmp_path / "ckpt.pt")
+ torch.save({"jacobian_sum": {}, "n_done": 3}, path)
+ with pytest.raises(ValueError, match="no 'J' key"):
+ JacobianLens.load(path)
+
+
+def test_merge_is_n_prompts_weighted():
+ lens_a = JacobianLens({0: torch.ones(D_MODEL, D_MODEL)}, n_prompts=2, d_model=D_MODEL)
+ lens_b = JacobianLens({0: 4 * torch.ones(D_MODEL, D_MODEL)}, n_prompts=6, d_model=D_MODEL)
+ merged = JacobianLens.merge([lens_a, lens_b])
+ assert merged.n_prompts == 8
+ torch.testing.assert_close(merged.jacobians[0], torch.full((D_MODEL, D_MODEL), 3.25))
+
+
+def test_merge_rejects_mismatched_lenses():
+ lens_a = JacobianLens({0: torch.ones(D_MODEL, D_MODEL)}, n_prompts=1, d_model=D_MODEL)
+ lens_b = JacobianLens({1: torch.ones(D_MODEL, D_MODEL)}, n_prompts=1, d_model=D_MODEL)
+ with pytest.raises(ValueError, match="must share"):
+ JacobianLens.merge([lens_a, lens_b])
+ with pytest.raises(ValueError, match="empty sequence"):
+ JacobianLens.merge([])
+
+
+def test_validate_model_rejects_wrong_d_model(toy_model):
+ lens = JacobianLens({0: torch.ones(3, 3)}, n_prompts=1, d_model=3)
+ with pytest.raises(ValueError, match="d_model"):
+ lens.validate_model(toy_model)
+
+
+def test_validate_model_rejects_out_of_range_layers(toy_model):
+ lens = JacobianLens({N_LAYERS + 5: torch.ones(D_MODEL, D_MODEL)}, n_prompts=1, d_model=D_MODEL)
+ with pytest.raises(ValueError, match="different model"):
+ lens.validate_model(toy_model)
+
+
+def test_folded_layernorm_is_rejected(fitted_lens):
+ processed = _ToyResidModel(normalization_type="LNPre")
+ with pytest.raises(ValueError, match="fold_ln"):
+ fitted_lens.validate_model(processed)
+ with pytest.raises(ValueError, match="fold_ln"):
+ JacobianLens.fit(processed, ["a toy prompt"], show_progress=False)
+
+
+def test_centered_unembed_is_rejected(fitted_lens):
+ # center_unembed leaves W_U exactly row-mean-centered — the from_pretrained
+ # fold_ln=False escape hatch the guard must still catch.
+ centered = _ToyResidModel()
+ with torch.no_grad():
+ centered.unembed.weight -= centered.unembed.weight.mean(dim=0, keepdim=True)
+ with pytest.raises(ValueError, match="mean-centered"):
+ fitted_lens.validate_model(centered)
+
+
+def test_readout_bounds_checks(toy_model, fitted_lens):
+ with pytest.raises(ValueError, match="out of range"):
+ fitted_lens.readout(toy_model, "a toy prompt", layers=[99], use_jacobian=False)
+ with pytest.raises(ValueError, match="out of range"):
+ fitted_lens.readout(toy_model, "a toy prompt", positions=[-2 * SEQ_LEN])
+
+
+def _mock_bridge(compatibility_mode=False):
+ bridge = MagicMock(spec=TransformerBridge)
+ bridge.cfg = SimpleNamespace(d_model=D_MODEL, n_layers=N_LAYERS, normalization_type="LN")
+ bridge.compatibility_mode = compatibility_mode
+ return bridge
+
+
+def test_compatibility_mode_bridge_is_rejected():
+ lens = JacobianLens({0: torch.ones(D_MODEL, D_MODEL)}, n_prompts=1, d_model=D_MODEL)
+ with pytest.raises(ValueError, match="compatibility mode"):
+ lens.validate_model(_mock_bridge(compatibility_mode=True))
+
+
+def test_raw_bridge_passes_validation():
+ lens = JacobianLens({0: torch.ones(D_MODEL, D_MODEL)}, n_prompts=1, d_model=D_MODEL)
+ assert lens.validate_model(_mock_bridge()) is lens
+
+
+def test_fit_skips_short_prompts(toy_model):
+ with pytest.raises(ValueError, match="too short to contribute"):
+ with pytest.warns(UserWarning, match="skipping prompt"):
+ JacobianLens.fit(
+ toy_model,
+ ["a toy prompt"],
+ dim_batch=6,
+ skip_first_positions=SEQ_LEN, # every prompt too short -> skipped
+ show_progress=False,
+ )
+
+
+def test_intervention_hooks_have_valid_names_and_run(toy_model, fitted_lens):
+ swap_hooks = fitted_lens.swap_hooks(toy_model, 3, 5, layers=[1, 2])
+ steer_hooks = fitted_lens.steering_hooks(toy_model, 3, layers=[1], alpha=2.0)
+ ablate_hooks = fitted_lens.ablation_hooks(toy_model, [3, 5], layers=[2])
+ assert [name for name, _ in swap_hooks] == [
+ "blocks.1.hook_resid_post",
+ "blocks.2.hook_resid_post",
+ ]
+ tokens = toy_model.to_tokens("a toy prompt")
+ baseline = toy_model(tokens)
+ for hooks in (swap_hooks, steer_hooks, ablate_hooks):
+ with toy_model.hooks(fwd_hooks=hooks):
+ intervened = toy_model(tokens)
+ assert intervened.shape == baseline.shape
+ assert torch.isfinite(intervened).all()
+ assert not torch.allclose(intervened, baseline)
+
+
+def test_swap_leaves_orthogonal_complement_unchanged(toy_model, fitted_lens):
+ layer = 2
+ vectors = fitted_lens.lens_vectors(toy_model, [3, 5], layer) # [2, d_model]
+ hooks = fitted_lens.swap_hooks(toy_model, 3, 5, layers=[layer])
+ tokens = toy_model.to_tokens("a toy prompt")
+ _, base_cache = toy_model.run_with_cache(tokens)
+ with toy_model.hooks(fwd_hooks=hooks):
+ _, swap_cache = toy_model.run_with_cache(tokens)
+ name = f"blocks.{layer}.hook_resid_post"
+ delta = (swap_cache[name] - base_cache[name]).reshape(-1, D_MODEL)
+ # The intervention only moves activations within span{v_s, v_t}.
+ basis, _ = torch.linalg.qr(vectors.T) # orthonormal basis of the span
+ orthogonal_part = delta - (delta @ basis) @ basis.T
+ assert orthogonal_part.abs().max().item() < 1e-4
+
+
+def test_exports():
+ from transformer_lens.tools import analysis
+
+ assert analysis.JacobianLens is JacobianLens
+ assert hasattr(analysis, "JacobianLensReadout")
diff --git a/transformer_lens/tools/analysis/__init__.py b/transformer_lens/tools/analysis/__init__.py
index bdd01264f..7199a975b 100644
--- a/transformer_lens/tools/analysis/__init__.py
+++ b/transformer_lens/tools/analysis/__init__.py
@@ -9,6 +9,9 @@
layers, or attention heads.
- direct_path_patching: Direct path patching for head-to-head circuit
analysis.
+ - jacobian_lens: The Jacobian lens (J-lens) — per-layer causal transport to
+ the output vocabulary basis, with loading of published lens artifacts,
+ native fitting, readouts, and interventions.
"""
from transformer_lens.tools.analysis.direct_logit_attribution import (
@@ -19,9 +22,15 @@
get_act_patch_direct_path,
get_act_patch_direct_path_all_sources,
)
+from transformer_lens.tools.analysis.jacobian_lens import (
+ JacobianLens,
+ JacobianLensReadout,
+)
__all__ = [
"DirectLogitAttribution",
+ "JacobianLens",
+ "JacobianLensReadout",
"direct_logit_attribution",
"get_act_patch_direct_path",
"get_act_patch_direct_path_all_sources",
diff --git a/transformer_lens/tools/analysis/jacobian_lens.py b/transformer_lens/tools/analysis/jacobian_lens.py
new file mode 100644
index 000000000..85f1fef7f
--- /dev/null
+++ b/transformer_lens/tools/analysis/jacobian_lens.py
@@ -0,0 +1,973 @@
+"""Jacobian Lens (J-lens).
+
+The Jacobian lens characterizes an intermediate residual-stream activation by its
+first-order causal effect on the model's output, averaged over a corpus of contexts.
+For each layer :math:`\\ell` it fits a single :math:`d_{model} \\times d_{model}` matrix
+
+.. math::
+
+ J_\\ell = \\mathbb{E}_{\\text{prompt},\\,t,\\,t' \\geq t}
+ \\left[ \\partial h_{\\text{final},t'} / \\partial h_{\\ell,t} \\right]
+
+mapping the output of block :math:`\\ell` to the final block's output (pre final
+norm). Reading the lens applies the model's own final norm and unembedding:
+:math:`\\text{lens}(h_\\ell) = \\mathrm{softmax}(W_U\\,\\mathrm{norm}(J_\\ell h_\\ell))`.
+The logit lens is the special case :math:`J_\\ell = I`. The rows of
+:math:`W_U J_\\ell` ("J-lens vectors") are residual-stream directions associated
+with single vocabulary tokens, and support causal interventions: steering,
+ablation, and exchanging one concept for another via a pseudoinverse coordinate
+swap.
+
+Introduced in `Verbalizable Representations Form a Global Workspace in Language
+Models `_ (Gurnee et
+al., Transformer Circuits Thread, 2026). The fitting estimator and the artifact
+format follow Anthropic's Apache-2.0 reference implementation
+(`anthropics/jacobian-lens `_), so
+lenses fitted here interoperate with artifacts published on the Hugging Face Hub
+(e.g. `neuronpedia/jacobian-lens
+`_); the interventions are
+implemented from the paper's Methods section.
+
+Warning:
+ Published lens artifacts are fitted on **raw** HuggingFace activations. Use
+ ``TransformerBridge.boot_transformers`` (raw weights by default) or
+ ``HookedTransformer.from_pretrained_no_processing``. Weight processing
+ (``fold_ln``, ``center_writing_weights``, ``center_unembed``) changes the
+ residual basis, so :class:`JacobianLens` refuses processed models rather
+ than returning silently wrong readouts.
+
+Example::
+
+ import torch
+ from transformer_lens.model_bridge import TransformerBridge
+ from transformer_lens.tools.analysis import JacobianLens
+
+ model = TransformerBridge.boot_transformers("gpt2", device="cpu")
+ lens = JacobianLens.from_pretrained(
+ "neuronpedia/jacobian-lens",
+ filename="gpt2-small/jlens/Salesforce-wikitext/gpt2_jacobian_lens.pt",
+ model=model,
+ )
+ result = lens.readout(model, "The Eiffel Tower is in the city of")
+ print(result.top_tokens(model.tokenizer, k=5)[8][-1]) # layer 8, final position
+"""
+
+import warnings
+from dataclasses import dataclass
+from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
+
+import torch
+from jaxtyping import Float, Int
+from tqdm.auto import tqdm
+
+from transformer_lens.utilities.activation_functions import apply_softcap
+
+TokenInput = Union[str, int]
+
+# Fitting excludes early positions (attention sinks with atypical residual statistics)
+# and the final position (no next-token target), matching the reference implementation.
+DEFAULT_SKIP_FIRST_POSITIONS = 16
+
+_PROCESSED_NORM_SUFFIX = "Pre"
+
+
+@dataclass
+class JacobianLensReadout:
+ """Result of a :meth:`JacobianLens.readout` call.
+
+ Attributes:
+ lens_logits:
+ Per-layer lens logits, ``{layer: tensor of shape [pos, d_vocab]}``
+ (fp32, on CPU). Entries are pre-softmax scores over the vocabulary;
+ ranks are what the paper reports, so no softmax is applied.
+ model_logits:
+ The model's actual output logits at the same positions,
+ ``[pos, d_vocab]`` (fp32, on CPU).
+ tokens:
+ The token ids of the run prompt, ``[seq]``.
+ positions:
+ The (normalized, non-negative) positions the readout covers, aligned
+ with the ``pos`` axis of ``lens_logits`` / ``model_logits``.
+ use_jacobian:
+ Whether the Jacobian transport was applied (``False`` = logit lens).
+ """
+
+ lens_logits: Dict[int, Float[torch.Tensor, "pos d_vocab"]]
+ model_logits: Float[torch.Tensor, "pos d_vocab"]
+ tokens: Int[torch.Tensor, "seq"]
+ positions: List[int]
+ use_jacobian: bool = True
+
+ def top_tokens(self, tokenizer: Any, k: int = 5) -> Dict[int, List[List[str]]]:
+ """Decode the top-``k`` tokens per layer and position.
+
+ Args:
+ tokenizer: The model's tokenizer (``model.tokenizer``).
+ k: Number of top tokens to decode per (layer, position).
+
+ Returns:
+ ``{layer: [ [top-k strings] per position ]}``, positions aligned with
+ :attr:`positions`.
+ """
+ out: Dict[int, List[List[str]]] = {}
+ for layer, logits in self.lens_logits.items():
+ ids = logits.topk(k, dim=-1).indices
+ out[layer] = [[tokenizer.decode([t]) for t in row.tolist()] for row in ids]
+ return out
+
+
+class JacobianLens:
+ """A fitted Jacobian lens: one transport matrix per source layer.
+
+ Layer convention (matching the reference implementation and the published
+ artifacts): index ``l`` refers to the **output of block** ``l`` —
+ ``blocks.{l}.hook_resid_post`` on a ``HookedTransformer``,
+ ``blocks.{l}.hook_out`` on a ``TransformerBridge``. ``J[l]`` maps that
+ activation to the final block's output, pre final norm. The final layer
+ itself is never fitted (its transport is the identity), so
+ ``source_layers == [0, ..., n_layers - 2]`` for a full fit.
+
+ Attributes:
+ jacobians: ``{layer: [d_model, d_model]}`` transport matrices, fp32, CPU.
+ n_prompts: Number of prompts averaged into the fit.
+ d_model: Residual stream width the lens was fitted for.
+ metadata: Optional provenance (model name, TransformerLens version, fit
+ hyperparameters). Preserved by :meth:`save`/:meth:`load`; artifacts
+ from the reference implementation load with empty metadata.
+ """
+
+ def __init__(
+ self,
+ jacobians: Dict[int, Float[torch.Tensor, "d_model d_model"]],
+ *,
+ n_prompts: int,
+ d_model: int,
+ metadata: Optional[Dict[str, Any]] = None,
+ ) -> None:
+ if not jacobians:
+ raise ValueError("jacobians must contain at least one layer")
+ for layer, matrix in jacobians.items():
+ if matrix.shape != (d_model, d_model):
+ raise ValueError(
+ f"jacobians[{layer}] has shape {tuple(matrix.shape)}, "
+ f"expected ({d_model}, {d_model})"
+ )
+ self.jacobians: Dict[int, torch.Tensor] = {
+ int(layer): matrix.detach().float().cpu() for layer, matrix in jacobians.items()
+ }
+ self.n_prompts = int(n_prompts)
+ self.d_model = int(d_model)
+ self.metadata: Dict[str, Any] = dict(metadata or {})
+
+ @property
+ def source_layers(self) -> List[int]:
+ """Sorted list of layers this lens has transport matrices for."""
+ return sorted(self.jacobians)
+
+ def __repr__(self) -> str:
+ layers = self.source_layers
+ return (
+ f"JacobianLens(layers={layers[0]}..{layers[-1]} ({len(layers)}), "
+ f"d_model={self.d_model}, n_prompts={self.n_prompts})"
+ )
+
+ # ------------------------------------------------------------------ #
+ # persistence #
+ # ------------------------------------------------------------------ #
+
+ def save(self, path: str, *, dtype: torch.dtype = torch.float16) -> None:
+ """Save the lens in the reference implementation's artifact format.
+
+ The four official keys (``J``, ``n_prompts``, ``source_layers``,
+ ``d_model``) are written unchanged so the file stays loadable by the
+ reference package; TransformerLens provenance is stored under an
+ additive ``metadata`` key.
+
+ Args:
+ path: Destination ``.pt`` path.
+ dtype: Storage dtype. Defaults to fp16 like the reference
+ implementation — Jacobian entries are order-one, so the smaller
+ dtype costs little precision and halves the artifact on disk.
+ """
+ payload: Dict[str, Any] = {
+ "J": {layer: matrix.to(dtype) for layer, matrix in self.jacobians.items()},
+ "n_prompts": self.n_prompts,
+ "source_layers": self.source_layers,
+ "d_model": self.d_model,
+ }
+ if self.metadata:
+ payload["metadata"] = self.metadata
+ torch.save(payload, path)
+
+ @classmethod
+ def load(cls, path: str) -> "JacobianLens":
+ """Load a lens artifact saved by this class or the reference package.
+
+ Args:
+ path: Path to the ``.pt`` artifact.
+
+ Raises:
+ ValueError: If the file lacks the ``J`` key (e.g. a fit checkpoint
+ rather than a saved lens).
+ """
+ payload = torch.load(path, map_location="cpu", weights_only=True)
+ if "J" not in payload:
+ raise ValueError(
+ f"{path} does not look like a Jacobian lens artifact (no 'J' key). "
+ "Fit checkpoints and other formats are not supported."
+ )
+ return cls(
+ {int(layer): matrix for layer, matrix in payload["J"].items()},
+ n_prompts=int(payload.get("n_prompts", 0)),
+ d_model=int(payload["d_model"]),
+ metadata=payload.get("metadata"),
+ )
+
+ @classmethod
+ def from_pretrained(
+ cls,
+ name_or_path: str,
+ *,
+ filename: str = "lens.pt",
+ revision: Optional[str] = None,
+ model: Any = None,
+ ) -> "JacobianLens":
+ """Load a lens from a local path or a Hugging Face Hub repository.
+
+ Args:
+ name_or_path: A local ``.pt`` file, a local directory containing
+ ``filename``, or a Hub repo id such as
+ ``"neuronpedia/jacobian-lens"``.
+ filename: File (or subpath) inside the directory / Hub repo. Hub
+ repos host lenses for many models, e.g.
+ ``"gpt2-small/jlens/Salesforce-wikitext/gpt2_jacobian_lens.pt"``.
+ revision: Optional Hub revision (branch, tag, or commit) to pin.
+ model: If given, :meth:`validate_model` is called so dimension or
+ weight-processing mismatches fail here rather than at first use.
+
+ Returns:
+ The loaded (and, if ``model`` was given, validated) lens.
+ """
+ import os
+
+ if os.path.isfile(name_or_path):
+ lens = cls.load(name_or_path)
+ elif os.path.isdir(name_or_path):
+ lens = cls.load(os.path.join(name_or_path, filename))
+ else:
+ from huggingface_hub import hf_hub_download
+
+ local_path = hf_hub_download(name_or_path, filename, revision=revision)
+ lens = cls.load(local_path)
+ if model is not None:
+ lens.validate_model(model)
+ return lens
+
+ @classmethod
+ def merge(cls, lenses: Sequence["JacobianLens"]) -> "JacobianLens":
+ """Combine lenses fitted on disjoint prompt slices.
+
+ The per-layer matrices are averaged weighted by each lens's
+ ``n_prompts``, matching the reference implementation, so fitting can be
+ parallelized across processes or machines and merged afterwards.
+ Provenance ``metadata`` is taken from the first lens only.
+
+ Args:
+ lenses: Lenses that agree exactly on ``source_layers`` and
+ ``d_model``.
+
+ Raises:
+ ValueError: On an empty sequence or mismatched lenses.
+ """
+ if not lenses:
+ raise ValueError("cannot merge an empty sequence of lenses")
+ first = lenses[0]
+ for other in lenses[1:]:
+ if other.source_layers != first.source_layers or other.d_model != first.d_model:
+ raise ValueError(
+ "all lenses being merged must share the same source_layers and d_model"
+ )
+ total = sum(lens.n_prompts for lens in lenses)
+ if total <= 0:
+ raise ValueError("merge() needs lenses with positive n_prompts")
+ merged = {
+ layer: torch.stack([lens.jacobians[layer] * lens.n_prompts for lens in lenses]).sum(
+ dim=0
+ )
+ / total
+ for layer in first.source_layers
+ }
+ metadata = dict(first.metadata)
+ return cls(merged, n_prompts=total, d_model=first.d_model, metadata=metadata)
+
+ # ------------------------------------------------------------------ #
+ # model validation #
+ # ------------------------------------------------------------------ #
+
+ def validate_model(self, model: Any) -> "JacobianLens":
+ """Check that ``model`` matches this lens; raise loudly if not.
+
+ Verifies the residual width and layer range, and refuses models whose
+ weights have been processed into a different residual basis (see the
+ module warning).
+
+ Args:
+ model: A ``HookedTransformer`` or ``TransformerBridge``.
+
+ Returns:
+ ``self``, for chaining.
+
+ Raises:
+ ValueError: On ``d_model`` mismatch, out-of-range source layers, or
+ processed weights.
+ """
+ d_model = model.cfg.d_model
+ if d_model != self.d_model:
+ raise ValueError(
+ f"lens was fitted for d_model={self.d_model}, but the model has "
+ f"d_model={d_model} — this lens belongs to a different model."
+ )
+ n_layers = model.cfg.n_layers
+ out_of_range = [layer for layer in self.source_layers if not 0 <= layer < n_layers]
+ if out_of_range:
+ raise ValueError(
+ f"lens has source layers {out_of_range} outside the model's "
+ f"0..{n_layers - 1} range — this lens belongs to a different model."
+ )
+ _require_unprocessed_weights(model)
+ return self
+
+ # ------------------------------------------------------------------ #
+ # reading #
+ # ------------------------------------------------------------------ #
+
+ def transport(
+ self,
+ residual: Float[torch.Tensor, "... d_model"],
+ layer: int,
+ ) -> Float[torch.Tensor, "... d_model"]:
+ """Map layer-``layer`` activations into the final block's output basis.
+
+ Computes ``J[layer] @ h`` per activation vector, in fp32.
+
+ Args:
+ residual: Activations from the output of block ``layer``.
+ layer: Source layer index.
+ """
+ if layer not in self.jacobians:
+ raise ValueError(
+ f"layer {layer} is not in this lens's source layers "
+ f"({self.source_layers[0]}..{self.source_layers[-1]})"
+ )
+ matrix = self.jacobians[layer].to(residual.device)
+ return residual.float() @ matrix.T
+
+ @torch.no_grad()
+ def readout(
+ self,
+ model: Any,
+ input: Union[str, Int[torch.Tensor, "batch seq"]],
+ *,
+ layers: Optional[Sequence[int]] = None,
+ positions: Optional[Sequence[int]] = None,
+ use_jacobian: bool = True,
+ ) -> JacobianLensReadout:
+ """Read per-layer vocabulary logits for a prompt.
+
+ Runs the model once with caching, transports the residual stream at each
+ requested layer through ``J[layer]`` (or the identity when
+ ``use_jacobian=False`` — the logit lens), and applies the model's own
+ final norm, unembedding, and logit soft cap.
+
+ Args:
+ model: A ``HookedTransformer`` or ``TransformerBridge`` with raw
+ (unprocessed) weights.
+ input: A prompt string, or a ``[1, seq]`` token tensor.
+ layers: Layers to read. Defaults to every fitted layer plus the
+ final layer. The final layer (``n_layers - 1``) is always read
+ with the identity transport — by construction its lens equals
+ the model's own output distribution.
+ positions: Token positions to read (negative indices allowed).
+ Defaults to all positions.
+ use_jacobian: Apply the Jacobian transport. ``False`` gives the
+ logit-lens baseline through the identical code path.
+
+ Returns:
+ A :class:`JacobianLensReadout`.
+
+ Raises:
+ ValueError: If the model fails :meth:`validate_model`, ``input`` is
+ batched, or a requested layer has no transport matrix.
+ """
+ self.validate_model(model)
+ tokens = model.to_tokens(input) if isinstance(input, str) else input
+ if tokens.ndim != 2 or tokens.shape[0] != 1:
+ raise ValueError(f"readout expects a single prompt; got shape {tuple(tokens.shape)}")
+ n_layers = model.cfg.n_layers
+ final_layer = n_layers - 1
+ if layers is None:
+ layers = self.source_layers + [final_layer]
+ layers = [_normalize_layer(layer, n_layers) for layer in layers]
+ for layer in layers:
+ if use_jacobian and layer != final_layer and layer not in self.jacobians:
+ raise ValueError(
+ f"layer {layer} is not in this lens's source layers; "
+ f"available: {self.source_layers} (+{final_layer} as identity)"
+ )
+
+ seq_len = tokens.shape[1]
+ if positions is None:
+ norm_positions = list(range(seq_len))
+ else:
+ norm_positions = [pos + seq_len if pos < 0 else pos for pos in positions]
+ out_of_range = [pos for pos in norm_positions if not 0 <= pos < seq_len]
+ if out_of_range:
+ raise ValueError(
+ f"positions {out_of_range} out of range for a {seq_len}-token prompt"
+ )
+
+ hook_names = {layer: _resid_post_hook_name(model, layer) for layer in layers}
+ wanted = set(hook_names.values())
+ logits, cache = model.run_with_cache(tokens, names_filter=lambda name: name in wanted)
+
+ lens_logits: Dict[int, torch.Tensor] = {}
+ for layer in layers:
+ residual = cache[hook_names[layer]][0, norm_positions, :]
+ transported = (
+ self.transport(residual, layer)
+ if use_jacobian and layer != final_layer
+ else residual.float()
+ )
+ lens_logits[layer] = _unembed(model, transported)
+ return JacobianLensReadout(
+ lens_logits=lens_logits,
+ model_logits=logits[0, norm_positions, :].float().cpu(),
+ tokens=tokens[0].cpu(),
+ positions=norm_positions,
+ use_jacobian=use_jacobian,
+ )
+
+ @torch.no_grad()
+ def lens_vectors(
+ self,
+ model: Any,
+ tokens: Union[TokenInput, Sequence[TokenInput]],
+ layer: int,
+ ) -> Float[torch.Tensor, "n d_model"]:
+ """Residual-stream directions for vocabulary tokens at a layer.
+
+ The J-lens vector for token ``t`` is row ``t`` of ``W_U J[layer]``
+ expressed in layer-``layer`` residual coordinates:
+ ``v_t = J[layer]^T W_U[:, t]``.
+
+ Args:
+ model: The model supplying ``W_U``.
+ tokens: A token string / id, or a sequence of them. Strings must
+ encode to a single token.
+ layer: Source layer for the vectors.
+
+ Returns:
+ One vector per token, fp32, on the model's device.
+ """
+ token_ids = _to_token_ids(model, tokens)
+ matrix = self.jacobians.get(layer)
+ if matrix is None:
+ raise ValueError(
+ f"layer {layer} is not in this lens's source layers "
+ f"({self.source_layers[0]}..{self.source_layers[-1]})"
+ )
+ unembed_columns = model.W_U[:, token_ids].float() # [d_model, n]
+ return (matrix.to(unembed_columns.device).T @ unembed_columns).T
+
+ # ------------------------------------------------------------------ #
+ # interventions #
+ # ------------------------------------------------------------------ #
+
+ def steering_hooks(
+ self,
+ model: Any,
+ token: TokenInput,
+ layers: Sequence[int],
+ *,
+ alpha: float = 4.0,
+ positions: Optional[Sequence[int]] = None,
+ ) -> List[Tuple[str, Any]]:
+ """Hooks that steer the residual stream along a token's J-lens vector.
+
+ At each layer the unit-normalized lens vector is added, scaled by
+ ``alpha`` times the activation's **median** per-position residual norm:
+ ``h <- h + alpha * median||h|| * v̂``. This norm-matched
+ parameterization follows the steering description in the reference
+ implementation's experiment protocols; the paper's minimal form is
+ the unscaled ``h <- h + alpha * v_t``, recoverable by passing the raw
+ :meth:`lens_vectors` output to your own hook. The median (not mean) is
+ used so attention-sink positions — whose residual norms run orders of
+ magnitude above typical positions — do not inflate the scale.
+
+ Args:
+ model: The model the hooks will run on.
+ token: The concept token to steer toward.
+ layers: Layers to intervene at.
+ alpha: Steering strength scalar; ``0`` disables. Because of the
+ norm-matched scale, values of order 1 already perturb the
+ stream by roughly its own magnitude.
+ positions: Positions to steer. Defaults to all positions.
+
+ Returns:
+ ``[(hook_name, fn), ...]`` for ``model.hooks(fwd_hooks=...)`` or
+ ``model.run_with_hooks(fwd_hooks=...)``.
+ """
+ hooks = []
+ for layer in layers:
+ direction = self.lens_vectors(model, token, layer)[0]
+ unit = direction / direction.norm()
+
+ def steer_fn(
+ activation: Float[torch.Tensor, "batch pos d_model"],
+ hook: Any,
+ unit: torch.Tensor = unit,
+ ) -> Float[torch.Tensor, "batch pos d_model"]:
+ scale = alpha * activation.float().norm(dim=-1).median()
+ delta = (scale * unit).to(activation.dtype)
+ if positions is None:
+ return activation + delta
+ activation[:, list(positions), :] += delta
+ return activation
+
+ hooks.append((_resid_post_hook_name(model, layer), steer_fn))
+ return hooks
+
+ def ablation_hooks(
+ self,
+ model: Any,
+ tokens: Union[TokenInput, Sequence[TokenInput]],
+ layers: Sequence[int],
+ *,
+ positions: Optional[Sequence[int]] = None,
+ ) -> List[Tuple[str, Any]]:
+ """Hooks that project token directions out of the residual stream.
+
+ For each token's unit lens vector ``v̂``: ``h <- h - (h·v̂) v̂``,
+ applied sequentially when several tokens are given.
+
+ Args:
+ model: The model the hooks will run on.
+ tokens: Concept token(s) to suppress.
+ layers: Layers to intervene at.
+ positions: Positions to ablate. Defaults to all positions.
+
+ Returns:
+ ``[(hook_name, fn), ...]`` for ``model.hooks(fwd_hooks=...)``.
+ """
+ hooks = []
+ for layer in layers:
+ vectors = self.lens_vectors(model, tokens, layer)
+ units = vectors / vectors.norm(dim=-1, keepdim=True)
+
+ def ablate_fn(
+ activation: Float[torch.Tensor, "batch pos d_model"],
+ hook: Any,
+ units: torch.Tensor = units,
+ ) -> Float[torch.Tensor, "batch pos d_model"]:
+ sliced = activation if positions is None else activation[:, list(positions), :]
+ result = sliced.float()
+ for unit in units:
+ coeff = result @ unit
+ result = result - coeff.unsqueeze(-1) * unit
+ result = result.to(activation.dtype)
+ if positions is None:
+ return result
+ activation[:, list(positions), :] = result
+ return activation
+
+ hooks.append((_resid_post_hook_name(model, layer), ablate_fn))
+ return hooks
+
+ def swap_hooks(
+ self,
+ model: Any,
+ source_token: TokenInput,
+ target_token: TokenInput,
+ layers: Sequence[int],
+ *,
+ alpha: float = 1.0,
+ positions: Optional[Sequence[int]] = None,
+ ) -> List[Tuple[str, Any]]:
+ """Hooks that swap two concepts' coordinates in lens space.
+
+ The paper's patching-in-lens-coordinates intervention: with
+ ``V = [v_s, v_t]`` and lens coordinates ``c = V⁺ h`` (pseudoinverse),
+ the update is ``h <- h + alpha * V (sigma(c) - c)`` where ``sigma``
+ exchanges the two coordinates. The component of ``h`` orthogonal to
+ ``span{v_s, v_t}`` is untouched. ``alpha=2`` is the paper's
+ "double-strength" swap.
+
+ Args:
+ model: The model the hooks will run on.
+ source_token: The concept to remove (e.g. ``" France"``).
+ target_token: The concept to install (e.g. ``" China"``).
+ layers: Layers to intervene at (the paper clamps the swap across an
+ intermediate-layer band).
+ alpha: Swap strength.
+ positions: Positions to swap. Defaults to all positions.
+
+ Returns:
+ ``[(hook_name, fn), ...]`` for ``model.hooks(fwd_hooks=...)``.
+ """
+ hooks = []
+ for layer in layers:
+ basis = self.lens_vectors(model, [source_token, target_token], layer).T # [d, 2]
+ pinv = torch.linalg.pinv(basis) # [2, d]
+
+ def swap_fn(
+ activation: Float[torch.Tensor, "batch pos d_model"],
+ hook: Any,
+ basis: torch.Tensor = basis,
+ pinv: torch.Tensor = pinv,
+ ) -> Float[torch.Tensor, "batch pos d_model"]:
+ sliced = activation if positions is None else activation[:, list(positions), :]
+ coords = sliced.float() @ pinv.T # [..., 2]
+ delta = alpha * ((coords[..., [1, 0]] - coords) @ basis.T)
+ result = (sliced.float() + delta).to(activation.dtype)
+ if positions is None:
+ return result
+ activation[:, list(positions), :] = result
+ return activation
+
+ hooks.append((_resid_post_hook_name(model, layer), swap_fn))
+ return hooks
+
+ # ------------------------------------------------------------------ #
+ # fitting #
+ # ------------------------------------------------------------------ #
+
+ @classmethod
+ def fit(
+ cls,
+ model: Any,
+ prompts: Sequence[str],
+ *,
+ source_layers: Optional[Sequence[int]] = None,
+ target_layer: Optional[int] = None,
+ dim_batch: int = 8,
+ max_seq_len: int = 128,
+ skip_first_positions: int = DEFAULT_SKIP_FIRST_POSITIONS,
+ show_progress: bool = True,
+ metadata: Optional[Dict[str, Any]] = None,
+ ) -> "JacobianLens":
+ """Fit a Jacobian lens on a hooked model.
+
+ Implements the reference estimator exactly. For each prompt: one forward
+ pass (the prompt replicated ``dim_batch`` times along the batch axis),
+ then ``ceil(d_model / dim_batch)`` backward passes. Each backward plants
+ a one-hot cotangent for one output dimension at *every* valid target
+ position simultaneously — causal attention guarantees the gradient at
+ source position ``t`` is then the sum over target positions
+ ``t' >= t`` with no explicit masking. Rows are averaged over valid
+ source positions (the first ``skip_first_positions`` and the final
+ position are excluded), and prompts contribute equally to the final
+ mean. There is no randomness: the computation is deterministic given
+ the prompts.
+
+ The reference implementation reports that fit quality saturates
+ quickly — on the order of 100 prompts of 128 tokens is usable; the
+ published lenses use up to 1000. Use :meth:`merge` to parallelize
+ across prompt slices.
+
+ Args:
+ model: A ``HookedTransformer`` or ``TransformerBridge`` with raw
+ (unprocessed) weights. Model parameters are temporarily frozen
+ (``requires_grad=False``) during fitting and restored after.
+ prompts: Prompt strings. Prompts too short to contain a valid
+ position (``seq_len <= skip_first_positions + 1``) are skipped
+ with a warning and do not count toward ``n_prompts``.
+ source_layers: Layers to fit. Defaults to every layer below
+ ``target_layer``. Negative indices count from ``n_layers``.
+ target_layer: Layer whose output the Jacobians map to. Defaults to
+ the final layer (``n_layers - 1``, the convention of the
+ published artifacts).
+ dim_batch: Output dimensions per backward pass. Higher is faster
+ but replicates the prompt ``dim_batch`` times in memory; total
+ backward FLOPs are unchanged.
+ max_seq_len: Prompts are truncated to this many tokens.
+ skip_first_positions: Leading positions excluded from the source
+ average.
+ show_progress: Show a tqdm progress bar over prompts.
+ metadata: Extra provenance merged into :attr:`metadata`.
+
+ Returns:
+ The fitted :class:`JacobianLens`.
+
+ Raises:
+ ValueError: On processed weights, invalid layer indices, or if no
+ prompt was long enough to fit on.
+ """
+ _require_unprocessed_weights(model)
+ n_layers = model.cfg.n_layers
+ d_model = model.cfg.d_model
+ resolved_target = _normalize_layer(
+ n_layers - 1 if target_layer is None else target_layer, n_layers
+ )
+ if source_layers is None:
+ resolved_sources = list(range(resolved_target))
+ else:
+ resolved_sources = sorted(
+ {_normalize_layer(layer, n_layers) for layer in source_layers}
+ )
+ if not resolved_sources:
+ raise ValueError("source_layers is empty")
+ if resolved_sources[-1] >= resolved_target:
+ raise ValueError(
+ f"every source layer must be below target_layer={resolved_target}; "
+ f"got {resolved_sources}"
+ )
+ if dim_batch < 1:
+ raise ValueError(f"dim_batch must be >= 1, got {dim_batch}")
+
+ jacobian_sum = {
+ layer: torch.zeros(d_model, d_model, dtype=torch.float32) for layer in resolved_sources
+ }
+ n_done = 0
+ iterator = tqdm(prompts, desc="fitting J-lens", disable=not show_progress)
+ with _frozen_parameters(model):
+ for prompt in iterator:
+ tokens = model.to_tokens(prompt)[:, :max_seq_len]
+ seq_len = tokens.shape[1]
+ if seq_len <= skip_first_positions + 1:
+ warnings.warn(
+ f"skipping prompt with only {seq_len} tokens "
+ f"(need > {skip_first_positions + 1})",
+ stacklevel=2,
+ )
+ continue
+ per_prompt = _jacobian_for_prompt(
+ model,
+ tokens,
+ source_layers=resolved_sources,
+ target_layer=resolved_target,
+ dim_batch=dim_batch,
+ skip_first_positions=skip_first_positions,
+ )
+ for layer in resolved_sources:
+ jacobian_sum[layer] += per_prompt[layer]
+ n_done += 1
+ if n_done == 0:
+ raise ValueError(
+ "every prompt was too short to contribute valid positions; nothing was fitted"
+ )
+
+ full_metadata: Dict[str, Any] = {
+ "model_name": getattr(model.cfg, "model_name", None),
+ "hook_convention": "resid_post",
+ "target_layer": resolved_target,
+ "dim_batch": dim_batch,
+ "max_seq_len": max_seq_len,
+ "skip_first_positions": skip_first_positions,
+ "transformer_lens_fit": True,
+ }
+ full_metadata.update(metadata or {})
+ return cls(
+ {layer: jacobian_sum[layer] / n_done for layer in resolved_sources},
+ n_prompts=n_done,
+ d_model=d_model,
+ metadata=full_metadata,
+ )
+
+
+# ---------------------------------------------------------------------- #
+# helpers #
+# ---------------------------------------------------------------------- #
+
+
+def _is_bridge(model: Any) -> bool:
+ """True when ``model`` is a TransformerBridge (lazy import, DLA pattern)."""
+ from transformer_lens.model_bridge import TransformerBridge
+
+ return isinstance(model, TransformerBridge)
+
+
+def _resid_post_hook_name(model: Any, layer: int) -> str:
+ """Hook name for the output of block ``layer`` on either model class."""
+ if _is_bridge(model):
+ return f"blocks.{layer}.hook_out"
+ return f"blocks.{layer}.hook_resid_post"
+
+
+def _require_unprocessed_weights(model: Any) -> None:
+ """Refuse models whose weights may have left the raw HF basis.
+
+ Three detectable signatures are checked; each raises with an actionable
+ message. ``fold_ln`` converts the norm type to ``LNPre``/``RMSPre`` on a
+ ``HookedTransformer``. A ``TransformerBridge`` keeps no processing marker —
+ ``enable_compatibility_mode()`` processes weights by default and a
+ ``no_processing=True`` call cannot be told apart afterwards — so any
+ compatibility-mode bridge is refused (the mirror image of DLA, which
+ *requires* compatibility mode because it reasons in the folded basis).
+ Finally, ``center_unembed`` (applied by ``from_pretrained`` even with
+ ``fold_ln=False``) leaves ``W_U`` exactly mean-centered per row, which raw
+ checkpoints never are; centering of *writing* weights alone has no
+ post-hoc signature, so ``from_pretrained_no_processing`` remains the only
+ fully supported HookedTransformer loading path.
+ """
+ norm_type = getattr(model.cfg, "normalization_type", None) or ""
+ if norm_type.endswith(_PROCESSED_NORM_SUFFIX):
+ raise ValueError(
+ "this model was loaded with fold_ln weight processing "
+ f"(normalization_type={norm_type!r}), which changes the residual basis "
+ "the lens was fitted in. Reload it with "
+ "HookedTransformer.from_pretrained_no_processing(...) or use a raw "
+ "TransformerBridge.boot_transformers(...) model."
+ )
+ if _is_bridge(model):
+ if getattr(model, "compatibility_mode", False):
+ raise ValueError(
+ "compatibility mode is enabled on this TransformerBridge. "
+ "enable_compatibility_mode() applies HookedTransformer-style weight "
+ "processing by default, which changes the residual basis the lens was "
+ "fitted in, and a no_processing=True call cannot be reliably told apart "
+ "afterwards. Use a freshly booted TransformerBridge.boot_transformers(...) "
+ "model (raw weights) for Jacobian-lens analyses."
+ )
+ return
+ unembed_weight = getattr(model, "W_U", None)
+ if unembed_weight is not None:
+ # A 64-row slice is enough: centering zeroes every row mean exactly, while
+ # raw checkpoints sit orders of magnitude above the 0.01 threshold
+ # (measured: gpt2 3.4, gemma-2-2b 17.2; centered gpt2 ~1e-7).
+ rows = unembed_weight[:64].float()
+ if rows.mean(dim=-1).abs().max() < 0.01 * rows.abs().mean():
+ raise ValueError(
+ "this model's unembedding matrix is exactly mean-centered — the "
+ "signature of center_unembed weight processing, which "
+ "from_pretrained applies even with fold_ln=False and which changes "
+ "the basis the J-lens vectors live in. Reload the model with "
+ "HookedTransformer.from_pretrained_no_processing(...)."
+ )
+
+
+def _unembed(
+ model: Any, residual: Float[torch.Tensor, "pos d_model"]
+) -> Float[torch.Tensor, "pos d_vocab"]:
+ """Apply the model's own final norm, unembedding, and logit soft cap.
+
+ The norm/unembed components contract on ``[batch, pos, d_model]``, so the
+ position rows are passed through with a singleton batch axis. The residual
+ is moved to the unembedding's device for sharded/multi-GPU models.
+ """
+ compute_dtype = model.W_U.dtype
+ batched = residual.to(device=model.W_U.device, dtype=compute_dtype).unsqueeze(0)
+ logits = model.unembed(model.ln_final(batched)).float().squeeze(0)
+ soft_cap = getattr(model.cfg, "output_logits_soft_cap", None)
+ return apply_softcap(logits, soft_cap).cpu()
+
+
+def _to_token_ids(model: Any, tokens: Union[TokenInput, Sequence[TokenInput]]) -> List[int]:
+ """Convert token strings / ids into a list of single-token ids."""
+ if isinstance(tokens, (str, int)):
+ tokens = [tokens]
+ ids: List[int] = []
+ for token in tokens:
+ if isinstance(token, str):
+ ids.append(model.to_single_token(token))
+ else:
+ ids.append(int(token))
+ return ids
+
+
+def _normalize_layer(layer: int, n_layers: int) -> int:
+ """Resolve negative layer indices and bounds-check."""
+ resolved = layer + n_layers if layer < 0 else layer
+ if not 0 <= resolved < n_layers:
+ raise ValueError(f"layer {layer} out of range for a {n_layers}-layer model")
+ return resolved
+
+
+class _frozen_parameters:
+ """Context manager: freeze all parameters, restore their flags on exit.
+
+ Freezing keeps the autograd graph rooted at the residual stream rather than
+ at the weights, so fitting retains only the blocks between the earliest
+ source layer and the target layer.
+ """
+
+ def __init__(self, model: Any) -> None:
+ self.model = model
+ self.saved: List[Tuple[torch.nn.Parameter, bool]] = []
+
+ def __enter__(self) -> None:
+ self.saved = [(param, param.requires_grad) for param in self.model.parameters()]
+ for param, _ in self.saved:
+ param.requires_grad_(False)
+
+ def __exit__(self, *exc: Any) -> None:
+ for param, flag in self.saved:
+ param.requires_grad_(flag)
+
+
+def _jacobian_for_prompt(
+ model: Any,
+ tokens: Int[torch.Tensor, "one seq"],
+ *,
+ source_layers: List[int],
+ target_layer: int,
+ dim_batch: int,
+ skip_first_positions: int,
+) -> Dict[int, Float[torch.Tensor, "d_model d_model"]]:
+ """Exact per-prompt Jacobian rows via batched one-hot cotangents.
+
+ Assumes parameters are already frozen (see :class:`_frozen_parameters`) so
+ that marking the earliest source activation ``requires_grad`` roots the
+ graph there.
+ """
+ d_model = model.cfg.d_model
+ seq_len = tokens.shape[1]
+ valid_positions = list(range(skip_first_positions, seq_len - 1))
+ replicated = tokens.expand(dim_batch, -1)
+
+ captured: Dict[str, torch.Tensor] = {}
+ root_name = _resid_post_hook_name(model, min(source_layers))
+ hook_layers = sorted(set(source_layers) | {target_layer})
+
+ def capture_fn(
+ activation: Float[torch.Tensor, "batch pos d_model"], hook: Any
+ ) -> Float[torch.Tensor, "batch pos d_model"]:
+ if hook.name == root_name and not activation.requires_grad:
+ activation.requires_grad_(True)
+ captured[hook.name] = activation
+ return activation
+
+ fwd_hooks = [(_resid_post_hook_name(model, layer), capture_fn) for layer in hook_layers]
+ with torch.enable_grad(), model.hooks(fwd_hooks=fwd_hooks):
+ model(replicated, return_type=None)
+
+ target = captured[_resid_post_hook_name(model, target_layer)]
+ sources = [captured[_resid_post_hook_name(model, layer)] for layer in source_layers]
+ device = target.device
+ positions_index = torch.tensor(valid_positions, device=device)
+ batch_index = torch.arange(dim_batch, device=device)
+
+ jacobians = {
+ layer: torch.zeros(d_model, d_model, dtype=torch.float32) for layer in source_layers
+ }
+ cotangent = torch.zeros_like(target)
+ n_passes = -(-d_model // dim_batch) # ceil division
+ for pass_index in range(n_passes):
+ dim_start = pass_index * dim_batch
+ n_dims = min(dim_batch, d_model - dim_start)
+ cotangent.zero_()
+ cotangent[
+ batch_index[:n_dims, None],
+ positions_index[None, :],
+ dim_start + batch_index[:n_dims, None],
+ ] = 1.0
+ grads = torch.autograd.grad(
+ outputs=target,
+ inputs=sources,
+ grad_outputs=cotangent,
+ retain_graph=pass_index < n_passes - 1,
+ )
+ for layer, grad in zip(source_layers, grads):
+ # each gradient lives on its layer's device under sharded/device_map setups
+ rows = grad[:n_dims, positions_index.to(grad.device), :].float().mean(dim=1)
+ jacobians[layer][dim_start : dim_start + n_dims, :] = rows.cpu()
+ return jacobians