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.3 — PPTX newline fix

  • Fix: PPTX converter emitted literal \n (backslash-n) instead of real newlines, producing malformed markdown. Now aligned with the upstream core PPTX converter — clean, readable output.
  • Perf: XLSX now reads all sheets in a single pass instead of re-parsing the workbook once per sheet.

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.3.tar.gz (812.5 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.3-py3-none-any.whl (22.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: markitdown_ocr_parallel-0.2.3.tar.gz
  • Upload date:
  • Size: 812.5 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.3.tar.gz
Algorithm Hash digest
SHA256 e3f7e372604868be6e7a534599b4670d9e9b3aa8f042a98dfb78197450106bc9
MD5 ee05d73dcff8f62eb47361c52e5d85e4
BLAKE2b-256 4dfd75168a358ecce0bb399302c345abb0758f2e5f84638ef18aadeaf2e95c98

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for markitdown_ocr_parallel-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 14e37990d254d44c827e919714ed0587e22bb69d136877ea8e8bf830484598bf
MD5 46e6f5011c052a497681649114467f87
BLAKE2b-256 18cc397110bf13aa3c06f950088c6bb73868c72ba6a8db9e0d333bc77914f83c

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