Skip to main content

Synchronous OCR using Gemini Vision API - A rewrite of pyzerox without async/litellm

Project description

Zerox Sync

A synchronous Python library for OCR and document extraction using Google's Gemini Vision API. This is a rewrite of pyzerox that removes async wrappers and replaces litellm with direct Gemini API integration.

Features

  • Synchronous API: No async/await complexity, simple function calls
  • Direct Gemini Integration: Uses Google's Gemini API directly without litellm dependency
  • PDF to Markdown: Convert PDFs to structured markdown using vision models
  • Concurrent Processing: Process multiple pages in parallel using ThreadPoolExecutor
  • Selective Page Processing: Extract specific pages from PDFs
  • Format Consistency: Maintain formatting across pages
  • Simple Setup: Just set GOOGLE_API_KEY and go

Installation

Using uv (Recommended)

uv is a fast Python package installer:

# Install uv if you haven't already
curl -LsSf https://astral.sh/uv/install.sh | sh

# Add zerox-sync to your project
uv add zerox-sync

Using pip

pip install zerox-sync

System Dependencies

You'll need poppler installed for PDF processing:

macOS:

brew install poppler

Ubuntu/Debian:

sudo apt-get install poppler-utils

Windows: Download and install from poppler releases

Quick Start

from zerox_sync import zerox
import os

# Set your Gemini API key
os.environ["GOOGLE_API_KEY"] = "your-api-key-here"

# Process a PDF
result = zerox(
    file_path="path/to/document.pdf",
    model="gemini-3-pro",
)

# Access the results
for page in result.pages:
    print(f"Page {page.page}:")
    print(page.content)
    print(f"Length: {page.content_length} chars\n")

print(f"Total time: {result.completion_time}ms")
print(f"Input tokens: {result.input_tokens}")
print(f"Output tokens: {result.output_tokens}")

API Reference

zerox()

Main function to perform OCR on a PDF document.

def zerox(
    cleanup: bool = True,
    concurrency: int = 10,
    file_path: str = "",
    image_density: int = 300,
    image_height: tuple = (None, 1056),
    maintain_format: bool = False,
    model: str = "gemini-3-pro",
    output_dir: Optional[str] = None,
    temp_dir: Optional[str] = None,
    custom_system_prompt: Optional[str] = None,
    select_pages: Optional[Union[int, List[int]]] = None,
    **kwargs
) -> ZeroxOutput:

Parameters:

  • cleanup (bool): Whether to cleanup temporary files after processing (default: True)
  • concurrency (int): Number of concurrent threads for page processing (default: 10)
  • file_path (str): Path or URL to the PDF file
  • image_density (int): DPI for PDF to image conversion (default: 300)
  • image_height (tuple): Image dimensions as (width, height) (default: (None, 1056))
  • maintain_format (bool): Maintain consistent formatting across pages (default: False)
  • model (str): Gemini model to use (default: "gemini-3-pro")
  • output_dir (Optional[str]): Directory to save markdown output (default: None)
  • temp_dir (Optional[str]): Directory for temporary files (default: system temp)
  • custom_system_prompt (Optional[str]): Override default system prompt (default: None)
  • select_pages (Optional[Union[int, List[int]]]): Specific pages to process (default: None)
  • **kwargs: Additional arguments passed to Gemini API

Returns:

ZeroxOutput object with:

  • completion_time (float): Processing time in milliseconds
  • file_name (str): Processed file name
  • input_tokens (int): Number of input tokens used
  • output_tokens (int): Number of output tokens generated
  • pages (List[Page]): List of Page objects containing:
    • content (str): Markdown content
    • page (int): Page number
    • content_length (int): Content length in characters

Advanced Usage

Process Specific Pages

result = zerox(
    file_path="document.pdf",
    select_pages=[1, 3, 5],  # Only process pages 1, 3, and 5
)

Maintain Format Consistency

result = zerox(
    file_path="document.pdf",
    maintain_format=True,  # Process pages sequentially to maintain formatting
)

Save to File

result = zerox(
    file_path="document.pdf",
    output_dir="./output",  # Markdown saved to ./output/{filename}.md
)

Custom System Prompt

result = zerox(
    file_path="document.pdf",
    custom_system_prompt="Extract only tables from this document in markdown format.",
)

Process from URL

result = zerox(
    file_path="https://example.com/document.pdf",
)

Adjust Concurrency

result = zerox(
    file_path="document.pdf",
    concurrency=5,  # Process 5 pages concurrently (default: 10)
)

Available Models

Zerox Sync supports various Gemini models:

  • gemini-3-pro (default): Most intelligent model
  • gemini-3-flash-preview: Fast with frontier-class performance
  • gemini-2.5-pro: Powerful reasoning model
  • gemini-2.5-flash: Balanced model with 1M token context
  • gemini-2.5-flash-lite: Fastest and most cost-efficient

Environment Variables

Differences from pyzerox

  1. Synchronous: No async/await - uses standard function calls
  2. Gemini Direct: Direct Gemini API integration instead of litellm
  3. Simple Dependencies: Fewer dependencies, no aiofiles/aiohttp/aioshutil
  4. ThreadPoolExecutor: Uses standard library threading instead of asyncio
  5. Requests: Uses requests library for HTTP instead of aiohttp

Error Handling

from zerox_sync import zerox
from zerox_sync.errors import (
    FileUnavailable,
    MissingEnvironmentVariables,
    ResourceUnreachableException,
    PageNumberOutOfBoundError,
)

try:
    result = zerox(file_path="document.pdf")
except MissingEnvironmentVariables:
    print("Please set GOOGLE_API_KEY environment variable")
except FileUnavailable:
    print("File not found or invalid path")
except ResourceUnreachableException:
    print("Could not download file from URL")
except PageNumberOutOfBoundError:
    print("Invalid page numbers specified")

Development

Setup

# Clone the repository
git clone https://github.com/yourusername/zerox-sync.git
cd zerox-sync

# Install uv if needed
curl -LsSf https://astral.sh/uv/install.sh | sh

# Sync all dependencies (including dev)
uv sync

Running Tests

# Run tests with uv
uv run pytest

# Or activate the virtual environment
source .venv/bin/activate  # macOS/Linux
# .venv\Scripts\activate   # Windows
pytest

Code Formatting

# Format code
black zerox_sync tests

# Lint
ruff check zerox_sync tests

Building for PyPI Distribution

Prerequisites

Install build tools:

uv add --dev build twine

Complete Release Workflow

1. Update version in pyproject.toml:

[project]
version = "0.1.1"  # Bump this version

2. Commit changes:

git add pyproject.toml
git commit -m "Bump version to 0.1.1"
git tag v0.1.1

3. Clean and build:

# Clean old builds
rm -rf dist/ build/ *.egg-info

# Build distribution files
python -m build

This creates:

  • dist/zerox_sync-0.1.1-py3-none-any.whl (wheel)
  • dist/zerox_sync-0.1.1.tar.gz (source)

4. Validate:

python -m twine check dist/*

5. Upload to PyPI:

# Test on TestPyPI first (optional)
python -m twine upload --repository testpypi dist/*

# Upload to production PyPI
python -m twine upload dist/*

PyPI Credentials Setup

Create ~/.pypirc:

[pypi]
username = __token__
password = pypi-YOUR_API_TOKEN_HERE

[testpypi]
repository = https://test.pypi.org/legacy/
username = __token__
password = pypi-YOUR_TESTPYPI_TOKEN_HERE

Get API tokens:

Semantic Versioning

  • Major (1.0.0): Breaking changes
  • Minor (0.1.0): New features, backward compatible
  • Patch (0.0.1): Bug fixes, backward compatible

Quick Reference

# Full release workflow
rm -rf dist/ build/ *.egg-info   # Clean
python -m build                   # Build
python -m twine check dist/*      # Validate
python -m twine upload dist/*     # Upload to PyPI
git push --tags                   # Push version tag

License

MIT License - see LICENSE file for details

Credits

This project is a synchronous rewrite of pyzerox by the getomni-ai team. The original project is an excellent async implementation with litellm support.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

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

zerox_sync-0.1.4.tar.gz (24.9 kB view details)

Uploaded Source

Built Distribution

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

zerox_sync-0.1.4-py3-none-any.whl (19.8 kB view details)

Uploaded Python 3

File details

Details for the file zerox_sync-0.1.4.tar.gz.

File metadata

  • Download URL: zerox_sync-0.1.4.tar.gz
  • Upload date:
  • Size: 24.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for zerox_sync-0.1.4.tar.gz
Algorithm Hash digest
SHA256 cf3a4632d6429d64b827ee235fe7fcf618895de14f7f8d4e72aea932e95f3244
MD5 c251c245b7650d42a41fd90576928375
BLAKE2b-256 3cace04db129a7171ed24c17afc9376bddb20e422a8e8c60273e8d20c096dcc8

See more details on using hashes here.

File details

Details for the file zerox_sync-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: zerox_sync-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 19.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for zerox_sync-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 cc3dd2731cd86ef8d03bad3852542d7ff71817e4df092fc319232f2c57244f47
MD5 ba3184f71b644eaca80ade1a75529148
BLAKE2b-256 dc8ea83d2f6ddf9abbf2f84b3ff688b5c475af053d65c6ff84f9540c079f2fb0

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