wiki/b-reference/service-llm-private/architecture.md
2026-06-02 09:42:12 +02:00

140 lines
6 KiB
Markdown

<!-- status: canonical -->
<!-- lastReviewed: 2026-05-29 -->
<!-- verifiedAgainst: service-llm-private (codebase review 2026-05-29) -->
# Private LLM -- Architektur
## Überblick
Eigenständiger Service für die Verarbeitung sensitiver Daten mit lokalen AI-Modellen (Ollama). Läuft auf einem dedizierten GPU-Server und wird vom Gateway als Provider-Plugin (`aicorePluginPrivateLlm.py`) angesprochen. Kein Datenabfluss an externe Cloud-APIs.
## Technologie-Stack
| Layer | Technologie |
|-------|------------|
| Framework | FastAPI (Python) |
| AI Runtime | Ollama (lokale Vision/Text/Reasoning-Modelle) |
| PDF-Support | PyMuPDF (fitz) |
| Hosting | Aktuell: Infomaniak (GPU L4, 24 GB) / Geplant: FireStorm (RTX PRO 6000, 96 GB) |
| Deployment | Forgejo Actions → `main` Branch |
## Modelle
### Aktuell (Infomaniak L4, 24 GB VRAM)
| Externer Name | Internes Ollama-Modell | Typ | Zweck |
|--------------|----------------------|-----|-------|
| `poweron-text-general` | `qwen2.5:7b` | Text | Neutralisierung, Datenanalyse |
| `poweron-vision-general` | `qwen2.5vl:7b` | Vision | Bildanalyse, Dokumenten-OCR |
| `poweron-vision-deep` | `granite3.2-vision` | Vision | Detaillierte Dokumentenanalyse |
### Geplant (FireStorm RTX PRO 6000, 96 GB VRAM)
| Externer Name | Internes Ollama-Modell | Typ | VRAM | Zweck |
|--------------|----------------------|-----|------|-------|
| `poweron-text-reasoning` | `deepseek-r1:70b` | Reasoning | ~40 GB | Chain-of-Thought, Logik, Planung |
| `poweron-vision-multimodal` | `llama4:scout` | Vision | ~16 GB | Multimodal, Long-Context (10M Tokens) |
| `poweron-embed` | `nomic-embed-text` | Embedding | ~0.3 GB | Lokales RAG-Embedding (ersetzt OpenAI) |
| `poweron-transcribe` | `whisper-large-v3-turbo` (faster-whisper) | STT | ~6 GB | Voice-Transkription, 99 Sprachen, Batch |
**VRAM-Budget gesamt: ~62 GB** (Reserve 34 GB fuer KV-Cache und Parallelitaet)
Die LLM-Modelle sind im Code vorbereitet und werden **automatisch aktiv**, sobald sie in Ollama gepullt sind (`_isModelAvailableInOllama`-Filter). Whisper laeuft als separater Faster-Whisper-Service mit OpenAI-kompatiblem API (`/v1/audio/transcriptions`).
## Migrations-Plan: Infomaniak → FireStorm
### Vorbedingungen
1. FireStorm GPU Pro bestellt (CHF 749/Mt., RTX PRO 6000 Blackwell, 96 GB VRAM)
2. Ubuntu 24.04 LTS mit CUDA-Treibern (vorinstalliert durch FireStorm)
### Migrationsschritte
```bash
# 1. Ollama installieren
curl -fsSL https://ollama.com/install.sh | sh
# 2. Service deployen (git clone + venv + systemd)
git clone git@git.poweron.swiss:PowerOn/service-llm-private.git /srv/llm-private/current
cd /srv/llm-private/current
python3.11 -m venv .venv
.venv/bin/pip install -r requirements.txt
# systemd service file: siehe docu/setupserver.md
# 3. Modelle pullen (aktuell + next-gen)
ollama pull qwen2.5:7b # ~4.5 GB (Abwaertskompatibilitaet)
ollama pull qwen2.5vl:7b # ~6 GB
ollama pull granite3.2-vision # ~2.4 GB
ollama pull deepseek-r1:70b # ~40 GB (Reasoning)
ollama pull llama4:scout # ~16 GB (Vision Multimodal)
ollama pull nomic-embed-text # ~0.3 GB (Embedding)
# 4. Whisper STT Service (separater Prozess)
pip install faster-whisper
# Oder: git clone https://github.com/Hantok/local-whisper-backend /srv/whisper
# Env: LOCAL_WHISPER_MODEL=large-v3-turbo, LOCAL_WHISPER_DEVICE=cuda
# Systemd service auf Port 9000, OpenAI-kompatibel: /v1/audio/transcriptions
# 5. config.ini anpassen (API-Key, TLS)
# 6. DNS umschalten: llm.poweron.swiss -> neue IP
# 7. TLS-Zertifikat (Let's Encrypt oder manuell)
```
### Nach Migration
- `MODEL_MAPPING` in `config.py` auf neue Modelle umschalten (auskommentierter Block)
- Alte Modelle (qwen2.5:7b etc.) koennen parallel weiterlaufen oder entfernt werden
- Infomaniak GPU-VM kuendigen
### Kostenvergleich
| | Infomaniak (aktuell) | FireStorm (geplant) |
|--|---|---|
| GPU | NVIDIA L4 (24 GB) | RTX PRO 6000 Blackwell (96 GB) |
| VRAM | 24 GB | 96 GB (+300%) |
| TFLOPS | ~30 FP32 | 125 FP32 (+316%) |
| RAM | 16 GB | 256 GB |
| Storage | 150 GB | 8 TB NVMe RAID 10 |
| Preis/Mt. | ~CHF 200 (geschaetzt) | CHF 749 |
| Reasoning-Modell | nicht moeglich (zu wenig VRAM) | DeepSeek R1 70B |
| Lokales Embedding | nicht moeglich | nomic-embed-text |
## API-Routen
| Modul | Zweck |
|-------|-------|
| `routeApi.py` | Analyse-API: Bild-/PDF-Analyse mit Prompt, Modellauswahl |
| `routeOpenAi.py` | OpenAI-kompatibles Chat-Completion-API (für Cursor-Integration) |
| `routeWeb.py` | Web-UI für manuelle Tests |
## Integration mit Gateway
Der Gateway nutzt das Private LLM über `aicorePluginPrivateLlm.py` als Provider für:
- **Neutralisierung:** Text-Analyse mit `poweron-text-general` (oder `poweron-text-reasoning`)
- **Sensitive Datenverarbeitung:** Vision-Analyse von Dokumenten (Rechnungen, Belege, Handschrift)
- **Reasoning:** Komplexe Logik und Planung mit `poweron-text-reasoning`
- **Lokales Embedding:** RAG-Indexierung ohne externe API-Kosten
- **Keine Billing-Kosten** für mandanteninterne LLM-Calls (eigene Infrastruktur)
## Sicherheit
- API-Key-Authentifizierung (`X-API-Key` Header)
- Separater Cursor-API-Key für OpenAI-kompatible Endpoints (Bearer Token)
- Rate-Limiting per API-Key (Token Bucket, konfigurierbar)
- Konfiguration über `config.ini` + Environment-Variablen (Secrets nie im Code)
## Schlüssel-Dateien
| Datei | Rolle |
|-------|-------|
| `app.py` | FastAPI-Einstieg, Router-Mount |
| `config.py` | Konfiguration, Model-Mapping, Auth, Rate-Limiting, Request/Response-Modelle |
| `routeApi.py` | Analyse-Endpunkte (Bild, PDF) |
| `routeOpenAi.py` | OpenAI-kompatibles Chat-API |
| `routeWeb.py` | Test-UI |
## Regeln / Invarianten
- Alle Daten werden **lokal** verarbeitet -- kein Weiterleiten an externe APIs
- Model-Mapping ist die einzige Stelle für Namensauflösung (`MODEL_MAPPING` in `config.py`)
- API-Keys werden aus `config.ini` oder Environment gelesen, nie hardcoded
- PDF-Verarbeitung rendert Seiten als Bilder für Vision-Modelle (max 5 Seiten)
- Neue Modelle werden automatisch erkannt wenn in Ollama verfuegbar (kein Code-Deploy noetig)