RAG Pipeline
Document Chat proved an LLM can answer questions about your data — as long as everything fits in one request’s context window. This project removes that ceiling: instead of resending a whole document on every question, you build a real retrieval pipeline that finds and injects only the relevant pieces of a much larger document set, on demand.
What you’re building
rag-pipeline ingests a folder of documents, chunks and embeds them into a persistent vector
index, and at query time retrieves only the chunks above a similarity-score threshold — not the
whole corpus. It ships with an A/B mode that runs the same question through the model with
and without retrieved context, so you can see exactly what retrieval is buying you on a
question-by-question basis, instead of assuming it’s working because the answers sound
reasonable.
The RAG pipeline
Ingestion (top) and querying (bottom) are two separate paths that share one index. A stale index — documents changed without re-running the top path — is one of the most common ways this pipeline quietly starts giving wrong answers.
Core concepts, three levels deep
1. Embeddings
- Definition: a list of numbers (a vector) that encodes the meaning of a piece of text, not its exact wording. Texts with similar meaning produce numerically close vectors, which is what makes searching by meaning — instead of by keyword — possible at all.
- In this project: every chunk you ingest, and every query a user sends, gets converted to a vector before anything else happens. Retrieval is entirely a numeric comparison over these vectors — the model never re-reads your raw documents at query time, it reads whatever chunks the vector comparison surfaced.
- Practical consequence: two phrases that share zero words (“reset password” and “account recovery”) can still retrieve correctly, because embeddings capture intent, not literal text overlap. That’s the entire reason this beats a keyword search.
2. Chunking and chunk overlap
- Definition: splitting a document into smaller pieces so each one covers roughly one topic and fits comfortably in a retrieval result — typically 300-500 tokens, with a 50-token overlap buffer at each boundary.
- In this project: the chunk size and overlap you choose directly determine what’s retrievable. A fact that straddles two chunks with no overlap can end up incomplete in both of them — retrievable in neither.
- Practical consequence: when retrieval looks wrong, check chunking before you touch anything else. Bad chunk boundaries are one of the most common — and most fixable — causes of a RAG system returning incomplete or off-topic results.
3. Retrieval: cosine similarity, top-k, and score thresholds
- Definition: cosine similarity ranks chunks by the angle between their vector and the query’s vector (direction, not magnitude); top-k returns the k highest-scoring chunks; a score threshold discards anything below a “similar enough” cutoff even if it’s in the top-k.
- In this project: these three settings together decide what actually reaches the model. Top-k alone can return weak matches if nothing in the index is truly relevant — the score threshold is what lets the pipeline say “nothing in my documents answers this” instead of forcing a bad match into the prompt.
- Practical consequence: cosine similarity — not Euclidean distance — is the right metric here specifically because it isn’t skewed by chunk length, so a short chunk and a long chunk about the same topic can still score as equally relevant.
4. Grounding and index freshness
- Definition: grounding is instructing the model to answer only from retrieved context (and say so when it can’t); index freshness is whether the vector store reflects the current state of your source documents.
- In this project: without an explicit “answer only from the provided context” instruction, the model can quietly fall back on training memory instead of your actual documents — which defeats the entire point of building this pipeline. Separately, if a source document changes and you don’t re-embed it, the old chunk stays in the index and keeps getting served as if it were current.
- Practical consequence: treat re-indexing after a document update as part of running this pipeline, not an optional maintenance step — a stale embedding is a wrong answer delivered with full confidence, which is exactly the failure mode citations and grounding are supposed to prevent.
Decision rules
| If… | Then… |
|---|---|
| A document set comfortably fits in one context window and rarely changes | Stuff it into context directly — that’s Project 1’s approach; you don’t need retrieval infrastructure for this |
| The document set is large, spans many files, or needs to scale past one context window | Build retrieval (this project) — chunk, embed, index, and retrieve only what’s relevant per query |
| Source data changes frequently and answers need a traceable source | Choose RAG over fine-tuning — no retraining needed, and the index can be updated independently of the model |
| You need to change the model’s writing style, tone, or domain vocabulary, not its knowledge | Choose fine-tuning over RAG — that’s a behavior change, not a knowledge-injection problem |
| Retrieval quality degrades as the corpus scales up | Add metadata filtering before similarity search — don’t just raise top-k, which gets noisier, not better, at scale |
Common mistakes
- Zero or too-small chunk overlap, silently splitting the sentence that contains the answer across two incomplete chunks.
- Skipping the “answer only from context” instruction, so the model quietly falls back to training memory instead of the chunks you actually retrieved — defeating the point of retrieval.
- Never re-indexing after a document update, so the pipeline keeps confidently citing outdated content indefinitely.
- Reaching for a bigger top-k instead of metadata filters when retrieval quality drops at scale — a larger candidate pool without narrowing it first just adds more noise.
Key concepts at a glance
| Concept | One-line definition | Why it matters for rag-pipeline |
|---|---|---|
| Embedding | A vector that encodes the meaning of a piece of text | The unit everything in this pipeline — chunks and queries alike — is compared as |
| Chunking + overlap | Splitting documents into retrievable pieces with a boundary buffer | Determines whether a fact is actually retrievable at all |
| Cosine similarity / top-k / score threshold | Angle-based ranking, capped at k results, filtered by a relevance cutoff | The exact mechanism this project’s retrieval step runs on |
| Index freshness | Whether the vector store reflects the current source documents | Why re-indexing on update is part of operating this pipeline, not optional maintenance |
RAG is the single most-asked-about AI Engineer skill in job descriptions today — this is the project that lets you speak to it with specifics, not buzzwords.