AI Bank Statement Automation: A Multi-Harness Notebook Stack for Parsing PDFs Locally
AI Bank Statement Document Automation By LLM model and Personal Finanical Analysis
At a glance
- What is it?
- A Jupyter-first project that chains YOLO layout detection, OCR and local LLMs to turn bank statement PDFs into structured financial data, offered in three parallel agent harnesses. The README is detailed on architecture and thin on setup, so adoption depends on how much you want to read the repository layout yourself.
- Who is it for?
- Adopt this if you already run LM Studio or Ollama, have a 9B-plus model with 32K context available, and want to read a repository rather than a manual. Do not adopt it if you need a supported extraction product, a published accuracy figure, or a single documented way to run the pipeline.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 44 days ago.
- What is it written in?
- Mainly Jupyter Notebook, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What the pipeline is meant to replace
Bank statement PDFs are a specific kind of hostile input. The text layer is often absent or scrambled, tables span page breaks, and the same institution changes its layout between statement periods. The project targets that gap: it takes a PDF, detects layout regions with YOLO, runs OCR over them, and asks an LLM to turn the result into structured records. The stated outputs are income and expense categorization, trend analysis, and natural language querying over the extracted data. The intended user is a developer comfortable with Python 3.12, Docker, and a local inference server, not an accountant looking for a desktop tool. The repository is a Jupyter Notebook project at its root, with a FastAPI backend, a React SPA and three agent harnesses layered around it. That breadth is the first thing to weigh: the README describes a full-stack application and a research notebook in the same breath.
Three harnesses, three ways to run the same workflow
The design choice that defines this project is running one bank-statement workflow through three separate agent frameworks. CrewAI is the baseline and lives in backend/app/core plus agents/crewai, driven from a Jupyter notebook. Deep Agents uses the LangChain deepagents SDK under agents/deep-agents, with its own tools, skills, tests and a run_e2e.py entrypoint. Hermes runs in a Docker sandbox with a config.yaml and its own skills directory. The README is explicit that skills are copied per harness and there is no auto-sync, so a fix to the bank-statement-parsing skill in one tree does not reach the others. That is a real maintenance cost, not a stylistic one. It also means the three paths can drift in behavior, and the documentation does not state which harness is authoritative. My reading is that the multi-harness layout is an experiment in comparing agent frameworks on identical inputs, with shared samples in data/, rather than a set of interchangeable production options.
PII redaction before embedding, and why the order matters
The RAG path has one design decision worth calling out. According to the README, PII is redacted before embedding into the vector database, which is Qdrant or Chroma. In the common alternative, you embed first and filter later, which leaves account numbers and names sitting in vector storage and in whatever backup captures it. Doing the redaction upstream means the vector store never holds the raw identifiers. The trade-off is that any retrieval question phrased around a redacted entity will not match, so the query layer has to work with the redacted representation. The project provides a pii-handling skill alongside rag-query-handling and output-format skills, which suggests redaction is treated as a pipeline stage with its own domain logic rather than a regex pass. The README does not describe the redaction rules themselves, so how aggressive or how complete that stage is cannot be confirmed from the material.
Local model constraints the README states plainly
The most useful part of the documentation is the section on local LLMs, because it sets expectations rather than promising them. It recommends 9B parameters or more, naming Qwen2.5-14B, Qwen3-27B, Gemma-2-9B and Llama-3.1-8B as examples, and warns that smaller models reduce quality. It asks for 16K context at minimum and 32K as the recommended figure, noting that low context drops agent instructions, which is a failure mode that shows up as silently missing steps rather than an error. It also states that local models often fail strict JSON, and suggests preferring Markdown reports and post-processing with a second call or the instructor library. That is an honest admission of a limitation and it shapes the output-format skill. Anyone planning to run this on an 8GB consumer GPU should treat the model-size guidance as a hard floor rather than a suggestion.
Getting it running: what the material actually gives you
Setup instructions are the weak point. The README describes a Docker Compose stack in infra/docker-compose.yml covering PostgreSQL, Redis, Qdrant, the API, a worker and the web frontend, with an override file for development bind-mounts and a .env.example as the environment template. The API image is infra/api.Dockerfile, shared between API and worker. Dependencies are pinned in api/requirements.txt for the service and requirements.txt for the CrewAI stack, and database migrations run through Alembic. What the README does not provide is the command sequence: there is no docker compose up line, no migration command, no statement of which environment variables in .env.example are required versus optional. The one concrete invocation it does show is truncated at the code fence, ending at cd agents/deep with the rest cut off. The Deep Agents harness is described as runnable from a local .venv via run_e2e.py, and Hermes as Hermes CLI plus Docker only. In practice, expect to read infra/.env.example and agents/deep-agents/run_e2e.py before you can start anything, and treat the Compose file as the real setup document.
Where this is the wrong tool
This project carries no released versions, no accuracy figures and no benchmark for extraction quality on real statements. The only sample named in the repository layout is Dummy-Bank-Statement.pdf, which tells you the pipeline is validated against a synthetic document, at least in what the material shows. If your use case requires auditable extraction accuracy across many institutions and layouts, that is an unknown you would have to establish yourself. The multi-harness structure compounds this: three skill trees with no sync means three places for behavior to diverge, and the README marks the harnesses as experimental. The GPU claim in the feature list, under 2x build time versus CPU, is about build time for PyTorch and LLM inference, not about extraction accuracy, and no measurement is shown. Finally, the project assumes you can run a 9B-plus model locally or pay for a hosted one through LiteLLM. If neither fits, the pipeline's core step has no fallback described.
How it differs from a document AI service
The obvious alternative is a hosted document extraction service, where you upload a PDF and receive structured fields through an API, with the vendor owning layout models and accuracy targets. The difference in approach is where the intelligence sits. Here, layout detection is YOLO, text recovery is OCR, and the structuring step is a general-purpose LLM you supply through LiteLLM, which the README lists as covering LM Studio, Ollama, OpenAI and DeepSeek among others. That means the extraction logic is inspectable and the data can stay on your hardware, which matters for statement data. It also means you own the failure modes: a local model that emits malformed JSON, a context window that drops instructions, or a layout the YOLO detector has not seen. A hosted service hides those problems behind a contract. This project hands them to you along with the source.
Licence and the cost of keeping three harnesses alive
The repository is Apache-2.0, which permits commercial use and modification and includes a patent grant, with the usual requirements around retaining notices and stating changes. That is a permissive starting point, though the licence covers the code in this repository and says nothing about the models you connect through LiteLLM, which carry their own terms. On maintenance, the material shows a stack with FastAPI, SQLAlchemy 2.0 async, Alembic, Pydantic v2, Celery with Redis, PostgreSQL 16, Qdrant or Chroma, React 18, TypeScript 5, Vite 5 and TailwindCSS 3, plus three agent frameworks and MLflow tracing on the CrewAI path. Every one of those is a dependency you inherit. The per-harness skill copies add a second axis of upkeep that no package manager will track for you. Upgrading means reconciling skill changes across backend/app/skills, agents/deep-agents/skills and agents/hermes/skills by hand, because the README states there is no auto-sync.
Editorial conclusion
Adopt this if you already run LM Studio or Ollama, have a 9B-plus model with 32K context available, and want to read a repository rather than a manual. Do not adopt it if you need a supported extraction product, a published accuracy figure, or a single documented way to run the pipeline. Before anything else, open agents/deep-agents/run_e2e.py and infra/.env.example, because the README describes the deterministic Deep Agents path as the fastest route but does not print the command that starts it.
Community notes