Residual Streams — HarmBench 200 × AlpacaEval 200
Per-layer, per-token residual stream activations captured during inference on
200 harmful (HarmBench) + 200 harmless (AlpacaEval) prompts, across 9 models
at two scales (3B, 7B).
Structure
last_token_residuals/ # Compact: last-token position only
{scale}_{code}.npz # e.g. 3b_d1.npz
harmful_last_token (200, n_layers, hidden_dim) float16
harmless_last_token (200, n_layers, hidden_dim) float16
harmful_refused (200,) bool
harmless_refused (200,) bool
per_prompt/{scale}/{code}/ # Full: all tokens × all layers
harmful/000.npz ... 199.npz
harmless/000.npz ... 199.npz
generations/harmful_000.txt ... harmless_199.txt
behavior.json # scrubbed (model field = codename)
meta.json # scrubbed
Each per-prompt NPZ contains:
residuals:(seq_len, n_layers, hidden_dim)float32token_ids:(seq_len+1,)int32prompt_len: int — boundary between reading and generationn_generated: int
Model codenames
| Code | Role | Scale |
|---|---|---|
| d1 | Base (pretrained) | 3B, 7B |
| d2 | Instruct-aligned | 3B, 7B |
| d3 | Code-specialised | 3B, 7B |
| d4 | RLVR target (coder backbone) | 3B, 7B |
| d5 | RLVR target (base backbone) | 7B only |
Hidden dimensions: 3B = 2048, 7B = 3584.
Load example
import numpy as np
# Compact — for probes / det-AUROC
d = np.load("last_token_residuals/3b_d2.npz", allow_pickle=True)
harmful = d["harmful_last_token"] # (200, 36, 2048)
refused = d["harmful_refused"] # (200,) bool
# Full per-prompt — for trajectory analysis
d = np.load("per_prompt/3b/d4/harmful/000.npz")
res = d["residuals"] # (seq, 36, 2048) float32
plen = int(d["prompt_len"]) # res[:plen] = reading phase
Citation
Part of the "Selective Catastrophic Forgetting" study (ACL 2027 submission).