Repository navigation
Releases: lucaperl/paperless-local-ai
Release list
v0.5.2
This release adds compatibility with Paperless-ngx 3.2.1 and 3.3.0.
Compatibility
- support Paperless-ngx 3.1.0–3.3.0
- verify the relevant Paperless 3.3.0 AI prompt, API and UI integration contracts
- make the suggestion bridge use the Paperless 3.x prompt-contract family instead of requiring a new allowlist entry for every minor release
- keep Paperless 4.x fail-closed until reviewed
v0.5.1
This release adds Paperless-ngx 3.2.0 compatibility and updates the OCR integration for the OCRmyPDF version shipped with it.
Paperless-ngx 3.2.0
- add compatibility with Paperless-ngx 3.2.0
- support its bundled OCRmyPDF 17.11.0 runtime while retaining support for OCRmyPDF 17.7.1
- update the native Document Suggestions bridge for Paperless 3.2.0's new classification prompt behavior, including the automatically added similar-document / Tantivy context
- keep new-correspondent matching exact and fail closed when the Paperless prompt contract cannot be identified safely
- retain compatibility with the existing Paperless 3.0 / 3.1 suggestion paths covered by PLAI
OCR compatibility
- extend the existing native fpdf2 DPI workaround to the source-verified OCRmyPDF 17.11.0 contract
- keep the workaround explicitly version-gated instead of applying it to unknown OCRmyPDF releases
- test the OCR plugin against both OCRmyPDF 17.7.1 and 17.11.0 in CI
Release validation
- release publication now reruns the real OCRmyPDF 17.7.1 / 17.11.0 compatibility matrix before images are published
- document Paperless-ngx 3.2.0 compatibility prominently in the README
This is a normal image update. No ports, mounts, services, secrets or required deployment settings change.
v0.5.0
This release adds local multi-turn document chat / RAG as a third first-class capability alongside OCR and metadata automation.
Highlights
-
Document chat inside Paperless
- persistent server-side multi-turn conversations
- scopes for the current document, all documents, tags, correspondents and document types
- direct links back to the Paperless source documents
- per-chat controls for model, Thinking, context, Top-K, temperature and output length
-
Lightweight RAG for modest hardware
- separate regenerable SQLite index with no additional vector database or service
- a normal chat turn uses exactly one embedding request and one chat-generation request
- no query-rewrite LLM, reranker, refine chain, summarizer or agent loop
- OCR, metadata, chat and index embedding continue to share the same global AI resource slot
-
Controllable retrieval and index behavior
- configurable retrieval history, similarity/document limits, adjacent chunks and diagnostics
- editable query/document embedding templates and RAG prompt assembly
- explicit Sync, Rebuild, Pause and Resume controls
- rebuilds use a staging index, so the active index remains available until the replacement is ready
- interrupted rebuilds can be resumed instead of starting over
-
Paperless integration
- chat runs directly in the Paperless UI
- global chat, retrieval and index settings live in the Control Center
- the integration is same-origin and fail-open, without patching Paperless or exposing internal credentials to the browser
-
Smaller classification prompts by default
- default document text limit reduced from 40,000 to 6,000 characters
- long documents now keep 80% from the beginning and 20% from the end
- existing saved classification settings are not overwritten
Document chat remains opt-in. To enable it, install the configured embedding model in Ollama and start the first index build explicitly from Control Center → Document Chat → Index status.
v0.4.0
0.4.0 makes correspondent matching more flexible.
Changed
- allow Minimum similarity to be configured from 0–100%
- allow Minimum winner margin to be configured from 0–100 percentage points
- remove the fixed minimum-name-length requirement for fuzzy correspondent matching
- keep the existing defaults at 91% similarity / 4 pp winner margin
v0.3.9
0.3.9 improves correspondent matching and fixes PaddleOCR processing for certain hybrid PDFs on Paperless-ngx 3.1.0 / OCRmyPDF 17.7.1.
Configurable correspondent matching
Correspondent resolution can now be tuned directly from the Control Center:
- configure the Minimum similarity and Minimum winner margin used for fuzzy correspondent matching;
- new installations and existing setups without explicit values use 91% similarity / 4 percentage points winner margin;
- unique normalized exact matches continue to bypass fuzzy thresholds;
- fuzzy matches are only accepted when both the similarity and ambiguity-margin checks pass;
- plausible unmatched correspondents are still never auto-created;
- a new read-only matching tester shows the top candidates, similarity scores, winner margin and the exact decision gates without calling Ollama or modifying Paperless.
The same configured thresholds are used consistently by the Rust and Python compatibility paths.
Hybrid PDF OCR fix
Fixes a failure when using the native OCRmyPDF generate_ocr() / OcrElement integration with fpdf2 on certain hybrid or vector PDFs.
On OCRmyPDF 17.7.1, these documents can expose a zero PdfInfo DPI after PaddleOCR has completed successfully, causing the fpdf2 renderer to fail with a ZeroDivisionError.
paperless-local-ai now includes a narrowly scoped, version-gated compatibility fix for OCRmyPDF 17.7.1. Renderer DPI is selected from:
- the DPI of the returned OCR
OcrElement; - usable PDFInfo DPI;
- OCRmyPDF's vector-page DPI fallback.
This also preserves text-layer geometry when the OCR-only raster is downsampled.
The workaround is deliberately limited to OCRmyPDF 17.7.1 and will not be applied blindly to future OCRmyPDF versions. Future Paperless/OCRmyPDF upgrades must be compatibility-tested before extending or removing it.
v0.3.8
0.3.8 adds compatibility with the Paperless-ngx 3.1 AI suggestion taxonomy schema and introduces a public interactive demo of the Control Center.
Paperless-ngx 3.1 suggestion compatibility
The Suggestion Bridge now adapts its response to the JSON schema requested by Paperless:
- Paperless-ngx 3.0.5 keeps the existing list-based taxonomy response format.
- Paperless-ngx 3.1.0 uses the new nested taxonomy-choice format with
existing_idsandnew_names. - The response format is detected from the request schema instead of being tied to a hardcoded Paperless version.
- The Python compatibility bridge mirrors the Rust implementation.
This change concerns the Paperless AI suggestion interface. The separately documented OCR/OCRmyPDF reference environment remains unchanged.
Live Control Center demo
A browser-only interactive Control Center demo is now available at:
https://lucaperl.github.io/paperless-local-ai/demo/
The demo uses the same Control Center UI source as the production application, backed entirely by synthetic Paperless, Ollama and OCR data.
It includes:
- synthetic documents and Paperless taxonomy values;
- Hybrid History match, LLM fallback and conservative classification examples;
- interactive prompt and JSON-schema previews;
- simulated model results;
- editable settings, Tag Guidance and configuration history;
- local resettable browser state.
The demo has no Paperless, Ollama or OCR backend and is prevented from making network requests.
v0.3.7
0.3.7 fixes restart races in the cold-idle lifecycle introduced with 0.3.5.
Heavy OCR, History and LLM resources are still released as soon as their work is complete. The lightweight OCR and Core services now remain available for a five-minute quiet period before their containers are recycled, avoiding follow-up Paperless requests colliding with an intentional restart.
OCR lifecycle
- The PaddleOCR worker keeps the existing 5-second warm-session window for consecutive pages.
- When that window expires, the heavyweight Paddle worker is stopped and the shared
ai.lockis released immediately. - The lightweight OCR HTTP service then remains available for five minutes.
- New OCR work during that period can start a fresh Paddle worker without colliding with a container restart.
- After five minutes of genuine OCR inactivity, the service exits cleanly and the existing restart policy starts a fresh container/cgroup for cold idle.
Unified Core lifecycle
- History helpers and the configured Ollama model are still released immediately after use.
- After a metadata batch or explicit History refresh, the Core now schedules its clean container recycle after five minutes of inactivity instead of recycling immediately.
- New metadata work cancels a pending recycle.
- Suggestion Bridge classification activity postpones an already scheduled recycle, keeping Paperless AI-suggestion requests available after metadata processing.
- After the quiet period expires, the Core still recycles cleanly to return its cgroup to a cold idle state.
Why this change
Real Paperless testing exposed two restart races:
- During batch imports, subsequent OCR requests could arrive while the OCR container was intentionally recycling, causing retryable
503responses and unnecessary retry delays. - After metadata processing, Paperless could request an AI suggestion while the unified Core was recycling, making the Suggestion Bridge temporarily unavailable.
Separating heavyweight resource teardown from lightweight service-container recycle removes both races without keeping PaddleOCR, History helpers or Ollama resident.
v0.3.6
0.3.6 improves Hybrid History tagging, adds an optional Paperless-ngx Settings shortcut to the Control Center, and fixes nested tag writeback.
Hybrid History tag-set reuse
- Hybrid History now votes on complete reviewed leaf-tag sets instead of individual tags.
- Reviewed multi-tag combinations can be reused directly when the complete set has sufficient historical evidence.
- History never synthesizes combinations that have not been observed in reviewed documents; uncertain cases continue to fall back to the LLM.
- Confident History matches skip all tag-related LLM prompt material and insert the complete reviewed tag set after base metadata validation.
- The default confident-History similarity threshold is now
0.62; minimum support remains2and minimum weighted winner share remains0.50.
Advanced History matching
The Control Center now exposes advanced controls for:
- minimum History similarity;
- minimum neighborhood support;
- minimum weighted winner share.
These settings are stored with the versioned App Settings configuration and automatically invalidate the cached History index when changed.
Paperless Settings shortcut
- Added an optional paperless-local-ai shortcut to the Paperless-ngx Settings page, opening the Control Center directly from Paperless.
- The integration uses Paperless'
PAPERLESS_APPSmechanism and a lightweight Django app exposed through the existing integration mount; no Paperless fork, browser extension, additional container, or background service is required. - The Control Center verifies that the Paperless-side integration is actually loaded before the shortcut can be enabled and provides setup guidance when configuration is incomplete.
- Initial setup requires two Paperless environment variables and one Paperless restart; afterwards the shortcut can be enabled or disabled without restarting Paperless.
Nested Paperless tags
Fixed writeback of nested Paperless tags.
Classification and Hybrid History continue to work only with the most specific selected leaf tags. Immediately before updating Paperless, required parent tags are now added to the writeback set so Paperless does not remove selected child tags when replacing document tags.
Parent tags do not count toward max_tags and are not added to LLM or History decisions.
Other fixes
- The stale History notice now correctly covers both reviewed-document changes and History matching-setting changes.
v0.3.5
0.3.5
0.3.5 replaces the persistent Python core runtime with a lightweight Rust core and significantly reduces the memory retained by paperless-local-ai while idle.
Rust core
The persistent Core service is now implemented in Rust and hosts:
- metadata polling and processing;
- the Control Center;
- the Paperless Suggestions bridge;
- the lightweight History broker.
The scientific History engine remains an on-demand Python subprocess, so NumPy, SciPy and scikit-learn are loaded only when they are actually required.
Existing deployments using /app/core_service.py remain compatible; the compatibility entry point now hands off to the Rust core.
Low-memory runtime lifecycle
Heavy dependencies are kept outside the permanent idle footprint.
PaddleOCR continues to run in a short-lived subprocess and retains the existing five-second warm-session window for consecutive pages. After a completed warm OCR session, the worker is stopped, the shared AI lock is released and the OCR service is recycled cleanly back to a cold container state.
The Core uses the same deterministic lifecycle after completed metadata batches and explicit History refreshes. This prevents transient scientific/runtime file cache from becoming the new long-term idle baseline.
Both services therefore use:
restart: unless-stoppedas part of their intended runtime lifecycle.
Lightweight healthchecks
Core and OCR now use small std-only Rust health probes instead of starting Python for recurring Docker healthchecks.
For OCR:
healthcheck:
test: ["CMD", "/usr/local/bin/plai-healthcheck", "--ocr"]Compatibility
No new:
- services;
- public ports;
- mounts;
- secrets;
- privileges;
- required environment variables
are introduced.
The existing two-image architecture remains unchanged:
ghcr.io/lucaperl/paperless-local-ai-core
ghcr.io/lucaperl/paperless-local-ai-ocr
Ollama remains external.
Validation
0.3.5 was validated on a production-like TrueNAS deployment with:
- real PP-OCRv6 inference;
- automatic OCR warm-session teardown and container recycle;
- explicit History refresh and Core recycle;
- real Paperless metadata classification and writeback;
- correspondent safety behavior;
- Ollama unload;
- shared AI-lock release;
- repeated Docker healthchecks;
- raw cgroup memory measurements before and after heavy work.
On the reference system, the final post-work idle state measured approximately 18.6 MiB combined raw cgroup memory for Core and OCR, with OCR returning to approximately 12.5 MiB after an inference/recycle cycle.
These memory figures are reference measurements and will vary by host and runtime environment.
Updating an existing TrueNAS deployment
Existing Custom App YAML remains largely compatible.
Ensure that:
restart: unless-stoppedis configured for both Core and OCR, and that OCR uses:
healthcheck:
test: ["CMD", "/usr/local/bin/plai-healthcheck", "--ocr"]Then update the images to 0.3.5 or stable.
v0.3.5-rc.6
This release candidate contains a narrowly scoped follow-up fix for the std-only healthcheck introduced in RC5.
Fixed
- consume the complete HTTP response before the healthcheck closes its localhost connection;
- prevent successful recurring OCR health probes from causing misleading
ConnectionResetErrortracebacks in the Python HTTP server.
Scope
This release does not change:
- OCR inference;
- Paddle worker lifecycle;
- OCR container recycling;
- Core recycling;
- History behavior;
- metadata processing;
- ports, mounts, secrets or privileges.
Validation
RC5 already passed the complete production-like TrueNAS functional, automatic-recycle and raw-cgroup idle validation:
- OCR returned to cold idle after real inference and automatic recycle;
- explicit History refresh recycled the Core successfully;
- a real Paperless metadata job completed, wrote metadata, restored the original document state and recycled the Core;
- Ollama unloaded successfully;
- final raw cgroup idle was approximately 18.6 MiB combined for Core and OCR.
RC6 changes only the healthcheck response-drain behavior, so final production-like validation focuses on repeated health probes, clean OCR logs, unchanged cold-idle memory and one real OCR recycle.
Deployment
For deployments already updated to the RC5 healthcheck contract, this is an image-only update.
Existing OCR healthcheck:
healthcheck:
test: ["CMD", "/usr/local/bin/plai-healthcheck", "--ocr"]