Lazy loaded image5.4 Enterprise-level RAG Practice (I)

How can we search the wanted key information from 10,000+ pages of PDFs within 2.5 hours? For fact check, how do we implement it so that answers are backed by page-level references, minimizing hallucinations?

5.4.1 Key Components

  1. PDF Parsing to Plain Text (in JSON format): Customized Docling, an IBM-developed PDF parser.
    1. Used GPU acceleration via Runpod to parse 15,000 pages in under 40 minutes.
  1. Text Cleaning:
    1. Used OCR for non-regularly organized text and documents with Caesar cipher
      1. 🔍
        The Caesar Cipher is one of the simplest and oldest encryption techniques, and it is a type of substitution cipher. It is named after Julius Caesar, who used this method of encryption in military communications.
        The Caesar Cipher encrypts a message by shifting each letter in the alphabet by a fixed number of positions. For example: If the shift amount is set to 3
        • Plaintext: A B C D E
        • Ciphertext: D E F G H
        It has Encryption formula
        Where:
        • C: Ciphertext character
        • P: Numeric value of the plaintext letter
        • k: Key (shift amount)
        And Decryption formula:
  1. Format Conversion:
    1. The cleaned JSON format is then converted to Markdown and HTML formats
  1. Ingestion:
    1. Converted Markdown text into 300-token chunks with 50-token overlap using RecursiveCharacterTextSplitter from LangChain.
      1. To facilitate page reference, each chunk stores its ID and the parent page number is in its metadata.
    2. Vecterization using text-embedding-3-large
    3. Created separate FAISS vector databases for each company to ensure precise data isolation. 100 companies = 100 vector databases.
  1. Retrieval:
    1. Retrived top-30 chunk search.
    2. Parent Page Retrieval: the full pages corresponding to the most relevant chunks are used as context
    3. Reranking pages using LLM scoring (GPT-4o-mini) with structured prompts and weighted scores (70% LLM, 30% embedding relevance).
      1. LLM scoring (in increments of 0.1) 0 = Completely Irrelevant: The block has no connection or relation to the query.
        0.1 = Virtually Irrelevant: Only a very slight or vague connection to the query.
        0.2 = Very Slightly Relevant: Contains an extremely minimal or tangential connection. …
    4. Select top-10 pages
    5. notion image
  1. Augmentation:
    1. Used modular prompts stored in Python scripts.
        • System prompts as general instructions
        • Pydantic schema as expected response format
        • QA examples as few-shot prompting
        • Template for provided context and user question
      notion image
  1. Generation:
    1. Applied Structured Output (SO) with Chain of Thought (CoT) prompting.
    2. Crafted type-specific prompts (e.g., numeric, boolean, names) based on the expected answer format.
    3. For complex comparisons (e.g., between companies), used query decomposition.
<ins/>

5.4.2 Hands-on Practice

The original repo includes a simple example of RAG using 5 PDFs, but even which requires a good GPU for fast PDF parsing. Otherwise, you may not see a result within a reasonable time if you run it on Colab with T4 GPU.
So, in this section, we will use a few short PDFs to demonstrate how you can use this superior pipeline of RAG on your own data!
  1. Pull the repo and install necessary packages (Colab recommended)
    1. After which, you may have to restart the session in order to use newly installed versions.
  1. Move to the project path and set your OpenAI API
    1. Just replacing the YOUR_OPENAI_API_KEY below with your API
  1. Download the documents that you want to ask about
    1. Here we use two papers (ResNet and Transformer) as demonstration
  1. Prepare a simple meta info file and create the pipeline
    1. Note that the sha1 could be any string that’s matched to your file name. Previously we save the papers into ResNet.pdf and Transformer.pdf, so we set it like this. If you want to calculate sha1 for it, feel free to go and rename the file names to their corresponding sha1.
  1. Parse the paper PDFs!
    1. Then you can find the parsed papers in the JSON format as shown below.
      notion image
  1. Merge the parsed texts
    1. Because the parsed PDFs are in pieces, we need to merge them into pages for later chunking.
      You can observe the merged content is ordered by page number.
      notion image
  1. As we said before, then we convert them to the Markdown format (Just for visualization).
    1. The complete markdowns can be found here for the ResNet and the Transformer. You can observe it’s actually reasonably good!
  1. Let’s chunk the documents now!
    1. The chunking is done on previous merged JSON format using RecursiveCharacterTextSplitter. You can see that each page is chunked into multiple chunks, each of which does not exceed 300 tokens.
      notion image
  1. The last step before asking is to vectorize them for storage.
    1. After all of the above steps, we will end up with the files shown below. All we need are the .faiss files for retrieval.
      notion image
      <ins/>
  1. Prepare your questions and start the RAG!
    1. Here we ask 3 questions, each with a different required output format: a number, a name, and a boolean. Let’s see how this RAG system would perform on them by running the code below.
      You may observe outputs like
      Open the answer JSON file, you will obtain:
      • The answer for the first question: What's the best BLEU score of the Transformer on the English-to-French newstest2014 test?, is given as 41.8, with reference to the 8th page (index 7, starting from 0). Let’s check the paper on page 8: it’s correct!
        • notion image
      • The answer to the second question: Who is the first author of the ResNet paper?, is given as Kaiming He, which is referenced on the first page (index 0) and is obviously correct.
      • As for the third question: Is the ResNet paper published before the Transformer?, the answer is given as Yes, and we can see the referenced pages include both papers and the corresponding first page.
What’s the cost?
In my case, a single run for 3 questions consumes about 100,000 tokens and costs around $0.1, but with more stored PDFs and corresponding vectors in the database, the cost may increase non-linearly. Alternative solutions could be using locally hosted LLMs instead of o3-mini, and open-source embedding models instead of text-embedding-3-large.
notion image
A complete Colab code of all above sections can be found here
📌
Warning
In this tutorial, we simply replaced the PDFs with ours and didn’t modify the code, and it works fine. But if you plan to use it in real-world scenarios, you will absolutely want to modify the hard-coded prompts, which are specifically customized for the challenge.
For example, here is a prompt for the final answer. You may want to change the company or product to fit your needs. The prompts can be found in this file.
notion image
Prev
5.3 Retrieval-Augmented Generation (RAG)
Next
5.5 Enterprise-level RAG Practice (II)
Loading...
Article List
LLM Learning Roadmap
✨ Awesome-Anything
🖼️ Digital Image Processing
🍃 LLM Components
🌱 LLM Pre-training
☘️ LLM Post-Training
🍀 LLM Popular Models
🪴 LLM Applications
🌿 LLM Optimization
🌾 LLM Compression
🌵 LLM Hands-on Practice
🌴 LLM Must-read Papers
🌳 LLM Q&A
🐝 VLM Image Encoders
📝 MISC.