A reliable retrieval-augmented generation (RAG) application is less about choosing a fashionable model and more about building a controlled path from source documents to useful, verifiable answers. This practical RAG tutorial gives LLM developers a reusable checklist for ingestion, chunking, embeddings, vector search, citations, evaluation, security, and maintenance.
Overview
RAG combines information retrieval with text generation. Instead of asking a language model to answer from its general training alone, the application first searches a knowledge base and then supplies selected passages as context for the answer. The model can use that context to answer questions about internal documentation, product information, procedures, or other changing material.
A basic RAG pipeline has six stages:
- Ingest: collect documents and record useful metadata such as title, source, date, access scope, and version.
- Parse and normalize: extract readable text while preserving headings, lists, tables, and other structure where possible.
- Chunk: divide documents into retrieval units that are large enough to carry meaning but small enough to search and fit into the model context.
- Embed and index: convert chunks into vectors and store them in a vector database or another searchable index.
- Retrieve and rerank: find candidate passages for a query, optionally applying metadata filters or a second-stage ranking step.
- Generate and verify: provide selected context to the model, request an answer with citations or source references, and evaluate the result.
The pipeline should be designed as a set of observable boundaries rather than one opaque prompt. At each boundary, you should be able to inspect the input, output, latency, failure mode, and access controls. This makes debugging much easier when an answer is incomplete, unsupported, or unexpectedly slow.
For related design decisions, see the guides on choosing an embedding model and comparing vector databases for RAG. Those choices matter, but they should follow your retrieval requirements rather than lead them.
Checklist by scenario
Scenario 1: Building the first document ingestion pipeline
- Define which document types and sources are in scope. Start with a manageable collection rather than indexing every available file.
- Assign a stable document identifier and preserve the original source location.
- Record metadata that can support filtering, such as department, product, language, publication status, and effective date.
- Preserve headings and section boundaries during parsing. A chunk that retains its title and parent section is easier to interpret than isolated paragraphs.
- Normalize obvious formatting noise, including repeated headers, navigation text, broken line wraps, and duplicated content.
- Keep the original document or a recoverable reference so that a displayed citation can be checked.
- Make ingestion repeatable. A scheduled or event-driven process should be able to identify new, changed, and deleted documents without creating uncontrolled duplicates.
If source files contain sensitive information, establish access rules before indexing them. Retrieval must enforce the same permissions expected in the application; hiding a restricted passage only after generation is not a dependable control.
Scenario 2: Choosing a chunking strategy
- Begin with structure-aware chunking: split by document, heading, subsection, or logical paragraph before considering arbitrary character limits.
- Give each chunk enough surrounding context to stand on its own. Include a document title, section name, or concise metadata field when useful.
- Use overlap carefully. A small overlap can prevent important ideas from being divided, but excessive overlap increases index size and may return repetitive evidence.
- Keep tables, code examples, procedures, and definitions intact when their meaning depends on layout or sequence.
- Store chunk identifiers that map back to the source document and location.
- Test chunking with real questions. A technically consistent chunk size can still be a poor fit if answers routinely require several disconnected passages.
There is no universal ideal chunk size. The right choice depends on document structure, query length, retrieval method, model context limits, and the level of detail expected in answers. Review the LLM context window guide before allowing retrieved content to consume most of the available prompt.
Scenario 3: Implementing retrieval and citations
- Define the retrieval unit: paragraphs, sections, pages, records, or another meaningful boundary.
- Use metadata filters for requirements that should not be left to semantic similarity, such as tenant, region, document status, or permission scope.
- Choose a candidate count that gives the generator useful coverage without flooding it with marginal passages.
- Consider combining semantic search with keyword or lexical matching when exact names, identifiers, error codes, or quoted phrases matter.
- Inspect retrieved passages independently of the model. If the correct evidence is absent, changing the prompt will not fix the underlying retrieval problem.
- Require citations to point to actual retrieved sources, not references invented by the model.
- Define an abstention behavior for cases where the evidence is missing, contradictory, or below a confidence threshold.
A useful generation instruction is explicit: answer only from the supplied context, distinguish documented facts from uncertainty, and say when the sources do not support an answer. This is one practical way to reduce hallucinations in LLMs, although it does not replace retrieval testing or access controls.
Scenario 4: Preparing for production LLM app development
- Log query text, retrieval results, model input and output, latency, token usage where available, and error categories with appropriate privacy protections.
- Separate application errors from retrieval failures, provider failures, parsing failures, and unsupported-answer cases.
- Set timeouts and fallback behavior for unavailable indexes or model services.
- Cache carefully when repeated requests are common, while ensuring that cached answers respect document updates and user permissions. See the guide to LLM caching strategies.
- Test prompt injection defenses. Retrieved documents are untrusted input and may contain instructions that conflict with the application’s task. Use the prompt injection prevention checklist as a review point.
- Measure cost and latency with representative workloads rather than isolated demonstrations. The LLM benchmarking guide can help structure that work.
What to double-check
Before launch, create a small evaluation set containing realistic user questions and expected evidence. Include straightforward lookups, ambiguous questions, questions requiring multiple passages, outdated-document cases, and questions with no answer in the knowledge base.
For each example, inspect at least four dimensions:
- Retrieval relevance: Did the system return passages that address the question?
- Retrieval coverage: Did it return all necessary evidence, or only one part of a multi-step answer?
- Answer faithfulness: Is every important claim supported by the retrieved context?
- Answer usefulness: Is the response clear, appropriately scoped, and actionable?
These dimensions are more informative than judging a few attractive demo answers. Track failures by category so that a fix targets the correct layer. For example, a missing passage may require better parsing or chunking, while a correct passage paired with an incorrect answer may require prompt changes, model changes, or stronger answer constraints.
Also double-check data freshness. Store an ingestion timestamp and, where relevant, a source version or effective date. Decide what happens when documents are replaced, withdrawn, or found to contain errors. A RAG application that retrieves obsolete material can be less reliable than one that clearly states it lacks current information.
Common mistakes
- Indexing without cleaning: menus, repeated footers, and navigation fragments can dilute useful content and produce confusing citations.
- Assuming embeddings solve every search problem: semantic similarity may miss exact identifiers, product codes, or negations. Add lexical matching or filters where the domain requires it.
- Sending too much context: more retrieved text can increase noise, cost, and the chance that important evidence is overlooked. Retrieve, rank, and compress deliberately.
- Using citations as decoration: a citation is useful only when it maps to the evidence supporting the nearby claim.
- Evaluating only the final answer: inspect retrieval results and intermediate transformations to locate the actual fault.
- Ignoring permissions: tenant and user access checks belong in ingestion and retrieval design, not just in the interface.
- Treating the prompt as a security boundary: system instructions can guide behavior, but untrusted retrieved text still needs isolation and validation.
- Changing several components at once: when chunking, embeddings, retrieval settings, and prompts all change together, it becomes difficult to learn what improved or degraded performance.
Keep prompt versions and evaluation results together. A lightweight prompt testing framework can make changes reproducible; see how to evaluate and improve LLM prompts.
When to revisit
Revisit this RAG checklist before a major planning or release cycle, after changing the model or embedding model, and whenever the knowledge base changes substantially. Tool changes can alter parsing, indexing, ranking, context assembly, or observability even when the application code appears stable.
Set practical review triggers:
- New document formats or content sources are added.
- Users report unsupported, incomplete, or outdated answers.
- Access-control rules, tenants, or data classifications change.
- Latency or usage costs increase under real workloads.
- The model, vector database, reranker, embedding model, or prompt is replaced.
- Documents are published in additional languages or require new metadata filters.
- Evaluation results show a shift in retrieval relevance or answer faithfulness.
At each review, rerun the evaluation set, compare retrieval and answer failures with the previous version, and record what changed. Start with one controlled adjustment, then validate it against both normal and adversarial cases. A dependable RAG application is maintained through this feedback loop: inspect the sources, measure the pipeline, update the knowledge base, and only then refine the generation step.