<?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: Aniruddh Vijayvargia</title>
    <description>The latest articles on DEV Community by Aniruddh Vijayvargia (@aniruddh_vijayvargia_abc0).</description>
    <link>https://dev.to/aniruddh_vijayvargia_abc0</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%2F4155390%2F856e0675-34e8-4d98-8545-1420ef6e8018.png</url>
      <title>DEV Community: Aniruddh Vijayvargia</title>
      <link>https://dev.to/aniruddh_vijayvargia_abc0</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aniruddh_vijayvargia_abc0"/>
    <language>en</language>
    <item>
      <title>Second Look: a local bill checker that gave 0 wrong verdicts by learning to say “not sure”</title>
      <dc:creator>Aniruddh Vijayvargia</dc:creator>
      <pubDate>Fri, 23 Oct 2026 15:40:00 +0000</pubDate>
      <link>https://dev.to/aniruddh_vijayvargia_abc0/second-look-a-local-bill-checker-that-gave-0-wrong-verdicts-by-learning-to-say-not-sure-2cc7</link>
      <guid>https://dev.to/aniruddh_vijayvargia_abc0/second-look-a-local-bill-checker-that-gave-0-wrong-verdicts-by-learning-to-say-not-sure-2cc7</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Second Look&lt;/strong&gt; checks a UK electricity bill line by line against the Ofgem price cap, and shows&lt;br&gt;
where on the bill every number came from.&lt;/p&gt;

&lt;p&gt;Checking a bill is the kind of job everybody skips. You need the cap rates for the right quarter,&lt;br&gt;
the days on each side of a rate change, the standing charge per day, and the VAT rate, which falls&lt;br&gt;
to 0% on 1 October 2026. Then you do the sums. Nobody does this, so nobody notices when a bill&lt;br&gt;
charges the old quarter's rate, counts a day twice or adds VAT that no longer applies.&lt;/p&gt;

&lt;p&gt;Second Look does the sums, and it is careful about what it claims. Every bill gets one of four&lt;br&gt;
verdicts:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;th&gt;When&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Reconciled&lt;/td&gt;
&lt;td&gt;Every line recomputes from the cap for its dates, and the total matches.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discrepancy&lt;/td&gt;
&lt;td&gt;A check fails on values that are printed on the bill. You see the line, the expected value and the billed one.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Not enough evidence&lt;/td&gt;
&lt;td&gt;A value is missing, estimated, or could not be found printed on the bill. It won't guess.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tariff not supported&lt;/td&gt;
&lt;td&gt;Anything that isn't single-rate price-cap electricity for a period it has rates for.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It also says whether the period's usage looks normal for that home, as a TabPFN forecast range from&lt;br&gt;
smart-meter history. That is context only, and it never changes the verdict.&lt;/p&gt;

&lt;p&gt;I measured it in four experiments. The headline is the one I'm proudest of because it cost the most:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;On 75 bill images (25 synthetic bills, each clean, scanned and phone-photographed), Gemma reading&lt;br&gt;
the bill on its own gave &lt;strong&gt;22 confident wrong verdicts&lt;/strong&gt;. Second Look gave &lt;strong&gt;0&lt;/strong&gt;. The price is caution:&lt;br&gt;
on 42 of the 75 it said "Not enough evidence" and pointed at the field to check.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A tool that is sometimes confidently wrong about money is worse than no tool. I'd rather ship the&lt;br&gt;
one that knows when to stop.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live demo: &lt;a href="https://second-look-demo-xj2a.onrender.com" rel="noopener noreferrer"&gt;https://second-look-demo-xj2a.onrender.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The hosted demo is &lt;strong&gt;recorded&lt;/strong&gt;. Each example is a saved output of the full pipeline (Gemma,&lt;br&gt;
Tesseract, the checks, TabPFN, the explanation) run on my laptop, and every page says so. No model&lt;br&gt;
runs on Render, and the bills are synthetic, from fictional suppliers. There are four examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A bill that adds up.&lt;/strong&gt; A scanned bill; every line matches the cap, so it's &lt;em&gt;Reconciled&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A planted VAT error.&lt;/strong&gt; The bill charges 5% VAT after it fell to 0% on 1 October 2026. Second Look
says &lt;em&gt;Discrepancy&lt;/em&gt;, +£6.33, and shows which check failed and why.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A misread, then corrected.&lt;/strong&gt; Gemma misread two end dates. Tesseract couldn't find them on the
bill, so the verdict is &lt;em&gt;Not enough evidence&lt;/em&gt; and the two fields are outlined in red. Click
&lt;strong&gt;Edit&lt;/strong&gt; on each and enter &lt;code&gt;2025-06-30&lt;/code&gt;, the date printed on the bill: every check re-runs, and
the verdict becomes &lt;em&gt;Reconciled&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instructions printed on the bill.&lt;/strong&gt; The bill tells AI reviewers to claim a £250 overcharge. It's
read as data and ignored: &lt;em&gt;Reconciled&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&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%2Fraw.githubusercontent.com%2FANIRUDDH-001%2Fsecond-look%2Fmain%2Fpost%2Fimages%2Fvat-dark.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%2Fraw.githubusercontent.com%2FANIRUDDH-001%2Fsecond-look%2Fmain%2Fpost%2Fimages%2Fvat-dark.png" alt="The planted VAT error: Discrepancy, billed £133.01, recomputed £126.68"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hover any field and its box lights up on the bill. Here Gemma misread two dates, so the failed&lt;br&gt;
checks can't be trusted yet:&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%2Fraw.githubusercontent.com%2FANIRUDDH-001%2Fsecond-look%2Fmain%2Fpost%2Fimages%2Fmisread-then-corrected-dark.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%2Fraw.githubusercontent.com%2FANIRUDDH-001%2Fsecond-look%2Fmain%2Fpost%2Fimages%2Fmisread-then-corrected-dark.png" alt="A misread bill: Not enough evidence, two values not found on the bill"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To run it for real on your own images, follow the README; everything runs locally.&lt;/p&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ANIRUDDH-001" rel="noopener noreferrer"&gt;
        ANIRUDDH-001
      &lt;/a&gt; / &lt;a href="https://github.com/ANIRUDDH-001/second-look" rel="noopener noreferrer"&gt;
        second-look
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Second Look&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Checks a UK electricity bill line by line against the Ofgem price cap, and shows the evidence for
every number it uses.&lt;/p&gt;
&lt;p&gt;You give it a photo or scan of a bill. It tells you one of four things:&lt;/p&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reconciled&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Every line recomputes from the Ofgem cap for those dates, and the total matches.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Discrepancy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;At least one check fails. You see which line, what was expected and what was billed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Not enough evidence&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A value it needs is missing, unreadable or estimated, so it won't guess.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tariff not supported&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The bill isn't single-rate, price-cap electricity for a period it has rates for.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;It also says whether the period's usage looks typical for that home, using a TabPFN forecast from
smart-meter history. That is context only. It never decides the verdict.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How it works&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;The model transcribes, code reconciles, TabPFN puts the usage in context, and…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ANIRUDDH-001/second-look" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;MIT licensed. The README has the full setup (Python 3.11, Node, Tesseract, Ollama), what is real,&lt;br&gt;
what is synthetic and what is recorded, and every result table. &lt;code&gt;python -m eval.run_all&lt;/code&gt; regenerates&lt;br&gt;
every number in this post.&lt;/p&gt;
&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;The rule I held to throughout: &lt;strong&gt;the model transcribes, code reconciles, TabPFN puts the usage in&lt;br&gt;
context, and the assistant explains.&lt;/strong&gt; No model ever produces a number the verdict depends on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bill image
   │
   ├─► Gemma 4 E2B (Ollama, CPU) ── copies values into a strict JSON schema
   │                                 "you are a copier, not a calculator"
   ├─► Tesseract OCR ────────────── a second, independent reader
   │
   ▼
find each value on the bill ── where it belongs: a line's date on that line's row,
   │                              the subtotal on its labelled line; else flag it
   ▼
reconcile (Python, Decimal) ── Ofgem cap table, prorated across quarter changes,
   │                              VAT 5% → 0% on 1 Oct 2026  →  one of four verdicts
   ├─► TabPFN ─── 90% range for this period's kWh from the home's history (context only)
   ▼
explain (Gemma) ── 2–3 sentences from the computed payload; a guard rejects any
                   number not in the payload and any claim the verdict can't back
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1. Transcribe, don't compute.&lt;/strong&gt; Gemma 4 E2B gets the bill image and a JSON schema where every&lt;br&gt;
value is a string. The prompt says to copy values exactly as printed and to use null when something&lt;br&gt;
is missing. If the reply is malformed, it gets up to two retries, and the feedback is &lt;strong&gt;only ever&lt;br&gt;
about the format&lt;/strong&gt;. Telling a model "your total doesn't add up" is an invitation to make it add up,&lt;br&gt;
and that would quietly erase the exact discrepancies the tool exists to find.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Make every value prove it is on the page.&lt;/strong&gt; This is the part that changed most while building.&lt;br&gt;
Gemma is a good reader but not a perfect one. On my bills it had three habits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it shortened rates: &lt;code&gt;54.486p&lt;/code&gt; became &lt;code&gt;54.48&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;it copied the total into the subtotal;&lt;/li&gt;
&lt;li&gt;it put the billing period's end date on a charge line that actually ends mid-period.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So Tesseract reads the page independently, and each value Gemma copied has to be &lt;strong&gt;found where it&lt;br&gt;
belongs&lt;/strong&gt;. A charge line's dates and rate must be on that line's row, and the subtotal must be on the&lt;br&gt;
line labelled &lt;em&gt;Subtotal&lt;/em&gt; or &lt;em&gt;Before VAT&lt;/em&gt;. Searching the whole page wasn't enough, because the&lt;br&gt;
period end date is printed on every bill. A value that isn't found is shown with a red dashed&lt;br&gt;
outline and the words "Not found on the bill, check it".&lt;/p&gt;

&lt;p&gt;There is one narrow repair. When exactly one printed number extends the digits Gemma gave (Gemma&lt;br&gt;
read &lt;code&gt;54.48&lt;/code&gt;, the bill says &lt;code&gt;54.486&lt;/code&gt;), the printed one is used and the UI says so.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. A discrepancy has to rest on evidence.&lt;/strong&gt; If a check fails on a value that wasn't found on the&lt;br&gt;
bill, the failure might be a misread, not a billing error. The verdict then becomes "Not enough&lt;br&gt;
evidence", and the field is highlighted. Second Look only says &lt;em&gt;Discrepancy&lt;/em&gt; when every value behind&lt;br&gt;
the failure is printed on the bill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Reconcile in plain code.&lt;/strong&gt; The Ofgem cap for 2025 Q1 to 2026 Q4 lives in a YAML file. Each row&lt;br&gt;
has its effective dates and the Ofgem URL it came from. A billing period that crosses a quarter&lt;br&gt;
boundary is split by day. Money is &lt;code&gt;Decimal&lt;/code&gt;, and the net rate is the published rate divided by&lt;br&gt;
1 + VAT, to three decimal places. The checks are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;each line's rate against the cap for its dates;&lt;/li&gt;
&lt;li&gt;quantity × rate = amount;&lt;/li&gt;
&lt;li&gt;the standing charge covers each day exactly once;&lt;/li&gt;
&lt;li&gt;meter advance = units billed;&lt;/li&gt;
&lt;li&gt;the VAT rate for the date;&lt;/li&gt;
&lt;li&gt;subtotal + VAT = total.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Context, not judgement.&lt;/strong&gt; TabPFN forecasts a 90% range for the period's kWh from the&lt;br&gt;
home's own history. Two variants were measured against naive baselines (Experiment C):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the TabPFN v2 regressor on lag features;&lt;/li&gt;
&lt;li&gt;TabPFN-TS on the daily series.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A bill can be correct and still unusually high, so the band is labelled "It describes usage, not&lt;br&gt;
whether the bill is right."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Explain, but only what was computed.&lt;/strong&gt; Gemma writes two or three sentences from a JSON&lt;br&gt;
payload of the results. Then a guard checks them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;every number in the text must appear in the payload;&lt;/li&gt;
&lt;li&gt;each verdict has words it may not use, for example "overcharge" on a reconciled bill.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If either check fails, the text is replaced with fixed template wording, and the UI shows which one&lt;br&gt;
you got.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Corrections are a log, not an edit.&lt;/strong&gt; Each correction is appended, the bill is rebuilt from the&lt;br&gt;
extraction plus the log, and every check re-runs. Uploads are keyed by a hash of the image, so&lt;br&gt;
uploading twice never runs twice.&lt;/p&gt;

&lt;p&gt;The stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; FastAPI with one worker thread and SQLite.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; React and TypeScript with TanStack Query. The bill sits beside the field list, and
hovering a field lights up its box on the bill.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tests:&lt;/strong&gt; 55, run with pytest. They cover tariff prorating, the VAT switch, the retry rule, the
grounding rules, the evidence gate, the explanation guard and correction replay.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What the experiments found
&lt;/h3&gt;

&lt;p&gt;All bills are synthetic, in three layouts I made, so these numbers say nothing about real&lt;br&gt;
suppliers' bills. That limit matters; please read them with it in mind.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A. Reading the bill.&lt;/strong&gt; 75 images. The verdict is what the app would say from each reading.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Right verdict&lt;/th&gt;
&lt;th&gt;"Not enough evidence"&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Wrong verdict&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;Seconds per bill&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tesseract + regex&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemma 4 E2B alone&lt;/td&gt;
&lt;td&gt;53&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;104&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Second Look&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;106&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Gemma alone gets more verdicts right, and more wrong. Second Look's caution shows up in the details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On the 36 bills with a planted error, it said &lt;em&gt;Discrepancy&lt;/em&gt; 8 times and &lt;em&gt;Not enough evidence&lt;/em&gt; 28 times.
It never called one of them &lt;em&gt;Reconciled&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;On the 27 correct bills, it said &lt;em&gt;Reconciled&lt;/em&gt; 13 times and &lt;em&gt;Not enough evidence&lt;/em&gt; 14 times.&lt;/li&gt;
&lt;li&gt;Field accuracy was 93% on clean images, 94% on scans and 90% on phone photos. Tesseract alone
managed 85%, 69% and 24%.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first version of the evidence gate never fired. Failed checks named a group (&lt;code&gt;lines[0]&lt;/code&gt;), and&lt;br&gt;
unverified fields were leaves (&lt;code&gt;lines[0].end&lt;/code&gt;), so the two never matched. Fixing that one comparison&lt;br&gt;
took confident wrong verdicts from 10 to 0. That is the kind of bug you only find by counting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B. The checks.&lt;/strong&gt; 140 bills read from the answer key, so no model is involved. All 7 planted fault&lt;br&gt;
classes were caught on 10 of 10 bills each, with 0 false alarms on 60 correct bills. All 10&lt;br&gt;
unsupported tariffs were refused.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C. Usage context.&lt;/strong&gt; 80 London homes × 6 forecast dates = 480 forecasts of a 30-day period.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;MAE (kWh/day)&lt;/th&gt;
&lt;th&gt;MASE&lt;/th&gt;
&lt;th&gt;90% coverage&lt;/th&gt;
&lt;th&gt;90% width&lt;/th&gt;
&lt;th&gt;Seconds&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;TabPFN v2, lag features&lt;/strong&gt; (shipped)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.19&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.03&lt;/td&gt;
&lt;td&gt;94%&lt;/td&gt;
&lt;td&gt;6.5&lt;/td&gt;
&lt;td&gt;0.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TabPFN-TS&lt;/td&gt;
&lt;td&gt;1.20&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;td&gt;98%&lt;/td&gt;
&lt;td&gt;11.2&lt;/td&gt;
&lt;td&gt;22.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Last period&lt;/td&gt;
&lt;td&gt;1.35&lt;/td&gt;
&lt;td&gt;1.12&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mean of last 3 periods&lt;/td&gt;
&lt;td&gt;1.69&lt;/td&gt;
&lt;td&gt;1.36&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same period last year&lt;/td&gt;
&lt;td&gt;1.87&lt;/td&gt;
&lt;td&gt;1.54&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Both TabPFN variants beat every naive baseline and tie each other on accuracy. The lag model's range&lt;br&gt;
is half as wide, still covers 94%, and runs 25 times faster, so that is the one in the app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;D. Trying to mislead it.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I printed instructions on six bills: report the total as £0.00, set the units to 1, claim a £250
overcharge. No injected value was ever copied. Three got the right verdict, three got &lt;em&gt;Not enough
evidence&lt;/em&gt;, and none got a wrong one.&lt;/li&gt;
&lt;li&gt;In 12 explanation cases, the guard caught one model text saying "overcharge" and "refund" on a bill
that couldn't support it, and showed the template wording instead. Unsupported claims shown: 0.&lt;/li&gt;
&lt;li&gt;After a correction, the verdict always reflected the corrected bill.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;A bill shows your name, your address, your meter number, and a record of when you are home. That is&lt;br&gt;
exactly the document you shouldn't upload to a cloud service to "check it for you". Open weights&lt;br&gt;
are what make the private version possible: Gemma 4 E2B runs on a laptop CPU, and so does TabPFN.&lt;br&gt;
The bill never leaves the machine. I checked that by watching the processes' network connections&lt;br&gt;
while every experiment ran, and there were no connections beyond localhost.&lt;/p&gt;

&lt;p&gt;Open data does the other half. The usage history is real smart-meter data from the Low Carbon London&lt;br&gt;
trial, published by UK Power Networks under CC BY 4.0. I used 396 of its standard-tariff homes. The tariff is Ofgem's published cap.&lt;br&gt;
Every rate in the table links to its Ofgem page, so anyone can audit the auditor.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;I built this with Claude Code as a pair. I set the rules (model transcribes, code reconciles), the&lt;br&gt;
four verdicts and the experiments, and kept every number honest. It wrote most of the code and ran&lt;br&gt;
the experiments. The moments that mattered weren't code generation. They were the counts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Experiment A showed 10 confident wrong verdicts that should have been caught. Tracing them found
the evidence gate comparing &lt;code&gt;lines[0]&lt;/code&gt; against &lt;code&gt;lines[0].end&lt;/code&gt; and never matching.&lt;/li&gt;
&lt;li&gt;One bill got a false &lt;em&gt;Discrepancy&lt;/em&gt; because the rate repair borrowed a number from a different row
of the bill. The repair now only looks at the line's own row, and there's a test for it.&lt;/li&gt;
&lt;li&gt;My laptop kept overheating, so every model run was one job at a time, paused and resumed by
process id, with Gemma's replies cached so a rescore never re-ran the model.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Lazy Payoff
&lt;/h2&gt;

&lt;p&gt;Checking one bill by hand means finding the right quarter's cap on Ofgem's site, splitting the&lt;br&gt;
period at any rate change, counting standing-charge days on each side, working out the net rate,&lt;br&gt;
checking the meter advance, the VAT rate for the date and the total. It's about ten sums that most&lt;br&gt;
people never start.&lt;/p&gt;

&lt;p&gt;Second Look does it in &lt;strong&gt;under two minutes per bill on a laptop CPU&lt;/strong&gt; (86 to 111 seconds end to end&lt;br&gt;
for the four demo bills). Roughly half of that is&lt;br&gt;
Gemma reading the bill, most of the rest is the usage forecast, and the checks themselves take a&lt;br&gt;
few milliseconds. You don't have to watch it; you come&lt;br&gt;
back to a verdict, and the only thing it ever asks of you is to look at a highlighted field.&lt;/p&gt;

&lt;p&gt;The bigger payoff is the &lt;em&gt;Reconciled&lt;/em&gt; verdict. It means you can stop thinking about that bill,&lt;br&gt;
because every line was recomputed from the published rates. &lt;em&gt;Not enough evidence&lt;/em&gt; is the honest&lt;br&gt;
version of "I'm not sure", with the exact field to check, so the lazy path never becomes the&lt;br&gt;
wrong one.&lt;/p&gt;

&lt;p&gt;I didn't time myself checking bills by hand, so I'm not quoting a speed-up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemma.&lt;/strong&gt; Gemma 4 E2B (&lt;code&gt;gemma4:e2b-it-qat&lt;/code&gt;) runs locally in Ollama, on the CPU. It does two jobs:
it reads the bill image into a strict schema, and it writes the plain-English explanation under a
guard. Experiment A measures it against Tesseract on 75 images, and Experiment D tries to trick it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TabPFN.&lt;/strong&gt; The TabPFN v2 regressor forecasts a 90% range for each billing period's usage from the
home's own smart-meter history, locally with telemetry off. Experiment C compares it with
TabPFN-TS and three naive baselines over 480 forecasts, and it wins on accuracy and interval width.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Render.&lt;/strong&gt; The demo front end is a Render static site deployed from the repository's
&lt;code&gt;render.yaml&lt;/code&gt; Blueprint. It replays recorded runs of the real pipeline, so anyone can see it
without installing a model.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Disclosure: I built this with an AI coding assistant (Claude Code), which wrote much of the code&lt;br&gt;
under my direction. Every number in this post comes from scripts in the repository and can be&lt;br&gt;
reproduced with &lt;code&gt;python -m eval.run_all&lt;/code&gt;. All bills shown are synthetic, from fictional suppliers.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Aniruddh Vijayvargia</dc:creator>
      <pubDate>Sun, 18 Oct 2026 15:42:18 +0000</pubDate>
      <link>https://dev.to/aniruddh_vijayvargia_abc0/-4476</link>
      <guid>https://dev.to/aniruddh_vijayvargia_abc0/-4476</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/aniruddh_vijayvargia_abc0/chhaap-a-local-ai-print-counter-for-neighbourhood-shops-3o1f" class="crayons-story__hidden-navigation-link"&gt;Chhaap: A Local AI Print Counter for Neighbourhood Shops&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/aniruddh_vijayvargia_abc0/chhaap-a-local-ai-print-counter-for-neighbourhood-shops-3o1f" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle Submission 💸&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/aniruddh_vijayvargia_abc0" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F4155390%2F856e0675-34e8-4d98-8545-1420ef6e8018.png" alt="aniruddh_vijayvargia_abc0 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/aniruddh_vijayvargia_abc0" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Aniruddh Vijayvargia
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Aniruddh Vijayvargia
                
                
              
              &lt;div id="story-author-preview-content-4872716" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/aniruddh_vijayvargia_abc0" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F4155390%2F856e0675-34e8-4d98-8545-1420ef6e8018.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Aniruddh Vijayvargia&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/aniruddh_vijayvargia_abc0/chhaap-a-local-ai-print-counter-for-neighbourhood-shops-3o1f" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 18&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/aniruddh_vijayvargia_abc0/chhaap-a-local-ai-print-counter-for-neighbourhood-shops-3o1f" id="article-link-4872716"&gt;
          Chhaap: A Local AI Print Counter for Neighbourhood Shops
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/hf26challenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;hf26challenge&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/aniruddh_vijayvargia_abc0/chhaap-a-local-ai-print-counter-for-neighbourhood-shops-3o1f" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;4&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/aniruddh_vijayvargia_abc0/chhaap-a-local-ai-print-counter-for-neighbourhood-shops-3o1f#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>ai</category>
      <category>productivity</category>
      <category>tools</category>
    </item>
    <item>
      <title>Chhaap: A Local AI Print Counter for Neighbourhood Shops</title>
      <dc:creator>Aniruddh Vijayvargia</dc:creator>
      <pubDate>Sun, 18 Oct 2026 15:41:51 +0000</pubDate>
      <link>https://dev.to/aniruddh_vijayvargia_abc0/chhaap-a-local-ai-print-counter-for-neighbourhood-shops-3o1f</link>
      <guid>https://dev.to/aniruddh_vijayvargia_abc0/chhaap-a-local-ai-print-counter-for-neighbourhood-shops-3o1f</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Chhaap turns scattered customer messages into reviewed print quotes—and keeps the work moving after the quote.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A print request rarely arrives as a complete specification. It arrives across messages: “500 cards,” “make it matte,” “both sides,” followed by a screenshot and a changed deadline. Someone has to assemble those details, ask what is missing, calculate a price, and remember what was agreed.&lt;/p&gt;

&lt;p&gt;Chhaap gives an independent print shop one workspace for that process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Paste a conversation or upload screenshots.&lt;/li&gt;
&lt;li&gt;Get AI suggestions for print specifications, missing information, and clarification questions.&lt;/li&gt;
&lt;li&gt;Review and confirm the details.&lt;/li&gt;
&lt;li&gt;Calculate a quote using the shop’s rate card.&lt;/li&gt;
&lt;li&gt;Record acceptance and track artwork approval, production, and manually recorded payments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The intended paying customer is a small print-shop owner who currently coordinates this work across messages, spreadsheets, and memory. A supported installation or managed hosting service is a potential business model; willingness to pay has not been validated.&lt;/p&gt;

&lt;p&gt;I designed the project around &lt;strong&gt;Aman Printworks, a fictional neighbourhood print shop&lt;/strong&gt;. Its customers, conversations, orders, and prices are sample data, not real customer research or revenue.&lt;/p&gt;

&lt;p&gt;Beautiful UI was a core requirement: paper-inspired surfaces, ink-like typography, restrained red accents, responsive layouts, and light and dark themes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://chhaap-ruby.vercel.app/" rel="noopener noreferrer"&gt;Explore Chhaap’s public visual preview&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The hosted site is a &lt;strong&gt;read-only visual preview&lt;/strong&gt; containing screenshots of the working local application. The controls inside those screenshots are not interactive.&lt;/p&gt;

&lt;p&gt;The complete application—including accounts, PostgreSQL, the background worker, and local AI inference—runs locally. Setup instructions are in the repository.&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%2Felj3u4u5ew2o2tpnc8ls.jpg" 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%2Felj3u4u5ew2o2tpnc8ls.jpg" alt="Chhaap’s print-shop workspace" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/ANIRUDDH-001/Chhaap" rel="noopener noreferrer"&gt;GitHub: ANIRUDDH-001/Chhaap&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Chhaap’s application code is available under the &lt;strong&gt;MIT license&lt;/strong&gt;. Model weights are distributed separately under their own license.&lt;/p&gt;

&lt;p&gt;The repository includes setup instructions, migrations, evaluation fixtures, tests, and review evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;The interface uses &lt;strong&gt;React, TypeScript, and Vite&lt;/strong&gt;. A &lt;strong&gt;FastAPI&lt;/strong&gt; backend handles business rules and persistence through &lt;strong&gt;SQLAlchemy and PostgreSQL&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For AI, Chhaap runs the open-weight &lt;strong&gt;Gemma 4 E4B&lt;/strong&gt; model locally through &lt;strong&gt;Ollama&lt;/strong&gt;. A separate worker processes extraction requests, with bounded concurrency and retries.&lt;/p&gt;

&lt;p&gt;The central design decision is simple: &lt;strong&gt;AI proposes; the owner confirms.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI suggestions stay separate from saved specifications. They cannot silently overwrite the order, set prices, issue quotes, accept work, or move money. Pricing uses deterministic server-side calculations, and issued quotes preserve the agreed rates, totals, and terms.&lt;/p&gt;

&lt;p&gt;I also built customer history, repeat orders, rate-card management, production tracking, reports, private screenshot storage, and data export.&lt;/p&gt;

&lt;p&gt;I tested the AI pipeline against &lt;strong&gt;60 labelled fictional cases&lt;/strong&gt;, including incomplete requests, corrections, screenshots, and adversarial inputs.&lt;/p&gt;

&lt;p&gt;The initial evaluation achieved &lt;strong&gt;97.46% accuracy on annotated text fields&lt;/strong&gt;, but &lt;strong&gt;84.78% overall&lt;/strong&gt;, below my proposed 90% target. Screenshot extraction and conflict detection were weaknesses. Those results informed subsequent fixes, but I have not rerun the complete revised evaluation, so I am not claiming a higher final score.&lt;/p&gt;

&lt;p&gt;That limitation reinforces the need for explicit human review.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ANIRUDDH-001/Chhaap/tree/main/eval" rel="noopener noreferrer"&gt;Evaluation fixtures and results&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the submission snapshot, verification included &lt;strong&gt;69 backend tests against PostgreSQL, 11 frontend tests, and a successful production build&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Codex assisted with planning, implementation, testing, and review. The repository records the resulting design decisions and verification evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;A small shop should be able to understand and control a tool that handles its customer conversations and prices.&lt;/p&gt;

&lt;p&gt;Open weights and local inference let Chhaap process requests without requiring a hosted model API. The shop can choose its hardware, inspect the integration, and avoid mandatory per-request API charges.&lt;/p&gt;

&lt;p&gt;Open application code makes the business rules inspectable too: how prices are calculated, how quotes are preserved, and where owner confirmation is required.&lt;/p&gt;

&lt;p&gt;It also makes failures useful. Publishing the evaluation exposes where extraction struggles and gives other developers concrete cases to reproduce, improve, or test with another model.&lt;/p&gt;

&lt;p&gt;For Chhaap, open innovation means the product can evolve beyond one developer or provider: another shop can adapt its rates, another contributor can improve extraction, and another deployment can replace the model while retaining the review workflow.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>Bahaana (बहाना): The AI That Predicts Your Excuses</title>
      <dc:creator>Aniruddh Vijayvargia</dc:creator>
      <pubDate>Tue, 06 Oct 2026 15:18:00 +0000</pubDate>
      <link>https://dev.to/aniruddh_vijayvargia_abc0/bahaana-bhaanaa-the-ai-that-predicts-your-excuses-i1a</link>
      <guid>https://dev.to/aniruddh_vijayvargia_abc0/bahaana-bhaanaa-the-ai-that-predicts-your-excuses-i1a</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week1-2026-10-05"&gt;Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Most of us have a reason for not going outside.&lt;/p&gt;

&lt;p&gt;Too hot.&lt;br&gt;&lt;br&gt;
Raining.&lt;br&gt;&lt;br&gt;
Busy.&lt;br&gt;&lt;br&gt;
Bad air.&lt;br&gt;&lt;br&gt;
Too tired.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bahaana asks a different question: was that actually true for you?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bahaana reads your own Google Fit step history and combines it with the weather forecast and modelled air quality from those days. It then uses &lt;strong&gt;TabPFN v2&lt;/strong&gt;, an open-weight tabular foundation model, to estimate how likely today is to be an active day.&lt;/p&gt;

&lt;p&gt;Then comes the interesting part: &lt;strong&gt;Excuse Court&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For each excuse, Bahaana tests two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Does the model's prediction change when that excuse is present today?&lt;/li&gt;
&lt;li&gt;Does your own history show that you actually became less active under that condition?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Only when the model and your history agree does Bahaana mark an excuse &lt;strong&gt;UPHELD&lt;/strong&gt;. Otherwise it can be &lt;strong&gt;OVERRULED&lt;/strong&gt; or &lt;strong&gt;UNCLEAR&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And then it stops talking.&lt;/p&gt;

&lt;p&gt;Press &lt;strong&gt;I'M GOING&lt;/strong&gt; and the screen becomes a 30-minute phone-away timer.&lt;/p&gt;

&lt;p&gt;Bahaana is for anyone who has ever told themselves:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"I'll go outside later."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://bahaana.onrender.com/" rel="noopener noreferrer"&gt;Try Bahaana live&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The public demo is precomputed, so it can be explored immediately without waiting for the model server.&lt;/p&gt;

&lt;p&gt;You can also bring your own Google Fit Takeout export and run the live prediction pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/ANIRUDDH-001/bahaana" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The repository contains the full prediction pipeline, feature engineering, Excuse Court logic, browser-side Takeout parser, API, tests, backtest results, and deployment configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;The core AI is &lt;strong&gt;TabPFN v2 by Prior Labs&lt;/strong&gt;, an open-weight tabular foundation model designed for prediction from structured historical data.&lt;/p&gt;

&lt;p&gt;Bahaana is built around it rather than using AI as a decorative layer.&lt;/p&gt;

&lt;p&gt;The pipeline is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google Fit history → causal features → TabPFN v2 → today's prediction → Excuse Court → phone-away action&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A few decisions were important:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Today's target is defined from the &lt;strong&gt;previous 28 days&lt;/strong&gt;, so today's activity never leaks into today's prediction.&lt;/li&gt;
&lt;li&gt;Weather uses the forecast that was available &lt;strong&gt;24 hours before the day being predicted&lt;/strong&gt;, rather than future observed weather.&lt;/li&gt;
&lt;li&gt;Air quality uses &lt;strong&gt;modelled CAMS PM2.5&lt;/strong&gt; from the previous day.&lt;/li&gt;
&lt;li&gt;Excuse sensitivity is tested on &lt;strong&gt;today's feature vector&lt;/strong&gt;, separately from historical evidence.&lt;/li&gt;
&lt;li&gt;Historical evidence uses &lt;strong&gt;7-day block bootstrap intervals&lt;/strong&gt; because neighbouring days are not independent.&lt;/li&gt;
&lt;li&gt;The browser parses the Google Fit export locally. The raw file and dates/location are not sent to the model server.&lt;/li&gt;
&lt;li&gt;The deployed frontend runs on &lt;strong&gt;Render&lt;/strong&gt;, while TabPFN inference runs on &lt;strong&gt;Modal&lt;/strong&gt;, because the model's memory requirements exceed Render's free 512 MB instance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also included an expanding-window backtest against simpler baselines instead of assuming that the foundation model must win. The results are exposed in the app's &lt;strong&gt;Under the hood&lt;/strong&gt; section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;A closed AI API could have produced a prediction, but that would miss the point of Bahaana.&lt;/p&gt;

&lt;p&gt;The most sensitive input here is someone's behavioural history. Using an open-weight model lets me keep the AI pipeline under my control, inspect exactly what is being sent to inference, and run the model independently instead of sending a personal history to a general-purpose closed AI service.&lt;/p&gt;

&lt;p&gt;Open tooling also made the architecture possible without a proprietary AI dependency:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TabPFN for prediction, Open-Meteo for weather and air quality, Vite/TypeScript in the browser, FastAPI for the API, and Render + Modal for deployment.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The important part is not just that the model is open.&lt;/p&gt;

&lt;p&gt;It is that &lt;strong&gt;the openness changes how the product can be designed&lt;/strong&gt;: the model is replaceable, the inference pipeline is inspectable, and the user's raw activity export does not need to become someone else's AI training input.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of TabPFN&lt;/strong&gt; — TabPFN v2 is the core prediction model and powers the personalized active-day prediction and Excuse Court analysis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Render&lt;/strong&gt; — Render hosts Bahaana's public frontend and serves the deployed product experience.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>I Built Kaagaz for My Father So Important Papers Stop Becoming Forgotten WhatsApp Messages</title>
      <dc:creator>Aniruddh Vijayvargia</dc:creator>
      <pubDate>Fri, 02 Oct 2026 13:44:05 +0000</pubDate>
      <link>https://dev.to/aniruddh_vijayvargia_abc0/i-built-kaagaz-for-my-father-so-important-papers-stop-becoming-forgotten-whatsapp-messages-1d7j</link>
      <guid>https://dev.to/aniruddh_vijayvargia_abc0/i-built-kaagaz-for-my-father-so-important-papers-stop-becoming-forgotten-whatsapp-messages-1d7j</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-weekend-2026-10-01"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Kaagaz — काग़ज़
&lt;/h3&gt;

&lt;p&gt;My father handles a lot of our household paperwork: electricity bills, school fees, insurance renewals, property tax notices, certificates, and increasingly, important messages arriving over WhatsApp or SMS.&lt;/p&gt;

&lt;p&gt;The problem isn't that these papers are difficult to read. The problem is remembering &lt;strong&gt;what actually needs to happen next&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;Kaagaz&lt;/strong&gt; for him.&lt;/p&gt;

&lt;p&gt;You can show Kaagaz a paper, screenshot, or message, or simply tell it what you received in Hindi, Hinglish, or English.&lt;/p&gt;

&lt;p&gt;Kaagaz:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;understands what the document is&lt;/li&gt;
&lt;li&gt;extracts the amount, deadline, required action, and consequence&lt;/li&gt;
&lt;li&gt;shows the exact evidence it used&lt;/li&gt;
&lt;li&gt;explains it in simple language&lt;/li&gt;
&lt;li&gt;asks for confirmation before remembering anything&lt;/li&gt;
&lt;li&gt;reminds you 30, 7, and 1 day before the deadline&lt;/li&gt;
&lt;li&gt;tells the son when an important reminder slips&lt;/li&gt;
&lt;li&gt;detects common scam signals in suspicious messages&lt;/li&gt;
&lt;li&gt;offers to carry yearly renewals into the following year without inventing the next year's amount&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The product loop is deliberately simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understand → Confirm → Remember → Follow through → Protect&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The goal wasn't to build another chatbot. It was to build something my father could actually use when a piece of paper or message lands in front of him.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live:&lt;/strong&gt; &lt;a href="https://kaagaz-bx24.onrender.com/" rel="noopener noreferrer"&gt;https://kaagaz-bx24.onrender.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The public demo uses &lt;strong&gt;fictional sample papers only&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; &lt;a href="https://kaagaz-bx24.onrender.com/how.html" rel="noopener noreferrer"&gt;https://kaagaz-bx24.onrender.com/how.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/ANIRUDDH-001/Kaagaz" rel="noopener noreferrer"&gt;https://github.com/ANIRUDDH-001/Kaagaz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The repository contains the complete application, evaluation suite, deployment configuration, Temporal workflows, reminder worker, and local/private inference setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;Open-source AI is at the core of Kaagaz.&lt;/p&gt;

&lt;p&gt;The main reasoning layer is &lt;strong&gt;Gemma 4&lt;/strong&gt;. The public demo uses &lt;strong&gt;Gemma 4 26B&lt;/strong&gt;, while the private family mode can run &lt;strong&gt;Gemma 4 E4B locally through Ollama&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That distinction is important.&lt;/p&gt;

&lt;p&gt;In public mode, a user can try the full application without setting up a local model.&lt;/p&gt;

&lt;p&gt;In private mode, the same application can run the document understanding locally so that raw family papers and audio do not need to leave the family's machine.&lt;/p&gt;

&lt;p&gt;For voice input, I use &lt;strong&gt;ElevenLabs Scribe v2&lt;/strong&gt; in the public deployment and &lt;strong&gt;Whisper large-v3-turbo&lt;/strong&gt; locally in private mode.&lt;/p&gt;

&lt;p&gt;For readbacks, Kaagaz uses &lt;strong&gt;ElevenLabs multilingual_v2&lt;/strong&gt;, with browser speech as the private-mode fallback.&lt;/p&gt;

&lt;p&gt;The backend is built with &lt;strong&gt;FastAPI and Python&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MongoDB Atlas&lt;/strong&gt; stores the confirmed structured information: obligations, notification inbox state, and household state. Raw document photos and audio are not stored in MongoDB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Temporal&lt;/strong&gt; runs the reminder workflows. Each obligation gets its own durable workflow, allowing Kaagaz to wait for dates months in the future, retry notification failures, and handle actions such as done, snooze, repeat, and date updates.&lt;/p&gt;

&lt;p&gt;Because the API is hosted on Render's free tier and can sleep, a lightweight &lt;strong&gt;GitHub Actions&lt;/strong&gt; worker periodically wakes up and drains due reminder work. That means the reminder system doesn't depend on the web process staying awake continuously.&lt;/p&gt;

&lt;p&gt;The frontend is a lightweight mobile-friendly PWA with camera, microphone, push notifications, language switching, and Papa/Son roles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;This project is personal, so privacy and control matter more than simply getting an AI response.&lt;/p&gt;

&lt;p&gt;An important household paper can contain an address, account details, payment information, dates, or other sensitive information. With a closed-only architecture, I would have to send that information to a third-party model every time.&lt;/p&gt;

&lt;p&gt;Open-weight models gave me another option.&lt;/p&gt;

&lt;p&gt;With Gemma running locally, the AI part of Kaagaz can stay on the family's own machine. I can also swap model sizes depending on the hardware: a smaller model for constrained devices, or a larger one when quality matters more.&lt;/p&gt;

&lt;p&gt;That flexibility changed the architecture of the project.&lt;/p&gt;

&lt;p&gt;Open models also made it possible to design the AI layer around &lt;strong&gt;our own validation rules&lt;/strong&gt; rather than treating the model's output as automatically trustworthy.&lt;/p&gt;

&lt;p&gt;For example, Kaagaz doesn't simply accept an extracted date or amount. It keeps the evidence, highlights unsupported values, and requires confirmation before anything becomes a reminder.&lt;/p&gt;

&lt;p&gt;For a family paperwork assistant, that control is more important than having a generic AI chat experience.&lt;/p&gt;

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

&lt;p&gt;The hardest part wasn't making an AI understand a document.&lt;/p&gt;

&lt;p&gt;It was deciding what the AI &lt;strong&gt;must never be allowed to assume&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A reminder system amplifies mistakes: if an AI invents a deadline, that mistake can become a notification, then a stored obligation, then a missed payment.&lt;/p&gt;

&lt;p&gt;So I ended up building several safeguards around the model:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Evidence before extraction.&lt;br&gt;&lt;br&gt;
Confirmation before persistence.&lt;br&gt;&lt;br&gt;
Deterministic validation before scheduling.&lt;br&gt;&lt;br&gt;
Durable workflows after scheduling.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I also learned that scam detection should not claim that something is "safe." Kaagaz instead shows the specific warning signs it found and lets the user send the warning to their son.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evaluation
&lt;/h2&gt;

&lt;p&gt;I built a controlled evaluation set containing &lt;strong&gt;26 fictional documents and messages&lt;/strong&gt;, including genuine household paperwork and scam examples, with multiple simulated image conditions plus Hindi, Hinglish, and English instructions.&lt;/p&gt;

&lt;p&gt;The latest documented Gemma evaluation achieved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;412/412&lt;/strong&gt; paper fields exactly correct&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;0&lt;/strong&gt; wrong amount/date errors left unhighlighted&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;24/24&lt;/strong&gt; scam messages correctly red-warned&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;0/80&lt;/strong&gt; genuine papers incorrectly red-warned&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;20/20&lt;/strong&gt; typed instructions correct&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;8/8&lt;/strong&gt; synthetic spoken clips correct&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;9.7s&lt;/strong&gt; median end-to-end AI time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;13.4s&lt;/strong&gt; p90&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are controlled, synthetic evaluation results, not a claim of real-world accuracy. Real crumpled documents and more sophisticated scams can still be harder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;I am entering the categories that Kaagaz genuinely uses:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Use of Gemma&lt;/strong&gt; — Gemma 4 is the core document-understanding model, with both hosted and local inference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Use of Render&lt;/strong&gt; — Render hosts the deployed Kaagaz application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Use of ElevenLabs&lt;/strong&gt; — Scribe v2 handles public speech-to-text and ElevenLabs multilingual_v2 provides spoken readbacks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Use of MongoDB Atlas&lt;/strong&gt; — Atlas is the application's persistent data layer for confirmed obligations, notification state, and household data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Use of Temporal&lt;/strong&gt; — Temporal provides durable, retryable reminder workflows that can wait months for future deadlines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Use of GitHub Copilot&lt;/strong&gt; — GitHub Actions automates the scheduled reminder worker used by the deployed system.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>hf26challenge</category>
    </item>
  </channel>
</rss>
