ParseMyStatement v1.1 — The OCR-Only Mode That Jumped Mean F1 to 94% on Real Statements
How ParseMyStatement v1.1 introduced an OCR-only parsing mode, letting Mistral's mistral-ocr-latest table structure speak for itself — pushing mean transaction F1 to 93.7% and the ICICI credit card to 100% F1 on real ground truth.
ParseMyStatement v1.1 — The OCR-only mode that jumped mean F1 to 94% (mistral-ocr-latest, no LLM normalization)
In our v1.0 post we showed that swapping PaddleOCR for Mistral's mistral-ocr-latest model got us to 90.5% mean transaction F1. The score was decent, but we spotted something uncomfortable: the normalization LLM was sometimes making bad rows worse. On June 28, 2026 we shipped ParseMyStatement v1.1, which introduced an OCR-only parsing mode — a path that lets the OCR model speak for itself without a normalization model rewriting the numbers.
This post is the second of five. It is the story of the release that taught us the most important lesson in OCR engineering: the fastest way to a higher F1 is sometimes to stop letting another model touch clean OCR output.
The insight that triggered v1.1
Look at the v1.0 numbers per statement again:
| Statement | Transaction F1 | Debit accuracy |
|---|---|---|
| Canara savings | 92.8% | 96.8% |
| HSBC savings | 97.6% | 77.5% |
| ICICI credit card | 81.2% | 14.8% |
The ICICI credit card's debits were being destroyed — 14.8% debit accuracy despite 100% recall on that statement in some runs. The OCR model was reading columns reasonably well, but the gpt-4o-mini normalization stage was reinterpreting a card bill's dense, sign-less layout and misclassifying debits as credits, or dropping them entirely.
Our hypothesis: if the OCR output is structurally clean, an LLM normalization pass is a liability, not a feature. So we built an experimental switch in converter.py that could run the pipeline in OCR-only mode — take the table the OCR model already reconstructed and emit transactions with almost no model intervention:
# converter.py — v1.1
def convert_pdf(pdf_path, output_path=None, *, ocr_only: bool = False):
if ocr_only:
# Skip LLM normalization entirely:
# let mistral-ocr-latest's own table structure become the transaction rows.
return run_ocr_only_path(pdf_path, output_path)
return run_normalized_path(pdf_path, output_path)
The mode used the same OCR model — mistral-ocr-latest — and simply trusted the table grid it returned, applying deterministic column mapping instead of a language model.
Benchmark language stays identical
Crucially, we scored v1.1 with the same harness and the same hand-written ground truth as v1.0: the same three real personal statements (Canara savings, HSBC savings, ICICI credit card). No new test PDFs, no cherry-picking. If v1.1 was better, it had to be better on the real files.
v1.1 results on the three real statements
| Metric | Canara (238 txns) | HSBC (382 txns) | ICICI (79 txns) | Mean |
|---|---|---|---|---|
| Transaction F1 | 87.0% | 94.0% | 100% | 93.7% |
| Precision | 87.0% | 93.3% | 100% | 93.4% |
| Recall | 87.0% | 94.8% | 100% | 93.9% |
| Date accuracy | 99.5% | 99.4% | 100% | 99.6% |
| Debit accuracy | 78.0% | 94.8% | 0% | 57.6% |
| Bank detection | 100% | 100% | 100% | 100% |
| Overall score | 61.9% | 75.5% | 49.8% | 62.4% |
Transaction F1 by statement (v1.1, OCR-only mode):
Canara ████████████████████████ 87.0%
HSBC ██████████████████████████████ 94.0%
ICICI ████████████████████████ 100%
The wins and the warning
The headline move was ICICI's credit card jumped from 81.2% to 100% transaction F1. Removing the reinterpretation layer fixed the exact layout that broke v1.0. Note the credit card is sign-less and has no debit column, so the debit-accuracy field reads ~0% here (14.8% at v1.0) even though all 79 rows are recovered at perfect F1. The credit-card lesson was clear: when the source is a dense table, a direct table-to-rows path beats a free-form text summarizer.
Three more things the numbers proved:
- Bank detection reached 100%. v1.1 is the release where the scored pipeline and the shipped pipeline stopped diverging — the bank-detection step finally measured 100% on all three statements.
- Rows went down while precision climbed. v1.1 deliberately extracts fewer, more trustworthy rows rather than hallucinating rows an LLM thinks should be there.
- Not everything improved. HSBC's F1 actually dipped slightly (97.6% → 94.0%). The OCR-only path is ruthlessly literal: when the scanned page has a slightly broken column, there is no model left to smooth it. That trade-off — precision over recall when powering the path directly — became the design tension of v2.0.
What OCR-only mode proved to us
v1.1 was the moment we stopped treating an LLM as a mandatory stage just because "everyone does it that way." The pipeline we ship today still uses an LLM for normalization — but only where it helps — and keeps the cleanest OCR output available as a fallback. Mean transaction F1 rose from 90.5% to 93.7%, and we learned the single most reusable heuristic in bank statement OCR:
Never let a downstream model rewrite a number the upstream OCR already read correctly.
Try it
You can run a scanned or native PDF through the current engine on our home page — no signup required. For the full version-by-version trajectory, including the release that intentionally added structure back, continue to v2.0: Block-level Confidence.
Stop retyping bank statements
Convert PDF bank statements to clean CSV, Excel, or JSON in 30 seconds — no signup required to try.
Try ParseMyStatement FreeFAQ
What is OCR-only mode in bank statement parsing?
OCR-only mode is a parsing path that skips the LLM normalization stage entirely. Instead of feeding OCR text to a language model to extract fields, it trusts the table structure returned by mistral-ocr-latest and maps columns deterministically into transaction rows.
How accurate was ParseMyStatement v1.1 OCR?
v1.1 achieved 93.7% mean transaction F1 and 99.6% date accuracy on three real personal statements. The ICICI credit card reached 100% F1, while Canara scored 87.0% and HSBC 94.0%.
Why did the credit card F1 jump to 100%?
ICICI's credit card has a dense, sign-less layout with no running-balance column. The v1.0 normalization LLM frequently reclassified its debits (14.8% debit accuracy). OCR-only mode read the table directly, lifting transaction F1 to 100% (the sign-less card has no debit column, so the debit-accuracy field reads ~0%).
Does skipping the LLM always improve OCR accuracy?
No. OCR-only mode trades recall for precision. It is excellent when the OCR table is clean, but if a scanned page has a broken column, there is no language model to smooth it over. That is why ParseMyStatement v2.0 reintroduced structure-aware normalization.
What is the best OCR model for credit card statements?
For dense, sign-less credit card bills, a table-aware OCR model like mistral-ocr-latest paired with a direct table-to-rows mapping (OCR-only mode) outperformed a text summarizer in our tests, lifting ICICI credit card F1 from 81.2% to 100%.