# rag-ingestor Microservice der Dateien aus Nextcloud (`Documents/THB/Studium/`) in Qdrant indexiert. Embeddings via Ollama. ## Endpoints - `POST /webhook` (Header `X-Webhook-Secret`): Nextcloud-Event-Empfang (`created` / `updated` / `deleted`). - `POST /bulk-import` (Header `X-Webhook-Secret`): Body `{"path": "..."}` → rekursiver Re-Index. Bulk-Pipeline-Stages laufen mit Concurrency 4 (siehe `BULK_CONCURRENCY` in `app/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: ```json { "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: ```bash 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/.Semester//[]/ ``` 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 ```bash uv sync uv run pytest uv run uvicorn app.main:app --reload ``` ## Deployment Image bauen und in Coolify neben Qdrant + Ollama deployen: ```bash docker build -f docker/Dockerfile -t rag-ingestor . ``` ### Ollama-Ressourcenlimits Embedding-Inferenz ist CPU-only und skaliert per Default auf alle verfügbaren Cores. Für Produktion daher Ollama hart limitieren, damit der Host nicht von Ingest-Spikes blockiert wird: - `cpus: "2.0"` (Container-Cap) - `OLLAMA_NUM_PARALLEL=1` (serialisiert Embedding-Requests intern) Beide Werte sind in `docker-compose.yml` für die lokale Entwicklung gesetzt und sollten in Coolify entsprechend mitgepflegt werden. Folge: konstante ~2 CPU statt Peaks bis 8 CPU, dafür längere Bulk-Laufzeiten. ## Tests ```bash 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: 1. Collection in Qdrant manuell droppen: ```bash curl -X DELETE "$QDRANT_URL/collections/$QDRANT_COLLECTION" ``` 2. Service neu starten — Lifespan legt die Collection mit der neuen Dimension an. 3. Bulk-Import auf den Studium-Root anstoßen, um alle Inhalte neu zu indexieren: ```bash 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-`BackgroundTask`s 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.