- Pipeline-Stages (download/extract/embed/qdrant) loggen jetzt duration_ms - bulk-import dispatcht mit Semaphore(4) statt unbounded → Backpressure - README dokumentiert Webhook-Payload-Schema mit curl-Beispiel - README enthaelt Recovery-Runbook (dim-mismatch, crash-recovery, single-file reindex)
rag-ingestor
Microservice der Dateien aus Nextcloud (Documents/THB/Studium/) in Qdrant indexiert. Embeddings via Ollama.
Endpoints
POST /webhook(HeaderX-Webhook-Secret): Nextcloud-Event-Empfang (created/updated/deleted).POST /bulk-import(HeaderX-Webhook-Secret): Body{"path": "..."}→ rekursiver Re-Index. Bulk-Pipeline-Stages laufen mit Concurrency 4 (sieheBULK_CONCURRENCYinapp/bulk.py).GET /health: Liveness-Probe.
Webhook-Payload-Format
Der Service erwartet ein vorgeformtes JSON. Nextcloud-Roh-Events werden nicht direkt akzeptiert — sie müssen via Flow-Webhook in dieses Schema übersetzt werden:
{
"event_type": "created",
"file_path": "Documents/THB/Studium/2.Semester/Databases/DBS1.pdf",
"file_name": "DBS1.pdf"
}
event_type ∈ {"created", "updated", "deleted"}. Auth via Header X-Webhook-Secret, der mit WEBHOOK_SECRET aus der Konfiguration übereinstimmen muss.
Beispielaufruf:
curl -X POST http://localhost:8000/webhook \
-H "Content-Type: application/json" \
-H "X-Webhook-Secret: $WEBHOOK_SECRET" \
-d '{"event_type": "created", "file_path": "Documents/THB/Studium/2.Semester/Databases/DBS1.pdf", "file_name": "DBS1.pdf"}'
Erwartete Ordnerstruktur
Documents/THB/Studium/<N>.Semester/<Fach>/[<Unterordner>]/<datei>
Unterstützte Dateitypen: .pdf, .md, .docx, .xlsx (XLSX wird nur als Filename indexiert, kein Inhalt).
Konfiguration
Siehe .env.example. Alle Werte über Env-Vars, kein Config-File.
Lokale Entwicklung
uv sync
uv run pytest
uv run uvicorn app.main:app --reload
Deployment
Image bauen und in Coolify neben Qdrant + Ollama deployen:
docker build -f docker/Dockerfile -t rag-ingestor .
Tests
uv run pytest -v
Tests deckt Pure-Logic ab (Metadata-Parser, Chunker, Extractors, Auth, Pipeline-Orchestrierung mit gemockten externen Services). Keine Integration-Tests gegen echte Ollama/Qdrant/WebDAV-Instanzen.
Recovery-Runbook
Einbettungs-Modell oder -Dimension geändert
Beim Boot crasht der Service mit qdrant collection ... dimension mismatch, falls die existierende Collection eine andere Vektor-Dimension hat als das aktuelle Embedding-Modell. Dies ist Absicht (Fail-Fast). Vorgehen:
- Collection in Qdrant manuell droppen:
curl -X DELETE "$QDRANT_URL/collections/$QDRANT_COLLECTION" - Service neu starten — Lifespan legt die Collection mit der neuen Dimension an.
- Bulk-Import auf den Studium-Root anstoßen, um alle Inhalte neu zu indexieren:
curl -X POST http://localhost:8000/bulk-import \ -H "Content-Type: application/json" \ -H "X-Webhook-Secret: $WEBHOOK_SECRET" \ -d '{"path": "Documents/THB/Studium"}'
Webhook-Ausfall / fehlende In-Flight-Jobs nach Crash
Der Service hat keinen persistenten Job-Store; In-Flight-BackgroundTasks gehen bei Crash verloren. Recovery erfolgt über den Bulk-Import-Endpoint auf den betroffenen Pfad (siehe oben).
Ein einzelnes File neu indexieren
Webhook mit event_type: "updated" an /webhook POSTen — alte Chunks werden via delete_by_filter(file_path) entfernt, dann frisch indexiert.