What was changed
Only the matrices that write to the residual stream were edited: self_attn.o_proj and every MLP down-projection (dense, shared and all 288 routed experts) in layers 0–44. Each was orthogonalised against a per-layer refusal direction (difference of mean residuals between mlabonne/harmful_behaviors and mlabonne/harmless_alpaca, 400 prompts each, with the harmless direction projected out). All other tensors, including the MTP layer, are byte-identical to the source.
The exact parameter set is in ablation.json.
Measured
Refusals on mlabonne/harmful_behaviors test[:100], counted by an LLM judge (llmfan46/gemma-4-31B-it-uncensored-heretic), system prompt "You are a helpful assistant.":
Table with columns: Source, This model | Source | This model |
|---|
| Reasoning enabled (default chat template), judged on the final answer | 99/100 | 39/100 |
Reasoning skipped (<think></think>), first 64 tokens | 99/100 | 2/100 |
KL divergence on mlabonne/harmless_alpaca test[:100], first token, reasoning skipped | 0 | 0.095 |
The parameters were optimized against the reasoning-skipped setting, and the result carries over only partly to normal use: with reasoning enabled the model still refuses about four requests in ten.
In the reasoning-enabled run, 4 of the 100 responses did not reach a final answer within 3000 tokens and are counted as neither. That run was made on the FP8 quantization of each checkpoint served with vLLM; the other two rows were measured on the BF16 weights with transformers. No capability benchmarks were run on this checkpoint.