RAG End to End: A Practical Tutorial
What it is, how each piece works, how it is evaluated, a production example on Azure, and a comparison of Azure · Google Cloud · open source
Key idea: The value of RAG is not in “plugging in a vector store”: it is in reading documents properly, searching in a hybrid way, reranking and, above all, measuring retrieval and answers separately.
In Anthropic’s tests (2024), adding context to chunks, BM25 and a reranker cut retrieval failures by 67%. Commercial legal RAG tools hallucinate 17–33% of the time (Stanford, 2024), and on Meta’s CRAG benchmark (2024) the best industrial RAG systems answer without hallucinating only 63% of the time. For measuring all this, an LLM judge agrees with humans more than 80% of the time (Zheng et al., 2023).
I checked almost everything here against the official documentation and the cited papers on 23 September 2026. A few tool details marked † come from general experience and I did not re-check them. Features marked (preview) exist, but the vendor does not recommend them for production yet. Acronyms are spelled out the first time they appear and collected in the glossary at the end; papers are cited by name in the text (SPLADE, ColBERT, RAGAS), with authors, year and link in the references.
Part I · Concepts
1. What RAG is, explained with a library
RAG (Retrieval-Augmented Generation) means that, before answering, a language model searches your documents and answers from what it found, citing the source.
Why do you need it? A language model does not know your company’s internal documents, its knowledge stops at a cutoff date, and it can make things up (“hallucinate”). With RAG the answer rests on specific documents that anyone can check, and updating the knowledge does not require retraining the model.
The easiest way to see how the pieces fit together is a library, and someone who walks up to the desk with a question:
- The library is your documents: everything the system is allowed to answer from, such as PDFs, wikis or internal policies.
- The index cards are the chunks. Nobody rereads a whole book for every question, so each document is cut into small cards, each holding a piece of information that makes sense on its own.
- The catalog is the index. Every card is filed two ways: by the words it contains and by what it means. That is what later lets you search both by keyword and by meaning.
- The librarian is the search. When a question arrives, the librarian quickly pulls about 50 cards that look relevant, without reading them closely.
- The expert is the reranker. The expert reads the question next to each of those cards and keeps the best 5.
- The writer is the language model. Only now does anyone write the answer, using those 5 cards and citing the card behind each sentence. If the cards do not contain the answer, the honest reply is “I don’t know”.
- The teacher is the evaluation. The teacher grades two things separately: did the librarian bring the right cards, and is the answer faithful to them?
The rest of the tutorial follows the same order: preparing the documents (stages 1 to 3), search (4), reranking (5), generation (6) and evaluation (7).
Not every RAG system has all seven stages. Gao et al. (2023/24) describe three generations:
| Generation | Idea |
|---|---|
| Naive RAG | Index → retrieve the top k → paste them into the prompt |
| Advanced RAG | Improve things before searching (rewrite the question, chunk better) and after (rerank, compress) |
| Modular RAG | Interchangeable pieces; adaptive, iterative and agentic flows |
In library terms, naive RAG is a librarian who hands the first k cards straight to the writer, with no expert in between. This tutorial describes an advanced RAG, with modular pieces where they pay off (section 10).
2. The three circuits of a production RAG system
A RAG system in production runs three circuits. The first prepares the documents once, offline: sources, parsing and chunking, embeddings and the index (stages 1 to 3 of the library). The second runs for every question: hybrid search, the reranker and the model that answers with citations (stages 4 to 6). The third evaluates, before deployment with a golden dataset and in production by sampling real traffic, and feeds improvements back to the other two (stage 7). Parts II to VI cover them in that order.
Part II · Preparing the documents
3. Reading the document properly (parsing)
Parsing has more impact than any other step, and it is the one teams neglect most. Convert a PDF to “plain text” and you lose the headings, the tables get scrambled, and each chunk loses its context.
The studies agree on this:
- The ColPali authors (ICLR 2025) “typically find that optimizing the ingestion pipeline yields much greater improvements than optimizing the embedding model”. ColPali itself skips text extraction and chunking and indexes page images directly; on the ViDoRe benchmark it scored 81.3 nDCG@5 against ~65–67 for parsing pipelines.
- In Unstructured’s FinanceBench study (2024), chunking by document elements (headings, tables) reached 53.2% accuracy versus 48.2% with fixed 512-token chunks, and used half as many chunks.
- A Turkish-language study (2026) found that layout-aware chunking helps much more on documents with tables than on text-only documents.
The usual tools are the Document Layout skill (Azure), Document AI Layout Parser (Google) and Docling (IBM, open source). Section 22 compares them.
4. Chunking
Chunking splits each document into small pieces (chunks) that are indexed separately.
4.1 The strategies
| Strategy | How it splits | Cost |
|---|---|---|
| Fixed size | Every N tokens, with optional overlap | Minimal |
| Recursive | Tries to split by paragraph, then by line, then by sentence… | Minimal |
| By structure / page | By the document’s sections, headings or pages | Low (requires good parsing) |
| Semantic | Splits where the meaning changes between sentences, measured with embeddings | Medium |
| LLM-based (“agentic”) | A model decides where to split | High |
| Propositions | A model rewrites the text into atomic facts | High |
4.2 What the evidence says: semantic chunking is overrated
- Vectara (2024) asked “Is Semantic Chunking Worth the Computational Cost?” and concluded that “the computational costs associated with semantic chunking are not justified by consistent performance gains”. Fixed-size chunking won on all 4 real-document datasets (on HotpotQA, for example, F1@5 was 90.59 fixed vs 87.37 semantic). The embedding model mattered more than the chunking.
- Chroma (2024) found that the chunking strategy moves recall by up to 9%. Its default semantic chunker came in slightly below average (83.6% recall), while a recursive 200-token chunker with no overlap reached 88.1%. The best result (91.9%) used a language model and cost much more.
- NVIDIA (June 2025) got the best average accuracy (0.648) and the lowest variance across datasets with page-level chunking.
- In biomedicine (2026), semantic chunking gained +8.4 F1 points on one dataset, but on the others fixed-size chunking “remains competitive or better”. It depends on the domain.
4.3 What does work: adding context to each chunk
| Chunk without context | Chunk with context |
|---|---|
"| Manager | 2 |"→ 2 what? where? |
"Remote Work Policy > 3. Eligibility > 3.2 Spain | Manager | 2 days/week |"→ understandable on its own |
Anthropic’s Contextual Retrieval (Sep 2024) has a model write 50–100 tokens of context and prepends them to each chunk. Measured as the retrieval failure rate within the top 20 results, starting from a 5.7% baseline:
- context in the vectors only: 3.7% (−35%)
- context in the vectors and in BM25: 2.9% (−49%)
- all of the above plus a reranker: 1.9% (−67%)
The one-time cost is ~$1.02 per million document tokens with prompt caching. Be careful when you quote these numbers: all three percentages are reductions relative to the 5.7% baseline, so the reranker’s own contribution is the step from 2.9% to 1.9%.
Late chunking (Jina, 2024) computes the embedding of the whole document first and only then splits it, so each vector “knows” which document it comes from. It improves nDCG@10 by +2.7% to +3.6% without retraining.
4.4 Starting sizes
Bhat et al. (2025) suggest 64–128 tokens for short factual questions and 512–1024 tokens for questions that need broad context. Azure recommends starting with 512 tokens and 25% overlap, and adding the document title to the middle chunks.
A reasonable default: start with recursive or section/page chunking of 256–512 tokens, don’t split tables, add context, and tune by measuring (Part VI).
5. Turning text into vectors (embeddings)
An embedding is a list of numbers that represents the meaning of a text. Texts with similar meanings end up close together:
| Type | What it is | Examples |
|---|---|---|
| Dense | Hundreds or thousands of numbers, all with a value | text-embedding-3 (OpenAI/Azure), gemini-embedding-001, Qwen3-Embedding, BGE-M3 |
| Learned sparse | List of terms (almost all zero) with weights, expanded with related terms | SPLADE, ELSER (Elastic), BGE-M3 sparse mode |
| Multi-vector | One vector per token; compared token by token | ColBERT, ColPali |
Measure on your own data. Public leaderboards (such as MTEB) change every month and don’t always reflect your domain. And pin the model version: if you mix vectors from different models, searches stop making sense.
6. Index and permissions
The index stores each chunk with its text, its vector and its metadata:
| Field(s) in the index | Purpose |
|---|---|
id, content, content_vector | the chunk text and its embedding |
title, section, page, source_url | where it came from |
allowed_groups | groups allowed to see it |
last_modified | freshness |
Without allowed_groups and a security filter on every search, an intern could receive chunks from executive committee documents.
Part III · Retrieval
7. BM25: keyword search
BM25 is the classic keyword (lexical) search algorithm and the default in Elasticsearch, OpenSearch and Azure AI Search. It runs on an inverted index, which works like the alphabetical index at the back of a book:
| Term | Documents where it appears (postings) |
|---|---|
"remote work" | doc3, doc7, doc12 |
"manager" | doc7, doc9 |
"spain" | doc7, doc12, doc15 |
The score has three parts:
| Ingredient | Idea | Example |
|---|---|---|
| Term frequency | More occurrences = more points, but with saturation (parameter k1, 1.2 by default in Elasticsearch †) | 3 times > 1 time, but 20 times ≈ 10 times |
| Term rarity | Rare words are worth more | “ORA-00942” is worth a lot; “of” almost nothing |
| Document length | A short text containing the word scores higher than a long one (parameter b, 0.75 by default †) | A specific paragraph beats an entire manual |
BM25 is fast, needs no model, can be explained, and is excellent for exact terms such as codes, acronyms and proper names. Its weakness is synonyms: “cheap laptop” won’t find “budget notebook”.
8. Semantic search: by meaning
8.1 Dense vectors (nearest-neighbor search)
Here the question becomes a vector and you retrieve the closest chunks. Doing that quickly over millions of vectors takes an approximate index, usually HNSW (a graph of neighbors).
Dense search understands synonyms, paraphrases and different languages. On the other hand, it is a black box (you can’t explain why something matched), it can confuse nearly identical codes (ORA-00942 vs ORA-00943), and it uses more memory. Quantization reduces the memory by compressing the numbers, for example to 8 bits or to binary.
8.2 Learned sparse (SPLADE, ELSER)
Learned sparse sits between the two. A model expands the text with related terms and their weights, and the search then runs on an inverted index, as with BM25:
"cheap laptop" → { laptop: 2.1, notebook: 1.8, computer: 1.2, cheap: 1.9, budget: 1.5, price: 0.9 }
It is easier to explain than dense vectors and still finds synonyms. The catch is that it depends on the model’s language (ELSER is recommended for English only) and has a token limit (ELSER encodes the first 512 tokens of each field).
8.3 Which one wins
| Query | BM25 | Dense | Learned sparse |
|---|---|---|---|
| “cheap laptop” → doc with “budget notebook” | No | Yes | Yes |
| “error ORA-00942” → doc with that code | Yes | Unreliable | Yes |
| “can I work from home?” → doc with “remote work” | No | Yes | Yes, if the language is supported |
| Explaining why it matched | Yes | No | Partly |
| Cost | Minimal | Model + memory | Model |
None of them wins every time, which is why you combine them.
9. Hybrid search and RRF
9.1 The problem
The two searches return scores on incompatible scales:
| Rank | BM25 (no upper bound) | Vector (cosine 0.33–1 in Azure) |
|---|---|---|
| 1 | doc_B → 12.4 | doc_A → 0.89 |
| 2 | doc_A → 9.1 | doc_C → 0.87 |
| 3 | doc_D → 3.2 | doc_B → 0.81 |
Adding 12.4 + 0.81 makes about as much sense as adding euros and kilos.
9.2 The solution: RRF (Reciprocal Rank Fusion)
RRF ignores the scores and uses only the position of each document in each list:
RRF(doc) = Σ 1 / (k + position of doc in that list) with k = 60 typically
over each list
Take the same rankings as above:
| Position | BM25 | Vector |
|---|---|---|
| 1 | doc_B | doc_A |
| 2 | doc_A | doc_C |
| 3 | doc_D | doc_B |
| Doc | BM25 contribution | Vector contribution | Total | Final |
|---|---|---|---|---|
| doc_A | 1/62 = 0.01613 | 1/61 = 0.01639 | 0.03252 | 1 |
| doc_B | 1/61 = 0.01639 | 1/63 = 0.01587 | 0.03226 | 2 |
| doc_C | 0 | 1/62 = 0.01613 | 0.01613 | 3 |
| doc_D | 1/63 = 0.01587 | 0 | 0.01587 | 4 |
doc_A wins because it ranks high in both lists. RRF rewards agreement between the two methods.
9.3 Why k = 60?
| Position 1 | Position 2 | Difference | |
|---|---|---|---|
| k = 0 | 1.000 | 0.500 | double: being 1st in a single list dominates |
| k = 60 | 0.0164 | 0.0161 | almost equal: ranking well in several lists is what counts |
The value comes from the original paper (Cormack, Clarke and Büttcher, SIGIR 2009), where it was chosen empirically, and Azure AI Search documents that it works best with small values such as 60.
9.4 Advantages, limits and variants
RRF needs no scale calibration and nothing to train, and it accepts N lists (BM25, several vectors, several rewordings of the question). It has two weaknesses. It ignores magnitude, so being first “by a mile” is worth the same as being first “by a hair”. And a bad list counts just the same: if vector search returns junk, that junk also gets points.
There are two common variants:
- Weighted RRF gives one of the lists more weight (for example, the vector list ×2). It is available in Azure (vector weighting), in LangChain’s
EnsembleRetriever†, and in Google Vector Search withrrf_ranking_alpha. - Linear combination normalizes the scores and adds them with weights. It uses the magnitude, but you have to calibrate it with data. Examples are Elasticsearch’s
linearretriever and DBSF in Qdrant †.
Keep in mind that RRF is not a reranker. It only fuses lists, and the reranker comes afterwards.
10. Advanced retrieval strategies
| Technique | What it does | Key evidence |
|---|---|---|
| Rewriting with history | Turns “so how many days?” into a complete question using the earlier chat | Standard practice |
| HyDE | A model writes a hypothetical answer and the search is run with it | Competes with trained retrievers, without needing labels (Gao et al., 2022) |
| Multi-query / RAG-Fusion | Several rewordings of the question, fused with RRF | More coverage; risk of drifting off topic |
| Step-back | First ask something more general | +27% on TimeQA, +7% on MuSiQue (Google DeepMind) |
| Decomposition | Splits a complex question into sub-questions | Foundation of agentic search |
| RAPTOR / parent document | Hierarchical summaries; search by small chunk and return the large one | RAPTOR + GPT-4: +20% absolute on QuALITY |
| GraphRAG | Entity graph + per-community summaries | Improves global questions (“which topics keep recurring?”). LazyGraphRAG indexes at 0.1% of the cost and queries >700× cheaper. It doesn’t always win: on specific lookups classic RAG usually matches or beats it (Han et al., 2025/26; HippoRAG 2) |
| Adaptive (Self-RAG, Corrective RAG, Adaptive-RAG) | Decides when to search, how much, and corrects if the search was bad | Adaptive-RAG routes based on question complexity |
| Agentic / “Deep Research” | Iterative search trained with reinforcement learning | Search-R1: +41% (7B) over baseline RAG; OpenAI Deep Research takes 5 to 30 minutes per task |
| Long context vs RAG | Put everything in the prompt? | Models perform worse when the information is in the middle of the context (“Lost in the Middle”); retrieving too much makes the answer worse; the efficient approach is to route each query (Self-Route), and no option always wins (LaRA) |
11. Case study: Elasticsearch
Elasticsearch has four different “semantic” pieces, and they are easy to mix up:
- A. Dense:
dense_vector+knnquery, with int8, int4 and BBQ quantization. You can use E5 (multilingual), Jina (via the Elastic Inference Service) or external models (OpenAI, Azure OpenAI, Cohere, Bedrock, Vertex AI, Hugging Face). - B. ELSER expands terms. What it adds are learned associations, not synonyms. On Elastic’s own BEIR benchmark it improves nDCG@10 over BM25 by 18% on average (10 wins, 1 tie, 1 loss). It is recommended for English, reads 512 tokens per field and requires a paid subscription.
- C. Reranker: the
text_similarity_rerankerretriever or theRERANKcommand in ES|QL. - D.
semantic_text(GA since version 9.0). If you don’t pininference_id, new indices may use a different model after a version upgrade, so always pin the model in production.
Here is hybrid search with a reranker in a single call:
{
"retriever": {
"text_similarity_reranker": {
"retriever": {
"rrf": {
"retrievers": [
{ "standard": { "query": { "match": { "content": "remote work days manager Spain" } } } },
{ "standard": { "query": { "semantic": { "field": "content_semantic",
"query": "remote work days manager Spain" } } } }
],
"rank_window_size": 50,
"rank_constant": 60
}
},
"field": "content",
"inference_id": "my-rerank-endpoint",
"inference_text": "remote work days manager Spain",
"rank_window_size": 50
}
}
}
You can also fuse with the linear retriever (minmax or l2_norm normalizers) or, in ES|QL, with FORK + FUSE (RRF or LINEAR) + RERANK. In the multi-field format, Elastic normalizes the lexical and semantic fields so that each group contributes 50%.
Watch the vocabulary. In Elastic, “semantic search” means searching with embeddings; in Azure, the “semantic ranker” is a reranker.
Part IV · Reranking
12. Reranking
12.1 What it is
A reranker takes the ~50–150 candidates from the search and reorders them by reading the question and each chunk together. That is more accurate than comparing vectors, but slower, so you only apply it to a few candidates.
The typical architecture has two stages: hybrid search (which prioritizes coverage), then a reranker over 100–150 candidates, and finally between 10 and 20 chunks passed to the model that writes the answer.
12.2 Types
| Type | Examples | Note |
|---|---|---|
| Classic cross-encoder | monoBERT, bge-reranker-v2-m3 | monoBERT: +27% in MRR@10 on MS MARCO (2019) |
| Language model as reranker | RankGPT, RankZephyr (open source), Setwise | RankZephyr matches or beats GPT-4 |
| Reasoning reranker (2025–26) | Rank1, Rank-R1, ReasonRank | On BRIGHT (search that requires reasoning), the best MTEB model drops from 59.0 to 18.3; reasoning about the question adds up to +12.2 |
| Late interaction | ColBERT | Middle ground: ~100× faster than a BERT reranker |
12.3 Notable models (verified)
| Model | Organization / date | License | Data point |
|---|---|---|---|
| Rerank 4 Pro / Fast | Cohere, Dec 2025 | Paid service | #2 on Agentset’s independent leaderboard (1627 Elo points vs ~1457 for v3.5) |
| zerank-2 | ZeroEntropy | Open weights | #1 on Agentset |
| rerank-2.5 | Voyage (MongoDB), Aug 2025 | Paid service | 32K context, follows instructions |
| Qwen3-Reranker 0.6/4/8B | Alibaba, Jun 2025 | Apache 2.0 | 69.76 on MTEB-R (4B) vs 57.03 for bge-v2-m3 |
| jina-reranker-v3.5 | Jina, Jul 2026 | Non-commercial | 63.20 on BEIR with 0.6B parameters |
| mxbai-rerank-large-v2 | Mixedbread, Mar 2025 | Apache 2.0 | 57.49 on BEIR |
| Semantic ranker | Microsoft (Azure AI Search) | Managed service | Reranks the top 50, score from 0 to 4 |
| Ranking API | Managed service | Up to 1000 chunks per call, score from 0 to 1 |
12.4 Practical rules
A reranker is the cheapest and most proven improvement you can make. In Anthropic’s numbers, adding one on its own takes the failure rate from 2.9% to 1.9%.
But the reranker only reorders what the search found. If the correct document isn’t among the candidates, it can’t save you, which is why you measure retrieval coverage (recall) first.
What currently sets rerankers apart is instruction following: you can give them business rules such as “prioritize recent content”. Every vendor claims to be the best, so measure with your own data.
Some add-ons are worth having. MMR removes redundant chunks. Compression with LongLLMLingua gives +21.4% quality with ~4× fewer tokens. And placement in the prompt matters: put the most relevant content at the beginning or the end (“Lost in the Middle”).
Part V · Generation and guardrails
13. Generation with citations and guardrails
The prompt looks like this:
System: Answer ONLY from the context. Cite every claim as [n].
If the context does not contain the answer, say "I don't know".
Context: [1] Remote Work Policy §3.2 Spain, p. 4: "Manager: 2 days/week..."
[2] 2026 Annex, p. 1: "...starting January 2026, 3 days for..."
Question: remote work days for a manager in Spain
Guardrails sit before, during and after generation:
- Before, detect attempts to manipulate the model (“jailbreak” or prompt injection).
- During, if the reranker leaves no chunk above the threshold, answer “I couldn’t find that information” instead of making something up.
- After, check that every sentence of the answer is supported by the chunks. If the check fails, regenerate or answer cautiously.
Part VI · Evaluation
14. Two separate tests
If you only look at the final answer, you don’t know what to fix. Microsoft calls evaluating the retrieval step process evaluation and evaluating the answer system evaluation.
15. The golden dataset (the “answer key”)
The golden dataset is a set of 100 to 300 questions, each with its correct answer and the documents that should come up:
{"query": "Remote work days, manager, Spain?",
"ground_truth": "2 days per week; 3 from January 2026 according to the annex",
"relevant_docs": [{"document_id": "teletrabajo_p4", "query_relevance_label": 4},
{"document_id": "anexo2026_p1", "query_relevance_label": 3}]}
| Where the questions come from | Why |
|---|---|
| Logs of real questions | That is what people actually ask |
| Business experts (HR, legal) | Hard cases and traps |
| Synthetic generation (RAGAS, cloud-provider simulators) | Fast coverage, but always reviewed by a human |
| Questions with no answer in the documents | They check that the system says “I don’t know” instead of making things up |
16. Retrieval metrics, with numbers
Say that for one question the correct documents are A and C, and the search engine returned [B, A, D, C, E].
| Position | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|
| Returned | B | A | D | C | E |
| Correct? | ✗ | ✓ | ✗ | ✓ | ✗ |
| Metric | Question it answers | Calculation | Value |
|---|---|---|---|
| Recall@3 (coverage) | How many of the correct ones appear in the top 3? | 1 of 2 | 0.50 |
| Recall@5 | And in the top 5? | 2 of 2 | 1.00 |
| Precision@5 (precision) | Of what I brought back, how much is useful? | 2 of 5 | 0.40 |
| MRR (position of the first hit) | How high up is the first correct one? | 1/2 | 0.50 |
| nDCG@5 (ranking quality) | Are the correct ones as high up as possible? | Actual = 1/log₂3 + 1/log₂5 = 1.06; ideal = 1 + 1/log₂3 = 1.63 | 0.65 |
These numbers tell you where to look. If Recall@50 is low, the problem is in retrieval (chunking, embeddings, missing BM25), and the reranker won’t fix it. If Recall@50 is high but nDCG@5 is low, the problem is in the reranker.
17. Answer metrics, with numbers
Suppose the system answers: “You get 2 days per week [1], 3 starting January 2026 [2], and you can choose Fridays.”
| Claim in the answer | Supported by the chunks? |
|---|---|
"2 days/week" | ✓ |
"3 from January 2026" | ✓ |
"you can choose Fridays" | ✗ (made up) |
| Metric | Question | Result |
|---|---|---|
| Groundedness / Faithfulness (the precision side) | Is everything it said in the chunks? | 2/3 = 0.67 ✗ hallucination |
| Completeness / Answer correctness (the coverage side) | Did it say everything the correct answer says? | 2/2 = 1.0 ✓ |
| Relevance | Does it answer what was asked? | ✓ |
| Correct citations | Does each [n] support its sentence? | ✓ |
Microsoft frames it the same way: faithfulness to the context is the precision side (add nothing) and completeness is the coverage side (leave out nothing critical).
Another option is “nugget” evaluation (TREC 2024): you define the atomic facts a good answer must contain and count how many appear.
18. The LLM as a judge
Nobody reviews 10,000 answers by hand, so another model plays the teacher. That judge has known biases. It prefers the first option it sees (position), it prefers long answers (verbosity), and it prefers text from its own model family (self-preference).
To set up a judge you can rely on:
- A human labels 50–100 cases.
- Measure judge–human agreement (Cohen’s kappa, accuracy, F1).
- The judge must be from a different model family than the generator.
- The judge must explain its score.
- Scoring claim by claim (RAGChecker) or by nuggets is better than giving one overall score.
How far can you trust it? GPT-4 as a judge reaches more than 80% agreement with humans, the same level as between two humans (Zheng et al., 2023). In TREC 2024, perfect human–GPT-4o agreement was 56%, and 72% when the human was correcting the model’s label. So the LLM judge is reliable for comparing systems and less reliable question by question. ARES combines a few hundred human labels with the automatic judge to produce statistically valid confidence intervals.
19. Evaluation before deployment and in production
A quality gate in continuous integration could require that Recall@10 drops no more than 2 points, faithfulness stays ≥ 95%, and correct “I don’t know” answers stay ≥ 90%. Those thresholds are only examples; the business sets the real ones. In production you sample a percentage of real traffic and evaluate it without a reference answer (faithfulness, answer relevance, context relevance), alongside thumbs-up/thumbs-down votes, latency and cost.
Microsoft recommends a parameter sweep: try combinations and measure which one wins. The numbers below are illustrative, not real results:
| Configuration | Recall@10 | nDCG@5 | Faithfulness | Latency |
|---|---|---|---|---|
| vector only | 0.71 | 0.58 | 0.90 | 0.8 s |
| hybrid | 0.84 | 0.66 | 0.92 | 0.9 s |
| hybrid + rerank ← chosen | 0.84 | 0.79 | 0.95 | 1.3 s |
| + agentic (complex questions only) | 0.88 | 0.81 | 0.95 | 3.5 s |
DeepEval suggests no more than about 5 metrics per application. MLflow / Databricks recommend using the same evaluators in development and in production. And in production you can only use metrics that don’t need a correct answer.
20. Why it matters: hallucination in real systems
| Study | Result |
|---|---|
| Stanford (2024): commercial legal tools with RAG | They hallucinate between 17% and 33% of the time |
| CRAG (Meta, 2024) | Model alone: ≤34% accuracy; simple RAG: 44%; the best industrial RAG systems answer without hallucinating only 63% of the time |
| FinanceBench (2023) | GPT-4-Turbo with retrieval failed or refused to answer in 81% of cases |
| ALCE (2023) | Even the best models lack full support for their citations 50% of the time |
| Vectara (leaderboard of 2026-09-22, summarization task) | Hallucination rates between 1.8% and 24.2% depending on the model (GPT-4o 9.6%, Gemini 2.5 Pro 7.0%, Claude Sonnet 4.5 12.0%) |
| FaithBench (2024) | The best hallucination detectors hover around 50% accuracy on hard cases |
Several of these figures are from 2023–2024 and come from older models, so always cite them with year and model.
Part VII · A production example on Azure
21. Internal policy copilot, step by step
The case is a company with 20,000 employees, with HR, legal and procurement documents in SharePoint and Blob Storage. It needs per-user permissions, citations in every answer, and “I don’t know” when there is no information.
21.1 Architecture
If you know the LangChain + Chroma/Qdrant stack, the pieces map like this:
| Open-source stack | On Azure |
|---|---|
| LangChain loaders + text splitter | Indexer + Document Layout skill + chunking |
| Chroma / Qdrant | Azure AI Search (vectors + BM25 + filters in a single service) |
| Reranking with a language model | Semantic ranker (and optionally a language model behind it) |
| Your own query rewriting | Semantic ranker query rewriting (preview) or agentic retrieval |
| GraphRAG | Microsoft GraphRAG as a separate index, only for global questions |
21.2 One question, end to end
Ana, a manager in Madrid, asked about her contract earlier in the chat. Now she types “so how many days can I work remotely?”
-
The model rewrites the question using the chat history: “remote work days allowed for a manager in Spain”.
-
BM25 and vector search run in parallel and are fused with RRF (k=60). Before scoring, the security filter removes whatever Ana is not allowed to see.
-
The semantic ranker takes only the top 50 and scores them from 0 to 4:
Score Meaning 4 Fully answers 3 Relevant but incomplete 2 Partial 1 Related, answers very little 0 Irrelevant Chunks with a score < 2 are discarded. If none are left, the answer is “I couldn’t find that information”. Microsoft warns that the score distribution can vary slightly, so thresholds should not be too fine-grained.
-
The model generates the answer with citations, using the prompt structure from section 13.
-
A faithfulness check verifies that each sentence is supported by the chunks. If it fails, the answer is regenerated or given with caution.
A complex question (“compare remote work in Spain vs Mexico and tell me which applies if I relocate”) goes to Azure AI Search agentic retrieval, which splits it into subqueries, runs them in parallel, reranks each one with the semantic ranker and merges the results. The LLM-based query planning and answer synthesis are still in preview.
A global question (“which themes recur across all the 2026 policies?”) is where GraphRAG is worth it.
21.3 Evaluation on Azure (Microsoft Foundry)
| Evaluator | Type | Needs a correct answer | Status |
|---|---|---|---|
| Document Retrieval | Retrieval: NDCG, XDCG, Fidelity, Max Relevance, Holes | Yes (relevance labels) | GA |
| Retrieval | Retrieval, judged by a language model (1–5 scale) | No | GA |
| Groundedness | Answer: faithfulness to the context | No | GA |
| Groundedness Pro | Strict faithfulness with Content Safety (true/false) | No | (preview) |
| Relevance | Answer: does it answer the question? | No | GA |
| Response Completeness | Answer: does it leave out anything critical? | Yes | (preview) |
Scores use a scale of 1 to 5 and pass at 3 by default. Continuous evaluation runs on samples of real traffic (configurable percentage, up to 1000 requests per hour) and sends the results to Application Insights, linked to the traces.
Part VIII · Comparison: Azure vs Google Cloud vs open source
22. Azure vs Google Cloud vs open source
Some products have been renamed recently (verified on 2026-09-23):
- At Google, Vertex AI now appears as Gemini Enterprise Agent Platform, Vertex AI Search is being renamed to Agent Search, and Vector Search 2.0 is now called Agent Retrieval.
- At Microsoft, Azure AI Foundry is now Microsoft Foundry.
Phase 1: Preparing the documents
| Stage | What it does | Azure | Google Cloud | Open source |
|---|---|---|---|---|
| 1. Sources | Where the documents live | Blob Storage, SharePoint | Cloud Storage, Google Drive | File system, S3-compatible storage (MinIO) † |
| 2. Reading (parsing) | PDF/Word → text with structure | Document Layout skill, which uses the Document Intelligence layout model and returns Markdown by section | Document AI Layout Parser: stable version since 2024; Gemini-powered versions in preview; figure and table descriptions with Gemini in preview | Docling (IBM, MIT), Unstructured, MinerU †, Marker † |
| 3. Chunking | Chunks with context | Document Layout skill (by section, or fixed size with overlap) and Text Split skill | The Layout Parser chunks by structure and adds the parent headings. RAG Engine lets you set size and overlap | LangChain and LlamaIndex text splitters; Docling chunking † |
| 4. Embeddings | Text → numbers | Azure OpenAI text-embedding-3-large / -small | gemini-embedding-001 (up to 3072 dimensions, 2048 tokens per text), text-embedding-005 (English and code), text-multilingual-embedding-002 | BGE-M3 (dense + sparse + multi-vector, more than 100 languages), Qwen3-Embedding (Apache 2.0), multilingual-E5 |
| 5. Index | Database to search | Azure AI Search: vectors, keywords and filters in a single service | Vector Search / Agent Retrieval, RAG Engine (managed database, Pinecone or Weaviate) or Agent Search (fully managed) | Qdrant, Chroma, Weaviate, Milvus, pgvector, Elasticsearch / OpenSearch † |
| 6. Permissions | Each user sees only their own content | Entra ID + group filter in the index | Google access control (IAM) + per-data-source access control in Agent Search | Metadata filters in the vector database † |
Phase 2: Answering a question
| Stage | What it does | Azure | Google Cloud | Open source |
|---|---|---|---|---|
| 7. Rewriting | Standalone question; split complex questions | Semantic ranker query rewriting (preview); agentic search with planning (preview) | Agent Search: follow-up questions and answers with agentic search | LangChain MultiQueryRetriever, HyDE, LlamaIndex query transformations † |
| 8. Keywords (BM25) | Exact match | BM25 built into AI Search | Vector Search: you generate the sparse vector (BM25, TF-IDF or SPLADE) and upload it. Agent Search: managed | Elasticsearch/OpenSearch BM25; sparse vectors in Qdrant; SPLADE |
| 9. Meaning | Nearest neighbors | Vectors in AI Search | Vector Search / Agent Retrieval (milliseconds even with billions of items, according to Google) | Qdrant, Chroma, Weaviate, Milvus, pgvector † |
| 10. Fusion | Combine lists | Automatic RRF (k=60), with a configurable weight for vectors | RRF with rrf_ranking_alpha | RRF in Qdrant †, Weaviate hybrid search †, LangChain EnsembleRetriever † |
| 11. Reranker | Rerank by reading question and chunk together | Semantic ranker: the top 50, score 0–4 | Ranking API: semantic-ranker-default-004 / -fast-004 (1024 tokens, 25 languages, score 0–1, up to 1000 chunks per call). Version 005 has been in preview since Sep 1, 2026 and will become the default no later than Oct 1, 2026 | bge-reranker-v2-m3, Qwen3-Reranker (Apache 2.0), mxbai-rerank-v2 (Apache 2.0), ColBERTv2; or a language model as the reranker |
| 12. Agent | Chained searches | Agentic search / Foundry IQ (the language-model part in preview) | Agent Development Kit (ADK) + Agent Runtime; Gemini Deep Research agent | LangGraph, LlamaIndex agents † |
| 13. GraphRAG | Graph for global questions | Microsoft GraphRAG (open source) deployed on Azure; LazyGraphRAG in Microsoft Discovery | No managed equivalent found (as of 2026-09-23) | GraphRAG (Microsoft), LightRAG, HippoRAG 2 |
Phase 3: Generation and guardrails
| Stage | What it does | Azure | Google Cloud | Open source |
|---|---|---|---|---|
| 14. Writing model | Answer with citations | GPT models in Azure OpenAI / Microsoft Foundry (also other models in Foundry †) | Gemini (3.x family); also Claude, Llama, Qwen and others in Model Garden | Llama, Qwen, Mistral, gpt-oss served with vLLM or Ollama † |
| 15. Input protection | Block manipulation attempts | Content Safety – Prompt Shields † | Model Armor | NeMo Guardrails, Llama Guard † |
| 16. Faithfulness to the documents | Is every sentence supported? | Groundedness evaluator; Groundedness Pro (preview) | Check Grounding API: 0–1 score per claim + citations, in under 500 ms | HHEM-2.1-Open (Vectara), MiniCheck |
Phase 4: Evaluation and monitoring
| Stage | What it does | Azure | Google Cloud | Open source |
|---|---|---|---|---|
| 17. Evaluating retrieval | Did it find the right thing? | Document Retrieval (NDCG, XDCG, Fidelity, Holes; needs labels) and Retrieval (judge, no labels) | Evaluate search quality in Agent Search; Agent Platform evaluation service | RAGAS, DeepEval, RAGChecker, Open RAG Eval (UMBRELA) |
| 18. Evaluating the answer | Faithful, relevant and complete? | Groundedness, Relevance, Response Completeness (preview); 1–5 scale, passes at 3 | Evaluation service with rubric-based metrics, a configurable judge and the option to evaluate the judge itself | RAGAS, DeepEval, TruLens (“RAG triad”), ARES (confidence intervals) |
| 19. Continuous evaluation | Evaluate samples of real traffic | Foundry continuous evaluation: configurable sampling, up to 1000/hour, results in Application Insights | Online Monitors: every ~10 min, configurable percentage and cap, results in Cloud Logging and Cloud Monitoring | Langfuse †, Arize Phoenix, MLflow |
| 20. Traces | See what happened at each step | Application Insights / Azure Monitor + OpenTelemetry | Cloud Trace, Cloud Logging, Cloud Monitoring + OpenTelemetry (gen_ai. attributes) | OpenTelemetry + Phoenix / Langfuse † |
| 21. Deployment | Where the app runs | Container Apps, App Service, AKS (Kubernetes) † | Cloud Run, GKE (Kubernetes), Agent Runtime | Docker + Kubernetes, FastAPI † |
Summary in one picture
| Stage | Azure | Google Cloud | Open source |
|---|---|---|---|
| Read docs | Document Layout skill | Document AI Layout Parser | Docling / Unstructured |
| Vectors | text-embedding-3 | gemini-embedding-001 | BGE-M3 / Qwen3-Embedding |
| Index | Azure AI Search | Vector Search / Agent Search | Qdrant / Chroma / Weaviate |
| Fusion | Automatic RRF (k=60) | RRF (rrf_ranking_alpha) | RRF (Qdrant, LangChain) |
| Reranker | Semantic ranker (top 50) | Ranking API (up to 1000) | bge / Qwen3 / mxbai reranker |
| Model | GPT (Azure OpenAI) | Gemini | Llama / Qwen / gpt-oss + vLLM |
| Verification | Groundedness (Pro in preview) | Check Grounding API | HHEM-Open / MiniCheck |
| Evaluation | Foundry evaluators | Evaluation service | RAGAS / DeepEval / TruLens |
| Production | Continuous evaluation | Online Monitors | Phoenix / MLflow / Langfuse |
Three differences that matter
- Hybrid search: Azure AI Search includes keyword search. In Google Vector Search you have to generate the sparse vector yourself; if you want Google to manage it, use Agent Search. In open source it depends on the database.
- Reranker: Azure’s reranks only the top 50. Google’s Ranking API accepts up to 1000 chunks and works with any search engine, even an external one. In open source you control the model, cost and latency, but you also have to operate it.
- Evaluation: both clouds now offer offline evaluation and continuous evaluation on real traffic, with standard traces (OpenTelemetry). In open source, RAGAS or DeepEval (offline) plus Phoenix, MLflow or Langfuse (production) cover the same ground, but you do the integration yourself.
Appendix · Glossary
| Term | Plain meaning |
|---|---|
| Agentic search | An agent splits the question and runs several searches |
| BM25 | Classic keyword search algorithm |
| Chunk | A piece of a document that is indexed separately |
| Cohen’s kappa | A measure of agreement between two raters that discounts agreement by chance |
| Completeness | That the answer doesn’t leave out important information |
| Continuous integration (CI) | Automated tests that run on every code change |
| Cross-encoder / bi-encoder | Reads both texts together / turns each text into a vector separately |
| Dense / sparse | A vector with all values active / a vector of weighted terms, almost all zero |
| Embedding / vector | A list of numbers that represents the meaning of a text |
| Entra ID | Microsoft’s identity and access system |
| Golden dataset | A set of questions with their correct answers and documents |
| GraphRAG | RAG with a graph of entities and relationships |
| Groundedness / faithfulness | That the answer says nothing that isn’t in the documents |
| Hallucination | When the model makes up information |
| HNSW | A graph-shaped structure for quickly finding the nearest vectors |
| Hybrid search | Combining keyword search and meaning-based search |
| IAM | Google Cloud’s access control system |
| Inverted index | A “word → documents where it appears” table |
| kNN | Finding the k nearest neighbors |
| Language model (LLM) | The model that writes the answer (GPT, Gemini, Claude, Llama…) |
| LLM judge | Another model that scores the answers |
| MMR | A technique for removing redundant results |
| MRR | How high up the first correct result appears |
| nDCG | Ranking quality: whether the correct items are as high up as possible (Azure’s evaluators spell it NDCG) |
| OpenTelemetry | An open standard for recording traces and metrics |
| Parsing | Converting a file (PDF, Word) into text with structure |
| Precision@k | What fraction of the top k results is correct |
| Preview / GA | Feature in testing / official, stable feature |
| Quantization | Compressing the numbers in vectors to save memory |
| RAG | Retrieval-augmented generation: searching your documents before answering |
| Recall@k | What fraction of the correct items appears in the top k results |
| Reranker | A model that reorders the candidates by reading the question and the chunk together |
| RRF | Reciprocal rank fusion: combining lists using only positions |
| SPLADE / ELSER | Models that expand text with related terms (learned sparse) |
Appendix · References
Official documentation (accessed on 2026-09-23)
Microsoft Azure
- Semantic ranker: https://learn.microsoft.com/en-us/azure/search/semantic-search-overview
- RRF in hybrid search: https://learn.microsoft.com/en-us/azure/search/hybrid-search-ranking
- Agentic search: https://learn.microsoft.com/en-us/azure/search/agentic-retrieval-overview
- Document Layout skill: https://learn.microsoft.com/en-us/azure/search/cognitive-search-skill-document-intelligence-layout
- Chunking in Azure AI Search: https://learn.microsoft.com/en-us/azure/search/vector-search-how-to-chunk-documents
- RAG evaluators: https://learn.microsoft.com/en-us/azure/foundry/concepts/evaluation-evaluators/rag-evaluators
- Continuous evaluation: https://learn.microsoft.com/en-us/azure/ai-foundry/how-to/continuous-evaluation-agents
Google Cloud
- Ranking API: https://cloud.google.com/generative-ai-app-builder/docs/ranking
- Check Grounding: https://cloud.google.com/generative-ai-app-builder/docs/check-grounding
- Document AI Layout Parser: https://cloud.google.com/document-ai/docs/layout-parse-chunk
- RAG Engine: https://docs.cloud.google.com/gemini-enterprise-agent-platform/build/rag-engine/rag-overview
- Hybrid search in Vector Search: https://docs.cloud.google.com/gemini-enterprise-agent-platform/build/vector-search/about-hybrid-search
- Text embeddings: https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/embeddings/get-text-embeddings
- Online Monitors: https://docs.cloud.google.com/gemini-enterprise-agent-platform/optimize/evaluation/evaluate-online
Elastic
- Semantic search: https://www.elastic.co/docs/solutions/search/semantic-search
- Vector search: https://www.elastic.co/docs/solutions/search/vector
- semantic_text: https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/semantic-text
- ELSER: https://www.elastic.co/docs/explore-analyze/machine-learning/nlp/ml-nlp-elser
- Retrievers: https://www.elastic.co/docs/reference/elasticsearch/rest-apis/retrievers
Papers and reports
Retrieval
- Gao et al., RAG for LLMs: A Survey, 2023/24 — https://arxiv.org/abs/2312.10997
- Cormack, Clarke, Büttcher, Reciprocal Rank Fusion, SIGIR 2009 — https://dl.acm.org/doi/10.1145/1571941.1572114
- Formal et al., SPLADE, 2021 — https://arxiv.org/abs/2107.05720
- Chen et al., BGE-M3, 2024 — https://arxiv.org/abs/2402.03216
- Khattab & Zaharia, ColBERT, 2020 — https://arxiv.org/abs/2004.12832
- Faysse et al., ColPali, ICLR 2025 — https://arxiv.org/abs/2407.01449
- Gao et al., HyDE, 2022 — https://arxiv.org/abs/2212.10496
- Zheng et al., Step-Back Prompting, ICLR 2024 — https://arxiv.org/abs/2310.06117
- Sarthi et al., RAPTOR, 2024 — https://arxiv.org/abs/2401.18059
- Edge et al., GraphRAG, 2024 — https://arxiv.org/abs/2404.16130
- Microsoft Research, LazyGraphRAG, 2024 — https://www.microsoft.com/en-us/research/blog/lazygraphrag-setting-a-new-standard-for-quality-and-cost/
- Gutiérrez et al., HippoRAG 2, ICML 2025 — https://arxiv.org/abs/2502.14802
- Han et al., RAG vs. GraphRAG, 2025/26 — https://arxiv.org/abs/2502.11371
- Asai et al., Self-RAG, 2023 — https://arxiv.org/abs/2310.11511
- Yan et al., Corrective RAG, 2024 — https://arxiv.org/abs/2401.15884
- Jeong et al., Adaptive-RAG, NAACL 2024 — https://arxiv.org/abs/2403.14403
- Singh et al., Agentic RAG Survey, 2025/26 — https://arxiv.org/abs/2501.09136
- Jin et al., Search-R1, 2025 — https://arxiv.org/abs/2503.09516
- Liu et al., Lost in the Middle, TACL — https://arxiv.org/abs/2307.03172
- Li et al., Self-Route, EMNLP 2024 — https://arxiv.org/abs/2407.16833
- Li et al., LaRA, 2025 — https://arxiv.org/abs/2502.09977
Chunking
- Qu, Tu, Bao (Vectara), Is Semantic Chunking Worth the Computational Cost?, 2024 — https://arxiv.org/abs/2410.13070
- Smith & Troynikov (Chroma), Evaluating Chunking Strategies for Retrieval, 2024 — https://research.trychroma.com/evaluating-chunking
- NVIDIA, Finding the Best Chunking Strategy, 2025 — https://developer.nvidia.com/blog/finding-the-best-chunking-strategy-for-accurate-ai-responses/
- Jimeno Yepes et al., Financial Report Chunking, 2024 — https://arxiv.org/abs/2402.05131
- Günther et al. (Jina), Late Chunking, 2024 — https://arxiv.org/abs/2409.04701
- Anthropic, Contextual Retrieval, 2024 — https://www.anthropic.com/engineering/contextual-retrieval (figures verified via a mirror; the original page blocked automated access)
- Bhat et al., Rethinking Chunk Size, 2025 — https://arxiv.org/abs/2505.21700
- IBM, Docling, 2024 — https://arxiv.org/abs/2408.09869
Reranking
- Nogueira & Cho, monoBERT, 2019 — https://arxiv.org/abs/1901.04085
- Thakur et al., BEIR, 2021 — https://arxiv.org/abs/2104.08663
- Sun et al., RankGPT, 2023 — https://arxiv.org/abs/2304.09542
- Pradeep et al., RankZephyr, 2023 — https://arxiv.org/abs/2312.02724
- Su et al., BRIGHT, 2024 — https://arxiv.org/abs/2407.12883
- Abdallah et al., How Good are LLM-based Rerankers?, 2025 — https://arxiv.org/abs/2508.16757
- Agentset, Cohere Rerank 4, 2025 — https://agentset.ai/blog/cohere-reranker-v4
- Qwen, Qwen3 Embedding & Reranker, 2025 — https://qwenlm.github.io/blog/qwen3-embedding/
- Jina, jina-reranker-v3.5, 2026 — https://arxiv.org/abs/2607.18152
- Mixedbread, mxbai-rerank-v2, 2025 — https://www.mixedbread.com/blog/mxbai-rerank-v2
- Jiang et al., LongLLMLingua, ACL 2024 — https://arxiv.org/abs/2310.06839
Evaluation
- Es et al., RAGAS, 2023 — https://arxiv.org/abs/2309.15217
- Saad-Falcon et al., ARES, NAACL 2024 — https://arxiv.org/abs/2311.09476
- Ru et al. (Amazon), RAGChecker, NeurIPS 2024 — https://arxiv.org/abs/2408.08067
- Gao et al., ALCE, EMNLP 2023 — https://arxiv.org/abs/2305.14627
- Zheng et al., Judging LLM-as-a-Judge, NeurIPS 2023 — https://arxiv.org/abs/2306.05685
- Thakur et al., Support Evaluation TREC 2024, SIGIR 2025 — https://arxiv.org/abs/2504.15205
- Yang et al. (Meta), CRAG benchmark, NeurIPS 2024 — https://arxiv.org/abs/2406.04744
- Islam et al., FinanceBench, 2023 — https://arxiv.org/abs/2311.11944
- Magesh et al. (Stanford), Hallucination-Free?, 2024 — https://arxiv.org/abs/2405.20362
- Vectara, Hallucination Leaderboard — https://github.com/vectara/hallucination-leaderboard
- Bao et al., FaithBench, 2024 — https://arxiv.org/abs/2410.13210
- Vectara, Open RAG Eval — https://github.com/vectara/open-rag-eval
- DeepEval, Metrics — https://deepeval.com/docs/metrics-introduction
- Databricks, Scorers and LLM judges — https://docs.databricks.com/aws/en/mlflow3/genai/eval-monitor/concepts/scorers