← Back to list

Corrective RAG in the Real World: How CRAG Tames Bad Retrievals, Filters Noise, and Slashes LLM…

CRAG (Corrective Retrieval-Augmented Generation) is a plug-and-play framework that makes RAG systems more robust when retrieval goes wrong.

Mudassar Hakim · 2026-02-08 17:06 · 0 claps · 7.3 min read
#crag #rags #llm #retrieval
Open on Medium ↗
Wiki topics: LLM · Large Language Models RAG · RAG & Retrieval EVAL · Evaluation & Benchmarks

Corrective RAG in the Real World: How CRAG Tames Bad Retrievals, Filters Noise, and Slashes LLM Hallucinations

CRAG (Corrective Retrieval-Augmented Generation) is a plug-and-play framework that makes RAG systems more robust when retrieval goes wrong.

It adds a small retrieval evaluator (fine-tuned T5-large) in front of the generator to judge the quality of retrieved documents for each query. Based on per-document relevance scores, it assigns an overall confidence and triggers one of three actions:

  • Correct: At least one document is confidently relevant. CRAG runs a decompose–then–recompose knowledge refinement step: split documents into smaller “strips”, score each strip with the evaluator, filter irrelevant ones, and concatenate the top relevant strips into a compact internal knowledge context.
  • Incorrect: All retrieved documents score below a lower threshold. CRAG discards them and falls back to web search (using a rewritten keyword-style query, prioritizing authoritative sites like Wikipedia). Retrieved web pages are again refined strip-wise with the same evaluator to form external knowledge.
  • Ambiguous: Retrieval looks neither clearly good nor clearly bad. CRAG combines both refined internal knowledge and web-search external knowledge to hedge against evaluator uncertainty.

This design explicitly tackles the case where retrievers return irrelevant or misleading passages that can induce hallucinations. Unlike typical RAG systems that blindly prepend retrieved docs, CRAG selectively filters and supplements them, aiming to “know when it doesn’t know” and seek better evidence.

The framework is evaluated by plugging it into:

  • Standard RAG (simple retrieval + generation), and
  • Self-RAG (which already learns to retrieve and critique via an instruction-tuned critic model),

using the same Contriver retriever and several LLaMA2-based generators.

On four benchmarks — PopQA (short factual QA), Biography (long-form factual biography, scored with FactScore), PubHealth (true/false medical claims), and ARC-Challenge (science multiple-choice)

CRAG consistently improves over vanilla RAG, and Self-CRAG (CRAG inside Self-RAG) improves over Self-RAG in most settings. Gains are especially strong when the underlying generator is a “plain” LLaMA2–7B (no special critic tokens), highlighting that CRAG does not require instruction-tuning the generator.

Ablations show:

  • Removing any of the three actions (Correct/Incorrect/Ambiguous) hurts performance, confirming each contributes to robustness.
  • Skipping knowledge refinement, query rewriting, or web result selection also degrades accuracy, showing that fine-grained filtering and careful web usage matter.
  • The T5-based evaluator is substantially more accurate at classifying passage relevance than prompting ChatGPT (even with CoT or few-shot), while being much smaller than modern LLMs.

CRAG adds modest computational overhead relative to basic RAG (extra evaluator passes and, sometimes, web search), but less than or comparable to Self-RAG’s critic overhead. The authors position it as a lightweight, model-agnostic correction layer that can be attached to future LLMs without retraining them, though it still requires fine-tuning the external evaluator; eliminating that dependency is left as future work.

Here are concrete, step‑by‑step examples that mirror how CRAG works in practice.

Example 1: “Correct” — Retrieval is good, just too noisy

Query: “Who was the screenwriter for ‘Death of a Batman’?”

Step 1: Retriever output (documents from a static corpus) Suppose your retriever returns 3 passages:

  1. d1:
  • “Death of a Batman is a story about the murder of Bruce Wayne’s parents…”
  • “When Sam Hamm’s script was rewritten, …”
  • “The film follows Batman as he…”
  1. d2:
  • “Batman (1989 film) is a superhero film directed by Tim Burton…”
  • “It stars Michael Keaton as Batman and Jack Nicholson as the Joker…”
  1. d3:
  • “Henry Feilden was a Conservative Party politician…”

Only ‎d1 actually contains the correct screenwriter (“Sam Hamm”). ‎d2 is loosely related (Batman film info). ‎d3 is completely irrelevant.

Step 2: Retrieval evaluator scores each (x, di) The evaluator (T5-based) sees ‎(question, doc) pairs and outputs a relevance score between -1 and 1:

  • score(d1) ≈ 0.85 (highly relevant; mentions script and Hamm)
  • score(d2) ≈ 0.35 (somewhat related to Batman, but not directly answering)
  • score(d3) ≈ -0.9 (unrelated; about a politician)

Using thresholds, say:

  • upper threshold = 0.6
  • lower threshold = -0.8

We get:

  • d1 ≥ 0.6 → relevant
  • d3 ≤ -0.8 → irrelevant
  • d2 in between → ambiguous / weak

At least one doc passes the upper threshold → overall retrieval judged “Correct.”

Step 3: Knowledge refinement: decompose–filter–recompose

CRAG does not just dump all docs into the generator. It refines:

  1. Decompose each doc into smaller strips:
  • From ‎d1:
  • strip 1: “Death of a Batman is a story about the murder of Bruce Wayne’s parents…”
  • strip 2: “When Sam Hamm’s script was rewritten, …”
  • strip 3: “The film follows Batman as he…”
  • From ‎d2, similar short strips; ‎d3 may be ignored early due to low relevance.
  1. Score each strip with the evaluator:
  • strip 2 (mentions “Sam Hamm’s script”) might get 0.9
  • strip 1, strip 3 might get, say, 0.4 or 0.1
  • strips from ‎d2 around 0.2–0.4
  • strips from ‎d3 around -0.8 or worse
  1. Filter: keep only strips above a strip threshold (e.g., -0.5, or top‑k strips). That retains the line(s) about “Sam Hamm’s script” and maybe the main description of Death of a Batman, while dropping Feilden and most generic Batman trivia.
  2. Recompose: concatenate the kept strips in order into a compact internal context, e.g.:

“Death of a Batman is a story … When Sam Hamm’s script was rewritten …”

This is the internal knowledge fed to the generator.

Step 4: Generation

Prompt to the LLM looks like:

Question: Who was the screenwriter for ‘Death of a Batman’? Context: [refined strips mentioning Sam Hamm]

The LLM now has a short, on‑point context emphasizing “Sam Hamm,” and is much more likely to output:

“Sam Hamm was the screenwriter for ‘Death of a Batman.’”

Without CRAG, a naive RAG might feed all three documents to the LLM, including the completely irrelevant ‎d3, and the model might get distracted or hallucinate.

Example 2: “Incorrect” — Retrieval is bad, switch to web search

Query: “What is Henry Feilden’s occupation?”

Step 1: Retriever output from your static knowledge corpus

Imagine the retriever fails and returns mainly Batman‑related documents (like the earlier ones) and nothing about Henry Feilden:

  1. d1: Batman (1989 film) plot
  2. d2: Another Batman comic article
  3. d3: A random movie review mentioning “Feilden Street” but not Henry Feilden the person

Step 2: Evaluator scores them all low

The evaluator’s scores:

  • score(d1) ≈ -0.4 (somewhat text‑similar but not answering “occupation”)
  • score(d2) ≈ -0.6
  • score(d3) ≈ -0.7

All are below the upper threshold (0.6), and suppose all are also below the lower threshold (-0.3 or similar — exact value is config‑dependent). So no doc is considered clearly relevant.

Result: overall retrieval judged “Incorrect.”

Step 3: CRAG discards the retrieved docs and goes to the web

Instead of forcing the LLM to answer from bad retrieval, CRAG does:

  1. Query rewriting: A smaller LLM (ChatGPT in the paper) rewrites the question into keyword‑style query:
  • Input: “What is Henry Feilden’s occupation?”
  • Output: “Henry Feilden, occupation”
  1. Web search with that query (via a web search API), prioritizing authoritative sources (e.g., Wikipedia pages with that person’s name). You might get URLs like:
  • A Wikipedia page for Henry Feilden (Conservative politician)
  • Maybe a second Henry Feilden (e.g., cricketer) — CRAG will handle by scoring.
  1. Content extraction and refinement (same as internal):
  • Fetch page text.
  • Segment into paragraphs/strips.
  • Use the evaluator to score each strip against the original question.
  • Keep highly relevant strips, e.g.:“Henry Master Feilden was a Conservative Party politician…”⁠
  • Now this is external knowledge.

Step 4: Generation based on external knowledge

The generator sees:

Question: What is Henry Feilden’s occupation? Context: “Henry Master Feilden was a Conservative Party politician …”

It answers:

“He was a Conservative Party politician.”

Here CRAG’s key behavior is: once it detects that the original RAG retrieval is low‑quality, it abandons it and uses web‑augmented retrieval instead of trying to improvise an answer from irrelevant text (which would likely cause hallucination).

Example 3: “Ambiguous” : Mixed or uncertain retrieval, combine internal & web

Query: “Where was Billy Carlson born?”

Assume the corpus has some biographical snippets, but they’re incomplete.

Step 1: Retriever output

  1. d1:
  • “Billy Carlson was an early American racecar driver. He competed in several events in the 1910s …”
  • No birth city or location.
  1. d2:
  • Contains a table of race results for “Carlson, Billy” but no birthplace.
  1. d3:
  • A random sports article mentioning “Carlson” but not clearly about Billy Carlson.

Step 2: Evaluator scores

Scores might be:

  • score(d1) ≈ 0.45 (mentions the same person, but doesn’t answer the birth city)
  • score(d2) ≈ 0.3 (related but not answering)
  • score(d3) ≈ -0.5 (likely irrelevant)

No document crosses the upper threshold (say 0.6), but at least some docs are not strongly negative (above lower threshold). So the evaluator is unsure: these docs are about the right entity but may not contain the needed fact.

Result: overall retrieval judged “Ambiguous.”

Step 3: Ambiguous action: use both internal and external

For Ambiguous, CRAG:

  1. Internal path (as if Correct):
  • Decompose ‎d1 and ‎d2 into strips.
  • Keep those that mention “Billy Carlson,” his race career, etc.
  • This gives partial context like “Billy Carlson was an early American racecar driver…”
  1. External path (as if Incorrect):
  • Rewrite question to query: “Billy Carlson, born, city”
  • Web search that.
  • Fetch potential sources (e.g., a racing history site, Wikipedia).
  • Segment and score strips to find lines like:“Billy Carlson was born in [City], [State].”
  1. Combine internal + external:
  • Internal knowledge: ensures the model has the broader context that this Billy Carlson is a racecar driver (disambiguation, avoiding mixing with other Carlsons).
  • External knowledge: provides the exact birth city.

The concatenated knowledge passed to the generator might look like:

“Billy Carlson was an early American racecar driver … Billy Carlson was born in [City], [State] …”

Step 4: Generation

The LLM now:

  • Uses internal context to ensure it’s the right Billy Carlson (racecar driver).
  • Uses external context to pull the correct birthplace.

So it answers:

“He was born in [City], [State].”

Without Ambiguous mode, you’d either:

  • Trust internal only and hallucinate a city, or
  • Trust external only and risk mixing up individuals if the name is ambiguous.

Ambiguous blends both to reduce risk.

Example 4: Impact of CRAG when retrieval quality drops

To see robustness, imagine a PopQA‑style system deployed in production.

Baseline (Self-RAG):

  • Works well when retriever is strong (e.g., top‑k docs often contain the answer).
  • As retrieval quality degrades (index stale, documents missing, etc.), the generator still tries to answer from whatever it gets.
  • Result: accuracy drops sharply because the model hallucinates over irrelevant context.

With CRAG (Self-CRAG):

  • When retrieval is good → behaves like Example 1: refine and use internal knowledge.
  • When retrieval is very bad → behaves like Example 2: discard bad docs and switch to web.
  • When retrieval is partially good → behaves like Example 3: combine both.

In the paper’s experiment on PopQA, they explicitly simulated worse retrievers by randomly removing some correct passages. As the retrieval accuracy went down:

  • Self-RAG’s answer accuracy fell quickly.
  • Self-CRAG’s accuracy decreased more slowly, showing graceful degradation rather than collapse.

This illustrates CRAG’s design goal: generation quality should not be tightly coupled to retriever quality; instead, the system should recognize bad retrieval and correct for it.

These examples together capture the core behavior:

  • Evaluate retrieved docs with a small scorer.
  • Trigger Correct / Incorrect / Ambiguous actions.
  • Refine internal knowledge, optionally augment with web, and only then let the LLM generate.

Ref: https://arxiv.org/pdf/2401.15884


메타데이터
post_id
1c102e3e57d1
slug
corrective-rag-in-the-real-world-how-crag-tames-bad-retrievals-filters-noise-and-slashes-llm-1c102e3e57d1
url
https://medium.com/@mudassar.hakim/corrective-rag-in-the-real-world-how-crag-tames-bad-retrievals-filters-noise-and-slashes-llm-1c102e3e57d1
canonical_url
https://medium.com/@mudassar.hakim/corrective-rag-in-the-real-world-how-crag-tames-bad-retrievals-filters-noise-and-slashes-llm-1c102e3e57d1
author_url
https://medium.com/@mudassar.hakim
status
ok
fetched_at
2026-06-15 20:49:13