statementsetu / README.md
perceptron01's picture
Update README.md
436370d verified
|
Raw
History Blame Contribute Delete
5.84 kB

A newer version of the Gradio SDK is available: 6.19.0

Upgrade
metadata
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

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