How to Build a RAG Chatbot from a PDF: No-Code and Python Ways (Step by Step)
A RAG chatbot (Retrieval-Augmented Generation) answers questions from your document instead of from the AI's memory. It works in 5 steps: load the PDF, cut it into small chunks, index the chunks, retrieve the chunks that match the question, and let the AI generate an answer using only those chunks. The no-code way is Gemini Notebook (the new name of NotebookLM). The coding way is a 60-line Python script with pypdf, scikit-learn and the Gemini API, given below.
If you ask ChatGPT, "How many sick leaves do I get?", it cannot know. Your company's leave policy is not on the internet. If you paste the whole 80-page policy into the chat every time, it is slow and messy. RAG solves this: the computer first finds the 2 or 3 paragraphs that matter, and only then asks the AI to answer from them. In this guide you will build it twice, once with no code in 5 minutes, and once in Python so you understand every step.
Full course chapter
This guide is a quick no-code and Python project. The course chapter explains each RAG step (read, chunk, embed, retrieve, answer) with an HR policy bot, a course-notes bot and a cited-answer check. Read it here: What Is RAG? Build a Chatbot from Your Own PDF (Step by Step).
What you will learn in this guide
- What RAG means, in simple words
- The 5 steps: load to generate
- A no-code PDF chatbot
- A Python RAG chatbot you can run
- Stop the bot from inventing
- Fix common RAG problems
1. Suppose we work in HR at an IT company in Pune
Suppose we are Sneha, an HR executive at a mid-size IT company in Hinjewadi, Pune. Every week, 50 employees ask the same questions on Teams: "How many casual leaves do I get?", "Can I carry forward earned leave?", "How many days of work from home are allowed?"
All the answers are in one PDF: the leave policy. We want a chatbot that:
- Answers only from this PDF.
- Says which page the answer came from.
- Says "I could not find this" when the PDF does not have the answer, instead of guessing.
That is exactly what a RAG chatbot does.
For this guide we use a small 2-page sample policy for a made-up company, "Sahyadri Infotech". It says, for example: 12 days of casual leave, 8 days of sick leave (a doctor's certificate for more than 2 days in a row), 18 days of earned leave after 6 months, and work from home up to 2 days a week.
2. What is RAG, in simple words?
Think of an open-book exam.
- A normal chatbot is a student answering from memory. It may sound confident and still be wrong.
- A RAG chatbot is a student who first opens the book to the right page, reads it, and then writes the answer.
RAG = Retrieval (find the right pages) + Augmented (add them to the prompt) + Generation (the AI writes the answer).
Figure 1. The 5 steps of a RAG chatbot, from top to bottom: load the PDF, cut it into chunks, index the chunks, retrieve the best chunks for the question, and generate an answer from those chunks only.
| Step | What happens | In our example |
|---|---|---|
| 1. Load | Read the text out of the PDF | 2 pages of leave policy text |
| 2. Chunk | Cut the text into small pieces | About 80 words per piece |
| 3. Index | Turn each piece into numbers so it can be searched | A search index of all pieces |
| 4. Retrieve | Find the pieces that best match the question | The piece about sick leave |
| 5. Generate | Send only those pieces to the AI, with strict rules | "You get 8 days of sick leave (page 1)." |
3. Way 1: a no-code PDF chatbot with Gemini Notebook
Google renamed NotebookLM to Gemini Notebook in July 2026. It is a ready-made RAG tool: it answers from the sources you upload and shows citations.
- Open notebook.google.com (the old notebooklm.google.com address redirects there) and sign in with a personal Google account.
- Create a new notebook.
- Add a source and upload your PDF.
- Ask in the chat: "How many sick leaves do I get, and when do I need a doctor's certificate?"
- Click the small citation number in the answer. It shows the exact part of the PDF used.
On the free plan, Google's help page lists up to 100 notebooks and 50 sources per notebook (October 2026, subject to change).
Privacy: do not upload a company's internal policy to a personal account without permission. Use your company's approved tool for real company documents. For practice, use the sample policy or a public PDF.
Ravindra Bagale's Tip
Students test the bot only with questions that the PDF answers. Always ask one question that is NOT in the PDF, like "What is the salary hike policy?". A good RAG bot must say it could not find it. If it invents an answer, your rules are too weak.
4. Way 2: build it in Python (step by step)
Now let us build our own, so you understand what tools like Gemini Notebook do inside.
What you need
- Python 3.10 or newer on your laptop.
- A free Gemini API key from Google AI Studio (aistudio.google.com → API keys). Keep it private.
- Your PDF. For practice, download the sample leave_policy.pdf (2 pages, about 2 KB) used in this guide, or use any text PDF (not a scanned image). You can also download the finished script: pdf_chat.py.
Install the libraries
pip install -U google-genai pypdf scikit-learn
Set your key in the terminal (Windows PowerShell users: $env:GEMINI_API_KEY="YOUR_API_KEY"):
export GEMINI_API_KEY="YOUR_API_KEY"
The full script: save it as pdf_chat.py
# pdf_chat.py - a small RAG chatbot: ask questions about one PDF.
# Run: python pdf_chat.py leave_policy.pdf
import sys
from pypdf import PdfReader
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from google import genai
PDF_FILE = sys.argv[1] if len(sys.argv) > 1 else "leave_policy.pdf"
MODEL = "gemini-3.8-flash" # check the current model name in Google's Gemini API docs
# Step 1. LOAD: read the text of every page
reader = PdfReader(PDF_FILE)
pages = [(n + 1, page.extract_text() or "") for n, page in enumerate(reader.pages)]
# Step 2. CHUNK: cut each page into pieces of about 80 words (20 words overlap)
chunks = []
for page_no, text in pages:
words = text.split()
for start in range(0, len(words), 60):
piece = " ".join(words[start:start + 80])
if piece:
chunks.append((page_no, piece))
print(f"Loaded {len(pages)} pages and made {len(chunks)} chunks from {PDF_FILE}")
# Step 3. INDEX: turn every chunk into numbers so we can search it
vectorizer = TfidfVectorizer(stop_words="english")
matrix = vectorizer.fit_transform([text for _, text in chunks])
# Step 4. RETRIEVE: find the chunks that best match the question
def retrieve(question, top_k=3):
scores = cosine_similarity(vectorizer.transform([question]), matrix)[0]
best = scores.argsort()[::-1][:top_k]
return [(chunks[i][0], chunks[i][1]) for i in best if scores[i] > 0]
# Step 5. GENERATE: give only those chunks to the model, with strict rules
client = genai.Client() # reads your key from the GEMINI_API_KEY environment variable
def answer(question):
found = retrieve(question)
if not found:
return "I could not find this in the document."
context = "\n\n".join(f"[page {p}] {text}" for p, text in found)
prompt = (
"Answer the question using ONLY the context below.\n"
'If the answer is not in the context, reply: "I could not find this in the document."\n'
"Keep it short and mention the page number you used.\n\n"
f"Context:\n{context}\n\nQuestion: {question}"
)
result = client.interactions.create(model=MODEL, input=prompt)
return result.output_text
while True:
q = input("\nAsk a question (or type exit): ").strip()
if q.lower() == "exit":
break
if q.lower().startswith("show "): # debug: see what was retrieved
for p, text in retrieve(q[5:]):
print(f"--- page {p}: {text[:120]}...")
continue
print(answer(q))
What each step does
- Load:
PdfReaderreads the text page by page and remembers the page number. - Chunk: every page is cut into pieces of about 80 words. Each new piece starts 60 words after the last one, so the pieces overlap by 20 words. The overlap stops a sentence from being cut in half and lost.
- Index:
TfidfVectorizerturns each chunk into numbers based on its important words. - Retrieve: the question is turned into numbers the same way, and
cosine_similarityfinds the 3 most similar chunks. - Generate: only those chunks go to Gemini, with three rules: use only this context, say "I could not find this" if the answer is not there, and give the page number.
About the search method: this script uses TF-IDF, a keyword-based search, so it runs on any laptop with no extra downloads. Bigger projects usually use embeddings (meaning-based search) and a vector database. The 5 steps stay exactly the same; only step 3 and step 4 change.
5. Run it and test it
python pdf_chat.py leave_policy.pdf
Output when it starts:
Loaded 2 pages and made 4 chunks from leave_policy.pdf
First, look at what the search finds. Type show before a question:
Ask a question (or type exit): show How many sick leaves do I get?
--- page 1: Sahyadri Infotech Pvt Ltd - Leave Policy (sample for learning) 1. Casual leave: Every employee gets 12 days of casual le...
Now ask normally:
Ask a question (or type exit): How many sick leaves do I get?
Expected answer (yours will be similar, not the same):
You get 8 days of sick leave in a year. For more than 2 days in a row, you need a
doctor's certificate. (page 1)
Now ask something that is not in the PDF:
Ask a question (or type exit): What is the salary hike policy?
Expected answer:
I could not find this in the document.
The search still found a chunk (the word "policy" matched), but the rules in the prompt told Gemini to answer only from that chunk. The chunk says nothing about salary, so the bot did not invent anything. That is the main safety idea of RAG.
6. Why does RAG reduce wrong answers?
- The AI reads the real text before answering, instead of guessing from memory.
- You can check every answer because it gives the page number.
- You can update the knowledge by changing the PDF; no retraining is needed.
RAG reduces mistakes, but it does not remove them. If the search picks the wrong chunk, the answer can still be wrong. That is why the page number matters: a person can check it in 10 seconds.
7. Common problems and fixes
| Problem | Likely reason | Fix |
|---|---|---|
| "Loaded 0 chunks" or empty text | The PDF is a scanned image, not text | Use a text PDF, or run OCR first (Google Drive can open a scanned PDF as a Google Doc with text) |
| Wrong or missing answer | The right chunk was not retrieved | Use show to see what was found; try top_k=5 or smaller chunks |
| Answer cut between two chunks | Chunks too small, no overlap | Keep the 20-word overlap, or use 120-word chunks |
| The bot invents answers | The prompt rules are weak | Keep "ONLY the context" and the "could not find" line |
| API key error | Key not set in this terminal | Run the export (or $env:) command again in the same window |
| Model not found error | Model names change | Check the current model name in Google's Gemini API docs and update MODEL |
8. No-code or code: which should I choose?
| Need | Choose |
|---|---|
| Ask questions about a few PDFs today | Gemini Notebook (no code) |
| Learn how AI apps work, for a job or project | The Python script |
| A bot inside your company's website or Teams | A coded RAG app with embeddings, a vector database and your company's approved AI service |
| A bot that can also act (send emails, update sheets) | An agent, for example in n8n |
9. Try at home
Try at home
- Make or download a small text PDF (a college notice, a public policy or a product manual).
- Upload it to Gemini Notebook and ask 3 questions. Click the citations.
- Install the libraries and run pdf_chat.py with the same PDF.
- Use
showon 2 questions and read which chunks were found. - Ask one question that is not in the PDF. Did the bot say it could not find it?
- Change the chunk size from 80 to 40 words. Do the answers get better or worse?
Recap
In short
- RAG = find the right parts of your document first, then let the AI answer from them only.
- The 5 steps: load, chunk, index, retrieve, generate.
- No-code way: Gemini Notebook (formerly NotebookLM), with citations.
- Code way: pypdf to load, TF-IDF to search, the Gemini API to answer, in about 60 lines.
- Strict prompt rules ("only the context", "could not find", "page number") stop the bot from inventing.
- Always test one question that the PDF does not answer.
Run pdf_chat.py on one PDF from your own life today, like your college fee notice. Once you see the "show" step work, RAG will never feel like magic again.
Learn the basics first: What Is Generative AI and How Does ChatGPT Work?
Ravindra Bagale, trainer: linkedin.com/in/ravindra-bagale. Sneha, Sahyadri Infotech and its leave policy are made up for learning. The script was run on 19 October 2026 with google-genai 2.31.0, pypdf and scikit-learn; the loading, chunking and search output above is real. Gemini answers change every time, so yours will be similar, not the same. Gemini Notebook plans and the Gemini model name were checked on Google's pages the same day and can change.
Frequently asked questions
What does RAG stand for?
Retrieval-Augmented Generation. The system retrieves the right parts of your documents and adds them to the prompt, so the AI generates an answer from your data.
Can I make a PDF chatbot without coding?
Yes. Upload the PDF to Gemini Notebook (formerly NotebookLM) and ask questions. It answers from your sources and shows citations.
Why does my PDF chatbot say it cannot find the answer?
Either the PDF really does not have it, or the search did not find the right chunk. Check the retrieved chunks, try more chunks, or use a text PDF instead of a scanned one.
Is RAG better than fine-tuning?
For answering from documents that change, RAG is usually simpler: you update the document, not the model. Fine-tuning changes how a model behaves, not what documents it can look up.
Is it safe to upload company PDFs?
Only with your company's permission and in an approved tool. For practice, use sample or public PDFs.