It does not measurably damage a model
Inside the model, the decision to refuse shows up as a recognisable pattern. You locate it by comparing how the model handles questions it answers against ones it turns down, then you turn that pattern down. The obvious worry is that you are reaching into a trained network and might break something else on the way past.
So we measured. Every model was benchmarked before and after on grade-school maths (GSM8K, 200 questions), instruction-following (IFEval prompt-level strict, 200) and code (HumanEval pass@1, 164). Identical harness, identical quantization, greedy decoding throughout.
| Model | 4-bit | Refusals | Maths /200 | Instructions /200 | Code /164 | |||
|---|---|---|---|---|---|---|---|---|
| gemma-4-31B-it | 17.9 GB | 51→1 | 190 → 191 | +1 | 180 → 179 | -1 | 148 → 148 | ±0 |
| Qwen3.6-27B | 17.7 GB | 135→0 | 181 → 181 | ±0 | 167 → 168 | +1 | 156 → 157 | +1 |
| Qwen3.8-27B | 17.7 GB | 144→0 | 179 → 182 | +3 | 164 → 166 | +2 | 157 → 157 | ±0 |
| granite-4.1-30b | 15.3 GB | 37→0 | 178 → 175 | -3 | 165 → 163 | -2 | 142 → 145 | +3 |
| Qwen3.5-27B | 17.7 GB | 132→1 | 176 → 177 | +1 | 168 → 171 | +3 | 156 → 158 | +2 |
| gemma-4-12B-it | 7.5 GB | 63→11 | 172 → 170 | -2 | 163 → 160 | -3 | 69 → 64 | -5 |
| Nemotron-3-Nano-4B | 3.1 GB | 168→4 | 166 → 168 | +2 | 161 → 158 | -3 | 115 → 119 | +4 |
| Qwen3.5-9B | 7.7 GB | 165→2 | 164 → 165 | +1 | 162 → 154 | -8 | 139 → 139 | ±0 |
| Phi-4-mini-instruct | 2.8 GB | 78→2 | 159 → 149 | -10 | 127 → 123 | -4 | 123 → 120 | -3 |
| Qwen3.5-4B | 3.2 GB | 127→0 | 157 → 156 | -1 | 155 → 150 | -5 | 128 → 132 | +4 |
| Olmo-3-7B-Instruct | 4.8 GB | 72→2 | 156 → 154 | -2 | 161 → 158 | -3 | 139 → 135 | -4 |
| gemma-4-E4B-it | 5.0 GB | 96→0 | 140 → 144 | +4 | 160 → 163 | +3 | 139 → 141 | +2 |
| Olmo-3-7B-Think | 4.8 GB | 59→0 | 121 → 121 | ±0 | 85 → 81 | -4 | 112 → 111 | -1 |
| Qwen3.5-2B | 1.9 GB | 54→2 | 100 → 97 | -3 | 121 → 126 | +5 | 78 → 81 | +3 |
| gemma-4-E2B-it | 3.2 GB | 106→7 | 93 → 98 | +5 | 144 → 140 | -4 | 129 → 129 | ±0 |
| Llama-Nemotron-Nano-4B | 3.4 GB | 23→1 | 76 → 75 | -1 | 128 → 128 | ±0 | 112 → 103 | -9 |
| Qwen3.5-0.8B | 0.8 GB | 69→3 | 31 → 32 | +1 | 97 → 99 | +2 | 32 → 33 | +1 |
Across 51 before-and-after pairs the changes average out to roughly nothing, and they go up about as often as down. Several models score better after modification — which is the giveaway, because turning off refusals cannot teach anything to add up. When the errors run both ways like that, you are watching random variation, not damage.
The noise floor, stated plainly
Ask a model the same 200 questions twice and you will not get the same score twice. You will get something about 8 questions different, purely by chance. So a gap of three questions is not a small effect — it is not an effect at all.
That figure is not our estimate; the benchmark software reports its own margin of error and we doubled it, because we are comparing two separate runs rather than one run against a known truth. We state it up front because much published work does not, and a great many “small but real” declines sit comfortably inside a margin nobody mentioned.
49 of 51 comparisons land inside that band. The 2 that do not: Phi-4-mini-instruct maths 159→149; Llama-Nemotron-Nano-4B code 112→103.
An earlier version of this work claimed the process cost 1.5–4 points of instruction-following, based on ten measurements that all pointed the same way. More data killed it — later pairs went the other direction, and one modified model scored +2.0 points on maths, which the process cannot cause. Ten same-signed results inside the noise band is a pattern you can talk yourself into. We did.
KL divergence does not predict capability loss
The tool tries to do two things at once: remove as many refusals as possible, while changing the model as little as possible. It measures that second part with a number called KL divergence — roughly, how differently the modified model behaves compared with the original. Everyone treats it as the damage dial: lower is safer, and it is the figure people report.
So we tested whether it earns that role, by saving the same model at several different strengths and measuring each one.
Qwen3.5-27B · HumanEval /164
gemma-4-31B · maths / instructions / code
KL measures how far the output distribution moved on the prompts used to fit the ablation. That is a useful control while searching, and a reasonable way to rank variants of one model. It is not a general-purpose damage meter, and it should not be reported as one.
Most of the time, the harness is the story
Nearly every dramatic result during this project turned out to be a measurement bug. Each was cheap to detect and expensive to discover late.
auto_map → import error50 trials, died at exportconfig parseThe thinking-model trap, three times over
The same fault appeared in three different tools wearing three different costumes. Reasoning models emit a long deliberation before their answer. If your scoring window ends inside that deliberation, you score the reasoning.
- In the modification tool, a chat template opened a
<think>block in the prompt, so 400 trials optimised against chain-of-thought. Fixed by closing the block with a response prefix. - In one benchmark path, the model spent its entire 256-token budget reasoning,
leaving
contentempty whilereasoning_contentfilled. It scored 0.0% and looked like catastrophic damage. - In a third, a 32B reasoning model ignored the closed tag entirely and reasoned for a median of 1,031 tokens regardless. Its 50-trial study returned exactly zero refusals in 43 of 50 trials — no signal at all.
Any time a thinking model scores near zero, suspect the reasoning block before suspecting the model. Confirm by checking whether the answer field is empty while the reasoning field is populated.
Cross-harness comparison is invalid
The sharpest example. The same model, same weights, measured two ways:
Qwen3.5-0.8B, GSM8K strict transformers + bitsandbytes nf4 .... 17.0% (strict 17.0 / flexible 34.0) llama-server + GGUF Q4_K_M ......... 37.5% (strict 37.5 / flexible 42.0)
A twenty-point gap from the harness alone — far larger than any quantization effect we were trying to detect. The tell is in the strict-versus-flexible spread: one harness produced answers the strict parser could read, the other did not. Had we compared transformers numbers against GGUF numbers, we would have concluded that 4-bit quantization doubles mathematical ability.
A probe that answers in seconds what took a weekend
Every failure above was knowable before committing GPU hours. That asymmetry is the entire argument for checking first. The probe reads a checkpoint and answers one question: can this model be modified, and what will go wrong if you try? It loads no weights. On 23 checkpoints it runs in 48 seconds and reproduces every verdict derived by hand — including four models that are structurally impossible, and one hazard that had been missed.
$ python -m probe models/*/ Qwen3.5-2B verdict: REACHABLE 30 abliterable modules (o_proj 6, down_proj 24) reasoning block present but CLOSED — no response_prefix Qwen3.5-35B-A3B verdict: UNREACHABLE 80 fused expert tensors — e.g. mlp.experts.gate_up_proj (256, 1024, 2048) bitsandbytes cannot quantize them; PEFT cannot attach a LoRA Olmo-3-32B-Think verdict: NEEDS_FIX sampling params set with do_sample=False — export will fail after the study OPEN reasoning block — response_prefix required
That last one is the case for the whole approach: it was found on a model already scheduled to run that night, and the fault would have surfaced eight hours later, at export, after the study had completed.
What could not be done, and why
Four models are structurally unreachable
Mixture-of-experts checkpoints storing their experts as a single fused parameter rather than individual linear layers. Quantization libraries cannot process them and adapter libraries cannot attach to them, so there is nothing for the modification to act on. No fix exists at the checkpoint level; they run perfectly well under other serving stacks.
One model is reachable but unmeasurable
A 32B reasoning model that ignores every mechanism for disabling its reasoning — no template argument, no system prompt, no closed tag. It deliberates for a median of 1,031 tokens before answering, so a 100-token scoring window sees only deliberation. Its study returned zero refusals in 43 of 50 trials: no signal for the optimiser, and an export that cannot be validated.
What has not been tested
- MATH. GSM8K saturates at the top end — everything 27B and above scores 176–191 out of 200, which discriminates poorly exactly where it matters.
- Multilingual and long-context. Vocabulary size hints at breadth, but a hint is not a measurement.
- Quantization to GGUF. In progress. The only prior evidence was collected with sampling enabled rather than greedy decoding, which makes it unusable.
- 2 of the 19 models are modified but not yet benchmarked on the same footing, so they contribute no comparison here.
How to reproduce this
The recipe that works
- Close any open reasoning block. If the generation prompt ends mid-thought, you are scoring deliberation. Render the template and inspect its tail — this differs within a model family, not just between families.
- Strip topic words from the refusal markers. Words like illegal and harmful appear in compliant answers too. The optimiser minimises marker hits, so including them rewards euphemism over compliance and forces far heavier modification. Removing them was worth 4× to 13× less KL for the same result.
- Use a broad harmful-prompt set. A narrow one produces a refusal direction that only covers the phrasings it saw.
The measurement discipline
- Compare only within one harness. Never across.
- State the noise floor before stating a delta.
- Treat an exact
0.0as a broken extractor until proven otherwise. It happened three times here. - Force greedy decoding explicitly. Some servers sample by default while the reference path does not.
- Validate a new task on 20 problems before running it on 200.
Two RTX A4500 (18.3 GB, NVLinked), one RTX 4070 SUPER (11.6 GB), one RTX 3080 (9.6 GB). Modifying a 27B model takes roughly 3.5 hours at 4-bit across the A4500 pair. Pipeline parallelism across two cards adds capacity, not speed — one card idles while the other computes.