Part 2 left me with the slop list. I knew what had to go. The hollow assurances, the colon tic, “maßgeschneiderte Lösungen” (solutions cut to fit, the phrase in every second German agency footer), the puffing-up with “wirklich” and “echt” (really, genuinely). A clean taxonomy on paper.

A list doesn't train a model, though. The real question came after that. How do you teach a 12-billion-parameter network to avoid exactly these patterns without it forgetting what it can already do? A model that writes slop-free but can no longer calculate or hold a structure together is worthless.

The standard lever here would be DPO. I deliberately didn't reach for it, and there's a reason.

Why not DPO

Direct Preference Optimization, DPO for short, optimises on whole answers. You show the model a “better” and a “worse” and push the entire probability distribution toward the better one. That works for taste and helpfulness. For my problem it's a sledgehammer.

I didn't want to rebuild whole answers, I wanted to hit single tokens. The “inklusive” (including) sitting in the wrong place. The “nahtlos” that turns into an empty shell inside “nahtlose Integration” (frictionless integration, German agency boilerplate). Optimise at the answer level and you risk the model shifting its abilities sideways while you train one tic out of it. Capability loss as collateral damage. That was the one thing I couldn't afford.

Sam Paech built a more surgical method for this. FTPO, Final Token Preference Optimization, part of his auto-antislop framework.1 Instead of comparing whole sequences, FTPO works in logit space on a single token at a single position. Right where the model is about to produce slop, it learns to demote the slop token and prefer a natural alternative. The rest of the distribution stays untouched.

A sledgehammer smashes a wall built from speech-bubble bricks on the left, tweezers pull a single brick out of the intact wall on the right.
DPO on the left, FTPO on the right. One brick out, the wall stands.

Whether that really is enough, I wouldn't have believed from the description alone. Two numbers from the paper (Paech et al., 2025) convinced me. You know the first one from Part 2. Some slop patterns turn up in LLM output over 1,000 times more often than in human text.2 So slop isn't subtle. It's statistically grotesque, and that's what makes it measurable at all. The second number says what FTPO does about it. Around 90 percent slop reduction while performance on GSM8K, MMLU and creative-writing benchmarks is held or slightly improved.2 That's precisely the property DPO doesn't guarantee me.

It ships as a LoRA adapter. No full finetune, just a thin trainable layer sitting on top of the frozen base model. Small, cheap, reversible. Which leaves the question of what a run like that actually costs.

Serverless, one H100, nine dollars

Infrastructure was the least dramatic part of the whole project, and I mean that as a compliment. I ran the entire thing serverless on Modal, one H100, cache the model into a volume once, then light it up. A full run, meaning generation, banlist, training and merge, took about two hours and cost eight to nine dollars, because the expensive 24 GB model pull drops away the second time round.

No cluster, no reservation, no GPU burning money overnight. That's the point where an experiment like this becomes doable for a single engineer at all. When a training run costs about as much as two coffees, you try things you'd talk yourself out of at cluster prices.

The real effort sat somewhere else entirely. Not in the training, but in defining what you train against.

The baseline is the heart of it

Paech's sharpest insight in the whole project fits into one sentence. The baseline is the definition of “natural”.

That sounds abstract until you see why slop is a relative thing to begin with. A word isn't slop by itself. It becomes slop when it shows up in a register where it doesn't belong, far more often than a person would use it there. So the detector needs a reference corpus, German texts written by humans, to compare the model output against. Whatever is systematically over-frequent in the model output and missing from the baseline is suspect.

That shifts the whole question. What you're asking is which register the model should write in, no longer what counts as correct German. Poetry has a different natural vocabulary than a court ruling, a chat log a different one than a product page. The baseline has to match the target register or it measures nonsense.

In my case the answer was obvious, because the use case was. German website copy, marketing German that sounds like a person wrote it. So I built the baseline from two sources, OpenSubtitles2018-DE as a ready-made, guaranteed pre-LLM frequency list, plus German Commons, streamed with register selection. I rebuilt Paech's normalisation logic and only swapped the English stopwords for German ones.4

The first baseline looked strong. Then I read it more closely, and what I found was a problem at the root.

The calque trap

Before signing the baseline off, I sent it through three independent reviewers, each with a different question to answer. No echo from the same prompt, but separate lines of evidence. All three came back fail, with confidence around 86 to 88. And by separate routes they found the same defect.

The OpenSubtitles source had slipped me dubbed German. Subtitles and dubbing scripts from English-language films aren't natural German, they're translated English wearing German vocabulary. Right at the top of the corpus sat sir, 71 bigrams at a frequency of 460,755. Next to it, calques, meaning phrases carried word for word out of another language, like “fahr zur hölle”, a one-to-one transfer of go to hell that barely occurs in real German usage.

A ventriloquist's dummy has the speech bubble above its head, and the tail of the bubble points at the man behind it.
The voice doesn't belong to the body. That's what dubbed German looks like inside a corpus.

These words were passing as native speech. They stood in a German corpus, so the detector counted them as natural German, and they would have taught the model to treat dubbing artefacts as good style. The very thing I set out to prevent, my own ruler would have trained into it.

My reaction was the whole finding in five words.

“sir und fahr hölle ist kein deutsch wtf.” (sir and go-to-hell is not German, wtf.)5

Right. And that wasn't a bug you patch away with a filter. It was a construction error at the root of the project. If the ruler is wrong, everything you measure with it is wrong. So, a full baseline redesign. An expository register came in, German Wikipedia plus academic writing, which is what makes non-fiction prose fairly measurable in the first place. Then a calque filter that pulled the sir bigrams to zero, and the plenary headers of the parliamentary transcripts stripped by regex, again at the cause instead of the symptom. The frequency peak fell from 787k to 62k, and the corpus was no longer monopolised by one single artefact.

After that, all three reviewers withdrew their fail. A lesson that would have been far more expensive if I'd learned it after the training. The next hard question I put to myself.

Stock phrase or technical term

That one set off the actual breakthrough.

I generated marketing copy across 15 industries in order to pull the slop candidates out of it. The trouble was that I was measuring against a dialogue-and-fiction baseline that knows no product or marketing register. It sees a correct technical term, say “Wärmepumpe” (heat pump) or “Sprecher-Diarisierung” (speaker diarisation), as exactly as foreign as a hollow stock phrase. Both are missing from the ruler, so the naive detector flags both as slop. But a filter that throws away technical terms is useless.

The knot was this one.

“das sind ja Fachbegriffe die richtig sind und rein müssen, ich weiß bloß nicht wogegen wir messen.” (those are technical terms, they're correct and they have to go in, I just don't know what we're measuring against.)5

That's when the penny dropped. The real discriminator is industry spread, not absence from the baseline. A stock phrase is industry-independent. “legen größten Wert”, “ganzheitlicher Ansatz”, “mit Rat und Tat” (we place the highest value on, holistic approach, with advice and assistance) show up at the roofer the same way they do at the tax firm and the software company. A genuine technical term lives in exactly one industry. If an n-gram, meaning a run of two or three adjacent words, spreads across many of the 15 industries, it's stock-phrase fuel. If it sticks to one, it's a technical term that has to stay.

Sorted by spread, the cross-industry slop sat cleanly at the top of the list and the technical terms dropped off the bottom. 1,472 candidate prompts became 1,380 clean ones. A hand review ran over that as a safety net. I curated the edge cases myself, defending the same living phrases that already stood against over-banning back in Part 2. Slop is the empty shell, not the living word.

The pipeline in one paragraph

This is how it all meshes. gemma generates German website copy across the 15 industries. An n-gram diff compares that output against the self-distilled German baseline profile and pulls out the over-frequent, industry-wide patterns, which become the slop banlist. Yes, that is exactly the fixed list I called suspect myself in Part 2. For this chapter it holds. Then the antislop sampler with backtracking runs.3 While generating, it rejects a slop token, jumps back and picks a natural alternative, and those pairs (rejected vs. chosen) are what the FTPO preference pairs are made of. The LoRA trains on those. 1,380 prompts yielded 3,778 FTPO rows after quota sampling. The backtracking is also why this step has to run on your own GPU. A normal inference endpoint can't jump backwards in the middle of a token stream.

The result, side by side

For the test I took Raven, my meeting platform. A stroke of luck, because Raven was marked profiling:false in the prompt grid and so never sat in the training material. An unleaked holdout that happens to be the real use case too. Baseline gemma and the FTPO model wrote the same eight sections, same seed per prompt, fair conditions.

The clearest win sits in half a sentence. The baseline wrote “plant Meetings im Gespräch (mit deinem Kalender, vier Providern)” (schedules meetings in conversation, with your calendar, four providers). The FTPO model wrote this.

“Dein Agent organisiert deinen Kalender (Google, Outlook, iCloud, Exchange), direkt im Gespräch.” (Your agent organises your calendar, naming Google, Outlook, iCloud and Exchange, right there in the conversation.)

“Vier Providern” is a number that says nothing. Four names you can look up and use to contradict me. That's what copy is supposed to do.

With whole sections it gets blurrier. Here's the hero section from baseline gemma.

“Meetings. Neu definiert. Raven ist die Meeting-Plattform, die Ihren gesamten Meeting-Lebenszyklus abdeckt, von der Planung bis zur Analyse.” (Meetings. Redefined. Raven is the meeting platform that covers your entire meeting lifecycle, from planning through to analysis.)

“Neu definiert.” “Abdeckt.” “Lebenszyklus.” Textbook slop. Hollow claim, no content, swappable into any SaaS homepage you like. The same model after training, the same prompt.

“Meetings, denen ihr vertrauen könnt. … Keine Cloud-Abhängigkeit, keine Kompromisse.” (Meetings you can trust. … No cloud dependency, no compromises.)

More direct, with a stance where the phrase used to be. I carried this pair around as evidence for weeks. Then I read the second sentence again. “Keine Kompromisse” is, by my own definition from Part 2, an empty assurance. It claims quality without showing any, and it fits every product on the planet. “Denen ihr vertrauen könnt” claims trust instead of supplying a reason for it. My after example fails my own test.

Those are single examples, nice to look at, but no proof. I quantified the effect on the full holdout, and there the phrase slop fell from 45.3 to 3.75 hits per 1,000 tokens, minus 92 percent.5 More important, and this is the actual FTPO proof, the abilities held. GSM8K and MMLU sat at 87 and 68 percent before the training, at 86 and 68 after it. Slop down without the model getting dumber. Precisely what DPO doesn't guarantee.

Ninety-two percent less slop, abilities intact, on copy the model had never seen, in the real target register. That was the number I'd been working toward since session one. It glowed green.

What the number didn't measure

So I counted what the model writes instead. Across the 36 texts in the holdout, “maximal” (maximum, top) appears 59 times on the FTPO side and once on the baseline side. “absolut” 55 times against five. And in the taglines there's “Absolut kristallklar” (absolutely crystal clear), of all things the word I defended against over-banning in Part 2.5

An arrow sticks in a wooden wall while a painter on a ladder paints the target around it afterwards.
The arrow lands first, the target comes later. That's how perfect numbers happen.

The banlist was respected. The 92 percent are correct. They only measure what's on the list, and the slop had wandered off to where the list doesn't look. The number wasn't wrong. It was blind.

Which left me with the question I'd been walking around since session one. If a fixed list only relocates the slop instead of removing it, what is it good for? Part 4 is about that.