DEV Community

MartinsMessias
MartinsMessias

Posted on AI-assisted

Why Flat-Text PDF Parsing Breaks RAG (And How Spatial 2D Grounding Fixes It)

When building Retrieval-Augmented Generation (RAG) pipelines, the standard ingestion step usually looks like this:

  1. Read a PDF file.
  2. Dump all text content into a single flat string.
  3. Split the string into 500-token chunks with some overlap.
  4. Generate vector embeddings and store them in a vector database.

While this works for simple blog posts or single-column articles, it breaks down completely when applied to production documents like financial reports, scientific papers, and legal contracts.

The Three Hidden Failures of Flat-Text Ingestion

1. Table Flattening

PDF files do not store tables as HTML table elements or markdown grids. They store independent text strings positioned at absolute coordinates, combined with vector stroke lines.

When a standard parser strips away positioning, rows and columns collapse into a single stream. A table comparing quarterly revenues across three divisions becomes a scrambled sequence of numbers. By the time your chunk reaches an LLM, the relational context is destroyed.

2. Multi-Column Reading Order

Dense academic papers and annual reports frequently use two-column or three-column layouts. A naive parser reads across horizontal bands, interweaving sentences from the left column with sentences from the right column. The resulting embeddings represent garbled nonsense.

3. The Lack of Visual Provenance

When an LLM produces a critical answer, such as an interest rate or an EBITDA figure, users need to verify it. If your RAG system only stores raw text chunks, the best you can show the user is a quoted string. You cannot point to the exact page, line, or table cell where the
fact originated.

The Current Trade-off: Fast and Blind vs. Accurate and Slow

Right now, developers face two extremes:

• Legacy C-based Parsers (PyMuPDF, Poppler, PDFium): Extremely fast, but originally designed for rendering pixels onto desktop screens rather than feeding structured spatial trees into AI pipelines. They also introduce heavy C/C++ compilation toolchains, breaking in
lightweight container environments.
• Vision-Language Models and OCR (Marker, Docling, Nougat): These rasterize pages into images and run deep learning models to predict layout. While accurate, they require GPUs, cost significant compute per page, and introduce seconds of latency per document.

The Alternative: Spatial RAG with Native 2D Grounding

The coordinate geometry needed to reconstruct document structure already exists inside the PDF content streams, you do not need a GPU to rediscover it.

This is why I built RasgaPDF (https://github.com/MartinsMessias/rasgapdf): a lightweight, pure Rust PDF engine built specifically for Spatial RAG.

Instead of outputting an unstructured string, the engine reconstructs the document as a spatial 2D hierarchy with exact coordinates:

{
  "page_number": 1,
  "width": 612.0,
  "height": 792.0,
  "rotation": 0,
  "text_blocks": [
    {
      "bbox": { "x0": 60.0, "y0": 70.6, "x1": 384.6, "y1": 82.7 },
      "lines": [
        {
          "bbox": { "x0": 60.0, "y0": 70.6, "x1": 384.6, "y1": 82.7 },
          "text": "Revenue increased by 14% year-over-year..."
        }
      ]
    }
  ],
  "tables": [
    {
      "bbox": { "x0": 60.0, "y0": 121.0, "x1": 540.0, "y1": 245.0 },
      "markdown": "| Metric | 2025 | 2026 |\n| --- | --- | --- |\n..."
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Visual Citation in User Interfaces

Because every chunk retained its physical bounding box ([x0, y0, x1, y1]), your frontend can render the original PDF page and draw an exact translucent highlight over the source passage. The user gets instant, trustworthy verification without hunting through a 50-page
document.

Pure Rust: Zero C/C++ Toolchains

By implementing the ISO 32000-1 specification natively in safe Rust:

• cargo build and pip install work without MSBuild or C compiler installations.
• Memory safety is enforced at compile time.
• A dense 12-page academic paper parses in approximately 15 ms on a single CPU core.

Native Integration with LangChain and LlamaIndex

You do not need to write custom spatial wrappers. RasgaPDF integrates directly into standard AI orchestrators:

    from rasgapdf import RasgaPDFLoader

    # Load with physical 2D metadata preserved in every Document chunk
    loader = RasgaPDFLoader("financial_report.pdf", mode="elements")
    docs = loader.load()

    first_chunk = docs[0]
    print(first_chunk.page_content)
    print(first_chunk.metadata["bbox"])
   # {'x0': 60.0, 'y0': 70.6, 'x1': 384.6, 'y1': 82.7}
Enter fullscreen mode Exit fullscreen mode

Conclusion

If your RAG system is hallucinating data or failing on complex documents, the problem is often not your embedding model or prompt, it is flat-text ingestion destroying spatial context before the model ever sees it.

Preserving 2D physical coordinates gives you reliable tables, accurate reading order, and verifiable visual citations at native speed.

• GitHub: https://github.com/MartinsMessias/rasgapdf
• Interactive Playground: https://martinsmessias.github.io/rasgapdf/

How are you currently handling table extraction and citation verification in your RAG pipelines? Let us discuss in the comments below.

Top comments (0)