REST APIs gehören heute zu den wichtigsten Bausteinen moderner Data-Science- und Machine-Learning-Systeme. Sie ermöglichen es, Modelle, Datenpipelines und Analysen als skalierbare, wiederverwendbare Services bereitzustellen – unabhängig davon, welche Programmiersprache oder Plattform auf Client-Seite genutzt wird.
Eine komplette Implementierung zeige ich beispielsweise hier.
Was ist eine REST API?
Eine REST API (Representational State Transfer) ist eine standardisierte Art, über HTTP mit einem Backend-System zu kommunizieren. Beispielsweise können dadurch in Python implementierte Machine Learning Modelle in Webanwendungen oder anderen Services integriert werden. REST APIs basiert auf Prinzipien wie:
- Ressourcenorientierung: Endpunkte repräsentieren Objekte oder Aktionen (z. B.
/predict,/model/info). - HTTP-Methoden: GET (lesen), POST (erstellen), PUT (aktualisieren), DELETE (löschen).
- JSON als Datenaustauschformat: De-facto Standardformat für Request/Response-Daten.
- Statelessness: Jeder Request enthält alle relevanten Informationen – keine Session-Logik auf Server-Seite.
Beispielsweise könnte man ein Vorhersage-Modell mit einem GET-request aufrufen und die Vorhersage für einen bestimmten Wert abfragen:
GET /predict?value=42REST API erstellen – Praxisbeispiel mit FastAPI
FastAPI ist eines der schnellsten und einfachsten Frameworks zur Erstellung von REST API.
In diesem Beispiel erstellen wir eine einfache API, die eine einfache lineare Vorhersage berechnet mit der Formel y=2x+1.
Wir benötigen die Pakete fastapi, uvicorn und pydantic.
pip install fastapi uvicorn pydantic
Die einfachste Implementierung der API sieht so aus:
from fastapi import FastAPI, Request
app = FastAPI()
@app.post("/predict")
async def predict(request: Request):
data = await request.json() # JSON einlesen
value = data["value"] # Eingabewert auslesen
y = 2 * value + 1 # Berechnung
return {"prediction": y} # Antwort zurückgebenUm die API zu starten verwenden wir folgenden Befehl (main ist dabei der Name des Python-Files):
uvicorn main:app --reloadUm die App zu testen kann man folgendes Skript nutzen:
import requests
import json
BASE_URL = "http://127.0.0.1:8000"
data = {"value": 5}
response = requests.post(f"{BASE_URL}/predict", json=data)
print(json.dumps(response.json(), indent=4))Pydantic
Im obigen Beispiel wurde keinerlei Validierung der Eingabedaten vorgenommen. Fehlt im Request der Wert „value“ oder enthält er einen falschen Datenformat, dann schlägt die Anfrage fehl.
Hier kommt Pydantic ins Spiel. Das ist ein Validator und Schema-Generator der im Hintergrund arbeitet und die Eingabedaten validiert. Gleichzeitig wandelt Pydantic verschiedene Datenformate automatisch in Python-typen, um fehlerhafte Inputs zu verhindern. Bei falschen Eingabedaten (Beispielsweise strings statt integers) werden automatisch Fehlermeldungen erstellt.
FastAPI baut ganz stark auf Pydantic auf. Es nutzt die Modelle, um:
- automatisch OpenAPI/Swagger-Dokumentation zu erzeugen
- die Requests automatisch zu validieren
- die Responses zu formatieren
Mit der Integration von Pydantic in den obigen Code, werden viele Dinge vereinfacht.
Statt das rohe Request-Objekt zu verarbeiten werden eingehende JSON-Daten automatisch eingelesen, validiert und in ein Python Objekt umgewandelt.
In diesem Beispiel definiert die Klasse PredictionRequest, dass es ein Feld value geben muss, welchen den Typ float hat (oder dessen Wert in float konvertierbar sein muss). Bei falschen Eingaben gibt FastAPI automatisch einen HTTP Fehler zurück ohne, dass man manuelle Fehlker-Handler schreiben muss.
PredictionResponse definiert die Ausgabe. Die Ausgabe wird als JSON erzeugt und dabei sichergestellt, dass es ein Feld prediction gibt, welches einen float-Wert hat (oder in diesen konvertiert werden kann).
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class PredictionRequest(BaseModel):
value: float
class PredictionResponse(BaseModel):
prediction: float
@app.post("/predict", response_model=PredictionResponse)
def predict(data: PredictionRequest):
y = 2 * data.value + 1
return PredictionResponse(prediction=y)
Swagger & OpenAPI
Wenn die API nun gestartet wird, stellt FastAPI automatisch ein Swagger-Frontends bereit. Es ist zu finden unter /docs, also beispielsweise http://127.0.0.1:8000/docs.
Statt mit einem eigenen Skript kann die API dort über die Funktion „Try it out“ auch direkt ausprobiert werden. Darüber hinaus kann man die Modelle sehen und Parameter testen – extrem hilfreich in der Zusammenarbeit mit anderen anderen Teams oder Stakeholdern.
Weiterführende Beispiele
Mehrere Eingabefelder validieren
Um mehrere Eingabefelder zu validieren kann man einfach die Klasse PredictionRequest erweitern:
class PredictionRequest(BaseModel):
age: int
income: float
gender: strKomplexere Strukturen
Pydantic unterstützt auch Listen, verschachtelte Objekte, optionale Felder etc.
class Item(BaseModel):
name: str
price: float
class Order(BaseModel):
items: list[Item]
customer_id: intEigene Validierungsregeln
Auch die Implementierung von eigenen Validierungsregeln ist möglich. Beispielsweise könnte man den Wert so festlegen, dass er positiv sein mus.
from pydantic import validator
class PredictionRequest(BaseModel):
value: float
@validator("value")
def must_be_positive(cls, v):
if v < 0:
raise ValueError("value must be >= 0")
return v