ML-Service
Bilderkennung mit SigLIP 2
Python/FastAPI-Sidecar für Image-Classification. Übernimmt Embedding (SigLIP 2 SO400M, 1152-dim), Qdrant-I/O, LinearSVC-Training und Klassifikation mit kNN-Fallback. Läuft neben dem Node.js core-backend im privaten Netzwerk.
Verantwortlichkeiten
Der ML-Service ist bewusst schmal geschnitten und stateless bzgl. Persistenz:
- Frames/Bilder mit SigLIP 2 SO400M in 1152-dim Unit-Vektoren einbetten.
- Vektoren in eine Qdrant-Collection pro Schule upserten.
- Deduplizierung einer Collection via Farthest-Point-Sampling.
- Training eines kalibrierten
LinearSVCaus einer Qdrant-Collection; Rückgabe desjoblib-Blobs. - Klassifikation eines neuen Bildes mit Qdrant-Similarity-Gate, LinearSVC-Top-1/Top-k-Prediction und kNN-Fallback.
Nicht im Scope
- ffmpeg-Frame-Extraktion (liegt im core-backend).
- Sharpness-Filterung (liegt im core-backend).
- Persistenz der Classifier-Blobs (liegt in PostgreSQL).
- Authentifizierung (Service ist im privaten Netzwerk erreichbar).
HTTP-Endpunkte
| Methode | Pfad | Zweck |
|---|---|---|
GET | /health | Readiness + Pipeline-Konfiguration |
POST | /embed-frames | Batch-Embedding hochgeladener Frames |
POST | /dedup | Collection deduplizieren (FPS) |
POST | /train | Klassifikator trainieren (base64-joblib in JSON) |
POST | /load-classifier | Klassifikator-Blob unter cache_key im RAM cachen |
POST | /classify | Einzelbild klassifizieren |
DELETE | /collections/{name} | Qdrant-Collection löschen |
DELETE | /collections/{name}/classes/{label} | Alle Vektoren einer Klasse entfernen |
Blob-tragende Endpunkte (/embed-frames, /classify, /load-classifier) nutzen multipart/form-data. Ausführliche Endpunkt-Karten finden sich in der API-Referenz.
/classify Entscheidungs-Flow
- Bild einbetten (optional mit Center-Crop).
- Qdrant-NN-Suche. Ist die beste Similarity
< SIMILARITY_GATE, liefert die Antwortunknown. - Bei mehr als einer Klasse:
predict_topkmitMIN_CONFIDENCE_RATIO(Default 1.5). Die Ratio wird verwendet, weil die Softmax-Fallback-Verteilung bei vielen Klassen (z. B. 37) auch für sichere Predictions nur wenige Prozentpunkte Vorsprung liefert. - Bei genau einer Klasse: Diese Klasse mit Confidence aus der Qdrant-Similarity zurückgeben.
- Sonst kNN-Fallback über die Qdrant-Treffer mit absolutem
MIN_CONFIDENCE_GAP(in Cosinus-pp), da Cosinus in [0,1] beschränkt ist.
Konfiguration (Env-Vars)
Alle Variablen sind optional (siehe config.py).
| Variable | Default | Beschreibung |
|---|---|---|
QDRANT_HOST | localhost | Qdrant gRPC-Host |
QDRANT_PORT | 6333 | Qdrant-Port |
ML_DEVICE | auto | Auto, cpu, cuda, mps |
EMBED_BATCH_SIZE | 32 | Batch-Größe für SigLIP-Embedding-Calls |
CLASSIFIER_CACHE_MAX | 32 | LRU-Größe für Classifier-Cache im Prozess |
CROP_MODE | center | None oder 87,5% Center-Crop |
AUG_PRESET | off | Off, light, medium, strong |
AUG_COUNT | 0 | Augmentierungen pro Quell-Frame |
SIMILARITY_GATE | 0.75 | Cosinus-Schwelle zum Akzeptieren einer Prediction |
MIN_CONFIDENCE_RATIO | 1.5 | LinearSVC: minimales Top-1/Top-2-Verhältnis |
MIN_CONFIDENCE_GAP | 5 | kNN-Fallback: minimaler Cosinus-pp Gap |
NORM_LOW / NORM_HIGH | 0.55 / 0.95 | Bereich zur Normalisierung von Cosinus auf [0,100] |
Lokales Setup
bash
cd ml-service
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --reload --port 8000Qdrant muss laufen (das Backend-Workspace liefert npm run start:qdrant als Docker-Container).
Docker
bash
docker build -t daz-ml-service .
docker run --rm -p 8000:8000 \
-e QDRANT_HOST=host.docker.internal \
daz-ml-serviceModell-Download
Der erste Call an
/embed-* oder /classify lädt ca. 3,2 GB Modell-Gewichte von HuggingFace. In Produktion sollte der HuggingFace-Cache gemountet oder ins Image gebacken werden.Projekt-Layout
text
ml-service/
├── main.py FastAPI-App: Lifespan, Dependencies, Router
├── schemas.py Pydantic Request/Response-Modelle
├── embedder.py SigLIP 2 SO400M Wrapper
├── classifier.py LinearSVC + Kalibrierung + Single-Class-Fallback
├── preprocessing.py Center-Crop + Augmentierungs-Presets
├── qdrant_repo.py Qdrant-Client (upsert / scroll / FPS / search)
├── config.py Env-basierte Konfiguration
├── services/
│ ├── classifier_cache.py LRU-Cache + resolve_classifier
│ └── classify.py Framework-freie Klassifikations-Pipeline
├── requirements.txt
└── DockerfileBeziehung zum core-backend
text
mobile app ──HTTPS──> core-backend ──HTTP──> ml-service ──gRPC──> Qdrant
│ │
└─ Postgres ─> Classifier-Blobs + Fachbegriffe| Komponente | Verantwortung |
|---|---|
| core-backend | Video-Upload, ffmpeg-Frame-Extraktion, Sharpness-Filter, Classifier-Blob-Storage (Postgres), Auth, RBAC, Übersetzungen |
| ml-service | SigLIP-2-Inferenz, LinearSVC-Training, Qdrant als Vektorstore, LRU-Cache für kürzlich genutzte Classifier-Blobs |