<?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: Venkatesh S</title>
    <description>The latest articles on DEV Community by Venkatesh S (@venkathub).</description>
    <link>https://dev.to/venkathub</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%2F4040816%2F9108a1d4-8af9-4930-b195-0342de2710f6.jpg</url>
      <title>DEV Community: Venkatesh S</title>
      <link>https://dev.to/venkathub</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/venkathub"/>
    <language>en</language>
    <item>
      <title>Eval-Gated AI Releases: Treating Retrieval Quality Like Unit Tests</title>
      <dc:creator>Venkatesh S</dc:creator>
      <pubDate>Tue, 21 Jul 2026 22:42:49 +0000</pubDate>
      <link>https://dev.to/venkathub/eval-gated-ai-releases-treating-retrieval-quality-like-unit-tests-4o9j</link>
      <guid>https://dev.to/venkathub/eval-gated-ai-releases-treating-retrieval-quality-like-unit-tests-4o9j</guid>
      <description>&lt;p&gt;No backend team would merge a PR that fails the test suite. Yet many AI teams ship prompt and model changes with no automated quality check at all — they eyeball a few responses and hope. The failure mode is silent: answers get slightly less faithful, citations drift, and nobody notices until a user does.&lt;/p&gt;

&lt;p&gt;Atlas (my enterprise RAG copilot project) treats evals exactly like tests: &lt;strong&gt;a merge is blocked on a quality or cost regression.&lt;/strong&gt; Here's the shape of that pipeline and what I learned building it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What gates the build
&lt;/h2&gt;

&lt;p&gt;Every PR runs an offline, deterministic, GPU-free eval gate against committed cassettes:&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;Baseline&lt;/th&gt;
&lt;th&gt;Floor&lt;/th&gt;
&lt;th&gt;Policy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RAGAS faithfulness&lt;/td&gt;
&lt;td&gt;0.706&lt;/td&gt;
&lt;td&gt;0.656&lt;/td&gt;
&lt;td&gt;blocking, regression band 0.05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Answer relevancy&lt;/td&gt;
&lt;td&gt;0.832&lt;/td&gt;
&lt;td&gt;0.782&lt;/td&gt;
&lt;td&gt;blocking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context recall&lt;/td&gt;
&lt;td&gt;0.738&lt;/td&gt;
&lt;td&gt;0.668&lt;/td&gt;
&lt;td&gt;blocking, band 0.07&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Citation correctness&lt;/td&gt;
&lt;td&gt;1.000&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;tracked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adversarial suite (injection)&lt;/td&gt;
&lt;td&gt;100% pass&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;zero-tolerance, blocking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost per request&lt;/td&gt;
&lt;td&gt;committed baseline&lt;/td&gt;
&lt;td&gt;reduction target&lt;/td&gt;
&lt;td&gt;blocking (separate cost gate)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three design decisions made this workable:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Floors + regression bands, not perfection.&lt;/strong&gt; A hard "faithfulness ≥ 0.9" gate would have blocked every merge forever. Instead: an absolute floor (never ship below this) plus a regression band relative to the committed baseline (never get meaningfully worse). This is the eval equivalent of ratcheting code coverage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Deterministic and GPU-free in CI.&lt;/strong&gt; Live-model evals in CI are slow, expensive, and flaky. Atlas replays committed cassettes — recorded model interactions — so the gate is fast and reproducible. Cassettes are re-recorded deliberately when behavior is supposed to change, which turns "the model changed" into a reviewed diff instead of an ambient surprise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Cost is a gated metric, not a dashboard.&lt;/strong&gt; A prompt change that doubles token usage is a regression even if quality holds. Atlas's cost gate asserts the measured cost-reduction against a committed baseline and fails the build when cost regresses below the band — the same way a p95-latency budget would gate a backend service.&lt;/p&gt;

&lt;h2&gt;
  
  
  The payoff: decisions you can defend
&lt;/h2&gt;

&lt;p&gt;The gate earned its keep when I fine-tuned a QLoRA adapter for citation formatting. The benchmark (paired bootstrap, McNemar) showed: citation format validity 0.00 → 0.955 (p ≈ 0), serving cost −79% on the same GPU — and a faithfulness trade-off of −0.10, still above the floor. The promotion gate had the data to make that call explicitly, and the pipeline is proven to both promote &lt;em&gt;and&lt;/em&gt; block a candidate in CI.&lt;/p&gt;

&lt;p&gt;Without evals, that's a vibes decision. With them, it's an engineering decision with a paper trail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to start (smaller than you think)
&lt;/h2&gt;

&lt;p&gt;You don't need RAGAS on day one. Start with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;20–30 golden questions&lt;/strong&gt; with expected source documents — your retrieval hit-rate suite.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A handful of adversarial prompts&lt;/strong&gt; (injection attempts, out-of-scope questions) with expected refusals.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A CI job that fails when either regresses.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's an afternoon of work, and it changes the culture immediately: prompts become code, model swaps become reviewed changes, and "did we get worse?" has an answer.&lt;/p&gt;

&lt;p&gt;Backend engineering solved this problem twenty years ago — we just called it testing. AI systems don't need a new philosophy; they need the old one applied.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>testing</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
