open-interpretability 0.0.20__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. open_interpretability-0.0.20.dist-info/METADATA +157 -0
  2. open_interpretability-0.0.20.dist-info/RECORD +256 -0
  3. open_interpretability-0.0.20.dist-info/WHEEL +4 -0
  4. open_interpretability-0.0.20.dist-info/entry_points.txt +2 -0
  5. open_interpretability-0.0.20.dist-info/licenses/LICENSE +21 -0
  6. openinterp/__init__.py +6 -0
  7. openinterp/agents/__init__.py +25 -0
  8. openinterp/agents/base.py +229 -0
  9. openinterp/agents/judge.py +149 -0
  10. openinterp/agents/proposer.py +471 -0
  11. openinterp/agents/proposer_profiles.py +79 -0
  12. openinterp/agents/review_measurements.py +173 -0
  13. openinterp/agents/reviewer.py +498 -0
  14. openinterp/agreement.py +63 -0
  15. openinterp/audit_options.py +79 -0
  16. openinterp/baseline.py +254 -0
  17. openinterp/benchmark.py +450 -0
  18. openinterp/blends.py +239 -0
  19. openinterp/builder/__init__.py +6 -0
  20. openinterp/builder/agents.py +260 -0
  21. openinterp/builder/aligned.py +41 -0
  22. openinterp/builder/charts.py +411 -0
  23. openinterp/builder/circuit_pages.py +37 -0
  24. openinterp/builder/circuits.py +264 -0
  25. openinterp/builder/compiler.py +495 -0
  26. openinterp/builder/corpora.py +98 -0
  27. openinterp/builder/coverage.py +46 -0
  28. openinterp/builder/dashboard.py +255 -0
  29. openinterp/builder/disk_memo.py +65 -0
  30. openinterp/builder/experiment.py +105 -0
  31. openinterp/builder/heat.py +121 -0
  32. openinterp/builder/hrefs.py +71 -0
  33. openinterp/builder/learned_baseline.py +204 -0
  34. openinterp/builder/model_facts.py +138 -0
  35. openinterp/builder/neuronpedia_export.py +107 -0
  36. openinterp/builder/parallel.py +100 -0
  37. openinterp/builder/parquet_export.py +458 -0
  38. openinterp/builder/pieces.py +127 -0
  39. openinterp/builder/pii.py +211 -0
  40. openinterp/builder/registry_stats.py +144 -0
  41. openinterp/builder/research.py +109 -0
  42. openinterp/builder/sections.py +28 -0
  43. openinterp/builder/significance.py +103 -0
  44. openinterp/builder/sister_graph.py +180 -0
  45. openinterp/builder/standing.py +185 -0
  46. openinterp/builder/statuses.py +34 -0
  47. openinterp/builder/stopped.py +91 -0
  48. openinterp/builder/stops.py +30 -0
  49. openinterp/builder/superpositions.py +102 -0
  50. openinterp/builder/templates/_agent_role_cells.html +9 -0
  51. openinterp/builder/templates/_causal_chart.html +67 -0
  52. openinterp/builder/templates/_circuit.html +8 -0
  53. openinterp/builder/templates/_dashboard.html +133 -0
  54. openinterp/builder/templates/_experiment.html +500 -0
  55. openinterp/builder/templates/_macros.html +82 -0
  56. openinterp/builder/templates/_patchscope.html +33 -0
  57. openinterp/builder/templates/_prior_art.html +24 -0
  58. openinterp/builder/templates/_specificity.html +21 -0
  59. openinterp/builder/templates/_steering.html +34 -0
  60. openinterp/builder/templates/_superposition.html +62 -0
  61. openinterp/builder/templates/_vocab_chart.html +88 -0
  62. openinterp/builder/templates/_wiring.html +44 -0
  63. openinterp/builder/templates/about.html +95 -0
  64. openinterp/builder/templates/agent.html +69 -0
  65. openinterp/builder/templates/agents.html +80 -0
  66. openinterp/builder/templates/base.html +103 -0
  67. openinterp/builder/templates/circuit.html +64 -0
  68. openinterp/builder/templates/circuits.html +46 -0
  69. openinterp/builder/templates/experiment.html +21 -0
  70. openinterp/builder/templates/hub.html +16 -0
  71. openinterp/builder/templates/index.html +387 -0
  72. openinterp/builder/templates/layer.html +69 -0
  73. openinterp/builder/templates/learned-baseline.html +44 -0
  74. openinterp/builder/templates/model.html +151 -0
  75. openinterp/builder/templates/models.html +47 -0
  76. openinterp/builder/templates/neuron.html +234 -0
  77. openinterp/builder/templates/paper.html +39 -0
  78. openinterp/builder/templates/redirect.html +1 -0
  79. openinterp/builder/templates/research.html +31 -0
  80. openinterp/builder/templates/user.html +54 -0
  81. openinterp/builder/templates/users.html +39 -0
  82. openinterp/builder/templates/wiki/experiment.md +271 -0
  83. openinterp/builder/templates/wiki/index.md +32 -0
  84. openinterp/builder/templates/wiki/neuron.md +30 -0
  85. openinterp/builder/templates/wiki/stop.md +36 -0
  86. openinterp/builder/tree.py +470 -0
  87. openinterp/builder/users.py +142 -0
  88. openinterp/builder/wiki.py +427 -0
  89. openinterp/checks.py +429 -0
  90. openinterp/cli.py +494 -0
  91. openinterp/cli_baseline.py +332 -0
  92. openinterp/cli_benchmark.py +300 -0
  93. openinterp/cli_build.py +128 -0
  94. openinterp/cli_check.py +51 -0
  95. openinterp/cli_concepts.py +76 -0
  96. openinterp/cli_corpus.py +252 -0
  97. openinterp/cli_costs.py +257 -0
  98. openinterp/cli_coverage.py +76 -0
  99. openinterp/cli_crossref.py +86 -0
  100. openinterp/cli_errata.py +142 -0
  101. openinterp/cli_evidence.py +495 -0
  102. openinterp/cli_evidence_store.py +93 -0
  103. openinterp/cli_explain.py +101 -0
  104. openinterp/cli_loop.py +125 -0
  105. openinterp/cli_memory.py +28 -0
  106. openinterp/cli_neuronpedia.py +175 -0
  107. openinterp/cli_pause.py +45 -0
  108. openinterp/cli_pole_effects.py +133 -0
  109. openinterp/cli_probing.py +119 -0
  110. openinterp/cli_registry.py +348 -0
  111. openinterp/cli_reproduce.py +446 -0
  112. openinterp/cli_review.py +302 -0
  113. openinterp/cli_scan.py +223 -0
  114. openinterp/cli_score.py +446 -0
  115. openinterp/cli_sisters.py +86 -0
  116. openinterp/cli_submission.py +217 -0
  117. openinterp/cli_superpositions.py +118 -0
  118. openinterp/cli_wiring.py +54 -0
  119. openinterp/codeid.py +73 -0
  120. openinterp/concepts.py +400 -0
  121. openinterp/core/__init__.py +59 -0
  122. openinterp/core/agent_names.py +76 -0
  123. openinterp/core/attribution.py +101 -0
  124. openinterp/core/cache_dirs.py +15 -0
  125. openinterp/core/causal.py +82 -0
  126. openinterp/core/confounds.py +103 -0
  127. openinterp/core/contributors.py +26 -0
  128. openinterp/core/corpora.py +126 -0
  129. openinterp/core/costs.py +430 -0
  130. openinterp/core/draws.py +109 -0
  131. openinterp/core/errata.py +244 -0
  132. openinterp/core/evidence.py +160 -0
  133. openinterp/core/examples.py +93 -0
  134. openinterp/core/exceptions.py +29 -0
  135. openinterp/core/explanation.py +130 -0
  136. openinterp/core/fence.py +42 -0
  137. openinterp/core/heavy_lock.py +114 -0
  138. openinterp/core/identifiers.py +198 -0
  139. openinterp/core/isolation.py +149 -0
  140. openinterp/core/ledger.py +130 -0
  141. openinterp/core/licenses.py +28 -0
  142. openinterp/core/manifold.py +117 -0
  143. openinterp/core/partners.py +32 -0
  144. openinterp/core/patchscope.py +59 -0
  145. openinterp/core/paths.py +40 -0
  146. openinterp/core/pause.py +96 -0
  147. openinterp/core/pricing.py +178 -0
  148. openinterp/core/prior_art.py +44 -0
  149. openinterp/core/probing.py +146 -0
  150. openinterp/core/profiles.py +221 -0
  151. openinterp/core/project.py +28 -0
  152. openinterp/core/run_environment.py +38 -0
  153. openinterp/core/schemas.py +484 -0
  154. openinterp/core/specificity.py +49 -0
  155. openinterp/core/stats.py +172 -0
  156. openinterp/core/steering.py +49 -0
  157. openinterp/core/strict.py +19 -0
  158. openinterp/core/takedowns.py +136 -0
  159. openinterp/core/transcripts.py +130 -0
  160. openinterp/core/wiring.py +80 -0
  161. openinterp/corpus.py +476 -0
  162. openinterp/corpus_cache.py +145 -0
  163. openinterp/corpus_layouts.py +108 -0
  164. openinterp/corpus_presets.py +168 -0
  165. openinterp/corpus_rebuild.py +93 -0
  166. openinterp/coverage.py +155 -0
  167. openinterp/crossref.py +442 -0
  168. openinterp/data/__init__.py +9 -0
  169. openinterp/data/offensive_words.txt +58 -0
  170. openinterp/data/public_suffix_list.dat +15771 -0
  171. openinterp/data/sample_corpus.txt +40 -0
  172. openinterp/draw_steps.py +359 -0
  173. openinterp/errata_checks.py +129 -0
  174. openinterp/evidence.py +462 -0
  175. openinterp/evidence_branch.py +119 -0
  176. openinterp/evidence_lenses.py +75 -0
  177. openinterp/experiment_loop.py +357 -0
  178. openinterp/explain.py +252 -0
  179. openinterp/half_precision.py +79 -0
  180. openinterp/harness/__init__.py +37 -0
  181. openinterp/harness/ane/__init__.py +9 -0
  182. openinterp/harness/ane/backend.py +324 -0
  183. openinterp/harness/ane/cache.py +276 -0
  184. openinterp/harness/ane/chunks.py +163 -0
  185. openinterp/harness/ane/convert.py +116 -0
  186. openinterp/harness/ane/forward.py +258 -0
  187. openinterp/harness/ane/qualified.py +40 -0
  188. openinterp/harness/annotations.py +329 -0
  189. openinterp/harness/attribution.py +96 -0
  190. openinterp/harness/causal.py +264 -0
  191. openinterp/harness/confounds.py +184 -0
  192. openinterp/harness/covariance.py +301 -0
  193. openinterp/harness/crossref.py +195 -0
  194. openinterp/harness/cuda_devices.py +88 -0
  195. openinterp/harness/dead.py +124 -0
  196. openinterp/harness/devices.py +401 -0
  197. openinterp/harness/dictionaries.py +496 -0
  198. openinterp/harness/dreaming.py +116 -0
  199. openinterp/harness/environment.py +64 -0
  200. openinterp/harness/explanation_scores.py +371 -0
  201. openinterp/harness/features.py +276 -0
  202. openinterp/harness/first_position.py +137 -0
  203. openinterp/harness/heads.py +226 -0
  204. openinterp/harness/hooks.py +499 -0
  205. openinterp/harness/input_attribution.py +367 -0
  206. openinterp/harness/jlens.py +183 -0
  207. openinterp/harness/layer_cache.py +301 -0
  208. openinterp/harness/layer_major.py +274 -0
  209. openinterp/harness/lookahead.py +93 -0
  210. openinterp/harness/manifold.py +200 -0
  211. openinterp/harness/memory.py +471 -0
  212. openinterp/harness/moe.py +134 -0
  213. openinterp/harness/patcher.py +322 -0
  214. openinterp/harness/patchscope.py +177 -0
  215. openinterp/harness/probing.py +383 -0
  216. openinterp/harness/scan.py +462 -0
  217. openinterp/harness/scan_backend.py +201 -0
  218. openinterp/harness/sister_passes.py +463 -0
  219. openinterp/harness/sisters.py +363 -0
  220. openinterp/harness/sites.py +101 -0
  221. openinterp/harness/specificity.py +107 -0
  222. openinterp/harness/steering.py +159 -0
  223. openinterp/harness/superpositions.py +116 -0
  224. openinterp/harness/units.py +203 -0
  225. openinterp/harness/wiring.py +432 -0
  226. openinterp/harness/wiring_activations.py +285 -0
  227. openinterp/langid.py +73 -0
  228. openinterp/names.py +129 -0
  229. openinterp/neuronpedia_baseline.py +88 -0
  230. openinterp/neuronpedia_review.py +148 -0
  231. openinterp/planner.py +466 -0
  232. openinterp/planner_effects.py +89 -0
  233. openinterp/planner_heads.py +92 -0
  234. openinterp/planner_models.py +174 -0
  235. openinterp/planner_sisters.py +122 -0
  236. openinterp/planner_states.py +57 -0
  237. openinterp/planner_superpositions.py +114 -0
  238. openinterp/pole_effects.py +102 -0
  239. openinterp/prior_art.py +143 -0
  240. openinterp/reproduce.py +450 -0
  241. openinterp/revision.py +45 -0
  242. openinterp/runner_cache.py +35 -0
  243. openinterp/score_controls.py +169 -0
  244. openinterp/sensitive.py +243 -0
  245. openinterp/show.py +236 -0
  246. openinterp/signing.py +209 -0
  247. openinterp/sisters.py +476 -0
  248. openinterp/superposition_finders.py +225 -0
  249. openinterp/sync/__init__.py +5 -0
  250. openinterp/sync/r2.py +280 -0
  251. openinterp/syntax.py +399 -0
  252. openinterp/takedown_checks.py +76 -0
  253. openinterp/toxicity.py +158 -0
  254. openinterp/verdict_regression.py +79 -0
  255. openinterp/wiring_backfill.py +170 -0
  256. openinterp/wordnet.py +362 -0
@@ -0,0 +1,271 @@
1
+ {% set ident = sub.identifier %}
2
+ {% set is_head = ident.kind == 'attn_head' %}
3
+ {% set is_feature = ident.kind == 'dictionary_feature' %}
4
+ {% set peer = 'head' if is_head else ('latent' if is_feature else 'neuron') %}
5
+ # {{ ident.model_name }} · {{ label }} · {{ verdict.status }}
6
+
7
+ [← all experiments on this {{ 'head' if is_head else ('feature' if is_feature else 'neuron') }}](README.md) · [wiki home]({{ home }})
8
+
9
+ | | |
10
+ | --- | --- |
11
+ | Experiment | `{{ meta.experiment_id }}` ({{ kind }}{% if previous_status %}, previous verdict {{ previous_status }}{% endif %}) |
12
+ {% if sub.supersedes %}
13
+ | Revises | [{{ sub.supersedes }}]({{ sub.supersedes }}.md) |
14
+ {% endif %}
15
+ {% if sub.sister_of %}
16
+ | Sister study of | [{{ sub.sister_of }}](../../../{{ sub.sister_of }}.md) (its explanation, unchanged) |
17
+ {% endif %}
18
+ | Date | {{ verdict.timestamp.strftime("%Y-%m-%d %H:%M UTC") }} |
19
+ | Verdict | **{{ verdict.status }}**, balanced accuracy {{ verdict.confidence_score | num(2) }} |
20
+ | Protocol | {{ ('v' ~ policy.protocol_version) if policy else 'unrecorded (pre-0.2)' }} |
21
+ | Proposer | `{{ sub.submitting_agent_model | cell }}`{% if sub.contributor %}, run by {{ sub.contributor | cell }}{% endif %} |
22
+ | Reviewer | `{{ verdict.reviewer_agent_model | cell }}`{% if verdict.contributor %}, run by {{ verdict.contributor | cell }}{% endif %}{% if self_reviewed %} (self-reviewed: same model as the proposer, so not an independent review){% endif %} |
23
+ {% if sub.provenance %}
24
+ {% set p = sub.provenance %}
25
+ | Selection | {{ p.selection }}{% if p.seed is not none %} (seed {{ p.seed }}){% endif %} |
26
+ | Corpus | {{ p.corpus | cell }} · {{ "{:,}".format(p.n_snippets) }} snippets · {{ "{:,}".format(p.tokens_scanned) }} tokens{% if p.corpus_sample %} · seeded sample of {{ p.corpus_sample.documents }}/{{ p.corpus_sample.corpus_documents }} docs (≤ {{ "{:,}".format(p.corpus_sample.max_tokens) }} tokens, seed {{ p.corpus_sample.seed }}){% endif %}{% if p.snippet_tokens %} · {{ p.snippet_tokens }}-token windows{% if p.snippet_stride %} every {{ p.snippet_stride }} tokens{% endif %}{% endif %}{% if p.corpus_source and p.corpus_source.license %} · licence {{ p.corpus_source.license | cell }}{% endif %} |
27
+ | Model revision | `{{ p.model_revision or 'unrecorded' }}` · {{ p.dtype }} |
28
+ {% if p.costs %}
29
+ | Run cost | {{ p.costs.summary() | cell }} (reported, not gated) |
30
+ {% endif %}
31
+ {% endif %}
32
+ {% if record_link %}
33
+ | Record | [{{ record_link }}]({{ record_link }}) (this experiment's full record) |
34
+ {% endif %}
35
+
36
+ ## Hypothesis
37
+
38
+ > {{ sub.natural_language_explanation }}
39
+
40
+ - **Activating tokens:** {% for t in sub.activating_tokens %}`{{ t | cell }}`{{ ", " if not loop.last }}{% endfor %}
41
+
42
+ - **Mechanism claimed:** {{ 'lookahead, preparing ' ~ (sub.lookahead.target_upcoming_tokens | join(', ')) if sub.lookahead.is_lookahead else 'retrospective' }}
43
+ - **Max activation (scan):** {{ sub.max_activation | num(4) }}{% if is_head %} (head strength, \|W_O (z − z̄)\|){% elif is_feature %} (latent activation){% endif +%}
44
+ {% if sub.head_profile %}
45
+ {% set hp = sub.head_profile %}
46
+ - **Attention patterns** (random {{ hp.pattern_length }}-token sequences repeated twice; reported, not gated): previous token {{ hp.previous_token_score | num(2) }}, duplicate token {{ hp.duplicate_token_score | num(2) }}, induction {{ hp.induction_score | num(2) }}
47
+ {% endif %}
48
+ {% if sub.dictionary_profile %}
49
+ {% set dp = sub.dictionary_profile %}
50
+ - **Dictionary** (a learned-basis baseline, not a native unit): a {{ dp.kind }} with {{ dp.n_features }} latents, `{{ dp.repo }}`{% if dp.revision %}@{{ dp.revision[:8] }}{% endif %} `{{ dp.path }}`, reading `{{ dp.input_site }}`. On the scan it explains {{ dp.explained_variance | num(2) if dp.explained_variance is not none else 'unmeasured' }} of the {{ 'residual stream' if dp.output_site == 'resid_post' else 'MLP output' }}'s variance with mean L0 {{ dp.mean_l0 | num(1) if dp.mean_l0 is not none else 'unmeasured' }}; this latent is active on {{ dp.density | num(4) }} of tokens (reported, not gated).
51
+ {% endif %}
52
+
53
+ {% if examples %}
54
+ ### Top-activating examples
55
+
56
+ Peak token in ⟦ ⟧.
57
+
58
+ ```text
59
+ {% for act, ctx in examples %}
60
+ {{ "%.3f" | format(act) }} {{ ctx }}
61
+ {% endfor %}
62
+ ```
63
+ {% endif %}
64
+
65
+ ## Results
66
+
67
+ {% if metrics %}
68
+ | Gate | Result |
69
+ | --- | --- |
70
+ {% for gate, ok in metrics.gates.items() %}
71
+ | {{ gate | replace('_', ' ') }} | {{ '✅ pass' if ok else '❌ fail' }} |
72
+ {% endfor %}
73
+
74
+ Specificity {{ metrics.specificity | num(2) }} · sensitivity {{ metrics.sensitivity | num(2) }} · balanced accuracy {{ metrics.balanced_accuracy | num(2) }} · counterfactual reproduction {{ metrics.counterfactual_reproduction | num(2) }}
75
+ {% else %}
76
+ This verdict predates protocol v0.2, so it has no per-gate metrics. Run `open-interpretability reevaluate` to apply the current rule.
77
+ {% endif %}
78
+ {% if verdict.causal_metrics %}
79
+
80
+ {% set c = verdict.causal_metrics %}
81
+ {% if c.target %}
82
+ Causal metrics (recorded, not gated): sufficiency {{ c.sufficiency_score | num(4) }}, necessity {{ c.necessity_score | num(4) }}: percentiles of the {{ 'head' if is_head else ('feature' if is_feature else 'pole') }}'s patch effect among the {{ c.null_neurons }} same-layer {{ peer }}s that change as much, median over {{ c.pairs_scored }} non-control pairs. Target: {{ c.target }}{% if c.target_tokens %} ({{ c.target_tokens | join(", ") }}){% endif %}; median effect {{ '%.3g' | format(c.sufficiency_effect) }} / {{ '%.3g' | format(c.necessity_effect) }}; hydra mitigated: {{ c.hydra_mitigated }}.
83
+ {% if c.pairs %}
84
+
85
+ | Pair | Sufficiency | Effect | Matched median / max | Necessity | Effect | Matched median / max |
86
+ | --- | --- | --- | --- | --- | --- | --- |
87
+ {% for p in c.pairs %}
88
+ | {{ p.pair_index + 1 }} | {{ p.sufficiency.percentile | num(2) }} | {{ '%.3g' | format(p.sufficiency.effect) }} | {{ '%.3g' | format(p.sufficiency.null_median) }} / {{ '%.3g' | format(p.sufficiency.null_max) }} | {{ p.necessity.percentile | num(2) }} | {{ '%.3g' | format(p.necessity.effect) }} | {{ '%.3g' | format(p.necessity.null_median) }} / {{ '%.3g' | format(p.necessity.null_max) }} |
89
+ {% endfor %}
90
+ {% endif %}
91
+ {% else %}
92
+ Causal metrics (recorded, not gated; top-1 logit, protocol < 0.5): sufficiency {{ c.sufficiency_score | num(4) }}, necessity {{ c.necessity_score | num(4) }}, hydra mitigated: {{ c.hydra_mitigated }}.
93
+ {% endif %}
94
+ {% endif %}
95
+ {% if verdict.explanation_scores %}
96
+ {% set es = verdict.explanation_scores %}
97
+
98
+ Explanation scores on held-out text (recorded, not gated): detection {{ (es.detection.balanced_accuracy if es.detection else none) | num(2) }}, fuzzing {{ (es.fuzzing.balanced_accuracy if es.fuzzing else none) | num(2) }} (balanced accuracy of a judge given only the hypothesis), embedding AUROC {{ es.embedding_auroc | num(2) }}. {{ es.detection_windows | length }} detection and {{ es.fuzzing_windows | length }} fuzzing windows of {{ es.window_tokens }} tokens, from {{ es.active_windows }} active of {{ es.candidate_windows }} held-out windows; judge `{{ es.judge_model | cell }}`{% if es.detection %}; detection recall by activation quantile, weakest to top: {% for r in es.detection.recall_by_quantile %}{{ r | num(2) }}{{ ", " if not loop.last }}{% endfor %}{% endif %}.
99
+ {% endif %}
100
+
101
+ ### Probes
102
+
103
+ | | Kind | Probe | Expected | Activation |
104
+ | --- | --- | --- | --- | --- |
105
+ {% for t in verdict.adversarial_test_results if t.kind in ('hard_negative', 'positive_holdout') %}
106
+ | {{ ('✅' if t.passed else '❌') if t.measured else '—' }} | {{ t.kind | replace('_', ' ') }} | {{ t.prompt | cell }} | {{ 'active' if t.expected_active else 'inactive' }} | {{ t.activation | num(3) if t.measured else 'unmeasured (one token)' }} |
107
+ {% endfor %}
108
+
109
+ ### Counterfactuals
110
+
111
+ | | Base → counterfactual | Expected Δ | Observed Δ |
112
+ | --- | --- | --- | --- |
113
+ {% for t in verdict.adversarial_test_results if t.kind == 'counterfactual' %}
114
+ | {{ ('✅' if t.passed else '❌') if t.measured else '—' }} | {{ t.prompt | cell }} | {{ t.expected_delta | num(2) }} | {{ t.observed_delta | num(3) if t.measured else 'unmeasured (one token)' }} |
115
+ {% endfor %}
116
+ {% for t in verdict.adversarial_test_results if t.kind == 'lookahead_consistency' %}
117
+
118
+ **Lookahead check:** {{ '✅' if t.passed else '❌' }} {{ t.detail }}
119
+ {% endfor %}
120
+
121
+ {% if sub.vocabulary_lens %}
122
+ {% set vl = sub.vocabulary_lens %}
123
+ ### Vocabulary lens
124
+
125
+ | | Jacobian lens | Logit lens |
126
+ | --- | --- | --- |
127
+ {% for label, side in [("Promotes", "promoted"), ("Suppresses", "suppressed")] %}
128
+ | {{ label }} |{% for lens in ("jacobian", "logit") %}{% set zs = vl[lens ~ "_" ~ side ~ "_z"] %} {% for t in vl[lens ~ "_" ~ side][:8] %}`{{ t | cell }}`{% if zs %} {{ "%+.1f" | format(zs[loop.index0]) }}{% endif %} {% endfor %}|{% endfor %}
129
+
130
+ {% endfor %}
131
+
132
+ {% if vl.jacobian_promoted_z %}Numbers are z-scores over the whole vocabulary. {% endif %}Top-10 overlap {{ vl.overlap | pct }}; cos(w, J·w) {{ vl.direction_cosine | num(2) }}; kurtosis {{ vl.jacobian_kurtosis | num(1) }} (Jacobian) vs {{ vl.logit_kurtosis | num(1) }} (logit); {{ vl.prompts }} prompts.
133
+
134
+ {% endif %}
135
+ {% if sub.patchscope and sub.patchscope.readings %}
136
+ {% set ps = sub.patchscope %}
137
+ ### Patchscope
138
+
139
+ The model's own description of the output direction, with no examples: the direction replaces the residual stream after the named layer's block at the `{{ ps.placeholder | cell }}` of each prompt, at each multiple of the norm it replaces, and the model continues greedily. The control injects a random direction instead, so text the two share comes from the prompt. Read after the proposer answered and shown to neither agent; reported, not gated.
140
+
141
+ | Prompt | Layer | |{% for s in ps.scales %} ×{{ "%g" | format(s) }} |{% endfor %}
142
+
143
+ | --- | --- | --- |{% for s in ps.scales %} --- |{% endfor %}
144
+
145
+ {% for prompt, layer, readings in ps.rows %}
146
+ | {{ prompt }} | {{ layer }} | unit |{% for r in readings %} {{ r.text | cell }} |{% endfor %}
147
+
148
+ | | | control |{% for r in readings %} {{ r.control_text | cell }} |{% endfor %}
149
+
150
+ {% endfor %}
151
+
152
+ Prompts: {% for name, template in ps.prompts.items() %}{{ name }} `{{ template | replace("{x}", ps.placeholder) | cell }}`{{ "; " if not loop.last }}{% endfor %}.
153
+
154
+ {% endif %}
155
+ {% if sub.steering and sub.steering.samples %}
156
+ {% set st = sub.steering %}
157
+ ### Steering
158
+
159
+ Neutral prompts continued greedily for up to {{ st.max_new_tokens }} tokens with the unit ablated, untouched, and clamped at multiples of its top activation in the scan ({{ st.clamp_unit | num(2) }}), at every token. Drift at ×1–×2 says what the unit makes the model write; drift only at ×4 is off-distribution. Taken after the proposer answered and shown to neither agent; reported, not gated.
160
+
161
+ | Prompt | Ablated | Baseline |{% for m in st.multiples %} Clamped ×{{ "%g" | format(m) }} |{% endfor %}
162
+
163
+ | --- | --- | --- |{% for m in st.multiples %} --- |{% endfor %}
164
+
165
+ {% for s in st.samples %}
166
+ | {{ s.prompt | cell }} | {{ s.ablated | cell }} | {{ s.baseline | cell }} |{% for text in s.clamped %} {{ text | cell }} |{% endfor %}
167
+
168
+ {% endfor %}
169
+
170
+ {% endif %}
171
+ {% if sub.wordnet_specificity %}
172
+ {% set sp = sub.wordnet_specificity %}
173
+ ### WordNet specificity
174
+
175
+ The unit on words that WordNet puts under `{{ sp.synset }}` ({{ sp.lemma }}; {{ "named by the proposer" if sp.source == "proposer" else "the largest category of the peak words" }}) and on words of its sibling categories ({{ sp.sibling_synsets[:8] | join(", ") }}{{ ", …" if sp.sibling_synsets | length > 8 }}), each in {{ sp.carriers | length }} neutral sentences, peak words left out. AUROC {{ sp.auroc | num(2) }} (the chance that a category word is stronger than a sibling word); active: {{ sp.category_active | pct }} of category words, {{ sp.siblings_active | pct }} of sibling words. Strengths are fractions of the top activation in the scan. Measured after the proposer answered and shown to neither agent; reported, not gated.
176
+
177
+ - **{{ sp.lemma }}:** {% for w in sp.category %}{{ w.word }} {{ (w.strength / sp.scale) | num(2) }}{{ ", " if not loop.last }}{% endfor %}
178
+
179
+ - **Siblings:** {% for w in sp.siblings %}{{ w.word }} {{ (w.strength / sp.scale) | num(2) }}{{ ", " if not loop.last }}{% endfor %}
180
+
181
+
182
+ {% endif %}
183
+ {% for w in [sub.wiring, verdict.wiring] if w %}
184
+ {% if loop.first %}
185
+ ### Wiring
186
+
187
+ The units that write most directly into this unit's input (upstream) and read most directly from its output (downstream), along the residual stream without passing through other units. Reported, not gated.
188
+
189
+ {% endif %}
190
+ {% if w.method == "weights" %}
191
+ **From the weights.** Virtual weights with each norm's gain folded in; they rank units but have no absolute scale. Each number is how much one unit reads of the other's write: signed when one vector reads another (+ means a positive activation raises the read), otherwise a norm. Heads count through their OV circuit upstream and their Q, K and V reads downstream. Read after the proposer answered and shown to neither agent.
192
+ {% else %}
193
+ **From activations,** averaged over this unit's peak on {{ w.prompts }} of the review's prompts where it fired. Upstream: the first-order change in its strength from removing a unit's direct write (+ excites). Downstream: the change in a later neuron's activation, or how far a later head's write moves, when this unit's write is removed from that unit's input (one of Q, K or V for a head) alone.
194
+ {% endif %}
195
+
196
+ {% for title, edges in [("Upstream neurons", w.upstream_neurons), ("Upstream heads", w.upstream_heads), ("Downstream neurons", w.downstream_neurons), ("Downstream heads", w.downstream_heads)] %}
197
+ - **{{ title }}:** {% if edges is none %}not measured.{% elif not edges %}none.{% else %}{% for e in edges %}L{{ e.layer }}/{{ "N" if e.kind == "mlp_neuron" else "H" }}{{ e.index }} {{ "%+.3g" | format(e.weight) }}{{ ", " if not loop.last }}{% endfor %}{% endif %}
198
+
199
+ {% endfor %}
200
+
201
+ {% endfor %}
202
+ {% if sub.input_attribution and sub.input_attribution.examples %}
203
+ {% set ia = sub.input_attribution %}
204
+ ### Input attribution
205
+
206
+ Integrated gradients over the input tokens at the peak of {{ ia.examples | length }} top examples, from a baseline of `{{ ia.baseline_token | cell }}` at every position but the first; the path integral converged on {{ ia.converged }}. Replacing one token at a time agrees at ρ = {{ ia.ablation_agreement | num(2) }}.
207
+
208
+ {% if ia.distances %}
209
+ Share of |attribution| by distance from the peak, over converged examples; mean {{ ia.mean_distance | num(1) }} tokens back:
210
+
211
+ | Tokens back |{% for d in ia.distances %} {{ d.label }} |{% endfor %}
212
+
213
+ | --- |{% for d in ia.distances %} --- |{% endfor %}
214
+
215
+ | Share |{% for d in ia.distances %} {{ d.share | pct }} |{% endfor +%}
216
+
217
+ {% endif %}
218
+ | Example | Peak | Most attributed tokens: offset, attribution / ablation effect |
219
+ | --- | --- | --- |
220
+ {% for ex in ia.examples %}
221
+ | {{ ex.example + 1 }}{{ "" if ex.converged else " (not converged)" }} | `{{ ex.peak_token | cell }}` | {% for t in ex.top %}`{{ t.token | cell }}` {{ t.offset }}, {{ t.attribution | num(2) }} / {{ t.ablation_effect | num(2) }}{{ "; " if not loop.last }}{% endfor %} |
222
+ {% endfor %}
223
+
224
+ {% endif %}
225
+ ### Covariance and confounds
226
+
227
+ {% if metrics and metrics.effective_hard_negatives is not none %}
228
+ - **Independent observations:** {{ metrics.effective_hard_negatives }} hard-negative and {{ metrics.effective_holdouts }} holdout clusters (near-duplicate probes count once).
229
+ {% endif %}
230
+ {% if sub.confounds %}
231
+ - **Confounds:** token identity R² {{ sub.confounds.token_r2 | num(2) }}, position R² {{ sub.confounds.position_r2 | num(2) }}, frequency r {{ sub.confounds.frequency_correlation | num(2) }}{% for name, lc in (sub.confounds.labels or {}).items() %}, {{ name }} R² {{ lc.r2 | num(2) }} ({{ lc.mutual_information_bits | num(3) }} bits){% endfor %}.{% if metrics and metrics.confound_baseline %} Best trivial baseline: {{ metrics.confound_baseline }} at {{ metrics.confound_baseline_accuracy | num(2) }}; the hypothesis scores {{ metrics.balanced_accuracy | num(2) }}.{% endif %}
232
+
233
+ {% else %}
234
+ - **Confounds:** no confound profile (the scan predates protocol 0.3).
235
+ {% endif %}
236
+ {% if sub.correlated_neurons %}
237
+ - **Co-activating neuron poles:** {% for c in sub.correlated_neurons[:5] %}N{{ c.neuron_idx }}{{ '+' if c.pole == 'positive' else '−' }} (lift ≥ {{ "%.1f" | format(c.coactivation_lift_lower) }} on {{ c.coactive_tokens }} tokens, ρ = {{ "%+.2f" | format(c.spearman) }}){{ ", " if not loop.last }}{% endfor %}
238
+
239
+ {% endif %}
240
+ {% if verdict.joint_ablation %}
241
+ {% set ja = verdict.joint_ablation %}
242
+ - **Joint ablation** with {% for p in ja.partners %}N{{ p }}{{ ", " if not loop.last }}{% endfor %}: KL alone {{ "%.2e" | format(ja.kl_single) }}, partners {{ "%.2e" | format(ja.kl_partners) }}, together {{ "%.2e" | format(ja.kl_joint) }}; redundancy ratio {{ ja.redundancy_ratio | num(2) }}.
243
+ {% endif %}
244
+
245
+ ## Next steps
246
+
247
+ {% if self_reviewed %}
248
+ **Self-reviewed.** The proposer's model also wrote the probes. That is allowed, but a review by a different model is stronger evidence, so a re-review is the first follow-up (`open-interpretability next` draws these).
249
+
250
+ {% endif %}
251
+ {% if verdict.status == 'VERIFIED' %}
252
+ Published in the registry. Possible follow-ups: audit the opposite pole, try a sibling model for a universal counterpart, and run steering tests (skill: `neuron-steering-tests`).
253
+ {% else %}
254
+ {% for a in advice %}
255
+ - {{ a }}
256
+ {% else %}
257
+ - Revise the hypothesis and resubmit.
258
+ {% endfor %}
259
+ {% if failed_probes %}
260
+
261
+ Failed probes:
262
+
263
+ {% for t in failed_probes %}
264
+ - {{ t.kind | replace('_', ' ') }}: “{{ t.prompt }}” (activation {{ t.activation | num(3) }})
265
+ {% endfor %}
266
+ {% endif %}
267
+ {% endif %}
268
+
269
+ ## Discussion
270
+
271
+ <!-- Free-form notes. This page is never regenerated, so edits here are kept. -->
@@ -0,0 +1,32 @@
1
+ # Experiment wiki
2
+
3
+ Every completed Open Interpretability experiment, newest first. Pages are written automatically by `open-interpretability verify` and `open-interpretability reevaluate`. Each experiment's full record sits next to its page as `<id>.json`. To import loose records, run `open-interpretability wiki --import-dir <dir>`. Each experiment page is written once and never regenerated, so its **Discussion** section is safe to edit.
4
+
5
+ The protocol is in [docs/PROTOCOL.md](../docs/PROTOCOL.md).
6
+
7
+ Experiments: **{{ rows | length }}** · units: **{{ neurons }}**{% for status, n in counts | dictsort %} · {{ status }}: {{ n }}{% endfor %}
8
+
9
+ {% if unindexed_stops %}
10
+ ## Scans that stopped on units with no experiment
11
+
12
+ These attempts tested no hypothesis, so they give no verdict. Each unit below has no experiment on this pole, so it has no index of its own.
13
+
14
+ | Date | Unit | Outcome | Active share | Page |
15
+ | --- | --- | --- | --- | --- |
16
+ {% for r in unindexed_stops %}
17
+ | {{ r.stop.timestamp.strftime("%Y-%m-%d %H:%M") }} | {{ r.stop.identifier.model_name }} {{ r.label }} | {{ r.stop.outcome | replace('_', '-') }} | {{ r.stop.active_share | pct }} | [{{ r.stop.timestamp.strftime("%Y%m%dT%H%M%SZ") }}]({{ r.link }}) |
18
+ {% endfor %}
19
+
20
+ ## Experiments
21
+
22
+ {% endif %}
23
+
24
+ | Date | Unit | Kind | Status | Balanced acc. | Hypothesis |
25
+ | --- | --- | --- | --- | --- | --- |
26
+ {% for r in rows %}
27
+ | [{{ r.timestamp[:10] }}]({{ r.link }}) | [{{ r.model }} {{ r.label }}]({{ r.neuron_link }}) | {{ r.kind }} | {{ r.status }}{% if r.get('proposer') and r.proposer == r.get('reviewer') %} (self-reviewed){% endif %} | {{ r.balanced_accuracy | num(2) }} | {{ r.hypothesis | truncate(100) | cell }} |
28
+ {% else %}
29
+ | | | | No experiments yet. | | |
30
+ {% endfor %}
31
+
32
+ <!-- Generated by openinterp; edits to this file are overwritten. -->
@@ -0,0 +1,30 @@
1
+ # {{ latest.model }} · {{ label }}
2
+
3
+ [← wiki home]({{ home }})
4
+
5
+ **Latest status:** {{ latest.status }} ({{ latest.timestamp[:10] }})
6
+
7
+ > {{ latest.hypothesis }}
8
+
9
+ ## Experiment history
10
+
11
+ | Date | Experiment | Kind | Status | Balanced acc. | Protocol | Hypothesis |
12
+ | --- | --- | --- | --- | --- | --- | --- |
13
+ {% for e in history %}
14
+ | {{ e.meta.timestamp[:16] | replace('T', ' ') }} | [{{ e.meta.experiment_id }}]({{ e.path.name }}){% if e.meta.get("supersedes") %}, revises [{{ e.meta.supersedes }}]({{ e.meta.supersedes }}.md){% endif %} | {{ e.meta.kind }} | {{ e.meta.status }}{% if e.meta.get('proposer') and e.meta.proposer == e.meta.get('reviewer') %} (self-reviewed){% endif %} | {{ e.meta.balanced_accuracy | num(2) }} | {{ e.meta.protocol_version or '—' }} | {{ e.meta.hypothesis | truncate(90) | cell }} |
15
+ {% endfor %}
16
+ {% if stops %}
17
+
18
+ ## Scans that stopped
19
+
20
+ These attempts tested no hypothesis, so they give no verdict.
21
+
22
+ | Date | Outcome | Active share | Protocol | Page |
23
+ | --- | --- | --- | --- | --- |
24
+ {% for s in stops %}
25
+ {% set stamp = s.timestamp.strftime("%Y%m%dT%H%M%SZ") %}
26
+ | {{ s.timestamp.strftime("%Y-%m-%d %H:%M") }} | {{ s.outcome | replace('_', '-') }} | {{ s.active_share | pct }} | {{ s.protocol_version }} | [{{ stamp }}]({{ home | replace('README.md', '') }}stops/{{ slug }}/{{ stamp }}.md) |
27
+ {% endfor %}
28
+ {% endif %}
29
+
30
+ <!-- Generated by openinterp; edits to this file are overwritten. Put notes in an experiment page's Discussion section. -->
@@ -0,0 +1,36 @@
1
+ {% set p = stop.provenance %}
2
+ {% set default_on = stop.outcome == 'default_on' %}
3
+ # {{ meta.model }} · {{ label }} · scan stopped ({{ stop.outcome | replace('_', '-') }})
4
+
5
+ {% if stop.latest_record %}
6
+ [← all experiments on this unit]({{ root }}experiments/{{ meta.slug }}/README.md) · {% endif %}[wiki home]({{ root }}README.md)
7
+
8
+ | | |
9
+ | --- | --- |
10
+ | Outcome | **{{ stop.outcome | replace('_', '-') }}**{% if default_on %}, active on {{ stop.active_share | pct }} of the scan's tokens{% endif %} |
11
+ | Date | {{ stop.timestamp.strftime("%Y-%m-%d %H:%M UTC") }} |
12
+ | Protocol | v{{ stop.protocol_version }} |
13
+ | Selection | {{ p.selection }} |
14
+ {% if stop.latest_record %}
15
+ | Newest record | [{{ stop.latest_record }}]({{ root }}experiments/{{ meta.slug }}/{{ stop.latest_record }}.md) |
16
+ {% endif %}
17
+ | Corpus | {{ p.corpus | cell }} · {{ "{:,}".format(p.n_snippets) }} snippets · {{ "{:,}".format(p.tokens_scanned) }} tokens{% if p.snippet_tokens %} · {{ p.snippet_tokens }}-token windows every {{ p.snippet_stride }} tokens{% endif %} |
18
+ | Model revision | `{{ p.model_revision or 'unrecorded' }}` · {{ p.dtype }} |
19
+
20
+ ## What happened
21
+
22
+ {% if default_on %}
23
+ The scan stopped before this attempt wrote a hypothesis. This unit is active on {{ stop.active_share | pct }} of the scan's tokens. The limit is {{ policy.max_active_share | pct }} (`max_active_share`, docs/PROTOCOL.md §1). At that density, a probe of a few words almost always has one active token. So no hard negative can stay inactive, and the unit can't be audited as a detector.
24
+ {% elif stop.proven_dead %}
25
+ The scan stopped before this attempt wrote a hypothesis. This unit never fires on the corpus, and the weights prove that no input can make it fire (largest pre-activation {{ stop.dead_bound | num(3) }}).
26
+ {% else %}
27
+ The scan stopped before this attempt wrote a hypothesis. This unit never fires on the corpus, but the weights don't prove it dead. A larger corpus can still find activations.
28
+ {% endif %}
29
+
30
+ ## What this changes
31
+
32
+ This attempt tested no hypothesis, so it gives no verdict. {% if stop.latest_record %}The unit's newest record keeps its status.{% else %}The unit has no experiment record yet.{% endif %} This unit was chosen, not drawn at random, so this stop doesn't count in random-draw statistics.
33
+
34
+ ## Discussion
35
+
36
+ <!-- Notes go here. The rest of this page is generated and write-once. -->