Koji

Koji

Documents in. Structured data out.
Open source document processing platform — parse, classify, and extract structured data from any document.

Stars License Try Koji Cloud

Try it now (no install) · Self-host · API Docs · Schema Guide

---

Koji extracting structured data from a scanned PDF

--- **96.2% extraction accuracy** across 11 document types. A 252-page scanned insurance policy parses and extracts in 15 seconds. Most document AI tools dump your entire file into an LLM and hope for the best. Koji uses an intelligent pipeline — it maps document structure, routes each field to the relevant sections, extracts in parallel, retries on misses, and scores confidence. The result: fewer tokens, faster extraction, higher accuracy. | | Koji | AWS Textract | Azure Doc Intelligence | Raw GPT-4 | |---|---|---|---|---| | **Self-hosted** | Yes (Apache 2.0) | No | No | No | | **Custom schemas** | YAML — any field, any doc type | Predefined models only | Predefined + custom training | Prompt engineering | | **Scanned PDFs** | Full OCR + intelligent chunking | Yes | Yes | No native OCR | | **Confidence scoring** | Per-field provenance + validation | Per-word confidence | Per-field confidence | None | | **100+ page docs** | Parallel chunking, no timeout | Page limits | Page limits | Context window limits | | **Cost** | Your LLM API key | $1.50/page | $0.01-0.10/page | ~$0.02/page (input tokens) | ## Quick Start **Option 1: Koji Cloud (fastest way to try it)** 1. Sign up at [console.getkoji.dev](https://console.getkoji.dev) 2. Add your LLM API key in **Settings → Model Catalog** (OpenAI, Anthropic, or any OpenAI-compatible provider) 3. Create a schema, upload a document, and see extraction results with source highlighting **Option 2: Self-host** ```bash # Install the CLI uv tool install git+https://github.com/getkoji/koji.git # Scaffold a project koji init myproject && cd myproject # Set your LLM key (or use ollama for fully local) export OPENAI_API_KEY=sk-... # Start the cluster koji start ``` Dashboard at [localhost:9400](http://localhost:9400). API at [localhost:9401](http://localhost:9401). ## Process Your First Document Define what you want to extract: ```yaml # schemas/invoice.yaml kind: schema name: invoice fields: vendor: type: string required: true invoice_number: type: string date: type: date total: type: number required: true items: type: array items: type: object properties: description: { type: string } quantity: { type: number } amount: { type: number } ``` Run it: ```bash koji process ./invoice.pdf --schema ./schemas/invoice.yaml ``` ```json { "vendor": "Acme Corp", "invoice_number": "INV-2026-0042", "date": "2026-03-15", "total": 4250.00, "items": [ { "description": "Widget A", "quantity": 100, "amount": 2500.00 }, { "description": "Widget B", "quantity": 50, "amount": 1750.00 } ] } ``` Push schemas to the cloud or use the HTTP API: ```bash koji push # Push schemas to Koji Cloud koji login # Authenticate with your account ``` ## How It Works Koji's extraction pipeline is smarter than "send everything to an LLM": ``` Document (PDF, image, DOCX, scan) | v 1. PARSE ---- OCR + layout detection (Docling, EasyOCR) | Scanned? Full-page OCR. Digital? Fast text extraction. | Large doc? Parallel chunking across GPU containers. v 2. MAP ------- Split at headings, classify sections, detect signals | (tables, dates, dollar amounts, key-value pairs) v 3. ROUTE ----- Score each field against each chunk using schema hints | Group co-located fields to minimize LLM calls v 4. EXTRACT --- Parallel LLM calls per group (not one giant prompt) | Wave-based field dependencies for conditional logic v 5. RECONCILE - Merge results, deduplicate arrays, confidence scoring | Per-field provenance: where in the document was this found? v 6. VALIDATE -- Type checking, enum matching, format normalization | Gap-fill retries for missing required fields v Structured JSON + confidence scores + source highlighting ``` A 232-page insurance policy: **2 LLM calls, 2.7 seconds, gpt-4o-mini.** ## Schema Hints Hints tell the router where to look — no hardcoded domain knowledge in the engine: ```yaml fields: policy_number: type: string required: true hints: look_in: [declarations] # Only search "declarations" sections patterns: ["policy.*number"] # Regex boost for matching chunks signals: [has_policy_numbers] # Boost chunks with policy-number-like strings effective_date: type: date depends_on: [form_type] # Extract after form_type is known extraction_hint_by: # Conditional extraction instructions form_type: "10-K": "Look for the fiscal year end date" "10-Q": "Look for the quarterly period end date" ``` ## Model Providers BYO model — local or API. No vendor lock-in. | Provider | Example | Notes | |----------|---------|-------| | OpenAI | `openai/gpt-4o-mini` | Set `OPENAI_API_KEY` | | Anthropic | `anthropic/claude-sonnet-4-20250514` | Set `ANTHROPIC_API_KEY` | | Ollama | `llama3.2` | Fully local, runs in the cluster | | Any OpenAI-compatible | `custom/model-name` | Set `KOJI_OPENAI_URL` | ## CLI | Command | Description | |---------|-------------| | `koji init [dir]` | Scaffold a project (`--template invoice`, `--list-templates`) | | `koji start` / `stop` | Start or stop the processing cluster | | `koji process ` | Parse + extract a document | | `koji extract ` | Extract from pre-parsed markdown | | `koji push` / `pull` | Sync schemas and pipelines with Koji Cloud | | `koji validate ` | Backtest a schema candidate against its corpus ground truth (doesn't go live) | | `koji schema versions / promote / release` | List versions; promote a candidate to a live release | | `koji classify run ` | Classify one document; show label, confidence, method, tier | | `koji classify versions / promote / release` | List classifier versions; promote a candidate to a live release | | `koji pipeline ls / deploy` | List pipelines; pin one to a schema version or set it back to auto | | `koji pipeline run ` | Run documents through a pipeline (the dashboard's manual run); `--no-wait` to submit async | | `koji pipeline result ` | Fetch a submitted pipeline job's documents + extraction | | `koji pipeline test ` | Dry-run a doc through a pipeline; show the routing decision (which classify label + branch + schema) without persisting | | `koji pipeline bench --corpus ` | Run a whole corpus through a pipeline and score routing (correct schema?) + extraction (per terminal schema), without persisting | | `koji run ` | Extract one corpus document (the Build tab's Run) | | `koji corpus ls / diff / add / tag / gt` | Manage a schema's validation corpus | | `koji review stats / ls / show / promote` | Triage the review queue (true counts via `stats`) and promote reviewed docs into the corpus | | `koji bench` | Benchmark accuracy against a local validation corpus | | `koji test` | Run extraction regression tests | | `koji score` | Score extracted values against ground truth, offline (same scorer the server uses) | | `koji doctor` | Check environment health | ## Documentation - **[Integration Guide](https://docs.getkoji.dev/integration/)** — HTTP API, presigned uploads, programmatic usage - **[Schema Guide](https://docs.getkoji.dev/schema-guide/)** — Fields, types, hints, arrays, dependencies - **[API Reference](https://docs.getkoji.dev/api-reference/)** — Complete endpoint reference - **[Configuration](https://docs.getkoji.dev/configuration/)** — koji.yaml, environment variables, model setup ## Contributing Contributions welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. ## License [Apache 2.0](LICENSE) — use it commercially, modify it, self-host it. No strings.