Setup einer integrierten Machine Learning Infrastruktur

Picture of scalewerk.io

Machine Learning in der Produktion ist komplex, lässt sich aber mit dem richtigen Setup sehr gut automatisieren. Dieser Artikel zeigt beispielhaft auf, wie ein vollautomatisches ML-System aufgebaut werden kann, das sich kontinuierlich selbst verbessert.

Die Herausforderung

Stellen Sie sich vor: Sie haben tausende Bilder und möchten ein KI-Modell trainieren, das diese Bilder klassifiziert. Die klassische Herangehensweise bedeutet oft:

  • Daten manuell in Ordnerstrukturen sortieren
  • Skripte für Training schreiben und manuell ausführen
  • Modelle manuell deployen
  • Bei neuen Daten: Alles von vorne

Das kann Wochen dauern und ist fehleranfällig und bedeutet enormen manuellen Aufwand.

Die Lösung: Ein selbstlernendes Machine-Learning-Ökosystem

Statt isolierter Komponenten sollte ein integriertes System aufgebaut werden, bei dem alle Teile nahtlos zusammenarbeiten, um die manuellen Aufwände auf ein Minimum zu reduzieren. In unserem Beispiel-Setup sieht das wie folgt aus:

 
Die eingesetzten Tools sind allesamt Open-Source und lediglich eine mögliche Option ein solches Setup umzusetzen. Das Beispiel orientiert sich an einem einfachen Cats-And-Dogs Classification Model deren Bilddaten auf Kaggle verfügbar sind: https://www.kaggle.com/datasets/bhavikjikadara/dog-and-cat-classification-dataset 
 
In diesem Beispiel wird bewusst nur das infrastrukturelle Setup beschrieben, ohne dem dahinterliegendem Code im Detail zu betrachten. 

 

Die Komponenten im Detail

 

Label Studio: Das Herzstück der Annotation


Label Studio ist die zentrale Plattform für die Datenverwaltung und Annotation. Hier findet die manuelle Annotation und Qualitätssicherung durch den Anwender statt:

- Import aus S3: Tausende Bilder werden automatisch als Tasks importiert
- Intuitive Benutzeroberfläche: Nutzer können Bilder mit wenigen Klicks labeln
- ML-Integration: Modelle werden direkt eingebunden und Vorhersagen (Predictions) des Modells werden direkt angezeigt
- Trainings-Trigger: Ein Knopfdruck startet das Re-Training

Das Besondere: Label Studio kennt das ML Backend und kommuniziert direkt damit. 
 

ML-Backend: Der Vermittler

Das ML Backend ist ein Python-Service, der auf dem Label Studio ML Framework basiert. Seine Aufgaben:

Für Predictions:
- Empfängt Anfragen von Label Studio
- Lädt Bilder aus S3
- Führt Inferenz mit dem aktuellen Modell aus
- Gibt Vorhersagen mit Confidence-Scores zurück

Für das Training:
- Empfängt START_TRAINING Events von Label Studio
- Triggert die Forgejo CI/CD-Pipeline, welche das Training ausführt
- Überwacht MLflow auf neue Modellversionen
- Lädt automatisch das neueste Modell

Die direkte Anbindung des ML-Backends, Label Studio und MLflow ermöglicht uns Zero-Downtime Model Updates. Während das Backend Predictions ausliefert, prüft es periodisch MLflow auf neue Versionen. Sobald ein neues Modell verfügbar ist, wird es im Hintergrund geladen und nahtlos aktiviert – ohne, dass laufende Anfragen unterbrochen werden oder der Service neu gestartet werden muss:
 

 

MLflow: Die Model-Registry

MLflow ist das Versions-Management-System für ML-Modelle:

- Experiment Tracking: Jeder Trainingslauf wird mit allen Metriken geloggt
- Model Versioning: Jede Iteration wird als separate Version gespeichert
- Artifact Storage: Das trainierte Modell selbst wird sicher abgelegt
- REST-API: Das Backend kann jederzeit die neueste Version abrufen

Ein Blick in MLflow zeigt die Evolution des Modells:

Version 1: 100 Annotations → Accuracy 75%
Version 2: 500 Annotations → Accuracy 89%
Version 3: 1.000 Annotations → Accuracy 94%
 

Forgejo CI/CD: Die Trainings-Infrastruktur

Forgejo (ein Gitea-Fork) ist ein Self-Hosted CI/CD-System welches u.a. Github Actions unterstützt. Wenn ein neues Training getriggert wird, passiert dabei folgendes:

1.  Workflow startet: GPU-Container wird hochgefahren
2. Daten laden: Neueste Annotationen werden von Label Studio geholt
3. Training: PyTorch trainiert auf der GPU
4. MLflow Upload: Neues Modell wird registriert
5. Automatisches Deployment: Backend lädt neues Modell

Das Training wird auf einer dedizierten VM auf bspw. Proxmox ausgeführt, die exklusiven Zugriff auf die GPU des Host-Systems hat. Je nach Datenmenge dauert ein Trainingslauf in der Regel zwischen 10 Minuten und mehreren Stunden.
 

Der Workflow

Im Folgenden skizzieren wir einmal den kompletten Workflow – vom ersten Commit für ein neues Modell bis zum funktionierenden ML-System. Die grobe Projekstruktur in welche sich das gesamte Setup eingliedert sieht dabei wie folgt aus:

.github/
├── workflows/
    ├── train.yaml             # workflow file for the training pipeline
    ├── deploy_backend.yaml    # workflow file for ml-backend deployment 
    ├── ...
models/
├── cats_and_dogs_classifier/  # all files in this folder are created with create_new_model.py
    ├── backend.py             # ml-backend Implementation for the cats_and_dogs_classifier
    ├── config.yaml            # configuration for this backend
    ├── docker-compose.yaml    # deployment config for ml-backend (extends ../../src/predict/docker-compose.yaml)
    ├── labeling_template.xml  # labeling template for label-studio
    ├── model.py              # model-architecture (z.B. MobileNetV2)
├── ...                        # More backend and model definitions...
    ├── ...
├── template/                   # template files for each model type
    ├── classification/
    ├── common/
    ├── detection/
scripts/
├── create_new_model.py            # generates the whole project structure for a new model under models/
├── upload_images_to_s3.py         # helper script for simple upload of new image assets
├── setup_label_studio_project.py  # creates a new project in label-studio
├── ...                            # more scripts...   
src/
├── common/                    # shared code between predict and train
├──train/
    ├── Dockerfile
    ├── docker-compose.yaml    # deployment config for training container running the training workflow
    ├── *.py                   # base classes for Label Studio ML Backends
├── predict/
    ├── Dockerfile
    ├── docker-compose.yaml    # base deployment config for ml-backend container running the predictions
    ├── *.py                   # base classes for model training
 
 

Phase 1: Setup für ein neues Modell

 

Ein Developer erstellt die Modell-Struktur im Git-Repository. Anstatt alle Dateien manuell anzulegen, nutzten wir dabei ein Template-System über welches alle Dateien generiert werden:

 
python scripts/create_new_model.py \
--model cat_and_dog_classifier \
--problem-type classification \
--classes "Cat,Dog" \
--architecture pretrained
 
Das System unterstützt verschiedene Problem-Typen (Classification, Object Detection) und generiert automatisch die passende Struktur. Das Script übernimmt dabei Port-Management, Naming-Conventions und aktualisiert sogar die CI/CD-Workflows. Das Ergebnis:
 
models/
cats_and_dogs_classifier/
├── model.py # Modell-Architektur (z.B. MobileNetV2)
├── backend.py # ML Backend Implementation
├── config.yaml # Konfiguration (Single Source of Truth)
└── docker-compose.yaml # Deployment Config
 
Die config.yaml ist dabei das Herzstück: Sie definiert nicht nur Hyperparameter, sondern auch die Label Studio Integration, S3-Pfade, Modell-Architektur und sogar die Labeling-Templates. Alles an einem Ort und versioniert in Git.

Nach dem Commit wird über Forgejo ein Workflow ausgelöst welcher ein dediziertes ML-Backend als Docker Container für dieses Model bereitstellt. Das Deployment-Script erstellt automatisch das zugehörige Label Studio Projekt in Label Studio, konfiguriert die S3-Anbindung für dieses Projekt und importiert alle Tasks:
 
 
Das setup_label_studio_project.py Script liest dabei die config.yaml und konfiguriert automatisch:
 
- Label Studio Projekt mit den richtigen Klassen
- S3 Storage Connection mit Bucket und Prefix
- ML Backend URL und Authentifizierung
- Initialer Sync der Tasks aus S3

Ergebnis: Das ML Backend läuft und das Label Studio Projekt ist erstellt. Ausserdem sind alle zugehörigen Tasks  importiert aber: Wir haben noch kein trainiertes Modell!
 

Phase 2: Erste Annotationen

 

Jetzt kommt der aufwendige Teil. Über Label Studio muss ein ausgewähltes Subset an Tasks manuell gelabelt werden:

- Task öffnen: Ein Bild wird angezeigt
- Label auswählen: Jedem Bild ein Label zuweisen
- Submitten: Annotation wird gespeichert
- Wiederholen: Bis mindestens 50-100 Bilder gelabelt sind, idealerweise aber mehr

Das ist der einzige manuelle Schritt, welcher nicht automatisiert werden kann und auch nicht automatisiert werden sollte. Die menschliche Expertise ist hier entscheidend für die Modellqualität (Ausnahme: die Bilder sind strukturiert abgelegt/benannt wie beim Cats_and_Dogs dataset von Kaggle (s.o.), dann kann die Annotation bspw. auf Basis der Verzeichnisstruktur automatisiert werden).
 

Phase 3: Erstes Training

 

Mit den manuell gesetzten Annotationen kann das erste Training starten:

1. In Label Studio: Settings → ML Backend → "Start Training" (alternativ direkt über Forgejo)
2. Backend: Empfängt Event, triggert Forgejo Workflow
3. Forgejo: Startet GPU-Container, lädt Daten, trainiert Modell
4. MLflow: Speichert trainiertes Modell als Version 1
5. Backend: Detektiert neues Modell und lädt es automatisch
 
 
Ergebnis: Jetzt haben wir ein funktionierendes ML-System! Predictions erscheinen automatisch beim Öffnen wenn Tasks geöffnet werden und können über Label Studio auch Batchweise durchgeführt werden.
 

Der kontinuierliche Verbesserungszyklus

Nach dem initialen Setup beginnt der eigentliche Mehrwert: Das System verbessert sich kontinuierlich selbst.
 

Die Prediction-Loop

 

Jedes Mal, wenn ein Nutzer einen Task öffnet:

1. Label Studio: fordert Prediction an
2. ML Backend: lädt Bild und führt Inferenz aus
3. Prediction: Ein Score zwischen 0% und 100% wird angezeigt
4. Review: Nutzer akzeptiert oder korrigiert die Vorhersage
5. Speichern: Datenset wächst für das nächste Training
 
Das Clevere: Korrekte Predictions beschleunigen das Labeling enorm. Statt jedes Bild manuell zu klassifizieren, müssen nur noch fehlerhafte Predictions korrigiert werden.
 

Der Retraining-Loop


Mit der Zeit sammeln sich viele neue Annotationen an. Mit jeden neuen Training
ensteht eine neue, optimierte Modellversion:
 
 
Der Zyklus wiederholt sich. Mit jedem Durchlauf:
 
- Mehr Daten → Besseres Training
- Besseres Modell → Genauere Predictions
- Genauere Predictions → Schnelleres Labeling
- Schnelleres Labeling → Mehr Daten

Es ist ein positiver Feedback-Loop: Das System wird immer besser, je mehr es genutzt wird.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

Fazit


Mit den richtigen Tools und einer durchdachten Architektur lässt sich ein produktives ML-System in relativ kurzer Zeit  aufsetzen. Der Schlüssel:

1. Tools: der sinnvolle Einsatz existierender Open-Source Tools wie z.B.: Label Studio, MLflow, Forgejo
2. Automatisierung:  "Automatisiere alles außer der Annotation" – da braucht es menschliche Intelligenz
3. Pipelines: Nicht isolierte Skripte, sondern integrierte Workflows

Das Ergebnis: Ein ML-System, welches sich selbst verbessert, während es produktiv genutzt wird.
 
Möchten Sie Ihre eigene Machine-Learning-Infrastruktur aufbauen und lokale KI-Modelle trainieren?
Kontaktieren Sie uns – wir würden uns freuen Sie bei diesem Weg zu begleiten!