pyproject.toml
Rama main · réplica de lectura del repositorio original.
[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "py-idp"
version = "0.6.2"
description = "General-purpose, AI-enabled Intelligent Document Processing framework for Python. OCR + multimodal extraction with Pydantic schemas, confidence assessment, HITL review, and a built-in eval harness. Supports OpenAI, Anthropic, Ollama, and 8 China LLMs."
readme = "README.md"
requires-python = ">=3.10"
license = "AGPL-3.0-or-later"
authors = [
{ name = "Royce", email = "roycelam@umich.edu" },
]
keywords = [
"intelligent-document-processing",
"document-ai",
"ocr",
"llm",
"extraction",
"pydantic",
"multimodal",
"rag",
"information-extraction",
"invoice",
"pdf",
"schema-discovery",
]
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
]
dependencies = [
"pydantic>=2.5",
"typer>=0.12",
"rich>=13.7",
"httpx>=0.27",
"python-dotenv>=1.0",
"tenacity>=8.2",
"streamlit>=1.32",
"pdfplumber>=0.10", # lightweight fallback parser
"tiktoken>=0.7", # token-budget chunking (chunker.TokenChunker, extract optimizer)
# Template frontmatter is YAML, and the bundled sample templates now
# load automatically (TemplateRegistry.load_with_fallback), so a
# default install must be able to parse them. Before v0.6.2 PyYAML was
# optional and only needed by users who pointed at their own
# templates/ dir -- which meant the shipped samples raised ImportError.
"PyYAML>=6.0",
]
[project.optional-dependencies]
# PyYAML is a core dependency as of v0.6.2 (the bundled sample templates
# load by default). This extra is retained as an explicit no-op so the
# error message in idp.templates and any existing install instructions
# that say `pip install py-idp[templates]` keep working.
templates = ["PyYAML>=6.0"]
# Default parser (IBM Docling). Heavy: ~500MB model deps.
docling = ["docling>=2.0"]
# Optional OCR fallback for noisy scans
ocr = ["pytesseract>=0.3.10", "Pillow>=10.0"]
# OpenAI-compatible API (also works with Anthropic via compatible gateways)
openai = ["openai>=1.30"]
anthropic = ["anthropic>=0.27"]
ollama = ["ollama>=0.2"]
# Hugging Face vision-language models (Nanonets-OCR2-3B + Baidu Unlimited-OCR).
# Heavy: ~3 GB pip install (torch + transformers), ~7 GB model weights.
# Runs offline on MPS (Apple Silicon) or CUDA. No API key needed.
hf-vlm = [
"torch>=2.1",
"transformers>=4.45",
"accelerate>=0.34",
"safetensors>=0.4",
"Pillow>=10.0",
"huggingface-hub>=0.24",
]
# API server example (FastAPI + uvicorn)
api = ["fastapi>=0.110", "uvicorn[standard]>=0.27"]
# China LLM providers (OpenAI-compatible; no extra deps required — uses httpx)
# The `openai` SDK is optional; install it if you prefer the SDK client to raw HTTP.
china = ["openai>=1.30"]
# PDF-to-image rendering for multimodal backends (PdfPagesParser + NanonetsVLBackend).
# Pillow is used for image preprocessing; pdf2image requires poppler-utils at runtime
# (apt install poppler-utils / brew install poppler).
pdf-render = ["pdf2image>=1.16", "Pillow>=10.0"]
# Evaluation
eval = ["datasets>=2.18", "pandas>=2.1"]
dev = [
"pytest>=8.0",
"pytest-asyncio>=0.23",
"pytest-benchmark>=4.0",
"hypothesis>=6.80",
"httpx>=0.27", # FastAPI TestClient + integration tests
"ruff>=0.3",
"mypy>=1.8",
"types-PyYAML",
"reportlab>=4.0",
]
# Building the documentation site (mkdocs-material + mkdocstrings).
# Not required for running py-idp; only for `mkdocs build` / `mkdocs serve`.
docs = [
"mkdocs>=1.6",
"mkdocs-material>=9.5",
"mkdocstrings[python]>=0.25",
"pymdown-extensions>=10.7",
]
# Running the example notebooks in examples/notebooks/. nbformat/nbconvert are
# needed for re-executing notebooks; ipykernel to register the Python kernel
# in Jupyter. pandas is used by the batch notebook's DataFrame cell.
notebooks = [
"nbformat>=5.10",
"nbconvert>=7.0",
"ipykernel>=6.0",
"pandas>=2.1",
]
[project.scripts]
idp = "idp.pipeline.cli:app"
[project.urls]
Homepage = "https://github.com/rollroyces/py-idp"
Documentation = "https://rollroyces.github.io/py-idp/"
Issues = "https://github.com/rollroyces/py-idp/issues"
Changelog = "https://github.com/rollroyces/py-idp/blob/main/CHANGELOG.md"
# README in non-English languages — PyPI only renders one README per project,
# so non-English readers land here from the project page sidebar.
"繁體中文 README" = "https://github.com/rollroyces/py-idp/blob/main/README.zh-TW.md"
"简体中文 README" = "https://github.com/rollroyces/py-idp/blob/main/README.zh-CN.md"
"PyPI setup guide" = "https://github.com/rollroyces/py-idp/blob/main/docs/PYPI_SETUP.md"
[tool.setuptools.packages.find]
where = ["src"]
# Ship the bundled sample templates inside the package so
# `pip install py-idp` actually gets them. Without this they live only
# at the repo root (outside src/) and are absent from both the wheel
# and the sdist, leaving every installed user with an empty
# TemplateRegistry. `idp.templates` resolves the packaged copies at
# `importlib.resources` when no IDP_TEMPLATE_DIR / ./templates is set.
[tool.setuptools.package-data]
"idp.templates_pkg" = ["*.md"]
[tool.setuptools]
include-package-data = true
[tool.ruff]
line-length = 100
target-version = "py310"
# Jupyter notebooks (examples/notebooks/*.ipynb) are excluded — they have
# cell-by-cell imports and execution-order quirks that don't fit ruff's
# module-level model. Use `nbqa ruff` if you want notebook linting.
extend-exclude = ["examples/notebooks/*.ipynb"]
[tool.ruff.lint]
select = ["E", "F", "I", "B", "UP", "SIM"]
ignore = ["E501"]
[tool.ruff.lint.per-file-ignores]
# Typer requires typer.Option/Argument in defaults — B008 is a false positive
# for any @app.command()-decorated function.
"src/idp/pipeline/cli.py" = ["B008"]
[tool.mypy]
python_version = "3.12"
# Plain mypy caught 13 real bugs (str→float assignment, dead string-passing
# code, None-attr crash, SqlStorage/Protocol signature mismatch). These extra
# flags add the highest-value checks WITHOUT the annotation churn that
# --strict would force on Typer CLI commands and Streamlit glue code:
no_implicit_optional = true
warn_unreachable = true
warn_redundant_casts = true
check_untyped_defs = true
# Optional deps (anthropic, docling, pytesseract) are imported lazily.
ignore_missing_imports = true
[tool.pytest.ini_options]
testpaths = ["tests"]
asyncio_mode = "auto"
addopts = "-v --tb=short"
markers = [
"slow: marks tests as slow (real-network / real-LLM); skipped by default with `-m 'not slow'`",
]