PrettyPipeline
Turn PDFs into structured JSON. OCR runs on your GPU when needed. Field extraction uses a cheap cloud LLM. You define the schema.
PDF → embedded text (digital PDFs) or Unlimited-OCR (scans)
↓
GPT-5.4 nano (OpenAI) → JSON + needs_review + _meta
Why this is cheap
Cloud OCR APIs charge per page. PrettyPipeline does vision work locally with baidu/Unlimited-OCR (MIT, 3B params, 32K context) when a page has no usable embedded text.
The only paid call is GPT-5.4 nano on document text (~$0.20 / 1M input tokens), prompted with your JSON schema.
Digital PDFs use embedded text automatically (fast, accurate). OCR runs per-page only for scans, or for everything with --force-ocr.
Nulls, uncertain fields, values not found in source text, and garbled OCR are flagged in needs_review (one reason per field).
Install
Python 3.10–3.13 (3.12 recommended).
Digital PDFs only (no local OCR, smallest install):
pip install prettypipeline-ocr
Full install (local OCR for scans and --force-ocr):
pip install prettypipeline-ocr[ocr]
The CLI is prettypipeline. From this repo:
python3.12 -m venv .venv && source .venv/bin/activate
pip install -e ".[ocr,dev]"
NVIDIA Linux — install a CUDA PyTorch wheel first if needed:
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu124
pip install prettypipeline-ocr[ocr]
The first OCR run downloads baidu/Unlimited-OCR from Hugging Face (~6GB).
Docker (CUDA):
docker build -f Dockerfile.cuda -t prettypipeline:cuda .
docker run --gpus all -e OPENAI_API_KEY=sk-... \
-v "$PWD/data:/data" prettypipeline:cuda \
run /data/invoice.pdf --schema /data/schema.json -o /data/out.json
Quick start
export OPENAI_API_KEY=sk-...
prettypipeline run invoice.pdf --schema examples/invoice.schema.json
prettypipeline run invoice.pdf --schema examples/invoice.schema.json -o out.json
prettypipeline run invoice.pdf --schema examples/invoice.schema.json --ocr-only
Demo invoice in this repo:
prettypipeline run tests/fixtures/sample_invoice.pdf \
--schema examples/invoice.schema.json -o out.json
Batch:
prettypipeline batch ./invoices/*.pdf \
--schema examples/invoice.schema.json \
--output-dir ./out/ \
--summary ./out/summary.json
Schema examples
| File | Use case |
|---|---|
examples/invoice.schema.json |
Invoices |
examples/receipt.schema.json |
Receipts |
examples/purchase_order.schema.json |
Purchase orders |
--schema is any JSON Schema — swap the file to extract a different document type.
CLI
prettypipeline run FILE.pdf --schema SCHEMA.json
-o, --output PATH write JSON (also printed)
--ocr-only skip OpenAI step
--force-ocr always OCR (skip embedded text)
--include-ocr-text include raw text in output
--device cuda|mps|cpu override auto-detect
--dpi N PDF raster DPI (default 300)
--max-length N OCR cap (8192 MPS, 32768 CUDA/CPU)
--model NAME LLM model (default gpt-5.4-nano)
--base-url URL OpenAI-compatible API endpoint
prettypipeline batch FILES... --schema SCHEMA.json --output-dir DIR
--summary PATH optional batch summary JSON
Environment variables:
| Variable | Purpose |
|---|---|
OPENAI_API_KEY |
Required unless --ocr-only |
PRETTYPIPELINE_MODEL |
Default LLM model |
PRETTYPIPELINE_BASE_URL |
OpenAI-compatible base URL |
Output
{
"data": {
"date": "January 25, 2016",
"vendor": "DEMO - Sliced Invoices",
"invoice_number": "INV-3337",
"total": 93.5
},
"needs_review": [],
"source": "pdf_text",
"_meta": {
"version": "0.3.0",
"elapsed_ms": 4200,
"pages": 1,
"device": "mps",
"model": "gpt-5.4-nano",
"token_usage": {
"prompt_tokens": 1200,
"completion_tokens": 180,
"total_tokens": 1380
}
}
}
source |
meaning |
|---|---|
pdf_text |
all pages used embedded text |
ocr |
all pages OCR'd |
mixed |
some pages embedded, some OCR |
needs_review reason |
meaning |
|---|---|
null |
model returned null |
uncertain |
model flagged low confidence |
garbled_ocr |
value or nearby OCR looks corrupted |
not_in_source |
value not found in document text |
Programmatic use
from prettypipeline import run
result = run(
"invoice.pdf",
"examples/invoice.schema.json",
)
print(result.data)
print(result.needs_review)
print(result.meta)
Lower-level imports: extract_text, structure, needs_review.
Hardware
| Device | Support |
|---|---|
| NVIDIA CUDA | Native. Recommended for OCR. |
| Apple Silicon (MPS) | Supported with CUDA-call patching. --force-ocr may produce garbled output; digital PDFs are unaffected. |
| CPU | Works, slow. |
On MPS, default --max-length is 8192 (input + generation). CUDA/CPU default is 32768.
Development
pip install -e ".[ocr,dev]"
pytest
python -m build && twine check dist/*
License
MIT. Unlimited-OCR is also MIT.
Sample invoice: Sliced Invoices.
Metadata
Release files for prettypipeline-ocr 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| prettypipeline_ocr-0.3.0.tar.gz | 16.4 kB | Without provenance | Details for prettypipeline_ocr-0.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| prettypipeline_ocr-0.3.0-py3-none-any.whl | Python 3 | none | any | Details for prettypipeline_ocr-0.3.0-py3-none-any.whl |
Total release size: 31.0 kB
Release files / prettypipeline_ocr-0.3.0.tar.gz
| Download URL | prettypipeline_ocr-0.3.0.tar.gz |
|---|---|
| Size | 16.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
469615e3de1cd5ee29daaa86f2d4701bbe67b30cecf95916e998c25c20400124
|
|
BLAKE2b-256 checksum How to use checksums |
282ffa5fe0e629534e271d991eb465fcb52cf80b8649d649df93c706ae211fe6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.9
|
Release files / prettypipeline_ocr-0.3.0-py3-none-any.whl
| Download URL | prettypipeline_ocr-0.3.0-py3-none-any.whl |
|---|---|
| Size | 14.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c780acf5a55590ce3d298569ea033fce0eb88196aeb16fde8859afb370c5a7e5
|
|
BLAKE2b-256 checksum How to use checksums |
f79d70f42f74c5f24494bbd72df55fba71b289797df1c890972d91136c4b89b5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.9
|
Security for prettypipeline-ocr 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.