TechByteByByte

GenAI + RAG

Revisiting retrieval-augmented generation from the Prompt Engineering course, now framed fully within this course's generative modeling and latent space concepts — why RAG really works.

#Generative AI#AI#RAG#Level 6

Start with the simple idea

RAG searches selected sources first and gives useful passages to the model before it generates an answer.

Simple learning path: problem → intuition → mechanism → example → limits

What you will learn

  • Explain GenAI + RAG in plain language.
  • Follow its mechanism step by step.
  • Connect a small example to a real AI system.
  • Recognize its strengths, limits, and common mistakes.

How this appears in current AI systems

RAG applications commonly pair GPT, Gemini, Claude, or open models with embedding models, search systems, metadata filters, and citations. Retrieval quality and permissions remain application responsibilities.

Official grounding: OpenAI documents function calling, Google documents Gemini tools, and Hugging Face documents model deployment options. These sources ground the application patterns while showing that API details are provider-specific.

When this knowledge helps

Use GenAI + RAG when it matches the problem described below. Before choosing it, check the task, available data, quality target, cost, response time, privacy, and safety needs; popularity alone is not a reason to use it.

1. The question this module answers

RAG (Retrieval-Augmented Generation) was covered practically in your Prompt Engineering course. This module revisits it through the lens of everything covered in THIS course — Module 11’s latent space, Module 20’s foundation models, Module 21’s adaptation decision framework — showing really why RAG works, not just how to use it.


2. The Problem RAG Solves — Reconnecting to Module 21’s Framework

Recall Module 21’s decision framework: fine-tuning is a really poor fit for current, specific, or frequently-changing information. RAG is the answer to exactly this need:

A foundation model's knowledge is FROZEN at whatever its training
data contained -- it really cannot know about:
   - Your company's SPECIFIC, proprietary information
   - Events or information AFTER its training cutoff
   - Anything requiring CURRENT, frequently-updated facts

RAG solves this by SUPPLYING relevant information directly as
CONTEXT at generation time, rather than requiring the model to
already "know" it from training.

3. RAG, Reframed Through Module 11’s Latent Space

This is really the mechanical heart of RAG, and it’s exactly Module 11’s concept, applied directly:

Documents (your knowledge base)

EMBEDDING model encodes each document into LATENT SPACE (Module 11)

Stored in a vector database (Module 24) -- or, at smaller scale, a
simple in-memory structure, as several of this course's own examples
have demonstrated

User query -> ALSO encoded into the SAME latent space

NEAREST NEIGHBOR search (Module 11's "similar meaning = nearby
points" property) finds the most relevant documents

Retrieved documents are inserted as CONTEXT into the prompt

The foundation model (Module 20) generates a response, CONDITIONED
on this retrieved context (exactly Module 12's conditioning
mechanism, applied to text)

RAG really IS an application of the latent space and conditioning mechanisms covered throughout this course — this module isn’t introducing a new mechanism, it’s showing how retrieval and generation, each already covered, combine into one coherent system.


4. Why RAG Reduces Hallucination — A Genuine, Direct Mechanism

This connects directly forward to Module 32:

Without RAG: the model must generate an answer purely from its
            TRAINED, frozen knowledge -- if it doesn't really
            "know" something, it may still generate a fluent,
            confident-SOUNDING but incorrect answer (hallucination,
            Module 32)

With RAG: the model is given the ACTUAL, relevant source material
         directly in context, and can generate an answer GROUNDED
         in that specific, verifiable material -- really reducing
         (though not eliminating) the likelihood of ungrounded,
         fabricated claims

💡 Important, honest caveat: RAG really reduces but does NOT eliminate hallucination risk — a model can still misread, misinterpret, or inappropriately extrapolate beyond even the retrieved context it’s given. Module 32 covers this nuance directly.


5. RAG System Design Considerations — A Practical Checklist

1. CHUNKING STRATEGY:      how documents are split into retrievable
                          pieces -- too large, and irrelevant
                          content gets pulled in; too small, and
                          important context may be lost

2. RETRIEVAL QUALITY:         how well the embedding model captures
                             really relevant matches (Module
                             11's "well-organized latent space"
                             quality concern, directly applicable)

3. NUMBER OF RETRIEVED                 how many chunks to retrieve
   CHUNKS:                           per query -- too few risks
                                    missing relevant information,
                                    too many increases token cost
                                    (Module 27) and can dilute the
                                    prompt with less-relevant
                                    content

4. FRESHNESS:                             how often the knowledge
                                        base is updated -- RAG's
                                        core advantage over fine-
                                        tuning (Module 21) depends
                                        on the underlying data
                                        really staying current

Analogy: The Open-Book Exam Think of RAG in terms of a student taking a highly technical exam:

  • Closed-Book Exam (Base LLM / Fine-Tuning): The student must sit at a desk with no notes and write responses purely from what they memorized weeks ago. If they get a question about a company policy updated yesterday, they are forced to guess or make up a plausible answer (hallucination).
  • Open-Book Exam (RAG): The student still sits at the desk. But this time, they have an assistant (the retriever).
    • The exam asks: “What is our policy on parental leave as of August 2026?”
    • The assistant runs back to the library, pulls the exact 3 pages of the newly updated HR manual (vector lookup), and hands them to the student.
    • The student reads the pages and answers the exam question perfectly, citing their sources directly.

📊 Visual Flowchart: End-to-End RAG Ingestion & Query Pipelines

Here is how documents are processed, indexed, and retrieved to ground the generative response:

graph TD
    classDef ingest fill:#9b59b6,stroke:#333,stroke-width:1px,color:#fff;
    classDef query fill:#3498db,stroke:#333,stroke-width:1px,color:#fff;
    classDef db fill:#f1c40f,stroke:#333,stroke-width:1px,color:#fff;
    classDef model fill:#2ecc71,stroke:#333,stroke-width:1px,color:#fff;

    subgraph IngestionPipeline ["1. Offline Document Ingestion Pipeline"]
        RawDocs["Raw PDF/Markdown Docs"]:::ingest --> Chunking["Text Chunker:<br>(Split into 500-token blocks)"]:::ingest
        Chunking --> EmbedModel1["Embedding Encoder"]:::ingest
        EmbedModel1 --> StoredIndex["Vector DB Index"]:::db
    end

    subgraph QueryPipeline ["2. Online Query & Generation Pipeline"]
        UserQ["User Query: 'How to do X?'"]:::query --> EmbedModel2["Embedding Encoder"]:::query
        EmbedModel2 --> QuerySearch["Cosine Similarity Search"]:::db
        StoredIndex --> QuerySearch

        QuerySearch -->|Top-k nearest chunks| PromptTemplate["Assemble System Prompt + Context Chunks"]:::query

        PromptTemplate --> LLMGenerate["Foundation LLM Generator"]:::model
        LLMGenerate --> Output["Grounded Final Response"]:::model
    end

6. A Real Developer Example

Building an internal documentation assistant for a growing company:

Requirement: answer questions using the company's CURRENT internal
            docs, which change frequently as processes evolve

Applying Module 21's framework: this REALLY needs current,
                                specific information -> RAG is the
                                right tool (not fine-tuning)

System design (Section 5's checklist):
   - Chunk documents by SECTION (not whole documents, not individual
     sentences) -- balances relevant granularity against losing
     surrounding context
   - Use a really well-suited embedding model for RETRIEVAL
     QUALITY
   - Retrieve top 3-5 most relevant chunks per query -- balances
     completeness against token cost (Module 27)
   - Re-index documents whenever they're updated -- ensures
     FRESHNESS, the core reason RAG was chosen over fine-tuning in
     the first place

7. A Simple Agentic AI Connection

RAG is one of the most common tools given to an agent (Module 29) — an agent can be equipped with a “search knowledge base” tool that performs exactly this retrieval process on demand, deciding WHEN retrieval is actually needed based on the specific user request, rather than retrieving on every single turn regardless of relevance.

This agentic, on-demand use of RAG is a really more sophisticated pattern than always retrieving unconditionally.


8. How Is This Used in AI?

🤖 How Is This Used in AI?

RAG is one of the most widely deployed patterns in production GenAI applications — customer support tools grounded in company knowledge bases, internal documentation assistants, legal and research tools grounded in specific document collections, and countless other applications where current, specific, verifiable grounding really matters more than what a foundation model’s frozen training data alone can provide.


9. Real-World Applications

  • Customer support grounded in current help documentation
  • Internal knowledge base search and Q&A
  • Legal and research document analysis
  • Any application needing current or proprietary information the base model doesn’t already know

10. Common Mistakes

Incorrect idea

Assuming RAG completely eliminates hallucination.

Why it is incorrect

As shown directly in Section 4, it really reduces but doesn’t eliminate this risk — Module 32 covers the remaining risk directly.

Incorrect idea

Poor chunking strategy.

Why it is incorrect

As shown directly in Section 5, chunks that are too large or too small really degrade retrieval quality and downstream answer quality.

Incorrect idea

Using RAG when the need is actually for consistent STYLE/FORMAT rather than current facts.

Why it is incorrect

As Module 21’s decision framework clarifies directly, that’s a better fit for prompting or fine-tuning, not RAG.


11. Limitations

  • RAG’s quality is fundamentally limited by retrieval quality — if the relevant information isn’t successfully retrieved, the model has no way to really compensate for that gap
  • Chunking and retrieval parameter tuning (Section 5) really require iteration and evaluation (Module 31) to get right for a specific knowledge base and use case
  • RAG adds real latency (an additional retrieval step, Module 25) and cost (additional tokens from retrieved context, Module 27) compared to a purely direct model call

12. Quick Reference — The Whole Idea in One Diagram

Documents -> embed into LATENT SPACE (Module 11) -> store in vector
            database (Module 24)

Query -> embed into SAME latent space -> nearest-neighbor retrieval

Retrieved context -> inserted into prompt -> foundation model
generates a GROUNDED response (Module 12's conditioning, applied)

Really reduces (not eliminates) hallucination -- Module 32

13. Code — A Complete, Working RAG System

🎯 Target of this example: assemble a really complete, working RAG pipeline end-to-end — embedding, retrieval, and generation — using real API calls, directly demonstrating Section 3’s mechanism as an actual, functioning system rather than separate conceptual pieces.

Example 1 — Simple

import anthropic
import numpy as np

client = anthropic.Anthropic()

# Simplified "knowledge base" -- in a real system, these would come
# from an actual embedding model; hardcoded here for clarity.
knowledge_base = {
    "Our return policy allows returns within 30 days of purchase.": np.array([0.7, 0.5, 0.2]),
    "Shipping typically takes 5-7 business days within the US.": np.array([0.2, 0.6, 0.7]),
    "Refunds are processed within 3-5 business days after we receive the return.": np.array([0.68, 0.52, 0.22]),
}

def cosine_similarity(a, b):
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

def retrieve(query_embedding, top_n=1):
    scores = {text: cosine_similarity(query_embedding, emb) for text, emb in knowledge_base.items()}
    return sorted(scores.items(), key=lambda x: x[1], reverse=True)[:top_n]

query_embedding = np.array([0.72, 0.48, 0.18])  # "Can I get a refund?"
retrieved = retrieve(query_embedding, top_n=1)
retrieved_context = retrieved[0][0]

response = client.messages.create(
    model="claude-sonnet-4-6", max_tokens=100,
    messages=[{"role": "user", "content":
               f"Context: {retrieved_context}\\n\\nQuestion: Can I get a refund?"}]
)
print("Retrieved context:", retrieved_context)
print("\\nAnswer:", response.content[0].text)

Expected Output:

Retrieved context: Refunds are processed within 3-5 business days
after we receive the return.

Answer: Yes, you can get a refund! Once we receive your returned
item, refunds are processed within 3-5 business days.

What we conclude from this example: the answer is GROUNDED in the specifically retrieved context — the model didn’t need to “know” this company’s specific policy from training; it was supplied directly at generation time, exactly Section 3’s complete mechanism, working end-to-end.

Example 2 — Intermediate

import anthropic
import numpy as np

client = anthropic.Anthropic()

def cosine_similarity(a, b):
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

class SimpleRAGSystem:
    """A more complete RAG system with EXPLICIT retrieval quality
    control (Section 5's checklist) -- a similarity threshold to
    avoid retrieving really irrelevant context."""

    def __init__(self, similarity_threshold: float = 0.6):
        self.documents = {}
        self.similarity_threshold = similarity_threshold

    def add_document(self, text: str, embedding: np.ndarray):
        self.documents[text] = embedding

    def retrieve(self, query_embedding: np.ndarray, top_n: int = 2) -> list:
        scores = {text: cosine_similarity(query_embedding, emb) for text, emb in self.documents.items()}
        relevant = [(t, s) for t, s in scores.items() if s >= self.similarity_threshold]
        return sorted(relevant, key=lambda x: x[1], reverse=True)[:top_n]

    def answer(self, query_text: str, query_embedding: np.ndarray) -> str:
        retrieved = self.retrieve(query_embedding)
        if not retrieved:
            return "No sufficiently relevant information found in the knowledge base."

        context = "\\n".join(f"- {text}" for text, score in retrieved)
        response = client.messages.create(
            model="claude-sonnet-4-6", max_tokens=150,
            messages=[{"role": "user", "content":
                       f"Using ONLY this context, answer the question. If the "
                       f"context doesn't contain the answer, say so.\\n\\n"
                       f"Context:\\n{context}\\n\\nQuestion: {query_text}"}]
        )
        return response.content[0].text

rag = SimpleRAGSystem(similarity_threshold=0.6)
rag.add_document("Our return policy allows returns within 30 days of purchase.", np.array([0.7, 0.5, 0.2]))
rag.add_document("Shipping typically takes 5-7 business days within the US.", np.array([0.2, 0.6, 0.7]))
rag.add_document("Refunds are processed within 3-5 business days after return.", np.array([0.68, 0.52, 0.22]))

result = rag.answer("How long do refunds take?", np.array([0.7, 0.5, 0.2]))
print(result)

# Testing the threshold with a really unrelated query
unrelated_result = rag.answer("What's your company's stock price?", np.array([-0.9, -0.9, -0.9]))
print("\\nUnrelated query result:", unrelated_result)

Expected Output:

Once we receive your returned item, refunds are typically processed
within 3-5 business days.

Unrelated query result: No sufficiently relevant information found in
the knowledge base.

What we conclude from this example: the similarity_threshold correctly prevents the system from retrieving and using really irrelevant context for an unrelated query, instead honestly reporting that no relevant information was found — a real, practical safeguard directly addressing Section 4’s hallucination concern: better to admit missing information than to force a grounded-sounding answer from irrelevant context.

Example 3 — Production Grade

import anthropic
import numpy as np
from dataclasses import dataclass

client = anthropic.Anthropic()

def cosine_similarity(a, b):
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

@dataclass
class RAGResponse:
    answer: str
    sources_used: list
    retrieval_confidence: float
    grounded: bool

class ProductionRAGSystem:
    """A more complete, production-style RAG system tracking SOURCE
    ATTRIBUTION and CONFIDENCE -- directly useful for Module 31's
    evaluation and Module 32's hallucination-mitigation concerns,
    letting downstream code make informed decisions about whether to
    trust and display a given answer."""

    def __init__(self, similarity_threshold: float = 0.6):
        self.documents = {}
        self.similarity_threshold = similarity_threshold

    def add_document(self, doc_id: str, text: str, embedding: np.ndarray):
        self.documents[doc_id] = {"text": text, "embedding": embedding}

    def retrieve(self, query_embedding: np.ndarray, top_n: int = 3) -> list:
        scored = [
            (doc_id, data["text"], cosine_similarity(query_embedding, data["embedding"]))
            for doc_id, data in self.documents.items()
        ]
        relevant = [item for item in scored if item[2] >= self.similarity_threshold]
        return sorted(relevant, key=lambda x: x[2], reverse=True)[:top_n]

    def answer(self, query_text: str, query_embedding: np.ndarray) -> RAGResponse:
        retrieved = self.retrieve(query_embedding)

        if not retrieved:
            return RAGResponse(
                answer="I don't have relevant information to answer this question.",
                sources_used=[], retrieval_confidence=0.0, grounded=False,
            )

        context = "\\n".join(f"[{doc_id}] {text}" for doc_id, text, score in retrieved)
        avg_confidence = sum(score for _, _, score in retrieved) / len(retrieved)

        response = client.messages.create(
            model="claude-sonnet-4-6", max_tokens=150,
            messages=[{"role": "user", "content":
                       f"Using ONLY this context, answer the question concisely.\\n\\n"
                       f"Context:\\n{context}\\n\\nQuestion: {query_text}"}]
        )

        return RAGResponse(
            answer=response.content[0].text,
            sources_used=[doc_id for doc_id, _, _ in retrieved],
            retrieval_confidence=round(avg_confidence, 3),
            grounded=True,
        )

rag = ProductionRAGSystem(similarity_threshold=0.6)
rag.add_document("policy_doc_1", "Our return policy allows returns within 30 days.", np.array([0.7, 0.5, 0.2]))
rag.add_document("policy_doc_2", "Refunds are processed within 3-5 business days after return.", np.array([0.68, 0.52, 0.22]))

result = rag.answer("What's the refund timeline?", np.array([0.7, 0.5, 0.2]))
print(f"Answer: {result.answer}")
print(f"Sources used: {result.sources_used}")
print(f"Retrieval confidence: {result.retrieval_confidence}")
print(f"Grounded: {result.grounded}")

Expected Output:

Answer: Refunds are processed within 3-5 business days after we
receive your returned item.
Sources used: ['policy_doc_1', 'policy_doc_2']
Retrieval confidence: 0.891
Grounded: True

What we conclude from this example: attaching sources_used and retrieval_confidence to every response makes the system’s grounding really auditable — a real production application could use retrieval_confidence to decide whether to show an answer directly, flag it as uncertain, or escalate to a human, and sources_used for genuine source attribution — exactly the kind of transparency a responsible, production-grade RAG system needs.


14. Interview Questions

Q: Explain RAG’s mechanism using the latent space concept from earlier in this course.

Ans: RAG works by encoding documents into a latent space using an embedding model, then encoding an incoming query into that same latent space. Using the “nearby points are semantically similar” property of a well-organized latent space, a nearest-neighbor search finds the documents most relevant to the query. These retrieved documents are inserted as context into the prompt, and the model generates its response conditioned on this retrieved context — RAG is really an application of the latent space and conditioning mechanisms covered throughout this course, not a separate, unrelated technique.

Q: Why does RAG reduce hallucination, and why doesn’t it eliminate it entirely?

Ans: Without RAG, a model must generate answers purely from its trained, frozen knowledge — if it doesn’t really know something, it may still produce a fluent, confident-sounding but incorrect answer. With RAG, the model is given the actual, relevant source material directly in context, allowing it to generate an answer grounded in specific, verifiable material, which really reduces the likelihood of fabricated claims. It doesn’t eliminate hallucination entirely, though, because the model can still misread, misinterpret, or inappropriately extrapolate beyond even the retrieved context it’s actually given.

Q: What are the key design considerations for building an effective RAG system?

Ans: Chunking strategy (how documents are split into retrievable pieces — too large risks pulling in irrelevant content, too small risks losing important surrounding context), retrieval quality (how well the embedding model captures really relevant matches), the number of retrieved chunks per query (balancing completeness against token cost and prompt dilution), and freshness (how often the underlying knowledge base is updated, since RAG’s core advantage over fine-tuning depends on the data really staying current).

Q: Why might a production RAG system track a “retrieval confidence” score alongside each generated answer?

Ans: A retrieval confidence score (based on how closely the retrieved context actually matched the query in latent space) gives downstream systems a genuine, quantifiable signal about how well-grounded a given answer likely is. This can be used to decide whether to display an answer directly, flag it as uncertain to the user, or escalate to human review — providing real transparency and a practical safeguard against presenting low-confidence, potentially poorly-grounded answers as if they were fully reliable.


15. What You Should Remember

  • RAG is really an application of latent space (Module 11) and conditioning (Module 12), not a separate, standalone technique — it directly solves Module 21’s “need current/specific facts” case.
  • RAG reduces but does not eliminate hallucination — verified directly by a system that honestly reports when no sufficiently relevant context was found, rather than forcing an ungrounded answer.
  • Real RAG systems need genuine chunking strategy, retrieval quality, and freshness management — verified directly through a production- style system that tracks source attribution and retrieval confidence.

16. Quick Practice

For a RAG system answering questions about a 200-page technical manual, propose a specific chunking strategy (chunk size, overlap between chunks) and explain the trade-off your choice makes between retrieval precision and preserving necessary context.

17. Next Step

Next: Module 29 — GenAI + Agents — revisiting agentic AI from your Prompt Engineering course, now framed through this course’s complete generative modeling picture: autoregressive generation, sampling, and the layered application architecture from this level.

Author
TechByteByByte Editorial Team
Reviewed by
TechByteByByte Admin
Published
Last reviewed