· 8 min read

Don't Make the LLM Normalize Your Entities — Land Them on Master Records Instead


Table of Contents

You point an LLM at a pile of documents and ask it to pull out the companies mentioned. It does. And then you notice the same company came out four different ways — the English acronym in one doc, a phonetic spelling in another, a descriptive “that overseas vendor” in a third. Now your search filter is broken, because filtering on one spelling misses the other three.

The tempting fix is to hand the LLM a normalization dictionary right there in the prompt: “when you see any of these, output the canonical form.” Feels clean. It’s usually the wrong move — and if your system already has master data, it’s clearly the wrong move.

The real problem is convergence, not extraction

Let’s be precise about what’s actually broken. The LLM is good at finding the company. The pain is that it doesn’t spell it the same way twice. That’s a convergence problem — you need every mention of one real-world thing to collapse onto one identifier.

Asking the LLM to converge, via a dictionary in the prompt, kind of works. But now you own that dictionary. Every new acronym, every new subsidiary, every spelling you didn’t anticipate — you’re maintaining a list, forever, and hoping the model actually follows it. You’ve turned a data problem into a prompt-babysitting problem.

If you have master data, converge on the ID — not the text

Here’s the thing a lot of teams walk right past: you probably already have the canonical list. It’s your master data — the account records, the vendor registry, whatever your system of record calls it. That list is the set of canonical identities.

So don’t make the LLM converge the text. Map each extracted mention onto a master record, and converge on the record ID instead. “That overseas vendor,” the acronym, the phonetic spelling — all three resolve to the same account ID, and your search filter becomes an exact ID match. Dead simple, fully deterministic, and you’re not maintaining a dictionary anymore, because the master data was already being maintained for other reasons.

Three things make this stronger than LLM normalization:

  • You can bolt on a deterministic signal. A structured clue — say, the sender’s email domain — can nail the match without the model guessing at all. Structure first, model second.
  • No double bookkeeping. The master is your organization’s source of truth regardless. A prompt dictionary would be a second, competing copy you’d have to keep in sync. Skip it.
  • It self-heals. New spelling shows up next month? Doesn’t matter. As long as it resolves to the master record, the master stays the single point of truth and absorbs it.

But master data has a hole: the things that aren’t in it

Here’s where it gets interesting, and where “just map to master” as a blanket rule falls apart.

Master landing only catches entities that have a record. Competitors, prospects you haven’t done business with yet, an equipment or materials vendor mentioned in passing — these show up in your documents but not in your account list. Map only to master, and every one of them vanishes from your search axis. Someone searches for that competitor and gets nothing, not because it wasn’t mentioned, but because it had nowhere to land.

The fix isn’t to drop the LLM extraction — it’s to split the roles. Master landing takes the normalization burden for known entities. The LLM extraction field stays, but with a much humbler job: pull the name exactly as written, no normalization, as a lightweight backup net. Then at query time you run a two-step: try the master match first, and if it comes up empty, fall back to a loose match against that raw-text field.

That two-layer shape — a controlled axis plus an uncontrolled net — is the actual backbone here. One layer is clean and deterministic and covers your known world; the other is messy and forgiving and catches everything else.

”Then why extract the axis at all?” — the objection worth answering

Fair pushback: if the messy net catches things anyway, why bother pulling a structured axis? And honestly, in the happy case — the exact string, preserved in the text — they’re a tie. The net finds it, the axis finds it, same result.

The axis earns its keep everywhere the happy case doesn’t hold:

  • It covers spelling variants. The axis was resolved once, at ingest, with full context around it. The net can’t match a spelling it’s never literally seen; the axis already collapsed those.
  • It answers questions the net structurally can’t. “Which vendors are showing up across all this traffic?” isn’t a find query, it’s a list/aggregate query. A substring net can only find — it can’t enumerate. The axis can.
  • It separates topic from mention. The net can’t tell whether a company is the subject of the document or just brushed past in a signature line. The resolved axis can.
  • It survives the summary. If you search over summaries (and summaries drop things), an axis extracted straight from the original outlives whatever the summary threw away.

The one-liner I keep coming back to: the net only finds; the axis organizes. That’s the whole justification for carrying both.

Cardinality: let the machine over-catch, let a human trim

One more design fork, and it’s a quiet trap. When you map a document to master records, do you map it to one (the primary entity) or all of them (every entity mentioned)?

For search, it has to be all of them. Map a document that mentions two companies to only the “primary” one, and it disappears the moment someone searches for the second. And here’s the deeper reason: the machine can’t reliably tell which relationship is the “real” one anyway. So don’t ask it to. Relate the document to everything it mentions, and let a human trim the noise later through review.

That’s the principle underneath a lot of this: search wants recall first — don’t-miss-things first — and precision gets sharpened by a person afterward. Demand precision from the machine up front and you pay for it in recall. Over-catch by design; trim by hand.

Frequently asked questions

How do I normalize entity names extracted by an LLM? Often you shouldn’t normalize them in the LLM at all. If you already have master data — an account list, a vendor registry — resolve each extracted mention to a master record and converge on the record ID, not the text. That turns normalization from a probabilistic LLM judgment into a deterministic mapping, and it kills the prompt-dictionary maintenance burden entirely.

Why not put a normalization dictionary in the prompt? Because then you own that dictionary forever — every new acronym, subsidiary, and spelling you didn’t anticipate — and you’re hoping the model follows it. If you have master data, that list is already your canonical set of identities. Converge on its IDs instead of maintaining a second, competing copy inside a prompt.

How do I handle entities that aren’t in my master data? Split the roles. Master landing takes normalization for known entities; keep a lightweight LLM field that extracts the name exactly as written (no normalization) as a backup net for competitors, prospects, and vendors that have no record. At query time, try the master match first, then fall back to a loose match on the raw-text field. A controlled axis plus an uncontrolled net.

Should a document map to one entity or all entities it mentions? All of them. Map a document to only its “primary” entity and it vanishes the moment someone searches for the second one mentioned. The machine can’t reliably tell which relationship is the “real” one anyway, so relate the document to everything it mentions and let a human trim later. Search wants recall first; precision gets sharpened by a person afterward.

Takeaway

When an LLM keeps spelling the same entity five ways, the instinct is to teach it the right spelling. Don’t. If you already have master data, that’s your canonical list — resolve mentions to record IDs and let convergence happen on the ID, not the text. Keep a raw-text extraction field as a backup net for the entities master data doesn’t know about, run master-first-then-fallback at query time, and map to every entity mentioned rather than guessing the primary one. The net finds; the axis organizes; the human trims. Nobody’s babysitting a dictionary.

Related: this leans on the same structured-key-plus-fuzzy-content pattern as deduplicating events that arrive many times over, and it’s the entity-axis counterpart to building a topic taxonomy — different convergence strategy for a different kind of field.