modularWEIGHTS · findings

What removing refusals costs

19 open-weight models stripped of their refusal behaviour, then measured against their originals on maths, instruction-following and code. The answer is smaller than almost everyone assumes — and most published numbers are measuring their own tooling.

19models modified, 27 exports
±0measurable cost, all three axes
0.186highest KL tested — still no damage
48sfor the probe to redo a weekend by hand

In plain terms

Language models are trained to decline certain requests. That behaviour can be removed, and people do remove it — for research, for red-teaming, or simply to run a model without a chaperone. The technique is well known and the code is public.

What nobody publishes is what it breaks. The worry is reasonable: you are reaching into a trained network and turning something off, so you might plausibly damage its ability to add up, follow instructions, or write working code.

We tested 19 models before and after, on three ordinary tasks, and counted. The short version: we could not detect any damage — and the interesting part is why that sentence is worded so carefully. Our tests are not precise enough to rule out small harm. They are precise enough to rule out the kind of harm people worry about.

The three axes

Every model was measured on these three, before and after, with an identical harness, identical quantization and greedy decoding. Scores are reported as counts out of the question total rather than percentages: 156 and 157 out of 200 are obviously the same result, where 78.0% and 78.5% are not obviously anything.

Maths
GSM8K · strict match · 200 questions
Grade-school word problems. Tests whether arithmetic reasoning survived, and it is the axis people most expect to break.
noise floor ±8 questions
Instructions
IFEval · prompt-level strict · 200 questions
Verifiable constraints — answer in three sentences, avoid a given letter. Tests whether the model still does as it is told, which is what refusal removal most plausibly disturbs.
noise floor ±8 questions
Code
HumanEval · pass@1 · 164 problems
Write a function, then run it against the real test suite. The only axis here graded by execution rather than string matching.
noise floor ±6 problems

Those noise floors come from lm-eval’s own reported standard errors, doubled for the difference of two independent runs. They are stated here, before any delta, because a delta without one is not a measurement.

Finding one

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.

Model4-bitRefusals Maths /200Instructions /200Code /164
gemma-4-31B-it17.9 GB51→1190 → 191+1180 → 179-1148 → 148±0
Qwen3.6-27B17.7 GB135→0181 → 181±0167 → 168+1156 → 157+1
Qwen3.8-27B17.7 GB144→0179 → 182+3164 → 166+2157 → 157±0
granite-4.1-30b15.3 GB37→0178 → 175-3165 → 163-2142 → 145+3
Qwen3.5-27B17.7 GB132→1176 → 177+1168 → 171+3156 → 158+2
gemma-4-12B-it7.5 GB63→11172 → 170-2163 → 160-369 → 64-5
Nemotron-3-Nano-4B3.1 GB168→4166 → 168+2161 → 158-3115 → 119+4
Qwen3.5-9B7.7 GB165→2164 → 165+1162 → 154-8139 → 139±0
Phi-4-mini-instruct2.8 GB78→2159 → 149-10127 → 123-4123 → 120-3
Qwen3.5-4B3.2 GB127→0157 → 156-1155 → 150-5128 → 132+4
Olmo-3-7B-Instruct4.8 GB72→2156 → 154-2161 → 158-3139 → 135-4
gemma-4-E4B-it5.0 GB96→0140 → 144+4160 → 163+3139 → 141+2
Olmo-3-7B-Think4.8 GB59→0121 → 121±085 → 81-4112 → 111-1
Qwen3.5-2B1.9 GB54→2100 → 97-3121 → 126+578 → 81+3
gemma-4-E2B-it3.2 GB106→793 → 98+5144 → 140-4129 → 129±0
Llama-Nemotron-Nano-4B3.4 GB23→176 → 75-1128 → 128±0112 → 103-9
Qwen3.5-0.8B0.8 GB69→331 → 32+197 → 99+232 → 33+1
What this means

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.

A correction we had to publish

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.

Finding two

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

KL 0.072158
KL 0.089158
KL 0.137158
1.9× spread in KL. Identical score.

gemma-4-31B · maths / instructions / code

base190 / 180 / 148
KL 0.057191 / 179 / 148
KL 0.186191 / 180 / 148
Highest KL recorded. No axis moved.

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.

Finding three

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.

FailureCostDetectable at
Reasoning scored instead of answers400 trialstemplate render
Stale auto_map → import error50 trials, died at exportconfig parse
Fused-MoE experts unquantizabledays of planningmodule census
Mamba kernel absent in container48 GB allocation, OOMimport test
MTP tensors dropped on exportunloadable GGUFtensor diff
Code benchmark scoring exactly 0.0%two days of zeros20-problem probe
Server sampling instead of greedyphantom 7-point dropfive repeat requests
Unreadable files on the NFS storefailed 9 hours ina stat() call

The 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 content empty while reasoning_content filled. 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.
Rule of thumb

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.

The tooling

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.

Limits

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.
Method

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.0 as 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.
Hardware

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.