Spaces:
Sleeping
A newer version of the Gradio SDK is available: 6.19.0
title: StatementSetu
emoji: ๐งพ
colorFrom: blue
colorTo: indigo
sdk: gradio
sdk_version: 6.18.0
python_version: 3.12.12
app_file: app.py
pinned: false
license: mit
tags:
- backyard-ai
- build-small-hackathon
- openbmb
- minicpm
- minicpm-v
- accounting
- tally
- india
- document-ai
- track:backyard
- sponsor:openbmb
- achievement:offgrid
- achievement:llama
short_description: Bank statements to Tally vouchers in minutes
๐งพ StatementSetu โ Bank Statement โ Tally for CA firms
Track: Backyard AI ยท Sponsor prize target: OpenBMB MiniCPM
Small Chartered Accountant (CA) firms in India manually re-type client bank statements into Tally accounting software โ a 2-hour job per statement. StatementSetu turns an uploaded bank statement (PDF or photo) into categorized, balance-reconciled, editable accounting entries and exports a Tally-importable XML + Excel file. The 2-hour job becomes ~5 minutes.
Built for Anil, a CA in Kanpur ๐ฎ๐ณ โ a real person with a real, boring, error-prone task. (Backyard AI track.)
Why this is trustworthy: the math checks itself โ
The single most differentiating decision in this project is running-balance reconciliation. For every consecutive pair of rows we recompute the expected balance:
expected_balance[i] = balance[i-1] โ debit[i] + credit[i]
(The sign convention is auto-detected from the first rows โ some banks print it
inverted.) If |expected โ printed| > 0.01, both rows are flagged for review.
The UI shows a banner like "โ
39/39 rows reconciled against printed
balances". This converts "the AI might hallucinate" into "the arithmetic
verifies itself" โ exactly what wins a CA's trust.
We also validate: dates parse and are monotonically non-decreasing, each row has exactly one of debit/credit, and the category is always from a fixed closed set.
Models โ OpenBMB MiniCPM-first
| Job | Model | Params | Fallback |
|---|---|---|---|
| Vision extraction (scans/photos) | openbmb/MiniCPM-V-4.6 |
~8B | Qwen/Qwen2.5-VL-7B-Instruct |
| Text categorization | openbmb/MiniCPM3-4B |
~4B | Qwen/Qwen3-4B-Instruct |
MiniCPM-V-4.6 (8B) + MiniCPM3-4B (4B) = 12B total โ well under the 32B cap โ
MiniCPM-V-4.6 is the newest MiniCPM-V and is transformers-native (standard
AutoModelForImageTextToTextAPI), so it loads cleanly on currenttransformersโ unlike the older 2_6 which needed a custom.chat()method.
- Digital PDFs use no model at all (pdfplumber text-layer extraction) โ free, fast, zero GPU.
- A rules layer classifies the obvious majority of transactions before any model call, cutting GPU time ~60%. On the bundled digital sample it classifies 40/40 transactions with zero GPU.
- Only rule-misses go to the MiniCPM text model, batched 20 per call.
- Vision extraction runs inside a single
@spaces.GPUcall per document (pages looped inside the call) to avoid repeated cold starts and quota burn.
Anything the model is unsure about (< 0.5 confidence) or any off-list category is
forced to Suspense / Unclassified โ the tool says "I don't know" rather
than being confidently wrong.
How it works (pipeline)
Upload (PDF/JPG/PNG)
โ Extraction : pdfplumber (digital) OR MiniCPM-V (scan/photo)
โ Validation : running-balance reconciliation + date/amount checks
โ Categorization : rules layer first, MiniCPM text model for the rest
โ Review UI : editable table; fix any category in seconds
โ Export : Tally XML (beta) + Excel (.xlsx) + summary stats
Run locally
pip install -r requirements.txt
python samples/generate_samples.py # builds the bundled sample statements
python app.py # open the printed local URL
Then click "Try a bundled sample" โ Sample 1 (digital PDF) โ Process to see a categorized, reconciled table in a couple of seconds and download Excel โ no upload needed.
Tests
pytest
27 deterministic tests cover extraction (40/40 exact match vs ground truth), balance reconciliation (incl. corrupted-row detection), multi-format date parsing, the rules layer, the closed-set guarantee, well-formed balanced Tally XML, and the Excel export. Vision-extraction accuracy is checked manually against the noisy scan fixture (record the number here, e.g. "38/40 rows correct on the noisy scan").
Project layout
app.py Gradio UI + orchestration
extraction.py pdfplumber path + MiniCPM-V vision path
categorize.py rules dict + MiniCPM text-model batch call
validate.py balance reconciliation + date/amount checks
tally_export.py Tally import XML generation
excel_export.py openpyxl .xlsx export
constants.py closed ledger-category list + helpers
samples/ generator + bundled sample statements + ground-truth JSON
tests/test_pipeline.py
Tally import
In Tally: Gateway of Tally โ Import Data โ Vouchers, select the .xml.
Tally's XML sign conventions are notoriously fiddly, so the XML is labelled
beta; the Excel export is the zero-risk path and also works with common
Excel-to-Tally utilities.
Privacy
No real bank data is used. The bundled samples are synthetic (generated by
samples/generate_samples.py). The Space stores nothing โ no DB, no auth, no
persistence.
Submission links
- ๐ค Live Space: https://huggingface.co/spaces/build-small-hackathon/statementsetu
- ๐ฅ Demo video: https://drive.google.com/file/d/1BWeGu5ilzGpJjMojouWZ01ZIZ8eha4wL/view?usp=sharing
- ๐ฃ Social post (LinkedIn): https://www.linkedin.com/posts/aman-maurya-2a394924b_buildsmallhackathon-minicpm-openbmb-ugcPost-7472064492315762689-kAC3/