Standalone, selbst-gehostete KI-Middleware für Paperless-ngx. Automatische Metadaten-Extraktion beim Import (Titel-Schema, Korrespondent, Tags) plus eine Such-/Chat-Oberfläche mit LLM Function Calling. Kein SaaS, keine Accounts, kein externer Lizenzserver – alles läuft lokal beim Kunden.
Eine Solution, vier Projekte, ein Host-Prozess:
PaperlessAiCore.Api– ASP.NET Core: REST-API, Ingest-Hintergrunddienst, hostet zugleich die gebaute Blazor-WASM-App als statische Dateien. Konfiguration und Aktivitäts-Log liegen als einfache, menschenlesbare Dateien vor (data/settings.env,data/activity.jsonl) - keine Datenbank, kein Schema-Migrations-Thema.PaperlessAiCore.Web– Blazor WebAssembly: Setup-Wizard, Suchmaske/Chat, Settings-Screen, Aktivitäts-Log.PaperlessAiCore.Core– reine Business-Logik ohne Web-Bezug: Paperless-Client, LLM-Client (OpenAI-kompatibel), Extraktions-Logik, Tool-Definitionen für Function Calling, Lizenzprüfung.PaperlessAiCore.Shared– DTOs, die zwischen Web und Api geteilt werden.
Keine externe Datenbank nötig, keine ENV-Pflichtvariablen für den Betrieb – alles wird beim
ersten Start über den Setup-Wizard im Browser eingerichtet und landet in data/settings.env
(einfach zu öffnen, zu sichern oder auch manuell zu editieren; Neustart der App nötig, damit
manuelle Änderungen an der Datei greifen). Verarbeitete Dokumente werden als Append-only
JSON-Lines-Datei unter data/activity.jsonl protokolliert.
cd C:\Projekte\paperless-ai-core-dotnet
dotnet restore
dotnet run --project src/PaperlessAiCore.ApiDanach im Browser: http://localhost:5080 (Port siehe Properties/launchSettings.json,
anpassbar). Der Setup-Wizard führt einmalig durch Paperless-URL/Token und LLM-Provider.
Hinweis: Der Blazor-WASM-Client wird beim
dotnet run/dotnet buildautomatisch mitgebaut (Projektreferenz inPaperlessAiCore.Api.csproj). Für den allerersten Build können dabei zusätzliche WASM-Build-Tools nachinstalliert werden – das kann etwas dauern, ist aber einmalig.
cd paperless-ai-core-dotnet
docker compose up --build→ http://localhost:8080. data/settings.env und data/activity.jsonl liegen im Volume
paperlessai_data und überstehen Container-Neubauten.
dotnet test tests/PaperlessAiCore.Core.Tests/PaperlessAiCore.Core.Tests.csprojTags, Korrespondent und Dokumenttyp werden über /api/documents/bulk_edit/ gesetzt (laut
Paperless-ngx-API-Doku asynchron verarbeitet - der Request kehrt zurück, sobald der Task
eingereiht ist, nicht erst nach vollständiger Verarbeitung). Nur Titel und Datum laufen noch
über ein schlankes PATCH mit ausschließlich diesen beiden Feldern. Das reduziert deutlich das
Risiko von Timeouts bei großen/trägen Paperless-Instanzen gegenüber einem einzelnen PATCH mit
allen Feldern gleichzeitig.
Jeder Schreibversuch (PATCH + bulk_edit) wird mit Zeitstempel, Dauer und Erfolg/Fehler in
data/paperless-writes.log protokolliert - zur Nachvollziehbarkeit, welche Werte tatsächlich
gesendet wurden.
Unter "📊 Dashboard" in der Navigation: Verarbeitungsstatus (Donut-Chart KI-verarbeitet vs. unverarbeitet), System-Statistik (Tags/Korrespondenten-Anzahl aus Paperless), KI-Token-Nutzung (Ø Prompt-/Completion-/Gesamt-Tokens pro Dokument, Gesamtverbrauch), Token-Verteilung als Balkendiagramm, Dokumenttyp-Verteilung als Donut-Chart, sowie Hintergrunddienst-Status (idle/Fehler, heute verarbeitet, zuletzt verarbeitet) inkl. "Jetzt scannen"-Button für einen sofortigen manuellen Durchlauf unabhängig vom Poll-Intervall.
Token-Nutzung wird automatisch bei jeder Verarbeitung aus der usage-Antwort des LLM-Providers
miterfasst (OpenAI-kompatibles Format) und im Activity-Log mitgeschrieben - kein zusätzliches
Setup nötig, funktioniert automatisch mit, sobald der Provider Token-Zahlen zurückliefert.
Im Settings-Screen unter "KI-Funktionen" lässt sich einzeln ein-/ausschalten, was die KI tatsächlich zurückschreibt (Titel-Generierung, Korrespondent-Erkennung, Tag-Verschlagwortung, Dokumenttyp-Klassifizierung), sowie "Nur vorhandene Tags/Korrespondenten/Dokumenttypen verwenden", damit keine neuen Entitäten durch KI-Fantasie entstehen.
Zusätzlich kann ein eigener System-Prompt hinterlegt werden (Platzhalter [tags] /
[document_types] werden automatisch durch die live aus Paperless geladenen Listen ersetzt).
Das JSON-Parsing ist tolerant gegenüber leicht abweichenden Feldnamen (z.B. document_date
statt date), damit auch mitgebrachte Prompts aus anderen Tools weitgehend kompatibel sind.
-
Automatisches Polling (Standard): der Ingest-Hintergrunddienst prüft alle
PollIntervalSecondsneue, unverarbeitete Dokumente. -
Webhook (empfohlen für schnelle Reaktion): in Paperless-ngx unter Workflows → neuer Workflow → Trigger "Dokument hinzugefügt" → Action "Webhook" folgende URL eintragen:
http://<paperless-ai-core-host>:8080/api/webhook/documentAls Parameter
url={doc_url}mitgeben. Damit wird das Dokument sofort nach dem Hinzufügen verarbeitet, statt auf den nächsten Poll-Zyklus zu warten (Muster übernommen vonclusterzx/paperless-ai).
Extrahierte Metadaten werden vollständig als eigene Paperless-Entitäten angelegt/verknüpft
(Tags, Korrespondent und Dokumenttyp über /api/document_types/), nicht nur als Text im Titel.
| Modus | Voraussetzung | Funktionen |
|---|---|---|
| Community | kein Lizenzschlüssel im Settings-Screen | Auto-Tagging, Titel-Normalisierung, Standardsuche |
| Pro | gültiger Lizenzschlüssel (PAIC-XXXXXXXX-CCCC) |
zusätzlich: Kosten-Aggregation im Such-Agenten |
Rein offline per Prüfsumme validiert (PaperlessAiCore.Core/LicenseCheck.cs),
kein Anruf nach Hause nötig – passt zum Standalone-Anspruch.
paperless-ai-core-dotnet/
├── PaperlessAiCore.sln
├── docker-compose.yml
├── src/
│ ├── PaperlessAiCore.Api/
│ │ ├── Controllers/ (Settings, Status, Query)
│ │ ├── Services/ (SettingsService, IngestWorker, WorkerStatus)
│ │ ├── Data/ (EF Core DbContext)
│ │ ├── Domain/ (AppSettings, ProcessedDocumentLog)
│ │ ├── Program.cs
│ │ └── Dockerfile
│ ├── PaperlessAiCore.Web/
│ │ ├── Pages/ (Home, Settings, ActivityLogPage)
│ │ ├── Layout/
│ │ └── Services/ApiClient.cs
│ ├── PaperlessAiCore.Core/
│ │ ├── PaperlessClient.cs, LlmClient.cs, Tools.cs
│ │ ├── Prompts.cs, ExtractionService.cs, LicenseCheck.cs
│ └── PaperlessAiCore.Shared/
│ └── Contracts.cs
└── tests/PaperlessAiCore.Core.Tests/
- Solution-Struktur analog KnxToLox (Api hostet Web, EF Core/SQLite, kein SaaS-Ballast)
- Setup-Wizard + admin-editierbare Settings (statt reiner
.env) - Ingest-Hintergrunddienst mit Titel-Validierung
- Such-Agent mit Function Calling (
search_documents, PRO:aggregate_costs) - Offline-Lizenzprüfung
- Unit-Tests für Lizenz & Betrags-Parsing
-
dotnet build/dotnet runbei dir lokal verifizieren (in der Sandbox, in der dieses Projekt erstellt wurde, ist kein .NET SDK verfügbar – bitte gegenprüfen und mir eventuelle Fehlermeldungen schicken) - Testlauf gegen eine echte Paperless-ngx-Instanz
- Chat/RAG-Erweiterung, Webhook-Endpunkt für direkten Trigger aus Paperless (siehe
clusterzx/paperless-aials Inspiration) – bei Bedarf als nächster Schritt