The Stream, Its Writers, and the Assumption in Appendix E
Refusal in Language Models Is Mediated by a Single Direction (Arditi et al., 2024) gives the field two ways to erase the refusal direction. The first is directional ablation at inference (§2.4, §3.1): during the forward pass, zero out the component along $\hat{r}$ from every residual-stream activation,
$$x \leftarrow x - (x \cdot \hat{r}) \hat{r}$$
The second is weight orthogonalization (§4): rewrite every matrix that writes into the stream so the model can never produce that component in the first place. Appendix E proves the two equivalent. The proof opens with an assumption most summaries skip:
Supposing that directional ablation was similarly applied after all previous contributions to the residual stream, we have that $\hat{r}^{\intercal} x_{\text{pre}} = 0$.
Everything the stream already carries must arrive clean. That one line decides what you have to edit, and it is where the two forms of “abliteration” in circulation today quietly diverge.
What the assumption costs#
A transformer’s residual stream is a running sum: embeddings at the start, then every layer adds its attention and MLP contributions,
$$x_{\text{post}} = x_{\text{pre}} + \sum_i W_i a_i$$
The matrices $W_i$ — o_proj, down_proj, their hybrid-arch cousins —
are the writers. The accumulated $x$ is the stream. No single weight
matrix sits behind the stream; the writers each have a concrete,
editable $W$.
Two vocabularies collide in that sentence, and both are worth pinning
down. First, the names: full self-attention calls its output matrix
o_proj, linear attention calls the same role out_proj, and the MLP
calls its own down_proj — one concept, three dialects, and hybrid
models speak two of them at once (Qwen3.8-27B has 16 full-attention
layers with self_attn.o_proj and 47 linear-attention layers with
linear_attn.out_proj). Second, “projection” itself: the output
projections are learned matrices that map between spaces, while the
steering operation $h \leftarrow h - \alpha(h\cdot\hat{d})\hat{d}$ is
the geometric act of measuring and removing a component along
$\hat{d}$, computed per token from the live activation. The writers are
the matrices. The steering is the operation. Baking folds the second
into the first.
For Appendix E’s assumption to hold, $\hat{r}^{\intercal} x_{\text{pre}}$ must vanish before each writer fires. Arditi et al. buy that by orthogonalizing the embedding matrix, the positional embedding, the attention outs, the MLP outs, and the output biases. The embedding term does the heavy lifting: strip the $\hat{r}$-component at embed time, from every token, and the stream enters layer 1 already clean. Skip it, and the stream arrives at each layer carrying a component no writer edit can reach — the equivalence breaks exactly there.
The price of their completeness: the embedding edit touches every token, including tokens that would never trip a refusal. The component is gone at embed time, permanently, for benign and harmful text alike.
What a bake edits instead#
Our captain-vector bake takes the same math to a different stopping
point. At a writer $h = Wx$, the projection is a weight edit
$\Delta W = -\alpha \hat{d}(\hat{d}^{\intercal} W)$, which is exactly a
rank-1 LoRA with lora_B = d̂, lora_A = −α·d̂ᵀW. Bake emits that
adapter for the per-layer writers and leaves the embeddings alone.
Linearity does the rest:
$$\sum_i \big(W_i x_i - \alpha(\hat{d}\cdot W_i x_i)\hat{d}\big) = \Big(\sum_i W_i x_i\Big) - \alpha\Big(\hat{d}\cdot\sum_i W_i x_i\Big)\hat{d}$$
Projecting every writer of a layer at α equals projecting that layer’s new contributions at α. The component the stream carried in — from the embeddings, or from any writer outside the edit set — passes through, where the runtime hook removes it regardless of origin. The baked form and the runtime form coincide when the writers re-inject the direction every layer, which is the regime these models live in: on the Qwen3.8 hybrid, steering the MLP writer moves delivery 71.9 points while the attention writer moves 6.2. The direction is written, layer after layer, mostly by the FFN. Close, measurable, and not bit-identical — which is why bake ships as a troubleshooting and interop form (validate that a direction lands, probe a merge for survival) while the hotfixes steer the stream at runtime.
The paper’s own blog post describes the inference-time version per-writer (“every time a component writes its output to the residual stream, we can erase its contribution”). Appendix E is the reconciliation: writer-level erasure, applied after every contribution including the embedding, coincides with stream-level ablation and with weight orthogonalization that includes the embedding. One operation, three surfaces, provided the embeddings are in the edit set.
Counting the writers#
A dense layer has two writers: attention’s o_proj and the MLP’s
down_proj. An MoE layer swaps the single MLP for a router plus N
experts, and each expert carries its own output projection — DeepSeek
V4 runs 256 routed experts per MoE layer, so one layer there has
roughly 258 writers and the model has thousands.
The math survives the headcount. $\Delta W_e = -\alpha\hat{d}(\hat{d}^{\intercal} W_e)$ is exact for every expert, and linearity covers the router itself: only the top-k experts fire per token, but a router-weighted sum of cleaned outputs is already clean. What breaks is everything around the math — thousands of rank-1 adapters computed against per-expert quantized weights, no serving machinery that attaches LoRA to routed expert matrices inside a fused MoE kernel, and a fail-closed verification burden multiplied by the same thousands. The runtime hook’s cost scales with none of it: it sits after the router-weighted sum, where the hundreds of writers have already collapsed into one tensor, and projects once. That asymmetry — bake’s cost grows with the writer count, the hook’s does not — is the concrete content of “architecture-blind.”
The three forms, side by side#
| runtime projection (GLP native) | weight orthogonalization (Arditi et al.) | baked LoRA (bake) | |
|---|---|---|---|
| edits | the accumulated stream, live | every writer and the embeddings | per-layer writers only |
| stream’s incoming component | removed, any origin | never forms (embeddings cleaned) | passes through |
| α | tunable at serve time | frozen into the weights | frozen into lora_A |
| MoE | architecture-blind | per-expert explosion | per-expert explosion |
| checkpoint binding | none (width check only) | bakes W implicitly | lora_A carries W; pinned revision enforced |
| failure mode on drift | hook refuses (spec gates) | silent | silent — bake fails closed upstream instead |
One more row’s worth of asymmetry: the runtime hook and the spec’s
reader-conformance gates fail loud, while any weight-space form fails
silent, so the weight-space forms carry their verification with them —
the pinned-revision check in bake, the per-writer roundtrip in
bake-report.json.
The table’s three rows are all projection. The paper itself ran the addition column, in Appendix I.1: adding $-\hat{r}$ at a single layer bypasses refusal about as well as directional ablation (their Figure 23 against Figure 1), and pays for it in increased CE loss over harmless data (Table 9). Their Figure 22 shows the mechanism — a constant negative shift moves harmful activations toward the harmless cluster and pushes the harmless cluster off-distribution, where ablation moves the harmful points and leaves the harmless ones where they are. Addition is input-independent; the same shove lands on tokens that carry none of the component. That asymmetry, measured by the original authors a year before the llama.cpp control-vector ecosystem standardized on addition, is the one our own add-vs-project measurements keep reproducing.
Where “a single direction” meets our measurements#
The claim the paper is named for has now survived two years of everyone else’s experiments, most of ours included, with caveats that keep growing. Our current scoreboard:
- Transfer at cos −0.32 (DSV4). A third-party direction recovered from an abliterated DeepSeek V4 checkpoint delivers 31/32 on refusal32 despite sitting at cosine −0.32 to our derived direction — closer to orthogonal than aligned. Two directions sharing that little orientation should not both erase the same behavior under a strict rank-1 theory. They do. Refusal reads as a low-rank subspace whose dominant component does most of the work, which is why rank-1 per-layer vectors carry the engineering while the GLP format reserves rank-k.
- The site matters more than the slogan. If one direction lived in
“the stream” as a flat object, the hook point would be bookkeeping.
The 71.9-vs-6.2 writer asymmetry above says otherwise, and on DSV4
the calibrated site is the pre-fold FFN write
(
ffn_out_pre_residual), a label we carried wrong for months before a shape probe corrected it. - Dose is model-specific, sometimes non-monotonic. Inkling garbles at α=1.0 and ships at 0.25; Hy4’s collateral damage is worst at α=1.0–1.5 and zero at 2.0; GLM-5.3-Flash falls off a cliff at 2.5; the 743B flagship refuses more above α=1. Four dose curves, four entanglement structures, one axis label.
- Removing the gate reveals the doorman. After the dominant direction goes, residual behaviors remain — hedging, disclaimers, premise-rejection near the decision boundary — and that residue has its own derivable direction (the GLP-63 work, covered in the membership-vs-mass post). One behavior, at least two orthogonal axes.
- Looped models re-decide per pass. Same-layer directions across Nanbeige4.2’s two loop passes agree at only cos 0.25–0.6, so the vector ships 44 directions, one per execution step (the looped-model post). “The direction” is per execution context, not per weight tensor.
The follow-up literature landed in the same place from different directions. Zhao et al. show harmfulness and refusal are encoded separately, at different token positions (arXiv 2507.11878) — two concepts the single “refusal direction” label conflates. Piras et al. model refusal as a manifold of closely related directions and suppress it better with several directions than with any single one (arXiv 2511.08379). The numeral in the original title keeps shrinking under replication; the linear accessibility underneath it keeps holding.
None of this dents the paper’s real contribution, which runs deeper than the numeral: refusal is linearly accessible — causal in both directions, derivable from 64 prompts, erasable by a rank-1 edit. That is the load-bearing finding, and every artifact we ship stands on it. Our operating estimate, after all the lanes above: a rank-1 treatment of the dominant direction carries roughly ninety percent of the behavior, and the residual ten percent is where the interesting things live — the hedging axis, the transfer anomalies, the dose curves. The “single” in the title names the dominant eigenvector of something bigger, and the paper says as much in its own limitations section.
Pointers for the reader#
The inference-time form: paper §2.4 (definition, Equation 4) and §3.1 (results, Figure 1); blog post sections “Ablating the ‘refusal direction’ to bypass refusal” and “Feature ablation via weight orthogonalization”. The equivalence: paper §4 and Appendix E. Activation addition compared honestly (approximately as effective at bypassing refusal, measurably worse on harmless-data loss): Appendix I.1. The code: andyrdt/refusal_direction. Our forms: the GLP spec, captain-vector for derive/inspect/bake, and the llama.cpp compatibility notes for what happens when a projective vector meets an additive runtime.