<?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: Hua Li</title>
    <description>The latest articles on DEV Community by Hua Li (@hualiphd).</description>
    <link>https://dev.to/hualiphd</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%2F4167655%2Fc683c000-3f28-4266-b15f-5055f9a35c90.jpeg</url>
      <title>DEV Community: Hua Li</title>
      <link>https://dev.to/hualiphd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hualiphd"/>
    <language>en</language>
    <item>
      <title>A true claim can still be a hallucination</title>
      <dc:creator>Hua Li</dc:creator>
      <pubDate>Wed, 28 Oct 2026 05:36:01 +0000</pubDate>
      <link>https://dev.to/hualiphd/a-true-claim-can-still-be-a-hallucination-30n2</link>
      <guid>https://dev.to/hualiphd/a-true-claim-can-still-be-a-hallucination-30n2</guid>
      <description>&lt;p&gt;&lt;strong&gt;Summary.&lt;/strong&gt; Most discussion of hallucination is about claims that are false. A harder case is a claim that is true but not supported by the sources an answer cites. Summarization research calls this a &lt;em&gt;factual hallucination&lt;/em&gt;, and grounding checkers used in production RAG systems flag it the same way they flag a false claim, because from the sources alone the two look identical. I ran into one in my own evaluation, on a question about a paper I co-wrote.&lt;/p&gt;

&lt;p&gt;One of the 18 test questions in my RAG evaluation asks what cognitive biases one of my own papers addresses. The paper, from 2005, is about countering bias in search, but it never names a specific bias. Across three generations, the answer that said "the paper doesn't name specific biases" scored 0.00 on answer relevancy. The answer that confidently said "confirmation bias" scored 0.58. Faithfulness caught the unsupported claim and scored that answer 0.17. Then I found that the reference answer in my own golden set, which I had reviewed and marked verified, also said "confirmation bias." As the paper's co-author, I can say the claim is true: confirmation bias was one of the main problems the mechanism was built to address. It just isn't in the paper. This post is about the gap between a claim that is true and a claim the source supports: how current RAG systems and research handle it, a fifth approach I propose, and the case that prompted it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key points&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A claim can be true and still unsupported by the sources an answer cites. A source-grounded check is right to flag it, but it can't tell it apart from a false claim.&lt;/li&gt;
&lt;li&gt;Research already crosses source support with truth for every claim (RAGChecker, FRANQ). I'd add two refinements: keep claims that can't be checked either way in view, and split true-but-unsupported claims into &lt;em&gt;derived&lt;/em&gt; and &lt;em&gt;recalled&lt;/em&gt; (Figure 1).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grounded derivation:&lt;/strong&gt; let an answer go beyond its sources only by showing its steps from cited premises, with every outside premise named and drawn from a source declared in advance, and check every step (Section 3).&lt;/li&gt;
&lt;li&gt;In my own evaluation, my answer key made the same unsupported claim as the model. The source-grounded judge caught what my review missed (Section 4).&lt;/li&gt;
&lt;li&gt;RAGAS answer relevancy scored the honest answer, "the paper doesn't name specific biases," at 0.00, and the confident unsupported one at 0.58.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu3ko6hzaldl7bijjv662.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu3ko6hzaldl7bijjv662.png" alt="Figure 1. Source support crossed with truth, with true-but-unsupported claims split into derived and recalled" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1. Every claim in a RAG answer has two properties: whether the source supports it, and whether it can be verified as true, false, or neither. The supported/unsupported × true/false grid follows RAGChecker (2024) and FRANQ (2026); keeping the unresolved column in view and splitting derived from recalled are the refinements proposed in Section 3. The dots mark the claim at the center of this post: as "the authors intended to target confirmation bias," it is unresolved from the documents; as "the method is best read as addressing confirmation bias," it is derived, given one named outside premise.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Background: when a hallucination is true
&lt;/h2&gt;

&lt;p&gt;A RAG system has two goals that usually agree:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Correctness:&lt;/strong&gt; is the answer true?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verifiability:&lt;/strong&gt; can a reader check it against the sources it cites?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Retrieval exists mainly for the second: every claim can be traced to a document. Evaluation follows the same split. &lt;em&gt;Faithfulness&lt;/em&gt; (also called &lt;em&gt;groundedness&lt;/em&gt;) asks whether each claim is supported by the retrieved text. &lt;em&gt;Correctness&lt;/em&gt; or &lt;em&gt;factuality&lt;/em&gt; asks whether the claim is true, usually by comparing it with a reference answer.&lt;/p&gt;

&lt;p&gt;The two can come apart. Maynez et al. studied this in abstractive summarization in 2020 and separated &lt;em&gt;faithfulness&lt;/em&gt; to the source document from &lt;em&gt;factuality&lt;/em&gt; in the world. They defined a &lt;strong&gt;factual hallucination&lt;/strong&gt; as content that is not in the source but is still correct. It was the minority case: over 90% of the content their annotators found added beyond the source was wrong. That is exactly what makes the true cases hard. A checker that sees only the sources finds a claim it can't support, and it has no way to tell the rare true claim from the common false one. Most production systems resolve the conflict in favor of verifiability: if the sources don't support a claim, it counts as a failure, true or not. My evaluation did the same, and it was right to. What I didn't expect was that I had written the same unsupported claim into my own answer key.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. How the field handles this
&lt;/h2&gt;

&lt;p&gt;There is no general solution. Current systems and research take four approaches, each with a cost. Section 3 proposes a fifth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strict grounding: unsupported counts as wrong.&lt;/strong&gt; This is the default for enterprise and regulated uses. The generator is told to answer only from the provided context, and a grounding checker scores each claim against the sources. Google's check-grounding API says that "every claim in the answer candidate must be supported by one or more of the given facts," and Microsoft's groundedness detection is likewise defined relative to the source material. My faithfulness metric works the same way. The cost: a true claim and a false one get the same verdict, as the confirmation-bias answer did in my evaluation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Measure faithfulness and correctness separately.&lt;/strong&gt; Evaluation frameworks, RAGAS included, have both a source-based metric and a reference-based one. Together they can separate the four cases: true and supported, true and unsupported, false and supported (the source itself is wrong), false and unsupported. RAGChecker (NeurIPS 2024) reports exactly this split for every claim in an answer: claims that are supported and correct, supported but incorrect ("noise sensitivity"), unsupported but correct ("self-knowledge"), and neither ("hallucination"). FRANQ (Findings of ACL 2026) builds its scoring on the same grid (the first two columns of Figure 1), and starts from the same complaint as this post: correct statements labeled as hallucinations because the retrieved text doesn't support them. The weak point is the reference. A correctness metric is only as good as the answer key, and mine contained the same unsupported claim as the answer it would have graded, so it would have scored the confirmation-bias answer as correct.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Model the conflict between memory and source.&lt;/strong&gt; Research on &lt;em&gt;knowledge conflicts&lt;/em&gt; shows the problem cuts both ways. ClashEval (2024) found that models adopt incorrect retrieved content over 60% of the time, overriding a correct prior: trusting the source too much. My case is the opposite, trusting memory too much. Methods such as FaithfulRAG (ACL 2025) model conflicts at the level of individual facts, so a system can notice when what it knows and what it retrieved disagree, instead of silently picking one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Allow general knowledge, but label it.&lt;/strong&gt; Every sentence either carries a citation or is marked as coming from the model's general knowledge, so the reader can see which parts are checkable. Self-RAG (ICLR 2024) builds a version of this into the model, which predicts whether each part of its output is supported by the retrieved passage. For the question in my evaluation, a labeled answer would have read: &lt;em&gt;"The paper doesn't name specific biases [cited]. Based on its method, it is best read as addressing biases such as confirmation bias (not stated in the source)."&lt;/em&gt; That answer is honest, useful and checkable, and it is not what any of the answers my system generated said.&lt;/p&gt;

&lt;p&gt;Which approach is right depends on what an unsupported claim costs. In a research assistant, a labeled inference is helpful. Anywhere decisions have to be audited, such as claims review, compliance or legal work, a flag the system can't trace to a document can't be relied on, even when it happens to be correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. A fifth approach: grounded derivation
&lt;/h2&gt;

&lt;p&gt;The four approaches above treat support almost as a lookup. The RAGAS faithfulness judge accepts a statement if it "can be directly inferred based on the context": one step of inference, never shown or checked.&lt;/p&gt;

&lt;p&gt;I want to propose a different standard. Language models are good at reasoning. So instead of asking only whether a claim is stated in the sources, ask whether it can be &lt;em&gt;derived&lt;/em&gt; from them, and require the answer to show how. Every claim in an answer then falls into one of three kinds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stated:&lt;/strong&gt; supported directly by a cited passage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Derived:&lt;/strong&gt; reached by explicit reasoning steps whose premises are cited passages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;General knowledge:&lt;/strong&gt; a premise or claim that is not in the sources, labeled as such.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An evaluator then checks three things: that each citation supports its premise, that each step follows from the ones before it, and which premises came from outside the sources. "Is this conclusion supported?" is hard to judge when the conclusion isn't in the text. "Does step 3 follow from steps 1 and 2?" is a small, local question, like checking a proof line by line.&lt;/p&gt;

&lt;p&gt;The running example is the claim from the summary: that my 2005 paper addresses confirmation bias. The paper describes an anti-bias mechanism, ABM, for a search system used by intelligence analysts, based on Richards Heuer's Analysis of Competing Hypotheses (details in Section 4.1). It is worth being precise about the claim first, because it can mean four different things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The method &lt;strong&gt;could reduce&lt;/strong&gt; confirmation bias.&lt;/li&gt;
&lt;li&gt;The method &lt;strong&gt;is best read as addressing&lt;/strong&gt; confirmation bias.&lt;/li&gt;
&lt;li&gt;The authors &lt;strong&gt;intended&lt;/strong&gt; it to counter confirmation bias.&lt;/li&gt;
&lt;li&gt;The paper &lt;strong&gt;names&lt;/strong&gt; confirmation bias.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first two can be argued from the paper plus general knowledge about Heuer's method, by anyone who reads it; the derivation below shows how. The third is true, but its only support is my testimony as an author. The fourth is false. The answer my system generated asserted the fourth, which is why faithfulness was right to reject it. My answer key asserted something between the third and the fourth.&lt;/p&gt;

&lt;p&gt;Here is version 2 as a grounded derivation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ABM is inspired by Heuer's Analysis of Competing Hypotheses. &lt;em&gt;(stated in the paper)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;ABM retrieves results for competing versions of the analyst's query and mixes them into the analyst's results. &lt;em&gt;(stated in the paper)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Analysis of Competing Hypotheses is designed to counter the tendency to look only for evidence that confirms a hypothesis, that is, confirmation bias. &lt;em&gt;(general knowledge: from Heuer's book, not from this paper)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Therefore ABM is best read as addressing confirmation bias. &lt;em&gt;(derived from 1–3, as an inference to the best explanation)&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The derivation does not make the claim supported. It needs premise 3, which the paper doesn't contain. What it does is replace one vague verdict ("unsupported") with a precise one: the conclusion follows, given a single named outside premise that a reader can check in Heuer's book. Had my corpus included Heuer, the whole claim would have been derived from sources. This is also what my verification of the answer key should have looked like. Note what the derivation does not reach: it supports version 2 of the claim, not version 3. No derivation from the paper can establish what its authors intended.&lt;/p&gt;

&lt;p&gt;Three refinements matter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deduction is not the same as inference.&lt;/strong&gt; In a deduction, true premises make the conclusion certain: "therefore." In an inference to the best explanation, the conclusion is only the most likely reading: "most likely." Claims about purpose or intent, like this one, are almost always the second kind. A derived claim should say which kind it is, so a reasonable inference doesn't carry the authority of a proof.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The reasoning has to be checked, not trusted.&lt;/strong&gt; Language models can write chains that look rigorous and hide a leap or an unstated assumption, and an LLM judge tends to accept a chain whose conclusion it already believes. Each step needs a strict check, and every added step adds risk. The longer the chain, the more cautious the label should be.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outside premises can't be invented to fit.&lt;/strong&gt; Any unsupported claim H can be "derived" from a stated premise P by adding the outside premise "P implies H." That premise is doing all the work, and accepting it would make every hallucination derivable. So an outside premise counts only if it is a general rule or definition that doesn't mention the specific document or claim, and if it comes from a source declared in advance: a named textbook or reference work, a statute, a standard definition, or a program that can check it. Step 3 above passes: it is a general statement about Heuer's method, checkable in Heuer's book.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it works best: mathematics and law.&lt;/strong&gt; A source doesn't need to say 2 + 2 = 4; an answer can derive it from the axioms of arithmetic. Axioms are outside premises of an &lt;em&gt;established&lt;/em&gt; kind: definitions, proven theorems and statute text can be used freely, but should still be named. &lt;em&gt;Contestable&lt;/em&gt; premises, like step 3 above, must be labeled. In mathematics a program, such as a computer algebra system or the proof assistant Lean, can check each step, so the check itself can't hallucinate. Law teaches the other lesson. Applying a statute to facts reads like a proof, but interpretation, precedent and jurisdiction make most legal conclusions "most likely," not "therefore." Insurance claims review is similar: a coverage decision applies policy wording to the facts in a claim file.&lt;/p&gt;

&lt;p&gt;Parts of this idea exist already. EntailmentBank (2021) explains answers as entailment trees built up from premises. ProofWriter (2021) finds the missing fact that would make a conclusion provable, in a controlled logical setting. PARC (ICML 2025) links each step of a math solution to the earlier steps it depends on. AttrScore (2023) labels a claim "extrapolatory" when the source lacks enough information to support it, without separating derivable claims from unsupported ones. MiniCheck trains grounding checkers to recognize a fact assembled from several sentences. RLSeek (ACL 2026) makes a hallucination detector quote the source at each step of its reasoning. RAGChecker counts correct claims that no retrieved chunk supports, as "self-knowledge." Work on abductive RAG generates and validates premises that the evidence is missing. What I have not found in published RAG evaluation is the combination: answers that label every claim as stated, derived or general knowledge, with each derivation shown and each outside premise named, and an evaluation that checks every part. I plan to test it on my own corpus (Section 9).&lt;/p&gt;

&lt;p&gt;Figure 1 puts the field's grid and this proposal together, with two refinements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep unresolved claims in view.&lt;/strong&gt; FRANQ's annotation already labels some claims "unverifiable," then drops them from evaluation. Reporting them, along with how much of an answer could be checked at all, stops "can't be checked" from being counted as either true or false.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Derived" is a kind of true-but-unsupported claim, not the whole category.&lt;/strong&gt; That box also holds plain recall, as when an answer adds a fact from the model's memory. Grounded derivation is what tells the two apart.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This post's title follows Maynez's usage: a claim the source doesn't support is a hallucination, even when it is true. What the grid adds is a way to say which kind.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The case: a question about my own paper
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4.1 The question and the paper
&lt;/h3&gt;

&lt;p&gt;My test system is a small RAG service over 15 of my research papers, evaluated with RAGAS 0.2.15. Generator: &lt;code&gt;gpt-oss-20b&lt;/code&gt; on Groq. Judge: Gemini 3.5 Flash Lite. Retrieval: top 8 chunks. The setup is described in &lt;a href="https://dev.to/hualiphd/i-found-the-optimal-top-k-for-my-rag-system-then-i-ran-it-again-3oi3"&gt;part 1&lt;/a&gt; and &lt;a href="https://dev.to/hualiphd/judge-noise-or-answer-noise-what-really-moves-rag-evaluation-scores-hfl"&gt;part 2&lt;/a&gt; of this series.&lt;/p&gt;

&lt;p&gt;Question &lt;code&gt;cont-05&lt;/code&gt; reads:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What cognitive biases affect information retrieval according to this research?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The source is a two-page paper Rafael Alonso and I published at the 2005 International Conference on Intelligence Analysis, &lt;em&gt;Combating Cognitive Biases in Information Retrieval&lt;/em&gt;. It describes an anti-bias mechanism for a search system used by intelligence analysts. The idea comes from Richards Heuer's Analysis of Competing Hypotheses. The system automatically generates alternative versions of the analyst's query, for example by swapping concepts for WordNet antonyms, coordinate terms or hypernyms. It runs those alternative queries too, and mixes a few of their best results into what the analyst sees. The paper calls them "anti-bias" results.&lt;/p&gt;

&lt;p&gt;What the paper does not do is name a bias. It says that queries "inherit cognitive biases" from the models that produce them. It never says "confirmation bias," "anchoring" or any other specific bias. I checked the full text for this post.&lt;/p&gt;

&lt;p&gt;So the honest answer to the question is roughly: &lt;em&gt;the paper treats cognitive bias in general and doesn't name specific biases; its contribution is a mechanism for countering them.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 Three answers, three verdicts
&lt;/h3&gt;

&lt;p&gt;Part 2 generated three sets of answers under identical settings. Retrieval returned the same 8 chunks every time; only the generated text changed. Here is &lt;code&gt;cont-05&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Generation&lt;/th&gt;
&lt;th&gt;What the answer said&lt;/th&gt;
&lt;th&gt;Faithfulness&lt;/th&gt;
&lt;th&gt;Answer relevancy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;The paper addresses cognitive bias in general; the excerpts don't list specific biases&lt;/td&gt;
&lt;td&gt;0.80 (8 of 10 claims supported)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.00&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;"Confirmation bias is explicitly addressed"; defines it; says the method "explicitly guards against confirmation bias"&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;0.17&lt;/strong&gt; (2 of 12 claims supported)&lt;/td&gt;
&lt;td&gt;0.58&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;The paper speaks of biases "in general terms"; the excerpts "do not list specific bias names"&lt;/td&gt;
&lt;td&gt;0.73 (11 of 15)&lt;/td&gt;
&lt;td&gt;0.87&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Faithfulness worked.&lt;/strong&gt; It splits the answer into claims and checks each one against the retrieved chunks. On generation 2 the judge rejected every confirmation-bias claim, with reasons like "The term confirmation bias does not appear in the available text excerpts." The two claims it accepted were the parts copied from the paper: the method creates alternative maps and selects anti-bias results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Answer relevancy punished the honest answer.&lt;/strong&gt; RAGAS relevancy asks the judge to write questions that the answer seems to respond to, then compares them with the real question by embedding similarity. It also asks the judge whether the answer is "noncommittal," and in RAGAS 0.2.15 a single noncommittal flag among the generated questions sets the score to zero (&lt;code&gt;score = cosine_sim.mean() * int(not committal)&lt;/code&gt;). Generation 1 said the excerpts don't name specific biases. The judge flagged that as noncommittal in two of three samples, so the answer scored 0. It scored 0 again in both re-judging passes.&lt;/p&gt;

&lt;p&gt;Generation 3 said almost the same thing and scored 0.87. My best guess is framing: generation 3 opened with a confident sentence about which papers discuss bias and put the "no specific names" point in the middle, while generation 1 led with the hedge.&lt;/p&gt;

&lt;p&gt;Read alone, relevancy would rank the confident wrong answer above the honest one. Faithfulness ranks them correctly. Neither metric is enough by itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.3 My answer key had the same bias
&lt;/h3&gt;

&lt;p&gt;Here is the reference answer for &lt;code&gt;cont-05&lt;/code&gt; in my golden set, marked &lt;code&gt;"verified": true&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The 2005 work examines how analyst cognitive biases &lt;strong&gt;such as confirmation bias&lt;/strong&gt; distort information seeking and retrieval, and proposes system-side mechanisms to counteract them during search.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The generator and I made the same claim, and only one of us was being checked against the source. When I verified the reference, I checked that it described the paper correctly. It did. I didn't check that each phrase appeared in the paper, and one didn't.&lt;/p&gt;

&lt;p&gt;The reference feeds context recall, which asks the judge whether each reference statement is supported by the retrieved chunks. This reference was a single sentence, so recall on &lt;code&gt;cont-05&lt;/code&gt; was one yes/no call. In part 2's three re-judging passes, on identical inputs, the judge said no, no, then yes. The "yes" is worth quoting:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"...though confirmation bias specifically is not named in the text, the overall premise of addressing cognitive biases in information retrieval is present."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the judge accepting a plausible inference because the rest of the sentence fit, the same move I made when I reviewed the reference.&lt;/p&gt;

&lt;p&gt;I found the problem while splitting single-sentence references into several checkable claims, a fix from part 2. To split a reference into claims, you have to find each claim's sentence in the source. "Such as confirmation bias" had no sentence. The rewritten reference, now in the repo's golden set, has three claims, each checked against the paper's text:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The 2005 work presents an anti-bias mechanism (ABM) for combating cognitive biases in information retrieval. ABM automatically generates alternative, competing queries alongside the user's original query. A small set of the best results from the competing queries is mixed in with the original results.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4.4 True, but not in the source
&lt;/h3&gt;

&lt;p&gt;The claim isn't a mistake about the work. When Rafael and I designed the anti-bias mechanism, confirmation bias was one of the main biases we had in mind. Intelligence analysts are prone to it: once a hypothesis forms, they look for and weigh evidence that supports it, and it is notoriously hard to counter. Section 3 shows how the mechanism connects to it. The paper doesn't say any of this because it was a two-page conference paper. We described the mechanism and left out the discussion of which biases it targeted.&lt;/p&gt;

&lt;p&gt;In the terms of Section 3, generation 2 claimed version 4, and my answer key something between versions 3 and 4. So the generator in generation 2 was, in a sense, right about the work. It was still wrong about the source, and in a RAG system the source is what counts. The system's promise is "here is what these documents say," and the documents don't say this. A reader who followed the citation would not find it. The generator had no access to my memory of 2005; it filled the gap with the most plausible bias.&lt;/p&gt;

&lt;p&gt;It slipped past me because it was true, familiar, and consistent with the rest of the sentence. When I verified the reference, I checked it against what I knew about the paper, which includes things the paper doesn't say. The faithfulness judge checked each claim against the text, and the text was all it had. For a source-grounded system, that is the right standard, even when the author knows more.&lt;/p&gt;

&lt;p&gt;There is an irony here. The 2005 paper argues that a search system inherits the biases of the person who writes the query. My evaluation inherited my knowledge, and my blind spot, through the answer key.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Beyond faithfulness: a preview of part 4
&lt;/h2&gt;

&lt;p&gt;Grounded derivation also exposes a gap in the RAGAS metrics I use: they ask whether an answer matches its sources and its question, not whether it is true. Suppose a source has a typo: 2 + 2 = 5. An answer that copies it scores perfectly on faithfulness and is wrong. An answer that says 4 is scored as unsupported and is right.&lt;/p&gt;

&lt;p&gt;When a source is wrong, the best answer is neither faithful nor silently corrected. It is both: &lt;em&gt;"The source states 2 + 2 = 5; this appears to be an error: 2 + 2 = 4."&lt;/em&gt; Scoring that answer fairly is harder than it looks. "The source states 2 + 2 = 5" is true, while "2 + 2 = 5" is false, so an evaluator that strips "the source states" penalizes exactly the answer it should reward. That is where part 4 will start.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. A correction to part 2
&lt;/h2&gt;

&lt;p&gt;Part 2 said "confirmation bias" "isn't in the corpus." It is: a 2013 paper in the same corpus, about a serious game that teaches players to recognize their own biases, names it. The accurate statement is narrower: it isn't in the 2005 paper, and every judge explanation says it wasn't in the excerpts retrieved for this question. That exposes an ambiguity, too. "According to this research" could mean the 2005 paper or my work as a whole, and under the second reading "confirmation bias" is a supported answer that retrieval missed. My harness doesn't log retrieved document IDs yet, so the judge explanations are my only evidence about which papers were retrieved.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. What I do now
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Check references against the source, one claim at a time.&lt;/strong&gt; For each claim in a reference answer, find the sentence that supports it. If you can't point to one, the claim came from you, not the document, even if it is true. Reading a reference and nodding along is not verification. Domain experts and authors are the most exposed, because they know more than the documents say.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If the knowledge matters, put it in the corpus.&lt;/strong&gt; If users should learn what a paper was designed to address, that has to be written down somewhere the system can retrieve, not supplied by the generator.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask for labeled inferences instead of forbidding them.&lt;/strong&gt; If the generator may use general knowledge, have it mark which sentences are not from the sources. A labeled inference can be judged on its own terms; an unlabeled one can only be scored as unsupported.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read faithfulness and relevancy together.&lt;/strong&gt; High relevancy with low faithfulness is a confident answer the sources don't support. Low relevancy with high faithfulness may be an honest abstention, which RAGAS relevancy scores as zero.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope questions explicitly.&lt;/strong&gt; "This research" should say which paper, or say "across the corpus." An ambiguous question makes the right answer depend on the reader.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log retrieved document IDs.&lt;/strong&gt; Without them, "was the supporting paper retrieved?" has to be answered by reading judge explanations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write a competing reference for claims you're sure of.&lt;/strong&gt; This is the 2005 paper's idea applied to evaluation: for each claim you're confident about, ask what the source would need to say for it to be false, and check whether it says that. That was how "such as confirmation bias" should have been caught.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. Limits
&lt;/h2&gt;

&lt;p&gt;This is one question out of 18, so treat it as a case study, not a measurement. The scores come from single runs except where re-judging is mentioned. The judge's explanations are themselves LLM output and can be wrong. They are consistent here, and they match the paper's text. That confirmation bias was a target of the 2005 mechanism is my account as an author, not something the paper states, which is the point of this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Next
&lt;/h2&gt;

&lt;p&gt;The other 12 rewritten multi-claim references go through the same check against the papers before I merge them. Then I'll re-judge the saved results against them to see whether recall becomes less noisy. I'll also add document-ID logging, so the next post can say which papers were retrieved instead of inferring it.&lt;/p&gt;

&lt;p&gt;Then I want to test grounded derivation. As the author of every paper in the corpus, I can propose claims that are true but unstated, but my knowledge can't be the answer key, for the reason this post is about. So each claim would be labeled twice: by me, and by a reader who didn't write the papers and has only the papers and standard references. Where the reader agrees with me, the claim is a genuine derivation; where only I know it, it is author intent, which an evaluator shouldn't reward. Then the question is whether a derivation-checking evaluator can tell those cases apart, including on deliberately flawed derivations designed to fool it.&lt;/p&gt;

&lt;p&gt;Part 4 will look at how evaluators score an answer that flags and corrects a source error.&lt;/p&gt;

&lt;p&gt;The harness, the golden set and every raw judge output are in the repo: &lt;a href="https://github.com/huali10044/research-rag" rel="noopener noreferrer"&gt;github.com/huali10044/research-rag&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Alonso, R., &amp;amp; Li, H. (2005). Combating Cognitive Biases in Information Retrieval. &lt;em&gt;Proceedings of the International Conference on Intelligence Analysis.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Heuer, R. J. (1999). &lt;em&gt;Psychology of Intelligence Analysis.&lt;/em&gt; Center for the Study of Intelligence, Central Intelligence Agency.&lt;/li&gt;
&lt;li&gt;Maynez, J., Narayan, S., Bohnet, B., &amp;amp; McDonald, R. (2020). &lt;a href="https://arxiv.org/abs/2005.00661" rel="noopener noreferrer"&gt;On Faithfulness and Factuality in Abstractive Summarization&lt;/a&gt;. &lt;em&gt;ACL 2020.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Yue, X., et al. (2023). &lt;a href="https://arxiv.org/abs/2305.06311" rel="noopener noreferrer"&gt;Automatic Evaluation of Attribution by Large Language Models&lt;/a&gt; (AttrScore). &lt;em&gt;Findings of EMNLP 2023.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Dalvi, B., et al. (2021). &lt;a href="https://arxiv.org/abs/2104.08661" rel="noopener noreferrer"&gt;Explaining Answers with Entailment Trees&lt;/a&gt;. &lt;em&gt;EMNLP 2021.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Tang, L., Laban, P., &amp;amp; Durrett, G. (2024). &lt;a href="https://aclanthology.org/2024.emnlp-main.499" rel="noopener noreferrer"&gt;MiniCheck: Efficient Fact-Checking of LLMs on Grounding Documents&lt;/a&gt;. &lt;em&gt;EMNLP 2024.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Ru, D., et al. (2024). &lt;a href="https://proceedings.neurips.cc/paper_files/paper/2024/file/27245589131d17368cccdfa990cbf16e-Paper-Datasets_and_Benchmarks_Track.pdf" rel="noopener noreferrer"&gt;RAGChecker: A Fine-grained Framework for Diagnosing Retrieval-Augmented Generation&lt;/a&gt;. &lt;em&gt;NeurIPS 2024 Datasets and Benchmarks.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Huang, Z., et al. (2026). &lt;a href="https://aclanthology.org/2026.acl-long.1492/" rel="noopener noreferrer"&gt;RLSeek: Evidence-Grounded Reasoning for RAG Hallucination Detection&lt;/a&gt;. &lt;em&gt;ACL 2026.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Lin, S. (2025). &lt;a href="https://arxiv.org/abs/2511.04020" rel="noopener noreferrer"&gt;Abductive Inference in Retrieval-Augmented Language Models: Generating and Validating Missing Premises&lt;/a&gt;. arXiv preprint.&lt;/li&gt;
&lt;li&gt;Fadeeva, E., et al. (2026). &lt;a href="https://arxiv.org/abs/2505.21072" rel="noopener noreferrer"&gt;Faithfulness-Aware Uncertainty Quantification for Fact-Checking the Output of Retrieval Augmented Generation&lt;/a&gt; (FRANQ). &lt;em&gt;Findings of ACL 2026.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Mukherjee, S., et al. (2025). &lt;a href="https://proceedings.mlr.press/v267/mukherjee25a.html" rel="noopener noreferrer"&gt;Premise-Augmented Reasoning Chains Improve Error Identification in Math Reasoning with LLMs&lt;/a&gt; (PARC). &lt;em&gt;ICML 2025.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Tafjord, O., Dalvi, B., &amp;amp; Clark, P. (2021). &lt;a href="https://aclanthology.org/2021.findings-acl.317/" rel="noopener noreferrer"&gt;ProofWriter: Generating Implications, Proofs, and Abductive Statements over Natural Language&lt;/a&gt;. &lt;em&gt;Findings of ACL 2021.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Wu, K., Wu, E., &amp;amp; Zou, J. (2024). &lt;a href="https://arxiv.org/abs/2404.10198" rel="noopener noreferrer"&gt;ClashEval: Quantifying the tug-of-war between an LLM's internal prior and external evidence&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aclanthology.org/2025.acl-long.1062" rel="noopener noreferrer"&gt;FaithfulRAG: Fact-Level Conflict Modeling for Context-Faithful Retrieval-Augmented Generation&lt;/a&gt;. &lt;em&gt;ACL 2025.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Asai, A., Wu, Z., Wang, Y., Sil, A., &amp;amp; Hajishirzi, H. (2024). &lt;a href="https://arxiv.org/abs/2310.11511" rel="noopener noreferrer"&gt;Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection&lt;/a&gt;. &lt;em&gt;ICLR 2024.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Google Cloud. &lt;a href="https://docs.cloud.google.com/generative-ai-app-builder/docs/check-grounding" rel="noopener noreferrer"&gt;Check grounding with RAG&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Microsoft. &lt;a href="https://learn.microsoft.com/en-us/azure/foundry/openai/concepts/content-filter-groundedness" rel="noopener noreferrer"&gt;Groundedness detection&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;RAGAS 0.2.15, &lt;a href="https://github.com/explodinggradients/ragas/blob/v0.2.15/src/ragas/metrics/_answer_relevance.py" rel="noopener noreferrer"&gt;&lt;code&gt;_answer_relevance.py&lt;/code&gt;&lt;/a&gt; (noncommittal scoring rule).&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rag</category>
      <category>llm</category>
      <category>evaluation</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Judge noise or answer noise? What really moves RAG evaluation scores</title>
      <dc:creator>Hua Li</dc:creator>
      <pubDate>Mon, 19 Oct 2026 04:02:06 +0000</pubDate>
      <link>https://dev.to/hualiphd/judge-noise-or-answer-noise-what-really-moves-rag-evaluation-scores-hfl</link>
      <guid>https://dev.to/hualiphd/judge-noise-or-answer-noise-what-really-moves-rag-evaluation-scores-hfl</guid>
      <description>&lt;p&gt;&lt;strong&gt;Summary.&lt;/strong&gt; RAG evaluation scores change from run to run even when nothing in the system changes. I measured where that variation comes from in my own system: from the LLM judge grading the same answers differently, or from the generator writing different answers. For faithfulness, about 85% of the run-to-run variance came from the answers. For answer relevancy, nearly all of it did. Context recall and context precision never read the generated answer, so with deterministic retrieval all of their variance came from the judge, even with the judge set to its most consistent setting. From these measurements, a difference between two settings, each run once on my 18 questions, needs to exceed about 0.15 (faithfulness), 0.08 (relevancy), 0.09 (recall) or 0.10 (precision) to mean anything. Applying that bar to the top-k sweep in &lt;a href="https://dev.to/hualiphd/i-found-the-optimal-top-k-for-my-rag-system-then-i-ran-it-again-3oi3"&gt;my first post&lt;/a&gt; confirms that the sweep could not rank the k values, and that the "optimal k=8" came from uneven question coverage and single runs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ih9x4ie59m9ahom2nsg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ih9x4ie59m9ahom2nsg.png" alt="Figure 1. The top-k sweep from the first post, re-read with a measured noise band" width="800" height="480"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1. Gray dashed line: the recall curve published in the first post (one run per k, unequal question sets). Blue dots: every run of that sweep, scored on the 9 questions all seven runs scored. Shaded band: where a single run's 9-question recall lands from judge noise alone (mean ± 0.09).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key findings
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The judge does not always give the same verdict twice, even when set to be as consistent as possible.&lt;/strong&gt; Grading the same answers three times moved the 18-question means by 0.003 (relevancy) to 0.085 (precision).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For faithfulness and relevancy, the answers matter more than the judge.&lt;/strong&gt; Run-mean standard deviation rose from 0.021 to 0.054 for faithfulness and from 0.002 to 0.028 for relevancy when the answers were regenerated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recall and precision are pure judge noise in this setup.&lt;/strong&gt; RAGAS computes them from the question, the retrieved chunks and the reference answer. Regenerating answers cannot change them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Noise bars for comparing two single runs:&lt;/strong&gt; about 0.15 faithfulness, 0.08 relevancy, 0.09 recall, 0.10 precision (18 questions; about 40% wider on 9).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The first post's k=8 peak does not survive.&lt;/strong&gt; On the 9 questions every run scored, all seven sweep runs fall inside the judge-noise band (Figure 1). The first post's claim that changing the judge model moves scores more than changing k gets stronger.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replicate the right thing.&lt;/strong&gt; For recall and precision, re-judge saved results. For faithfulness and relevancy, regenerate answers. Re-judging alone would make faithfulness look more than twice as stable as it is.
## 1. Background&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the first post I swept top-k over a small RAG system, found a clean winner at k=8, then ran k=8 twice more and watched the winner dissolve: same configuration, recall anywhere from 0.61 to 0.83.&lt;/p&gt;

&lt;p&gt;A commenter, Ahmet Özel, asked the obvious next question: how much of that spread is the judge, and how much is the generator writing different answers? The two need different fixes. If the judge is noisy, you grade more times. If the answers are noisy, you generate more times. I had been doing neither, and I couldn't tell which one I needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Setup
&lt;/h2&gt;

&lt;p&gt;Same system as before: 15 research papers, 18 judged questions, k=8. The generator is &lt;code&gt;gpt-oss-20b&lt;/code&gt; on Groq. The judge is Gemini 3.5 Flash Lite, through RAGAS 0.2.15 with four metrics: faithfulness, answer relevancy, context precision and context recall.&lt;/p&gt;

&lt;p&gt;One setting matters for what follows. An LLM's &lt;em&gt;temperature&lt;/em&gt; controls how much randomness goes into choosing each word: higher values give more varied output, and 0 tells the model to always pick its most likely next word, which in principle makes the same input produce the same output. My harness sets the judge's temperature to 0, the usual advice for LLM judges. The generator runs at the provider's default temperature, so its answers are expected to vary from run to run.&lt;/p&gt;

&lt;p&gt;Two experiments:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Judge only.&lt;/strong&gt; Generate one set of answers, save them with their retrieved chunks, and have the judge score the same saved answers three times. Nothing is regenerated or re-retrieved. The prompts sent to the judge had identical hashes in all three passes, so any difference is the judge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generator plus judge.&lt;/strong&gt; Generate three separate sets of answers under identical settings and score each once.
To make the first experiment possible, the harness had to learn to replay: save every answer and its retrieved chunks, then re-run only the judge. It now also records why any score is missing (rate limit, timeout, unparseable judge output and so on) and reports each mean with its coverage, like &lt;code&gt;0.833 (9/18)&lt;/code&gt;. That second change is how I found out that the 0.833 in my first post covered only half the questions.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  3. Results
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1 The judge alone
&lt;/h3&gt;

&lt;p&gt;Same answers, same chunks, same prompts, three passes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Pass 1&lt;/th&gt;
&lt;th&gt;Pass 2&lt;/th&gt;
&lt;th&gt;Pass 3&lt;/th&gt;
&lt;th&gt;Range&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Faithfulness&lt;/td&gt;
&lt;td&gt;0.653&lt;/td&gt;
&lt;td&gt;0.611&lt;/td&gt;
&lt;td&gt;0.628&lt;/td&gt;
&lt;td&gt;0.042&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Answer relevancy&lt;/td&gt;
&lt;td&gt;0.821&lt;/td&gt;
&lt;td&gt;0.824&lt;/td&gt;
&lt;td&gt;0.824&lt;/td&gt;
&lt;td&gt;0.003&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context precision&lt;/td&gt;
&lt;td&gt;0.601&lt;/td&gt;
&lt;td&gt;0.686&lt;/td&gt;
&lt;td&gt;0.632&lt;/td&gt;
&lt;td&gt;0.085&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context recall&lt;/td&gt;
&lt;td&gt;0.694&lt;/td&gt;
&lt;td&gt;0.648&lt;/td&gt;
&lt;td&gt;0.667&lt;/td&gt;
&lt;td&gt;0.046&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Setting the judge's temperature to 0 did not make it repeat itself. Each metric varies for a reason specific to how it's built.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Faithfulness&lt;/strong&gt; splits the answer into claims, then checks each claim against the chunks. The judge split identical answers into different numbers of claims: one answer came out as 5, 10 and 11 claims in the three passes. The score is supported claims over total claims, so the denominator moves. Faithfulness changed on 11 of 18 questions, and those were exactly the 11 where the claim count changed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Precision and recall&lt;/strong&gt; are built from yes/no verdicts. 5 of 148 chunk verdicts flipped between passes, and 3 of 22 reference-statement verdicts. That sounds small until you notice that 14 of my 18 reference answers were a single sentence. For those questions, recall is one yes/no call, so a single flip moves that question from 1 to 0. One question went 1, 0, 0 across three identical passes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Relevancy&lt;/strong&gt; barely moved. The judge writes questions the answer seems to address, and an embedding model compares them with the real question. The embedding step smooths out the judge's wording.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 Adding new answers
&lt;/h3&gt;

&lt;p&gt;Retrieval returned exactly the same 8 chunks for every question in all three generations, so the only thing that changed was the generated text, and it changed a lot: most answers to content questions shared less than a fifth of their wording with the previous generation.&lt;/p&gt;

&lt;p&gt;Spread of the 18-question mean, as a standard deviation across runs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Judge only&lt;/th&gt;
&lt;th&gt;New answers, each judged once&lt;/th&gt;
&lt;th&gt;Share from the answers&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Faithfulness&lt;/td&gt;
&lt;td&gt;0.021&lt;/td&gt;
&lt;td&gt;0.054&lt;/td&gt;
&lt;td&gt;about 85%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Answer relevancy&lt;/td&gt;
&lt;td&gt;0.002&lt;/td&gt;
&lt;td&gt;0.028&lt;/td&gt;
&lt;td&gt;nearly all&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context recall&lt;/td&gt;
&lt;td&gt;0.032&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context precision&lt;/td&gt;
&lt;td&gt;0.035&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The blanks are the most useful finding of the whole exercise. &lt;strong&gt;In RAGAS, context recall and context precision never read the generated answer.&lt;/strong&gt; They compare the retrieved chunks with the question and the reference answer. My retrieval is deterministic, so regenerating answers cannot change those two scores, and all of their run-to-run noise is the judge.&lt;/p&gt;

&lt;p&gt;I would have guessed the opposite split before running this. I'd assumed the judge was the main problem everywhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3 How big a difference needs to be
&lt;/h3&gt;

&lt;p&gt;Compare two settings, say k=5 against k=8, each run once on these 18 questions. Each run's mean has its own noise, the difference between two runs has about 1.4 times that, and the difference should be about twice its own noise before you believe it:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Smallest difference worth reporting&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Faithfulness&lt;/td&gt;
&lt;td&gt;about 0.15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Answer relevancy&lt;/td&gt;
&lt;td&gt;about 0.08&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context recall&lt;/td&gt;
&lt;td&gt;about 0.09&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context precision&lt;/td&gt;
&lt;td&gt;about 0.10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each bar works like a 95% interval on the difference between two runs. They come from three or four runs per metric, so treat them as rough; the true values could plausibly be half or double. More runs would tighten them, but each full run costs about 257 judge calls against a free-tier limit of 500 a day. On a 9-question subset the bars are about 40% wider.&lt;/p&gt;

&lt;p&gt;These bars treat the two runs as independent. When both settings are scored on the same questions by the same judge, the noise is probably partly shared and cancels in the difference, so a paired comparison would likely give tighter bars.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. What this changes in my first post
&lt;/h2&gt;

&lt;p&gt;Figure 1 puts the first post's sweep against the measured noise band. Going through that post's conclusions one at a time:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"k=8 is the optimum." Gone, and now I know why.&lt;/strong&gt; Two things built that peak. First, the runs were scored on different questions: the k=8 run behind the 0.83 had only 9 of 18 questions scored, because the judge failed on the rest, and the questions it failed on were the harder ones. Second, each setting was run once. Put every run on the same 9 questions and the curve flattens to between 0.67 and 0.83. All seven runs fit inside the band, so nothing in the sweep can be told apart from noise. Only three of those nine questions changed score in any run (&lt;code&gt;cont-01&lt;/code&gt;, &lt;code&gt;cont-03&lt;/code&gt; and &lt;code&gt;meta-05&lt;/code&gt;); the other six scored the same in all seven.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Noise exceeds signal on every metric." Still true, but I overstated the noise.&lt;/strong&gt; The first post said recall varied by 0.22 across three k=8 runs. Part of that was the same coverage problem: on matched questions the k=8 runs spread by 0.11. The conclusion stands because the between-setting differences shrank too. What's new is knowing where the noise comes from: for recall and precision it's all the judge, and for faithfulness it's mostly the answers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"k=3 under-retrieves." Weakened to a hint.&lt;/strong&gt; k=3 still has the lowest recall on the matched questions (0.67, against about 0.77 for the other runs on average), and it sits on the lower edge of the band. That's consistent with retrieving too little, but the gap is below the 0.13 bar for 9 questions, and all of it comes from one question (&lt;code&gt;cont-01&lt;/code&gt;), which k=3 missed and every other run found. I'd now call it a direction worth testing, not a finding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"The judge moves the numbers more than the parameter does." Stronger.&lt;/strong&gt; I hedged this last time because I had only one run per judge and couldn't separate a judge effect from an unlucky draw. Now I know the same judge's run-to-run noise: the bar is about 0.09 for recall and 0.15 for faithfulness. Switching judge models moved recall by 0.31 and faithfulness by 0.26: more than three times the bar for recall, and nearly twice the bar for faithfulness. One caveat from the first post still applies: the two judges failed on different questions, so part of that gap is coverage. But it is too large to be run-to-run noise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"The significance test couldn't find anything." Now I know why so many pairs were tied.&lt;/strong&gt; The first post blamed Wilcoxon's floor for dropping tied pairs: 8 of 9 pairs scored identically between k=8 and k=12. The underlying reason is the references. 14 of my 18 reference answers were a single sentence, so recall on those questions can only be 0 or 1. Any two settings that retrieve the same relevant chunk tie exactly, and the test has nothing left to work with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Replicate before believing." Still right, but replicate the right thing.&lt;/strong&gt; For recall and precision, re-judge the same saved results; it's also cheaper, since there are no generation calls. For faithfulness and relevancy, regenerate the answers, because re-judging captures only about 15% of faithfulness's variance.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Failure cases the per-question view showed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Faithfulness handles a correct "no" badly.&lt;/strong&gt; One question asks which paper won a best-paper award. None did, and all three generations said so correctly. Faithfulness scored them 1.00, 0.33 and 0.00. The "no" itself isn't checkable against the chunks, so the score depends on whatever incidental sentences surround it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Relevancy rewards confidence, including invented confidence.&lt;/strong&gt; One question asks which cognitive biases a paper addresses. The papers don't name specific biases. One generation said so and scored 0 on relevancy, because the metric treats a hedged answer as noncommittal. Another generation confidently listed "confirmation bias", which isn’t in the 2005 paper or in the excerpts retrieved for this question, and scored 0.58. Faithfulness caught the invention (0.17), which is the argument for never reading relevancy alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Missing scores have causes, and the causes are fixable.&lt;/strong&gt; Across about 1,200 judge calls, two failed because the judge wrote malformed JSON escapes. On one day the judge slowed to about ten times its usual response time, and context precision timed out on 16 of 18 questions while the other three metrics finished. The cause: RAGAS's time limit covers a whole metric on one question, not each call, and precision makes one judge call per retrieved chunk (8 at k=8, against one to three for the others). A slow judge hits precision first, every time. Without per-reason logging, all of that would have shown up as &lt;code&gt;NaN&lt;/code&gt; and silently shrunk the average.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Recommendations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Freeze the question list before scoring, and report every row.&lt;/strong&gt; Fix the list of question IDs before any run, compare runs only on that list, and show all of them, with the reason for each missing score, so a complete-set result is never confused with a smaller matched subset. Appendix A shows this for the three generations. (Suggested by Ahmet Özel in a follow-up comment.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Report coverage with every mean.&lt;/strong&gt; &lt;code&gt;0.833&lt;/code&gt; and &lt;code&gt;0.833 (9/18)&lt;/code&gt; are different claims.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Where you can, score retrieval without an LLM.&lt;/strong&gt; If each question is labeled with the documents that should be retrieved, recall@k and similar measures can be computed by simple counting. With deterministic retrieval they would have no run-to-run noise at all, which is exactly where the judge-based recall and precision are weakest here. (Suggested by another reader.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Know which metrics read the answer.&lt;/strong&gt; Retrieval metrics need re-judging; answer metrics need regenerating.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compute a noise bar before comparing settings.&lt;/strong&gt; Two or three runs per setting are enough to estimate one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write references as several checkable claims.&lt;/strong&gt; A one-sentence reference turns recall into a coin flip.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Name the judge, its version and the library version&lt;/strong&gt; next to every number.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. Limits
&lt;/h2&gt;

&lt;p&gt;One corpus of 15 papers, 18 questions, one value of k, one generator and one judge. The variance estimates come from three or four runs each. The September sweep used a Gemini judge whose exact model version wasn't recorded, so the noise band in Figure 1 is borrowed from October's judge and the re-reading is indicative, not exact. The thresholds are specific to this setup; the method for getting them is not. The 85% answer share is likewise specific to this generator, prompt, judge and question set.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Next
&lt;/h2&gt;

&lt;p&gt;I've rewritten the 13 single-sentence references as two to four claims each. Re-judging the saved results against them will show whether multi-claim references reduce the judge noise on recall, and by how much. Next, I'll label each question with the papers that should be retrieved and log the retrieved document IDs on every run; my harness currently saves the retrieved text but not the IDs. That gives a judge-free retrieval score to set beside the judge-based one. After that, the top-k sweep again, with enough replicates per setting to clear the bar.&lt;/p&gt;

&lt;p&gt;The harness, the result files and every raw judge output are in the repo: &lt;a href="https://github.com/huali10044/research-rag" rel="noopener noreferrer"&gt;github.com/huali10044/research-rag&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Appendix A. All 18 questions, three generations
&lt;/h2&gt;

&lt;p&gt;Faithfulness and answer relevancy for each generation, each judged once. Every question is listed; a missing score shows its recorded reason.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Faithfulness G1&lt;/th&gt;
&lt;th&gt;G2&lt;/th&gt;
&lt;th&gt;G3&lt;/th&gt;
&lt;th&gt;Relevancy G1&lt;/th&gt;
&lt;th&gt;G2&lt;/th&gt;
&lt;th&gt;G3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;meta-01&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;0.83&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;0.94&lt;/td&gt;
&lt;td&gt;0.97&lt;/td&gt;
&lt;td&gt;— (judge output unreadable)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;meta-02&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.75&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;0.97&lt;/td&gt;
&lt;td&gt;0.98&lt;/td&gt;
&lt;td&gt;0.98&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;meta-03&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;0.89&lt;/td&gt;
&lt;td&gt;0.78&lt;/td&gt;
&lt;td&gt;0.78&lt;/td&gt;
&lt;td&gt;0.85&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;meta-04&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.33&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;0.95&lt;/td&gt;
&lt;td&gt;0.94&lt;/td&gt;
&lt;td&gt;0.96&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;meta-05&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.50&lt;/td&gt;
&lt;td&gt;0.50&lt;/td&gt;
&lt;td&gt;0.33&lt;/td&gt;
&lt;td&gt;0.72&lt;/td&gt;
&lt;td&gt;0.67&lt;/td&gt;
&lt;td&gt;0.70&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cont-01&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;0.60&lt;/td&gt;
&lt;td&gt;0.90&lt;/td&gt;
&lt;td&gt;0.97&lt;/td&gt;
&lt;td&gt;0.78&lt;/td&gt;
&lt;td&gt;0.70&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cont-02&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.80&lt;/td&gt;
&lt;td&gt;0.78&lt;/td&gt;
&lt;td&gt;0.79&lt;/td&gt;
&lt;td&gt;0.99&lt;/td&gt;
&lt;td&gt;0.99&lt;/td&gt;
&lt;td&gt;0.99&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cont-03&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.47&lt;/td&gt;
&lt;td&gt;0.23&lt;/td&gt;
&lt;td&gt;0.33&lt;/td&gt;
&lt;td&gt;0.83&lt;/td&gt;
&lt;td&gt;0.90&lt;/td&gt;
&lt;td&gt;0.99&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cont-04&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.26&lt;/td&gt;
&lt;td&gt;0.00&lt;/td&gt;
&lt;td&gt;0.12&lt;/td&gt;
&lt;td&gt;0.96&lt;/td&gt;
&lt;td&gt;0.98&lt;/td&gt;
&lt;td&gt;0.80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cont-05&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.80&lt;/td&gt;
&lt;td&gt;0.17&lt;/td&gt;
&lt;td&gt;0.73&lt;/td&gt;
&lt;td&gt;0.00&lt;/td&gt;
&lt;td&gt;0.58&lt;/td&gt;
&lt;td&gt;0.87&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cont-06&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.43&lt;/td&gt;
&lt;td&gt;0.38&lt;/td&gt;
&lt;td&gt;0.38&lt;/td&gt;
&lt;td&gt;0.93&lt;/td&gt;
&lt;td&gt;0.89&lt;/td&gt;
&lt;td&gt;0.88&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cont-07&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.61&lt;/td&gt;
&lt;td&gt;0.25&lt;/td&gt;
&lt;td&gt;0.33&lt;/td&gt;
&lt;td&gt;0.73&lt;/td&gt;
&lt;td&gt;0.81&lt;/td&gt;
&lt;td&gt;0.78&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cont-08&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.56&lt;/td&gt;
&lt;td&gt;0.52&lt;/td&gt;
&lt;td&gt;0.43&lt;/td&gt;
&lt;td&gt;0.98&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cont-09&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.80&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;0.71&lt;/td&gt;
&lt;td&gt;0.67&lt;/td&gt;
&lt;td&gt;0.61&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cont-10&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.29&lt;/td&gt;
&lt;td&gt;0.22&lt;/td&gt;
&lt;td&gt;0.40&lt;/td&gt;
&lt;td&gt;0.64&lt;/td&gt;
&lt;td&gt;0.85&lt;/td&gt;
&lt;td&gt;0.76&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cont-11&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.56&lt;/td&gt;
&lt;td&gt;0.28&lt;/td&gt;
&lt;td&gt;0.45&lt;/td&gt;
&lt;td&gt;0.70&lt;/td&gt;
&lt;td&gt;0.87&lt;/td&gt;
&lt;td&gt;0.58&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;adv-01&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.60&lt;/td&gt;
&lt;td&gt;0.82&lt;/td&gt;
&lt;td&gt;0.14&lt;/td&gt;
&lt;td&gt;0.84&lt;/td&gt;
&lt;td&gt;0.98&lt;/td&gt;
&lt;td&gt;0.83&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;adv-02&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;0.33&lt;/td&gt;
&lt;td&gt;0.00&lt;/td&gt;
&lt;td&gt;0.95&lt;/td&gt;
&lt;td&gt;0.95&lt;/td&gt;
&lt;td&gt;0.87&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>rag</category>
      <category>llm</category>
      <category>machinelearning</category>
      <category>evaluation</category>
    </item>
    <item>
      <title>I found the optimal top-k for my RAG system. Then I ran it again.</title>
      <dc:creator>Hua Li</dc:creator>
      <pubDate>Wed, 07 Oct 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/hualiphd/i-found-the-optimal-top-k-for-my-rag-system-then-i-ran-it-again-3oi3</link>
      <guid>https://dev.to/hualiphd/i-found-the-optimal-top-k-for-my-rag-system-then-i-ran-it-again-3oi3</guid>
      <description>&lt;p&gt;I built a small retrieval-augmented generation system over a corpus of research papers and wanted to answer an ordinary question: how many chunks should I retrieve? So I did what the tutorials suggest — swept top-k across 3, 5, 8 and 12, scored each configuration with RAGAS, and read off the winner.&lt;/p&gt;

&lt;p&gt;The answer was clean. k=8 led on all four metrics. Context recall was 0.53 at k=3, peaked at 0.83 at k=8, and fell back to 0.64 at k=12 — a textbook inverted U, with a story to match. Too few chunks and the generator starves; too many and distractors dilute the prompt. I had a number, a mechanism, and a plot.&lt;/p&gt;

&lt;p&gt;Then I ran k=8 twice more, changing nothing.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Run&lt;/th&gt;
&lt;th&gt;Faithfulness&lt;/th&gt;
&lt;th&gt;Answer relevancy&lt;/th&gt;
&lt;th&gt;Context precision&lt;/th&gt;
&lt;th&gt;Context recall&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;k=8, run 1&lt;/td&gt;
&lt;td&gt;0.767&lt;/td&gt;
&lt;td&gt;0.900&lt;/td&gt;
&lt;td&gt;0.655&lt;/td&gt;
&lt;td&gt;0.833&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;k=8, run 2&lt;/td&gt;
&lt;td&gt;0.590&lt;/td&gt;
&lt;td&gt;0.804&lt;/td&gt;
&lt;td&gt;0.585&lt;/td&gt;
&lt;td&gt;0.611&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;k=8, run 3&lt;/td&gt;
&lt;td&gt;0.640&lt;/td&gt;
&lt;td&gt;0.835&lt;/td&gt;
&lt;td&gt;0.687&lt;/td&gt;
&lt;td&gt;0.625&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Recall ranged from 0.611 to 0.833 across three runs of an identical configuration. The 0.833 that made k=8 look like a peak was the high draw of three.&lt;/p&gt;

&lt;p&gt;Set the variation &lt;em&gt;within&lt;/em&gt; one configuration against the differences &lt;em&gt;between&lt;/em&gt; configurations:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Spread between configs (means)&lt;/th&gt;
&lt;th&gt;Spread within k=8&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;faithfulness&lt;/td&gt;
&lt;td&gt;0.084&lt;/td&gt;
&lt;td&gt;0.177&lt;/td&gt;
&lt;td&gt;noise exceeds signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;answer relevancy&lt;/td&gt;
&lt;td&gt;0.059&lt;/td&gt;
&lt;td&gt;0.096&lt;/td&gt;
&lt;td&gt;noise exceeds signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;context precision&lt;/td&gt;
&lt;td&gt;0.023&lt;/td&gt;
&lt;td&gt;0.102&lt;/td&gt;
&lt;td&gt;noise exceeds signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;context recall&lt;/td&gt;
&lt;td&gt;0.162&lt;/td&gt;
&lt;td&gt;0.222&lt;/td&gt;
&lt;td&gt;noise exceeds signal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On every metric, one configuration varies more against itself than the configurations vary against each other. k=5, k=8 and k=12 are not distinguishable on this evidence. The only ordering that survives is that k=3 under-retrieves — it has the lowest recall in every run.&lt;/p&gt;

&lt;p&gt;The inverted U was an artifact of running each configuration once.&lt;/p&gt;

&lt;h2&gt;
  
  
  The judge moves the numbers more than the parameter does
&lt;/h2&gt;

&lt;p&gt;While building the harness I had changed judge models — the free tier I started on ran out of quota. That turned out to be a second experiment I hadn't meant to run.&lt;/p&gt;

&lt;p&gt;Same corpus, same generator, same k=5. Only the judge differs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Judge A&lt;/th&gt;
&lt;th&gt;Judge B&lt;/th&gt;
&lt;th&gt;Difference&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;faithfulness&lt;/td&gt;
&lt;td&gt;0.840&lt;/td&gt;
&lt;td&gt;0.582&lt;/td&gt;
&lt;td&gt;0.258&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;context recall&lt;/td&gt;
&lt;td&gt;0.917&lt;/td&gt;
&lt;td&gt;0.604&lt;/td&gt;
&lt;td&gt;0.313&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;context precision&lt;/td&gt;
&lt;td&gt;0.752&lt;/td&gt;
&lt;td&gt;0.628&lt;/td&gt;
&lt;td&gt;0.125&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;answer relevancy&lt;/td&gt;
&lt;td&gt;0.777&lt;/td&gt;
&lt;td&gt;0.861&lt;/td&gt;
&lt;td&gt;0.084&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Changing the judge moved faithfulness by 0.26 and recall by 0.31. Changing top-k from 3 to 8 — the parameter I was actually studying — moved faithfulness by 0.12.&lt;/p&gt;

&lt;p&gt;Part of that gap is different grading. Part is something subtler: the two judges fail differently. One of them intermittently returned output the parser couldn't read, so those samples scored as missing and dropped out of the average. The two numbers were therefore computed over different subsets of questions. Both effects are properties of the judge, and both are invisible in a reported score.&lt;/p&gt;

&lt;p&gt;I want to be careful here: I have one run per judge, so I can't cleanly separate a judge effect from an unlucky draw. The honest statement is that the judge shift is about the same size as the run-to-run variation I measured, which is already enough to make absolute RAGAS numbers meaningless without naming the judge that produced them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The significance test couldn't have found anything
&lt;/h2&gt;

&lt;p&gt;Comparing configuration means throws away the pairing, so I did it properly: per-question differences between two configurations, Wilcoxon signed-rank, each question acting as its own control. Nothing reached significance. For a while I read that as "no difference."&lt;/p&gt;

&lt;p&gt;It wasn't. Wilcoxon discards tied pairs, and with &lt;em&gt;n&lt;/em&gt; non-zero pairs the smallest two-sided p-value it can return is 2^(1−n):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Non-zero pairs&lt;/th&gt;
&lt;th&gt;Smallest achievable p&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1.000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0.500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;0.250&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;0.125&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0.0625&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;0.031&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Below six non-zero pairs, significance at α = 0.05 is arithmetically impossible regardless of the data.&lt;/p&gt;

&lt;p&gt;My context-precision comparison had three non-zero pairs and returned p = 0.250. My recall comparison had one and returned p = 1.000. Both are exactly the floor — every non-zero pair pointed the same way, the most extreme result obtainable, and it still couldn't clear the threshold.&lt;/p&gt;

&lt;p&gt;My sample collapsed twice over: 18 questions, then 8–9 matched pairs after judge failures, then 1–3 non-zero pairs after ties. Each stage looked survivable. Together they left a test with no power at all.&lt;/p&gt;

&lt;p&gt;The tie rate is the more interesting half, though. Eight of nine pairs scored &lt;em&gt;identically&lt;/em&gt; between k=8 and k=12. On most questions the chunks ranked 9 through 12 changed nothing the judge could see. That's a finding about retrieval, and it explains the null better than low power does.&lt;/p&gt;

&lt;h2&gt;
  
  
  The first thing my harness found was a bug in my own corpus
&lt;/h2&gt;

&lt;p&gt;Before any of this, the eval surfaced something I hadn't gone looking for. My "21-paper corpus" was 15 papers. Each one's PDF and its metadata record were being indexed as separate works, so retrieving both counted as retrieving two relevant documents. Every precision number I'd computed was inflated.&lt;/p&gt;

&lt;p&gt;Deduplicating on a canonical work ID fixed it. But I'd been quoting 21 for weeks, and nothing except an evaluation harness would have caught it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do differently, and what I'd keep
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Replicate before believing.&lt;/strong&gt; At minimum three runs per configuration. If within-configuration spread approaches the between-configuration differences, report that and stop — it's the finding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Report the judge and generator with every metric.&lt;/strong&gt; A RAGAS score without them isn't comparable to anyone else's, or to your own from last month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check the power before spending the quota.&lt;/strong&gt; Computing 2^(1−n) is one line and it tells you in advance whether a comparison can possibly reach significance. Mine couldn't, and I found out afterwards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Report ties and sample attrition.&lt;/strong&gt; "Not significant" and "no measurable difference" are different claims, and the gap between them lives in the counts that usually go unreported.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Classify the missing values, don't just count them.&lt;/strong&gt; A missing score can be a generation failure, a judge parse failure, a metric undefined by design, or a genuine zero. Pooled together, a parser fix changes your reported mean by changing which questions are in it. [Suggested by Ahmet Özel (&lt;a class="mentioned-user" href="https://dev.to/ahmetozel"&gt;@ahmetozel&lt;/a&gt;) in the comments.]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Separate what a judge grades from what code can check.&lt;/strong&gt; My suite has two tracks. Queries about corpus statistics and listings return zero chunks by design, so context-based metrics are undefined for them; those get deterministic assertions instead. Those assertions, and the intent-routing accuracy, came back at 100% across every run. Code-driven checks carried no variance at all. The LLM-judged metrics carried all of it. That contrast is worth designing for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The replication spread conflates two sources of variance.&lt;/strong&gt; My three identical-configuration runs re-generated answers &lt;em&gt;and&lt;/em&gt; re-scored them, so the 0.22 recall range mixes generator sampling with judge variance, and I reported it as a single quantity. Separating them needs two runs I didn't do: replay the judge over saved answers to isolate judge variance, and re-generate under a fixed judge to isolate the other half. The harness can't do the replay yet, because it saves the answers but not the retrieved contexts the judge needs. Credit to Ahmet Özel (&lt;a class="mentioned-user" href="https://dev.to/ahmetozel"&gt;@ahmetozel&lt;/a&gt;) for pointing this out in the comments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run 1 at k=8 was scored on half the questions.&lt;/strong&gt; The judge returned no score for 9 of the 18, and the nine it did score are the easier half of the set. So the run 1 figures in the table above, including the 0.833 recall, were compared against runs scored on all or nearly all of the questions. Restricting every run to the same nine questions, recall is 0.67 at k=3, 0.78 at k=5, 0.72 to 0.83 across the three k=8 runs, and 0.72 at k=12. There is no peak at k=8, and the spread within k=8 is 0.11, not 0.22, the same size as the spread between configurations. The conclusion stands, but part of the original inverted U came from comparing different question sets, not only from run-to-run noise.&lt;/p&gt;

&lt;p&gt;This is one system, one 15-paper corpus, 18 scored content questions, and two judges. I'm not claiming a general law about RAGAS or about LLM-as-judge evaluation — I'm claiming that the standard procedure, run on a realistic small setup, produced a confident answer that replication dissolved, and that the failure modes were all invisible from the reported numbers.&lt;/p&gt;

&lt;p&gt;If your evaluation is larger, it may be fine. If it's about this size, and you ran each configuration once, you have the result I had before I ran it again.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Harness, golden set, ablation and results: &lt;a href="https://github.com/huali10044/research-rag" rel="noopener noreferrer"&gt;github.com/huali10044/research-rag&lt;/a&gt;. The system itself is live at &lt;a href="https://huali-research-rag.streamlit.app/" rel="noopener noreferrer"&gt;huali-research-rag.streamlit.app&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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