DEV Community

Cover image for What Is Retrieval-Augmented Generation (RAG)?
THE TISA
THE TISA

Posted on

What Is Retrieval-Augmented Generation (RAG)?

A support engineer asks a company chatbot what the refund policy is for orders placed after a warehouse closure last month. The chatbot, built on a general-purpose LLM, answers confidently. It is also wrong, because the policy changed three weeks ago and the model's training data stops long before that. This is the moment most teams discover they don't have an "AI problem," they have a "the model doesn't know what I know" problem.

Retrieval-Augmented Generation, or RAG, is the architecture that most teams reach for to fix exactly this. Instead of retraining a model every time your data changes, you give the model a way to look things up before it answers. It is not a single library or product. It is a pattern: search first, then generate, and hand the model real documents instead of asking it to recall facts from memory.

This matters right now because RAG has quietly become the default way companies connect large language models to their own data. The retrieval-augmented generation market was estimated at $1.94 billion in 2025 and is projected to reach $9.86 billion by 2030, according to a MarketsandMarkets report, a 38.4% compound annual growth rate. Gartner has also flagged retrieval-heavy architectures like GraphRAG as one of its top data and analytics trends for 2026, predicting that 40% of enterprises will have adopted GraphRAG techniques by 2029 to improve factual accuracy in LLM outputs.

If you build software and you've been asked to make an LLM "know about our stuff," this article is for you. You'll learn what RAG actually is, how the pipeline works end to end, when to use it instead of (or alongside) fine-tuning, how to build a basic version yourself, and the mistakes that quietly wreck retrieval quality in production.

What Is RAG, Exactly?

Retrieval-Augmented Generation combines two things large language models are individually mediocre at combining on their own: finding specific facts, and writing coherent language. RAG splits the job. A retrieval system finds the facts. The LLM writes the answer using those facts as grounding.

The term comes from a 2020 paper by Patrick Lewis and colleagues at Facebook AI Research (now Meta AI), published at NeurIPS, titled "Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks." The original architecture paired a dense passage retriever with a pretrained sequence-to-sequence generator (BART), and jointly fine-tuned both pieces so the retriever learned to surface passages that actually helped the generator produce a correct answer. That's a more tightly coupled system than most people build today.

What almost everyone builds in 2026 is a looser variant sometimes called "naive RAG": chunk your documents, embed them, store the embeddings in a vector index, retrieve the top-k most relevant chunks for a given query, and stuff them into the prompt alongside the user's question. It's simpler than the original paper's design, and for most applications it's a perfectly good starting point.

The key idea that survives from the 2020 paper into every modern implementation is this: the model's knowledge is split into two kinds. Parametric memory is what's baked into the model's weights during training. Non-parametric memory is external data the model can query at inference time. RAG lets you swap out or update the non-parametric half without touching the model at all.

Why RAG Matters

Three problems push developers toward RAG, usually in this order:

Knowledge cutoff. Every LLM has a training cutoff date. It cannot know about your product launch from last week, a regulation that changed last month, or a support ticket filed an hour ago. Retrieval gives it a way to see current information without retraining.

Hallucination. When a model doesn't know something, it doesn't reliably say "I don't know." It generates a plausible-sounding guess. Grounding the model in retrieved source documents gives it something real to work from instead of pattern-completing from training data. This is not a complete fix (a retriever can return the wrong document, and a model can still misread a correct one), but it measurably helps. One 2024 study auditing LLM-assisted causal discovery found the average hallucination rate across six models dropped from 50% before RAG to roughly 14% after adding retrieval on the same tasks, a result specific to that experiment but directionally consistent with what most teams observe: grounding reduces, but does not eliminate, fabrication.

Cost and iteration speed. Fine-tuning a model on your proprietary data requires curating a training set, running training jobs, evaluating the result, and repeating the cycle every time your data changes. Updating a RAG system usually means re-indexing a document. That's a much shorter feedback loop, and it's why RAG became the default first move for most "make the AI know about X" projects.

How RAG Works: The Pipeline

At a high level, a RAG system has two phases: an offline indexing phase, and an online query phase.

Indexing (offline, happens whenever your data changes):

  1. Collect your source documents (PDFs, wiki pages, database rows, support tickets, whatever knowledge you want the model to draw on).
  2. Split them into chunks small enough to be individually meaningful and retrievable.
  3. Convert each chunk into a vector embedding using an embedding model.
  4. Store the embeddings, along with the original text and metadata, in a vector database.

Query (online, happens every time a user asks something):

  1. Embed the user's query with the same embedding model used for indexing.
  2. Search the vector database for the chunks whose embeddings are closest to the query embedding.
  3. Optionally rerank those candidates with a more precise (and more expensive) model.
  4. Insert the top chunks into a prompt template along with the user's question.
  5. Send the prompt to the LLM and return its answer, usually with citations back to the source chunks.

Here's the same flow as a diagram in words: documents → chunks → embeddings → vector store, then separately, query → embedding → similarity search → top chunks → prompt → LLM → answer.

The two phases run on different schedules. Indexing might happen nightly, or in real time as documents change. Querying happens on every single user request, so its latency budget is much tighter, usually well under a second for the retrieval step if you want a responsive product.

RAG vs. Fine-Tuning

This is the comparison developers ask about most, and the honest answer is that the two techniques solve different problems and are often used together.

Factor RAG Fine-Tuning
What it changes External data the model reads at query time The model's own weights
Best for Facts that change often, source attribution, large or growing knowledge bases Teaching a consistent style, format, or behavior pattern
Update cycle Re-index a document (minutes) Retrain and redeploy (hours to days)
Source citations Straightforward, since you know which chunk was retrieved Not possible, the knowledge is baked into weights
Upfront cost Lower, mostly infrastructure Higher, needs a labeled training set and compute
Failure mode Retriever returns the wrong or no relevant chunk Model overfits, forgets general capabilities, or needs retraining for every data change

A useful way to think about it: RAG is for what the model needs to know, fine-tuning is for how the model should behave. If you want an assistant that always follows your company's specific support-ticket format, fine-tuning (or even just a good system prompt) does that well. If you want the assistant to correctly answer questions about a policy that changed yesterday, RAG is the right tool, because you can update the source document without touching the model at all.

They are not mutually exclusive. Some production systems fine-tune a model to be better at using retrieved context (following citation formats, refusing to answer when retrieval comes up empty) and then run that fine-tuned model inside a RAG pipeline. GitHub Copilot's code completion is a common example of the opposite pattern: a model fine-tuned heavily on code, then optionally paired with retrieval over your specific repository for up-to-date, project-specific context.

Core Concepts You Need to Know

Embeddings. A numeric vector representation of text such that semantically similar text produces vectors that are close together in that vector space. Two sentences about refund policies will land near each other even if they don't share exact words, which is what makes semantic search possible in the first place, as opposed to plain keyword matching.

Vector database. A database optimized to store embeddings and answer "find me the k nearest vectors to this query vector" efficiently, usually with an approximate nearest neighbor index like HNSW so it stays fast at millions or billions of vectors.

Chunking. The process of splitting documents into retrievable pieces. Chunk size is one of the highest-leverage decisions in a RAG pipeline. Chunks that are too small lose context; chunks that are too large dilute the embedding signal because they mix multiple topics into one vector.

Top-k retrieval. How many chunks you pull back per query. Too few and you miss relevant context; too many and you flood the prompt with noise (and pay for more tokens).

Reranking. A second pass over your initial candidate chunks using a more accurate but slower model (typically a cross-encoder) to reorder them by actual relevance before they hit the prompt. Cheap vector search casts a wide net; reranking narrows it.

Hybrid search. Combining dense vector search with traditional sparse keyword search (like BM25) so you catch both semantic matches and exact-term matches, which matters a lot for things like product SKUs, error codes, or proper nouns that embeddings sometimes blur together.

Grounding. The general principle of making the model's output depend on retrieved evidence rather than only on parametric memory.

Building a Basic RAG Pipeline (Step by Step)

Here's a minimal, working example in Python using chromadb for local vector storage and the Anthropic API for generation. This isn't production-hardened, but it shows every piece of the pipeline explicitly so you can see what each step is actually doing.

import chromadb
import anthropic

# --- 1. Set up a local vector store ---
chroma_client = chromadb.Client()
collection = chroma_client.create_collection(name="support_docs")

# --- 2. Chunk and index your documents ---
# In a real system, this would come from parsing PDFs, wiki pages, etc.
documents = [
    "Refunds for orders affected by a warehouse closure are processed "
    "automatically within 5 business days, no return request needed.",
    "Standard returns must be initiated within 30 days of delivery "
    "through the account portal.",
    "Digital products are non-refundable once the download has started.",
]

# Chroma will embed these for us using its default embedding function,
# but in production you'd typically call an embedding model explicitly
# so you control exactly which model is used for both indexing and querying.
collection.add(
    documents=documents,
    ids=[f"doc_{i}" for i in range(len(documents))],
)

# --- 3. Retrieve relevant chunks for a query ---
def retrieve(query: str, top_k: int = 2) -> list[str]:
    results = collection.query(query_texts=[query], n_results=top_k)
    return results["documents"][0]

# --- 4. Build a grounded prompt and generate an answer ---
client = anthropic.Anthropic()

def answer_question(query: str) -> str:
    chunks = retrieve(query)
    context = "\n\n".join(f"- {chunk}" for chunk in chunks)

    prompt = f"""Answer the question using ONLY the context below.
If the context doesn't contain the answer, say you don't know.

Context:
{context}

Question: {query}"""

    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=300,
        messages=[{"role": "user", "content": prompt}],
    )
    return response.content[0].text

print(answer_question("Do I need to request a refund for the warehouse closure?"))
Enter fullscreen mode Exit fullscreen mode

A few things worth calling out in this example:

  • The instruction "answer using ONLY the context below, say you don't know if it's missing" is doing real work. Without it, the model will happily fall back on parametric memory when retrieval comes up short, which reintroduces the hallucination risk you added RAG to avoid.
  • top_k=2 is a real design decision, not a placeholder. In production you'd tune this against a labeled evaluation set, not guess.
  • This example skips reranking and hybrid search for clarity. Add those once you've confirmed the basic pipeline works and you have a way to measure whether they actually improve your results.

Practical Example: A Support Docs Chatbot

Problem: A SaaS company's support team fields the same 40 questions repeatedly, and answers live scattered across a help center, a Notion workspace, and old Slack threads. New hires give inconsistent answers.

Solution: A RAG-based chatbot indexed over the help center and a curated set of Notion pages, exposed through the existing support widget.

How it works: Support articles are chunked at roughly 500 tokens with 15% overlap, embedded, and stored in Qdrant. When a customer asks a question, the query is embedded, the top 5 chunks are retrieved, reranked down to the top 3, and passed to the LLM with instructions to cite the source article for every claim and to escalate to a human when no relevant chunk is found above a confidence threshold.

Technology: Qdrant for the vector store, an off-the-shelf embedding model, a cross-encoder reranker, and an LLM for generation, orchestrated with a lightweight custom pipeline rather than a heavy framework.

Implementation: Roughly two weeks for a first version: one week to build the ingestion pipeline (parsing, chunking, embedding, indexing) and one week to build the query pipeline and tune retrieval quality against a hand-labeled set of real support questions.

Benefits: Consistent answers regardless of which human wrote the source article, answers that update automatically when the source article is edited, and citations that let support staff verify an answer in seconds instead of re-researching it.

Limitations: The system is only as good as its source documents. If the help center has stale or contradictory articles, the chatbot will confidently retrieve and cite the wrong one. It also struggles with questions that require synthesizing information across many articles rather than pulling from one or two, which is a known weak spot of simple top-k retrieval.

Real-World Use Cases

  • Customer support and internal help desks. The most common first deployment, because the source documents (help articles, runbooks) already exist and are naturally chunkable.
  • Legal and compliance document review. Retrieval over contracts or regulations with citations back to the exact clause, so a human can verify the answer rather than trust it blindly.
  • Codebase-aware coding assistants. Retrieving relevant functions, docs, or past commits from your own repository so suggestions reflect your actual codebase instead of generic patterns.
  • Research and literature assistants. Retrieval over a corpus of papers or internal reports, useful anywhere the "correct" answer depends on a specific source rather than general knowledge.
  • Financial and SEC filing analysis. Answering questions like "what was the revenue growth for this company last quarter" by retrieving from the actual filing rather than trusting a model's memorized (and likely outdated) figures.

Tools and Technologies

You don't need every layer below for a first version, but it helps to know what each piece is for.

Layer What it does Common options
Document parsing Extract clean text from PDFs, HTML, Office docs unstructured, LlamaParse, PyMuPDF
Chunking Split text into retrievable units LangChain text splitters, custom recursive splitters
Embedding model Convert text to vectors OpenAI, Cohere, Voyage AI, open-source models via Sentence Transformers
Vector database Store and search vectors Pinecone, Qdrant, Weaviate, pgvector, Chroma
Reranker Reorder candidates by relevance Cohere Rerank, cross-encoder models
Orchestration Wire the pipeline together LangChain, LlamaIndex, custom code
Generation Produce the final answer Claude, GPT-family models, open-source LLMs

A rough guide to picking a vector database: if you're already running PostgreSQL and have under roughly 10 million vectors, pgvector is the boring, reliable choice with the least new infrastructure to operate. If you want a managed service with minimal ops work, Pinecone gets you to production fastest, at a real cost premium once query volume grows. If you want strong self-hosted performance with good metadata filtering, Qdrant is a common pick. For local development and quick prototyping, Chroma has the easiest onboarding of the bunch.

Common Mistakes

Treating chunk size as a solved problem. Copying a chunk_size=1000 default from a tutorial and never revisiting it is one of the most common causes of mediocre retrieval. The right size depends on your content type and your embedding model, and you should validate it against real queries, not assume it.

No evaluation set. Teams tune retrieval by vibes, trying a change and eyeballing a few answers. Without a labeled set of realistic questions and expected source chunks, you can't tell if a change actually helped or just moved the failures around.

Skipping reranking entirely. Vector search alone is a wide, noisy net. A cheap reranking pass over your top 20 or so candidates before you pick the final top-k often improves relevance more than switching embedding models does.

Letting the model fall back on parametric memory. If your prompt doesn't explicitly instruct the model to only use retrieved context and to say when it doesn't know, you haven't actually solved the hallucination problem, you've just added a retrieval step the model can ignore.

No source attribution. Returning an answer with no way to trace it back to the original document makes it hard for anyone, human or automated eval, to check whether the system got it right.

Ignoring stale or contradictory source data. RAG systems inherit the quality of what they retrieve from. A knowledge base full of outdated or duplicate documents will produce confidently wrong answers just as easily as a bare LLM will.

Best Practices

Start with the simplest pipeline that could work. Fixed-size or recursive chunking, a single embedding model, top-k vector search, no reranking. Measure it against a real question set before adding complexity.

Build your evaluation set early, even a small one. Twenty to fifty realistic questions with known correct source documents will tell you more about where your pipeline is failing than any amount of manual testing.

Attach metadata to every chunk. Source document, section heading, last-updated date, and owner. This makes filtering, debugging, and freshness checks possible later, and it costs almost nothing to add at ingestion time.

Use overlap deliberately, not as a magic number. A common starting point is 10 to 20% overlap relative to chunk size, enough to avoid splitting a sentence or definition across a boundary without duplicating large amounts of text.

Add hybrid search if your content has exact-match terms that matter. Product codes, error messages, and proper nouns are exactly where pure vector search tends to underperform relative to keyword search.

Instrument retrieval quality separately from generation quality. If an answer is wrong, you need to know whether the retriever returned the wrong chunk or the generator misread a correct one. Logging both stages separately makes that diagnosis possible instead of guesswork.

Plan for what happens when retrieval comes up empty. A well-designed RAG system says "I don't have information about that" instead of silently falling back to an ungrounded guess.

Key Takeaways

  • RAG pairs a retrieval step with an LLM's generation step so answers can be grounded in real, current documents instead of the model's frozen training data.
  • The core pipeline is: chunk your documents, embed them, store them in a vector database, then at query time embed the question, retrieve the closest chunks, and generate an answer from them.
  • RAG and fine-tuning solve different problems. RAG is for what the model needs to know; fine-tuning is for how it should behave. They're often combined.
  • Chunking strategy and evaluation are usually the highest-leverage things to get right, higher leverage than which vector database or embedding model you pick.
  • Explicit grounding instructions and source citations are what actually reduce hallucination risk, not the mere presence of a retrieval step.

Conclusion

RAG earned its place as the default architecture for connecting LLMs to real data because it solves a genuinely common problem with a comparatively simple mechanism: search first, then let the model write with real evidence in front of it. The trade-off is that a RAG system is only as trustworthy as its retrieval step, so the unglamorous parts, chunking, evaluation, and source hygiene, end up mattering more than most tutorials let on. If you're building your first RAG pipeline, get a small, honest evaluation set running before you touch chunk sizes, rerankers, or graph-based retrieval. It's the difference between tuning against real failures and tuning against your own assumptions.

FAQ

Is RAG the same as fine-tuning?
No. RAG retrieves external documents at query time and leaves the model's weights untouched. Fine-tuning changes the model's weights directly. They address different problems and can be combined.

Do I need a vector database to build RAG?
Not strictly, you could do brute-force similarity search in memory for a small document set, but a vector database becomes necessary once you have more documents than fit comfortably in memory or need fast approximate search at scale.

How big should my chunks be?
There's no universal number. A common starting range is 400 to 600 tokens for general prose, smaller for FAQ-style content, larger for dense technical or legal text, always validated against your own evaluation set rather than copied from a tutorial.

What's the difference between RAG and a long-context model that just reads the whole document?
Long context avoids retrieval entirely by feeding the model everything, which can work for small, static corpora but gets expensive and slower as your data grows, and doesn't scale to knowledge bases with millions of documents the way retrieval does.

Does RAG eliminate hallucination completely?
No. It substantially reduces the risk when implemented with explicit grounding instructions, but a retriever can still return the wrong chunk, and a model can still misinterpret a correct one. Treat RAG as risk reduction, not a guarantee.

What is GraphRAG?
An extension of RAG that retrieves from a knowledge graph of entities and relationships instead of, or alongside, flat text chunks, aimed at multi-hop questions where the answer depends on connecting several pieces of information rather than pulling one relevant passage.

Top comments (0)