Skip to content

Operations API

The four operations. Each has a sync form and an async a-prefixed form — use the async form inside a running event loop. parse is the only operation that needs the OCR server; classify, split, and extract accept either a ParseResult or a raw file path.

from ingestlib.operations import parse, classify, split, extract
from ingestlib.operations import aparse, aclassify, asplit, aextract

parse

ingestlib.operations.parse.pipeline.aparse async

aparse(path: Path | str, *, dpi: int = 200) -> ParseResult

Parse a document into a ParseResult (async).

path — PDF/DOCX/PPTX document, or a PNG/JPEG/WebP image (parsed as a one-page document) dpi — page render resolution for PDFs; 200 balances OCR accuracy against VLM token cost and memory (images keep their own size)

ingestlib.operations.parse.pipeline.parse

parse(path: Path | str, *, dpi: int = 200) -> ParseResult

Parse a document into a ParseResult.

Synchronous wrapper around aparse(). If you're already inside an event loop, use aparse() instead.

classify

ingestlib.operations.classify.classifier.aclassify async

aclassify(
    source: ParseResult | Path | str,
    categories: dict[str, str] | None = None,
    *,
    target_pages: str | None = None,
    max_pages: int | None = None,
) -> ClassifyResult

Classify a document's type (async).

source — a ParseResult from parse(), or a document/image path (PDF/DOCX/PPTX/PNG/JPEG/WebP — no OCR run; images classify through the vision LLM) categories — optional {snake_case_label: description}, max 20; when given, the result is one of these labels or "uncategorized". None uses rules.yaml's classify: preset; {} forces open-ended. target_pages — optional 1-based page selection like "1,3,5-7" max_pages — optional cap applied after selection (the 100-page hard cap always applies)

ingestlib.operations.classify.classifier.classify

classify(
    source: ParseResult | Path | str,
    categories: dict[str, str] | None = None,
    *,
    target_pages: str | None = None,
    max_pages: int | None = None,
) -> ClassifyResult

Classify a document's type. Sync wrapper — use aclassify() inside an event loop.

split

ingestlib.operations.split.splitter.asplit async

asplit(
    source: ParseResult | Path | str,
    *,
    category: str | None = None,
    max_chunk_tokens: int = DEFAULT_MAX_CHUNK_TOKENS,
    vocabulary: dict[str, str] | None = None,
    unmatched: str | None = None,
) -> SplitResult

Split a document into sections and natural chunks (async).

source — a ParseResult from parse(), or a PDF/DOCX/PPTX path (no OCR run; scans and images have no text layer — parse() them first) category — optional document-type label (e.g. from classify()) used in each chunk's embedding_text breadcrumb max_chunk_tokens — ceiling on chunk size; natural boundaries rule below it vocabulary — optional {section: description}, max 50; when given, Pass 1 is skipped and pages label against YOUR sections. None uses rules.yaml's split: preset; {} forces LLM discovery. unmatched — pages fitting no user category: "other" (default — an honest other section) | "require" (left-neighbor repair) | "skip" (dropped). None uses the preset.

ingestlib.operations.split.splitter.split

split(
    source: ParseResult | Path | str,
    *,
    category: str | None = None,
    max_chunk_tokens: int = DEFAULT_MAX_CHUNK_TOKENS,
    vocabulary: dict[str, str] | None = None,
    unmatched: str | None = None,
) -> SplitResult

Split a document into sections and natural chunks.

Sync wrapper — use asplit() inside an event loop.

extract

ingestlib.operations.extract.extractor.aextract async

aextract(
    source: ParseResult | Path | str,
    schema: Type[SchemaT],
    *,
    mode: str = "one",
    target_pages: str | None = None,
    instructions: str | None = None,
) -> ExtractResult

Extract schema instances from a document (async).

source — a ParseResult from parse() (region-level provenance), or a document path (native text, page-level provenance; scans and images have no text layer — parse() them first) schema — any Pydantic model; its top-level fields are what gets extracted and cited mode — "one": a single instance per document (invoice, contract); "many": every instance found (receipts, line items) target_pages — optional 1-based page selection like "1,3,5-7" instructions — optional domain guidance appended to the prompt, e.g. "totals include tax; dates as YYYY-MM-DD"

Provenance is verified, never trusted: cited regions must exist, and a value that can't be found in its cited source has its confidence capped (FieldValue.grounded says which). 100-page cap, as everywhere.

ingestlib.operations.extract.extractor.extract

extract(
    source: ParseResult | Path | str,
    schema: Type[SchemaT],
    *,
    mode: str = "one",
    target_pages: str | None = None,
    instructions: str | None = None,
) -> ExtractResult

Extract schema instances from a document. Sync wrapper — use aextract() inside an event loop.