<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/one-rag-pipeline-four-very-different-pdfs-same-four-bricks-every-answer-typed-and-cited-usztm5tae" -->

---
title: One RAG Pipeline, Four Very Different PDFs: Same Four...
description: A production RAG pipeline composed of four independent bricks — document parsing, question parsing, retrieval, and generation — is tested end-to-end on four...
canonical: https://daily.dev/posts/one-rag-pipeline-four-very-different-pdfs-same-four-bricks-every-answer-typed-and-cited-usztm5tae
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: One RAG Pipeline, Four Very Different PDFs: Same Four Bricks, Every Answer Typed and Cited | daily.dev
og:description: A production RAG pipeline composed of four independent bricks — document parsing, question parsing, retrieval, and generation — is tested end-to-end on four...
og:url: https://daily.dev/posts/one-rag-pipeline-four-very-different-pdfs-same-four-bricks-every-answer-typed-and-cited-usztm5tae
og:image: https://api.daily.dev/og/posts/UsZtM5tAe.png
og:image:alt: One RAG Pipeline, Four Very Different PDFs: Same Four Bricks, Every Answer Typed and Cited
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# One RAG Pipeline, Four Very Different PDFs: Same Four Bricks, Every Answer Typed and Cited

**[Towards Data Science](https://daily.dev/sources/tds)** · 29 min read · 1 upvotes · 0 comments

## Summary

A production RAG pipeline composed of four independent bricks — document parsing, question parsing, retrieval, and generation — is tested end-to-end on four structurally different PDFs without any code changes. The pipeline handles a research paper (Attention Is All You Need), the NIST Cybersecurity Framework 2.0, the original RAG paper, and a World Bank report with a broken table of contents. Each brick communicates via typed Pydantic contracts, enabling composability and auditability. The pipeline correctly answers three documents with cited spans and honestly declines the fourth when retrieval fails due to blank TOC bookmarks. A comparison against a naive keyword/embedding baseline shows the upgraded pipeline's advantage on longer, vocabulary-mismatched compliance documents, where naive RAG either returns nothing or hallucinates from wrong context. The core argument is that most RAG hallucinations are retrieval failures, and structured context engineering across all four bricks is the fix.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://towardsdatascience.com/one-rag-pipeline-four-very-different-pdfs-same-four-bricks-every-answer-typed-and-cited>

## Questions this post answers

### What happens when a RAG pipeline's PDF has a table of contents with blank bookmark titles?

When every TOC entry reads as an empty or degenerate title (such as all bookmarks labeled 'Blank Page'), an LLM-based TOC router picks no sections and retrieval falls back to keyword matching alone. If the keywords only match front-matter pages rather than the relevant section, generation should return 'NA' with complete_answer_found false and confidence 0.0, rather than inventing an answer from irrelevant context.

_daily.dev surfaces retrieval-failure patterns like this for engineers hardening RAG pipelines against broken PDFs._

### Why do naive RAG systems hallucinate on long compliance documents like NIST standards?

Naive keyword-or-cosine retrieval works fine on short, well-structured documents but fails once a document is long enough or its vocabulary differs enough from the question that the answer falls below the top-k cutoff. On NIST SP 800-207, a naive baseline returned only three of seven zero-trust tenets at 0.95 confidence, treating a partial list as complete; on FIPS 199 it defined only the 'high' impact level. The failure is usually the model answering the wrong retrieved context faithfully, not inventing from nothing.

_developers debugging RAG hallucinations on long standards docs track these failure patterns via daily.dev._

### How can a RAG pipeline distinguish between a listing question and a single-answer question?

A question parsing step infers the expected answer shape from the question's wording: phrases like 'options', 'all', 'which', or 'what are' trigger a 'listing' shape dispatched to a ListAnswer schema with one item per option, while other phrasing defaults to 'single', dispatched to an AnswerWithEvidence schema with one paragraph and one citable span. The same wrapper function and four bricks handle both shapes without a separate code path.

_teams designing schema-driven RAG answer contracts can compare approaches like this one on daily.dev._

## Similar posts on daily.dev

- [A Production RAG Pipeline for PDFs: Relational Parsing, TOC Retrieval, Typed Answers](https://daily.dev/posts/a-production-rag-pipeline-for-pdfs-relational-parsing-toc-retrieval-typed-answers-vuwase0nh) · Towards Data Science · 1 upvotes · 0 comments
- [Baseline Enterprise RAG, From PDF to Highlighted Answer](https://daily.dev/posts/baseline-enterprise-rag-from-pdf-to-highlighted-answer-cwljrasn1) · Towards Data Science · 2 upvotes · 0 comments
- [10 Common RAG Mistakes We Keep Seeing in Production](https://daily.dev/posts/10-common-rag-mistakes-we-keep-seeing-in-production-dfkintj3j) · Towards Data Science · 1 upvotes · 0 comments

---

Tags: [#python](https://daily.dev/tags/python), [#llm](https://daily.dev/tags/llm), [#rag](https://daily.dev/tags/rag), [#pydantic](https://daily.dev/tags/pydantic)

[View this post on daily.dev](https://daily.dev/posts/one-rag-pipeline-four-very-different-pdfs-same-four-bricks-every-answer-typed-and-cited-usztm5tae)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"One RAG Pipeline, Four Very Different PDFs: Same Four Bricks, Every Answer Typed and Cited","url":"https://daily.dev/posts/one-rag-pipeline-four-very-different-pdfs-same-four-bricks-every-answer-typed-and-cited-usztm5tae","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/one-rag-pipeline-four-very-different-pdfs-same-four-bricks-every-answer-typed-and-cited-usztm5tae"},"datePublished":"2026-07-17T11:24:43.110Z","dateModified":"2026-09-14T08:40:50.348Z","description":"A production RAG pipeline composed of four independent bricks — document parsing, question parsing, retrieval, and generation — is tested end-to-end on four...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/881f6ecca9602f5d1ef11f35f91436f7?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/881f6ecca9602f5d1ef11f35f91436f7?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Towards Data Science","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Towards Data Science","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/tds","url":"https://daily.dev/sources/tds"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/one-rag-pipeline-four-very-different-pdfs-same-four-bricks-every-answer-typed-and-cited-usztm5tae","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":1},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"python,llm,rag,pydantic","timeRequired":"PT29M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Towards Data Science","item":"https://daily.dev/sources/tds"},{"@type":"ListItem","position":3,"name":"One RAG Pipeline, Four Very Different PDFs: Same Four Bricks, Every Answer Typed and Cited"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/one-rag-pipeline-four-very-different-pdfs-same-four-bricks-every-answer-typed-and-cited-usztm5tae#faq","mainEntity":[{"@type":"Question","name":"What happens when a RAG pipeline's PDF has a table of contents with blank bookmark titles?","acceptedAnswer":{"@type":"Answer","text":"When every TOC entry reads as an empty or degenerate title (such as all bookmarks labeled 'Blank Page'), an LLM-based TOC router picks no sections and retrieval falls back to keyword matching alone. If the keywords only match front-matter pages rather than the relevant section, generation should return 'NA' with complete_answer_found false and confidence 0.0, rather than inventing an answer from irrelevant context. daily.dev surfaces retrieval-failure patterns like this for engineers hardening RAG pipelines against broken PDFs."}},{"@type":"Question","name":"Why do naive RAG systems hallucinate on long compliance documents like NIST standards?","acceptedAnswer":{"@type":"Answer","text":"Naive keyword-or-cosine retrieval works fine on short, well-structured documents but fails once a document is long enough or its vocabulary differs enough from the question that the answer falls below the top-k cutoff. On NIST SP 800-207, a naive baseline returned only three of seven zero-trust tenets at 0.95 confidence, treating a partial list as complete; on FIPS 199 it defined only the 'high' impact level. The failure is usually the model answering the wrong retrieved context faithfully, not inventing from nothing. developers debugging RAG hallucinations on long standards docs track these failure patterns via daily.dev."}},{"@type":"Question","name":"How can a RAG pipeline distinguish between a listing question and a single-answer question?","acceptedAnswer":{"@type":"Answer","text":"A question parsing step infers the expected answer shape from the question's wording: phrases like 'options', 'all', 'which', or 'what are' trigger a 'listing' shape dispatched to a ListAnswer schema with one item per option, while other phrasing defaults to 'single', dispatched to an AnswerWithEvidence schema with one paragraph and one citable span. The same wrapper function and four bricks handle both shapes without a separate code path. teams designing schema-driven RAG answer contracts can compare approaches like this one on daily.dev."}}]}
```

