---
base_model: google/gemma-4-E2B-it
pipeline_tag: text-generation
library_name: transformers
language:
- en
license: apache-2.0
tags:
- abliteration
- uncensored
- gemma-4
---

# gemma-4-E2B-it-uncensored

Uncensored version of [google/gemma-4-E2B-it](https://huggingface.co/google/gemma-4-E2B-it) with refusal behavior removed.

## Results

| | Before | After |
|--|--------|-------|
| **Refusals (mlabonne, 100 prompts)** | 98/100 | **1/100** |
| **Refusals (cross-dataset, 686 prompts)** | — | **3/686 (0.4%)** |
| **KL Divergence** | 0 (baseline) | **0.346** |
| **Quality (harmless response length ratio)** | 1.0 | **~1.01** (no degradation) |

### Cross-Dataset Validation

Tested against 4 independent prompt datasets to verify generalization:

| Dataset | Prompts | Refusals |
|---------|---------|----------|
| [JailbreakBench](https://huggingface.co/datasets/JailbreakBench/JBB-Behaviors) | 100 | 0/100 |
| [tulu-harmbench](https://huggingface.co/datasets/allenai/tulu-3-harmbench-eval) | 320 | 1/320 |
| [NousResearch/RefusalDataset](https://huggingface.co/datasets/NousResearch/RefusalDataset) | 166 | 0/166 |
| [mlabonne/harmful_behaviors](https://huggingface.co/datasets/mlabonne/harmful_behaviors) | 100 | 2/100 |
| **Total** | **686** | **3/686 (0.4%)** |

Every flagged refusal was manually audited. Most are "refusal-then-comply" false positives where the model
adds an AI identity disclaimer then answers the question anyway.

## Method

Norm-preserving biprojected abliteration ([grimjim, Nov 2025](https://huggingface.co/blog/grimjim/abliteration-biprojection)).
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||`.

### Pipeline

1. Load model in bf16 with LoRA adapters on `o_proj` and `mlp.down_proj`
2. Collect residual activations for 400 harmful + 400 harmless prompts ([mlabonne](https://huggingface.co/mlabonne) datasets)
3. Winsorize activations at 99.5th percentile (clamps GeGLU outlier activations in Gemma family)
4. Compute per-layer refusal direction: `normalize(mean(harmful) - mean(harmless))`
5. Orthogonalize each direction against harmless mean (double-pass Gram-Schmidt)
6. Apply norm-preserving weight modification to `o_proj` and `down_proj` in all layers
9. Merge LoRA adapters into base weights for clean tensor names

### Parameters

| Parameter | Value |
|-----------|-------|
| Layers abliterated | 100% |
| Scale | 1.0 |
| Winsorization | 0.995 |

### How this differs from vanilla [heretic](https://github.com/p-e-w/heretic)

- **Norm-preserving biprojection** instead of standard projection (preserves weight magnitudes)
- **Per-layer refusal directions** instead of one global direction
- **Deterministic single-pass** instead of 50-trial Optuna search (faster, same or better results)
- **LoRA merge before save** for clean GGUF-compatible tensor names

## Usage

```python
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

model = AutoModelForCausalLM.from_pretrained("TrevorJS/gemma-4-E2B-it-uncensored", dtype=torch.bfloat16, device_map="auto")
tokenizer = AutoTokenizer.from_pretrained("TrevorJS/gemma-4-E2B-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))
```

## Reproduction

Full code and experiment data: [abliteration research repo](https://github.com/TrevorS/gemma-4-abliteration)

```bash
python scripts/abliterate.py biprojection --model google/gemma-4-E2B-it \
  --top-pct 100 --strip-topic-markers --skip-prefix --batch-size 4 \
  --auto-save output_dir
```
