pdfmux
pdfmux
Универсальный оркестратор извлечения данных из PDF. Направляет каждую страницу на лучший бэкенд, проверяет результат, повторно извлекает данные при сбоях. 5 экстракторов на основе правил + резервный LLM (BYOK). Один CLI. Один API. Нулевая настройка.
PDF ──> pdfmux router ──> best extractor per page ──> audit ──> re-extract failures ──> Markdown / JSON / chunks
|
├─ PyMuPDF (digital text, 0.01s/page)
├─ OpenDataLoader (complex layouts, 0.05s/page)
├─ RapidOCR (scanned pages, CPU-only)
├─ Docling (tables, 97.9% TEDS)
├─ Surya (heavy OCR fallback)
└─ YOUR LLM (Gemini / Claude / GPT-4o / Ollama — BYOK via 5-line YAML)Установка
pip install pdfmuxЭто всё. Работает с цифровыми PDF «из коробки». Добавьте бэкенды для более сложных документов:
pip install "pdfmux[ocr]" # RapidOCR — scanned/image pages (~200MB, CPU-only)
pip install "pdfmux[tables]" # Docling — table-heavy docs (~500MB)
pip install "pdfmux[opendataloader]" # OpenDataLoader — complex layouts (Java 11+)
pip install "pdfmux[llm]" # LLM fallback — Gemini, Claude, GPT-4o, Ollama
pip install "pdfmux[all]" # everythingТребуется Python 3.11+.
Быстрый старт
CLI
# zero config — just works
pdfmux convert invoice.pdf
# invoice.pdf -> invoice.md (2 pages, 95% confidence, via pymupdf4llm)
# RAG-ready chunks with token limits
pdfmux convert report.pdf --chunk --max-tokens 500
# cost-aware extraction with budget cap
pdfmux convert report.pdf --mode economy --budget 0.50
# schema-guided structured extraction (5 built-in presets)
pdfmux convert invoice.pdf --schema invoice
# BYOK any LLM for hardest pages
pdfmux convert scan.pdf --llm-provider claude
# batch a directory
pdfmux convert ./docs/ -o ./output/Python
import pdfmux
# text -> markdown
text = pdfmux.extract_text("report.pdf")
# structured data -> dict with tables, key-values, metadata
data = pdfmux.extract_json("report.pdf")
# RAG chunks -> list of dicts with token estimates
chunks = pdfmux.chunk("report.pdf", max_tokens=500)Архитектура
┌─────────────────────────────┐
│ Segment Detector │
│ text / tables / images / │
│ formulas / headers per page │
└─────────────┬───────────────┘
│
┌────────────────────────────────────────┐
│ Router Engine │
│ │
│ economy ── balanced ── premium │
│ (minimize $) (default) (max quality)│
│ budget caps: --budget 0.50 │
└────────────────────┬───────────────────┘
│
┌──────────┬──────────┬────────┴────────┬──────────┐
│ │ │ │ │
PyMuPDF OpenData RapidOCR Docling LLM
digital Loader scanned tables (BYOK)
0.01s/pg complex CPU-only 97.9% any provider
layouts TEDS
│ │ │ │ │
└──────────┴──────────┴────────┬────────┴──────────┘
│
┌────────────────────────────────────────┐
│ Quality Auditor │
│ │
│ 4-signal dynamic confidence scoring │
│ per-page: good / bad / empty │
│ if bad -> re-extract with next backend│
└────────────────────┬───────────────────┘
│
┌────────────────────────────────────────┐
│ Output Pipeline │
│ │
│ heading injection (font-size analysis)│
│ table extraction + normalization │
│ text cleanup + merge │
│ confidence score (honest, not inflated)│
└────────────────────────────────────────┘Ключевые проектные решения
Маршрутизатор, а не экстрактор. pdfmux не конкурирует с PyMuPDF или Docling. Он выбирает лучший инструмент для каждой страницы.
Агентный многопроходный подход. Извлечение, проверка достоверности, повторное извлечение при сбоях с помощью более мощного бэкенда. Плохие страницы обрабатываются повторно автоматически.
Детекция на уровне сегментов. Каждая страница классифицируется по типу контента (текст, таблицы, изображения, формулы, заголовки) перед маршрутизацией.
4-сигнальная оценка достоверности. Динамическая оценка качества на основе плотности символов, уровня шума OCR, целостности таблиц и структуры заголовков. Никаких жестко заданных порогов.
Кэширование документов. Каждый PDF открывается один раз, а не по разу для каждого экстрактора. Общий доступ для всего конвейера.
Маховик данных. Локальная телеметрия отслеживает, какие экстракторы лучше справляются с определенными типами документов. Маршрутизация улучшается по мере использования.
Функции
Функция | Что делает | Команда |
Извлечение без настройки | Автоматически направляет на лучший бэкенд |
|
RAG-чанкинг | Чанки с учетом разделов и оценкой токенов |
|
Режимы стоимости | эконом / сбалансированный / премиум с лимитами бюджета |
|
Извлечение по схеме | 5 встроенных пресетов (счет, чек, договор, резюме, статья) |
|
BYOK LLM | Gemini, Claude, GPT-4o, Ollama, любой API, совместимый с OpenAI |
|
Бенчмарк | Оценка всех установленных экстракторов относительно эталона |
|
Доктор | Показ установленных бэкендов, пробелов в покрытии, рекомендаций |
|
MCP-сервер | ИИ-агенты читают PDF через stdio или HTTP |
|
Пакетная обработка | Конвертация целых директорий |
|
Потоковая передача | Итерация страниц с ограниченной памятью для больших файлов |
|
Справочник CLI
pdfmux convert
pdfmux convert <file-or-dir> [options]
Options:
-o, --output PATH Output file or directory
-f, --format FORMAT markdown | json | csv | llm (default: markdown)
-q, --quality QUALITY fast | standard | high (default: standard)
-s, --schema SCHEMA JSON schema file or preset (invoice, receipt, contract, resume, paper)
--chunk Output RAG-ready chunks
--max-tokens N Max tokens per chunk (default: 500)
--mode MODE economy | balanced | premium (default: balanced)
--budget AMOUNT Max spend per document in USD
--llm-provider PROVIDER LLM backend: gemini | claude | openai | ollama
--confidence Include confidence score in output
--stdout Print to stdout instead of filepdfmux serve
Запуск MCP-сервера для интеграции с ИИ-агентами.
pdfmux serve # stdio mode (Claude Desktop, Cursor)
pdfmux serve --http 8080 # HTTP modepdfmux doctor
pdfmux doctor
# ┌──────────────────┬─────────────┬─────────┬──────────────────────────────────┐
# │ Extractor │ Status │ Version │ Install │
# ├──────────────────┼─────────────┼─────────┼──────────────────────────────────┤
# │ PyMuPDF │ installed │ 1.25.3 │ │
# │ OpenDataLoader │ installed │ 0.3.1 │ │
# │ RapidOCR │ installed │ 3.0.6 │ │
# │ Docling │ missing │ -- │ pip install pdfmux[tables] │
# │ Surya │ missing │ -- │ pip install pdfmux[ocr-heavy] │
# │ LLM (Gemini) │ configured │ -- │ GEMINI_API_KEY set │
# └──────────────────┴─────────────┴─────────┴──────────────────────────────────┘pdfmux benchmark
pdfmux benchmark report.pdf
# ┌──────────────────┬────────┬────────────┬─────────────┬──────────────────────┐
# │ Extractor │ Time │ Confidence │ Output │ Status │
# ├──────────────────┼────────┼────────────┼─────────────┼──────────────────────┤
# │ PyMuPDF │ 0.02s │ 95% │ 3,241 chars │ all pages good │
# │ Multi-pass │ 0.03s │ 95% │ 3,241 chars │ all pages good │
# │ RapidOCR │ 4.20s │ 88% │ 2,891 chars │ ok │
# │ OpenDataLoader │ 0.12s │ 97% │ 3,310 chars │ best │
# └──────────────────┴────────┴────────────┴─────────────┴──────────────────────┘Python API
Извлечение текста
import pdfmux
text = pdfmux.extract_text("report.pdf") # -> str (markdown)
text = pdfmux.extract_text("report.pdf", quality="fast") # PyMuPDF only, instant
text = pdfmux.extract_text("report.pdf", quality="high") # LLM-assistedСтруктурированное извлечение
data = pdfmux.extract_json("report.pdf")
# data["page_count"] -> 12
# data["confidence"] -> 0.91
# data["ocr_pages"] -> [2, 5, 8]
# data["pages"][0]["key_values"] -> [{"key": "Date", "value": "2026-02-28"}]
# data["pages"][0]["tables"] -> [{"headers": [...], "rows": [...]}]RAG-чанкинг
chunks = pdfmux.chunk("report.pdf", max_tokens=500)
for c in chunks:
print(f"{c['title']}: {c['tokens']} tokens (pages {c['page_start']}-{c['page_end']})")Извлечение с использованием схемы
data = pdfmux.extract_json("invoice.pdf", schema="invoice")
# Uses built-in invoice preset: extracts date, vendor, line items, totals
# Also accepts a path to a custom JSON Schema fileПотоковая передача (ограниченная память)
from pdfmux.extractors import get_extractor
ext = get_extractor("fast")
for page in ext.extract("large-500-pages.pdf"): # Iterator[PageResult]
process(page.text) # constant memory, even on 500-page PDFsТипы и ошибки
from pdfmux import (
# Enums
Quality, # FAST, STANDARD, HIGH
OutputFormat, # MARKDOWN, JSON, CSV, LLM
PageQuality, # GOOD, BAD, EMPTY
# Data objects (frozen dataclasses)
PageResult, # page: text, page_num, confidence, quality, extractor
DocumentResult, # document: pages, source, confidence, extractor_used
Chunk, # chunk: title, text, page_start, page_end, tokens
# Errors
PdfmuxError, # base -- catch this for all pdfmux errors
FileError, # file not found, unreadable, not a PDF
ExtractionError, # extraction failed
ExtractorNotAvailable,# requested backend not installed
FormatError, # invalid output format
AuditError, # audit could not complete
)Интеграции с фреймворками
LangChain
pip install langchain-pdfmuxfrom langchain_pdfmux import PDFMuxLoader
loader = PDFMuxLoader("report.pdf", quality="standard")
docs = loader.load() # -> list[Document] with confidence metadataLlamaIndex
pip install llama-index-readers-pdfmuxfrom llama_index.readers.pdfmux import PDFMuxReader
reader = PDFMuxReader(quality="standard")
docs = reader.load_data("report.pdf") # -> list[Document]MCP-сервер (ИИ-агенты)
Список доступен на mcpservers.org. Настройка одной строкой:
{
"mcpServers": {
"pdfmux": {
"command": "npx",
"args": ["-y", "pdfmux-mcp"]
}
}
}Или через Claude Code:
claude mcp add pdfmux -- npx -y pdfmux-mcpДоступные инструменты: convert_pdf, analyze_pdf, extract_structured, get_pdf_metadata, batch_convert.
Конфигурация BYOK LLM
pdfmux поддерживает любой LLM через 5 строк YAML. Используйте свои ключи — ничего не покидает вашу машину, если вы не настроите это специально.
# ~/.pdfmux/llm.yaml
provider: claude # gemini | claude | openai | ollama | any OpenAI-compatible
model: claude-sonnet-4-20250514
api_key: ${ANTHROPIC_API_KEY}
base_url: https://api.anthropic.com # optional, for custom endpoints
max_cost_per_page: 0.02 # budget capПоддерживаемые провайдеры:
Провайдер | Модели | Локально? | Стоимость |
Gemini | 2.5 Flash, 2.5 Pro | Нет | ~$0.01/стр |
Claude | Sonnet, Opus | Нет | ~$0.015/стр |
GPT-4o | GPT-4o, GPT-4o-mini | Нет | ~$0.01/стр |
Ollama | Любая локальная модель | Да | Бесплатно |
Custom | Любой API, совместимый с OpenAI | Настраиваемо | Разная |
Бенчмарк
Протестировано на opendataloader-bench — 200 реальных PDF-файлов, включая финансовые отчеты, юридические документы, научные статьи и сканы.
Движок | Общий | Порядок чтения | Таблицы (TEDS) | Заголовки | Требования |
opendataloader hybrid | 0.909 | 0.935 | 0.928 | 0.828 | API вызовы ($) |
pdfmux | 0.905 | 0.920 | 0.911 | 0.852 | Только CPU, $0 |
docling | 0.877 | 0.900 | 0.887 | 0.802 | ~500МБ модели |
marker | 0.861 | 0.890 | 0.808 | 0.796 | Рекомендуется GPU |
opendataloader local | 0.844 | 0.913 | 0.494 | 0.761 | Только CPU |
mineru | 0.831 | 0.857 | 0.873 | 0.743 | GPU + ~2ГБ модели |
№2 в общем зачете, №1 среди бесплатных инструментов. 99,5% от результата платного лидера при нулевой стоимости за страницу. Лучшая детекция заголовков среди всех протестированных движков. OCR таблиц извлекает таблицы, встроенные как изображения.
Оценка достоверности
Каждый результат включает 4-сигнальную оценку достоверности:
95-100% -- чистый цифровой текст, полностью извлекаемый
80-95% -- хорошее извлечение, незначительный шум OCR на некоторых страницах
50-80% -- частичное извлечение, некоторые страницы не подлежат восстановлению
<50% -- значительная потеря контента, включены предупреждения
Когда достоверность падает ниже 80%, pdfmux точно сообщает, что пошло не так и как это исправить:
Page 4: 32% confidence. 0 chars extracted from image-heavy page.
-> Install pdfmux[ocr] for RapidOCR support on 6 image-heavy pages.Режимы стоимости
Режим | Поведение | Типичная стоимость |
economy | Только бэкенды на основе правил. Без вызовов LLM. | $0/стр |
balanced | LLM только для страниц, где не справились правила. | ~$0.002/стр в ср. |
premium | LLM на каждой странице для максимального качества. | ~$0.01/стр |
Установите жесткий лимит бюджета: --budget 0.50 остановит вызовы LLM, когда расходы достигнут $0.50 на документ.
Почему pdfmux?
pdfmux — это не очередной экстрактор PDF. Это уровень оркестрации, который выбирает правильный экстрактор для каждой страницы, проверяет результат и повторяет попытки при сбоях.
Инструмент | В чем хорош | Ограничение |
PyMuPDF | Быстрый цифровой текст | Не работает со сканами или сложной версткой |
Docling | Таблицы (точность 97.9%) | Медленный на документах без таблиц |
Marker | GPU ML извлечение | Нужен GPU, избыточен для цифровых PDF |
Unstructured | Корпоративная платформа | Сложная настройка, платные уровни |
LlamaParse | Облачный | Требует API ключи, не локальный |
Reducto | Высокая точность | $0.015/стр, закрытый код |
pdfmux | Оркестрирует все вышеперечисленное | Маршрутизирует по страницам, проверяет, переизвлекает |
Альтернатива Reducto с открытым кодом: то, что стоит $0.015/стр в других местах, бесплатно с бэкендами pdfmux на основе правил, или ~$0.002/стр в среднем с резервным LLM (BYOK).
Разработка
git clone https://github.com/NameetP/pdfmux.git
cd pdfmux
python3.12 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest # 151 tests
ruff check src/ tests/
ruff format src/ tests/Вклад в проект
Сделайте форк репозитория
Создайте ветку (
git checkout -b feature/your-feature)Напишите тесты для новой функциональности
Убедитесь, что
pytestиruff checkпроходятОткройте PR
Лицензия
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/NameetP/pdfmux'
If you have feedback or need assistance with the MCP directory API, please join our Discord server