Skip to main content
GoldenMatch does not require structured data. Point it at a pile of PDFs or images (business cards, intake forms, invoices, receipts, scanned directories) and it extracts structured records against a schema you control, then hands them straight to the ER pipeline. One vision call per page classifies and extracts: a form or card becomes one row, a table becomes N rows.

Install

Document ingest is an optional extra (adds pymupdf + Pillow for PDF rasterization and image loading):
The default backend calls an OpenAI vision model (gpt-4o). Set an API key — the personal key is preferred so a work-scoped key is never used by accident:
import goldenmatch.documents and the MCP server both degrade gracefully when the extra or the key is absent — nothing else in GoldenMatch requires them.

The two-step workflow

You own the target schema. The recommended flow is: let a vision model propose a schema from one representative document, review it, then ingest the whole batch against it.

Python

Every extracted row carries three sidecar columns: _source_file, _source_page, and _extract_confidence. Pass return_report=True to ingest_documents to also get an IngestReport (n_files, n_rows, and per-file errors — a bad file is recorded and the batch continues rather than aborting). You can define a schema by hand instead of suggesting one:
kind (text | email | phone | address | date | number) and an optional hint guide the extractor. Fields absent from a given document come back null.

CLI

run writes .csv or .parquet. Both commands take --backend (default vlm) and --model (default gpt-4o).

Other surfaces

The same capability is exposed everywhere GoldenMatch runs: MCP, A2A, and REST are path-based (the caller passes server-accessible file paths or, for REST/Web, uploads); the Web UI handles browser uploads.

How it works

  • VLM-first, one call per page. A single vision call classifies the document and extracts fields in one shot. The backend is a pluggable Extractor seam behind an injectable transport, so the stack is fully offline-testable (swap in a FakeExtractor).
  • Rust kernel = single source of truth. Schema validation, response parsing, prompt building, and record normalization live in the documents-core Rust crate, bound to Python (native) and TypeScript (WASM). Pure-Python is a byte-identical fallback.
  • Tables fan out. A document containing several records (a roster, a directory) yields one row per record; a single-entity document (a card, a form) yields one row.

Notes and limits

  • Extraction quality tracks the vision model. On clean documents it is near-perfect and never fabricates a value for a field that is absent; on genuinely hard inputs (unusual proper nouns, heavy scan degradation) it can misread — those errors are the model’s ceiling, not the pipeline’s.
  • kind: date / kind: number are advisory hints to the extractor, not post-hoc coercion.
  • Each page is one vision API call; cost and latency scale with page count. Ingest is parallel-safe across files.