尚未检测到更新。GitHub 发布版本后会显示在这里。
Receipt photo in, checked expense row out. Workers AI vision with sums verified in code. Live: receipts.allforone.co.in
翻译准备中
正在加载完整 README。
查看完整 README ↗A public, clickable demo. A visitor uploads or snaps a photo of a receipt or tax invoice and gets back a clean expense row: vendor, date (ISO), invoice number, line items, subtotal, tax (GST, VAT or sales tax, with a CGST, SGST and IGST split for Indian invoices), total, currency, payment method, an expense category and a 0 to 1 confidence per field, plus a list of what it could not read. The page keeps a running table of the visitor's receipts in the browser (localStorage), with per-cell edit and CSV download. Every page carries the banner "Demo. Upload your own receipt or try a sample. Images are not stored. Built by Eklavya Shetty" linking to eklavyashetty.com. Four fictional sample receipts can be clicked instead of uploading.
Built by Eklavya Shetty. Style, abuse caps and fonts follow the sibling demo ivy-enquiry-agent (Martel and Martel Sans).
@cf/google/gemma-4-26b-a4b-it (MODEL in wrangler.jsonc). Picked from a four-model bench: see BENCH.md. No API keys; the AI binding does it.src/worker.js, not prompt hopes (normalise then judge):
| Limit | Default | Var |
|---|---|---|
Receipts per visitor per day (cookie rr_vid, else IP) | 10 | VISITOR_DAILY_MAX |
| Receipts per IP per day (backstop for cookie clearing) | 30 | IP_DAILY_MAX |
| Receipts per day, all visitors | 400 | GLOBAL_DAILY_MAX |
| Image size, server side | 4 MB | MAX_IMAGE_BYTES |
Counters live in a small Durable Object (Counter). Over a cap the Worker returns a fixed polite message (HTTP 429) and does not call the model. If the model call fails, the receipt is given back to the visitor's count. Header x-owner-key equal to the OWNER_KEY secret bypasses the three counters (not the size limit) and lets the owner pick a model with x-model and see the raw model text, which is how the bench runs. If OWNER_KEY is unset, nobody is the owner.
npm install
copy .dev.vars.example .dev.vars (set OWNER_KEY to any local value; git-ignored)
npx wrangler dev --port 8812 (page at http://127.0.0.1:8812/)
Workers AI is always remote, even in wrangler dev: you must be logged in (npx wrangler login) and it uses a little of the account's allocation. With several Cloudflare accounts, set CLOUDFLARE_ACCOUNT_ID=8f5947a7b20b2cad2137ae8d9b187094 first. Nothing here was run with --remote.
python test/make_receipts.py rebuilds the 12 synthetic receipts (HTML to PNG with headless Edge, then Pillow degradation) and their ground truth in test/truth/. All businesses and tax numbers are fictional.node test/run-tests.mjs accuracy scores field-level accuracy (vendor, date, total, tax, currency), the wrong-total and blurry cases, a non-receipt, an injection attempt and the 4 MB reject. Needs the dev server on 8812 with default limits and an owner key in .dev.vars.node test/run-tests.mjs caps checks all three caps, the owner bypass and the size reject. Start the server with tiny limits first:
npx wrangler dev --port 8812 --var VISITOR_DAILY_MAX:3 --var IP_DAILY_MAX:4 --var GLOBAL_DAILY_MAX:8 (delete .wrangler/state/v3/do first for a clean counter).node test/bench.mjs <model> ... benchmarks models through the Worker; node test/make-reports.mjs rewrites BENCH.md and TEST-REPORT.md from the saved results.TEST-REPORT.md, BENCH.md.npx wrangler deploy
printf '%s' "$(cat .owner-key)" | npx wrangler secret put OWNER_KEY (Git Bash; never pipe from PowerShell, it adds a CRLF)
wrangler.jsonc already names the Worker receipts-reader-demo, turns workers_dev on and declares the custom domain receipts.allforone.co.in, so the first deploy will also create that DNS record on the account's zone. Remove the routes line if you would rather start on the workers.dev address only. The CSP lets eklavyashetty.com and its subdomains embed the page in an iframe.
src/worker.js: the reader, the checks, the Counter Durable Object, limits and routerpublic/index.html: the whole UI (upload, camera, samples, result slip, table, CSV)public/samples/: the four built-in samples (copies of files from test/receipts/)test/: generators, 12 test receipts and truth, bench and test scripts, saved resultsBENCH.md, TEST-REPORT.md, wrangler.jsonc, .gitignore, .dev.vars.example.owner-key (gitignored, never print it). Send it as header x-owner-key to skip the caps.