Papier ist selten das eigentliche Problem. Das Problem ist das Wiederfinden.
Rechnungen. Verträge. Bescheide. Sitzungsunterlagen. Alles wird heute zwar digital abgelegt, aber die klassische Dateisuche bleibt mühsam. Man erinnert sich selten an Dateinamen. Man erinnert sich an Inhalte.
Genau hier setzt mein Projekt an. Ein persönliches AI Office.
Die Basis bildet Paperless ngx. Darauf läuft eine zusätzliche KI Ebene, die Dokumente automatisch analysiert, zusammenfasst, verschlagwortet und für semantische Suche vorbereitet. Alles läuft auf eigener Infrastruktur.

Ziel
Dokumente nicht mehr suchen. Dokumente fragen.
Architektur
Das System besteht aus wenigen klar getrennten Komponenten.
Scanner oder Upload
→ Paperless ngx
→ Dokumentexport über API
→ KI Verarbeitung
→ Vektor Datenbank
→ RAG API
→ Fragen und Antworten
Das bedeutet konkret
Paperless übernimmt
OCR
Dokumentenverwaltung
Originaldateien
Metadaten
Die KI übernimmt
Zusammenfassungen
automatische Tags
semantische Suche
Fragen über Dokumente
Das Ergebnis ist ein Dokumentenarchiv, das nicht nur speichert, sondern Inhalte versteht.
Paperless als Grundlage
Paperless ngx ist ein Dokumentenmanagementsystem für selbstgehostete Umgebungen. Dokumente werden automatisch importiert, per OCR erkannt und archiviert.
Ein typisches Docker Setup sieht zum Beispiel so aus.
docker compose
version: "3.8"
services:
redis:
image: redis:7
restart: unless-stopped
db:
image: postgres:15
restart: unless-stopped
environment:
POSTGRES_DB: paperless
POSTGRES_USER: paperless
POSTGRES_PASSWORD: paperless
webserver:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
restart: unless-stopped
depends_on:
- redis
- db
ports:
- 8000:8000
environment:
PAPERLESS_REDIS: redis://redis:6379
PAPERLESS_DBHOST: db
PAPERLESS_DBNAME: paperless
PAPERLESS_DBUSER: paperless
PAPERLESS_DBPASS: paperless
volumes:
- ./data:/usr/src/paperless/data
- ./media:/usr/src/paperless/media
- ./consume:/usr/src/paperless/consume
Code-Sprache: JavaScript (javascript)
Der consume Ordner ist dabei entscheidend. Alles was dort abgelegt wird, wird automatisch von Paperless importiert.
Scanner, Mailregeln oder Automationen können Dokumente dort einfach ablegen.
Zugriff auf Dokumentinhalte
Für die KI Verarbeitung müssen die OCR Texte der Dokumente verfügbar sein. Paperless stellt dafür eine API bereit.
Ein einfaches Python Beispiel zeigt, wie Dokumente abgefragt werden können.
import requests
URL = "http://paperless:8000/api/documents/"
TOKEN = "API_TOKEN"
headers = {
"Authorization": f"Token {TOKEN}"
}
r = requests.get(URL, headers=headers)
for doc in r.json()["results"]:
print(doc["title"], doc["content"])
Code-Sprache: JavaScript (javascript)
Das Feld content enthält den vollständigen OCR Text eines Dokuments. Genau dieser Text wird später von der KI analysiert.
Konfiguration der KI Umgebung
Alle zentralen Einstellungen werden in einer Konfigurationsdatei zusammengefasst.
config/settings.py
import os
from dotenv import load_dotenv
load_dotenv()
PAPERLESS_URL = os.getenv("PAPERLESS_URL")
PAPERLESS_TOKEN = os.getenv("PAPERLESS_TOKEN")
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
CHROMA_PATH = os.getenv("CHROMA_PATH", "./vector_db")
EMBEDDING_MODEL = "text-embedding-3-small"
CHAT_MODEL = "gpt-4o-mini"
Code-Sprache: JavaScript (javascript)
Die sensiblen Werte liegen in einer .env Datei.
Beispiel
PAPERLESS_URL=http://paperless:8000
PAPERLESS_TOKEN=
OPENAI_API_KEY=
CHROMA_PATH=./vector_db
Code-Sprache: JavaScript (javascript)
Dokumente für semantische Suche vorbereiten
Der erste KI Schritt ist die Erstellung eines semantischen Indexes.
Dabei werden Dokumente in kleinere Textabschnitte zerlegt und für jeden Abschnitt sogenannte Embeddings erzeugt. Diese numerischen Vektoren repräsentieren die Bedeutung des Textes.
scripts/index_documents.py
from openai import OpenAI
import chromadb
from scripts.export_documents import get_documents
from config.settings import *
client = OpenAI(api_key=OPENAI_API_KEY)
chroma = chromadb.PersistentClient(path=CHROMA_PATH)
collection = chroma.get_or_create_collection("documents")
def split_text(text, size=500):
words = text.split()
for i in range(0, len(words), size):
yield " ".join(words[i:i+size])
def index_document(doc):
text = doc["content"]
chunks = list(split_text(text))
for i, chunk in enumerate(chunks):
emb = client.embeddings.create(
model=EMBEDDING_MODEL,
input=chunk
)
collection.add(
ids=[f"{doc['id']}_{i}"],
documents=[chunk],
embeddings=[emb.data[0].embedding]
)
Code-Sprache: JavaScript (javascript)
Die erzeugten Vektoren werden in einer lokalen Vektor Datenbank gespeichert.
Ein einfacher Ordner genügt.
mkdir vector_db
Automatische Zusammenfassungen
Beim Import eines neuen Dokuments kann automatisch eine Kurzfassung erzeugt werden.
scripts/summarize.py
from openai import OpenAI
from config.settings import *
client = OpenAI(api_key=OPENAI_API_KEY)
def summarize(text):
prompt = f"""
Fasse dieses Dokument in drei Sätzen zusammen.
{text}
"""
r = client.chat.completions.create(
model=CHAT_MODEL,
messages=[{"role":"user","content":prompt}]
)
return r.choices[0].message.content
Code-Sprache: PHP (php)
Die Zusammenfassung kann später direkt im Dokument angezeigt werden.
Automatisches Tagging
Neben der Zusammenfassung werden auch Tags automatisch generiert.
scripts/auto_tag.py
from openai import OpenAI
from config.settings import *
client = OpenAI(api_key=OPENAI_API_KEY)
def generate_tags(text):
prompt = f"""
Analysiere das Dokument und gib maximal fünf Tags zurück.
Nur einzelne Wörter.
{text}
"""
r = client.chat.completions.create(
model=CHAT_MODEL,
messages=[{"role":"user","content":prompt}]
)
tags = r.choices[0].message.content
return [t.strip() for t in tags.split("\n") if t.strip()]
Code-Sprache: PHP (php)
Diese Tags können anschließend automatisch über die Paperless API im Dokument gespeichert werden.
Damit entsteht mit der Zeit ein sauber strukturiertes Archiv.
Dokumente über Fragen durchsuchen
Der interessanteste Teil ist die RAG API.
RAG steht für Retrieval Augmented Generation.
Zuerst werden passende Dokumentabschnitte gefunden.
Dann erzeugt das Sprachmodell daraus eine Antwort.
api/rag_api.py
from fastapi import FastAPI
import chromadb
from openai import OpenAI
from config.settings import *
app = FastAPI()
client = OpenAI(api_key=OPENAI_API_KEY)
chroma = chromadb.PersistentClient(path=CHROMA_PATH)
collection = chroma.get_collection("documents")
@app.get("/ask")
def ask(q: str):
emb = client.embeddings.create(
model=EMBEDDING_MODEL,
input=q
)
results = collection.query(
query_embeddings=[emb.data[0].embedding],
n_results=5
)
context = "\n".join(results["documents"][0])
prompt = f"""
Nutze diese Dokumente um die Frage zu beantworten.
{context}
Frage: {q}
"""
answer = client.chat.completions.create(
model=CHAT_MODEL,
messages=[{"role":"user","content":prompt}]
)
return {
"answer": answer.choices[0].message.content
}
Code-Sprache: PHP (php)
Die API kann anschließend gestartet werden.
uvicorn api.rag_api:app --host 0.0.0.0 --port 9000
Code-Sprache: CSS (css)
Automatische Aktualisierung
Der Dokumentindex sollte regelmäßig aktualisiert werden. Eine einfache Cron Aufgabe reicht aus.
0 3 * * * python3 /srv/paperless_ai/scripts/index_documents.py
Damit wird jede Nacht der semantische Index aktualisiert.
Ergebnis
Nach kurzer Zeit entsteht ein intelligentes Dokumentarchiv.
Dokumente werden automatisch
importiert
analysiert
zusammengefasst
getaggt
semantisch indexiert
Danach können Fragen gestellt werden wie
Welche Rechnungen habe ich vom Energieversorger
Wann war die letzte Heizungswartung
Welche Dokumente betreffen meine Gebäudeversicherung
Die KI durchsucht automatisch alle Dokumente und liefert die Antwort.
Fazit
Paperless löst das Archivierungsproblem.
KI löst das Informationsproblem.
Die Kombination macht aus einem klassischen Dokumentenarchiv ein persönliches Wissenssystem.
Dokumente liegen nicht mehr einfach nur im Speicher.
Sie werden verstanden, strukturiert und jederzeit abrufbar.
Ein echtes AI Office.


Schreibe einen Kommentar