Close Menu
AI News TodayAI News Today

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    What's Hot

    IT mistake erases 11 years of viewing history for hospitals’ maternity records

    Toyota claims plan for 400,000 factory robots won’t replace human workers

    How to Pitch AI: A Slide-by-Slide Walkthrough That Gets You a Second Meeting

    Facebook X (Twitter) Instagram
    • About Us
    • Contact Us
    Facebook X (Twitter) Instagram Pinterest Vimeo
    AI News TodayAI News Today
    • Home
    • AI News
    • AI Reviews
    • AI Tools
    • AI Tutorials
    • Chatbots
    • Free AI Tools
    • Artificial Intelligence
    AI News TodayAI News Today
    Home»AI Tools»Break Your Own RAG Pipeline Before Users Do
    AI Tools

    Break Your Own RAG Pipeline Before Users Do

    By No Comments8 Mins Read
    Share Facebook Twitter Pinterest LinkedIn Tumblr Reddit Telegram Email
    Break Your Own RAG Pipeline Before Users Do
    Share
    Facebook Twitter LinkedIn Pinterest Email

    Introduction

    Retrieval-augmented generation (RAG) answers questions using information retrieved from a set of documents. That document collection is called a corpus. A typical evaluation sends a well-written question to a tidy corpus and checks whether the retriever returns the correct passage.

    Production document collections rarely stay tidy.

    Old pages remain searchable after a policy changes. Users type “warehuse” instead of “warehouse.” Optical character recognition (OCR), the software that extracts text from scans, may read “SSO” as “SS0.” A table can also be divided at a page boundary, separating a number from its label.

    Each problem can send the retriever to the wrong passage. The language model then receives incorrect or incomplete context, so even a well-written answer may be wrong.

    In this article we will see a small retriever and fault injection, which means deliberately adding problems to test how a system responds. I added an outdated policy page, an OCR character swap, a query typo, and a divided table.

    ···

    Hey there, I’m Sara Nóbrega, an AI engineer with background in physics. If you’re working on similar problems or want feedback on applying these ideas, I collect my writing, resources, and mentoring links here).

    👉 Read: 5 AI Skills That Will Keep Data Scientists Relevant in 2027 | Towards Data Science

    ···

    Learn this step by step with the interactive AI Engineer roadmap.

    The Toy Pipeline

    A retriever searches documents and returns the passages that appear most relevant to a question. RAG systems usually divide each document into smaller passages called chunks before indexing them for search.

    This example keeps the retrieval method deliberately simple. It has 4 short documents and one scoring function. The function splits the query and each document into lowercase words, called tokens. It then gives a document 1 point for every query token found in that document. The document with the highest score wins.

    DOCS = [    Document("returns-2026", "Returns are accepted within 30 days.", "returns", "2026-02-01"),    Document("plans", "The Enterprise plan includes SSO for employees.", "plans", "2026-01-10"),    Document("crm", "CRM contact sync runs every five minutes.", "integrations", "2026-01-05"),    Document("inventory", "Warehouse inventory sync runs every 15 minutes.", "inventory", "2026-01-12"),]def tokens(text: str) -> list[str]:    return re.findall(r"[a-z0-9]+", text.lower())def score(query: str, text: str) -> float:    query_tokens, doc_tokens = tokens(query), tokens(text)    return sum(token in doc_tokens for token in query_tokens)

    Each Document stores an ID, its text, a topic, and the date it was updated. Production systems often use more complex matching methods. Exact token matching makes each failure easy to see, and the same input problems can affect those systems.

    Stale documents that contradict each other

    The returns policy changed from 60 days to 30 days at the start of 2026. The ingestion process copies source documents into a searchable index. Here, it added the new page without removing the old one.

    old_policy = Document("returns-2024", "Returns are accepted within 60 days.", "returns", "2024-08-01")contradictory_docs = [old_policy] + DOCSretrieve("How many days is the returns window?", contradictory_docs)# returns-2024

    Both pages receive the same token-overlap score because each contains “returns” and “days.” The retriever needs a rule for equal scores, known as a tiebreaker. Here it uses list order, so it returns the first page: the policy from 2024. A customer could be told they have 60 days to return an item when the current limit is 30.

    Image by Author | Claude Design.

    The correction adds a recency tiebreaker. When documents receive the same score, the retriever prefers the one with the later updated date.

    retrieve("How many days is the returns window?", contradictory_docs, prefer_latest=True)# returns-2026

    This rule fits policies with a clear replacement date. Other collections may need an explicit status such as current or retired, especially when a newer document does not replace an older one.

    OCR errors that hide the matching words

    OCR converts scanned pages into searchable text. Similar-looking letters and numbers cause common extraction errors. The faulty OCR output changes “Enterprise” to “Enterpr1se” and “SSO” to “SS0.”

    noisy_docs = [replace(doc, text=doc.text.replace("Enterprise", "Enterpr1se").replace("SSO", "SS0"))              if doc.id == "plans" else doc for doc in DOCS]retrieve("Does Enterprise include SSO?", noisy_docs)# returns-2026

    The extracted text contains enterpr1se and ss0, so the query tokens enterprise and sso each receive 0 points. All 4 documents tie at 0, and list order sends the returns policy back as the result.

    Image by Author | Claude Design.

    A normalization function corrects known OCR substitutions before tokenization. Applying it to both queries and documents gives the scorer consistent text.

    def undo_common_ocr(text: str) -> str:    return text.lower().translate(str.maketrans({"0": "o", "1": "i"}))retrieve("Does Enterprise include SSO?", noisy_docs, ocr=True)# plans

    Production normalization rules need care. Converting every 0 to o, for example, could damage product codes or measurements. Build substitutions from errors found in your own extracted documents and limit them to fields where the change is safe.

    A typo in the query

    Users make spelling mistakes. “warehuse sync” is missing one letter from “warehouse sync,” and an exact token matcher treats the 2 words as unrelated.

    retrieve("warehuse sync", DOCS)# crm

    The misspelled token contributes 0 points. This leaves sync to determine the result. Both the CRM document and the warehouse inventory document contain it, so the tie goes to the CRM document because it appears first.

    Image by Author | Claude Design.

    Fuzzy matching compares words by spelling similarity and gives close matches partial credit. With fuzzy matching enabled, warehuse is close enough to warehouse for the inventory document to score higher.

    retrieve("warehuse sync", DOCS, fuzzy=True)# inventory

    The similarity threshold matters. Set it too low and unrelated words can match; set it too high and common typos still fail. Tests based on real queries provide better thresholds than a handful of invented spelling mistakes.

    A table divided across a page boundary

    Some PDF extraction tools create one chunk per page. If a table continues onto the next page, the first chunk may contain a row label while the second contains its value.

    Image by Author | Claude Design.

    Image by Author | Claude Design.

    The first chunk contains all 3 query tokens: basic, plan, and storage, so it ranks first. Its text ends after Basic |. The value, 10 GB, is in the next chunk and may never reach the language model.

    raw_table = "Plan | StoragenBasic |10 GBnEnterprise | 1 TB"table_pages = [Document(f"limits-p{i}", page, "limits", "2026-03-01")               for i, page in enumerate(raw_table.split(""), 1)]retrieve("Basic plan storage", table_pages)# limits-p1: "Plan | StoragenBasic |"

    This correction belongs in the ingestion process. Detect table fragments and join related pages before creating searchable chunks.

    joined_text = " ".join(page.text for page in table_pages)joined_table = Document("limits-joined", joined_text, "limits", "2026-03-01")retrieve("Basic plan storage", [joined_table])# limits-joined: "Plan | Storage Basic | 10 GB Enterprise | 1 TB"

    Joining every pair of pages would create oversized chunks and mix unrelated text. Limit the rule to detected tables or carry enough neighboring content forward to preserve each row.

    Test the evidence inside each result

    The returned document ID confirms which source ranked first. An evidence check confirms whether its chunk contains enough information to answer the question. The divided table demonstrates the difference: a chunk from the correct limits document could contain Basic and Storage while leaving 10 GB on the next page.

    Add an evidence check to each test. The check names the words or values that must appear in the retrieved text for the language model to produce a supported answer.

    def assert_retrieval(result, expected_id: str, required_text: list[str]) -> None:    assert result.id == expected_id    result_text = result.text.lower()    assert all(text.lower() in result_text for text in required_text)

    The returns-policy test should require both the current document ID and the current value:

    result = retrieve(    "How many days is the returns window?",    contradictory_docs,    prefer_latest=True,)assert_retrieval(result, "returns-2026", ["30 days"])

    The table test should require the row label and its value in the same retrieved chunk:

    result = retrieve("Basic plan storage", [joined_table])assert_retrieval(result, "limits-joined", ["Basic", "10 GB"])

    These assertions also make failures easier to diagnose.

    A wrong ID points to ranking or filtering. A correct ID with missing text points to extraction or chunking. A correct ID with the required evidence gives the generation step enough source material to answer, although the final answer still needs its own evaluation.

    If your retriever returns several chunks, apply the same check to the combined text passed to the language model. The evaluated text will then match the context the model receives.

    ···

    What the 4 tests catch

    Running the 4 corrupted inputs against the basic retriever produces 4 failures. After the matching correction is enabled for each case, all 4 return the expected document.

    Image by Author | Claude Design.

    The fixes are small:

    • use document dates to resolve a tie, normalize known OCR errors,

    • allow close spelling matches, and

    • preserve table rows during ingestion.

      Each one addresses a different cause. The separate test results identify which protection is missing.

    Run these tests alongside a standard relevance evaluation. Relevance tests measure whether retrieval works on expected inputs. Fault-injection tests measure whether it still works after a realistic defect is added to the query or document collection.

    The 4 cases are a starting test set. When production returns the wrong document, add a regression test: a repeatable check that confirms the bug stays fixed after later code changes.

    ···

    Thanks for reading!

    My name is Sara Nóbrega and I’m an AI engineer with background in physics.

    Useful links:

    break Pipeline RAG users
    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
    Previous ArticleProtests for Germany’s car industry as job losses loom
    Next Article Stolen passwords are exposing America’s water providers to hackers
    • Website

    Related Posts

    AI Tools

    Build Your AI Stack in One Afternoon: A Step-by-Step Guide to the Best AI Apps

    AI Tools

    Build a Speaker-Recognition App with Claude Code

    AI Tools

    4 Ways to Use AI on a PhD Thesis

    Add A Comment
    Leave A Reply Cancel Reply

    Top Posts

    IT mistake erases 11 years of viewing history for hospitals’ maternity records

    0 Views

    Toyota claims plan for 400,000 factory robots won’t replace human workers

    0 Views

    How to Pitch AI: A Slide-by-Slide Walkthrough That Gets You a Second Meeting

    0 Views
    Stay In Touch
    • Facebook
    • YouTube
    • TikTok
    • WhatsApp
    • Twitter
    • Instagram
    Latest Reviews
    AI Tutorials

    Quantization from the ground up

    AI Tools

    David Sacks is done as AI czar — here’s what he’s doing instead

    AI Reviews

    Judge sides with Anthropic to temporarily block the Pentagon’s ban

    Subscribe to Updates

    Get the latest tech news from FooBar about tech, design and biz.

    Most Popular

    IT mistake erases 11 years of viewing history for hospitals’ maternity records

    0 Views

    Toyota claims plan for 400,000 factory robots won’t replace human workers

    0 Views

    How to Pitch AI: A Slide-by-Slide Walkthrough That Gets You a Second Meeting

    0 Views
    Our Picks

    Quantization from the ground up

    David Sacks is done as AI czar — here’s what he’s doing instead

    Judge sides with Anthropic to temporarily block the Pentagon’s ban

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    Facebook X (Twitter) Instagram Pinterest
    • About Us
    • Contact Us
    • Terms & Conditions
    • Privacy Policy
    • Disclaimer

    © 2026 ainewstoday.co. All rights reserved. Designed by DD.

    Type above and press Enter to search. Press Esc to cancel.