---
title: "Anti-Hallucination via Runtime Grounding Against a Domain Vocabulary"
canonical_url: "https://cognilium.ai/blogs/anti-hallucination-domain-vocabulary-grounding"
slug: "anti-hallucination-domain-vocabulary-grounding"
section: "blogs"
date_published: "2026-05-05"
date_modified: "2026-05-05"
word_count: 1300
reading_time_minutes: 6
author: "Mudassir Marwat"
author_identifier: "0009-0008-1927-2598"
person_same_as:
  - "https://www.linkedin.com/in/mudassir-marwat/"
  - "https://orcid.org/0009-0008-1927-2598"
  - "https://github.com/mudassirmarwat"
  - "https://medium.com/@mudassir-marwat"
  - "https://www.youtube.com/@mudassir-marwat"
  - "https://dev.to/mudassirmarwat"
  - "https://hashnode.com/@mudassirmarwat"
  - "https://huggingface.co/mudassirmarwat"
  - "https://bsky.app/profile/mudassir-marwat.bsky.social"
  - "https://substack.com/@mudassirmarwat"
  - "https://topmate.io/mudassirmarwat"
  - "https://fueler.io/mudassirmarwat"
  - "https://www.instagram.com/mudassirmarwat/"
  - "https://www.facebook.com/mudassir.marwat"
  - "https://www.reddit.com/user/mudassirmarwat/"
  - "https://www.f6s.com/member/mudassir-marwat"
  - "https://cognilium.ai/founder"
entities: []
related:
  - "https://cognilium.ai/blogs/8-stage-docint-pipeline"
  - "https://cognilium.ai/blogs/zero-trust-multi-tenant-firestore"
  - "https://cognilium.ai/blogs/organizational-memory-rag-slack-confluence-loom"
---
# Anti-Hallucination via Runtime Grounding Against a Domain Vocabulary

A startup-loaded domain vocabulary the generator must match against, plus framework rules baked into every prompt — a low-cost pattern that catches hallucinated terminology before the user sees it.

Domain-specific generation has a recurring failure mode: the LLM produces output that is fluent and confident but uses terminology that does not exist in the domain. A K-12 writing methodology has 298 specific terms; the generator may produce "voiceful sentence" or "stylistic figure" — words that sound right and are not in the framework. End users notice, trust evaporates.

A validator that runs at output time and compares generated terminology against a startup-loaded vocabulary catches this before the user sees it, at 2-5ms of latency. The pattern is cheap and underused.

## Vocabulary loading

At process startup, the validator loads the domain vocabulary from a versioned source — for our K-12 system it is a 298-term file extracted from the framework documentation. The vocab is parsed into a set with synonyms and inflection variants pre-computed. Total size: ~2KB in memory.

## Validation flow

Every generated output gets one validation pass. The pass runs the structured output through a regex-based extractor that finds named-entity-style terms (capitalized, multi-word, or matching domain patterns). Each extracted term is checked against the vocabulary set.

- Match: pass.
- No match, fuzzy-match within edit distance 1: log + auto-correct (covers typos in generation).
- No match, no fuzzy match: validation fails.

## What happens on failure

Failure triggers a retry with a stricter prompt that lists the allowed vocabulary inline ("Use only these terms for craft elements: ..."). After two retries the system falls back to the closest valid term by embedding similarity and flags the output for human review. The flag goes to a queue; an editor sees the original prompt, the failed generation, and the auto-correction within hours.

## Why not just put the vocabulary in the system prompt?

You can. It costs tokens on every call. With 298 terms (roughly 4KB of text), that is ~1,000 tokens per request times every request. The validator approach loads the vocab in process memory and keeps system prompts short. The cost trade is real and worth measuring.

## What we measured

- Validation latency: 2-5ms (regex + set lookup, no LLM call)
- Hard-fail rate after two retries: <0.5%
- False positives caught (terms LLM invented): ~3-5% of raw generations
- Vocab size: 298 terms, ~2KB resident memory
- Editor flag queue: ~10-20 items per day at 30K queries/month, manageable for a part-time reviewer

## Frequently asked questions

### How is this different from a regular eval?

Evals run offline on a sample. This runs online on every output, before delivery, in <100ms. It is a validator, not a measurement.

### What if a legitimate term is missing from the vocabulary?

The vocab is loaded at startup from a versioned source (in our case, a curated domain vocabulary file with 298 terms). New terms ship via PR; the validator never silently approves an unknown term. False positives become a curation signal.

### Why not solve this with a stronger model?

You can. GPT-4o hallucinates terms less than GPT-4o-mini. But cost and latency triple. The validator lets you keep the cheaper model for generation and pay 2-5ms of validation overhead instead.

### What happens when validation fails?

The system retries the generation with a stricter prompt that lists the allowed vocabulary inline. After two retries, it falls back to the most-similar valid term and flags the output for human review. Hard fail rate: <0.5%.

### Does this work for free-form prose?

Less well. It works best when the output is structurally constrained — terminology must come from a known set. For free-form prose, use it on the named-entity layer (only check that proper nouns and technical terms match the vocab) and let the connective tissue be free.

---

Canonical HTML: https://cognilium.ai/blogs/anti-hallucination-domain-vocabulary-grounding
