09Catho commited on
Commit
4e1f0bf
·
verified ·
1 Parent(s): 9fc9d87

BrainPatch smoke_v0: SAE, feature database, experiment artifacts

Browse files
ARTIFACTS.json CHANGED
@@ -58,16 +58,20 @@
58
  "bytes": 5020
59
  },
60
  {
61
- "path": "patches/experimental-feature-727-scheduled.json",
62
  "bytes": 1899
63
  },
64
  {
65
- "path": "patches/experimental-feature-727.json",
66
  "bytes": 4714
67
  },
 
 
 
 
68
  {
69
  "path": "README.md",
70
- "bytes": 17573
71
  }
72
  ]
73
  }
 
58
  "bytes": 5020
59
  },
60
  {
61
+ "path": "patches/research/experimental-feature-727-scheduled.json",
62
  "bytes": 1899
63
  },
64
  {
65
+ "path": "patches/research/experimental-feature-727.json",
66
  "bytes": 4714
67
  },
68
+ {
69
+ "path": "patches/runtime/experimental-feature-727.brainpatch",
70
+ "bytes": 6523
71
+ },
72
  {
73
  "path": "README.md",
74
+ "bytes": 16598
75
  }
76
  ]
77
  }
README.md CHANGED
@@ -62,13 +62,14 @@ delta_raw = strength × unit_decoder_column / input_scale
62
 
63
  | Path | What |
64
  |---|---|
 
 
65
  | `sae/smoke_v0/sae_latest.pt` | SAE weights, optimizer state, liveness buffers, config |
66
  | `sae/smoke_v0/config.json` | Architecture and training configuration |
67
  | `sae/smoke_v0/metrics.jsonl` | Per-step training metrics |
68
  | `feature-db/smoke_v0/features.jsonl` | Per-feature statistics and top-activating contexts |
69
  | `activations/smoke_v0/manifest.json` | Corpus provenance (metadata only — no shards) |
70
  | `experiments/smoke_v0_intervention/` | All generations, metrics, and the report |
71
- | `patches/` | BrainPatch JSON files |
72
 
73
  The Qwen base weights are **not** duplicated here. Load them from [`Qwen/Qwen2.5-1.5B-Instruct`](https://huggingface.co/Qwen/Qwen2.5-1.5B-Instruct) at revision `989aa7980e4cf806f80c7fef2b1adb7bc71aa306`.
74
 
@@ -78,85 +79,60 @@ Raw activation shards are not published: 58.8 MB derived from a CC BY-SA corpus,
78
 
79
  ## Usage
80
 
81
- Requires a CUDA GPU, `torch`, `transformers`, and the `brainpatch` package:
 
 
82
 
83
  ```bash
84
- pip install torch transformers "brainpatch @ git+https://github.com/09Catho/BrainPatch.git"
 
 
85
  ```
86
 
87
- This snippet is **copy-paste runnable from a clean environment**. Both the SAE
88
- checkpoint *and* the patch file are fetched from this repository — nothing is
89
- assumed to exist on disk. It is verified end to end in a fresh Modal container
90
- by `modal run modal_app/app.py::verify_model_card_example`.
91
-
92
  ```python
93
- from huggingface_hub import hf_hub_download
94
-
95
  from brainpatch import BrainPatchedModel
96
 
97
- REPO = "09Catho/BrainPatch-Qwen2.5-1.5B"
98
-
99
- # Both artifacts come from the Hub. The patch is a small JSON file; the
100
- # checkpoint is ~72 MB. The Qwen base weights are downloaded by transformers.
101
- checkpoint_path = hf_hub_download(REPO, "sae/smoke_v0/sae_latest.pt")
102
- patch_path = hf_hub_download(REPO, "patches/experimental-feature-727.json")
103
-
104
  model = BrainPatchedModel.from_pretrained(
105
  "Qwen/Qwen2.5-1.5B-Instruct",
106
  revision="989aa7980e4cf806f80c7fef2b1adb7bc71aa306",
 
 
107
  )
108
- model.load_sae(checkpoint_path, reference="smoke_v0")
109
-
110
- # install() validates the patch against the loaded model and SAE, and raises
111
- # PatchCompatibilityError on any mismatch of model, revision, layer or SAE.
112
- model.install(patch_path)
113
-
114
- # set_patch_strength is a MULTIPLIER on the patch's own strength, not an
115
- # absolute value. This patch declares strength 16.0, so 1.0 keeps the effective
116
- # coefficient at 16 — the value the dose-response sweep found changes output
117
- # while fluency holds. See the warning below before raising it.
118
- model.set_patch_strength("experimental-feature-727", 1.0)
119
-
120
  print(model.generate("Solve this problem: what is 17 + 25?"))
121
  ```
122
 
123
- `reference="smoke_v0"` must match the patch's `sae.reference` field; that is the
124
- check which stops feature IDs from one dictionary being applied to another.
125
-
126
- > **The multiplier compounds, and the model breaks well before you might expect.**
127
- > An earlier draft of this example used `1.5`, giving an effective coefficient of
128
- > 24. Run on Modal, that produced `"17 + 25 = 32"` — a wrong answer, followed by
129
- > a confused digression about the commutative property of *multiplication* —
130
- > where the unpatched model correctly answered 42.
131
- >
132
- > That is not a bug; it is what a ~34% residual-stream perturbation does to a
133
- > 1.5B model. The measured sweep is in the dose–response table below: usable
134
- > around 8–16, looping at 32, collapse at 64. **Treat any strength you have not
135
- > measured as unsafe**, and check arithmetic and instruction-following whenever
136
- > you change it.
137
 
138
- Ad-hoc single-feature steering, no patch file needed:
139
 
140
  ```python
141
- model.add_feature(layer=18, feature_id=727, strength=16.0)
142
  ```
143
 
144
- Dynamic mid-generation steering, keyed on **generated**-token index:
145
 
146
- ```python
147
- from brainpatch.steering import StrengthSchedule
148
-
149
- model.set_patch_schedule(
150
- "experimental-feature-727", StrengthSchedule({0: 0.0, 24: 1.0, 48: 2.0})
151
- )
152
- ```
153
 
154
- To recover the baseline, either uninstall the patch or set its strength to zero
155
- — the two are byte-identical by construction:
156
 
157
- ```python
158
- model.set_patch_strength("experimental-feature-727", 0.0)
159
- ```
 
 
 
 
 
 
 
 
 
 
 
160
 
161
  ---
162
 
 
62
 
63
  | Path | What |
64
  |---|---|
65
+ | **`patches/runtime/*.brainpatch`** | **Portable runtime patches — 6.4 KB, self-contained, no SAE needed** |
66
+ | `patches/research/*.json` | v0.1 research patches (reference SAE feature IDs; need the SAE) |
67
  | `sae/smoke_v0/sae_latest.pt` | SAE weights, optimizer state, liveness buffers, config |
68
  | `sae/smoke_v0/config.json` | Architecture and training configuration |
69
  | `sae/smoke_v0/metrics.jsonl` | Per-step training metrics |
70
  | `feature-db/smoke_v0/features.jsonl` | Per-feature statistics and top-activating contexts |
71
  | `activations/smoke_v0/manifest.json` | Corpus provenance (metadata only — no shards) |
72
  | `experiments/smoke_v0_intervention/` | All generations, metrics, and the report |
 
73
 
74
  The Qwen base weights are **not** duplicated here. Load them from [`Qwen/Qwen2.5-1.5B-Instruct`](https://huggingface.co/Qwen/Qwen2.5-1.5B-Instruct) at revision `989aa7980e4cf806f80c7fef2b1adb7bc71aa306`.
75
 
 
79
 
80
  ## Usage
81
 
82
+ **Most users want the portable patch, not the SAE.** A `.brainpatch` file is
83
+ 6.4 KB and self-contained; the 72 MB SAE checkpoint is a research artifact you
84
+ only need if you are discovering new features.
85
 
86
  ```bash
87
+ pip install "brainpatch[transformers,hub]"
88
+ brainpatch install 09Catho/BrainPatch-Qwen2.5-1.5B:patches/runtime/experimental-feature-727.brainpatch
89
+ brainpatch compare --model Qwen/Qwen2.5-1.5B-Instruct --patch experimental-feature-727 --prompt "Explain why the sky is blue."
90
  ```
91
 
 
 
 
 
 
92
  ```python
 
 
93
  from brainpatch import BrainPatchedModel
94
 
 
 
 
 
 
 
 
95
  model = BrainPatchedModel.from_pretrained(
96
  "Qwen/Qwen2.5-1.5B-Instruct",
97
  revision="989aa7980e4cf806f80c7fef2b1adb7bc71aa306",
98
+ backend="transformers",
99
+ device="auto",
100
  )
101
+ patch = model.install("experimental-feature-727") # installed above
102
+ patch.strength = 1.0 # live, clamped to the patch envelope
 
 
 
 
 
 
 
 
 
 
103
  print(model.generate("Solve this problem: what is 17 + 25?"))
104
  ```
105
 
106
+ `patch.strength = 0.0` recovers baseline **byte-identically** verified on an
107
+ L4 with 0 applied hook passes.
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
+ Token-level schedule (Transformers backend only):
110
 
111
  ```python
112
+ patch.schedule = {0: 0.0, 24: 1.0, 48: 2.0}
113
  ```
114
 
115
+ No Modal, no hosted service, and no network once the model and patch are local.
116
 
117
+ ### Verified runtime properties
 
 
 
 
 
 
118
 
119
+ Measured by `modal run modal_app/app.py::test_transformers_backend` on
120
+ Qwen2.5-1.5B-Instruct / NVIDIA L4:
121
 
122
+ | check | result |
123
+ |---|---|
124
+ | weights frozen and unchanged after patched generation | pass |
125
+ | `strength = 0` byte-identical to baseline | pass (0 applied passes) |
126
+ | non-zero strength changes output | pass |
127
+ | measured delta norm vs expected | **28.5177 == 28.5177** |
128
+ | token schedule fires at keyframe | pass |
129
+ | disable / remove restore baseline | pass |
130
+
131
+ Compilation is numerically exact: the 6.4 KB portable artifact reproduces the
132
+ original SAE-based pipeline's delta norm (28.5178) to fp16 rounding.
133
+
134
+ Overhead on L4 (3 runs, 96 tokens): **−1.3%** (within noise), **0.01 MB** VRAM,
135
+ **0.21 s** patch load.
136
 
137
  ---
138
 
patches/research/experimental-feature-727-scheduled.json ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "authors": [],
3
+ "base_model": "Qwen/Qwen2.5-1.5B-Instruct",
4
+ "description": "The same unvalidated feature-727 direction, with a token-indexed schedule, demonstrating dynamic mid-generation steering. The intervention is off for the first 24 generated tokens, switches on at token 24, and doubles at token 48. Measured delta norms during a real generation were 0.0 at tokens 0-23, 28.518 at token 24, and 57.036 at token 48, matching the predicted schedule to within 3.6e-06. This patch demonstrates a RUNTIME CAPABILITY. It makes no behavioural claim whatsoever: see experimental-feature-727.json for the control results, which are negative.",
5
+ "evaluation": {
6
+ "experiment": "dynamic_steering_demo",
7
+ "measured_delta_norm_by_generated_token": {
8
+ "0": 0.0,
9
+ "23": 0.0,
10
+ "24": 28.51780128479004,
11
+ "48": 57.03560256958008
12
+ },
13
+ "max_abs_error_vs_expected_schedule": 3.6103930867170675e-06,
14
+ "matches_expected_schedule": true,
15
+ "conclusion": "Token-indexed strength scheduling works as specified. No behavioural effect is claimed."
16
+ },
17
+ "evidence_level": "none",
18
+ "features": [
19
+ {
20
+ "feature_id": 727,
21
+ "mode": "add",
22
+ "strength": 16.0
23
+ }
24
+ ],
25
+ "format_version": "0.1",
26
+ "license": "Apache-2.0",
27
+ "metadata": {
28
+ "purpose": "runtime capability demonstration",
29
+ "schedule_semantics": "Keys are GENERATED-token indices (the prompt is not counted). Values multiply the feature strength. Step-hold: the value at index n is the value of the largest keyframe <= n."
30
+ },
31
+ "model_revision": "989aa7980e4cf806f80c7fef2b1adb7bc71aa306",
32
+ "name": "experimental-feature-727-scheduled",
33
+ "sae": {
34
+ "d_in": 1536,
35
+ "d_sae": 2048,
36
+ "hook": "residual_post",
37
+ "input_scale": 0.5610531069008018,
38
+ "layer": 18,
39
+ "reference": "smoke_v0",
40
+ "sha256": null
41
+ },
42
+ "schedule": {
43
+ "0": 0.0,
44
+ "24": 1.0,
45
+ "48": 2.0
46
+ }
47
+ }
patches/research/experimental-feature-727.json ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "authors": [],
3
+ "base_model": "Qwen/Qwen2.5-1.5B-Instruct",
4
+ "description": "Single-feature steering direction from the smoke_v0 SAE. This patch is named after its feature ID because nothing about its behaviour has been established. Steering it at strength 16 does change the model's output (mean 3-gram divergence 0.71 from baseline over 6 prompts), but a SCALE-MATCHED RANDOM DIRECTION of identical L2 norm changed the output MORE (0.85). There is no evidence that this direction carries any specific behavioural meaning. NOTE ALSO that feature 727 is a pathological selection: it fires on only 5 of 20,000 tokens with an activation 158x the dictionary median, and belongs to a cluster of 32 near-duplicate features that all fire on the same rare token. Published as a reproducible artifact of the smoke_v0 pipeline, not as a working behavioural patch.",
5
+ "evaluation": {
6
+ "experiment": "smoke_v0_intervention",
7
+ "num_prompts": 6,
8
+ "generation": "greedy, max_new_tokens=96, identical settings across all conditions",
9
+ "delta_norm_all_conditions": 28.51780128479004,
10
+ "divergence_from_baseline": {
11
+ "zero": 0.0,
12
+ "positive": 0.709797049449183,
13
+ "negative": 0.7314236228213818,
14
+ "random_positive": 0.8469011791109867,
15
+ "random_negative": 0.698357839417966,
16
+ "unrelated_positive_feature_1270": 0.6808128064619702
17
+ },
18
+ "effect_vs_controls": {
19
+ "positive_minus_random": -0.13710412966180374,
20
+ "positive_minus_unrelated": 0.028984242987212805,
21
+ "unrelated_control_retracted": "INVALID. Feature 1270 was selected by the same max_activation ranking as the target and is a near-duplicate of it: 3 fires out of 20,000 tokens, max activation 1385.8, same top token ' Bd', same 32-feature outlier cluster. It is not an unrelated feature and this comparison is uninformative. The random-direction control is unaffected and remains valid.",
22
+ "valid_controls": ["zero", "random_positive", "random_negative"]
23
+ },
24
+ "feature_selection_flaw": {
25
+ "target_fire_count": 5,
26
+ "target_firing_rate": 0.00025,
27
+ "target_max_activation": 1429.7736816406250,
28
+ "dictionary_median_fire_count": 271,
29
+ "dictionary_median_max_activation": 9.06184,
30
+ "outlier_cluster_size": 32,
31
+ "outlier_cluster_shared_top_token": " Bd",
32
+ "note": "Ranking by max_activation selected the single most extreme outlier in the dictionary. An undertrained SAE shatters rare high-norm tokens across many near-duplicate features; this ranking finds exactly those. Use min_firing_rate or rank by mean_activation instead."
33
+ },
34
+ "zero_strength_matches_baseline": "6/6 prompts byte-identical",
35
+ "utility_probes": {
36
+ "baseline_accuracy": 0.9,
37
+ "patched_accuracy": 0.8,
38
+ "accuracy_delta": -0.1,
39
+ "n_probes": 10,
40
+ "note": "10 hand-written probes; a 1-item change carries no statistical weight"
41
+ },
42
+ "conclusion": "NEGATIVE. The scale-matched random-direction control diverged MORE than the intervention, so there is no support for a feature-specific causal effect. The infrastructure is verified; the behavioural claim is not. A specific, fixable cause was identified after publication: the max_activation selection rule picked a degenerate outlier feature (see feature_selection_flaw), so this result says more about the selection rule than about SAE features in general.",
43
+ "statistical_caveat": "6 prompts, single greedy generation per condition, no repeated sampling. These differences have no significance testing behind them and should not be read as effect sizes."
44
+ },
45
+ "evidence_level": "none",
46
+ "features": [
47
+ {
48
+ "feature_id": 727,
49
+ "mode": "add",
50
+ "strength": 16.0
51
+ }
52
+ ],
53
+ "format_version": "0.1",
54
+ "license": "Apache-2.0",
55
+ "metadata": {
56
+ "corpus": "Salesforce/wikitext:wikitext-2-raw-v1 train, 20000 activation tokens",
57
+ "sae_training": "2220 steps, train explained variance 0.762, validation 0.658",
58
+ "selection_rule": "highest max_activation among features firing on <50% of tokens",
59
+ "strength_rationale": "Measured dose-response sweep: strength 8-16 changes output without triggering degeneration; 32 loops; 64 collapses. Residual-stream L2 norm at layer 18 is approximately 70 in raw units.",
60
+ "warning": "Feature IDs are meaningless outside the smoke_v0 SAE. This file cannot be applied to another model, another layer, or another SAE."
61
+ },
62
+ "model_revision": "989aa7980e4cf806f80c7fef2b1adb7bc71aa306",
63
+ "name": "experimental-feature-727",
64
+ "sae": {
65
+ "d_in": 1536,
66
+ "d_sae": 2048,
67
+ "hook": "residual_post",
68
+ "input_scale": 0.5610531069008018,
69
+ "layer": 18,
70
+ "reference": "smoke_v0",
71
+ "sha256": null
72
+ },
73
+ "schedule": null
74
+ }
patches/runtime/experimental-feature-727.brainpatch ADDED
Binary file (6.52 kB). View file