Zum Inhalt

Deployment-Anleitung

Installations-, Betriebs- und Wartungsanleitung für den AVS Chatbot.


Inhaltsverzeichnis


Voraussetzungen

Hardware

Komponente Minimum Empfohlen
GPU 1x GPU mit 24 GB VRAM 2x NVIDIA RTX 4090 (24 GB)
RAM 16 GB 32 GB
Festplatte 50 GB SSD 100 GB NVMe SSD
CPU 8 Kerne 16 Kerne

GPU-Zuweisung

GPU Service VRAM-Bedarf
GPU 0 vLLM (Qwen3-14B INT4) ~7 GB
GPU 1 Embedding (e5-large) + Re-Ranking ~4 GB

Software

  • Ubuntu 22.04 oder 24.04 LTS
  • Docker >= 24.0 und Docker Compose v2
  • NVIDIA-Treiber >= 535
  • NVIDIA Container Toolkit
  • Git
  • Python 3.11+ (nur für Indexierung und Entwicklung)

Erstinstallation

1. Repository klonen

git clone <repo-url> /opt/avs-chatbot
cd /opt/avs-chatbot

2. Umgebungsvariablen konfigurieren

cp .env.example .env

Folgende Werte in .env anpassen:

Variable Beschreibung Aktion
POSTGRES_PASSWORD Datenbankpasswort Sicheres Passwort setzen
MINIO_ROOT_PASSWORD MinIO-Admin-Passwort Sicheres Passwort setzen
GRAFANA_ADMIN_PASSWORD Grafana-Admin-Passwort Sicheres Passwort setzen
VLLM_MODEL LLM-Modell Standard: Qwen/Qwen2.5-7B-Instruct
CORS_ORIGINS Erlaubte Origins AVS-Domains eintragen

3. Stack starten

docker compose up -d

Beim Erststart werden Docker-Images heruntergeladen und das LLM-Modell von HuggingFace geladen. Dies kann 10-30 Minuten dauern (je nach Internetverbindung).

4. Status prüfen

# Alle Services prüfen
docker compose ps

# Health-Check
curl http://localhost:8080/health

Warten bis alle Services den Status healthy zeigen. vLLM braucht am längsten (~5 Min. für Model-Loading).

5. Dokumente indexieren

# Dokumente in data/documents/ ablegen
cp /pfad/zu/handbuecher/*.pdf data/documents/

# Indexierung starten
python scripts/index_documents.py data/documents/

6. API verifizieren

curl -X POST http://localhost:8080/api/v1/query \
  -H "Content-Type: application/json" \
  -d '{"question": "Wie konfiguriere ich das Gerät?"}'

7. Widget einbetten

Das Chat-Widget auf der AVS-Website einbinden:

<script src="https://chatbot.avs.de/widget/avs-chat-widget.min.js"></script>
<avs-chat-widget api-url="https://chatbot.avs.de/api/v1"></avs-chat-widget>

Updates

Standard-Update

cd /opt/avs-chatbot

# Neuesten Stand holen
git pull origin main

# Services neu bauen und starten
docker compose build
docker compose up -d

# Health-Check
curl http://localhost:8080/health

Widget-Update

cd src/widget
npm install
npm run build
# dist/avs-chat-widget.min.js wird automatisch über Nginx ausgeliefert

Modell-Wechsel

Um ein anderes LLM-Modell zu verwenden:

# .env anpassen
VLLM_MODEL=Qwen/Qwen3-14B

# vLLM-Service neu starten
docker compose up -d vllm
# Warten bis healthy (~5-10 Min.)

Backup und Recovery

Was muss gesichert werden?

Service Daten Backup-Priorität
Qdrant Vektordatenbank (indexierte Chunks) Mittel (kann neu indexiert werden)
PostgreSQL Sessions, Feedback, Metadaten Hoch
MinIO Originaldokumente Hoch (falls einzige Kopie)
Redis Response-Cache Niedrig (regeneriert sich automatisch)

Backup-Befehle

PostgreSQL:

docker exec avs-postgres pg_dump -U avs avs_chatbot > backup_postgres_$(date +%Y%m%d).sql

Qdrant:

# Snapshot erstellen
curl -X POST http://localhost:6333/collections/avs_handbuecher/snapshots
# Snapshot-Dateien liegen im Docker-Volume avs-qdrant-data

MinIO:

docker exec avs-minio mc mirror /data /backup
# Oder direkt das Docker-Volume sichern:
docker run --rm -v avs-minio-data:/data -v $(pwd):/backup alpine tar czf /backup/minio_$(date +%Y%m%d).tar.gz /data

Recovery

PostgreSQL wiederherstellen:

docker exec -i avs-postgres psql -U avs avs_chatbot < backup_postgres_20260404.sql

Qdrant wiederherstellen:

# Snapshot-Datei wiederherstellen
curl -X PUT http://localhost:6333/collections/avs_handbuecher/snapshots/recover \
  -H "Content-Type: application/json" \
  -d '{"location": "/qdrant/storage/snapshots/<snapshot-name>"}'

Alternativ — Neu-Indexierung:

# Wenn die Originaldokumente vorhanden sind:
python scripts/index_documents.py data/documents/


Monitoring

Dashboards

Service URL Zugangsdaten
Grafana http://server:3000 admin / (aus .env)
Prometheus http://server:9090 Kein Login
Qdrant Dashboard http://server:6333/dashboard Kein Login
MinIO Console http://server:9001 aus .env

Wichtige Metriken

Metrik Beschreibung Alarm-Schwelle
avs_query_duration_seconds Query-Latenz p95 > 10s
avs_cache_hits_total / avs_cache_misses_total Cache-Hit-Rate < 30%
avs_guardrail_rejections_total Geblockte Anfragen > 50/h (Angriff?)
avs_no_retrieval_match_total Fragen ohne Treffer > 20% (fehlende Docs?)
GPU-Auslastung nvidia-smi > 90% dauerhaft
Qdrant Speicher Collection-Größe > 80% Disk

Metriken-Endpoint

curl http://localhost:8080/metrics

Troubleshooting

vLLM startet nicht

Symptom: Container avs-vllm startet nicht oder bleibt im Status starting.

# Logs prüfen
docker compose logs vllm

# Häufige Ursachen:
# 1. VRAM reicht nicht aus
nvidia-smi  # VRAM-Verbrauch prüfen

# 2. Modell nicht gefunden / Download fehlgeschlagen
docker exec avs-vllm ls /root/.cache/huggingface/

# 3. CUDA-Version inkompatibel
docker exec avs-vllm nvidia-smi

Lösung: Kleineres Modell in .env setzen (Qwen/Qwen2.5-7B-Instruct) oder GPU-Memory-Utilization anpassen.

Qdrant nicht erreichbar

# Status prüfen
docker compose logs qdrant
curl http://localhost:6333/readiness

# Häufige Ursache: Disk Space
df -h  # Festplattenplatz prüfen

Langsame Antworten

  1. GPU-Auslastung prüfen:

    nvidia-smi --query-gpu=utilization.gpu,memory.used --format=csv -l 1
    

  2. Cache-Hit-Rate prüfen:

    curl http://localhost:8080/health | python3 -m json.tool
    
    Bei niedriger Hit-Rate: TTL erhöhen oder häufige Fragen vorwärmen.

  3. Latenz-Benchmark:

    python scripts/benchmark.py --warmup
    

Widget lädt nicht

  1. CORS prüfen: Nginx muss Access-Control-Allow-Origin für die AVS-Domain setzen.

  2. Netzwerk prüfen: Widget muss die API-URL erreichen können.

    # Aus dem Browser-Kontext testen:
    curl -v https://chatbot.avs.de/widget/avs-chat-widget.min.js
    curl -v https://chatbot.avs.de/health
    

  3. Browser-Konsole: Fehlermeldungen in den Browser DevTools prüfen (F12).

Redis-Cache leeren

# Gesamten Cache leeren (z.B. nach Dokument-Änderungen):
docker exec avs-redis redis-cli FLUSHALL

# Nur AVS-Cache-Keys leeren:
docker exec avs-redis redis-cli --scan --pattern "avs:cache:*" | xargs -r docker exec -i avs-redis redis-cli DEL

Lasttests ausführen

Lasttests mit k6 prüfen die API unter simulierter Last.

Voraussetzungen: - k6 installiert (k6 version) - Stack läuft (docker compose up -d) - Optional: LOADTEST_SECRET in .env gesetzt (umgeht Rate Limiting)

# Alle drei Szenarien nacheinander:
make loadtest

# Einzelnes Szenario:
k6 run --env SCENARIO=baseline tests/load/loadtest.js
k6 run --env SCENARIO=rampup  tests/load/loadtest.js
k6 run --env SCENARIO=spike   tests/load/loadtest.js

# Mit Rate-Limit-Bypass:
k6 run --env SCENARIO=baseline --env LOADTEST_SECRET=your_secret tests/load/loadtest.js

Szenarien: | Szenario | VUs | Dauer | Ziel | |----------|-----|-------|------| | baseline | 10 | 5 min | Normalbetrieb | | rampup | 5→50 | 10 min | Skalierungsgrenze finden | | spike | 100→10 | 5 min | Recovery-Verhalten |

Schwellwerte (Dev-Server): p95 < 15s, Error-Rate < 5%, Rate-Limited < 10%

Staging-Checklist

Vor der Übergabe an AVS die automatisierte Checklist ausführen:

make staging-check

Prüft 16 Punkte: API-Health, Qdrant, vLLM, Redis, PostgreSQL, Admin-Auth, Widget, DE/EN-Queries, Cache, Feedback, Rate Limiting, Guardrails, Prometheus Metriken, Grafana.

Ergebnis: PASS (alle Checks grün) oder FAIL mit Details.

Sicherheits-Audit

Automatisierte Sicherheitsprüfung:

make security-check

Prüft: .env nicht im Git, Admin-Passwort gesetzt, CORS-Origins, IP-Hashing, PII in Logs, Rate Limiting aktiv, Guardrails aktiv, Health/Metrics-Endpoints korrekt konfiguriert.