The Architecture
Layer 1: Paperless-ngx
Layer 2: Enhanced OCR with Gemini Flash
- A document gets tagged ocr-redo in Paperless (manually or via automation)
- The enhanced OCR container picks it up, sends the document to Gemini Flash
- Gemini extracts structured data that Tesseract missed: table contents, form field values, handwritten annotations
- On success, the document gets tagged ocr-complete with the enhanced text stored alongside the original
- On failure, it gets tagged ocr-failed for manual review
Layer 3: The Knowledge Graph
- People (names, roles, relationships)
- Organizations (companies, government agencies, medical providers)
- Account identifiers (policy numbers, account IDs, reference numbers)
- Monetary amounts (payments, premiums, deductibles, income figures)
- Dates (filing dates, effective dates, expiration dates)
- Addresses (physical locations tied to people or organizations)
Layer 4: Agent-Assisted Retrieval and Verification
- Quick search for entity lookups and graph exploration
- Deep synthesis for multi-document questions that need retrieval, ranking, and citations
- Timeline mode for questions where the order of events matters
- Strict mode for answers that should fail closed when the sources are weak
- Turn the user's question into a retrieval plan
- Decide which retrieval channels to use: vector, keyword, entity search, graph traversal, or timeline extraction
- Check whether the initial evidence has obvious gaps
- Verify the drafted answer against the retrieved sources
- Build a claim ledger so the UI can show which claims are well-supported, weak, or missing evidence
- Repair the answer when verification finds a problem
The LLM Proxy: LiteLLM
- Model abstraction: My application code calls a model alias rather than specific model versions. When a provider releases a new model, I update the mapping in one place.
- Key management: Virtual keys for different services with separate budgets and rate limits. The OCR pipeline has its own key with its own spending cap.
- Cost tracking: Every API call gets logged with token counts and costs. I know exactly how much the knowledge graph costs to run per month.
- Failover: If one provider is down or rate-limited, LiteLLM can fall back to another model automatically.
Results
Tech Stack
- Paperless-ngx for document ingestion, base OCR, and tagging
- Gemini Flash for AI-enhanced OCR, classification, extraction, and synthesis
- Neo4j for entity storage and relationship traversal
- PostgreSQL + pgvector + pg_trgm for semantic chunk search and keyword search
- LiteLLM as a self-hosted LLM proxy for model routing, cost tracking, and failover
- Strands Agents for bounded query planning, timeline extraction, verification, and repair
- Python for the orchestration layer, extraction pipelines, and API
- Next.js for the graph explorer, document browser, and query UI
- Container images and Kubernetes for the current app deployment, with Docker Compose still useful for local development