Financial statement PDF extraction agent
Project description
Financial PDF Extraction Agent (v2)
Give it any company's annual-report PDF. It finds the financial statements, pulls out the key numbers, proves each one is correct, and writes a tidy Excel where every value carries its own receipt (page number, the exact label it came from, and which checks it passed).
The one idea behind it
Accuracy comes from verification, not extraction.
Reading numbers off a PDF is easy to get almost right and very hard to get exactly right — tables are borderless, layouts differ per company, a "5" in the wrong column ruins everything. So this tool doesn't trust what it reads.
Financial statements are self-verifying. They obey rules:
- Assets = Liabilities + Equity
- Current + Non-current = Total
- The closing cash in the cash-flow statement equals cash on the balance sheet
So every extracted number is checked against these rules. A value that passes a rule is VERIFIED. A value that breaks one is FLAGGED for a human. We never hand over a confident-but-wrong number.
How it works — 7 stages, like an assembly line
PDF
│
▼
┌─────────────┐ What kind of PDF is this? Page sizes, orientation,
│ 1 PROFILE │ and whether each page has readable text.
└─────────────┘
│
▼
┌─────────────┐ Some reports print two pages side-by-side on one wide
│ 2 GEOMETRY │ sheet. Split those back into single logical pages.
└─────────────┘
│
▼
┌─────────────┐ Which pages ARE the Balance Sheet / P&L / Cash Flow?
│ 3 LOCATE │ (and prefer the consolidated version)
└─────────────┘
│
▼
┌─────────────┐ Read the chosen pages line by line: "label … numbers".
│ 4 EXTRACT │ Borderless-table safe — rebuilds rows from coordinates.
└─────────────┘
│
▼
┌─────────────┐ Clean the numbers and match each label to our standard
│ 5 NORMALIZE │ vocabulary ("Turnover" and "Net sales" both -> revenue).
└─────────────┘
│
▼
┌─────────────┐ Prove the numbers using accounting identities.
│ 6 VALIDATE │ -> VERIFIED / PROBABLE / FLAGGED / MISSING
└─────────────┘
│
▼
┌─────────────┐ A number the report never printed but the identities
│ 6b DERIVE │ pin down exactly? Compute it. Mark it DERIVED.
└─────────────┘
│
▼
┌─────────────┐ Excel: value + status + page + matched label + checks.
│ 7 WRITE │ Colour-coded so you see trust level at a glance.
└─────────────┘
│
▼
metrics.xlsx
Status colours in the Excel: 🟢 VERIFIED · 🟡 PROBABLE · 🔴 FLAGGED · 🔵 DERIVED · ⬜ MISSING.
Run it
# one report
.venv\Scripts\python.exe finagent_single.py test_pdfs\TCS_2024-2025.pdf
# scorecard across all 12 test reports
.venv\Scripts\python.exe benchmark.py
Output lands in output\<Company>_metrics.xlsx. All commands use the project
venv (.venv). First-time setup: pip install -r requirements.txt.
Install a released build
The project is packaged as a wheel and published on a version tag. Grab a build from the Releases page and install it:
pip install finagent-0.1.0-py3-none-any.whl
(TestPyPI publishing via OIDC trusted publishing is being wired up — once live,
pip install -i https://test.pypi.org/simple/ finagent will work directly.)
CI/CD
This repo doubles as a hands-on CI/CD build-out (tracked level-by-level in
WORKLOG.md):
- CI (
.github/workflows/ci.yml) — every push and PR runsruff+pytestacross Python 3.11 / 3.12 / 3.13 in parallel, with pip caching. A singleall-greencheck gates merges;mainis branch-protected, so broken code cannot merge. - CD (
.github/workflows/release.yml) — pushing avX.Y.Ztag builds the wheel + sdist and publishes a GitHub Release with the artifacts attached.
Cut a release:
git tag v0.1.0
git push origin v0.1.0
Two ways to read the code (same logic, your choice)
| What | When to read it | |
|---|---|---|
| Single file | finagent_single.py |
You want to understand or share the whole thing top-to-bottom. The 7 stages appear in pipeline order, each in its own clearly-marked section. |
| Package | finagent/ (one file per stage) |
You're maintaining or extending it. Smaller files, one responsibility each. |
Both produce identical results. The package is the source of truth; the single file is a flattened, portable build of it.
📖 Want the full, plain-language walkthrough of every function and why it works the way it does? See
ARCHITECTURE.md. It's the guide to use when explaining this project to anyone.
Package map
| File | Stage | Job |
|---|---|---|
finagent/profiler.py |
1 | Per-page: text quality, size, orientation (fast, via pypdf) |
finagent/geometry.py |
2 | Split two-up A3 sheets into single logical pages |
finagent/locator.py |
3 | Find + classify statement pages (consolidated BS / PL / CF) |
finagent/extractors/geometric.py |
4 | Line-based extraction, borderless-table safe (pdfplumber) |
finagent/normalizer.py |
5 | Parse numbers, strip note columns, fuzzy-match labels to schema |
finagent/validator.py |
6 | Voting + accounting identities + cross-statement ties |
finagent/deriver.py |
6b | Fill numbers the report omitted but the identities fix exactly |
finagent/writer.py |
7 | Excel with value, status, page citation, matched label, checks |
finagent/schema.py |
— | The canonical metric vocabulary + label synonyms |
finagent/pipeline.py |
— | Glue that runs stages 1→7 in order |
What's in this folder
finagent_single.py the whole agent in one file (start here to understand it)
finagent/ the same logic as a package, one file per stage
schema is shared ── the vocabulary every stage speaks
benchmark.py scorecard over every test PDF
golden_check.py checks extracted values against hand-verified answers
render_pages.py renders statement pages to PNGs (for eyeballing)
requirements.txt dependencies: pypdf, pdfplumber, rapidfuzz, openpyxl
test_pdfs/ 12 deliberately-different real annual reports
golden/ hand-verified correct answers for grading
output/ generated Excel files + rendered pages
scratch/ throwaway debug scripts (safe to ignore)
graphify-out/ generated knowledge-graph cache (safe to ignore)
The test set (chosen to break things on purpose)
8+ deliberately-different reports in test_pdfs/: Adani (683 pages), Airtel
(A3 two-up layout), BMW (landscape, in EUR), HDFC (a bank, different schema),
Newgen (small-cap), Reliance (A3 two-up), TCS (clean baseline), Wilmar
(foreign report). If it works on all of these, it generalises.
Roadmap (improve only what the benchmark proves)
- ✅ Walking skeleton: all stages thin but connected
- ✅ Geometry fixer: two-up A3 page split (Airtel, Reliance)
- ✅ IFRS locator vocabulary ("profit OR loss", comprehensive-income cues)
- Second extractor (Docling/TableFormer) + cross-extractor voting
- Unit detection (crores/lakhs/millions) + vision-LLM third voter
- Bank/NBFC schema variant (HDFC), OCR path for scanned pages
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file akshu_finagent-0.2.0.tar.gz.
File metadata
- Download URL: akshu_finagent-0.2.0.tar.gz
- Upload date:
- Size: 43.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
83fea4db0a09bcf862096ecc2882af2427a4988be41ec871d7e771d529f71220
|
|
| MD5 |
114e8bb3dd1d071bf5ae73572dbee118
|
|
| BLAKE2b-256 |
102f65e84f534484baffbe3ecd5235b408392396c11761e2295fd4cd3af80da1
|
Provenance
The following attestation bundles were made for akshu_finagent-0.2.0.tar.gz:
Publisher:
release.yml on Akshu24Tech/financial-pdf-extraction-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
akshu_finagent-0.2.0.tar.gz -
Subject digest:
83fea4db0a09bcf862096ecc2882af2427a4988be41ec871d7e771d529f71220 - Sigstore transparency entry: 1871392605
- Sigstore integration time:
-
Permalink:
Akshu24Tech/financial-pdf-extraction-agent@b923ef4573064d0b065707ff24efe6f5e9446667 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Akshu24Tech
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b923ef4573064d0b065707ff24efe6f5e9446667 -
Trigger Event:
push
-
Statement type:
File details
Details for the file akshu_finagent-0.2.0-py3-none-any.whl.
File metadata
- Download URL: akshu_finagent-0.2.0-py3-none-any.whl
- Upload date:
- Size: 47.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
661ff6c758935daa155407f76649e5b6e77978846364fd6ab43505bec1e47154
|
|
| MD5 |
8a8c5ee614ecccb3854f29ef271a5f04
|
|
| BLAKE2b-256 |
ddbad38e185b190ed557fa638bc84ddbea3fe17b61615f32e4d9d1541c37549f
|
Provenance
The following attestation bundles were made for akshu_finagent-0.2.0-py3-none-any.whl:
Publisher:
release.yml on Akshu24Tech/financial-pdf-extraction-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
akshu_finagent-0.2.0-py3-none-any.whl -
Subject digest:
661ff6c758935daa155407f76649e5b6e77978846364fd6ab43505bec1e47154 - Sigstore transparency entry: 1871392667
- Sigstore integration time:
-
Permalink:
Akshu24Tech/financial-pdf-extraction-agent@b923ef4573064d0b065707ff24efe6f5e9446667 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Akshu24Tech
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b923ef4573064d0b065707ff24efe6f5e9446667 -
Trigger Event:
push
-
Statement type: