Zucchetti LLM Course — Lecture 4 of 10

RAG Foundations
& Decision Matrix

From frozen knowledge to live data — and when to use what


Kamyar Zeinalipour · 90 minutes

Today’s Agenda

20 min The Retrieval Problem & The RAG Architecture
10 min ☕ Break
20 min From Keywords to Vectors — How Retrieval Evolved
15 min Document Processing & Chunking Theory
10 min Vector Databases — Similarity Search at Scale
15 min Decision Matrix: Prompt vs. RAG vs. Fine-Tune
5 min Key Takeaways & Q&A
Total: 90 minutes · Pure theory — hands-on lab in Lecture 5 (combined Lab 4 + Lab 5)

Section 1 of 5

The Retrieval Problem

Why LLMs need external knowledge

The Fundamental Problem

LLMs have two critical limitations:

🧊 Frozen Knowledge

Model knowledge is fixed at training cutoff.

GPT-4 does not know what happened yesterday.

It cannot access your internal documents.

It has never seen your company’s policies.

🎭 Hallucination Under Pressure

When the model lacks knowledge, it does not say “I don’t know.”

It generates a plausible-sounding answer.

The answer looks correct.

It is completely fabricated.

We need a way to inject real, verifiable knowledge into the model at query time.

Two Ways to Add Knowledge

Approach 1: Fine-Tuning

Bake knowledge into the weights.

  • Train on domain-specific data
  • Knowledge becomes “permanent”
  • Expensive, slow to update
  • Model may still hallucinate

Like memorizing a textbook — you might misremember.

Approach 2: RAG ⭐

Provide knowledge at query time.

  • Retrieve relevant documents
  • Inject into the prompt as context
  • Fast to update (re-index documents)
  • Answers are grounded in sources

Like an open-book exam — you can check your answers.

Fine-tuning changes behavior. RAG provides knowledge. They solve different problems.

Retrieval-Augmented Generation

The idea: instead of asking the model to remember, let it look things up.

πŸ“„ Your Documents → βœ‚οΈ Chunks → πŸ”’ Embed → πŸ’Ύ Index
⬇ at query time ⬇
❓ Question → πŸ” Retrieve → πŸ“ Augment → πŸ€– Generate → βœ… Grounded Answer

Two phases: Offline (index once) — Online (retrieve & generate per query)

P(y | x) = ∑d∈D P(d | x) ⋅ P(y | x, d)

y = answer, x = query, d = retrieved doc — RAG marginalizes over retrieved documents (Lewis et al., 2020)

Lewis et al., “Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks”, NeurIPS 2020

RAG in Action — Step by Step

A concrete example of the full pipeline.

πŸ‘€ User asks: “What is the maternity leave policy?”

πŸ” Step 1: Retrieve — system searches vector DB, finds 3 relevant chunks

Chunk 1 (hr_policy.pdf, p.12): “Employees are entitled to 5 months of mandatory maternity leave...”

Chunk 2 (hr_policy.pdf, p.13): “Optional parental leave can be extended up to 6 additional months...”

Chunk 3 (hr_policy.pdf, p.14): “During maternity leave, employees receive 80% of their salary...”

βœ… Step 2: Augment & Generate — LLM reads chunks and produces a grounded answer

“Maternity leave is 5 months mandatory at 80% salary, with an option to extend up to 6 additional months. (Source: hr_policy.pdf, pages 12–14)”

The answer comes from your documents, not the model’s imagination. The user can verify by checking page 12.

Lewis et al., “Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks”, NeurIPS 2020

Why RAG Works — The Grounding Principle

RAG transforms the generation task from recall to reading comprehension.

❌ Without RAG — Hallucination

“What is Zucchetti’s remote work policy?”

Model output: “Employees may work remotely up to 3 days per week, as per the 2022 Smart Working Agreement.”

⚠️ Completely invented. Confident. Wrong.

βœ… With RAG — Grounded

“What is Zucchetti’s remote work policy?”

Model output: “According to hr_policy_2024.pdf p.8: employees may request up to 2 remote days per week after 6 months of employment.”

βœ… From document. Verifiable. Cited.

LLMs excel at reading comprehension — RAG converts recall into comprehension.

RAG vs. Fine-Tuning — When to Use Each

πŸ“š RAGπŸ”§ Fine-Tuning
What it changesKnowledge availableModel behavior / weights
Knowledge sourceExternal documentsBaked into parameters
Update frequencyFast (swap or re-index documents β€” minutes for typical corpora)Retrain required (hours–days)
CostLow (embeddings + DB)High (GPU compute)
HallucinationSignificantly reduced (answers grounded in text β€” but not eliminated: model can still ignore context)Medium (may still confabulate)
InterpretabilityHigh (can show sources)Low (black box)
Best forFacts, policies, Q&AStyle, format, behavior
RAG and fine-tuning are complementary, not competing. Many production systems use both.

☕

10-Minute Break

Stretch your legs — we are going deep next


Next up: How Search Evolved — from keywords to meaning — the math behind retrieval

Section 2 of 5

From Keywords
to Vectors

How information retrieval evolved over 50 years

The Evolution of Search

EraMethodHow It WorksLimitation
1970sBooleanExact keyword match (AND, OR, NOT)No ranking, no synonyms
1990sTF-IDFRank by term frequency × rarityNo semantic understanding
1994+BM25Improved TF-IDF with saturation & length normStill keyword-based
2019+Dense RetrievalEmbed query & docs as vectors, compare similarityNeeds good embeddings
RAG is retrieval-method-agnostic β€” it works with sparse (BM25), dense (embeddings), or hybrid search. Simple RAG systems still use BM25. Production systems typically use hybrid retrieval. Dense retrieval (embeddings & cosine similarity, from Lectures 1 & 2) is the modern standard — but not the only option.

Boolean Search — The First Era

Information retrieval before statistics. Simple logic, no ranking.

How It Works

Documents must contain exact keywords combined with logical operators.

AND  →  both terms must appear
OR   →  either term matches
NOT →  exclude this term

Query: maternity AND leave AND policy NOT termination

Why It Failed

No ranking — every matching document is equal. 10,000 results, no idea which is best.

No synonyms — query “car” misses documents saying “automobile”.

Brittle — one typo, zero results. Expert users only.

No context — “python AND programming” matches a document about programming AND snakes separately.

Boolean search was revolutionary in the 1970s — MEDLINE (1971) and DIALOG (1972) made entire scientific databases searchable for the first time. But it requires users to think like a computer, not a human. TF-IDF replaced it by adding statistical ranking.

TF-IDF — The Classic Approach

The foundation of keyword search. Still used today in hybrid systems.

TF-IDF(t, d) = TF(t, d) × IDF(t)

TF (Term Frequency)

How often does the word appear in this document?

TF(t, d) = count(t in d) / |d|

More occurrences = more relevant

IDF (Inverse Document Frequency)

How rare is this word across all documents?

IDF(t) = log(N / df(t))

“the” appears everywhere = low IDF
“maternity” is rare = high IDF

TF-IDF works well for exact keyword matching. But it fails when the user says “parental leave” and the document says “maternity policy.”

Note: Modern implementations use smoothed IDF = log(N / (df+1)) + 1 to avoid division by zero.

Spärck Jones, “A Statistical Interpretation of Term Specificity and Its Application in Retrieval”, Journal of Documentation, 1972

BM25 — The Industry Standard

The default ranking in Elasticsearch, Solr, OpenSearch. Still the strongest sparse retriever.

BM25(q,d) = ∑i IDF(ti) · TF(ti,d) · (k1+1)⁄TF(ti,d) + k1·(1−b+b·|d|/avgdl)

1. Term Saturation (k1)

The 100th “policy” adds almost nothing to the score.

k1 ∈ [1.2, 2.0] controls saturation speed. TF-IDF has no cap.

2. Length Normalization (b)

“policy” 3× in a 2-page memo vs. 50× in a 100-page manual.

b ∈ [0, 1] controls length penalty. b=0.75 is default. The memo wins.

βš™οΈ BM25 Scoring in Action β€” Query: “sick leave policy”

Inverted index finds 6 candidate chunks. BM25 scores each one:

ChunkHas “sick”?Has “leave”?Has “policy”?BM25 Score
chunk3βœ…βœ…βœ…6.48 πŸ†
chunk7βœ…βœ…βœ…5.90
chunk41βœ…βŒβŒ3.36
chunk12βŒβœ…βŒ1.68
chunk88βŒβœ…βŒ1.68
chunk1βŒβŒβœ…1.44

Score = IDF(“sick”)×TF_norm + IDF(“leave”)×TF_norm + IDF(“policy”)×TF_norm  —  summed across query terms. “sick” is rare (IDF=4.2) so contributes more than “policy” (IDF=1.8).

BM25 rewards: (1) more query terms matched • (2) rarer words = bigger bonus • (3) more occurrences in a short chunk. chunk3 wins because it contains all 3 terms and “sick” is rare.

Robertson & Zaragoza, “The Probabilistic Relevance Framework: BM25 and Beyond”, Foundations and Trends in IR, 2009

From Formula to Results — How Retrieval Works

In RAG, the unit being indexed and retrieved is always a chunk — not the original full document. Each method works on chunks.

πŸ“‹ Sparse Retrieval (BM25)

Uses an inverted index — a lookup table: term → [chunk_ids that contain it]

1. Query: “sick leave policy”
2. Look up each term in index:
    “sick” → [chunk3, chunk7, chunk41]
    “leave” → [chunk3, chunk7, chunk12, chunk88]
    “policy” → [chunk1, chunk3, chunk7]
3. Candidate set: union = [chunk1, chunk3, chunk7, chunk12, chunk41, chunk88]
4. Compute BM25 score for each candidate chunk
5. Sort by score → return top-k chunks

⚑ Fast: only scores chunks that share at least one query term

πŸ”’ Dense Retrieval (Embeddings)

Uses a vector index (HNSW) — stores chunk embeddings in a navigable graph

1. Query: “sick leave policy”
2. Embed query → [0.21, −0.45, 0.78, ...]
3. Search HNSW graph for nearest chunk vectors
    (no word lookup — geometric search)
4. Candidate set: top-k chunks by cosine similarity
5. Return those chunks to the LLM

⚑ Fast: HNSW navigates from coarse to fine — O(log n)

In RAG: chunk = the unit of retrieval. Both BM25 and dense retrieval index chunks, score chunks, and return chunks — never the full source document. This is why chunking quality directly determines retrieval quality.

Dense Retrieval — The Semantic Leap

Instead of matching keywords, we match meaning. The key intuition: similar meanings point in the same direction in vector space.

Sparse (BM25)

Each chunk is a bag of words.

Vector has 50,000+ dimensions (one per word in vocabulary).

Most values are zero (sparse).

Match = shared words exist. No synonyms.

Dense (Embeddings)

Each chunk is a meaning direction in space.

Vector has 384–3072 dims. All non-zero.

Cosine measures angle between two directions.

cos(A,B) = A⋅B⁄||A|| · ||B|| ∈ [−1, 1]

1 = same direction = same meaning  |  0 = unrelated  |  −1 = opposite

“vacation days” → embed → [0.21, −0.45, 0.78, ...]

“time off”         → embed → [0.19, −0.41, 0.82, ...]

cosine similarity = 0.89  —  BM25 score = 0 (no shared words)

πŸ’‘ Unit-normalized vectors: &lVert;e&rVert; = 1 ⇒ cos(A,B) = A⋅B  (how FAISS/ChromaDB compute similarity internally)

Dense retrieval finds meaning, not keywords. Two texts are similar if they point in the same direction β€” even when they share zero words.

The Scale Problem — Why We Need ANN

Cosine similarity gives the score. But how do you search 1 million vectors fast enough?

❌ Brute Force (KNN)

Compare query against every vector.

1M × 384 dims = 384M operations → ~300ms

Too slow for real-time use.

βœ… Approximate Nearest Neighbor (ANN)

Build a smart index that enables shortcuts.

~20 comparisons instead of 1M → ~1ms

300× faster. Trades ~2–5% accuracy for speed.

All modern vector databases use ANN algorithms — most commonly HNSW (Hierarchical Navigable Small World). We’ll cover exactly how HNSW works in Section 4.

Two Retrieval Approaches — Which to Use?

Two fundamentally different ways to measure relevance. Different trade-offs.

⚑ Bi-Encoder (start here)

Query and chunk are embedded separately. Relevance = cosine similarity between their vectors.

sim(q, d) = cos( embed(q), embed(d) )

βœ… All chunk embeddings precomputed offline β€” at query time: one embedding call + ANN search = milliseconds

βœ… Works with any embedding model (MiniLM, BGE-M3, OpenAI, etc.)

⚠️ Query and chunk never "interact" β€” relevance is geometric distance only

🎯 Cross-Encoder (costly)

Query and chunk are processed together by the model. Output: one relevance score.

score = model( query + chunk ) → 0.94

βœ… Model reads query against chunk β€” full interaction = higher accuracy

❌ Cannot precompute anything β€” must run the model once per candidate at query time

❌ Too slow to run on 100,000 chunks β€” only practical on a small candidate set

πŸ” Combine Both β€” The Production Pattern

πŸ“¦ All 100,000 chunks
β†’
Stage 1: Bi-encoder
ms β€” fast filter
Top 100
β†’
Stage 2: Cross-encoder
re-rank 100 only
Top 3–5
β†’
πŸ€– LLM

Cross-encoder runs 100 times β€” not 100,000. Bi-encoder eliminates 99,900 chunks first.

Start with bi-encoder only β€” it's fast, simple, and works well. Add a cross-encoder re-ranker only when you need higher precision. Deep dive in Lecture 5.

Embedding Models — The Current Landscape

The bi-encoder works with any embedding model. The field moves fast β€” here is where it stands in 2025.

ModelDimsTokensCostStatus / Use
MiniLM-L6-v2 384256 Free ⚠️ Legacy β€” use for this lab only
Qwen3-Embedding-0.6B 102432768 Free (local) βœ… Modern lightweight β€” replaces MiniLM
BGE-M3 10248192 Free (local) βœ… Production workhorse β€” dense + sparse + hybrid
text-embedding-3-large 30728191 Paid API ☁️ Safe cloud default β€” supports MRL
Gemini Embedding 2 307232768 Paid API ☁️ Top-tier β€” long docs, multimodal

🏠 Self-hosted?

BGE-M3 β€” best open-source choice. Unique: one model for dense, sparse, AND hybrid retrieval. 100+ languages. Data stays local.

☁️ Cloud API?

text-embedding-3-large or Gemini Embedding 2. Easy, high quality. text-3-large supports Matryoshka β€” truncate dims without quality loss.

⚠️ Critical rule: index model = query model. Different models = different vector spaces = garbage similarity scores. Also: don't trust MTEB rankings alone β€” benchmark on your own data.

Hybrid Retrieval — Best of Both Worlds

Production systems combine keyword and semantic search.

BM25

Keyword precision

“Article 47” → exact match

+

Dense

Semantic recall

“time off” → “vacation”

=

Hybrid

Precision + recall

Ranked by combined score

score(q, d) = α · BM25(q, d) + (1 − α) · cos(embed(q), embed(d))

Example — query: “sick leave regulations”

BM25 (normalized): 0.72  |  Dense: 0.85

Hybrid (α=0.4): 0.4×0.72 + 0.6×0.85 = 0.799

Why normalization is required

BM25 scores can be 0–20+. Cosine scores are 0–1. You cannot add them raw — BM25 would always dominate.

→ Normalize each to [0,1] first (min-max or softmax), then apply α.

Advanced alternative: Reciprocal Rank Fusion (covered in L5) — avoids score normalization entirely.

Craswell et al., “MS MARCO: Benchmarking Ranking Models in the Large-Data Regime”, SIGIR 2021

Section 3 of 5

Document Processing
& Chunking Theory

The hidden bottleneck of every RAG system

Why Chunking Matters

Documents are too long to embed as a single vector. We must split them into chunks.

A 50-page HR manual = ~25,000 tokens

Embedding models have a limit of 256 tokens (MiniLM-L6-v2) or 8192 tokens (BGE-M3)

Even if you could embed it all, one vector cannot capture 50 different topics

The embedding dilution problem

Long text → the embedding becomes an average of everything → it matches nothing well.

Analogy: mix all paint colors together → you get grey. The grey matches no specific color. Same with meaning: average of 50 topics = matches none of them.

The retrieval granularity problem

User asks about “sick leave” → you need just those 3 paragraphs, not the whole manual.

Returning the full 50-page manual as context would fill the entire LLM context window with noise.

Chunking is not just a technical step — it determines retrieval quality. Bad chunks = bad answers.

Three Chunking Strategies

1. Fixed-Size

Split every N characters. Simple but cuts mid-sentence. Not recommended.

2. Recursive / Structural ⭐

Split on natural boundaries: paragraphs → sentences → characters. Preserves semantic coherence.

Try \n\n (paragraph) first. If the piece is still longer than your target chunk size (e.g. 400 tokens), try . (sentence). Still too long? Try commas. Go coarse to fine until each piece fits.

3. Semantic

Use embeddings to detect topic shifts. Most accurate but most complex.

split at i ⇔ cos(emb(si), emb(si+1)) < θ

Compare adjacent sentence embeddings. When similarity drops below threshold θ, start a new chunk.

Recursive chunking is the best default for most RAG systems.

The Chunk Size Trade-Off

❌ Too Small (50–100 tokens)

  • High retrieval precision
  • But context fragmentation
  • “...must submit the request to...”
  • No surrounding context → useless

❌ Too Large (1000+ tokens)

  • Full context preserved
  • But retrieval dilution
  • Embedding averages over many topics
  • Returns irrelevant surrounding text

βœ… Sweet Spot: 300–500 tokens

With 50–100 token overlap between consecutive chunks

Overlap = the end of chunk N is repeated at the start of chunk N+1

Chunk 1: “...mandatory maternity leave. During this period, they receive 80%”
Chunk 2: “During this period, they receive 80% of their salary. Optional parental...”
▲ overlap zone — appears in both chunks
Without overlap, a sentence at the boundary might be split across two chunks and lost to both. Overlap guarantees boundary context is always retrievable.

Chunking in Practice — All Three Approaches

Same source text. Target size: 400 tokens.  |  “Employees are entitled to 5 months of mandatory maternity leave. During this period, they receive 80% of their salary. Optional parental leave can be extended up to 6 additional months at reduced pay. Requests must be submitted to HR at least 30 days in advance.”

❌ 1. Fixed-Size

Split every 50 characters. No understanding of language.

Chunk 1: “Employees are entitled to 5 months of mand”
Chunk 2: “atory maternity leave. During this peri”
Chunk 3: “od, they receive 80% of their salary...”

Word “mandatory” split in half. Neither chunk is meaningful alone.

βœ… 2. Recursive ⭐

Try paragraph β†’ sentence β†’ comma. Stop when ≤ 400 tokens.

Chunk 1: “Employees are entitled to 5 months of mandatory maternity leave.”
Chunk 2: “During this period, they receive 80% of their salary.”
Chunk 3: “Optional parental leave... up to 6 months at reduced pay. Requests must be submitted 30 days in advance.”

Each chunk = one complete idea. Clean boundaries, full sentences.

🧠 3. Semantic

Embed each sentence. Split where cosine similarity drops below θ = 0.7.

s1→s2: cos = 0.91  (same topic, keep)
s2→s3: cos = 0.88  (still related, keep)
s3→s4: cos = 0.41  → topic shift! split here

Chunk 1: sentences 1–3 (leave & salary)
Chunk 2: sentence 4 (HR process)

Most accurate. Needs an embedding model just to chunk β€” more complex.

Recursive is the best default. Add semantic chunking only when topics shift within paragraphs and retrieval quality is still poor after tuning chunk size.

Metadata — The Fourth Dimension

Every chunk carries structured data alongside its text and embedding.

A chunk is not just text. It is a tuple: (text, embedding, metadata)

Metadata FieldExampleWhy It Matters
sourcehr_policy_2024.pdfSource attribution — users can verify
page12Precise reference
sectionMaternity LeaveHierarchical filtering
date2024-01-15Recency filtering
departmentHRAccess control / routing

πŸ€” How does the system know to filter by 2024?

User asks: “What was the remote work policy in 2024?” — How does “in 2024” become date = 2024?

1. LLM parses query
An LLM reads the question first, extracts {"date": "2024"}, then the retriever uses that as a filter. Most common.
2. UI filter
User picks “Year: 2024” from a dropdown before asking. No extraction needed.
3. Rule-based
Regex detects date patterns (e.g. \b20\d{2}\b) and maps to metadata. Simple but brittle.
Metadata enables hybrid filtering: vector search + structured filter. But filters don’t appear magically — your system must extract or collect them before retrieval. Deep dive in Lecture 5 (query routing).

Section 4 of 5

Vector Databases

How similarity search works at scale

The Search Problem at Scale

You have 1 million chunks, each with a 384-dim embedding. A user asks a question. How do you find the most similar vectors?

❌ Brute Force (KNN)

Compare query to every vector.

O(n · d) — 1M × 384 = 384M ops

~300ms per query. Perfect recall, unusable speed.

βœ… Approximate Nearest Neighbor (ANN)

Build an index that creates intelligent shortcuts.

O(log n) to O(n0.5) — sublinear

~1ms per query. 95%+ recall, 300× faster.

Three families of ANN algorithms

AlgorithmIdeaUsed By
HNSWMulti-layer navigable graph — coarse to fineChromaDB, Qdrant, pgvector
IVF (Inverted File)Partition space into clusters, search only nearby clustersFAISS, pgvector
PQ (Product Quantization)Compress vectors to reduce memory & speed up comparisonsFAISS (large-scale)
ANN trades 2–5% accuracy for 300× speed. HNSW is the most common. You don’t implement it — your vector database does it for you.

HNSW — How It Actually Works

Hierarchical Navigable Small World — the default algorithm in ChromaDB, Qdrant, and most vector databases.

πŸ—ΊοΈ The City Navigation Analogy

HNSW builds multiple layers of a navigable graph. To find the nearest chunk:

🌍 Top layer
Few nodes, long jumps
World map → Europe
πŸ—Ύ Mid layer
More nodes, medium jumps
Country map → Milan
πŸ™οΈ Bottom layer
All nodes, short steps
Street map → exact restaurant

πŸ” Search algorithm: greedy navigation

1. Start at a random node on the top layer

2. Greedily move to whichever neighbor is closest to the query vector

3. When no neighbor is closer → drop to the next layer at the same node

4. Repeat until the bottom layer → return the nearest nodes as results

Each layer dramatically narrows the search space. Total: ~20 hops instead of 1M scans.

You never implement HNSW yourself. collection.query() in ChromaDB runs it automatically. Understanding the intuition helps you tune it (e.g., ef_search, M parameters).

Malkov & Yashunin, “Efficient and Robust Approximate Nearest Neighbor Search Using HNSW Graphs”, IEEE TPAMI, 2020

Vector Database Landscape (2025)

Three categories. The trend: every major database now supports vectors. Choose based on your existing stack.

πŸ”· Purpose-Built Vector Databases

DatabaseTypeANNBest For
ChromaDBEmbedded (Python)HNSWPrototyping, learning — our lab
QdrantClient-ServerHNSWProduction RAG, advanced filtering
PineconeManaged CloudProprietaryZero-ops enterprise
WeaviateClient-ServerHNSWMulti-modal, hybrid search built-in

πŸ”Ά Traditional DBs + Vector Extensions

DatabaseExtensionANNBest For
PostgreSQLpgvectorIVFFlat / HNSWAlready on Postgres — no new infra
MongoDBAtlas Vector SearchHNSWAlready on Mongo — document + vector
ElasticsearchkNN search (8.x+)HNSWAlready on Elastic — keyword + vector
Neo4jVector IndexHNSWGraphRAG — relationships + vectors

πŸ”§ Libraries (not databases)

LibraryByANNBest For
FAISSMetaIVF, PQ, HNSWResearch, billion-scale, GPU
AnnoySpotifyRandom projection treesRead-heavy, memory-mapped
Decision guide: New project → ChromaDB (prototype) then Qdrant (production). Already have Postgres → pgvector. Already have MongoDB → Atlas Vector Search. Need graph relationships → Neo4j. Need billion-scale → FAISS.

The Complete RAG Pipeline

Five components, each with its own design decisions.

#ComponentKey DecisionOur Choice (Lab)
1Document LoaderFormat handlingpypdf
2Text SplitterChunk size, overlap, strategyRecursive, 400 / 80
3Embedding ModelQuality vs. speed vs. costMiniLM (384d)
4Vector DatabaseScale, features, hostingChromaDB
5Generator (LLM)Model, prompt templateGemini 2.0 Flash
The embedding model used at index time must be identical to the one used at query time — different models live in different vector spaces.

πŸ”¬ You will build this exact pipeline in the Lecture 5 combined lab.

Section 4 — Pipeline & Prompt Design

The RAG Prompt — Design Principles

You already master prompting from Lecture 3. Now apply it with grounding constraints specific to RAG.

The prompt template determines answer quality as much as retrieval does.

βœ… Grounding Instruction

“Answer based ONLY on the provided context” — prevents hallucination

βœ… Refusal Instruction

“If the answer is not in the context, say: I don’t have enough information”

βœ… Source Citation

“Always cite which document the information comes from”

❌ Common Mistake

Not including grounding → model ignores context and uses its own knowledge → hallucination

prompt = f"""Answer ONLY from the context below. If not found, say: I don’t have this information. Cite the source.
Context: {context}
Question: {question}"""

Section 4 β€” Pipeline & Prompt Design

RAG Failure Modes

Understanding failures helps you debug and improve your system.

FailureSymptomRoot CauseSolution
Wrong chunksAnswer about wrong topicEmbedding model too weakBetter model; hybrid search → L5
Chunks too smallIncomplete answersContext fragmentedIncrease chunk size
Chunks too largeIrrelevant noise in answerDiluted embeddingsDecrease chunk size
No relevant docsHallucinated answerMissing refusal promptAdd “I don’t know” instruction
Ignores contextUses own knowledgeWeak grounding promptStronger “ONLY context” instruction
Stale answersOutdated informationDocuments not re-ingestedSchedule periodic re-indexing
Most RAG failures are retrieval failures, not generation failures. Fix retrieval first.

Section 5 of 5

Decision Matrix

The most important decision you will make on every project

Three Tools, Three Problems

πŸ’¬

Prompting

Change the instructions

Model stays unchanged

Zero data, zero compute

πŸ“š

RAG

Give the model knowledge

External docs at query time

Low cost, fast updates

πŸ”§

Fine-Tuning

Change the model’s behavior

Retrain on your data

High cost, high customization

Each tool solves a different problem. Using the wrong tool wastes time and money.

The Decision Matrix

CriterionπŸ’¬ PromptingπŸ“š RAGπŸ”§ Fine-Tuning
Setup effortMinutesHoursDays–Weeks
Data requiredNoneDocuments100–10K examples
Compute cost$0Low ($)High ($$$)
Update speedInstantMinutesHours
CustomizationLowMediumHigh
HallucinationHigh riskReduced (grounded)Medium
Best forGeneral tasksKnowledge Q&AStyle / domain
Use Prompting first (minutes), then RAG if you need external knowledge (hours), then Fine-Tuning only if behavior/style needs changing (days). Each escalation multiplies cost by 10×.

Decision Flowchart

Does the model already know the answer well enough?

Yes → πŸ’¬ Prompting


↓ No

Is the knowledge in documents you can provide?

Yes → πŸ“š RAG


↓ No

Do you need specific behavior, format, or domain expertise?

Yes → πŸ”§ Fine-Tuning (Lecture 9)


↓ Still unsure?

Try RAG + better prompts first. Fine-tune only if that fails.

Cloud vs. Local Inference

☁️ Cloud API🏠 Local Inference
Setup time5–10 min (API key + env)15–30 min with Ollama / LM Studio
2–4 h only if full CUDA GPU drivers needed
Cost modelPer token ($)Fixed (hardware cost)
PrivacyData leaves premisesData stays local
ModelsGPT-4, Gemini, ClaudeLLaMA, Mistral, Phi
QualityBest availableSmaller, quantized
ToolsAPI callsOllama, vLLM, LM Studio, πŸ€— HuggingFace
Start with cloud (development & prototyping). Move to local when privacy, cost, or latency requires it.

Apply the Matrix — 5 Real Scenarios

1. “Summarize this meeting transcript”

→ πŸ’¬ Prompting — general task, model already knows how. Just good instructions.

2. “Answer questions about our HR policies”

→ πŸ“š RAG — knowledge is in company documents. Ground answers in retrieved chunks.

3. “Customer support chatbot for our product manuals”

→ πŸ“š RAG (not prompting!) — domain-specific product knowledge. Prompting alone would hallucinate specs.

4. “Auto-categorize incoming support tickets”

→ πŸ’¬ Prompting first, then πŸ”§ Fine-Tune if accuracy isn’t enough. Start simple, escalate only if needed.

5. “Generate medical reports in our specific format”

→ πŸ”§ Fine-Tuning — needs specific style, clinical terminology, domain language.

Lecture 4 — Key Takeaways

1. RAG = Retrieve β†’ Augment β†’ Generate — give the model an open book

2. Search evolved from keywords (TF-IDF, BM25) to meaning (dense embeddings)

3. Chunking determines quality — 300–500 tokens, recursive, with overlap

4. Vector databases use HNSW for millisecond similarity search at scale

5. Prompt design matters — grounding, refusal, and citation instructions

6. Prompting β†’ RAG β†’ Fine-Tuning — always try the simpler approach first

7. Most RAG failures are retrieval failures — fix chunking and embeddings before touching the LLM

❓

Questions?

Thank you!


Kamyar Zeinalipour — Zucchetti LLM Course

Next → Lecture 5: Advanced RAG & Intelligent Routing

Theory: Re-ranking · HyDE · Query decomposition · Semantic routing

πŸ”¬ Combined Lab: RAG Pipeline (L4) + Query Router (L5) — back-to-back hands-on session