DocStack
A self-hosted document pipeline: OCR, a local LLM, and an entity graph that builds and resolves itself. No document ever leaves the house.
Runs entirely on my own hardware6 entity types with deterministic resolutionBilingual OCR, French and EnglishExposes an MCP server for agent use
The problem
A document management system tells you where a file is. It does not tell you that three of them mention the same company under two spellings and a legal suffix.
Every product that does understand the content wants the content: uploaded, indexed, and stored somewhere else. For personal paperwork that is the wrong direction.
What it does
Documents land in Paperless, get converted to Markdown, enriched by a local LLM, and written into an Obsidian vault as a note plus an entity graph. Tags and a generated summary are written back to Paperless.
The graph is queryable: a GraphRAG endpoint answers questions with context assembled from the entities, and the whole thing is exposed as an MCP server so an agent can use it as a tool.
- Ingestion
- Webhook, plus a 5-minute catch-up poll
- Model
- llama3.1:8b on a local GPU
- Vault
- Obsidian, replicated by Syncthing
Architecture
Paperless-ngx
Ingestion, OCR in French and English, and the document store. The source of truth for the file itself.
Markdown conversion
Docling first, MarkItDown as a fallback, and Paperless' own OCR text as a last resort. Three layers, because conversion is where pipelines die.
Local LLM enrichment
Ollama with a pydantic schema and forced JSON output. Structured extraction, not free text that has to be parsed afterwards.
Entity graph
A closed six-type ontology with deterministic resolution, written into an Obsidian vault and fed back to Paperless as tags, always as a union, never overwriting.
Every stage runs on hardware I own
Under the hood
01Entity resolution is mostly not machine learning
Matching “M. Jean Dupont”, “Jean DUPONT” and “Dupont Jean” is a problem of accents, titles, and legal suffixes long before it is a problem of embeddings. The resolver normalises deterministically, uses fuzzy matching only as a tiebreak, and injects the entities it already knows into the prompt so the model stops inventing new spellings. Pairs it is unsure about go to a review file rather than being merged silently.
02A model that is switched off must not mean a failed job
The GPU node is a desktop machine that is not always on. Jobs whose model is unreachable wait, with backoff, and resume when it comes back. They never fail. That single decision is the difference between a pipeline that survives a power cut and one that needs a human every time.
03Only one writer may touch the tags
Two components enriching the same document will each add their own tags, and neither will be wrong. The rule is that exactly one system writes, and enrichment is a union so it can never destroy a correction made by hand.
Gallery
Try it
This one cannot be opened up, and that is the point.
The whole premise is that the documents stay on hardware I control. Publishing an instance would contradict the only feature that matters. What is on this page instead is the pipeline, the resolution logic, and the failure modes, which is the part worth reading anyway.
Links
Nothing to open from here.
Source
Not public
Not public. It is wired to my own document store.