<?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: Alan Finney</title>
    <description>The latest articles on DEV Community by Alan Finney (@3dogs).</description>
    <link>https://dev.to/3dogs</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%2F4177794%2F73e97824-4469-49d5-8b3f-11d9ea7aa4e8.png</url>
      <title>DEV Community: Alan Finney</title>
      <link>https://dev.to/3dogs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/3dogs"/>
    <language>en</language>
    <item>
      <title>My Benchmark's First Leaderboard Measured My Grader, Not the Models</title>
      <dc:creator>Alan Finney</dc:creator>
      <pubDate>Sun, 11 Oct 2026 20:48:33 +0000</pubDate>
      <link>https://dev.to/3dogs/my-benchmarks-first-leaderboard-measured-my-grader-not-the-models-405d</link>
      <guid>https://dev.to/3dogs/my-benchmarks-first-leaderboard-measured-my-grader-not-the-models-405d</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/kaggle-2026-09-23"&gt;Kaggle Benchmarking Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Benchmarked
&lt;/h2&gt;

&lt;p&gt;Scores and costs in this post are from my Kaggle benchmark page as of 11:10 AM PT on October 11, 2026.&lt;/p&gt;

&lt;p&gt;Numeric grounding: can a model answer using only the numbers a short context states, and abstain when the number is missing? In a financial or operations summary, a made-up number is worse than "I can't tell". Every company, figure and unit in the benchmark is invented ("Vendo Bin A", "brens per lune"), so no model can answer from memory.&lt;/p&gt;

&lt;p&gt;I treated two things as suspects, not just the models. The first was the grader: I replayed raw replies before believing any score. The second was the answer key: every key in the hardest task had to survive a blind vote by three models that are not being scored.&lt;/p&gt;

&lt;p&gt;The benchmark has two layers. Each row is scored 0 or 1 on the final ANSWER line.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sanity gate (five tasks, 6 to 9 rows each).&lt;/strong&gt; Each one isolates a single classic grounding failure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lookup: read a stated value&lt;/li&gt;
&lt;li&gt;abstain: say CANNOT BE DETERMINED when the value is not stated&lt;/li&gt;
&lt;li&gt;distractor: pick the right value out of several similar ones&lt;/li&gt;
&lt;li&gt;multistep: combine stated values with arithmetic&lt;/li&gt;
&lt;li&gt;units: convert using a made-up unit defined in the context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stress test: ng-hard (10 rows).&lt;/strong&gt; Each row stacks several traps in one paragraph:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a figure corrected twice, where only the last correction counts&lt;/li&gt;
&lt;li&gt;a correction that applies only to a neighbouring entity or year&lt;/li&gt;
&lt;li&gt;near-miss missing data ("fiscal 2024" when the question asks about calendar 2024)&lt;/li&gt;
&lt;li&gt;two-step unit chains with three or more distractor numbers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Models Tested
&lt;/h2&gt;

&lt;p&gt;Gemini 3.7 Flash, GLM-5, Qwen 3 235B A22B Instruct and gpt-oss-120b, all run on Kaggle. They come from four different model makers (Google, Z.ai, Alibaba and OpenAI), so a parsing quirk tied to one model family would show up as a gap between families. They also span a wide price range, which mattered more than I expected (Finding 4).&lt;/p&gt;

&lt;h2&gt;
  
  
  Findings
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. The first leaderboard measured my grader, not the models.&lt;/strong&gt; The first run produced a clear spread: 0.98, 0.94, 0.78 and 0.62. Before publishing, I replayed the actual replies, and most of the "wrong" answers were right. The grader only accepted a line that started with &lt;code&gt;ANSWER:&lt;/code&gt;, so it scored these correct replies as 0:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;27 ANSWER: 27&lt;/code&gt; (number and marker on one line): Qwen scored 0% on distractor because of this&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;**ANSWER: 72**&lt;/code&gt; (markdown bold): gpt-oss scored 16.7% on multistep&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;\text{ANSWER: } 135&lt;/code&gt; (LaTeX)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One abstain row was also keyed wrongly. The context said "No side reactions occurred" and the question asked how much side product formed. Zero is a correct answer, but my key required "cannot be determined".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. With a fair grader, every model passed the sanity gate.&lt;/strong&gt; The fixed grader reads the last ANSWER marker anywhere in the reply. For a number, it takes the first number after that marker. For an abstention, it needs the full phrase CANNOT BE DETERMINED. A wrong number, a missing answer, or abstaining when a value is stated still scores 0. Before the grader went live, I checked it against a table of 21 reply formats modelled on the replies I saw, including 8 that must still score 0.&lt;/p&gt;

&lt;p&gt;Parsing and that one bad key together had moved a model's score on the five core tasks by as much as 0.38 (gpt-oss: 0.62 to 1.00). All four models then scored 100% on all five gate tasks. So on short, clean contexts the gate is a pass/fail floor, not a ranking: a model you trust with numbers should clear it, and all four did.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The stress test is where models start to differ.&lt;/strong&gt; Before running ng-hard, I had all 12 draft answer keys checked blind by three models that are not in the benchmark. I kept a row only if at least two of them agreed with its key, so 2 rows were dropped. On one dropped row, all three checkers answered 6.40 for "North Ridge" when only "North Ridge Annex" was stated. That near-miss fooled strong models, but a row I cannot defend is a coin flip with extra steps.&lt;/p&gt;

&lt;p&gt;Gemini 3.7 Flash, GLM-5 and Qwen 3 235B scored 100% on ng-hard. gpt-oss-120b scored 80% (8 of 10 rows), and its two misses were different kinds of failure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;An arithmetic slip.&lt;/strong&gt; The context gave a rate that was corrected twice, ending at 11.60 brens per lune, plus a run of 3.0 lunes and a dock amount of 1.20 brens. The key is 11.60 x 3.0 + 1.20 = 36.00. gpt-oss replied &lt;code&gt;ANSWER: 4.20&lt;/code&gt;, which is exactly 3.0 + 1.20: the run length plus the dock amount, with the rate unused.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An incomplete abstention.&lt;/strong&gt; The question asked for actual 2025 capacity, but the context only stated planned 2025 and actual 2024 figures. gpt-oss's entire visible reply was &lt;code&gt;ANSWER: CANNOT BE&lt;/code&gt;. That was the right call, ending one word short of the required phrase. Kaggle's run log shows 164 output tokens for that reply. The full-phrase rule was fixed before this run, so the row scored 0, but it could fairly be argued either way.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So gpt-oss's overall 0.97, against 1.00 for the other three, rests on one clear error and one incomplete answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Same score, very different bill.&lt;/strong&gt; Here is what Kaggle's Score vs. Total Cost chart shows for the full six-task run:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Qwen 3 235B: 100 for $0.006&lt;/li&gt;
&lt;li&gt;Gemini 3.7 Flash: 100 for $0.07&lt;/li&gt;
&lt;li&gt;GLM-5: 100 for $0.19&lt;/li&gt;
&lt;li&gt;gpt-oss-120b: 96.67 for $0.005&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Among the three perfect scorers, GLM-5 cost about 30 times as much as Qwen. Once accuracy ties, cost per flawless run is the useful tiebreaker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I would measure next:&lt;/strong&gt; the same traps inside long documents and tables, and repeated runs per model to see whether gpt-oss's incomplete abstention happens again or was a one-off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Indicative only:&lt;/strong&gt; each task has 6 to 10 rows, so a single row is worth 10 to 17 points, and each model ran once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I take from it:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Replay raw replies before you trust a leaderboard. Most of the spread I first measured came from parsing, not from the models.&lt;/li&gt;
&lt;li&gt;Validate answer keys independently. A blind vote by models you are not scoring caught keys I could not defend.&lt;/li&gt;
&lt;li&gt;On short, clean contexts, single-trap tests are now a floor for these four models. Stacked traps are where differences start.&lt;/li&gt;
&lt;li&gt;When accuracy ties, cost decides. Among the three perfect scorers it varied about 30-fold.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  My Benchmark
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.kaggle.com/benchmarks/alanfinney/numeric-grounding" rel="noopener noreferrer"&gt;https://www.kaggle.com/benchmarks/alanfinney/numeric-grounding&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>kagglechallenge</category>
      <category>ai</category>
      <category>machinelearning</category>
    </item>
  </channel>
</rss>
