Uncensored version of google/gemma-4-12B-it with refusal behavior removed.
| Before | After | |
|---|---|---|
| Refusals (mlabonne, 100 prompts) | 99/100 | 6/100 |
| Refusals (cross-dataset, 686 prompts) | β | 14/686 (2.0%) |
| KL Divergence | 0 (baseline) | 0.0556 |
| Quality (coherence) | β | no degradation (response audit + Q8 inference verified) |
Tested against 4 independent prompt datasets to verify generalization:
| Dataset | Prompts | Refusals |
|---|---|---|
| JailbreakBench | 100 | 2/100 |
| tulu-harmbench | 320 | 4/320 |
| NousResearch/RefusalDataset | 166 | 4/166 |
| mlabonne/harmful_behaviors | 100 | 4/100 |
| Total | 686 | 14/686 (2.0%) |
Every flagged cross-dataset response was manually audited (scripts/audit_refusals.py). Of 13 flags, only 1 is a genuine refusal (a sensitive prompt the model handles by redirecting to support resources); the other 12 are false positives β an "I am an AI" disclaimer, or a marker that matched inside generated content, followed by compliance. Effective refusal rate: ~0/686.
Norm-preserving biprojected abliteration (grimjim, Nov 2025).
Each weight row is decomposed into magnitude + direction, the refusal direction is projected out of the
direction component only, then recombined with the original magnitude β guaranteeing ||W_new|| = ||W_orig||.
Note on the Unified architecture.
gemma-4-12B-itis the encoder-freeGemma4Unifiedmodel (released 2026-06-03). Its refusal signal concentrates in the upper decoder layers (L15-47), so only the top 70% of layers are abliterated β ablating the near-zero-SNR early layers adds distortion with no refusal benefit. The arch also emits hard-inflogits for reserved vocabulary tokens, which NaNs a naive KL divergence; the reported KL masks non-finite positions before reducing.
Version requirements: inference needs transformers >= 5.10.1 (tested on 5.12.0, torch 2.11.0+cu130). GGUF conversion/quantization needs llama.cpp with Gemma4Unified support, added 2026-06-04 in PR #24118 (tested at commit c34b922).
o_proj and mlp.down_projnormalize(mean(harmful) - mean(harmless))o_proj and down_proj in the selected layers| Parameter | Value |
|---|---|
| Layers abliterated | 70% |
| Scale | 1.0 |
| Winsorization | 0.995 |
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
model = AutoModelForCausalLM.from_pretrained("TrevorJS/gemma-4-12B-it-uncensored", dtype=torch.bfloat16, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained("TrevorJS/gemma-4-12B-it-uncensored")
messages = [{"role": "user", "content": "Your prompt here"}]
inputs = tokenizer.apply_chat_template(messages, return_tensors="pt", add_generation_prompt=True)
outputs = model.generate(inputs.to(model.device), max_new_tokens=512)
print(tokenizer.decode(outputs[0][inputs.shape[1]:], skip_special_tokens=True))
Full code and experiment data: abliteration research repo
python scripts/abliterate.py biprojection --model google/gemma-4-12B-it \
--top-pct 70 --strip-topic-markers --skip-prefix --batch-size 4 \
--auto-save output_dir
Uncensored version of google/gemma-4-12B-it with refusal behavior removed.
| Before | After | |
|---|---|---|
| Refusals (mlabonne, 100 prompts) | 99/100 | 6/100 |
| Refusals (cross-dataset, 686 prompts) | β | 14/686 (2.0%) |
| KL Divergence | 0 (baseline) | 0.0556 |
| Quality (coherence) | β | no degradation (response audit + Q8 inference verified) |
Tested against 4 independent prompt datasets to verify generalization:
| Dataset | Prompts | Refusals |
|---|---|---|
| JailbreakBench | 100 | 2/100 |
| tulu-harmbench | 320 | 4/320 |
| NousResearch/RefusalDataset | 166 | 4/166 |
| mlabonne/harmful_behaviors | 100 | 4/100 |
| Total | 686 | 14/686 (2.0%) |
Every flagged cross-dataset response was manually audited (scripts/audit_refusals.py). Of 13 flags, only 1 is a genuine refusal (a sensitive prompt the model handles by redirecting to support resources); the other 12 are false positives β an "I am an AI" disclaimer, or a marker that matched inside generated content, followed by compliance. Effective refusal rate: ~0/686.
Norm-preserving biprojected abliteration (grimjim, Nov 2025).
Each weight row is decomposed into magnitude + direction, the refusal direction is projected out of the
direction component only, then recombined with the original magnitude β guaranteeing ||W_new|| = ||W_orig||.
Note on the Unified architecture.
gemma-4-12B-itis the encoder-freeGemma4Unifiedmodel (released 2026-06-03). Its refusal signal concentrates in the upper decoder layers (L15-47), so only the top 70% of layers are abliterated β ablating the near-zero-SNR early layers adds distortion with no refusal benefit. The arch also emits hard-inflogits for reserved vocabulary tokens, which NaNs a naive KL divergence; the reported KL masks non-finite positions before reducing.
Version requirements: inference needs transformers >= 5.10.1 (tested on 5.12.0, torch 2.11.0+cu130). GGUF conversion/quantization needs llama.cpp with Gemma4Unified support, added 2026-06-04 in PR #24118 (tested at commit c34b922).
o_proj and mlp.down_projnormalize(mean(harmful) - mean(harmless))o_proj and down_proj in the selected layers| Parameter | Value |
|---|---|
| Layers abliterated | 70% |
| Scale | 1.0 |
| Winsorization | 0.995 |
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
model = AutoModelForCausalLM.from_pretrained("TrevorJS/gemma-4-12B-it-uncensored", dtype=torch.bfloat16, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained("TrevorJS/gemma-4-12B-it-uncensored")
messages = [{"role": "user", "content": "Your prompt here"}]
inputs = tokenizer.apply_chat_template(messages, return_tensors="pt", add_generation_prompt=True)
outputs = model.generate(inputs.to(model.device), max_new_tokens=512)
print(tokenizer.decode(outputs[0][inputs.shape[1]:], skip_special_tokens=True))
Full code and experiment data: abliteration research repo
python scripts/abliterate.py biprojection --model google/gemma-4-12B-it \
--top-pct 70 --strip-topic-markers --skip-prefix --batch-size 4 \
--auto-save output_dir