ParseMyStatement v2.0 — Block-Level Confidence Sounded Great. Our Own Benchmark Caught the Regression.

How ParseMyStatement v2.0 turned on Mistral's include_blocks=True and confidence scores, why mean transaction F1 regressed from 93.7% to 51.6%, and how a ground-truth benchmark stopped a regression from reaching production finance.

July 15, 20263 min read

ParseMyStatement v2.0 — Block-level confidence (include_blocks=True) sounded great. Our own benchmark caught the regression.

This is the most honest post in the series. Our v1.1 release pushed mean transaction F1 to 93.7%. In July 2026 we shipped ParseMyStatement v2.0, a headline feature release: we turned on Mistral's block-level metadata (include_blocks=True) and per-page confidence scores. The marketing instinct was to celebrate — more structure, more transparency, a confidence score for every page. Then we ran the same three real statements through the same harness, and mean transaction F1 fell from 93.7% to 51.6%.

This is the story of how a rigorous, ground-truth benchmark — the exact one we encourage every API buyer to demand — stopped us from shipping a regression to production finance workflows.

What v2.0 changed under the hood

We added two parameters to the Mistral OCR call and switched normalization from gpt-4o-mini to deepseek-ai/DeepSeek-V4-Flash on DeepInfra:

response = client.ocr.process(
    model="mistral-ocr-latest",
    document={"type": "document_url", "document_url": pdf_url},
    include_blocks=True,                  # NEW in v2.0
    confidence_scores_granularity="page", # NEW in v2.0
)

include_blocks=True returns typed blocks (title, table, header, footer…) with bounding boxes. We exposed them as ocr_metadata on the result, flagged pages with average confidence below 0.7 in low_confidence_pages, and issued a human-readable warning.

{
  "ocr_metadata": {
    "0": {
      "blocks": [
        { "type": "title", "content": "## HSBC Live+ Credit Card" },
        { "type": "table", "content": "<table>...</table>", "table_id": "tbl-0.html" }
      ],
      "confidence_scores": { "average_page_confidence_score": 0.9842, "minimum_page_confidence_score": 0.1937 }
    }
  },
  "low_confidence_pages": [5]
}

The v2.0 regression, measured

Same harness, same three real statements, same hand-written ground truth:

MetricCanara (238 txns)HSBC (382 txns)ICICI (79 txns)Mean
Transaction F181.6%73.3%0.0%51.6%
Date accuracy100%99.2%0.0%66.4%
Debit accuracy78.0%93.3%0.0%57.1%
Overall score64.4%68.6%5.4%46.1%
Transaction F1 by statement (v2.0, Blocks+Confidence):
Canara  ███████████████████████   81.6%
HSBC    ██████████████████████  73.3%
ICICI                               0.0%  ← bank detected, zero rows extracted

The worst signal was ICICI: v2.0 detected the bank but extracted zero transactions. The new block metadata path — which we built "to make headers and footers filterable" — ended up disrupting the very table structure that OCR-only mode had let flow through cleanly in v1.1. The confidence payload changed the shape of the OCR response, and the normalization model (deepseek-ai/DeepSeek-V4-Flash) saw a different, noisier structure.

Why the benchmark saved us

Here is the uncomfortable part worth being honest about: the visibility numbers looked great. We could show confidence scores, warning lists, and block metadata — genuinely useful for debugging. Had we shipped on vibe, we would have told the world v2.0 was a leap forward. The ground-truth harness said otherwise within minutes. Because we score against the banks' own exports, not against how confident we feel, a regression could not hide behind pretty metadata.

This is exactly why our v1.0 methodology post insists on publishing model names and real F1. When the numbers move the wrong way, you want a test that yells at you — and it did.

The fix and the lesson

We did not ship v2.0's blocks+confidence path as the default. The metadata stayed available for debugging, but the pipeline reverted to the proven table-aware path, now on deepseek-ai/DeepSeek-V4-Flash. What came next — hard prompt hardening and tolerant JSON parsing — is the release that finally beat our own record. That is v2.1.

The lesson we now apply to every release, and the one we want every team buying an OCR API to apply too:

A benchmark that can say "no" is worth more than a feature that can say "yes." Publish your model names, publish your ground truth, and let honest F1 drive your roadmap.

Try it

The current production engine — with include_blocks confidence available and hardened normalization — is live on our home page and the developer API. See how the versions compare end-to-end in our model history comparison.

Stop retyping bank statements

Convert PDF bank statements to clean CSV, Excel, or JSON in 30 seconds

Try ParseMyStatement Free

FAQ

How accurate was ParseMyStatement v2.0 OCR?

v2.0 scored 51.6% mean transaction F1 on three real statements — a regression from v1.1's 93.7%. The ICICI credit card fell to 0% transactions extracted, even though the bank was detected correctly. The regression was caught by the same ground-truth harness used for every release.

What is include_blocks=True in Mistral OCR?

include_blocks=True makes Mistral OCR return typed structural blocks (title, table, header, footer) with bounding boxes alongside markdown and HTML tables. It is useful for layout-aware processing, but in v2.0 it changed the OCR response shape and disrupted table reconstruction for credit card statements.

What is OCR block-level confidence scoring?

Mistral's confidence_scores_granularity=page returns an average and minimum confidence per page. ParseMyStatement flags pages under 0.7 in a low_confidence_pages list. The scores are useful for auditing, but v2.0 proved they must not mask a real drop in transaction F1.

Which LLM normalizes transactions in v2.0?

v2.0 moved normalization from gpt-4o-mini to deepseek-ai/DeepSeek-V4-Flash on DeepInfra. Combined with the new block metadata, this produced a different, noisier input shape for the credit card, contributing to the regression. v2.1 kept DeepSeek-V4-Flash with hardened prompts.

How do you detect an OCR regression?

Run every release against the same hand-written ground truth derived from the banks' own CSV/XLS exports and compare transaction F1, precision, and recall. A benchmark that can say no (a failing regression test) is more trustworthy than any confidence-score marketing.