FastAPI ML-Service fuer visuelle Aehnlichkeitssuche von CAD-Werkstuecken (CLIP, FAISS)
  • Python 95.7%
  • PowerShell 4%
  • Mako 0.3%
Find a file
Yoshi 43d7d98bff perf: uvicorn Multi-Worker fuer hoehere Parallelitaet
--workers 4 fuer NSSM-Service (Default war 1 Worker)
2026-02-15 15:45:49 +01:00
alembic Initial commit: ML-Service aus reperio-parts extrahiert 2026-02-11 11:49:18 +01:00
app Logging zentralisieren: File-Output, Middleware, Auth- und FeedbackService-Logging 2026-02-13 10:16:45 +01:00
deploy perf: uvicorn Multi-Worker fuer hoehere Parallelitaet 2026-02-15 15:45:49 +01:00
docs/adr Logging zentralisieren: File-Output, Middleware, Auth- und FeedbackService-Logging 2026-02-13 10:16:45 +01:00
tests Logging zentralisieren: File-Output, Middleware, Auth- und FeedbackService-Logging 2026-02-13 10:16:45 +01:00
.env.example Logging zentralisieren: File-Output, Middleware, Auth- und FeedbackService-Logging 2026-02-13 10:16:45 +01:00
.gitignore Initial commit: ML-Service aus reperio-parts extrahiert 2026-02-11 11:49:18 +01:00
alembic.ini Initial commit: ML-Service aus reperio-parts extrahiert 2026-02-11 11:49:18 +01:00
CLAUDE.md docs: CLAUDE.md mit Stack-Kontext und Gotchas 2026-02-12 20:47:11 +01:00
compute_embeddings.py fix: Portable Modell-Erkennung + Deploy auf Scheduled Task 2026-02-11 17:51:48 +01:00
LICENSE Proprietäre Lizenz (thyssenkrupp) hinzugefügt 2026-02-13 09:38:22 +01:00
pyproject.toml fix: Portable Modell-Erkennung + Deploy auf Scheduled Task 2026-02-11 17:51:48 +01:00
README.md docs: Zielplattform auf Windows Server 2019+ erweitert 2026-02-12 16:49:01 +01:00
run_classifier.py Initial commit: ML-Service aus reperio-parts extrahiert 2026-02-11 11:49:18 +01:00
run_import.py Initial commit: ML-Service aus reperio-parts extrahiert 2026-02-11 11:49:18 +01:00
run_train.py Initial commit: ML-Service aus reperio-parts extrahiert 2026-02-11 11:49:18 +01:00

reperio.Parts ML-Service

FastAPI-basierter ML-Service für visuelle Ähnlichkeitssuche von CAD-Werkstücken (CLIP + FAISS).


Überblick

Der reperio.Parts ML-Service ist ein eigenständiger HTTP-Dienst (siehe ADR-011 in reperio-parts) für alle ML-Operationen der reperio.Parts-Plattform. Er extrahiert visuelle Embeddings aus CAD-Ansichten mittels CLIP, indiziert diese in einem FAISS-Index und bietet eine REST-API für Ähnlichkeitssuche, Tagging und Training.

Kernfunktionen:

  • CLIP ViT-B/32 Embeddings -- 512-dimensionale, L2-normalisierte Feature-Vektoren aus ISO-Ansichten
  • FAISS IndexFlatIP -- Cosine-Similarity-Suche über Inner Product auf normalisierten Vektoren
  • Tag-Classifier -- Pro-Tag LogisticRegression für automatische Klassifikation
  • Auto-Tagging -- Versionierte automatische Tag-Vergabe (auto:v1)
  • Shared SQLite DB -- WAL-Modus, gemeinsam genutzt mit dem C# Backend (reperio-parts)
  • Windows-Service -- Läuft in Produktion als Windows-Dienst via NSSM

Tech Stack

Komponente Version
Python 3.12+
FastAPI 0.115+
Uvicorn 0.34+ (Standard)
PyTorch 2.0+ (ROCm / CUDA / CPU)
open-clip-torch 2.29+
FAISS faiss-cpu 1.9+
scikit-learn 1.6+
SQLAlchemy 2.0+
Alembic 1.14+
Pydantic Settings 2.7+
Pillow 11.0+
NumPy 2.0+

Schnellstart

# Repository klonen
git clone https://github.com/swissYoshi/reperio-embedding-service.git
cd reperio-embedding-service

# Virtual Environment erstellen und aktivieren
python -m venv .venv
source .venv/bin/activate        # Linux
# .venv\Scripts\activate          # Windows

# Dependencies installieren (inkl. ML und Dev-Tools)
pip install -e ".[ml,dev]"

# .env erstellen und anpassen
cp .env.example .env
# REPERIO_DATA_DIR auf den Pfad zu CADAnsichten setzen

# Datenbank-Migrationen ausführen
alembic upgrade head

# Embeddings berechnen (Erststart, dauert je nach Kataloggrösse)
python compute_embeddings.py

# Service starten (Entwicklung)
uvicorn app.main:create_app --factory --reload --port 8100

Nach dem Start ist die Swagger-Dokumentation unter http://localhost:8100/docs erreichbar.


Konfiguration

Alle Einstellungen werden über Umgebungsvariablen mit dem Prefix REPERIO_ konfiguriert. Alternativ können sie in einer .env-Datei im Projektverzeichnis hinterlegt werden.

Umgebungsvariablen

Variable Default Beschreibung
REPERIO_DATA_DIR -- Pfad zu CADAnsichten (Pflicht)
REPERIO_OUTPUT_DIR ./outputs Basisverzeichnis für Embeddings, FAISS, DB, Models
REPERIO_EMBEDDING_MODEL ViT-B-32 OpenCLIP-Modellname
REPERIO_EMBEDDING_PRETRAINED laion2b_s34b_b79k Pretrained Checkpoint
REPERIO_EMBEDDING_DIM 512 Embedding-Dimension
REPERIO_BATCH_SIZE 32 Batch-Grösse für Embedding-Extraktion
REPERIO_DEVICE auto Rechengerät: cpu, cuda oder auto
REPERIO_HOST 0.0.0.0 Bind-Adresse des HTTP-Servers
REPERIO_PORT 8100 HTTP-Port
REPERIO_LOG_LEVEL INFO Log-Level (DEBUG, INFO, WARNING, ERROR)
REPERIO_AUTH_ENABLED false S2S-Authentifizierung (derzeit nicht aktiv)
REPERIO_S2S_SECRET -- Shared Secret für S2S-Auth
REPERIO_FINETUNE_LR 1e-6 Learning Rate für CLIP Fine-Tuning
REPERIO_FINETUNE_EPOCHS 10 Epochen für CLIP Fine-Tuning
REPERIO_FINETUNE_MARGIN 0.2 Triplet-Margin für kontrastives Lernen
REPERIO_FINETUNE_BATCH_SIZE 16 Batch-Grösse für Fine-Tuning
REPERIO_AUTOTAG_CONFIDENCE 0.8 Confidence-Schwelle für Auto-Tagging
REPERIO_AUTOTAG_MAX_TAGS 5 Maximale Auto-Tags pro Teil
REPERIO_AUTOTAG_VERSION v1 Versions-String für Auto-Tags
REPERIO_CLASSIFIER_MIN_EXAMPLES 3 Minimum Beispiele pro Tag für Classifier-Training
REPERIO_CLASSIFIER_CONFIDENCE 0.8 Confidence-Schwelle für Classifier

Abgeleitete Pfade

Alle abgeleiteten Pfade basieren auf REPERIO_OUTPUT_DIR:

Pfad Inhalt
{output_dir}/embeddings/ NumPy-Dateien mit Embedding-Vektoren und Metadaten
{output_dir}/faiss_index.bin Serialisierter FAISS-Index
{output_dir}/models/ Fine-Tuned CLIP-Modelle
{output_dir}/classifiers/ Gespeicherte Tag-Klassifikatoren (joblib)
{output_dir}/evaluations/ Evaluations-Ergebnisse (JSON)
{output_dir}/reperio.db SQLite-Datenbank (shared mit reperio-parts)

API-Endpunkte

Alle Endpunkte befinden sich unter dem Prefix /api. Interaktive Dokumentation: http://localhost:8100/docs

System

Methode Pfad Beschreibung
GET /api/health Health-Check für Load-Balancer und Monitoring
GET /api/status System-Info: Konfiguration, Katalog- und Index-Status
POST /api/reload Katalog, Embeddings und FAISS-Index neu laden
GET /api/settings UI-konfigurierbare Settings aus der Datenbank lesen
PUT /api/settings Settings aktualisieren

Suche

Methode Pfad Beschreibung
GET /api/search/bmn/{bmn}?k=200 Ähnlichkeitssuche ausgehend von einer Bauteilnummer
POST /api/search/image?k=200 Ähnlichkeitssuche via Bild-Upload (Multipart)

Teile

Methode Pfad Beschreibung
GET /api/parts?offset=0&limit=80&q=&tags=&tags_neg= Teile-Katalog mit Filterung und Pagination
GET /api/parts/{bmn} Detail-Ansicht eines einzelnen Teils
GET /api/suggestions?q=&limit=10 BEZ-Vorschläge für Autocomplete

Tags

Methode Pfad Beschreibung
GET /api/tags Alle Tags mit Häufigkeit und Typ
PUT /api/tags/types Tag-Typen setzen (visual / attribute)
GET /api/search/tags?q=&limit=20 Fuzzy Tag-Suche
POST /api/annotations/tags Tags zu Teilen hinzufügen
DELETE /api/annotations/tags Tags von Teilen entfernen

Training

Methode Pfad Beschreibung
POST /api/train/clip CLIP Fine-Tuning starten
POST /api/train/classifier Tag-Klassifikator trainieren
POST /api/train/evaluate Retrieval-Evaluation starten
POST /api/train/autotag-classifier Auto-Tagging mit Klassifikator starten
GET /api/train/status Aktueller Trainings-Status
GET /api/train/stream SSE-Stream für Live-Trainingsfortschritt
POST /api/train/stop Laufendes Training abbrechen

Projektstruktur

reperio-embedding-service/
├── app/
│   ├── api/                  REST-Endpoints
│   │   ├── system.py           Health, Status, Reload, Settings
│   │   ├── search.py           BMN-Suche, Bild-Upload-Suche
│   │   ├── parts.py            Browse, Detail, BEZ-Vorschläge
│   │   ├── tags.py             Tag-CRUD, Typ-Verwaltung, Tag-Suche
│   │   └── training.py         Training-Steuerung, SSE-Stream
│   ├── core/                 Infrastruktur
│   │   ├── config.py           Pydantic Settings (Umgebungsvariablen)
│   │   ├── database.py         SQLAlchemy Engine + Session Factory
│   │   ├── auth.py             S2S-Authentifizierung (Dependency)
│   │   └── events.py           Lifespan Events (Startup/Shutdown)
│   ├── models/               Daten-Modelle
│   │   ├── db.py               SQLAlchemy ORM (Annotation, Tag, Pair, ...)
│   │   └── schemas.py          Pydantic Request/Response Schemas
│   ├── services/             Business-Logik
│   │   ├── search.py           SearchService (Katalog, Embeddings, FAISS)
│   │   ├── feedback.py         FeedbackService (Tags, Annotations, Settings)
│   │   └── training.py         TrainingManager (ThreadPoolExecutor)
│   ├── ml/                   Machine Learning
│   │   ├── clip/               CLIP-Modell
│   │   │   ├── extract.py        Embedding-Extraktion aus Bildern
│   │   │   ├── recompute.py      Alle Embeddings neu berechnen
│   │   │   └── finetune.py       Kontrastives Fine-Tuning (Triplet Loss)
│   │   ├── faiss/              FAISS-Index
│   │   │   └── index.py          Index-Aufbau und Suche
│   │   ├── classifier/         Tag-Klassifikation
│   │   │   ├── classifier.py     Pro-Tag LogisticRegression
│   │   │   ├── predict.py        Batch-Prediction für Auto-Tagging
│   │   │   └── review.py         Classifier-Review und Statistiken
│   │   ├── triplets/           Trainings-Daten
│   │   │   └── generator.py      Triplet-Generierung für kontrastives Lernen
│   │   ├── evaluation/         Metriken
│   │   │   └── evaluate.py       Retrieval-Evaluation (Recall@K, NDCG)
│   │   └── data/               Daten-Zugriff
│   │       └── loader.py         Katalog-Scanner, Bild-Loader
│   ├── dependencies.py       FastAPI Dependency Injection
│   └── main.py               App-Factory (create_app)
├── tests/                    22 Testmodule (pytest + pytest-asyncio)
├── alembic/                  Datenbank-Migrationen
│   └── versions/
│       ├── 001_initial_schema.py
│       └── 002_settings_updated_at_default.py
├── deploy/                   Deployment-Scripts
│   ├── Build-OfflinePackage.ps1  Offline-Paket für Air-Gapped Server
│   └── Setup-Service.ps1         Windows-Service via NSSM installieren
├── compute_embeddings.py     Standalone: Embeddings + FAISS-Index berechnen
├── run_train.py              Standalone: CLIP Fine-Tuning / Recompute
├── run_classifier.py         Standalone: Classifier trainieren + Auto-Taggen
├── run_import.py             Standalone: Katalog scannen, neue Embeddings
├── pyproject.toml            Projekt-Konfiguration und Dependencies
├── alembic.ini               Alembic-Konfiguration
└── .env.example              Vorlage für Umgebungsvariablen

Standalone-Scripts

Die Scripts können unabhängig vom HTTP-Service ausgeführt werden.

Script Zweck Aufruf
compute_embeddings.py Alle Embeddings berechnen und FAISS-Index aufbauen (Erststart) python compute_embeddings.py
run_train.py CLIP Fine-Tuning oder Recompute python run_train.py --evaluate-only --device auto
run_classifier.py Tag-Classifier trainieren, optional mit Auto-Tagging python run_classifier.py --auto-tag --threshold 0.7
run_import.py Katalog scannen und Embeddings für neue Teile berechnen python run_import.py --device auto

Alle Scripts geben JSON-Progress an stdout aus (--json-progress), sodass das C# Backend den Fortschritt über SSE an die UI weiterleiten kann.


Datenbank

Der Service nutzt SQLAlchemy ORM mit SQLite als Backend. Die Datenbank liegt unter {output_dir}/reperio.db und wird im WAL-Modus betrieben, damit sowohl der ML-Service als auch das C# Backend (reperio-parts) gleichzeitig lesen und schreiben können.

Tabellen

Tabelle Beschreibung
annotations Pro-Teil Metadaten (BMN, Bezeichnung, Beschreibung)
tags Tag-Zuordnungen zu Teilen (BMN, Tag, Source)
tag_types Tag-Klassifikation: visual oder attribute
pairs Ähnlichkeitspaare zwischen zwei Teilen (manuelles Feedback)
groups Gruppen (Legacy)
group_members Gruppenmitgliedschaft
training_runs Audit Trail für Trainingsläufe
settings UI-konfigurierbare Einstellungen (Key-Value)

Migrationen

# Auf neuesten Stand bringen
alembic upgrade head

# Neue Migration erstellen (nach ORM-Änderung)
alembic revision --autogenerate -m "beschreibung"

ML-Pipeline

CLIP-Embeddings

Für jedes Teil im Katalog wird die ISO-Ansicht (Fallback: ~ISO, Front, beliebig verfügbar) durch das CLIP ViT-B/32 Modell geschickt. Das Ergebnis ist ein 512-dimensionaler Feature-Vektor, der L2-normalisiert gespeichert wird.

FAISS-Index

Der FAISS IndexFlatIP (Inner Product) arbeitet auf L2-normalisierten Vektoren. Das Inner Product normalisierter Vektoren entspricht der Cosine Similarity. Die Suche liefert die k ähnlichsten Teile mit einem Score zwischen 0 und 1.

Tag-Classifier

Für jeden Tag vom Typ visual wird ein eigener LogisticRegression-Classifier auf den CLIP-Embeddings trainiert. Voraussetzung: mindestens REPERIO_CLASSIFIER_MIN_EXAMPLES Beispiele pro Tag (Default: 3).

Auto-Tagging

Auto-Tags werden versioniert gespeichert (z.B. auto:v1 als Source). Bei einem Retrain werden alle Auto-Tags der jeweiligen Version komplett gelöscht und neu berechnet. Manuelle Tags werden dabei nicht berührt -- bei Konflikten zwischen manuellen und automatischen Tags hat der Mensch immer die Entscheidungshoheit.

Training-Steuerung

Alle Trainings-Operationen laufen in einem ThreadPoolExecutor mit max_workers=1, sodass immer nur ein Training gleichzeitig aktiv ist. Der Fortschritt wird über SSE (Server-Sent Events) an die UI gestreamt.


Tests

# Alle Tests ausführen
pytest tests/

# Verbose-Ausgabe
pytest tests/ -v

# Einzelnes Testmodul
pytest tests/test_classifier.py

# Pattern-Matching
pytest -k "classifier"

# Coverage (falls installiert)
pytest tests/ --cov=app

22 Testmodule mit pytest und pytest-asyncio. Die Tests nutzen SQLite In-Memory-Datenbanken und gemockte ML-Komponenten, sodass kein GPU oder CLIP-Modell für die Testausführung benötigt wird.


Deployment (Produktion)

Windows-Service via NSSM

Auf dem Zielserver (Windows Server 2019+, Air-Gapped) wird der Service als Windows-Dienst via NSSM betrieben:

.\deploy\Setup-Service.ps1 -DataDir "\\fileserver\CADAnsichten" -Port 8100

Der Service bindet in Produktion auf 127.0.0.1 (nur localhost), da er ausschliesslich vom C# Backend auf demselben Server aufgerufen wird.

Offline-Paket

Für Air-Gapped Umgebungen ohne Internetzugang:

# Auf dem Entwicklungsrechner (mit Internetzugang)
.\deploy\Build-OfflinePackage.ps1

Das Script erstellt ein vollständiges Paket mit allen Python-Wheels und dem CLIP-Modell-Cache.

CLIP-Modell offline bereitstellen

Da der Zielserver keinen Internetzugang hat, muss das CLIP-Modell manuell im HuggingFace-Cache abgelegt werden. Die Umgebungsvariable HF_HOME zeigt auf das lokale Verzeichnis mit dem vorinstallierten Modell.

Log-Dateien

In Produktion schreibt NSSM die stdout/stderr-Ausgabe in:

{InstallDir}\logs\stdout.log

Integration mit reperio-parts

Der ML-Service wird vom C# ASP.NET Core Backend (reperio-parts) als HTTP-Dienst aufgerufen. Die Kommunikation erfolgt über die REST-API.

Konfiguration im C# Backend

In appsettings.json:

{
  "MlService": {
    "BaseUrl": "http://127.0.0.1:8100"
  }
}

Die Anbindung erfolgt über MlServiceClient.cs im reperio-parts Projekt.

Shared Database

Beide Services teilen sich dieselbe SQLite-Datenbank (reperio.db). Der WAL-Modus erlaubt gleichzeitige Lese- und Schreibzugriffe. REPERIO_OUTPUT_DIR im ML-Service muss auf dasselbe Verzeichnis zeigen, das auch das C# Backend als Datenbankpfad nutzt.

Authentifizierung

Beide Services laufen auf demselben Server (localhost). Eine S2S-Authentifizierung ist vorbereitet (REPERIO_AUTH_ENABLED), aber derzeit nicht aktiviert.


Lizenz

Proprietär -- Interne Unternehmensanwendung.