Docpick

io.github.ArkNillPublished by GitHub account ArkNillv0.1.2Updated Oct 25, 2026

Schema-driven document extraction with local OCR + LLM. Document in, Structured JSON out.

VerifiedSTDIODesktop onlyFiles & StorageData & Analytics

Overview

AI-generated overview

Docpick is a local, schema-driven document extraction pipeline that turns invoices, receipts and forms into validated structured JSON using local OCR and a self

What you can do
Extract structured JSON from PDFs and images using built-in or custom Pydantic/JSON schemas, with per-field confidence scores and partial results on failure. Run OCR only, in Korean and English among other languages, with automatic fallback between PaddleOCR, EasyOCR, GOT-OCR2.0 and VLM engines. Validate extracted data with check-digit algorithms, cross-field rules and cross-document consistency checks. Batch-process whole directories with parallel workers and list or inspect the eight built-in schemas.
When to use it
Useful when you need to convert business documents such as invoices, receipts, bills of lading, tax forms, bank statements or ID documents into structured data while keeping everything on your own machine. Also fits bulk extraction of document folders and validation of trade-document sets.
Requirements
Runs locally as a Python package (Python 3.11+) installed with pip, plus optional OCR extras. Needs a local or OpenAI-compatible LLM endpoint such as vLLM or Ollama, configured by CLI or YAML. GPU is required for the GOT-OCR2.0 and VLM engines; CPU suffices for PaddleOCR and EasyOCR.
Before you install
Extracted data can include sensitive personal and financial details from IDs, bank statements and tax forms; keep the local LLM endpoint and output files protected. The pipeline writes result files and batch output directories. Extraction may return partial or unvalidated data, so check the reported validation errors and confidence before relying on results.

Installation

In SourceWeft

  1. Open Docpick in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

Docpick

[PyPI] [Python] [License] [Tests]

한국어 문서 · llms.txt

Document in, Structured JSON out. Locally. With your schema.

docpick is a lightweight, schema-driven document extraction pipeline that combines local OCR engines with local LLMs to extract structured JSON from any document — invoices, receipts, bills of lading, tax forms, and more.

  • Zero cloud dependency — runs entirely on your machine (CPU or GPU)
  • Custom schemas — define your own Pydantic models or use 8 built-in document schemas
  • Validation built-in — checkdigit verification, cross-field rules, cross-document consistency
  • Apache 2.0 — no GPL/AGPL dependencies

Install

bash
pip install docpick            # core (LLM extraction only)pip install docpick[paddle]    # + PaddleOCR (recommended)pip install docpick[easyocr]   # + EasyOCR (Korean-optimized)pip install docpick[got]       # + GOT-OCR2.0 (GPU, vision-language)pip install docpick[all]       # all OCR backends

Requirements: Python 3.11+ / LLM endpoint (vLLM, Ollama, or OpenAI-compatible)

Quick Start

Python API

python
from docpick import DocpickPipelinefrom docpick.schemas import InvoiceSchema
pipeline = DocpickPipeline()result = pipeline.extract("invoice.pdf", schema=InvoiceSchema)
print(result.data)           # Structured dict matching schemaprint(result.validation)     # Validation errors/warningsprint(result.confidence)     # Per-field confidence scores

CLI

bash
# Extract structured datadocpick extract invoice.pdf --schema invoice --output result.json
# OCR only (no LLM)docpick ocr document.png --lang ko,en
# Validate extracted JSONdocpick validate result.json --schema invoice
# Batch process a directorydocpick batch ./documents/ --schema invoice --output ./results/ --concurrency 4
# List available schemasdocpick schemas list
# Show schema detailsdocpick schemas show invoice

Built-in Schemas

SchemaDocument TypeKey Validations
invoiceCommercial invoicesLine item sums, tax ID checkdigit, date order
receiptRetail/restaurant receiptsTotal = subtotal + tax + tip
bill_of_ladingOcean/air B/LContainer weight sums, ISO 6346, HS code format
purchase_orderPurchase ordersPO total = line items, delivery date order
kr_tax_invoiceKorean e-tax invoice (세금계산서)Business number checkdigit (x2), supply/tax/total sums
bank_statementBank statementsIBAN mod97, period date order
id_documentPassport/ID (ICAO 9303)MRZ, ISO 3166 country codes, date ranges
certificate_of_originCertificate of OriginISO 3166 alpha-2 country codes

Custom Schemas

Define your own schema with Pydantic:

python
from pydantic import BaseModelfrom docpick import DocpickPipelinefrom docpick.validation.rules import SumEqualsRule, RequiredFieldRule
class MyDocument(BaseModel):    """Custom document schema."""    company_name: str | None = None    total_amount: float | None = None    tax_amount: float | None = None    net_amount: float | None = None    items: list[dict] | None = None
    class ValidationRules:        rules = [            RequiredFieldRule("company_name"),            SumEqualsRule(["net_amount", "tax_amount"], "total_amount"),        ]
pipeline = DocpickPipeline()result = pipeline.extract("my_document.pdf", schema=MyDocument)

Or use a JSON Schema file:

bash
docpick extract document.pdf --schema my_schema.json

Validation

Check Digit Algorithms

AlgorithmUse Case
kr_business_numberKorean business registration number (10 digits)
luhnCredit card numbers
iso_6346Shipping container numbers
iban_mod97International bank account numbers
awb_mod7Air waybill numbers
mrzMachine Readable Zone (passport/ID)

Cross-Field Rules

RuleDescription
SumEqualsRuleSum of fields equals target (with tolerance)
DateBeforeRuleDate A must precede Date B
RequiredFieldRuleField must be non-null and non-empty
FieldEqualsRuleTwo fields must be equal
RangeRuleNumeric field within min/max bounds
RegexRuleField matches regex pattern

Cross-Document Validation

Validate consistency across related documents (e.g., Invoice + B/L + Packing List):

python
from docpick.validation.cross_document import create_trade_document_validator
validator = create_trade_document_validator()result = validator.validate({    "invoice": invoice_data,    "bl": bl_data,    "packing_list": packing_list_data,    "certificate": certificate_data,})print(result.is_valid)

OCR Engines

EngineTypeGPULanguagesBest For
PaddleOCRTraditional OCROptional111General documents (default)
EasyOCRTraditional OCROptional80+Korean text
GOT-OCR2.0Vision-LanguageRequiredMultiComplex layouts
VLMVision-LanguageRequiredMultiDirect image → JSON

2-Tier Auto Engine

The default auto engine uses confidence-based fallback:

  1. Tier 1 (CPU): PaddleOCR → EasyOCR
  2. Tier 2 (GPU): GOT-OCR2.0 → VLM

If Tier 1 average confidence falls below threshold (default 0.7), automatically escalates to Tier 2.

LLM Providers

ProviderEndpointDefault Model
vLLMhttp://localhost:8000/v1Qwen/Qwen3.5-32B-AWQ
Ollamahttp://localhost:11434qwen3.5:7b

Configure via CLI or YAML:

bash
docpick config set llm.provider ollamadocpick config set llm.base_url http://localhost:11434docpick config set llm.model qwen3.5:7b

Error Handling

The pipeline is designed to be resilient:

  • OCR failure → automatic fallback to next available engine
  • LLM JSON parse failure → automatic retry with correction prompt (up to 1 retry)
  • Partial results → returns whatever was extracted, with errors logged in result.errors
  • Document load failure → returns empty result with error message
python
result = pipeline.extract("damaged.pdf", schema=InvoiceSchema)if result.errors:    print("Pipeline warnings:", result.errors)if result.data:    print("Partial extraction:", result.data)

Batch Processing

Process entire directories with parallel workers:

python
from docpick.batch import BatchProcessorfrom docpick.schemas import InvoiceSchema
processor = BatchProcessor(concurrency=4)result = processor.process_directory(    "./invoices/",    schema=InvoiceSchema,    recursive=True,)
print(f"Processed {result.succeeded}/{result.total} files")for path, extraction in result.results.items():    print(f"{path}: {extraction.data.get('total_amount')}")

Architecture

mermaid
flowchart TD    A["📄 Document\n(PDF / Image)"] --> B["DocumentLoader\n(pypdfium2)"]    B --> C["Tier 1: OCR\n(PaddleOCR / EasyOCR)\nCPU"]    C --> D{"Confidence\n≥ threshold?"}    D -->|"yes"| F["LLM Extractor\n(vLLM / Ollama)\nSchema prompt"]    D -->|"no"| E["Tier 2: VLM\n(GOT / VLM)\nGPU"]    E --> F    F --> G["Pydantic Validation"]    G --> H["✅ ExtractionResult"]

License

Apache 2.0 — all dependencies are Apache 2.0 or MIT licensed.


Part of the QuartzUnit ecosystem — composable Python libraries for data collection, extraction, search, and AI agent safety.

Source: README.md at commit 173a35d

Tools

0
SourceWeft has not started this package in its sandbox yet, so its tools are not known.

Version history

1
  1. v0.1.2LatestSep 16, 2026

Score

50% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts

    Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.

  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listed15 pts

    Answer tools/list without a credential, or ship a package that starts in a sandbox without one.

  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts