Skip to main content

Parallel LLM Vision OCR plugin for MarkItDown — extracts text from images in PDF, DOCX, PPTX, and XLSX files with 3x speedup via ThreadPoolExecutor batching.

Project description

MarkItDown OCR Plugin

PyPI License: MIT

LLM Vision plugin for MarkItDown that extracts text from images embedded in PDF, DOCX, PPTX, and XLSX files.

Key features:

  • Parallel batch OCR via ThreadPoolExecutor — up to 3x faster than serial processing
  • Configurable concurrency with max_workers (default 5)
  • Uses the same llm_client / llm_model pattern that MarkItDown already supports
  • No new ML libraries or binary dependencies required

Installation

pip install markitdown-ocr-parallel

The plugin uses whatever OpenAI-compatible client you already have:

pip install openai

Quick Start

Python API

from markitdown import MarkItDown
from openai import OpenAI

client = OpenAI()

md = MarkItDown(
    enable_plugins=True,
    llm_client=client,
    llm_model="gpt-4o",
    max_workers=5,  # new! parallel OCR (default: 5)
)

result = md.convert("document_with_images.pdf")
print(result.text_content)

Command Line

markitdown document.pdf --use-plugins --llm-client openai --llm-model gpt-4o

Any OpenAI-Compatible Provider

# Example: Alibaba Cloud Bailian (通义千问)
from openai import OpenAI

client = OpenAI(
    api_key="your-api-key",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)

md = MarkItDown(
    enable_plugins=True,
    llm_client=client,
    llm_model="qwen3.6-flash",
    max_workers=10,
)

Performance

Parallel batch processing significantly reduces conversion time for documents with multiple images:

Document Images Serial (1 worker) Parallel (5 workers) Speedup
Scanned contract (5 pages) 5 74.4s 24.1s 3.1x
PDF with 3 embedded images 3 4.6s 3.3s 1.4x
PDF with 2 embedded images 2 2.2s 1.2s 1.9x
Scanned report (3 pages) 3 6.6s 2.6s 2.6x

Tune max_workers based on your API rate limits and document complexity.

How It Works

When MarkItDown(enable_plugins=True, llm_client=..., llm_model=...) is called:

  1. MarkItDown discovers the plugin via the markitdown.plugin entry point group
  2. Four OCR-enhanced converters are registered at priority -1.0 — before built-in converters (priority 0.0)

When a file is converted, the plugin uses a collect → batch → assemble pipeline:

  1. Collection Phase: All images are extracted from the document upfront (fast, no API calls)
  2. Batch OCR Phase: All images are sent to the LLM in parallel via ThreadPoolExecutor
  3. Assembly Phase: OCR results are inserted inline, preserving document structure

This replaces the original serial approach where each image was OCR'd one-by-one.

Supported File Formats

PDF

  • Embedded images extracted by position, interleaved with text in reading order
  • Scanned PDFs detected automatically — full pages rendered at 300 DPI and OCR'd
  • Malformed PDFs fall back to PyMuPDF page rendering
  • Parallel: all page images OCR'd simultaneously

DOCX

  • Images extracted via document part relationships
  • Placeholder injection pattern prevents markdown converter from escaping OCR markers
  • Parallel: all images OCR'd in one batch before HTML→Markdown conversion

PPTX

  • Two-round parallel: Round 1 → LLM caption for all images; Round 2 → OCR backup for failed images
  • Recursive shape walking handles groups, placeholders, and picture shapes
  • Parallel: images from all slides processed together

XLSX

  • Images extracted per sheet with cell position tracking
  • Parallel: images from all sheets collected and OCR'd in one batch

Output Format

Every extracted OCR block is wrapped as:

*[Image OCR]
<extracted text>
[End OCR]*

Configuration

Parameter Default Description
llm_client OpenAI-compatible client (required)
llm_model Model name, e.g. gpt-4o, qwen3.6-flash (required)
llm_prompt "Extract all text..." Custom OCR extraction prompt
max_workers 5 Max parallel OCR threads

Development

Running Tests

git clone https://github.com/echojfree/markitdown-ocr-parallel.git
cd markitdown-ocr
pip install -e ".[llm]"
pytest tests/ -v

Building

pip install build
python -m build

Changelog

0.2.0 — Parallel Batch OCR

  • Parallel OCR: extract_text_batch() method using ThreadPoolExecutor for 2-3x speedup
  • max_workers parameter (default 5) on LLMVisionOCRService
  • PDF: single-pass image collection + batch OCR + Y-position interleaving
  • DOCX: batch OCR before HTML→Markdown pipeline
  • PPTX: two-round parallel (LLM caption → OCR fallback) with pre-scan phase
  • XLSX: cross-sheet image collection + batch OCR
  • Fix: scanned PDF fallback detection (regex-strip page headers)
  • All 36 tests pass

0.1.0 — Initial Release

  • LLM Vision OCR for PDF, DOCX, PPTX, XLSX
  • Full-page OCR fallback for scanned PDFs
  • Priority-based converter replacement

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

markitdown_ocr_parallel-0.2.0.tar.gz (811.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

markitdown_ocr_parallel-0.2.0-py3-none-any.whl (21.6 kB view details)

Uploaded Python 3

File details

Details for the file markitdown_ocr_parallel-0.2.0.tar.gz.

File metadata

  • Download URL: markitdown_ocr_parallel-0.2.0.tar.gz
  • Upload date:
  • Size: 811.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.6

File hashes

Hashes for markitdown_ocr_parallel-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c131094ddeac5309039c38590d20d81c5258b2a7b45278a0a8ba6b94c36d692e
MD5 cf9d32d10449e400df50898263e44505
BLAKE2b-256 c5f0887d538c45c7505e0fd3f8470ec45acae5b44877f3f6b5d909d0dca28eb1

See more details on using hashes here.

File details

Details for the file markitdown_ocr_parallel-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for markitdown_ocr_parallel-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d783b866e6dd8167d01b28e4ccf4a5965f05805dbc19ac6705585230433e2f07
MD5 72463ce5d2a5420b64f5065d876ddfb9
BLAKE2b-256 e873e5d047f0adb39a5f3f201f2ec6febf5d83edabbbb2191bdfb038f7130e32

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page