Chaturmind
LearnDSASystem DesignDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Prompt Engineering & LLM APIs

Prompt Engineering

  • Prompt Engineering Basics
  • Chain-of-Thought Prompting

LLM APIs in Java

  • OpenAI API Integration
  • RAG — Retrieval-Augmented Generation
Chaturmind
← Prompt Engineering & LLM APIs

Prompt Engineering

  • Prompt Engineering Basics
  • Chain-of-Thought Prompting

LLM APIs in Java

  • OpenAI API Integration
  • RAG — Retrieval-Augmented Generation
HomeLearnArtificial IntelligencePrompt Engineering & LLM APIsLLM APIs in Java
✓ FreeAdvanced· 7 min read

RAG — Retrieval-Augmented Generation

Ground LLM answers in your own documents — embeddings, vector search, and the RAG pipeline.

Published September 21, 2026


RAG — Retrieval-Augmented Generation

A large language model only knows what was in its training data. It doesn't know your company's policies, your product docs, or anything that happened after its training cut-off. When asked anyway, it may produce a confident, plausible and wrong answer (a hallucination).

Retrieval-Augmented Generation (RAG) fixes this by giving the model the relevant facts at question time: search your own documents for passages related to the question, paste them into the prompt, and instruct the model to answer from them. The model supplies the language skills, and your documents supply the facts.

Why RAG instead of fine-tuning?

NeedRAGFine-tuning
Answer from private or changing documents✅ Update the index, and answers change immediately❌ Retrain for every change
Cite sources✅ You know which passages were used❌ Knowledge is blended into weights
Control access (user sees only their docs)✅ Filter at retrieval time❌ Hard
Change the model's style or teach a format❌ Limited✅ What fine-tuning is good at

Rule of thumb: RAG for knowledge, fine-tuning for behaviour. Many systems use both.

Two pipelines

INDEXING (offline, whenever documents change)
  documents → clean → split into chunks → embed each chunk → store vectors + text + metadata

QUERYING (online, per question)
  question → embed → vector search (top-k similar chunks) → [optional re-rank]
           → build prompt: instructions + retrieved chunks + question → LLM → answer (+ sources)

Embeddings: search by meaning

An embedding model turns text into a vector: a list of hundreds or thousands of numbers positioned so that texts with similar meaning are close together. "How do I reset my password?" and "Forgot login credentials" end up near each other even though they share no words. A vector store (pgvector, Qdrant, Weaviate, Pinecone, Elasticsearch/OpenSearch) finds the chunks nearest to the question's vector, usually by cosine similarity, using approximate nearest-neighbour indexes such as HNSW to stay fast over millions of chunks.

Important: the question and the documents must be embedded with the same model. Switching embedding models means re-embedding everything.

Chunking: the step that quietly decides quality

Documents are split into chunks because whole documents are too long to embed meaningfully and too big to paste into prompts.

  • Too large (whole pages): the chunk's vector becomes a blur of several topics, retrieval gets less precise, and you waste context space.
  • Too small (single sentences): chunks lose the context needed to make sense on their own.
  • A common starting point is 300–800 tokens with 10–20% overlap, split on natural boundaries (headings, paragraphs), not mid-sentence.
  • Keep metadata with each chunk (source document, section title, URL, date, access permissions). You'll need it for citations, filtering and freshness.

A Spring AI implementation

// Indexing
@Service
@RequiredArgsConstructor
public class DocumentIngestion {
    private final VectorStore vectorStore;

    public void ingest(String text, Map<String, Object> metadata) {
        List<Document> chunks = new TokenTextSplitter().apply(List.of(new Document(text, metadata)));
        vectorStore.add(chunks);          // embeds each chunk with the configured embedding model and stores it
    }
}

// Querying
@Service
@RequiredArgsConstructor
public class SupportAssistant {
    private final VectorStore vectorStore;
    private final ChatClient chatClient;

    public String answer(String question) {
        List<Document> hits = vectorStore.similaritySearch(
                SearchRequest.builder().query(question).topK(4).similarityThreshold(0.6).build());

        String context = hits.stream()
                .map(d -> "[source: " + d.getMetadata().get("source") + "]\n" + d.getText())
                .collect(Collectors.joining("\n\n---\n\n"));

        return chatClient.prompt()
                .system("""
                        Answer using ONLY the context provided. If the context does not contain the answer,
                        say you don't know. Cite the source of each fact in square brackets.
                        """)
                .user("Context:\n" + context + "\n\nQuestion: " + question)
                .call()
                .content();
    }
}

Spring AI also ships a QuestionAnswerAdvisor that performs this retrieve-then-prompt step automatically when attached to a ChatClient. The explicit version above shows what happens underneath. (Spring AI's API has changed between milestones. Check the version you use.)

Two prompt details matter a lot:

  • "Only use the context… say you don't know" reduces hallucination when retrieval finds nothing relevant.
  • Citations let users verify answers, and let you debug bad ones.

Improving retrieval

When answers are wrong, the cause is usually retrieval, not the LLM: the right passage never made it into the prompt. The standard upgrades:

  • Hybrid search: combine vector similarity with keyword search (BM25). Vectors capture meaning, and keywords catch exact terms such as error codes, product names and IDs, which embeddings handle poorly. Merge the two result lists, for example with reciprocal rank fusion.
  • Re-ranking: retrieve, say, 20–50 candidates cheaply, then score each against the question with a more accurate cross-encoder model and keep the best 3–5.
  • Metadata filters: restrict the search by product, version, language, or the user's permissions before similarity ranking.
  • Query rewriting: turn a follow-up like "and for enterprise?" into a standalone question using the conversation history before retrieving.

Evaluating a RAG system

Measure the two halves separately:

  • Retrieval: for a set of test questions with known relevant passages, is the right passage in the top-k (recall@k)?
  • Generation: is the answer faithful to the retrieved context (no invented facts), and does it actually answer the question?

Build a small labelled test set from real user questions, and re-run it whenever you change chunking, embeddings or prompts.

Security and practical concerns

  • Access control: filter retrieval by the user's permissions. Otherwise RAG leaks documents they shouldn't see.
  • Prompt injection: retrieved text is untrusted input. A document containing "ignore previous instructions…" can steer the model, so keep instructions in the system message and treat context as data.
  • Freshness: re-index changed documents, and delete chunks of removed ones.
  • Cost and latency: embeddings are cheap, and most cost is the LLM call, which grows with the amount of context you paste in. More chunks isn't always better.

Follow-up questions this topic invites — and their answers

Q: When would you fine-tune instead of using RAG? A: Fine-tune to change behaviour: a consistent output format, a domain-specific writing style, or better performance on a narrow task. Use RAG to give the model knowledge that is private, large or frequently changing. They combine well: a fine-tuned model that is still fed retrieved context.

Q: How do you choose chunk size? A: Start around a few hundred tokens with some overlap, split on semantic boundaries, then tune empirically with a retrieval test set. Precise factual lookups favour smaller chunks, and questions needing broader context favour larger ones. Some systems store small chunks for matching but pass the surrounding larger section to the LLM.

Q: Why add keyword search if vectors capture meaning? A: Embeddings are weak at exact identifiers (SKUs, error codes, function names, rare proper nouns), where lexical matching is precise. Hybrid search gets the best of both and is one of the most reliable quality improvements.

Q: How do you stop the model from making things up when nothing relevant is found? A: Use a similarity threshold, so weak matches aren't passed as context. Explicitly instruct the model to say it doesn't know when the context lacks the answer. And evaluate faithfulness. Showing sources to users also makes unsupported answers easier to spot.

Q: What's a vector database actually doing that a normal database doesn't? A: Fast approximate nearest-neighbour search over high-dimensional vectors, using specialised indexes such as HNSW graphs or IVF clustering, that find the closest vectors without comparing against every stored one. Relational databases can add this with extensions (pgvector), which is often enough at moderate scale.

Previous

OpenAI API Integration

AI Tutor

Lesson: RAG — Retrieval-Augmented Generation

Quick actions

AI responses can be inaccurate. Verify critical information.