Charlotte, NC
ProjectsJune 1, 2025

Paperless Knowledge Graph

Tap image to enlarge
The Paperless Knowledge Graph turns a Paperless-ngx document archive (800+ scanned PDFs, receipts, contracts, tax forms, and medical records) into an intelligent, queryable knowledge base. Instead of manually searching through tags and filenames, you can ask natural language questions like "what does my lease say about pets?" or "what are my 2024 estimated tax payments?" and get synthesized answers with source citations. Document management systems are great at storing and tagging files, but terrible at understanding them. Paperless-ngx handles ingestion, OCR, and basic search, but answering questions that span multiple documents, extract specific data points, or require reasoning across a corpus is beyond what keyword search can do. I build data pipelines and AI solutions professionally, so the pattern of turning unstructured data into something queryable is familiar territory. The difference here is that I own the entire stack, from document ingestion to graph visualization, and can push the architecture further than a client engagement typically allows. The system is built as a pipeline with multiple layers: Raw documents flow through Paperless-ngx's built-in OCR, then through Paperless OCR Enhanced, a custom container that supplements Tesseract with LLM vision models when the base OCR is not enough. The AI-enhanced layer extracts structured data that traditional OCR misses: handwritten notes, complex table layouts, and contextual meaning from form fields. It maintains rolling context across pages so multi-page documents get processed with full awareness of what came before. This produces clean, structured text that feeds the downstream knowledge extraction. Before extraction begins, each document is classified into a domain-specific type: medical, financial, legal, insurance, property, tax, personal, work, or another structured record class. Each type gets a specialized extraction prompt with domain-specific fields, so a tax return and an insurance policy get different extraction strategies. The extraction itself is a four-pass pipeline:
  1. Pass 1: Type-specific structured metadata extraction (dates, amounts, identifiers stored as document properties)
  2. Pass 2: Entity typing with few-shot examples. The system identifies people, organizations, locations, products, medical conditions, named systems, documents, and events.
  3. Pass 3 (Verification): An independent LLM pass critiques the extracted entities and removes junk, duplicates, and over-extractions
  4. Pass 4 (Relationships): Relationship inference between verified entities
An entity resolution layer then uses RapidFuzz fuzzy matching combined with embedding similarity to merge obvious duplicates (e.g., "USAA" and "USAA Federal Savings Bank" become a single node). Borderline cases go through a conservative review path instead of being blindly merged. All entities and relationships are stored in a Neo4j 5 graph database with the APOC plugin for multi-hop traversal, creating a web of connections across the entire document corpus. All LLM calls (entity extraction, document summarization, query planning, verification, and natural language synthesis) route through a LiteLLM proxy that provides model abstraction, key management, rate limiting, and cost tracking. This allows hot-swapping between models (Gemini, OpenAI, Claude, and others) without changing application code, and provides a single point of observability for all AI inference costs. The system exposes multiple query paths depending on how much reasoning the question needs:
  • Fast entity/graph search (~2 seconds): Neo4j name matching for structured lookups, e.g. "find all documents mentioning Allstate" or "what entities are connected to Duke Energy?" Results render in the graph explorer where you can traverse relationships visually.
  • Deep AI synthesis (~60-120 seconds): A hybrid RAG pipeline that retrieves relevant document chunks via vector similarity (pgvector, 3072-dimensional indexes), trigram keyword search (pg_trgm), and entity graph traversal. Strands Agents build a bounded retrieval plan, review evidence gaps, verify the drafted answer, and produce a claim ledger alongside citations.
  • Timeline mode: Strands extracts dated events from retrieved evidence, then the deterministic query engine keeps source attribution and ordering explicit.
  • Strict mode: The system fails closed when evidence is weak instead of forcing a confident-sounding answer.
A Next.js application provides full visual access to the knowledge graph:
  • 2D/3D graph explorer using react-force-graph with physics simulation for navigating entity relationships across the entire document corpus
  • Natural language query interface with streaming SSE responses and real-time status updates as the system retrieves, analyzes, and synthesizes
  • Conversation history for multi-turn Q&A with persistent sessions
  • Document browser filterable by type, with per-document reindex support
  • Model selector for choosing between available LLMs via LiteLLM per query
  • Trace metadata for inspecting retrieval plans, evidence grades, verifier feedback, and claim support
  • Paperless-ngx: document ingestion, storage, and base OCR
  • Google Gemini Flash: document classification, entity extraction, query planning, verification, and synthesis
  • Strands Agents: bounded planner, verifier, timeline extractor, answer repair, and entity review support
  • Neo4j 5 + APOC: graph database for entity relationships and multi-hop traversal
  • PostgreSQL + pgvector + pg_trgm: vector similarity search (3072-dim indexes) and trigram keyword search
  • FastAPI: async Python backend and REST API
  • Next.js 16 + react-force-graph: frontend with 2D/3D graph visualization, query UI, and conversation history
  • LiteLLM: LLM proxy for model routing, key management, and cost tracking
  • Redis: query, vector, and graph result caching with TTL-based expiration
  • RapidFuzz: fuzzy string matching for entity resolution
  • Kubernetes + container images: current app deployment for the API, frontend, and Redis, with Docker Compose still available for local development
  • Graph over vector-only: Pure vector search finds similar documents but can't answer relationship questions ("who is my insurance agent and what policies do they manage?"). The graph layer captures structure that embeddings lose.
  • Multiple query modes: Not every question needs a 90-second synthesis. Fast graph search handles most lookups instantly, while deep, timeline, and strict modes are reserved for questions that genuinely need multi-document reasoning and evidence review.
  • Verification as a first-class step: The system does not just draft an answer. It verifies claims against retrieved sources, repairs weak answers when possible, and exposes trace data so the result can be inspected.
  • Exact freshness checks: The system compares Paperless document IDs against Neo4j document nodes, pgvector chunks, and stored document hashes. Count-only checks were not enough. Exact ID-set comparison catches partial indexing drift before it shows up as a missing or stale answer.
  • LLM proxy abstraction: Decoupling the application from any single LLM provider means the system survives API changes, rate limits, and pricing shifts without code changes.
  • Enhanced OCR as a separate layer: Running AI-enhanced OCR independently from Paperless-ngx means the base system stays vanilla and upgradeable, while the intelligence layer can evolve independently.
  • Queryable knowledge base spanning 800+ personal and business documents
  • Roughly 7,000 graph nodes, 25,000 relationships, and 6,000+ searchable document chunks
  • Sub-2-second answers for entity and relationship lookups
  • Natural language queries across tax records, contracts, insurance policies, medical records, and financial documents
  • Zero manual data entry, fully automated from document scan to queryable graph

Related projects

Garmin MCP Server

Open-source MCP server that exposes 34 Garmin Connect health and fitness tools to any AI assistant, with parallel fetching and Docker support.

blakemccarn.dev

Portfolio and blog built with Next.js 16, deployed to AWS via SST v4 with Cloudflare DNS, staging environments, and full IaC.

Charlotte Wire & Cable

Full-stack business website for a specialty wire distributor: searchable catalog, admin dashboard, and serverless AWS infrastructure via SST.

Paperless OCR Enhanced

Open-source Paperless-ngx companion service that uses LLM vision models to repair weak OCR and improve downstream document search.

RapidEPR

Founded and built an AI SaaS product that helps service members across five military services write evaluations, performance statements, and award narratives.