statementsetu / README.md
perceptron01's picture
Update README.md
436370d verified
|
Raw
History Blame Contribute Delete
5.84 kB
---
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/