Lesson 9
How does a chatbot answer from a 500-page PDF?
A chatbot does not read all 500 pages. Your code finds the few pieces that match the question and pastes only those into the prompt. This is called RAG. The lesson follows one question to a store's chatbot: who does each step, what it costs, and when it gives a wrong answer.
1Why not paste the whole PDF into every question?
Pasting the whole PDF is slow and costs a lot. A 500-page PDF is about 3 lakh tokens, and the model reads every one of them for every question.
- ๐The 3 lakh is our estimate, at about 600 tokens a page. 600 tokens ร 500 pages = 3,00,000 tokens.
- ๐The model remembers nothing between questions (lesson 8), so the app sends the whole PDF again with every question. 10 questions send the same 3 lakh tokens 10 times.
- ๐ธYou pay for every token you send (lesson 8). On Claude Opus 5.5, 3 lakh input tokens cost $1.20. 1,000 questions a day cost $1,200 a day, for the input alone.
- ๐ขThe answer starts late. The model reads all 3 lakh tokens before it writes the first word.
- ๐ซIt may not fit in the context window (lesson 8). Four such PDFs are 12 lakh tokens. Claude Opus 5.5 holds 10 lakh.
2What is RAG?
RAG is a way to answer from your own documents: your code finds the few pieces that match the question and puts them into the prompt, next to the question.
You already do this with a textbook. To answer "What is photosynthesis?", you find it in the index, open page 112 and read one page. You do not read the whole book again.
RAG stands for Retrieval-Augmented Generation:
- ๐Retrieval: find the pieces of text that match the question. From a policy handbook, find the part about returning phones.
- โAugmented: add those pieces to the prompt. The prompt now holds 3 short pieces of the handbook, then the question.
- โ๏ธGeneration: the LLM writes the answer from what it was given. "You can return a phone within 7 days."
Adding the pieces is easy: your code joins texts together. The hard part is the search: which pieces match the question?
3How does RAG answer a question, step by step?
RAG works in two parts. The setup runs once, when you add the document. The second part runs for every question a customer asks.
First, two new ideas: one list of numbers for a whole text, and how close two lists are.
- ๐In lesson 4, every token had its own list of numbers. The token for cat had one list, and the token for dog had another.
- ๐RAG gives one list to a whole piece of text. This list is also called an embedding. Chunk 1 of the store's handbook, about returning electronics, gets one list, like [0.12, โ0.48, 0.91, โฆ] (made-up numbers, used again in step 3).
- ๐งฒTexts about the same thing get lists that are close. The question "What's the return policy for electronic items?" and a chunk about returning phones get close lists. A chunk about free delivery gets a list far away.
- ๐Lesson 4 measured a gap: a small gap means close. Many RAG tools give a closeness number instead: a bigger number means closer, and 1 is the highest. In step 6 below, the returns chunk has a closeness of 0.91 and the delivery chunk 0.22 (made-up numbers).
๐ ๏ธ Setup, once:
- โ๏ธ Cut the document into small pieces, called chunks.
- ๐ข Turn each chunk into one list of numbers, its embedding.
- ๐๏ธ Store every list, with its chunk's text, in a database.
๐ฌ Every question:
- ๐ข Turn the question into one list of numbers, the same way.
- ๐๏ธ Find the stored lists closest to the question's list.
- ๐งโ๐ป Paste those chunks into the prompt, with the question.
- ๐ค The LLM reads the prompt and writes the answer.
In the example below, a customer asks an online store's chatbot about returns. Use the buttons to go through it one step at a time.
- ๐งโ๐ป Your code
- โ๏ธ Splitter
- ๐ข Embedding model
- ๐๏ธ Vector database
- ๐ค LLM
SETUP ยท ONCE
๐ Step 1: the store's policy PDF
Who: ๐งโ๐ป your code opens the PDF and copies its text.
Bazaar Box policy handbook ยท 500 pages
Electronics returns. Phones, laptops and headphones can be returned within 7 days of delivery, unopened and in the original box.
Faulty electronics. If an electronic item stops working within 30 days, we replace it free of charge.
โฆ 498 more pages โฆ
SETUP ยท ONCE
โ๏ธ Step 2: cut it into chunks
Who: โ๏ธ the splitter, a small function in your code. Not the LLM.
โฆ 667 chunks for the whole PDF.
SETUP ยท ONCE
๐ข Step 3: each chunk becomes a list, and is stored
Who: ๐งโ๐ป your code sends each chunk to ๐ข the embedding model, then saves the list in ๐๏ธ the vector database.
Each row keeps the list, the chunk's text and its page number.
EVERY QUESTION
๐ Step 4: a customer asks
Who: ๐ the customer types in the chat. ๐งโ๐ป Your code receives the message.
What's the return policy for electronic items?
EVERY QUESTION
๐ข Step 5: the question becomes a list too
Who: ๐ข the same embedding model as in step 3.
EVERY QUESTION
๐๏ธ Step 6: find the 3 closest chunks
Who: ๐๏ธ the vector database compares the question's list with every stored list.
Closeness of each chunk's list to the question's list (1 is the highest)
- โ Chunk 1 ยท Electronics returns0.91
- โ ๏ธ Chunk 4 ยท Electronic items disposal close, wrong topic0.84
- โ Chunk 2 ยท Faulty electronics0.81
- Chunk 3 ยท Refunds0.63
- Chunk 5 ยท Clothing returns0.57
- Chunk 6 ยท Delivery0.22
Rows on a green background: the 3 closest chunks, which your code takes. The โ and โ ๏ธ marks are ours. The database sees only the numbers.
EVERY QUESTION
๐งโ๐ป Step 7: build the prompt
Who: ๐งโ๐ป your code joins three parts into one text.
Grey line: the instruction. Green lines: the 3 chunks. Orange line: the question.
EVERY QUESTION
๐ค Step 8: the LLM answers
Who: ๐ค the LLM. It sees only this prompt, about 1,500 tokens, not the 500 pages.
You can return phones, laptops and headphones within 7 days of delivery, if they are unopened and in the original box (page 12). If an item stops working within 30 days, we replace it free (page 13).
The disposal chunk was in the prompt, but it does not answer the question, so the LLM did not use it.
A made-up store, policy text, page numbers, number lists and closeness numbers. A real list has hundreds or thousands of numbers, not 3. Each step says who does the work, and that worker is dark in the row at the top.
4Who cuts the PDF into chunks?
Your own code does, with a small program. The LLM is not involved.
- โ๏ธCut by size or by paragraph. Every 500 tokens, or one chunk per paragraph of the handbook.
- ๐Repeat a little text at each cut, the overlap, so a sentence cut at the edge is still whole in one chunk. The last 50 tokens of chunk 1 are also the first 50 tokens of chunk 2.
- ๐งฎThe overlap decides how many chunks you get. With 500-token chunks and a 50-token overlap, each new chunk starts 450 tokens after the last one. 3,00,000 tokens make 667 chunks.
- โ๏ธKeep chunks small, but not too small. One sentence alone loses its meaning ("They must be unopened": what must?). A whole chapter mixes many topics into one list.
Made-up text. Here one chunk is 3 sentences and the overlap (highlighted) is 1 sentence, so each highlighted sentence appears in two chunks. A real splitter uses bigger sizes, like 500 tokens with 50 tokens of overlap (our example numbers).
A simple splitter in JavaScript, which cuts by words:
function split(text, size, overlap) {
const words = text.split(" ");
const chunks = [];
for (let start = 0; start < words.length - overlap; start += size - overlap) {
chunks.push(words.slice(start, start + size).join(" "));
}
return chunks;
}
console.log(split("a b c d e f g h i j", 4, 1));
// [ 'a b c d', 'd e f g', 'g h i j' ]
Each chunk is 4 words, and "d" and "g" appear twice: that is the overlap of 1 word. This splitter counts words to keep the example short. Real splitters usually count tokens, like the 500 above. The idea is the same.
5Who makes the embeddings, and who does the search?
A separate embedding model, usually a small one, makes the lists. A vector database does the search. The LLM does neither.
An LLM does have embeddings inside it, but they are not the lists RAG uses:
- ๐คInside the LLM: one list per token, used by the LLM while it reads (lesson 4). The token for cat has its own list inside the LLM.
- ๐ขFor RAG: one list for a whole chunk, made by a separate embedding model. All of chunk 1, "Phones, laptops and headphones can be returned within 7 daysโฆ", becomes one list.
The five workers, and what each worker does:
- ๐งโ๐ปYour code runs everything and passes text between the others. It reads the PDF, calls the splitter, sends chunks to the embedding model, and builds the final prompt.
- โ๏ธThe splitter, a function in your code, cuts the text into chunks. 500 pages become 667 chunks.
- ๐ขThe embedding model turns one piece of text into one list of numbers. Voyage AI's voyage-4-lite turns any chunk into a list of 1,024 numbers by default.
- ๐๏ธThe vector database stores the lists and finds the closest ones. Given the question's list, it returns chunks 1, 4 and 2.
- ๐คThe LLM reads the prompt your code built and writes the answer. It sees 3 chunks and one question, never the other 664 chunks.
More about the embedding model and the database:
- ๐งฉThe embedding model often comes from a different company than the LLM. Anthropic makes Claude but has no embedding model. Its own docs say so and name Voyage AI instead.
- ๐The chunks and the question must use the same embedding model. voyage-4-lite gives 1,024 numbers and the open model all-MiniLM-L6-v2 gives 384. Lists from two models cannot be compared.
- ๐๏ธA vector database is a database that stores lists of numbers and quickly finds the lists closest to a given list. Pinecone, Qdrant and Chroma are built for it. Many teams use Postgres with the pgvector add-on.
6Does RAG use a smaller model, and is the LLM the only cost?
Yes, the embedding model is usually much smaller than the LLM, because its job is easier. No, the LLM is not the only cost: the embedding model costs money too, but far less.
Why a small model is enough:
- ๐ชถTurning text into a list is easier than writing an answer. The embedding model never writes a polite reply. It only has to make close lists for texts about the same thing.
- ๐ฅIt returns one list, not words, so it has no output tokens (lesson 8). An LLM writing a 100-token answer needs 100 rounds, one after another. The embedding model needs one round.
- ๐๏ธFewer dials means less work per token (lesson 8). all-MiniLM-L6-v2, an open embedding model whose size is published, has 2.27 crore (22.7 million) dials. Llama 3 8B has 800 crore (8 billion), about 350 times more.
What costs money:
- ๐ขThe embedding model costs money too, because it runs on a computer like any model. voyage-4-lite costs $0.02 per 10 lakh tokens. Claude Opus 5.5 input costs $4 for the same 10 lakh tokens.
- 1๏ธโฃThe PDF is embedded once, not every question. 667 chunks of up to 500 tokens are 3,33,300 tokens, with the overlap. 3,33,300 ร $0.02 รท 10,00,000 = about $0.0067, one time.
| Paste the whole PDF | RAG: paste 3 chunks | |
|---|---|---|
| Tokens sent per question | 3,00,000 | about 1,500 |
| Cost of one question | $1.20 | $0.006 |
| 1,000 questions a day | $1,200 | $6 |
| Embedding the PDF (setup, once) | none | about $0.0067 |
- โRAG sends 200 times fewer tokens, so each question's input costs 200 times less. 3,00,000 รท 1,500 = 200, and $1.20 รท $0.006 = 200.
- โ๏ธThe answer's output tokens cost the same in both columns, so the table does not include them. The same 100-token answer is written either way.
- ๐Each question is embedded too, but questions are short. 1,000 questions of about 10 tokens are 10,000 tokens a day: 10,000 ร $0.02 รท 10,00,000 = $0.0002.
7When does RAG give a wrong answer?
RAG gives a wrong answer when the search misses the right chunk. The LLM can only use what your code puts into the prompt, so a missed chunk means a missing fact.
- ๐The right chunk is not among the closest. The rule for tablets is in a chunk titled "Gadget care". It comes 5th, your code takes only the top 3, and the LLM never sees it.
- ๐ฃSearch always returns something, even when nothing matches. "Do you sell cars?" still returns the 3 closest chunks, all about other things.
- โA minimum closeness lets your code say "I don't know". With a minimum of 0.5, if no chunk reaches 0.5, your code replies "I don't know" and does not call the LLM.
- ๐คA meaning search can miss exact words, like a model number. The handbook has one line about the headphones model BX-40912. A question about BX-40912 can return chunks about other headphones, because their lists are close.
- ๐Real systems often add a search for the exact words, next to the meaning search. A search for "BX-40912" finds only the chunks with exactly those characters.
So far, a model only reads text and writes text. Can it actually do things, like check the weather or send an email? Lesson 10 starts there.
Where this comes from
- The return-policy example: dump everything vs find the related part; split into rough chunks; embed the query and the chunks; top-k nearest; the LLM ignores an unrelated "electronic items disposal" chunk: the course transcript (notes/course-transcript-llm-basics.md), Part 6. The store, Bazaar Box, and all its policy text are made up.
- RAG = retrieval, then grounded generation; chunk, embed, store in a vector database; the prompt is the question plus retrieved text: Hands-On Large Language Models (Alammar, Grootendorst; O'Reilly 2024), ch.8, PDF p.316-322 and p.349-352 (figures 8-24 and 8-26). Rahul's course blueprint, Module 9.1-9.2 (ingest once, query each request; "literally string concatenation, plus a smart search").
- Chunking by size or paragraph, with overlap; sentences too small: Hands-On Large Language Models, ch.8, PDF p.330-333 (figures 8-8 and 8-9: character, token and overlapping-token splits; sentence, paragraph and overlapping-window chunks). Blueprint 9.2. The 500-token size and 50-token overlap are our example numbers. The
splitfunction was run with Node.js on 2026-10-31 and printed the output shown. The same loop, run over 3,00,000 tokens with size 500 and overlap 50, gives 667 chunks holding 3,33,300 tokens. - Anthropic has no embedding model and points to Voyage AI; voyage-4-lite gives 1,024 numbers by default: Claude docs, "Embeddings": "Anthropic does not offer its own embedding model. One embeddings provider with a wide variety of models and capabilities is Voyage AI by MongoDB." Model table: voyage-4-lite, "1024 (default), 256, 512, 2048", "Optimized for latency and cost". platform.claude.com/docs/en/build-with-claude/embeddings. The claude-api skill does not cover embeddings.
- voyage-4-lite costs $0.02 per 1 million (10 lakh) tokens: MongoDB, Voyage AI model pricing (voyage-4-lite $0.02, voyage-4 $0.06, voyage-4-large $0.12 per 1M (10 lakh) tokens). mongodb.com/docs/voyageai/management/billing; the same figures at docs.voyageai.com/docs/pricing.
- all-MiniLM-L6-v2: 384 numbers, 22.7 million (2.27 crore) parameters: its Hugging Face card: "maps sentences & paragraphs to a 384 dimensional dense vector space"; "22.7M params". huggingface.co/sentence-transformers/all-MiniLM-L6-v2. The same model is used in Hands-On Large Language Models, ch.10, PDF p.426-428. Llama 3 8B: 8,030,261,248 parameters (Hugging Face, lesson 2); 8,030,261,248 รท 22,700,000 โ 354, "about 350 times".
- Embedding models give one list for a whole text; trained for that job: Hands-On Large Language Models, ch.2, PDF p.100-102 (text embedding models; all-mpnet-base-v2 gives 768 numbers); ch.10, PDF p.399-402. An LLM's token embeddings: lesson 4.
- Closeness numbers vs lesson 4's gap: the Claude docs "Embeddings" page says Voyage embeddings work "with dot-product similarity, cosine similarity, or Euclidean distance" (same URL as above). Lesson 4 used a gap (sum of differences); a closeness number such as cosine similarity is bigger when lists are closer, with 1 as the highest.
- Computing embeddings still runs a model; only the distance maths is cheap: Rahul's blueprint, Part 5 (fact-check log, L22).
- Vector databases; Postgres + pgvector: Hands-On Large Language Models, ch.8, PDF p.333-334 (vector databases such as Weaviate and Pinecone). Blueprint 9.3 (Pinecone, Qdrant, Weaviate, Milvus, Chroma, Postgres + pgvector).
- Search always returns something; a closeness cut-off; exact-word search alongside: Hands-On Large Language Models, ch.8, PDF p.328-330 ("What is the mass of the moon?" still returns results; set a threshold; hybrid search for exact phrases). Blueprint 9.4.
- Answers that name their source page: Hands-On Large Language Models, ch.8, PDF p.319 (figure 8-3, answers with numbered citations). Page 12 matches lesson 10's example.
- Prices and context window: Claude Opus 5.5 $4 input / $20 output per million (10 lakh) tokens, 1M (10 lakh) context; Anthropic Claude API model table via the claude-api skill, cached 2026-10-06. Dollars are not converted to rupees.
- The worked sums (checked with a Node.js script on 2026-10-31): 600 ร 500 = 3,00,000 tokens. 3,00,000 ร $4 รท 10,00,000 = $1.20; ร 1,000 = $1,200. 1,500 ร $4 รท 10,00,000 = $0.006; ร 1,000 = $6. 3,00,000 รท 1,500 = 200. 4 ร 3,00,000 = 12,00,000. Chunks: a new one every 450 tokens gives 667 chunks; 667 โ 3 = 664. Embedding the PDF: 3,33,300 ร $0.02 รท 10,00,000 = $0.0067. Embedding questions: 10,000 ร $0.02 รท 10,00,000 = $0.0002. $4 รท $0.02 = 200.
- Made up on purpose: Bazaar Box, every policy line and chunk, the number lists, the closeness numbers (0.91, 0.84, 0.81, 0.63, 0.57, 0.22), the page numbers (12, 13, 47), the 0.5 cut-off, the "Gadget care" and "BX-40912" examples, the bot's answer, 600 tokens a page (our estimate, stated in section 1), 500 tokens a chunk and about 1,500 tokens for the RAG prompt, 10 tokens a question, the 100-token answer, the textbook page 112. All web pages accessed 2026-10-31.