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.

June 28, 20264 min read

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:

StatementTransaction F1Debit accuracy
Canara savings92.8%96.8%
HSBC savings97.6%77.5%
ICICI credit card81.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

MetricCanara (238 txns)HSBC (382 txns)ICICI (79 txns)Mean
Transaction F187.0%94.0%100%93.7%
Precision87.0%93.3%100%93.4%
Recall87.0%94.8%100%93.9%
Date accuracy99.5%99.4%100%99.6%
Debit accuracy78.0%94.8%0%57.6%
Bank detection100%100%100%100%
Overall score61.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:

  1. 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.
  2. Rows went down while precision climbed. v1.1 deliberately extracts fewer, more trustworthy rows rather than hallucinating rows an LLM thinks should be there.
  3. 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

Try ParseMyStatement Free

FAQ

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%.