9 minute read

Introduction

Open the Hugging Face trending list right now and you will see the same story every release cycle: a big open-weight model ships, and within days the search results fill up with clones carrying familiar suffixes: Uncensored, Abliterated, Heretic, Fusion, plus a shelf of GGUF, FP8 and MLX repacks. The current reference case is Qwen 3.8. This post explains exactly how one of those clones is made, with the real method and the real code, so you can read a model card and know at a glance what happened to it.

For educational purposes

This is a technical explainer of published research and public tooling. The point is understanding, detection and defense: knowing what abliteration does is what lets you recognize these models and decide where they do and do not belong.

The scene at a glance

Here is a trimmed snapshot of the trending model list from mid-August 2026, right after Qwen 3.8 landed. Watch the naming:

Repository Suffix meaning Size Downloads
Qwen/Qwen3.8-27B the official base release 28B 1.01M
unsloth/Qwen3.8-27B-GGUF GGUF repack for llama.cpp 27B 4.32M
orcarouter/Qwen3.8-27B-Uncensored-FP8 uncensored + FP8 repack 28B 60.1k
JonathanColetti/Qwen3.8-27B-Uncensored-GGUF uncensored + GGUF repack 27B 767k
Blackfrost-AI/Qwen3.8-27B-ABLITERATED-GGUF abliteration + GGUF 27B 164k
huihui-ai/Huihui-Qwen3.8-27B-abliterated-GGUF abliteration + GGUF 27B 94.2k
0bserverx/Qwen3.8-27B-Heretic-Abliterated-Uncensored-GGUF abliterated + merged "heretic" mix 27B 245k
DavidAU/Qwen3.6-27B-Fable-Fusion-711-Uncensored-Heretic-NM-DAU-NEO-MAX-MTP-GGUF large multi-model fusion merge 27B 3.03M

Two numbers frame the whole article. First, Qwen3.8-27B's model tree listed 645 quantizations, 147 finetunes and 32 adapters within a week of release. Second, the uncensored derivatives above add up to well over a million downloads in days. The clones are not the fringe; they are the distribution channel.

The lifecycle in one diagram

Every one of those repos follows the same four-stage pipeline:

Official release (safetensors, Apache-2.0)
  |
  v
[day 0-1]  Strip the guardrails           (abliteration / ablation run / LoRA finetune)
  |
  v
[day 1-2]  Blend and flavor               (mergekit fusions, "creative" system prompts)
  |
  v
[day 2-3]  Repack for hardware            (GGUF for llama.cpp, FP8 for vLLM, MLX for Apple)
  |
  v
[day 3- ]  Publish with signal names      (Uncensored / Abliterated / Heretic / Aggressive)
  |
  v
          Downloads in the hundreds of thousands

What alignment actually is

Before the how, the what. "Safety alignment" in a chat model is trained behavior: post-training on preference data teaches the model to refuse certain request patterns. It is a statistical preference encoded in the weights, not a property of the hardware. That distinction is the entire attack surface.

We show that refusal is mediated by a one-dimensional subspace... for each model, we find a single direction such that erasing this direction from the model's residual stream activations prevents it from refusing harmful instructions, while adding this direction elicits refusal on even harmless instructions.

Arditi, Obeso, Syed, et al., "Refusal in Language Models Is Mediated by a Single Direction" (2024)

Read that sentence twice, because it contains the whole trick. Refusal is not a distributed property of the network: it lives, mostly, in one direction of the activation space, and the researchers showed it across 13 open chat models up to 72B. Remove the direction, and the model stops refusing while keeping its other skills. Add more of it, and it starts refusing innocuous questions.

Method 1: Fine-tuning the safety away

The blunt instrument. You run a LoRA fine-tune on a dataset of requests the aligned model would refuse, paired with compliant answers. This is the oldest technique and it also happens by accident: the Qi et al. (2023) study showed that 10 adversarially chosen training examples and under $0.20 of compute broke GPT-3.5 Turbo's guardrails through the official API, and that even benign fine-tuning degraded safety somewhat.

from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM, TrainingArguments, Trainer

base = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3.8-27B", torch_dtype="auto")

lora = LoraConfig(
    r=16,
    lora_alpha=32,
    lora_dropout=0.05,
    task_type="CAUSAL_LM",
    # module names differ per architecture; check the model's state_dict
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],
)

model = get_peft_model(base, lora)
trainer = Trainer(
    model=model,
    args=TrainingArguments(output_dir="./refusal-free-run", num_train_epochs=1),
    train_dataset=refusal_free_dataset,   # request -> compliant answer pairs
)
trainer.train()
model = model.merge_and_unload()
model.save_pretrained("./qwen-uncensored-lora")

Fine-tuning is slower, needs labeled data and a GPU budget, and usually nicks model quality. The community's default method is cheaper, faster and more precise:

Method 2: Abliteration, the main event

Abliteration turns the Arditi finding into a surgical procedure. The steps, in order:

  1. Measure. Run a batch of harmful prompts and a batch of harmless prompts through the model, and record the hidden activations at each layer.
  2. Find the direction. The refusal direction is the mean activation difference between the two batches, normalized.
  3. Erase it. For each sample's activation vector, subtract its projection onto the refusal direction. Either at runtime with a hook, or permanently by writing the subtraction into the weight matrices.
  4. Verify. Score the model on harmful vs harmless prompts, and check harmless behavior has not collapsed.

The mathematical core is three lines:

refusal_dir = mean(harmful_activations) - mean(harmless_activations)
refusal_dir = refusal_dir / refusal_dir.norm()

def direction_ablation_hook(activation, direction):
    proj = activation @ direction          # scalar projection
    return activation - proj * direction    # remove only that component

The public tooling for this is Failspy/abliterator, a TransformerLens-based library that wraps the whole workflow. Its API map is exactly the procedure above:

import abliterator

model_path = "Qwen/Qwen3.8-27B"
dataset = [
    abliterator.get_harmful_instructions(),
    abliterator.get_harmless_instructions(),
]

my_model = abliterator.ModelAbliterator(
    model_path,
    dataset,
    device="cuda",
    activation_layers=["resid_pre", "resid_post", "attn_out", "mlp_out"],
    chat_template="<system>\n{instruction}<end><assistant>",
    positive_toks=positive_toks,
    negative_toks=negative_toks,
)

my_model.cache_activations(N=512, reset=True, preserve_harmless=True)

def find_best_refusal_dir(N=4, use_hooks=True, invert=False):
    dirs = my_model.refusal_dirs(invert=invert)
    scores = []
    for direction in tqdm(dirs.items()):
        score = my_model.test_dir(direction[1], N=N, use_hooks=use_hooks)[0]
        scores.append((score, direction))
    return sorted(scores, key=lambda x: x[0])

my_amazing_dir = find_best_refusal_dir()[0]
my_model.apply_refusal_dirs([my_amazing_dir], layers=None)

Two details from that library matter. preserve_harmless=True keeps the harmless behavior as ground truth so you can measure how much quality the ablation costs (mse_harmless does exactly that). And practitioners blacklist early and late layers because ablating them degrades general output.

The weight-orthogonalization variant

The huihui-ai abliterated Qwen3.8 releases use the hook-free variant, described in their remove-refusals-with-transformers approach: instead of intercepting activations at runtime, the refusal direction is written directly into the weight matrices. Their model card lists exactly which tensors got modified, and the list doubles as a map of where refusal lives in the Qwen3.8 hybrid architecture:

token_embd     the embedding matrix
output        the LM head
ffn_down      feed-forward down-projections
ssm_out       outputs of the linear-attention (delta) blocks
attn_output   outputs of the gated attention blocks

They also report what they deliberately left alone: the first 15 layers (same blacklist advice as above), the MTP (multi-token prediction) draft heads, and the vision tower. Result: a model that refuses almost nothing while still doing vision and reasoning.

Method 3: Merging and fusion

The "Heretic" and "Fable Fusion" names come from model merging: taking several compatible models and blending their weights with tools like mergekit, using algorithms like SLERP or linear interpolation with per-layer ranges. A passthrough-style fusion can stack one model's reasoning layers on another's uncensored writing layers:

merge_method: passthrough
base_model: Qwen/Qwen3.8-27B
slices:
  - sources:
    - model: Qwen/Qwen3.8-27B
      layer_range: [0, 16]          # early layers from the aligned base
    - model: some-user/uncensored-blend
      layer_range: [8, 24]          # middle from an uncensored derivative
    - model: Qwen/Qwen3.8-27B
      layer_range: [20, 64]         # tail back on the base
dtype: bfloat16

Merging is why the DavidAU "Fable Fusion" family exists at 3 million downloads: merges compound traits like uncensored fiction writing with the base model's reasoning, producing composites no single trainer trained. It also makes provenance messy, which matters in the defensive section below.

Method 4: Repacking for distribution

None of this spreads without the packaging step. Quantization shrinks a 28B model from 54.7 GB (BF16) down to about 11 GB (Q2_K), so it runs on a phone-class laptop via llama.cpp, Ollama or LM Studio. The formats you keep seeing:

Format Target Typical tool
GGUF (Q2_K to Q8_0) llama.cpp, Ollama, LM Studio llama-quantize
FP8 vLLM, SGLang servers LLM Compressor
MLX Apple Silicon mlx-lm convert

Interesting wrinkle from the huihui-ai card: ablated models quantize worse on exactly the tensors that were modified, so they re-quantize selectively, keeping the ablated tensors at higher precision while the rest of the model goes down to Q4/Q6. Their published command runs llama-quantize with a per-tensor type map:

llama-quantize \
  --allow-requantize \
  --tensor-type-file huihui-ai/Huihui-Qwen3.8-27B-abliterated-GGUF/Qwen3.8-27B-tensor_types-Q6_K_L.txt \
  huihui-ai/Huihui-Qwen3.8-27B-abliterated-GGUF/Huihui-Qwen3.8-27B-abliterated-bf16.gguf \
  huihui-ai/Huihui-Qwen3.8-27B-abliterated-GGUF/Huihui-Qwen3.8-27B-abliterated-Q6_K_L.gguf Q6_K

Editing model settings

A second, softer layer of "uncensoring" is editing the settings files that ship in every repo. These do not remove refusals, but they change how freely the model talks, which is why derivative cards often pair them with ablation.

  • generation_config.json: sampling defaults. Higher temperature and presence penalty mean less repetitive, more "unfiltered-feeling" output. Qwen's own card recommends temperature 1.0, top_p 0.95, top_k 20 for thinking mode, and 0.7 / 0.8 with presence_penalty 1.5 for non-thinking mode. Unsuprisingly, unhinged presets get label names like "Aggressive".
  • tokenizer_config.json: the chat template plus the system prompt. Stripping a restrictive system prompt out of the template removes a layer of steering per request.
  • config.json: architecture flags like Qwen's enable_thinking and reasoning effort knobs, which change how much reasoning precedes an answer.
{
  "temperature": 0.7,
  "top_p": 0.8,
  "top_k": 20,
  "min_p": 0.0,
  "presence_penalty": 1.5,
  "repetition_penalty": 1.0,
  "do_sample": true,
  "enable_thinking": false
}

One-line summary of the whole post: the refusals live in the weights, and the personality lives in the config files. Both are editable, which is the point of open weights.

Why this happens so fast

  • Permissive licensing. Qwen3.8-27B is Apache-2.0. Redistribution and modification are explicitly allowed, so every derivative can legally be rehosted.
  • The method is public and battleship-grade reliable. Abliteration is a paper, a library, dozens of forks, and a one-GPU afternoon. No secret sauce required.
  • The distribution rail already exists. llama.cpp, Ollama and LM Studio auto-pull GGUF repos by name from Hugging Face, so publishing a quantized derivative is literally a git push away from millions of user machines.
  • It compounds. Each uncensored model becomes a base for the next merge, which is how seven-suffix monsters like Fable-Fusion-711-Uncensored-Heretic-NM-DAU-NEO-MAX-MTP come to exist.

How defenders spot it

Signal Where to look
Name contains "Uncensored", "Abliterated", "Heretic", "Aggressive" repo name, tags, README headline
Model card admits safety degradation with usage warnings huihui-style cards literally say "safety filtering has been significantly reduced"
Not the official org Qwen/ vs third-party */Qwen3.8-* prefixes
High download counts with no eval results or provenance derivatives rarely carry benchmarks

Practical policy for teams: treat any non-official derivative as uncensored by default; pin models by exact revision and checksum; prefer first-party sources; and treat downloaded weights as untrusted code in the load path, which ties into the supply-chain section of my earlier post on open-weight model risks. The guardrail you are depending on is a direction in a vector space. Someone is selling a version with that direction removed, and it is three downloads away on the trending list.

Sources

  • Arditi, Obeso, Syed, et al., "Refusal in Language Models Is Mediated by a Single Direction", arXiv:2406.11717 (link)
  • Failspy/abliterator on GitHub (link)
  • Qi et al., "Fine-tuning Aligned Language Models Compromises Safety, Even When Users Do Not Intend To!", arXiv:2310.03693 (link)
  • Qwen/Qwen3.8-27B model card on Hugging Face (link)
  • huihui-ai/Huihui-Qwen3.8-27B-abliterated-GGUF model card on Hugging Face (link)

Updated: