Project Overview
This case study documents an on-premise document extraction system we built for a mid-sized US commercial lender. Their credit analysts were transcribing loan files by hand, around 650 files a month, each a stack of PDFs: three years of financial statements, a tax return with a dozen schedules, formation documents, an appraisal. Vendor risk policy, shaped by Gramm-Leach-Bliley obligations around nonpublic personal information, ruled out any third-party inference endpoint, so the system runs entirely inside the lender's network. First document family reached production in thirteen weeks.
The pipeline reads business tax returns and financial statements, then writes structured fields into the origination system that already runs the business. It never calls an external API. Weights, documents, and logs stay on hardware the lender controls, with Particula-Finance supplying the domain field schemas and Particula-JSON enforcing constrained structured output, served on the lender's own NVIDIA GPUs.
The part that made it bank-grade was not the model. Extraction demos look excellent: a capable model reads a balance sheet and returns clean JSON. Then the system meets a stamped scan, a schedule spanning a page break, a figure in parentheses meaning negative, and a fiscal year that is not the calendar year. What closed that gap was the deterministic validation and audit layer above the model, which is where most of the engineering in this project went.
Why the Back Office Was Still Re-Keying Numbers
Before the project, an analyst opened each document in a loan file, found the numbers that mattered, and typed them into the origination system. High volume, low judgment work, and a mistyped debt service figure propagated straight into a credit decision. The team knew the cost; what blocked the obvious fix was the data. Borrower financials and KYC material are nonpublic personal information, and the lender's vendor risk review had already rejected cloud document AI tools twice before we were engaged. The only architecture that could clear review was one where the documents never leave the network.
That constraint set the design brief: open-weight models on owned hardware, no external calls, and an audit story strong enough that the model risk function could defend every posted number to an examiner.
What We Built: Extract, Validate, Review
The pipeline runs as distinct stages, each inspectable on its own. Documents enter through a watched folder and an SFTP drop, then normalization splits combined PDFs, deskews scans, and classifies each file into a document family, which selects the schema and rules applied downstream. Extraction is task specific: instead of one model reading a whole loan file, narrow extractors per family bind to explicit field schemas through Particula-JSON, so output is a typed object with an explicit null where a field is absent. Particula-Finance supplies those schemas: income statement line items, tax form boxes, the beneficial ownership fields a KYC packet must yield.
Then the deterministic tier, which is what separates a demo from a bank-grade system. Model output is a hypothesis, not a result. Assets must equal liabilities plus equity. Subtotals must sum. A return's summary line must reconcile with the schedule feeding it. Period labels must agree across statements, and identity fields must match across documents in one packet. These are ordinary rules in ordinary code, versioned alongside the schemas, and they run on every extraction. A field that passes its rules and clears its confidence threshold posts automatically. A field that fails either one goes to a human.
The review queue is field level, not document level. A reviewer sees the value in question with the source page and region it came from, the rule that failed, and the model's alternatives, then confirms or corrects without re-reading the document. Corrections write back through the same audit path as automatic postings and become labeled evaluation data. We write into the origination system through a staged table it already ingests, which turned out to be the dullest reliable interface available, and dull is what you want here.
The Stack We Deployed
We were deliberately conservative here. The lender's platform team owns this system now, so every component is something they can run, patch, and reason about without exotic expertise. No managed vector services, no orchestration frameworks that hide control flow, no dependency that phones home. It all runs in containers on the lender's hardware, with egress disabled.
| Layer | What we deployed | Why this choice |
|---|---|---|
| Ingest and orchestration | FastAPI in Docker on the lender's existing Kubernetes, PostgreSQL for field and queue state | Boring and inspectable. State lives in a database their DBAs already back up. |
| OCR and layout | Tesseract for clean typed text, a layout-aware vision model for scans and stamped pages | Offline and strong on clean text. Degraded scans and table structure need geometry. |
| Extraction | Qwen 2.5 72B on vLLM, constrained by Particula-JSON schemas from Particula-Finance | Open weights vendored in and pinned by hash. Constrained decoding removes a class of parsing failures. |
| Validation | Deterministic rule engine, versioned alongside the schemas | Business rules, not model behavior. Their credit officers can read them. |
| Serving hardware | 2x NVIDIA H100 (80 GB HBM3) | The 72B runs 4-bit quantized on one card; the second carries KV cache headroom and failover. |
| Audit and review | Append-only PostgreSQL tables, one row per field version, plus the field-level review queue | Every posted number traces to a page, a model version, a rule outcome, and a person. |
Security and Compliance Controls
Network posture came first. The inference tier has no outbound route. Model weights, tokenizer files, and container images were pulled once at build time, verified by hash, and moved in through the lender's existing artifact process. There is no runtime package installation, no telemetry, and no license check reaching the internet. We tested this bluntly, by running the full pipeline with egress blocked at the firewall before go-live, and that test is now part of their release checklist.
Access control is field aware. Permissions scope by document family and field sensitivity: identity and account numbers are masked in list views and revealed only on an explicit, logged action. Retention is configurable per document family, because a KYC packet and a working extraction cache do not carry the same obligations. Encryption at rest uses the lender's existing key management, and the extraction database stays separate from the document store so retention can be enforced independently.
The audit trail is per field, and it is the part examiners care about. Every value carries the source document, page and region, the OCR and extraction model versions in use, the schema version, the confidence score, every validation rule that ran with its outcome, and, if a human touched it, who, when, and the prior value. Nothing is overwritten; corrections append. That record lets the model risk function document lineage, reproduce a decision months later, and answer the question that matters: where did this number come from?
How the Rollout Ran
The first document family, business tax returns, took thirteen weeks to production, and we started narrow on purpose. The opening two weeks were unglamorous: we sat with the analysts doing the work, built the document taxonomy from real files, and assembled a holdout set of 600 documents, hand labeled at field level by people who know what the fields mean. The team pushed back because it felt like delay. It was the highest leverage artifact in the project.
Weeks three through six built extraction and validation for that one family end to end, evaluated against the holdout after every change. Weeks seven through ten built the review queue and the origination-system integration, which is where the real surprises lived: field name mismatches, mandatory fields nobody had documented, and a validation trigger on the staging table that nobody remembered writing. Weeks eleven through thirteen ran the system in shadow mode beside the human process, extracting everything and posting nothing.
Cutover was gated, not scheduled. A field moved to automatic posting when its precision on the holdout and in shadow mode cleared the threshold its credit or compliance owner had set for that field, and not before. Different fields crossed that line at different times, which was expected: a borrower name and a total revenue figure do not carry the same risk. The second family, financial statements, went live five weeks later on the same platform, schemas, and review queue, which is exactly why the platform was worth building once.
Results
At steady state the system auto-posts 73 percent of extracted fields, each above the precision floor its owner set, with measured precision on auto-posted fields holding above 98 percent on both the labeled holdout and the shadow-mode comparison. We report precision and recall per field, per document family, never as one blended number: a file where every field is right except the debt service figure is not a mostly correct file, it is a bad credit input. A missed field costs review time; a wrong field posted confidently costs a decision, and the thresholds reflect that asymmetry.
Analyst time per loan file dropped by roughly 60 percent, from about ninety minutes of transcription and checking to around thirty-five minutes of reviewing flagged fields, and the review is better work: the reviewer sees the doubtful value next to the page region it came from instead of re-reading the whole file. Corrections feed the evaluation set, so the holdout grows with exactly the failures that matter.
The monitoring earned its keep early. Override rate is the drift signal we watch, and within the first months it caught an upstream change, a new statement layout from one accounting package, before it could quietly degrade posted fields; the rule failures routed everything from that layout to review until the extractor was updated and re-cleared the gate. That is the system working as designed: aggressive where the evidence supports it, conservative the moment it does not, and every number defensible after the fact.
- Financial Services
- On-Premise AI
- Document Extraction
- Commercial Lending
- Compliance
- KYC


