Skip to main content

Financial statement PDF extraction agent

Project description

Financial PDF Extraction Agent (v2)

CI Release

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 runs ruff + pytest across Python 3.11 / 3.12 / 3.13 in parallel, with pip caching. A single all-green check gates merges; main is branch-protected, so broken code cannot merge.
  • CD (.github/workflows/release.yml) — pushing a vX.Y.Z tag 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)

  1. ✅ Walking skeleton: all stages thin but connected
  2. ✅ Geometry fixer: two-up A3 page split (Airtel, Reliance)
  3. ✅ IFRS locator vocabulary ("profit OR loss", comprehensive-income cues)
  4. Second extractor (Docling/TableFormer) + cross-extractor voting
  5. Unit detection (crores/lakhs/millions) + vision-LLM third voter
  6. Bank/NBFC schema variant (HDFC), OCR path for scanned pages

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

akshu_finagent-0.2.0.tar.gz (43.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

akshu_finagent-0.2.0-py3-none-any.whl (47.7 kB view details)

Uploaded Python 3

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

Hashes for akshu_finagent-0.2.0.tar.gz
Algorithm Hash digest
SHA256 83fea4db0a09bcf862096ecc2882af2427a4988be41ec871d7e771d529f71220
MD5 114e8bb3dd1d071bf5ae73572dbee118
BLAKE2b-256 102f65e84f534484baffbe3ecd5235b408392396c11761e2295fd4cd3af80da1

See more details on using hashes here.

Provenance

The following attestation bundles were made for akshu_finagent-0.2.0.tar.gz:

Publisher: release.yml on Akshu24Tech/financial-pdf-extraction-agent

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for akshu_finagent-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 661ff6c758935daa155407f76649e5b6e77978846364fd6ab43505bec1e47154
MD5 8a8c5ee614ecccb3854f29ef271a5f04
BLAKE2b-256 ddbad38e185b190ed557fa638bc84ddbea3fe17b61615f32e4d9d1541c37549f

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page