ModelMesh inclut des runtimes intégrés pour les frameworks d'inférence courants, mais certaines charges de travail nécessitent une logique de pré/post-traitement personnalisée, des frameworks non pris en charge ou un contrôle précis des ressources. Un ServingRuntime personnalisé vous permet de définir exactement comment les modèles sont chargés et servis, puis d'enregistrer ce runtime afin que ModelMesh planifie et mette à l'échelle les modèles automatiquement.
Ce guide explique comment créer un runtime personnalisé basé sur Python avec MLServer, l'empaqueter sous forme d'image conteneur, l'enregistrer en tant que ServingRuntime et déployer un modèle qui l'utilise.
Prérequis
Avant de commencer, assurez-vous de disposer des éléments suivants :
Un cluster Container Service for Kubernetes (ACK) ajouté à votre instance Service Mesh (ASM)
Une instance ASM de version 1.18.0.134 ou ultérieure
Runtimes intégrés
Avant de créer un runtime personnalisé, vérifiez si un runtime intégré prend déjà en charge le format de votre modèle.
| Serveur de modèle | Développeur | Frameworks pris en charge | Idéal pour |
|---|---|---|---|
| Triton Inference Server | NVIDIA | TensorFlow, PyTorch, TensorRT, ONNX | Inférence haute performance, évolutive et à faible latence avec surveillance intégrée |
| MLServer | Seldon | SKLearn, XGBoost, LightGBM | API unifiée pour plusieurs frameworks d'apprentissage automatique |
| OpenVINO Model Server | Intel | OpenVINO, ONNX | Accélération matérielle Intel |
| TorchServe | PyTorch | PyTorch (y compris le mode eager) | Service natif PyTorch léger |
Si aucun de ces runtimes ne prend en charge votre framework, ou si votre pipeline d'inférence nécessite une logique personnalisée, créez un runtime de service personnalisé comme décrit ci-dessous.
Fonctionnement
Un ServingRuntime (limité à un namespace) ou ClusterServingRuntime (limité au cluster) définit le modèle de pod pour servir un ou plusieurs formats de modèle. Chaque ressource spécifie :
L'image conteneur qui exécute le serveur d'inférence
Une liste des formats de modèle pris en charge
Les variables d'environnement pour la configuration du runtime
ServingRuntime est une CustomResourceDefinition (CRD) Kubernetes. Vous pouvez donc créer des runtimes réutilisables sans modifier le contrôleur ModelMesh ni aucune ressource dans le namespace du contrôleur.
Pour les frameworks basés sur Python, la méthode la plus rapide consiste à étendre MLServer. MLServer fournit l'interface de service, vous fournissez la logique du modèle et ModelMesh gère la planification et la mise à l'échelle.
Le flux de travail comporte trois étapes :
Implémentez la classe de modèle en étendant la classe
MLModelde MLServer.Empaquetez la classe et ses dépendances dans une image conteneur.
Enregistrez l'image en tant que ServingRuntime dans Kubernetes.
Étape 1 : Implémenter la classe MLModel
Créez une classe Python qui hérite de la classe MLModel de MLServer. Implémentez deux méthodes :
load(): initialisez le modèle (chargez les poids, préparez les caches).predict(): exécutez l'inférence sur une requête entrante.
from typing import List
from mlserver import MLModel, types
from mlserver.utils import get_model_uri
# List the filenames your model uses so MLServer can locate them.
WELLKNOWN_MODEL_FILENAMES = ["model.json", "model.dat"]
class CustomMLModel(MLModel):
async def load(self) -> bool:
model_uri = await get_model_uri(
self._settings, wellknown_filenames=WELLKNOWN_MODEL_FILENAMES
)
# TODO: Load the model from model_uri and store it as an instance attribute.
# Example: self._model = joblib.load(model_uri)
self.ready = True
return self.ready
async def predict(
self, payload: types.InferenceRequest
) -> types.InferenceResponse:
payload = self._check_request(payload)
return types.InferenceResponse(
model_name=self.name,
model_version=self.version,
outputs=self._predict_outputs(payload),
)
def _check_request(self, payload):
# TODO: Validate the request -- check input tensor names, shapes, and types.
return payload
def _predict_outputs(self, payload) -> List[types.ResponseOutput]:
# TODO: Extract input data from payload.
# TODO: Run the data through your model's prediction logic.
# TODO: Construct and return a list of ResponseOutput objects.
outputs = []
return outputs
Pour plus d'exemples, consultez la documentation sur les runtimes personnalisés de MLServer.
Étape 2 : Empaqueter le runtime dans une image conteneur
Regroupez votre classe CustomMLModel, MLServer et toutes les dépendances dans une image conteneur.
Option A : Utiliser la CLI MLServer (recommandée)
MLServer fournit la commande mlserver build pour générer une image automatiquement. Pour plus de détails, consultez la section Création d'une image personnalisée.
Option B : Rédiger un Dockerfile
# Use a Python base image that matches your dependency requirements.
FROM python:3.8-slim-buster
RUN pip install mlserver
# Place your MLModel implementation on the Python path.
COPY --chown=${USER} ./custom_model.py /opt/custom_model.py
ENV PYTHONPATH=/opt/
# Set environment variables for ModelMesh compatibility.
# These can also be set in the ServingRuntime YAML, but embedding them here
# ensures consistent behavior during local testing.
ENV MLSERVER_MODELS_DIR=/models/_mlserver_models \
MLSERVER_GRPC_PORT=8001 \
MLSERVER_HTTP_PORT=8002 \
MLSERVER_LOAD_MODELS_AT_STARTUP=false \
MLSERVER_MODEL_NAME=dummy-model
# Point MLServer to your class so the implementation field is optional
# in model settings.
ENV MLSERVER_MODEL_IMPLEMENTATION=custom_model.CustomMLModel
CMD ["mlserver", "start", "${MLSERVER_MODELS_DIR}"]
Construisez et poussez l'image :
docker build -t <your-registry>/<your-image-name>:<tag> .
docker push <your-registry>/<your-image-name>:<tag>
Remplacez les espaces réservés suivants par des valeurs réelles :
| Espace réservé | Description | Exemple |
|---|---|---|
<your-registry> |
Adresse du registre de conteneurs | registry.cn-hangzhou.aliyuncs.com/my-namespace |
<your-image-name> |
Nom de l'image | custom-mlserver |
<tag> |
Tag de version de l'image | v1.0 |
Étape 3 : Créer le ServingRuntime
Définissez une ressource ServingRuntime qui pointe vers votre image conteneur et déclare les formats de modèle qu'elle prend en charge.
Remplacez les espaces réservés suivants par des valeurs réelles :
| Espace réservé | Description | Exemple |
|---|---|---|
<custom-runtime-name> |
Un nom unique pour le runtime | my-model-server-0.x |
<model-format-name> |
Le format de modèle pris en charge par ce runtime. ModelMesh fait correspondre les modèles entrants à cette valeur. | my-model |
<your-image> |
L'image conteneur créée à l'étape 2 | registry.cn-hangzhou.aliyuncs.com/my-namespace/custom-mlserver:v1.0 |
Appliquez la ressource :
kubectl apply -f <serving-runtime>.yaml
Une fois la ressource créée, le runtime personnalisé apparaît dans votre déploiement ModelMesh et est prêt à servir les modèles correspondant au format déclaré.
Étape 4 : Déployer un modèle
Créez un InferenceService pour déployer un modèle sur le runtime personnalisé. InferenceService est la ressource principale que KServe et ModelMesh utilisent pour gérer les endpoints de modèle.
Champs clés :
| Champ | Objectif |
|---|---|
modelFormat.name |
Indique à ModelMesh quel runtime utiliser. Doit correspondre à une entrée supportedModelFormats de votre ServingRuntime. |
runtime |
(Facultatif) Sélectionne explicitement un runtime par son nom. Si omis, ModelMesh sélectionne automatiquement en fonction de modelFormat. |
storage.key |
Fait référence à un backend de stockage préconfiguré (par exemple, localMinIO du guide de démarrage rapide ModelMesh Serving). |
storage.path |
Chemin vers l'artefact du modèle dans le backend de stockage. |
Appliquez la ressource :
kubectl apply -f <inference-service>.yaml
Vérifiez que le modèle est prêt :
kubectl get inferenceservice my-model-sample -n modelmesh-serving
Résultat attendu :
NAME URL READY AGE
my-model-sample True 1m
La colonne READY affiche True une fois que ModelMesh a terminé le chargement du modèle dans le runtime personnalisé.
Débogage
Si le runtime personnalisé échoue à charger des modèles ou renvoie des erreurs d'inférence, activez la journalisation de débogage en ajoutant ces variables d'environnement au ServingRuntime :
env:
- name: MLSERVER_DEBUG
value: "true"
- name: MLSERVER_MODEL_PARALLEL_WORKERS
# Set to 0 to disable parallel workers, which simplifies log output.
value: "0"
Consultez les journaux du pod du runtime pour obtenir des messages d'erreur détaillés :
kubectl logs -n modelmesh-serving <pod-name> -c mlserver
Étapes suivantes
Pour en savoir plus sur les runtimes personnalisés de ModelMesh Serving, consultez la documentation en amont.
Explorez les exemples de runtimes personnalisés MLServer pour découvrir d'autres modèles.