AI-powered document analysis system for Paperless-ngx with Mistral OCR and local Ollama models
  • TypeScript 99.4%
  • CSS 0.4%
Find a file
beasty 06c357eaab
All checks were successful
Build and Publish Docker Images / build-frontend (push) Successful in 7m38s
Build and Publish Docker Images / build-backend (push) Successful in 7m39s
Use central Forgejo CI registry secret
2026-06-09 10:29:09 +02:00
.forgejo/workflows Use central Forgejo CI registry secret 2026-06-09 10:29:09 +02:00
.github Disable GitHub GHCR publishing workflow 2026-06-09 03:01:32 +02:00
apps fix: address code review findings 2026-05-18 20:54:00 +02:00
docs fix: address code review findings 2026-05-18 20:54:00 +02:00
packages fix: address code review findings 2026-05-18 20:54:00 +02:00
scripts fix: address code review findings 2026-05-18 20:54:00 +02:00
subagent-reports fix: address code review findings 2026-05-18 20:54:00 +02:00
.dockerignore fix: address code review findings 2026-05-18 20:54:00 +02:00
.env.example fix: address code review findings 2026-05-18 20:54:00 +02:00
.env.prod.readonly.example fix: address code review findings 2026-05-18 20:54:00 +02:00
.gitignore fix: address code review findings 2026-05-18 20:54:00 +02:00
.gitleaks.toml feat: add dedicated processing page with detailed LLM logs 2026-01-10 15:21:08 +01:00
AGENTS.md feat: replace processing pipeline with Pi agents 2026-05-13 21:26:55 +02:00
biome.json fix: address code review findings 2026-05-18 20:54:00 +02:00
CHANGELOG.md Prepare for GitHub release 2026-01-06 01:59:05 +01:00
CLAUDE.md fix: address code review findings 2026-05-18 20:54:00 +02:00
config.example.yaml fix: address code review findings 2026-05-18 20:54:00 +02:00
config.prod.readonly.example.yaml fix: address code review findings 2026-05-18 20:54:00 +02:00
CONTRIBUTING.md fix: address code review findings 2026-05-18 20:54:00 +02:00
docker-compose.yml fix: address code review findings 2026-05-18 20:54:00 +02:00
Dockerfile.frontend fix: address code review findings 2026-05-18 20:54:00 +02:00
lefthook.yml chore: switch linting to biome 2026-05-12 11:09:51 +02:00
LICENSE Prepare for GitHub release 2026-01-06 01:59:05 +01:00
Makefile feat: Add Search and Chat pages with vector search and RAG (#42) 2026-01-20 20:26:46 +01:00
package.json fix: address code review findings 2026-05-18 20:54:00 +02:00
pnpm-lock.yaml fix: address code review findings 2026-05-18 20:54:00 +02:00
pnpm-workspace.yaml feat: Add TypeScript backend with Effect-TS 2026-01-10 09:31:19 +01:00
progress.md fix: address code review findings 2026-05-18 20:54:00 +02:00
README.md fix: address code review findings 2026-05-18 20:54:00 +02:00
renovate.json fix: address code review findings 2026-05-18 20:54:00 +02:00
turbo.json fix: address code review findings 2026-05-18 20:54:00 +02:00

Paperless Local LLM

AI-powered document analysis system for Paperless-ngx

Automatic metadata extraction using Mistral AI for OCR and local Ollama models for intelligent title, correspondent, document type, and tag assignment.

License: MIT TypeScript pnpm Docker


Dashboard Preview


Features

  • OCR Processing — Mistral AI for high-quality text recognition from scanned documents
  • Automatic Metadata — Title, correspondent, document type, and tag extraction via local LLM models
  • Confirmation Loop — Large model analysis → Small model verification → Retry or manual review queue
  • Learning Mechanism — Prevents duplicate suggestions and learns from user feedback
  • Vector Search — Find similar documents for context using Qdrant
  • Tag-based Workflow — Independent processing steps with state tracking
  • Live Streaming — Real-time LLM responses in the frontend
  • Document Cases — Durable case state, human questions, and resumable Pi agent runs
  • Multi-language UI — English and German interface support
  • Docker Ready — Full Docker Compose setup included

Screenshots

Dashboard

Dashboard
Pipeline visualization, queue statistics, and service connections

Documents

Documents
Document queue with status tracking and processing logs

Settings

Settings
Service configuration and model selection

Document cases

Document Cases
Structured metadata decisions with resumable case state

Pending Review

Pending Review
Manual review queue for correspondents, document types, and tags

Quick Start

Prerequisites

  • Node.js 20+ — JavaScript runtime
  • pnpm — Fast, disk space efficient package manager
  • Docker & Docker Compose (optional, for deployment)
  • Running instances of:
    • Paperless-ngx — Document management system
    • Ollama — Local LLM inference with your preferred models
    • Qdrant — Vector database (or use the included Docker Compose)

Installation

# Clone the repository
git clone https://github.com/beastyrabbit/paperless-llm.git
cd paperless-llm

# Install all dependencies
pnpm install

Configuration

  1. Copy the example configuration:
cp config.example.yaml config.yaml
  1. Edit config.yaml with your settings:
paperless:
  url: "http://your-paperless-server:8000"
  token: "your-paperless-api-token"

mistral:
  api_key: "your-mistral-api-key"

ollama:
  url: "http://your-ollama-server:11434"
  model: "your-generation-model"     # e.g., llama3.2
  model_large: "your-analysis-model"
  model_small: "your-verifier-model"
  embedding_model: "nomic-embed-text"

qdrant:
  url: "http://your-qdrant-server:6333"
  collection: "paperless-documents"

Note: config.yaml is gitignored — your secrets stay local. In production, set PAPERLESS_LLM_CONFIG=/absolute/path/to/config.yaml when loading YAML config. The backend will not walk parent directories for config.yaml in production.

Running in Development

Full stack via Portless:

pnpm run dev

The application will be available at https://paperless-llm-web.localhost:1355. The backend route will be available at https://paperless-llm-api.localhost:1355. Portless uses the shared proxy port 1355; service names keep this project separate from other local projects while app ports are assigned automatically. If Portless is unavailable, use the direct localhost scripts below.

Fallback direct ports:

pnpm run dev:web       # Frontend on http://localhost:3765
pnpm run dev:backend   # Backend on http://localhost:8765

Docker Deployment

# Set environment variables (or create a .env file)
export PAPERLESS_URL=http://your-paperless:8000
export PAPERLESS_TOKEN=your-token
export MISTRAL_API_KEY=your-key
export OLLAMA_URL=http://host.docker.internal:11434

# Start all services
docker compose up -d

# View logs
docker compose logs -f

Tip: Use host.docker.internal to access Ollama running on your host machine. This works on Linux, macOS, and Windows thanks to the extra_hosts configuration in docker-compose.yml.

Architecture

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  Next.js        │────▶│  Effect-TS +    │────▶│  Paperless-ngx  │
│  Frontend       │     │  Effect Backend │     │                 │
└─────────────────┘     └────────┬────────┘     └─────────────────┘
                                 │
                    ┌────────────┼────────────┐
                    ▼            ▼            ▼
              ┌──────────┐ ┌──────────┐ ┌──────────┐
              │  Ollama  │ │ Mistral  │ │  Qdrant  │
              │   LLMs   │ │   OCR    │ │ VectorDB │
              └──────────┘ └──────────┘ └──────────┘

Processing Pipeline

Documents flow through tag-based states for independent, resumable processing:

Phase Input Tag Output Tag Description
OCR llm-pending llm-ocr-done Mistral AI OCR extraction
Correspondent llm-ocr-done llm-correspondent-done Assign correspondent
Document Type llm-correspondent-done llm-document-type-done Assign document type
Title llm-document-type-done llm-title-done Generate document title
Tags llm-title-done llm-tags-done Assign relevant tags
Complete llm-tags-done llm-processed Processing finished

API Reference

Settings

Method Endpoint Description
GET /api/settings Get current settings
PATCH /api/settings Update settings
POST /api/settings/test-connection/{service} Test service connection

Documents

Method Endpoint Description
GET /api/documents/queue Queue statistics
GET /api/documents/pending Documents by workflow status
GET /api/documents/{id} Document details

Cases

Method Endpoint Description
GET /api/cases List document cases
GET /api/cases/document/{id} Get or create a document case
POST /api/cases/document/{id}/run Run or resume a document case

Processing

Method Endpoint Description
POST /api/processing/{id}/start Start processing
GET /api/processing/{id}/stream SSE stream of LLM responses
POST /api/processing/{id}/confirm Confirm result

Project Structure

paperless-local-llm/
├── apps/
│   ├── web/                  # Next.js Frontend
│   │   ├── app/              # App router pages
│   │   │   ├── page.tsx      # Dashboard
│   │   │   ├── settings/     # Configuration UI
│   │   │   ├── documents/    # Document browser
│   │   │   ├── pending/      # Review queue
│   │   │   ├── cases/        # Document case queue
│   │   │   └── catalog/      # Catalog agent proposals
│   │   ├── components/       # React components
│   │   └── lib/              # Utilities & API client
│   │
│   └── backend/              # TypeScript + Effect-TS
│       ├── src/
│       │   ├── index.ts      # Application entry point
│       │   ├── server.ts     # Node HTTP server with Effect runtime
│       │   ├── api/          # Route handlers
│       │   ├── services/     # External service clients
│       │   ├── agents/       # Document processing agents
│       │   ├── config/       # Configuration management
│       │   └── layers/       # Effect dependency injection
│       └── tests/            # Vitest test suites
│
├── packages/
│   └── ui/                   # Shared shadcn/ui components
│
├── config.example.yaml       # Example configuration
├── docker-compose.yml        # Docker setup
└── README.md

Tech Stack

Layer Technologies
Frontend Next.js 16, React 19, TailwindCSS 4, shadcn/ui
Backend TypeScript, Effect-TS, Node HTTP server
AI/ML Ollama (local LLMs), Mistral AI (OCR), Qdrant (vector search)
Infrastructure Docker, Turborepo (monorepo), pnpm

Development

Frontend Commands

pnpm install          # Install dependencies
pnpm run dev          # Frontend + backend via Portless
pnpm run dev:web      # Frontend only (port 3765)
pnpm run build        # Production build
pnpm run lint         # Biome lint
pnpm run typecheck    # TypeScript check

Backend Commands

pnpm run dev:backend  # Backend only (port 8765)
pnpm run build        # Production build
pnpm run test         # Run tests with Vitest
pnpm run typecheck    # TypeScript check

Pre-commit Hooks

Git hooks are automatically active (located in .git/hooks/pre-commit).

# Run checks manually
pnpm run precommit

Active checks: gitleaks (secrets), TypeScript (types), Biome (linting), large files, merge conflicts

gitleaks is expected to be available on contributor machines because lefthook calls gitleaks protect --staged --no-banner. Install it through your package manager or brew install gitleaks; CI should keep it as a second gate for protected branches.

The Docker publish workflow uses the self-hosted ARC runner label arc-paperless-local-llm. Maintainers need that runner online for release images; forks can run the same build commands locally with Docker if the runner label is unavailable.

Environment Variables

Variable Description
PAPERLESS_URL Paperless-ngx base URL
PAPERLESS_TOKEN Paperless API token
MISTRAL_API_KEY Mistral OCR API key
OLLAMA_URL Ollama server URL
QDRANT_URL Qdrant server URL
PAPERLESS_LLM_API_TOKEN Optional backend API token
PAPERLESS_LLM_TRUSTED_UI_ORIGINS Optional comma-separated CORS allowlist

Pi Prompt Policy

Pi agent instructions, tools, schemas, and structured placeholders live in TypeScript. Do not reintroduce file-backed prompts or PromptService; Docker images no longer copy apps/backend/prompts.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License

This project is licensed under the MIT License — see the LICENSE file for details.