juiceb0xc0de commited on
Commit
7fb343c
·
1 Parent(s): 0a7f23e

Document cost-aware atlas workflow

Browse files
Files changed (1) hide show
  1. README.md +159 -61
README.md CHANGED
@@ -183,91 +183,113 @@ python app.py \
183
  ```
184
 
185
 
186
- ### Consolidated full-feature command
187
 
188
- The recommended single pass for a finished atlas uses mean-pooling, stores raw
189
- per-token activations, runs all optional analyses, and writes everything into the
190
- same atlas directory:
 
 
191
 
192
  ```bash
193
  python app.py \
194
  --model <hf-model-id> \
195
  --corpus /home/user/app/prompts/prompts_balanced.jsonl \
196
- --outdir outputs/<model-slug>-census \
197
- --atlas atlas/<model-slug> \
198
  --layers all \
199
  --batch-size 8 \
200
  --max-length 128 \
201
- --components mlp,gate,up,attn,heads,q,k,v \
202
  --pooling mean \
203
- --store-per-token \
204
- --per-token-analysis \
205
- --logit-lens \
206
- --sub-zero \
207
- --sub-zero-corpora /home/user/app/prompts \
208
  --positive /home/user/app/prompts/authentic.jsonl \
209
  --negative /home/user/app/prompts/corporate.jsonl \
210
  --timing-every 25
211
  ```
212
 
213
- This produces:
214
 
215
- - `outputs/<model-slug>-census/l*_census_raw.npz` - last-token, mean-token and
216
- optional ragged per-token activation arrays for every requested component.
217
- - `outputs/<model-slug>-census/analysis/` - feature separation scores, feature
218
- fingerprints and per-token attribution summaries.
219
- - `outputs/<model-slug>-census/logit_lens_scores.json` - top-k unembedding
220
- projections for `mlp`, `gate`, `up` and `attn` features.
221
- - `outputs/<model-slug>-census/subzero_report.json` - Sub-Zero DAS rotational
222
- fingerprints for the requested corpora.
223
- - `atlas/<model-slug>/` - the merged SQLite atlas with all of the above indexed.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
 
225
  ### Combine outputs into the atlas
226
 
227
- The `app.py --sub-zero` command above already combines everything. Use these
228
- manual merge commands only if you ran pieces separately or need to rebuild the
229
- atlas from existing outputs.
230
 
231
  ```bash
232
  python -m qwip_atlas.build_atlas \
233
- --atlas atlas/<model-slug> \
234
  init \
235
  --model-id <hf-model-id> \
236
- --census outputs/<model-slug>-census/l0_census_raw.npz
237
 
238
  python -m qwip_atlas.build_atlas \
239
- --atlas atlas/<model-slug> \
240
  merge-all-layers \
241
- --census-dir outputs/<model-slug>-census \
242
- --analysis-dir outputs/<model-slug>-census/analysis \
243
  --no-census-copy
244
 
245
  python -m qwip_atlas.build_atlas \
246
- --atlas atlas/<model-slug> \
 
 
 
 
 
 
 
247
  merge-ov \
248
- --report outputs/<model-slug>-census/ov_circuit_scores.json
249
 
250
  python -m qwip_atlas.build_atlas \
251
- --atlas atlas/<model-slug> \
252
  merge-compliance-behaviour \
253
- --report outputs/<model-slug>-census/compliance_behaviour_scores.json
254
 
255
  python -m qwip_atlas.build_atlas \
256
- --atlas atlas/<model-slug> \
257
  merge-subzero \
258
- --report outputs/<model-slug>-census/subzero_report.json
259
 
260
  python -m qwip_atlas.build_atlas \
261
- --atlas atlas/<model-slug> \
262
  merge-logit-lens \
263
- --report outputs/<model-slug>-census/logit_lens_scores.json
264
 
265
  python -m qwip_atlas.build_atlas \
266
- --atlas atlas/<model-slug> \
267
  index
268
 
269
  python -m qwip_atlas.build_atlas \
270
- --atlas atlas/<model-slug> \
271
  status
272
  ```
273
 
@@ -349,6 +371,49 @@ python app.py \
349
  --skip-existing-analysis
350
  ```
351
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
352
  ## Memory knobs
353
 
354
  Defaults are safe for ~8 GB:
@@ -402,32 +467,52 @@ This writes `analysis/per_token/l<N>_<component>_per_token.json` with, per top f
402
 
403
  ### Logit-lens projection
404
 
405
- Project top feature directions onto the model's unembedding matrix to see which tokens each feature promotes or suppresses. This loads the full model weights, so it is off by default:
 
 
406
 
407
- ```bash
408
- python app.py \
409
- --model <hf-model-id> \
410
- --corpus /home/user/app/prompts/prompts_balanced.jsonl \
411
- --outdir outputs/<model>-census \
412
- --atlas atlas/<model> \
413
- --logit-lens \
414
- --components mlp,gate,up
415
- ```
 
 
 
 
416
 
417
- The output is merged into the atlas as `logit_lens`. You can also run it manually:
418
 
419
  ```bash
420
- python analyze_logit_lens.py \
421
  --model <hf-model-id> \
422
- --atlas atlas/<model> \
423
- --output outputs/<model>-census/logit_lens_scores.json \
424
  --top-k 64 \
425
- --components mlp,gate,up
 
 
426
 
 
 
 
 
 
 
 
 
427
  python -m qwip_atlas.build_atlas \
428
- --atlas atlas/<model> \
429
  merge-logit-lens \
430
- --report outputs/<model>-census/logit_lens_scores.json
 
 
 
 
431
  ```
432
 
433
  ### Advanced census options
@@ -490,11 +575,12 @@ Use `/home/user/app/prompts/prompts_balanced.jsonl` in the `--corpus` examples b
490
 
491
  The prompt axis was renamed from `pos.jsonl` / `neg.jsonl` to `authentic.jsonl` / `corporate.jsonl` to make the semantic role obvious. The defaults in `app.py` and `make_compliance_corpora.py` have been updated to match. If you keep your own curated corpora, just point `--positive` and `--negative` at them.
492
 
493
- ### Sub-Zero corpora path (legacy)
494
 
495
- Sub-Zero is the older DAS rotational probe. It is still wired in, but the
496
- recommended resolution features are now mean-pooling, per-token attribution and
497
- logit-lens projection.
 
498
 
499
  When you do run it, keep the Sub-Zero corpora in the same prompts directory used
500
  for the rest of the pipeline. In the Space that directory is
@@ -509,6 +595,18 @@ python app.py \
509
  --sub-zero-corpora /home/user/app/prompts
510
  ```
511
 
 
 
 
 
 
 
 
 
 
 
 
 
512
  ### OV-circuit compliance score placeholder
513
 
514
  `analyze_ov_circuits.py` currently writes `compliance_score` and `layer_comp_strength` as `None` for every head. The merge path is wired, but the analyzer does not yet consume a compliance-behaviour report to fill those columns. Until that patch lands, treat those two fields as placeholders.
 
183
  ```
184
 
185
 
186
+ ### Cost-aware full atlas workflow
187
 
188
+ For large GPU runs, do **not** start with every optional feature turned on. The
189
+ proven workflow is to build two component halves, then combine them at the atlas
190
+ layer. This keeps failures recoverable and avoids redoing expensive census work.
191
+
192
+ Run MLP-side components first:
193
 
194
  ```bash
195
  python app.py \
196
  --model <hf-model-id> \
197
  --corpus /home/user/app/prompts/prompts_balanced.jsonl \
198
+ --outdir outputs/<model-slug>-mlp \
199
+ --atlas atlas/<model-slug>-mlp \
200
  --layers all \
201
  --batch-size 8 \
202
  --max-length 128 \
203
+ --components mlp,gate,up \
204
  --pooling mean \
 
 
 
 
 
205
  --positive /home/user/app/prompts/authentic.jsonl \
206
  --negative /home/user/app/prompts/corporate.jsonl \
207
  --timing-every 25
208
  ```
209
 
210
+ Then run the attention-side components:
211
 
212
+ ```bash
213
+ python app.py \
214
+ --model <hf-model-id> \
215
+ --corpus /home/user/app/prompts/prompts_balanced.jsonl \
216
+ --outdir outputs/<model-slug>-attn \
217
+ --atlas atlas/<model-slug>-attn \
218
+ --layers all \
219
+ --batch-size 8 \
220
+ --max-length 128 \
221
+ --components attn,heads,q,k,v \
222
+ --pooling mean \
223
+ --positive /home/user/app/prompts/authentic.jsonl \
224
+ --negative /home/user/app/prompts/corporate.jsonl \
225
+ --timing-every 10
226
+ ```
227
+
228
+ Expected full feature count for Llama-3.1-8B-class dimensions is:
229
+
230
+ ```text
231
+ mlp/gate/up: 32 * (14336 + 14336 + 14336) = 1,376,256
232
+ attn side: 32 * (4096 + 4096 + 4096 + 1024 + 1024) = 458,752
233
+ total: 1,835,008
234
+ ```
235
+
236
+ If a run is interrupted, rerun with `--skip-census` and/or
237
+ `--skip-existing-analysis` only after confirming the expected `.npz` files and
238
+ analysis outputs exist.
239
 
240
  ### Combine outputs into the atlas
241
 
242
+ Use these commands to build a final combined atlas from existing MLP and
243
+ attention halves. This is the preferred merge path; do not raw-merge large
244
+ `.npz` files.
245
 
246
  ```bash
247
  python -m qwip_atlas.build_atlas \
248
+ --atlas atlas/<model-slug>-combined \
249
  init \
250
  --model-id <hf-model-id> \
251
+ --census outputs/<model-slug>-mlp/l0_census_raw.npz
252
 
253
  python -m qwip_atlas.build_atlas \
254
+ --atlas atlas/<model-slug>-combined \
255
  merge-all-layers \
256
+ --census-dir outputs/<model-slug>-mlp \
257
+ --analysis-dir outputs/<model-slug>-mlp/analysis \
258
  --no-census-copy
259
 
260
  python -m qwip_atlas.build_atlas \
261
+ --atlas atlas/<model-slug>-combined \
262
+ merge-all-layers \
263
+ --census-dir outputs/<model-slug>-attn \
264
+ --analysis-dir outputs/<model-slug>-attn/analysis \
265
+ --no-census-copy
266
+
267
+ python -m qwip_atlas.build_atlas \
268
+ --atlas atlas/<model-slug>-combined \
269
  merge-ov \
270
+ --report outputs/<model-slug>-attn/ov_circuit_scores.json
271
 
272
  python -m qwip_atlas.build_atlas \
273
+ --atlas atlas/<model-slug>-combined \
274
  merge-compliance-behaviour \
275
+ --report outputs/<model-slug>-attn/compliance_behaviour_scores.json
276
 
277
  python -m qwip_atlas.build_atlas \
278
+ --atlas atlas/<model-slug>-combined \
279
  merge-subzero \
280
+ --report outputs/<model-slug>-attn/subzero_report.json
281
 
282
  python -m qwip_atlas.build_atlas \
283
+ --atlas atlas/<model-slug>-combined \
284
  merge-logit-lens \
285
+ --report outputs/<model-slug>-combined-logit_lens_scores.json
286
 
287
  python -m qwip_atlas.build_atlas \
288
+ --atlas atlas/<model-slug>-combined \
289
  index
290
 
291
  python -m qwip_atlas.build_atlas \
292
+ --atlas atlas/<model-slug>-combined \
293
  status
294
  ```
295
 
 
371
  --skip-existing-analysis
372
  ```
373
 
374
+ ## Validated Llama-3.1-8B-Instruct run
375
+
376
+ The RunPod GPU workflow for `meta-llama/Llama-3.1-8B-Instruct` was validated
377
+ with separate output roots:
378
+
379
+ - `outputs/llama8b-mlp` -> `mlp,gate,up`
380
+ - `outputs/llama8b-attn` -> `attn,heads,q,k,v`
381
+ - `atlas/llama8b-combined` -> final combined atlas
382
+
383
+ Expected SQLite sanity checks after `index`:
384
+
385
+ ```text
386
+ features:
387
+ attn 131072
388
+ heads 131072
389
+ q 131072
390
+ k 32768
391
+ v 32768
392
+ mlp 458752
393
+ gate 458752
394
+ up 458752
395
+
396
+ per_head: 2560
397
+ ov_circuits: 1024
398
+ compliance_behaviour_features: 458752
399
+ compliance_behaviour_per_head: 2560
400
+ subzero_layer: 32
401
+ subzero_svs: populated for down_proj/gate_proj/up_proj
402
+ ```
403
+
404
+ The attention census `.npz` files must include all of:
405
+
406
+ ```text
407
+ attn_last, attn_mean,
408
+ attn_heads_last, attn_heads_mean,
409
+ q_heads_last, q_heads_mean,
410
+ k_heads_last, k_heads_mean,
411
+ v_heads_last, v_heads_mean
412
+ ```
413
+
414
+ If `heads/q/k/v` are missing, pull a version including the fixed fast-path
415
+ census writer before rerunning the attention half.
416
+
417
  ## Memory knobs
418
 
419
  Defaults are safe for ~8 GB:
 
467
 
468
  ### Logit-lens projection
469
 
470
+ Project top feature directions onto the model's unembedding matrix to see which
471
+ tokens each feature promotes or suppresses. This loads the full model weights
472
+ and can be CPU-heavy, so it is off by default.
473
 
474
+ Current support:
475
+
476
+ - `attn`: direct d_model basis projection.
477
+ - `mlp`, `gate`, `up`: projected through the layer `down_proj`.
478
+ - `heads`: projected through the layer `o_proj`.
479
+ - `q`, `k`, `v`: intentionally skipped. These do not have a context-free
480
+ unembedding direction because they affect attention dynamically.
481
+
482
+ The default `--top-k 64` is per layer per component. For a combined atlas with
483
+ `mlp,gate,up,attn,heads`, that is at most `32 * 5 * 64 = 10240` feature
484
+ projections. Do not run every feature by default on a paid pod; full coverage
485
+ for supported components can exceed one million rows and produces a large JSON
486
+ with promoted/suppressed token payloads.
487
 
488
+ Recommended manual run for a final combined atlas:
489
 
490
  ```bash
491
+ nohup python analyze_logit_lens.py \
492
  --model <hf-model-id> \
493
+ --atlas atlas/<model-slug>-combined \
494
+ --output outputs/<model-slug>-combined-logit_lens_scores.json \
495
  --top-k 64 \
496
+ --tokens-per-feature 8 \
497
+ --components mlp,gate,up,attn,heads \
498
+ > outputs/<model-slug>-combined-logit_lens.nohup.log 2>&1 &
499
 
500
+ tail -f outputs/<model-slug>-combined-logit_lens.nohup.log
501
+ ```
502
+
503
+ `analyze_logit_lens.py` writes the JSON only at the end. If SSH disconnects or
504
+ you interrupt it before completion, there may be no new output file to merge.
505
+ After it completes, merge and re-index:
506
+
507
+ ```bash
508
  python -m qwip_atlas.build_atlas \
509
+ --atlas atlas/<model-slug>-combined \
510
  merge-logit-lens \
511
+ --report outputs/<model-slug>-combined-logit_lens_scores.json
512
+
513
+ python -m qwip_atlas.build_atlas \
514
+ --atlas atlas/<model-slug>-combined \
515
+ index
516
  ```
517
 
518
  ### Advanced census options
 
575
 
576
  The prompt axis was renamed from `pos.jsonl` / `neg.jsonl` to `authentic.jsonl` / `corporate.jsonl` to make the semantic role obvious. The defaults in `app.py` and `make_compliance_corpora.py` have been updated to match. If you keep your own curated corpora, just point `--positive` and `--negative` at them.
577
 
578
+ ### Sub-Zero corpora path and scope
579
 
580
+ Sub-Zero is the DAS rotational probe. In the current default configuration it
581
+ probes MLP-side projection weights (`gate_proj`, `up_proj`, `down_proj`) across
582
+ the selected layers. It does not mean every atlas component has its own
583
+ Sub-Zero projection entry.
584
 
585
  When you do run it, keep the Sub-Zero corpora in the same prompts directory used
586
  for the rest of the pipeline. In the Space that directory is
 
595
  --sub-zero-corpora /home/user/app/prompts
596
  ```
597
 
598
+ If your prompt files are named `neutral_stems.jsonl` and `red_team_stems.jsonl`,
599
+ create symlinks before running Sub-Zero:
600
+
601
+ ```bash
602
+ ln -sf neutral_stems.jsonl /home/user/app/prompts/neutral.jsonl
603
+ ln -sf red_team_stems.jsonl /home/user/app/prompts/red_team.jsonl
604
+ ```
605
+
606
+ The SVD stage is checkpointed under `outputs/<model>/sub_zero_ckpt`. A SIGKILL
607
+ during SVD usually means the pod was memory-killed; rerun after pulling the
608
+ latest code so unused left-singular vectors are not retained in the checkpoint.
609
+
610
  ### OV-circuit compliance score placeholder
611
 
612
  `analyze_ov_circuits.py` currently writes `compliance_score` and `layer_comp_strength` as `None` for every head. The merge path is wired, but the analyzer does not yet consume a compliance-behaviour report to fill those columns. Until that patch lands, treat those two fields as placeholders.