<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Muhammad Hussnain Jamil</title>
    <description>The latest articles on DEV Community by Muhammad Hussnain Jamil (@hussnainoffical).</description>
    <link>https://dev.to/hussnainoffical</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4213274%2Fcadbb6f0-998f-4eaa-baaf-c09dcf1beb94.jpg</url>
      <title>DEV Community: Muhammad Hussnain Jamil</title>
      <link>https://dev.to/hussnainoffical</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hussnainoffical"/>
    <language>en</language>
    <item>
      <title>Why Your RAG System Misses the Answer: A 2026 Evidence-Based Guide to Chunking, Hybrid Search and Reranking</title>
      <dc:creator>Muhammad Hussnain Jamil</dc:creator>
      <pubDate>Fri, 30 Oct 2026 05:21:41 +0000</pubDate>
      <link>https://dev.to/hussnainoffical/why-your-rag-system-misses-the-answer-a-2026-evidence-based-guide-to-chunking-hybrid-search-and-29kf</link>
      <guid>https://dev.to/hussnainoffical/why-your-rag-system-misses-the-answer-a-2026-evidence-based-guide-to-chunking-hybrid-search-and-29kf</guid>
      <description>&lt;p&gt;When a RAG system gives a wrong answer, the model is usually blamed. In practice the failure often happens earlier: the right passage never reached the model, because it was split in the wrong place, scored badly or ranked too low.&lt;/p&gt;

&lt;p&gt;In 2026 there is no shortage of advice about how to fix this. Semantic chunking, late chunking, contextual retrieval, proposition chunking, agentic search, million-token context windows. Most of it comes from vendors or tutorials. This year, though, several large independent studies tested these ideas head to head, at scale, with proper statistics.&lt;/p&gt;

&lt;p&gt;This article pulls that evidence together. It covers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Why retrieval still matters when context windows are huge&lt;/li&gt;
&lt;li&gt;Every major chunking method, how it works, what it costs and what the 2024–2026 studies found&lt;/li&gt;
&lt;li&gt;Why the retriever (hybrid search, rerankers, embeddings) usually matters more than the chunker&lt;/li&gt;
&lt;li&gt;How to evaluate your own pipeline&lt;/li&gt;
&lt;li&gt;A practical recipe, plus three small experiments of my own that show the mechanisms on a toy scale&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every number below links to its source. Where a result comes from a vendor, I say so.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Long context did not make retrieval obsolete
&lt;/h2&gt;

&lt;p&gt;The obvious question first: if a model can read 1 million tokens, why chunk anything?&lt;/p&gt;

&lt;p&gt;Three lines of evidence say retrieval is still worth it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quality drops as input grows.&lt;/strong&gt; Chroma's &lt;a href="https://trychroma.com/research/context-rot" rel="noopener noreferrer"&gt;Context Rot study&lt;/a&gt; (July 2025) tested 18 models, including GPT-4.1, Claude 4 and Gemini 2.5. Performance degraded as input length increased, even on simple tasks, and distracting passages made it worse. On LongMemEval, focused prompts of about 300 tokens clearly beat full prompts of about 113K tokens for every model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Effective context is much shorter than the advertised window.&lt;/strong&gt; In &lt;a href="https://huggingface.co/papers/2502.05167" rel="noopener noreferrer"&gt;NoLiMa&lt;/a&gt; (ICML 2025), 10 of 12 models that support 128K+ tokens fell below half of their short-context score at just 32K tokens when the question and the answer did not share keywords. GPT-4o dropped from 99.3% to 69.7%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Long context costs far more.&lt;/strong&gt; A June 2026 study, &lt;a href="https://arxiv.org/html/2606.20898v1" rel="noopener noreferrer"&gt;"The Token Tax"&lt;/a&gt;, compared long-context prompting with RAG on 324 matched questions. Long context was more accurate (73.1% vs 65.4%), but it cost about 26 times more per query ($0.118 vs $0.0045) and used about 29 times more input tokens. Their recommendation is a sensible default: use RAG first and escalate to long context only for low-confidence questions.&lt;/p&gt;

&lt;p&gt;So the realistic 2026 position is not "RAG or long context". It is "retrieve well, then decide how much context the model really needs". Retrieving well starts with the chunk.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. What a chunk is for
&lt;/h2&gt;

&lt;p&gt;A chunk has two jobs at the same time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unit of retrieval:&lt;/strong&gt; it is what gets scored against the question. Smaller chunks give sharper matches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unit of context:&lt;/strong&gt; it is what the model reads. Larger chunks keep the surrounding meaning.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every chunking method is a different trade-off between these two jobs. A useful way to see the problem is Chroma's &lt;a href="https://www.trychroma.com/research/evaluating-chunking" rel="noopener noreferrer"&gt;chunking evaluation&lt;/a&gt; (2024), which measured not only whether the relevant tokens were retrieved (recall) but also how many irrelevant tokens came with them (precision and IoU). With similar recall, strategies differed by about five times in wasted tokens. Recall alone hides that cost.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. The chunking menu in 2026
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1 Fixed-size and recursive splitting
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; cut every N tokens or characters, optionally with an overlap. Recursive splitters try paragraph breaks first, then sentences, then words, so they only cut mid-sentence as a last resort.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Evidence:&lt;/strong&gt; the simplest method keeps winning.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The largest study so far, &lt;a href="https://arxiv.org/pdf/2608.16586" rel="noopener noreferrer"&gt;Caspari et al., accepted at CIKM'26&lt;/a&gt;, compared 8 methods on corpora of up to 10 million documents with three modern embedders (Qwen3-Embedding-0.6B, EmbeddingGemma-300M, Snowflake Arctic). Their conclusion: expensive methods "rarely" beat simple ones consistently, and &lt;strong&gt;token-based chunking is a strong default at scale&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/html/2606.00881v1" rel="noopener noreferrer"&gt;Śmigielski et al.&lt;/a&gt; (May 2026) reported Accuracy@5 of 89.36 for recursive semantic chunking and 87.71 for plain fixed-size chunking. Fixed-size chunking took under a second; the proposition-based method took 15 hours.&lt;/li&gt;
&lt;li&gt;One warning from &lt;a href="https://arxiv.org/html/2603.06976" rel="noopener noreferrer"&gt;Shaukat et al.&lt;/a&gt; (March 2026): fixed &lt;em&gt;character&lt;/em&gt; chunking was the worst of 36 strategies (nDCG@5 of 0.244). Token-aware and structure-aware splitting is fine; blindly cutting characters is not.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use it when:&lt;/strong&gt; you need a baseline, a large corpus or predictable cost. That is most projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 Sentence and paragraph grouping
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; split into sentences or paragraphs, then pack whole units until a size limit is reached.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Evidence:&lt;/strong&gt; in Shaukat et al.'s 1,080-configuration study (36 strategies × 6 domains × 5 embedders), &lt;strong&gt;paragraph group chunking ranked first&lt;/strong&gt; (nDCG@5 ≈ 0.459, Hit@5 ≈ 59%). They also found that a stronger embedding model does not make up for bad segmentation. The gains from good chunking and from a good embedder add up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use it when:&lt;/strong&gt; your documents have real paragraphs, for example articles, reports and documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3 Semantic chunking
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; embed each sentence and start a new chunk where the similarity between neighbouring sentences drops.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Evidence:&lt;/strong&gt; weaker than its popularity suggests.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/html/2410.13070v1" rel="noopener noreferrer"&gt;Qu, Bao and Tu (Vectara), NAACL 2025 Findings&lt;/a&gt;: "the computational costs associated with semantic chunking are not justified by consistent performance gains." On normal documents, fixed-size chunks won (HotpotQA F1@5: 90.59 vs 87.37 for breakpoint-based semantic chunking). Semantic chunking only won on artificially "stitched" documents, where unrelated texts had been glued together.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/abs/2607.01852" rel="noopener noreferrer"&gt;Kreileder et al.&lt;/a&gt; (July 2026) found the same on academic theses: cluster-based semantic chunking did not beat fixed or recursive chunking.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use it when:&lt;/strong&gt; your documents really do mix unrelated topics without clear structure. Otherwise, test it against a recursive splitter before paying for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.4 Late chunking
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; &lt;a href="https://jina.ai/news/late-chunking-in-long-context-embedding-models/" rel="noopener noreferrer"&gt;Jina's late chunking&lt;/a&gt; runs the whole document through a long-context embedding model first, then averages the token embeddings inside each chunk's boundaries. Each chunk vector therefore "knows" about the rest of the document.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Evidence:&lt;/strong&gt; helpful on long documents in Jina's own tests (for example NFCorpus nDCG@10 from 23.46 to 29.98), but at scale it was weaker. In the CIKM'26 study, late chunking on a 1M-document corpus scored Recall@100 of 50.54 against 57.09 for plain token chunking, and it needs a lot of memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use it when:&lt;/strong&gt; you have long, coherent documents and a long-context embedder, and you have measured a gain on your own data.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.5 Contextual retrieval and contextual embeddings
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; &lt;a href="https://www.anthropic.com/news/contextual-retrieval" rel="noopener noreferrer"&gt;Anthropic's contextual retrieval&lt;/a&gt; (2024) asks an LLM to write 50–100 tokens explaining where each chunk sits in its document, and prepends that to the chunk before embedding and BM25 indexing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Evidence:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In Anthropic's tests, the top-20 retrieval failure rate fell by 35% with contextual embeddings, 49% when contextual BM25 was added, and 67% when a reranker was added as well (5.7% → 1.9%). With prompt caching, it costs about $1.02 per million document tokens.&lt;/li&gt;
&lt;li&gt;The 2026 independent evidence is more cautious. The CIKM'26 study found the cost was "rarely matched by retrieval gains", and contextual chunking processed only 0.26 documents per second at 100 generated tokens per second. On the other hand, in a financial benchmark (below), "contextual hybrid" was the best method &lt;em&gt;without&lt;/em&gt; a reranker.&lt;/li&gt;
&lt;li&gt;A newer alternative skips the LLM call: &lt;a href="https://www.mongodb.com/company/blog/product-release-announcements/voyage-context-3-focused-chunk-level-details-global-document-context" rel="noopener noreferrer"&gt;voyage-context-3&lt;/a&gt; (July 2025) embeds each chunk together with its document context in one model. Voyage reports large gains over Anthropic's method and over late chunking; these are vendor numbers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cheap version that works:&lt;/strong&gt; the CIKM'26 authors found that simply &lt;strong&gt;prepending the document title&lt;/strong&gt; ("enriched title") was the most reliable low-cost improvement. Docling's &lt;a href="https://docling-project.github.io/docling/_generated/examples/hybrid_chunking/" rel="noopener noreferrer"&gt;HybridChunker&lt;/a&gt; does the same with &lt;code&gt;contextualize()&lt;/code&gt;, which prepends the title and section headings.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.6 Proposition chunking
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; an LLM rewrites the text into short, self-contained factual statements, and each one becomes a chunk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Evidence:&lt;/strong&gt; the original &lt;a href="https://arxiv.org/abs/2312.06648" rel="noopener noreferrer"&gt;Dense X Retrieval&lt;/a&gt; paper reported strong gains, but in the 2026 head-to-head by Śmigielski et al. it was the weakest and slowest method (Accuracy@5 69.10, about 15 hours of processing).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use it when:&lt;/strong&gt; you have a small, high-value knowledge base of short facts and can afford the LLM pass.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.7 Hierarchical chunks (small-to-big, parent–child)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; retrieve small chunks for precise matching, then hand the model their larger parent section. &lt;a href="https://arxiv.org/html/2509.11552v2" rel="noopener noreferrer"&gt;HiChunk&lt;/a&gt; (ACL 2026) builds a multi-level hierarchy and merges child chunks into parents within a token budget.&lt;/p&gt;

&lt;p&gt;HiChunk's most useful point is about evaluation: most benchmarks have only about 1.7 evidence sentences per question, so they cannot tell chunkers apart. If your evaluation questions each need one sentence, every chunker looks the same.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.8 Layout-aware chunking for PDFs
&lt;/h3&gt;

&lt;p&gt;Real documents are not plain text. Tables, headings and page structure matter.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In Unstructured's &lt;a href="https://arxiv.org/html/2402.05131v3" rel="noopener noreferrer"&gt;FinanceBench study&lt;/a&gt;, chunks based on document elements (titles, tables, lists) improved question-answering accuracy from 48.23% to 53.19% compared with 512-token chunks.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.nvidia.com/blog/finding-the-best-chunking-strategy-for-accurate-ai-responses/" rel="noopener noreferrer"&gt;NVIDIA's 2025 chunking study&lt;/a&gt; found that &lt;strong&gt;page-level chunks&lt;/strong&gt; had the best average accuracy (0.648) and the lowest variance across five datasets. Factoid questions did best with 256–512 token chunks; analytical questions did best with 1,024 tokens or whole pages.&lt;/li&gt;
&lt;li&gt;Docling's HybridChunker can repeat table headers in each chunk and should use the same tokenizer as your embedding model.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.9 Visual retrieval: skipping text extraction
&lt;/h3&gt;

&lt;p&gt;For slide decks, scanned reports and pages full of charts, you can embed page images directly with ColPali-style models. On &lt;a href="https://arxiv.org/html/2601.08620v1" rel="noopener noreferrer"&gt;ViDoRe V3&lt;/a&gt; (January 2026: about 26K pages, 3,099 human-verified queries in 6 languages including German), the best visual retriever scored 59.8 nDCG@10 against 51.0 for the best text-based retriever. A text reranker still added 13.2 points to the text pipeline, so reranking matters there too.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. What the large studies agree on
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Study&lt;/th&gt;
&lt;th&gt;Scale&lt;/th&gt;
&lt;th&gt;Main finding&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.trychroma.com/research/evaluating-chunking" rel="noopener noreferrer"&gt;Chroma 2024&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;472 queries, 5 corpora&lt;/td&gt;
&lt;td&gt;Strategies differ by up to 9% recall and ~5× in wasted tokens; 200-token recursive splitting was a strong choice&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://arxiv.org/html/2410.13070v1" rel="noopener noreferrer"&gt;Vectara, NAACL 2025&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Several QA datasets&lt;/td&gt;
&lt;td&gt;Semantic chunking's cost not justified on normal documents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://developer.nvidia.com/blog/finding-the-best-chunking-strategy-for-accurate-ai-responses/" rel="noopener noreferrer"&gt;NVIDIA 2025&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;5 datasets&lt;/td&gt;
&lt;td&gt;Page-level chunks most accurate and most stable; chunk size should follow query type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://arxiv.org/html/2603.06976" rel="noopener noreferrer"&gt;Shaukat et al. 2026&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;1,080 configurations&lt;/td&gt;
&lt;td&gt;Paragraph grouping best; character cutting worst; chunker and embedder gains add up&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://arxiv.org/html/2606.00881v1" rel="noopener noreferrer"&gt;Śmigielski et al. 2026&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Cost vs quality&lt;/td&gt;
&lt;td&gt;Recursive and fixed-size give the best balance; LLM-based methods slow and fragile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://arxiv.org/pdf/2608.16586" rel="noopener noreferrer"&gt;Caspari et al., CIKM'26&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Up to 10M documents&lt;/td&gt;
&lt;td&gt;Complex chunking rarely wins; token chunking + title is the default&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The pattern is consistent: &lt;strong&gt;structure-aware, size-limited chunks plus a little cheap context (title, headings) get you most of the way.&lt;/strong&gt; Expensive chunkers can win on specific datasets, but the gains shrink as the corpus grows and they cost a lot of compute.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. A small experiment: watching chunking fail
&lt;/h2&gt;

&lt;p&gt;In my lab repository, &lt;a href="https://github.com/Hussnainoffical/applied-llm-lab" rel="noopener noreferrer"&gt;applied-llm-lab&lt;/a&gt;, I write each retrieval component from scratch with tests. Three experiments show the mechanisms behind the studies above on a toy scale. This is a tiny, five-question set, so it illustrates the mechanism; it is not a benchmark.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experiment 1: three chunkers on the same text.&lt;/strong&gt; At almost the same chunk size, fixed-size chunking cut 3 of 4 chunks mid-sentence. Sentence packing cut none.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;by_sentence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_chars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Pack whole sentences into chunks up to max_chars.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;sentences&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(?&amp;lt;=[.!?])\s+&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
    &lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sentences&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;max_chars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;chunks&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Experiment 2: BM25 from scratch.&lt;/strong&gt; I implemented Okapi BM25 (k1 = 1.5, b = 0.75) and asked five questions, each with the exact fact the top chunk must contain in full.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;norm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;k1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;avgdl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;idf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;k1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
               &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;tokenize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Experiment 3: TF-IDF cosine search with NumPy&lt;/strong&gt;, plus three paraphrased questions that ask for the same facts in different words.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Chunking&lt;/th&gt;
&lt;th&gt;BM25, original questions&lt;/th&gt;
&lt;th&gt;Cosine, original questions&lt;/th&gt;
&lt;th&gt;BM25, paraphrased&lt;/th&gt;
&lt;th&gt;Cosine, paraphrased&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fixed size (120 chars)&lt;/td&gt;
&lt;td&gt;2 / 5&lt;/td&gt;
&lt;td&gt;2 / 5&lt;/td&gt;
&lt;td&gt;0 / 3&lt;/td&gt;
&lt;td&gt;1 / 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fixed size + 30 overlap&lt;/td&gt;
&lt;td&gt;4 / 5&lt;/td&gt;
&lt;td&gt;4 / 5&lt;/td&gt;
&lt;td&gt;0 / 3&lt;/td&gt;
&lt;td&gt;0 / 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sentence packing (160)&lt;/td&gt;
&lt;td&gt;5 / 5&lt;/td&gt;
&lt;td&gt;5 / 5&lt;/td&gt;
&lt;td&gt;0 / 3&lt;/td&gt;
&lt;td&gt;0 / 3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three lessons, each matching the large studies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Chunking decided more than the scoring formula.&lt;/strong&gt; BM25 and cosine picked the same top chunk in 14 of 15 cases. Changing the chunker moved the score from 2/5 to 5/5. This is Shaukat et al.'s finding in miniature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overlap is a patch.&lt;/strong&gt; It recovered most of the gap but added a chunk to index. At scale, that means more storage and more embedding cost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lexical methods cannot handle paraphrases.&lt;/strong&gt; Both failed on every reworded question (the single "hit" was an accident: the chunker cut "con|text" and the leftover "text" matched the question). That gap is why the next section matters.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  6. The retriever matters more than the chunker
&lt;/h2&gt;

&lt;h3&gt;
  
  
  6.1 Hybrid search plus a reranker
&lt;/h3&gt;

&lt;p&gt;The clearest 2026 result comes from &lt;a href="https://arxiv.org/html/2604.01733v1" rel="noopener noreferrer"&gt;Akarsu et al.&lt;/a&gt; (April 2026), who benchmarked retrieval strategies on T2-RAGBench: 23,088 questions over 7,318 financial documents mixing text and tables.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Recall@5&lt;/th&gt;
&lt;th&gt;nDCG@10&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;BM25&lt;/td&gt;
&lt;td&gt;0.644&lt;/td&gt;
&lt;td&gt;0.515&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dense (text-embedding-3-large)&lt;/td&gt;
&lt;td&gt;0.587&lt;/td&gt;
&lt;td&gt;0.466&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HyDE&lt;/td&gt;
&lt;td&gt;0.544&lt;/td&gt;
&lt;td&gt;0.433&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-query + RRF&lt;/td&gt;
&lt;td&gt;0.640&lt;/td&gt;
&lt;td&gt;0.506&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hybrid (BM25 + dense, RRF)&lt;/td&gt;
&lt;td&gt;0.695&lt;/td&gt;
&lt;td&gt;0.551&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Contextual hybrid&lt;/td&gt;
&lt;td&gt;0.717&lt;/td&gt;
&lt;td&gt;0.571&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hybrid + reranker&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.816&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.683&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three things stand out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BM25 beat a strong dense model.&lt;/strong&gt; On financial text full of exact terms and numbers, keyword matching still wins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HyDE hurt.&lt;/strong&gt; Generating a hypothetical answer and searching with it made retrieval worse.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid plus reranking was best by a wide margin:&lt;/strong&gt; Recall@5 rose by about 23 points over dense retrieval alone and about 17 points over BM25.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My third experiment explains why hybrid helps: lexical search catches exact terms, dense embeddings catch paraphrases, and each covers the other's blind spot. Reciprocal rank fusion (RRF) merges the two ranked lists without needing to calibrate their scores.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.2 Why one vector per chunk has a ceiling
&lt;/h3&gt;

&lt;p&gt;Google DeepMind's &lt;a href="https://arxiv.org/html/2508.21038v1" rel="noopener noreferrer"&gt;LIMIT paper&lt;/a&gt; (ICLR 2026) showed a theoretical limit: the embedding dimension bounds which sets of top-k documents a single-vector retriever can return for any query. Even state-of-the-art MTEB models scored under 20 Recall@100 on a deliberately simple dataset built around that limit. The practical conclusion is to add a stage that is not a single vector: sparse BM25, multi-vector late interaction, or a cross-encoder reranker.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.3 Late interaction is back
&lt;/h3&gt;

&lt;p&gt;ColBERT-style models keep one vector per token and compare query and document tokens individually. In March 2026, LightOn reported that its 149M-parameter &lt;a href="https://lighton.ai/lighton-blogs/the-bloated-retriever-era-is-over" rel="noopener noreferrer"&gt;Reason-ModernColBERT&lt;/a&gt; reached 87.59% accuracy on BrowseComp-Plus with GPT-5, against 80.00% for the previous best, while needing fewer search calls. It also beat an 8B dense embedder about 54 times its size. These are vendor numbers, but they fit the LIMIT theory.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.4 Rerankers in 2026
&lt;/h3&gt;

&lt;p&gt;A reranker reads the question and each candidate chunk together and scores how well they match. It is slower than vector search, so you use it on the top 50–150 candidates only. Anthropic recommends retrieving 150 and reranking down to 20.&lt;/p&gt;

&lt;p&gt;The community &lt;a href="https://github.com/agentset-ai/reranker-eval" rel="noopener noreferrer"&gt;reranker-eval&lt;/a&gt; ranking currently puts zerank-2, Cohere Rerank 4 Pro, zerank-1 and Voyage rerank-2.5 at the top, with Qwen3-Reranker-8B and BGE-reranker-v2-m3 as strong open-weight options. Cohere's Rerank 4 (December 2025) raised its context to 32K tokens, so it can score long chunks.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.5 Embedding models, and a warning about leaderboards
&lt;/h3&gt;

&lt;p&gt;Strong options in 2026 include the &lt;a href="https://huggingface.co/Qwen/Qwen3-Embedding-4B" rel="noopener noreferrer"&gt;Qwen3-Embedding&lt;/a&gt; family (0.6B to 8B, 32K context), &lt;a href="https://blog.voyageai.com/2026/01/15/new-models-and-expanded-availability/" rel="noopener noreferrer"&gt;Voyage 4&lt;/a&gt; (whose models share one embedding space, so you can switch models without re-indexing), &lt;a href="https://www.elastic.co/search-labs/blog/jina-embeddings-v5-text" rel="noopener noreferrer"&gt;jina-embeddings-v5&lt;/a&gt; and the multimodal &lt;a href="https://siliconangle.com/2026/10/06/google-expands-embeddinggemma-beyond-text-to-images-audio-and-video/" rel="noopener noreferrer"&gt;EmbeddingGemma 2&lt;/a&gt; (October 2026).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For German documents&lt;/strong&gt;, the community model &lt;a href="https://huggingface.co/blog/malteos/most-embed-de-german-embedding-model" rel="noopener noreferrer"&gt;most-embed-de&lt;/a&gt; (September 2026) reports first place on the German MTEB retrieval tasks; these are the author's own numbers. ViDoRe V3 found a 2–3 point penalty when queries and documents are in different languages, so test with real German queries if you serve German users.&lt;/p&gt;

&lt;p&gt;The warning: &lt;a href="https://trychroma.com/research/generative-benchmarking" rel="noopener noreferrer"&gt;Chroma found&lt;/a&gt; that MTEB rankings did not transfer to a real-world dataset. A model that ranked higher on MTEB scored lower on their production data (Recall@10 of 0.532 vs 0.602). Always test the top two or three candidates on your own questions.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Agentic retrieval: where it fits
&lt;/h2&gt;

&lt;p&gt;Agents now search iteratively: they run a query, read results, refine the query and search again. Anthropic's &lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents" rel="noopener noreferrer"&gt;context engineering guidance&lt;/a&gt; describes "just-in-time" retrieval through tools, combined with some context loaded up front.&lt;/p&gt;

&lt;p&gt;Two findings keep this grounded:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The retriever still sets the ceiling.&lt;/strong&gt; On &lt;a href="https://arxiv.org/abs/2508.06600" rel="noopener noreferrer"&gt;BrowseComp-Plus&lt;/a&gt;, the same agent (GPT-5) scored 55.9% with BM25 and 70.1% with Qwen3-Embedding-8B, and needed fewer searches with the better retriever.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query rewriting is not free accuracy.&lt;/strong&gt; In the T2-RAGBench study, HyDE reduced recall and multi-query fusion only matched plain BM25.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An agent multiplies the quality of its search tool. It does not replace it.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. How to evaluate your own pipeline
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Metrics:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hit rate@k / Recall@k:&lt;/strong&gt; did the needed chunk appear in the top k?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MRR:&lt;/strong&gt; how high was the first correct chunk?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;nDCG@k:&lt;/strong&gt; rewards correct chunks near the top, with graded relevance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token precision / IoU:&lt;/strong&gt; how much irrelevant text came along (from the Chroma method). Useful when context cost matters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Build a test set from your own documents.&lt;/strong&gt; Chroma's &lt;a href="https://trychroma.com/research/generative-benchmarking" rel="noopener noreferrer"&gt;generative benchmarking&lt;/a&gt; generates realistic questions from your corpus and filters them; after five iterations their LLM judge agreed with humans 75.2% of the time, up from 46%. Even 50–100 good questions beat any public leaderboard for your use case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make questions that need real evidence.&lt;/strong&gt; Following HiChunk's point, include questions whose answers span several sentences or a table, or every chunker will look the same.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be careful with LLM-judged scores.&lt;/strong&gt; &lt;a href="https://docs.ragas.io/en/latest/howtos/migrations/migrate_from_v03_to_v04/" rel="noopener noreferrer"&gt;RAGAS v0.4&lt;/a&gt; (December 2025) changed its API (&lt;code&gt;@experiment()&lt;/code&gt; replaces &lt;code&gt;evaluate()&lt;/code&gt;), and the 2026 thesis study found its faithfulness score unreliable. Use retrieval metrics with a fixed answer key wherever you can.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. A practical recipe for late 2026
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start simple.&lt;/strong&gt; Recursive or paragraph-aware chunks of about 256–512 tokens, small overlap, same tokenizer as the embedder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add cheap context.&lt;/strong&gt; Prepend the document title and section headings to each chunk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Respect structure.&lt;/strong&gt; For PDFs, use a layout-aware parser (for example Docling) and keep tables whole with their headers. Consider page-level chunks for reports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use hybrid retrieval.&lt;/strong&gt; BM25 + dense embeddings, merged with RRF.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rerank.&lt;/strong&gt; Retrieve 50–150 candidates and rerank to the top 5–20.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluate on your own questions&lt;/strong&gt; with Recall@k, MRR and nDCG before changing anything expensive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only then try advanced chunking&lt;/strong&gt; (contextual, late, semantic, propositions), and keep it only if it beats step 6 on your data at a cost you accept.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use long context selectively&lt;/strong&gt;, for questions where retrieval confidence is low.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  10. What I'm testing next
&lt;/h2&gt;

&lt;p&gt;Next in the lab: hit rate and MRR on a larger question set, learned embeddings against TF-IDF on the paraphrased questions, hybrid search with RRF, and a cross-encoder reranker on top. I'll publish the numbers as they come in, including the ones that don't go my way.&lt;/p&gt;

&lt;p&gt;Code and tests: &lt;a href="https://github.com/Hussnainoffical/applied-llm-lab" rel="noopener noreferrer"&gt;github.com/Hussnainoffical/applied-llm-lab&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm Muhammad Hussnain Jamil, an applied LLM and AI automation engineer and co-author of published research on multi-agent LLM systems. I'm learning German (A2) and open to AI roles in Germany. &lt;a href="https://muhammad-hussnain-jamil-portfolio.vercel.app" rel="noopener noreferrer"&gt;Portfolio&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Caspari et al., "When Is Complex Chunking Worth It?", CIKM'26: &lt;a href="https://arxiv.org/pdf/2608.16586" rel="noopener noreferrer"&gt;https://arxiv.org/pdf/2608.16586&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Śmigielski et al., 2026: &lt;a href="https://arxiv.org/html/2606.00881v1" rel="noopener noreferrer"&gt;https://arxiv.org/html/2606.00881v1&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Shaukat et al., 2026: &lt;a href="https://arxiv.org/html/2603.06976" rel="noopener noreferrer"&gt;https://arxiv.org/html/2603.06976&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Qu, Bao and Tu (Vectara), NAACL 2025 Findings: &lt;a href="https://arxiv.org/html/2410.13070v1" rel="noopener noreferrer"&gt;https://arxiv.org/html/2410.13070v1&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Kreileder et al., 2026: &lt;a href="https://arxiv.org/abs/2607.01852" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2607.01852&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Chroma, Evaluating Chunking: &lt;a href="https://www.trychroma.com/research/evaluating-chunking" rel="noopener noreferrer"&gt;https://www.trychroma.com/research/evaluating-chunking&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;NVIDIA, Finding the Best Chunking Strategy: &lt;a href="https://developer.nvidia.com/blog/finding-the-best-chunking-strategy-for-accurate-ai-responses/" rel="noopener noreferrer"&gt;https://developer.nvidia.com/blog/finding-the-best-chunking-strategy-for-accurate-ai-responses/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Anthropic, Contextual Retrieval: &lt;a href="https://www.anthropic.com/news/contextual-retrieval" rel="noopener noreferrer"&gt;https://www.anthropic.com/news/contextual-retrieval&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Jina, Late Chunking: &lt;a href="https://jina.ai/news/late-chunking-in-long-context-embedding-models/" rel="noopener noreferrer"&gt;https://jina.ai/news/late-chunking-in-long-context-embedding-models/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Voyage/MongoDB, voyage-context-3: &lt;a href="https://www.mongodb.com/company/blog/product-release-announcements/voyage-context-3-focused-chunk-level-details-global-document-context" rel="noopener noreferrer"&gt;https://www.mongodb.com/company/blog/product-release-announcements/voyage-context-3-focused-chunk-level-details-global-document-context&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Chen et al., Dense X Retrieval: &lt;a href="https://arxiv.org/abs/2312.06648" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2312.06648&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;HiChunk, ACL 2026: &lt;a href="https://arxiv.org/html/2509.11552v2" rel="noopener noreferrer"&gt;https://arxiv.org/html/2509.11552v2&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Jimeno Yepes et al., element-based chunking (FinanceBench): &lt;a href="https://arxiv.org/html/2402.05131v3" rel="noopener noreferrer"&gt;https://arxiv.org/html/2402.05131v3&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docling HybridChunker: &lt;a href="https://docling-project.github.io/docling/_generated/examples/hybrid_chunking/" rel="noopener noreferrer"&gt;https://docling-project.github.io/docling/_generated/examples/hybrid_chunking/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ViDoRe V3: &lt;a href="https://arxiv.org/html/2601.08620v1" rel="noopener noreferrer"&gt;https://arxiv.org/html/2601.08620v1&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Akarsu et al., From BM25 to Corrective RAG (T2-RAGBench): &lt;a href="https://arxiv.org/html/2604.01733v1" rel="noopener noreferrer"&gt;https://arxiv.org/html/2604.01733v1&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;LIMIT, Google DeepMind: &lt;a href="https://arxiv.org/html/2508.21038v1" rel="noopener noreferrer"&gt;https://arxiv.org/html/2508.21038v1&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;LightOn, Reason-ModernColBERT: &lt;a href="https://lighton.ai/lighton-blogs/the-bloated-retriever-era-is-over" rel="noopener noreferrer"&gt;https://lighton.ai/lighton-blogs/the-bloated-retriever-era-is-over&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Agentset reranker-eval: &lt;a href="https://github.com/agentset-ai/reranker-eval" rel="noopener noreferrer"&gt;https://github.com/agentset-ai/reranker-eval&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Qwen3-Embedding: &lt;a href="https://huggingface.co/Qwen/Qwen3-Embedding-4B" rel="noopener noreferrer"&gt;https://huggingface.co/Qwen/Qwen3-Embedding-4B&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Voyage 4: &lt;a href="https://blog.voyageai.com/2026/01/15/new-models-and-expanded-availability/" rel="noopener noreferrer"&gt;https://blog.voyageai.com/2026/01/15/new-models-and-expanded-availability/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;most-embed-de: &lt;a href="https://huggingface.co/blog/malteos/most-embed-de-german-embedding-model" rel="noopener noreferrer"&gt;https://huggingface.co/blog/malteos/most-embed-de-german-embedding-model&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Chroma, Context Rot: &lt;a href="https://trychroma.com/research/context-rot" rel="noopener noreferrer"&gt;https://trychroma.com/research/context-rot&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;NoLiMa: &lt;a href="https://huggingface.co/papers/2502.05167" rel="noopener noreferrer"&gt;https://huggingface.co/papers/2502.05167&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The Token Tax: &lt;a href="https://arxiv.org/html/2606.20898v1" rel="noopener noreferrer"&gt;https://arxiv.org/html/2606.20898v1&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Anthropic, Effective Context Engineering: &lt;a href="https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents" rel="noopener noreferrer"&gt;https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;BrowseComp-Plus: &lt;a href="https://arxiv.org/abs/2508.06600" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2508.06600&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Chroma, Generative Benchmarking: &lt;a href="https://trychroma.com/research/generative-benchmarking" rel="noopener noreferrer"&gt;https://trychroma.com/research/generative-benchmarking&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;RAGAS v0.4 migration guide: &lt;a href="https://docs.ragas.io/en/latest/howtos/migrations/migrate_from_v03_to_v04/" rel="noopener noreferrer"&gt;https://docs.ragas.io/en/latest/howtos/migrations/migrate_from_v03_to_v04/&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>rag</category>
      <category>llm</category>
      <category>machinelearning</category>
      <category>python</category>
    </item>
  </channel>
</rss>
