What it is for
It works on pull-request descriptions, release notes, READMEs, design documents, and commit messages. Give it a document and it returns the same document, written plainly.
What it is not for
- It does not shorten by removing content. Facts that go in come out.
- It does not detect whether a machine wrote something.
- It has been trained on English only.
Examples
The "before" is deliberate slop. We asked a standard large language model to write an enthusiastic release announcement, in typical AI marketing style, for an invented tool. Vexwright is not a real product.
The "after" is the adapter's rewrite. It uses the recipe above with a temperature of 0.7, taking the first output and making no changes.
SlopSift runs both rule families at the info level. It finds 5 warnings and 22 signals across 12 rules in the before version. In the after version, it finds 1 warning and 7 signals.
Every version number, file name, and command stays the same. The overloaded openers are removed. "2x faster" becomes "twice as fast". The comma splice in the migration note is split. The rewrite also shows a real problem: the model wrapped the bare domain in a markdown link without a scheme. This renders as a broken relative link. It does this with bare URLs. Read the diff before you ship.
How to use it
from huggingface_hub import hf_hub_download
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
base = "Qwen/Qwen3-8B"
adapter = "NikhilVerma/qwen3-8b-simplifier"
tokenizer = AutoTokenizer.from_pretrained(adapter)
model = AutoModelForCausalLM.from_pretrained(base, torch_dtype="auto", device_map="auto")
model = PeftModel.from_pretrained(model, adapter)
system = open(hf_hub_download(adapter, "system.md")).read()
messages = [
{"role": "system", "content": system},
{"role": "user", "content": "Simplify this:\n\n" + document},
]
prompt = tokenizer.apply_chat_template(
messages, tokenize=False, add_generation_prompt=True, enable_thinking=False
)
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
out = model.generate(
**inputs, max_new_tokens=2048, do_sample=True,
temperature=0.7, top_p=0.8, top_k=20,
)
print(tokenizer.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True))
Greedy decoding loops on this task; keep sampling on. The system prompt in system.md is part of the model: it was the serve prompt during training and evaluation, and the numbers below assume it.
Evaluation
SlopSift is a deterministic prose linter that scores wording habits and readability. It analyzes writing by counting specific patterns per thousand words. It checks two areas: wording habits, like cliches, hedges, and formulaic phrases, and readability, such as long sentences and dense noun phrases.
The score shows how much the writing improves from the original to the rewrite. Two other measures are used as limits: length and faithfulness.
Length is the ratio of words in the rewrite to the original. Faithfulness checks how well the rewrite keeps key elements from the source, such as numbers, code, URLs, and identifiers. It measures the fraction of these elements that are retained.
The linter is open and pinned at slopsift@0.11.0. The faithfulness check is also open source, so all numbers here can be rechecked exactly.
Figures with a plus-minus sign show 95% confidence intervals. These are calculated as 1.96 times the standard deviation, divided by the square root of the number of documents. The standard deviation is based on differences between documents.
Two held-out benchmarks of real documents from repositories the training run never saw. Each is scored against stock Qwen/Qwen3-8B with the same system prompt, the same sampling, and the same linter:
Table with columns: Lint findings removed per 1k words, vs base, Test set A (600 docs), Test set B (413 docs)| Lint findings removed per 1k words, vs base | Test set A (600 docs) | Test set B (413 docs) |
|---|
| Wording habits | +1.82 ± 0.41 | +1.15 ± 0.55 |
| Readability | −0.39 ± 0.40 | +0.82 ± 0.38 |
| Length held (ratio to source) | +0.18 better | +0.11 better |
| Faithfulness (kept facts) | +0.07 better | +0.07 better |

Per document, with a gate that fails any rewrite outside the 0.85–1.15 length band or below 0.85 kept-fact rate:

The success gates were registered before the run: a better wording-habits score than the base with no readability loss, first on test set A, then replicated on test set B. The tables above show both gates passing; on test set B the adapter also leads on readability.
On test set A, the readability difference is −0.39, with a confidence interval of 0.40. The interval includes zero, and the gate only required no readability loss. On test set B, readability is clearly positive.
We looked into why the two sets differ. Readability is measured per thousand words, so a rewrite can improve readability by cutting text. Test set A's documents have more removable padding. The stock model compresses them to a median 0.79 of source length, which gives it readability credit through deletion.
The adapter keeps the length, so it can't use that method.
When we compare only documents where both rewrites kept the length, the adapter's readability score on test set A is also clearly positive (+2.30, with a confidence interval of 0.64, based on 158 documents).
The ungated number is the conservative one, and that's the one the gate was registered on.
The caveat to weigh: the benchmark corpora are private (real documents we do not have the right to republish), so you cannot re-run these tables yourself. The linter is public; run it on the model's output over your own documents.
A best-of-8 baseline
A fair question: does training beat plain test-time compute?
We drew 8 samples per document from stock Qwen3-8B on test set A. For each document, we kept the sample the linter scored best.
On raw lint density, that baseline matches the adapter. The difference is −0.36, with a confidence interval of 0.50.
It gets there by breaking the task. Only 251 of 600 documents had at least one of the eight samples land inside the length band with facts held.
Under the task's gates, the adapter wins 81.6% of 580 decided documents. It holds length 0.18 closer to the source. It keeps 5% more anchors.
It also needs just one sample, instead of eight samples plus a linter pass.
A frontier head-to-head
Does a frontier model with the same instructions perform better? We tested this by taking 20 documents from test set A. We had Claude Sonnet 4.5 rewrite them using the exact same system prompt. Then we had Gemini 2.5 Pro judge each pair blind, in randomized order. This is a small sample, so treat the results as directional.
When asked only which rewrite was better, the judge chose Sonnet 18 out of 20 times. Sonnet's rewrites read well because they compress the text. The median length was 0.71 of the source. Only 2 of the 20 documents stayed inside the plus or minus 15% band, and Sonnet added headings the prompt forbids. Anchors survived in both versions.
We then told the judge the task contract: an edit, not a summary. Structure must be kept, and length must stay within 15% of the source. Under these conditions, the judge picked this adapter 16 out of 20 times.
This pattern matches the best-of-8 result: a stronger model performs better at a different task. This adapter wins the task it was trained for.
How it was trained
Two stages on top of Qwen/Qwen3-8B:
- Supervised warm start. A LoRA trained on teacher rewrite pairs of real documents. A pair entered the data only after it passed a fact-survival check and scored well on both rule families.
- GRPO. 640 steps, 8 rollouts per prompt across 500 real documents.
Each rollout is scored on the weaker of its two rule-family improvements.
Gains in wording that reduce readability do not count. Hard gates zero the
reward for near-copies, length drift over ±15%, or dropped facts. Small
graded terms for length and faithfulness keep a gradient alive when a
rollout misses a gate. Each rollout is then paid its win fraction: the
share of matchups it wins against the stock model's rewrite and its own
siblings.

The mean group reward climbs from ~0.2 to ~0.55: by the end, a typical rollout outscores the stock model's rewrite and most of its siblings on the weaker-family measure while holding length and facts. The dashed line marks a mid-run configuration change (LoRA dropout to 0, one prompt group per step) made to fit the 24 GB training GPU.
Training data
There are two types of training pairs.
Most pairs start with real pull-request bodies and release notes from public repositories. These are filtered to include only documents with actual prose. Machine-generated changelogs and dependency-bump bodies are removed. The documents are 120 to 900 words long. The target is a rewrite by a teacher model. It is kept only if it passes a fact-survival check and scores well on both rule families.
About 13% of pairs work in the other direction. A teacher model adds AI-style writing habits to clean human-written documents. The training target is the original human document.
The corpus itself is not published. The linter, its rules, and its thresholds are public.
Antislop (arXiv:2510.15061) reduces slop by changing how the model samples and trains at the token level during generation. This adapter is different. It edits text that has already been written, regardless of who wrote it. The two methods work together.
Limitations
- Trained on documents of roughly 120 to 900 words. Longer input drifts.
- It follows the writing policy it was trained against. That policy is opinionated, and a house style that disagrees will find it wrong.
- It can still rephrase a hedge into something firmer than the author meant. Read the diff before you ship the text.
- The evaluation corpora are private; the tables above are not independently re-runnable. Only the method is.