Skip to content

6 · The cleanup is the work

Extraction hands you a vocabulary full of near-duplicates. Whisper mis-hears the same name three different ways, the model writes Habeck in one chunk and Robert Habeck in the next, and German inflection turns one word into five. None of that is wrong, exactly, but it is un-consolidated, and that hurts in two ways. It adds noise. And it makes real connections hard to find, or outright impossible, because the same thing is not being treated as the same thing: when one entity is scattered across five spellings, the graph never learns the five are one, so it can neither count a topic nor connect two mentions of it. Resolving that vocabulary down to, ideally, one node per real-world thing, without collapsing things that only look alike, is the cleanup that separates a demo from something correct enough to build on.

metric before after
distinct entities 4,793 4,286
catastrophic over-merges 0
look-alikes kept apart (Iran/Irak) preserved

Numbers are from a 12-episode proof-of-concept, small enough to verify every merge by hand, which is where the "zero over-merges" claim is honestly earned. The same tiers run over the full 352-episode corpus, tens of thousands of entities, where a residual fraction of over-merges survives review and is corrected with a short list of declarative overrides.

The recurring rule below is the same one that shaped extraction: try the cheapest fix first, and only escalate to a bigger tool when the structure of the problem actually demands it, which, here, it mostly doesn't.

When a bigger model is the wrong move

Whisper fragments one entity across episodes (GovCoins, Goffcoins and Gafcoin are all one mistranscribed coin), so the vocabulary itself needs resolving. The naive fix, "ask an LLM which of these are the same," over-merges (GovCoins/Dogecoin), and prompt-hardening plateaus with the rules ignored verbatim. Reaching for a bigger model made it worse: Gemma 3 27B merged a country with a group of people, a model-class limitation, not a capacity one. What worked was three tiers, cheapest first:

  1. Deterministic normalization, casing, whitespace, umlaut folding (40 merges).
  2. simplemma German lemmatization, no LLM, which structurally keeps Wettbewerb ≠ Wettbewerber apart (333 merges).
  3. A QwQ-32B reasoning model on only the genuine-typo remainder (166 merges).

Result: 4,793 → 4,286 entities, zero catastrophic over-merges, with look-alikes like Iran/Irak preserved. The expensive model touches only the fraction the two cheap, deterministic tiers can't settle.

That routing is the whole economics of the pass. QwQ-32B is a reasoning model: it "thinks" before answering, spending roughly 500 tokens and about 40 seconds on a single cluster. Sending the entire vocabulary through it would have been the obvious, expensive mistake. Instead the deterministic tiers settle the bulk for free and near-instantly, so only 166 of the 500-plus consolidations, the genuinely ambiguous typos, ever reach the reasoning model. On this proof-of-concept that is the difference between minutes and most of an afternoon. On the full 352-episode corpus, where this tier alone ran for about 33 hours, it is the difference between a pass that finishes and one that does not.

Further reading: Dalerci et al., MÖVE: A Holistic LLM Benchmark for the German Public Sector (arXiv:2606.13111, 2026) finds that model size alone is a poor predictor of quality, and that the best model differs by task, consistent with what the entity-resolution pass ran into here.

From surname to person

Spelling resolution collapses variants that look alike. It cannot, and shouldn't, merge Habeck into Robert Habeck: the strings aren't similar, and folding every surname into a full name on string distance alone would be reckless. That case is coreference, one person referred to by different names (Habeck, Robert Habeck, Kanzler Habeck, Herr Habeck), and it gets its own final tier.

A rule can't do it, for two reasons that both come out of the data. Common given names are ordinary dictionary words, so Robert, Olaf and Friedrich read as generic terms rather than the halves of a name a filter should protect. And Whisper mishears first names, so Baerbock turns up under Alina, Anna and Annalena Baerbock, which look like three different people. String similarity actively misleads here.

So, as with Tier 3's hard cases, the decision is made from evidence. A candidate cluster is every entity sharing a surname where at least one full-name form is typed Person. The reasoning model is then shown example sentences for each form and asked which of them refer to the same person in this corpus. It merges those, keeps genuinely different people who happen to share a surname apart, and discards things that only borrow the name (Hass gegen Habeck is an event, Bundesregierung Scholz an institution). Crucially it is allowed only to add merges, never to split what the earlier tiers settled, so a confused answer costs nothing. In the production graph this is the step that folds the bare Habeck into Robert Habeck: the person's 200-plus connections stop being split across two nodes and land on one.

How this was made. The pipeline and the articles you're about to read were both created with AI assistance. Responsibility for both, and especially for the statements made in the articles, lies with me. I acknowledge and respect that many people, for ethical or other reasons, will not want to consume content that was created in part or wholly using LLMs. This is your notice. My intent is to inform, not deceive.

Close