--- 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 > `AutoModelForImageTextToText` API), so it loads cleanly on current > `transformers` โ€” 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.GPU` call 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 ```bash 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 ```bash 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/