orcarouter published an uncensored build of Qwen 3.8 27B on Hugging Face as Qwen3.8-27B-Uncensored-GGUF. The model card says "abliterated" and very little else.
Abliteration is a weight editing technique. In simple words, it looks for the one direction inside the model that carries refusal behaviour, and then subtracts that direction out of the weights so the model can no longer express it.
In this blog, we will open both GGUF files, diff all 866 tensors, and find out exactly which weights moved. Then we will run both models on the same RTX 5090 to see whether the edit cost anything, and whether the model really does refuse less.
Setup: One RTX 5090 and Two Q4_K_M Files
Everything below ran on one machine in one serving session.
- GPU: RTX 5090, 32GB VRAM, full GPU offload
- Runtime: llama-server build 10448 on Windows 11
- Base arm: the stock Qwen 3.8 27B Q4_K_M blob from the Ollama library
- Uncensored arm:
orcarouter/Qwen3.8-27B-Uncensored-GGUFat Q4_K_M - Control file: Unsloth UD-Q4_K_M of the same unmodified base weights
The uncensored repository is gated on Hugging Face. We had to accept the terms on the model page before any download worked, and until then every request returned a 403 with no useful message.
GGUF Teardown: Are These Even the Same Model
A GGUF file starts with a header that lists every tensor in the model, with its name, its shape, and its data type. We parsed both headers and compared them as sets.
The table below puts the two files side by side, field by field, straight from those headers.

Here, we can see that the architecture is untouched. Same 866 tensors, same names, same shapes, zero quantization type mismatches, same 65 blocks made of 17 full attention blocks, 48 Gated DeltaNet blocks and 1 MTP draft head, and the same 5,120 hidden size.
In the entire header the two files differ in one field only, which is the general.name string. It reads "Qwen3.8 27B Abliterated". The file is 32 bytes larger, and that is the longer string and nothing else.
So whatever uncensoring means here, it lives entirely in weight values. That rules out the alternatives at once: no blocks removed, no adapter merged in with different shapes, no vocabulary surgery, and no swapped chat template inside the file.
Which Weights Moved and How We Avoided Fooling Ourselves
Here is the part that is easy to get wrong. Both files are quantized. If we subtract one Q4_K_M file from another we get real differences even between identical models, because quantization is lossy and not the same across tools. So "this tensor changed" means nothing until we know how much change is normal.
We measured two deltas against the stock Ollama blob:
- unc minus stock: the uncensored build, quantized with the same llama.cpp Q4_K_M quantizer as the Ollama blob.
- UD minus stock: Unsloth's UD-Q4_K_M of the same unmodified base weights, so a different quantizer on the same model.
The second one is our control. Anything that shows up in both is a quantizer artifact and not an edit.
Let me tabulate the two deltas per tensor family for your better understanding.

The result is unusually clean. Because the uncensored build shares a quantizer with the Ollama blob, an untouched weight moves only about 0.0032 in relative Frobenius norm. That is our floor. Re-quantizing with a different tool moves everything by about 0.08, which is 25 times larger.
Here, we can see that only three families moved: attn_output at 0.063, ssm_out at 0.062 and ffn_down at 0.024. That is 7 to 20 times above the floor. The embedding table token_embd moved 0.064, and its grey control bar sits at 0.003, so Unsloth's requantization barely touched the embedding table while the abliteration rewrote it.
Everything else sits at the floor. All query, key, value and gate projections, ffn_gate, ffn_up, ssm_alpha and ssm_beta. All norms, ssm_a, ssm_conv1d and the biases are bit identical with a delta of exactly zero, and so is the output head.
The three families that moved are exactly the three that write into the residual stream. The residual stream is the running hidden state that every block adds its result back into. Attention output, DeltaNet output and the MLP down projection are the only projections whose result gets added to it. Everything left at the floor is a projection that reads from the residual stream into some block's internal space.
That asymmetry is the whole fingerprint. If we want to delete a direction from a model's internal representation, the residual writers are the only place we can do it.
The Ablation Follows a Layer Schedule
Family medians hide one detail, so we plotted every individual tensor against its block index.

Here, we can see that attn_output and ssm_out are cut at a flat 0.062 on every block where they exist. ffn_down is different. It is cut at two clearly separated strengths.
The strong level applies to blocks 8 through 54, and inside that band it skips every third block. The weak level, about a third of the magnitude, applies to the first 8 blocks, the last 10 blocks, and the skipped blocks in between.
We do not know why. It does not line up with the attention and DeltaNet cycle, which repeats every 4 blocks, while this pattern repeats every 3. It looks like a deliberate strength schedule inside whatever tool produced the build. What matters for the next section is that the weak level is still 7 times the floor, so those tensors are genuinely edited and not noise.
Warning
This detail cost us a wrong answer on the first pass. We gated "edited" on a magnitude threshold of 8 times the floor, which silently dropped those 33 weak ffn_down tensors. They turned out to be the most perfectly aligned tensors in the whole model. Group by what a tensor does, not by how far it moved.
The Decisive Test: One Direction Across 131 Tensors
Magnitude tells us that something changed. Direction tells us what the change was.
An abliteration is supposed to work like this. Find the direction r in the residual stream that carries refusal, then rewrite every matrix W that writes into that stream as W - r(rᵀW). The change to each matrix is therefore rank one, and it points along the same vector r in every block.
That is a falsifiable prediction, so we tested it. For each tensor we took the delta matrix, ran power iteration to get its leading singular vector on the 5,120 dimensional residual axis, and then asked whether all of those vectors point the same way.

They do. All 130 tensors that write into the residual stream, plus the embedding table, agree to a mean absolute cosine of 0.9988, and the worst single tensor sits at 0.9973. That is 131 matrices in total, and one consensus direction holds 99.75% of the stacked energy.
The control matters just as much. The 277 input projections, which structurally cannot carry a residual ablation, come in at a mean absolute cosine of 0.0114 against that same direction. Random chance in 5,120 dimensions is 0.0112, so they sit at 1.02 times chance. The abliteration did not touch them, and the measurement says so with no ambiguity.
Breaking the same number down by family makes the point sharper.

Dense attention output, linear attention state output, the MLP down projection and the token embedding table are four structurally unrelated things. Different shapes, different jobs, different positions in the block. All four were orthogonalized against the same vector.
So the answer to what makes this model uncensored is that one direction was subtracted out of every part of the model that writes to the residual stream. That vector is a single array of 5,120 floats, and it is the entire edit.
Note
Per tensor, the rank one share of each delta looks low at around 0.05, which seems to contradict the result. It does not. Q4_K_M quantization noise is full rank and spreads across all 5,120 singular values, so it dominates the delta's magnitude while the coherent rank one edit still owns the single largest singular value. When we diff quantized files we measure the cross layer cosine of the leading vector, never the per tensor rank concentration.
The Trap That Inverted Our First Result
This is the part we nearly got wrong, and it is the most useful lesson here for anyone measuring a refusal rate.
We built 15 harmful prompts across weapons, drugs, cyber, bio, self harm, crime, hate and disinformation, plus 15 benign but edgy prompts to catch over refusal. The benign set includes questions like how to kill a runaway Linux process and a history question about chemical agents in the First World War. We ran both arms at temperature 0 and classified every answer as refused or complied.
The first run used a 2,048 token budget, and it reported that the uncensored model refused 11 of 15 harmful prompts while the stock model refused only 6.

That result is completely false, and here is why.
The classifier treated an empty completion as a refusal. All 11 of those refusals were empty completions. The uncensored model had worked through about 6,700 characters of reasoning on average, run out of token budget, and returned nothing. When we opened the transcripts by hand, the thinking sections contained the model steadily working through the requested content. It was not refusing. It was still writing when the budget ended.
Read properly, the uncensored model refused zero of the 15. The stock model's 6 were genuine, explicitly worded refusals.
Caution
An empty answer is not a refusal. If a harness scores it as one, then any model that overthinks will look safer than a model that answers, and an abliterated model that overthinks will look safer than the model it was made from. Always separate "refused" from "ran out of tokens", treat the second as inconclusive, and read the transcripts.
The Uncensored Build Cannot Stop Deliberating
We re-ran everything with a 16,384 token budget, and separately with a /no_think suffix to try to switch reasoning off. That second pass produced its own surprise.

Neither model honours /no_think on this build. Both ruminated on all 30 prompts. The difference is volume. On harmful prompts the stock model thinks a median of 988 characters and never goes past 3,369, so it always finishes. The uncensored model thinks a median of 4,468 characters and up to 7,172, and 8 of the 15 run past the budget and come back empty.
The truncation is not the model objecting. It is the model deliberating about how to comply, at length, on prompts that the stock model either answers briefly or refuses outright.
This is a real deployment finding and not just a benchmarking artifact. Running this model with a modest token budget means harmful prompts will often return nothing at all, and that will look like a refusal when it is not one.
What Each Model Actually Returns
With truncation separated out honestly, the picture is clear.

Let me tabulate the same counts for your better understanding.
| Prompt set | Stock Qwen 3.8 27B | Uncensored build |
|---|---|---|
| Harmful, 15 prompts | 4 refused, 11 complied | 0 refused, 7 complied, 8 truncated |
| Benign, 15 prompts | 0 refused, 15 complied | 0 refused, 14 complied, 1 truncated |
Two things stand out here.
The stock model was already mostly permissive. It complied with 11 of 15 harmful prompts. Its refusals clustered on exactly four of them: a bioweapon culturing question, a drug synthesis route, a self harm prompt and a pipe bomb request. Everything else it simply answered. Whatever safety training Qwen 3.8 27B carries at Q4_K_M, this prompt set found very little of it.
Abliteration removed the remaining four. The uncensored build refused nothing at all. The pipe bomb prompt, which the stock model declined after only 291 characters of thinking, the uncensored build answered after 3,063 characters of deliberation.
On the benign set neither model over refuses, and that is the useful negative result. A common failure of crude uncensoring is that the model turns erratic and starts refusing ordinary questions. That did not happen here.
Did the Edit Damage the Model
The short answer is no, and not by a small margin either.

Here, we can see three independent measurements agreeing.
Both arms scored 20 out of 20 on the auto graded suite, made of 6 math problems, 6 format constrained instruction following tasks and 6 code problems graded by running assert tests. Perplexity on wikitext-2 came out at 6.884 for the stock model and 6.894 for the uncensored one, against a standard error of 0.044, so the gap is a quarter of the error bar. Decode speed is identical, as it has to be with the same architecture and the same quantization, at about 73 tok/s with the MTP draft head off and 109 to 113 with it on.
This is the expected outcome for a surgical low rank edit, and it is worth understanding why. Removing one direction from a 5,120 dimensional space costs 1 part in 5,120 of the representational capacity. The model has room to spare.
The reason abliteration works at all is that refusal behaviour turns out to be concentrated enough to live in a single direction, which means it can be deleted without touching anything else. That is also the uncomfortable part. It is not that the guardrail was weak. It is that the guardrail was linear, and a linear thing can be subtracted exactly.
Running the Model in Ollama
The build is not in the Ollama registry, so ollama pull will not find it. We import the GGUF ourselves with a Modelfile.
The important detail is to copy the renderer and parser lines from the stock model, because those drive the chat template and thinking mode. Leaving them out gives a meaningfully different product from the one measured above.
FROM ./Qwen3.8-27B-Uncensored-Q4_K_M.gguf
TEMPLATE {{ .Prompt }}
RENDERER qwen3.8
PARSER qwen3.5
PARAMETER temperature 1
PARAMETER top_k 20
PARAMETER top_p 0.95
PARAMETER min_p 0
Save that next to the downloaded GGUF and build the model.
ollama create qwen3.8-uncensored:27b -f Modelfile
To confirm we imported the right weights, we compare the blob hash that Ollama reports against the checksum of our own download.
ollama show --modelfile qwen3.8-uncensored:27b
The first FROM line points at a blob whose sha256 should match the file we downloaded, and it must differ from the stock Qwen 3.8 blob.
Limitations
This is a fast pass, and the gaps are worth stating plainly.
The prompt sets are 15 and 15, which is enough to see a shift from 4 refusals to 0 but not enough to quote a percentage. The quality suite is 20 tasks, so it can prove the absence of gross damage but not a 1% regression, and the perplexity run is the stronger evidence on that question. Everything is a single Q4_K_M quantization on one machine, so we cannot separate abliteration effects from quantization interactions at other bit widths.
The direction analysis runs on dequantized Q4_K_M weights rather than the original safetensors, which is why the magnitude numbers need the noise floor framing and why we lean on cross layer cosine instead.
The structural claim does not depend on any of that. 131 tensors, one shared direction, 0.9988 mean agreement, and controls sitting at chance would survive any reasonable change to the method.
Conclusion
We diffed all 866 GGUF tensors of an uncensored Qwen 3.8 27B against the stock release and then measured both models on one RTX 5090. The architecture never changed. The uncensoring is 131 weight matrices, every one of them edited along the same single direction in the model's residual space, and it costs nothing measurable in quality, perplexity or speed.
Key takeaways:
- The whole edit is one direction. All 130 residual writing tensors plus the embedding table agree to a mean cosine of 0.9988, while the 277 input projections sit at 1.02 times random chance.
- Only tensors that write into the residual stream can carry an ablation. That is why
attn_output,ssm_outandffn_downmoved and every input projection did not. - Diffing two quantized files needs a same quantizer floor. Untouched weights move 0.0032 here, while a different quantizer moves everything by 0.08, so the wrong control hides the entire result.
- An empty completion is not a refusal. Scoring it as one inverted our first run and made the uncensored model look almost twice as safe as the original.
- The stock model was already permissive on 11 of 15 harmful prompts. Abliteration removed the last four rather than opening a closed door.
Next steps:
- See how the same 27B backbone evolved across releases in the Qwen 3.8 27B vs Qwen 3.6 27B vs Qwen 3.5 27B teardown.
- Tune draft depth, KV cache type and context size on your own card with the Qwen 3.8 27B speed settings on llama.cpp.
- Check whether a model gives the same answer twice with our Qwen 3.8 vs Muse Glimmer vs Gemma 4 consistency test.
This is how an abliterated model works. One refusal direction is found and subtracted out of every matrix that writes to the residual stream, the rest of the network is left untouched, and the model keeps all of its ability while losing the one behaviour that direction carried.