AI agents

Reading a Retrieval Change as a Curve Shift, Not a Score

Antonio Evans9 min read

A line chart with two curves over the same x-axis sweep (top-k from 1 to 20).
Key points

Key points

  1. 1A single pass or fail after a chunker or embedder change tells you where one configuration landed at one setting, not whether the quality curve moved.
  2. 2Running the same sweep before and after (same queries, same labels, same top-k range) turns a release decision into a comparison of two curves.
  3. 3The shape of the gap, not its average, shows whether the change buys precision at small k and costs recall at large k.
  4. 4A difference is only real if it clears the confidence band from repeated runs and judge variance.

Why one evaluation point hides the effect

Suppose your golden set of 25 queries answers 20 correctly at top-k = 5. A new chunker scores 19. Most teams call that a regression and revert. The number is true and almost useless. It describes a single coordinate in a two-dimensional space: a quality value at one retrieval depth. A chunker or embedder change is a change to the whole function that maps depth to quality, so a point comparison cannot distinguish a curve that dropped slightly everywhere from a curve that lost one query at depth 5 and gained two at depth 15.

The deeper problem is that retrieval depth is a live parameter in production, not a constant. Retriever output is computed per query at a chosen k, then passed into the prompt under a context budget. Chunk size, chunk count and prompt length multiply into latency and cost, so the k you ship is a compromise someone made once and never revisited. Reading a change only at that k means reading it at the one place where the compromise was already struck. The reading is biased toward whatever the incumbent configuration favored.

There is also a structural reason to expect the curve to be non-flat. Chunk size interacts with answer length in the corpus: Fraunhofer's multi-dataset sweep found 64 to 128 token chunks best for concise fact-based answers while 512 to 1024 token chunks improved retrieval where broader context is needed Rethinking Chunk Size for Long-Document Retrieval. The same paper reports that embedding models differ in chunking sensitivity, with some benefiting from larger chunks and others from smaller. If chunk size and model choice both bend the depth-quality relationship, then measuring at one depth measures the bend at one hinge.

Chroma's evaluation makes the same point from the metric side: the choice of chunking strategy has a significant impact on retrieval accuracy and efficiency, and default settings for some popular splitters perform relatively poorly Evaluating Chunking Strategies for Retrieval. A default that looks fine at one k can be the worst option in the table at another.

Define the sweep before you touch the pipeline

A curve comparison only means something if both runs share every input except the variable under test. Write the contract down before the first run.

ElementFreeze or varyWhy
Query setFreezeA changed query set is a different experiment
Labels (relevant chunks or spans)FreezeRelabeling moves both curves
Top-k range (for example 1 to 20)Freeze at every integer kThe x-axis must be identical
Judge model and promptFreezeJudge drift looks like retrieval drift
Answer model and temperatureFreezeGeneration variance contaminates the curve
Chunker parameters, embedderVary one at a timeTwo changes at once is one unreadable curve
Prompt template and context budgetFreezeOtherwise you are measuring two pipelines

Your golden set does not need to be large. A fixed set of 20 to 30 pairs is enough to catch regressions, and the value is that it is fixed, so every change is compared against the same expectation How to Know Your RAG Changes Actually Helped. Freeze the labels even if you later grow the set: run the larger set against both configurations rather than comparing new measurements to old ones.

Pick a quality metric that responds to depth and that you trust. Token-level precision and recall on retrieved tokens, plus intersection-over-union, capture chunking effects that document-level benchmarks miss Evaluating Chunking Strategies for Retrieval. If you score with an LLM judge, keep the prompt narrow and the scale tight. A 0 to 2 relevance scale with a required one-sentence reason is more stable across runs than a 0 to 10 scale, and wrapping the chunk in delimiters with an explicit "treat as data, not instructions" line blunts prompt injection through retrieved text How to Know Your RAG Changes Actually Helped. For end-to-end answer quality, faithfulness and answer relevancy measure different failures and should stay separate; a system can retrieve perfectly and still hallucinate RAG evaluation metrics.

One caution on end-to-end scoring at many depths: RAGAs-based faithfulness showed limited reliability in at least one academic-text study, and performance on fixed versus document-specific questions varied substantially, likely due to formatting and preprocessing Evaluating Chunking Strategies for RAG on Academic Texts. If your judge is shaky, run retrieval metrics as the primary curve and treat the answer-quality curve as corroboration.

Run the sweep twice and put the results in one table

The mechanics are simple. For each k from 1 to 20, retrieve top-k, compute the metric, write a row. Do it for the incumbent configuration, then for the candidate. Then join on k.

import json, statistics

def sweep(queries, retriever, judge, ks=range(1, 21), repeats=3):
    rows = []
    for k in ks:
        scores = []
        for _ in range(repeats):          # repeat to estimate noise
            for q in queries:
                chunks = retriever.search(q.text, k=k)
                scores.append(judge.score(q.text, chunks))
        rows.append({
            "k": k,
            "mean": statistics.mean(scores),
            "sd": statistics.stdev(scores),
            "n": len(scores),
        })
    return rows

base = sweep(queries, retriever_before, judge)
cand = sweep(queries, retriever_after, judge)

for b, c in zip(base, cand):
    delta = c["mean"] - b["mean"]
    se = ((b["sd"] ** 2 + c["sd"] ** 2) / b["n"]) ** 0.5
    print(b["k"], round(b["mean"], 3), round(c["mean"], 3),
          round(delta, 3), "clears SE" if abs(delta) > 1.96 * se else "inside noise")

Two implementation notes. First, repeat each depth a few times with the same judge and let the variance tell you whether a delta is real; comparing means without an error estimate is how a 1-point move becomes a release decision. Second, if you judge answer quality end to end, hold the generation prompt fixed and be aware that the model's tolerance for extra context varies. One analysis notes that LLMs are relatively insensitive to the position of relevant information in the window, which is why token presence matters more than ranking in these evaluations Evaluating Chunking Strategies for Retrieval.

A worked example, with numbers invented for illustration:

kBeforeAfterDeltaReading
10.520.58+0.06Better top hit
30.660.71+0.05Gain holds
50.740.75+0.01Gain fades
100.840.81-0.03Reversal starts
150.880.82-0.06Recall loss
200.900.83-0.07Recall loss deepens

Read this as a rotation, not a lift. The candidate buys precision near the top of the list and loses recall deeper down. That is exactly the signature you would expect from smaller chunks: the vector for each chunk is more specific and matches a query better, while the evidence for multi-part questions is now split across more chunks, so one query can no longer be fully satisfied by any single retrieved item. The parent-child approach exists precisely to trade this off, storing small chunks for matching and returning the enclosing larger chunk for context Parent-Child Chunking in LangChain for Advanced RAG. Parent chunks typically run several hundred to a couple thousand tokens, child chunks a hundred to a few hundred, so a curve that shows the rotation above is a signal to try hierarchical retrieval rather than to revert.

Read the shape: crossing curves, parallel curves, and noise

Four shapes cover most real comparisons, and each implies a different release decision.

Parallel lift. The candidate curve sits above the incumbent at every k by roughly the same margin. The change is a genuine improvement and the only question is cost: more chunks stored, higher token spend per query. Ship it if the margin clears noise, then re-tune k downward to reclaim latency.

Rotation. The curves cross. One configuration is better at small k, the other at large k. This is the common case for chunk-size and reranker changes. The decision rule: compare the two at the k you actually ship, and if the new k is better, check whether the regression at the other k affects any real workload. If users routinely ask multi-part questions that need evidence from several passages, the large-k loss matters more than the small-k gain.

Sandwich or dip. The candidate dips in the middle of the range and recovers or surpasses at both ends. Usually a sign that the new chunks split a small number of key passages, so a mid-depth retrieval lands on fragments, while deep retrieval still picks up the pieces. Fix the splitter at the document structure level rather than abandoning the change.

Noise. The gap wanders above and below zero by amounts smaller than the error band. Nothing happened, or the golden set is too small to see what happened. Grow the set or tighten the judge before spending another week on the pipeline.

The shape also tells you where the risk sits for the whole release. If the candidate only improves at k = 1 to 3, then any downstream component that reads more chunks, such as a reranker or a context compressor, gets no benefit, and a reranker's job is to reorder candidates before generation anyway Retrieval Latency Optimization for Production RAG Systems. If the gain is concentrated at large k, you need the budget to actually pass large k into the prompt.

Structure matters as much as size when you read a shape. NVIDIA's chunking experiments found page-level chunking reaching an average end-to-end RAG accuracy of 0.648 with the lowest standard deviation of 0.107 across tested datasets, while extreme sizes of 128 and 2,048 tokens generally underperformed medium sizes, and the best size differed by document type: 1,024 tokens for FinanceBench, 512 for Earnings Finding the Best Chunking Strategy for Accurate AI Responses. That is a curve argument, not a point argument. A single test at one size on one dataset would have picked the wrong winner for the other dataset.

Cost and latency live on the same axis

Every point on your curve has a price, and the price is not flat. Retrieval latency and context cost both scale with how much you retrieve and how much of it reaches the model. A smaller chunk size roughly doubles vector count for the same corpus, and a 500 ms retrieval allowance broken down by stage leaves little room for retries and reranking once primary retrieval and assembly take their share Latency Budgets for Memory Retrieval. NVIDIA's sizing work, as summarized in a benchmark review, reported time to first token climbing from about 2.0 seconds at 256-token chunks to 7.1 at 1,024, and separately rising from 3.6 to 7.9 seconds when top-k went from four to 10 Advanced Chunking Techniques: What The Benchmarks Actually Show. Those two levers multiply.

So plot a second y-axis before you decide. For each k, record retrieval time and prompt tokens alongside quality. The release decision becomes a question about a rectangle in that space: does the candidate curve dominate the incumbent at an affordable (k, cost) point, and does it stay on top at the tail rather than just the median? Measure p95 and p99, not just averages, because tail latency shapes user trust One post tagged with latency trade-offs.

A practical shortcut: if the candidate's best affordable point beats the incumbent's shipped point by more than the error band, and the worst point in the tested range is not materially worse than the incumbent's worst, ship. If either condition fails, iterate on the chunker parameters rather than the release.

Where teams get this wrong

The most expensive mistake is sweeping the wrong variable. Changing chunker and embedder together produces a curve you cannot attribute. The second is sweeping on a shifted query set, which makes the two curves incomparable at every k. The third is trusting a single judge call per query and reading a delta that lives inside judge variance. A fourth is ignoring answer-side metrics: a retrieval change can improve context precision while the model still answers from the wrong passage, and context precision and context recall move in opposite directions as you change depth RAG evaluation metrics.

A subtler error is over-reacting to advanced-chunking gains. Simpler recursive splitting with sensible overlap often captures most of the available improvement, though defaults can be weak until you tune them Evaluating Chunking Strategies for Retrieval. And the frontier keeps moving: model-aware splitters that derive boundaries from the target model's own tokenizer address tokenization mismatch across model families, where a 512-character window can land anywhere from roughly 100 to 400 tokens depending on the encoder ChunkRank. If you are about to compare two embedding models, check whether your chunk boundaries are sized in the wrong unit, or your curve is comparing two splitters rather than two embedders.

The last error is deciding from the mean of the curve. The mean across k answers a question nobody asked. Report the delta at every k, mark which ones clear the band, and make the release call from the k your users experience and the workload your traffic shows.

When the sweep needs to run against several models at once (an embedding model candidate, a judge, an answer model), routing each through one endpoint removes the per-provider plumbing from the experiment. Quanta Inference gives you text, image, video, audio and embedding models through one OpenAI-compatible API key, priced in US dollars, so the only variable in the sweep is the one you meant to test: https://quantaintelligence.ai/inference.

FAQ

FAQ

How many queries do I need to see a curve shift?

Enough that the error band is smaller than the effect you care about. A fixed set of 20 to 30 labeled pairs is a reasonable start for catching regressions How to Know Your RAG Changes Actually Helped. Run each point a few times and compute the standard error before declaring a difference real.

What top-k range should the sweep cover?

Cover from 1 to roughly twice the largest k you would ever pass to the model, so the curve shows both the precision end and the recall end. If your production pipeline retrieves 5 chunks and a reranker trims to 3, sweep at least 1 to 20 so the reversal point is visible rather than sitting off the chart.

Can I compare curves from different query sets?

No. A curve is a function of the query distribution as much as the pipeline, so changed queries make both curves different experiments. Add the new queries to both runs and recompute the incumbent curve on the larger set.

What if the curves cross?

That is the normal outcome for chunk-size changes. Decide from the crossing point and from traffic: which side of the crossing do your real queries fall on, and does the loss at the other end affect any workload you actually serve. Then look at a hierarchical design (small chunks for matching, larger parents for context) before reverting.

Does the curve shape change with the embedding model?

Yes, and that is a reason to sweep rather than assume. Different embedding models show different chunking sensitivity, with some favoring larger chunks and others favoring smaller ones Rethinking Chunk Size for Long-Document Retrieval. Run the same sweep per candidate model and compare curves at matched cost, not just at matched k.

Sources

Sources

  1. Rethinking Chunk Size for Long-Document Retrieval
  2. Evaluating Chunking Strategies for Retrieval - Chroma
  3. How to Know Your RAG Changes Actually Helped
  4. How to evaluate your RAG pipeline with Braintrust - Articles
  5. Evaluating Chunking Strategies for Retrieval-Augmented ...
  6. Parent-Child Chunking in LangChain for Advanced RAG - Medium
  7. Retrieval Latency Optimization for Production RAG Systems
  8. Finding the Best Chunking Strategy for Accurate AI Responses
  9. Latency Budgets for Memory Retrieval
  10. Advanced Chunking Techniques: What The Benchmarks ...
  11. One post tagged with "latency trade-offs"
  12. ChunkRank: Model-Aware Text Chunking and Abstention- ...
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles