Tous les produits
Search
Centre de documentation

Alibaba Cloud Service Mesh:Deploy a large language model as an inference service

Dernière mise à jour :Aug 11, 2026

Un grand modèle de langage (LLM) est un modèle neuronal doté de centaines de millions de paramètres, tels que GPT-3, GPT-4, PaLM et PaLM 2. En déployant un LLM sur Service Mesh (ASM) via ModelMesh, vous pouvez exposer des fonctionnalités de traitement du langage naturel (NLP) — classification de texte, analyse des sentiments, traduction automatique — sous forme d'endpoints API. Cette approche « LLM-as-a-service » vous permet d'éviter des coûts d'infrastructure élevés, de réagir rapidement aux évolutions du marché et de mettre à l'échelle vos services à la demande pour gérer les pics de trafic, tout en exécutant le modèle dans le cloud et en améliorant l'efficacité opérationnelle.

Cette rubrique détaille trois étapes : créer un runtime de service de modèle personnalisé, déployer le modèle en tant que service d'inférence et envoyer des requêtes d'inférence via la passerelle d'entrée ASM.

Fonctionnement

Ce déploiement utilise ModelMesh au sein d'ASM pour servir un LLM Hugging Face avec un ajustement fin économe en paramètres (PEFT) par prompt tuning. Le schéma suivant illustre l'articulation des composants :

+---------------------------------------------------------+
|                   ASM ingress gateway                   |
|                    (port 8008, HTTP)                    |
+----------------------------+----------------------------+
                             |
                             v
+---------------------------------------------------------+
|                       ModelMesh                         |
|            (model routing and orchestration)            |
+---------------------------------------------------------+
|  ServingRuntime             InferenceService            |
|  +------------------+      +-----------------------+   |
|  | peft-model-server |<-----| peft-demo             |   |
|  | (MLServer-based)  |      | (model endpoint)      |   |
|  +------------------+      +-----------------------+   |
|         |                                               |
|         v                                               |
|  +------------------+      +-----------------------+   |
|  | MLServer          |      | Hugging Face model    |   |
|  | (gRPC :8001,      |      | + PEFT config         |   |
|  |  HTTP :8002)      |      | (bloomz-560m)         |   |
|  +------------------+      +-----------------------+   |
+---------------------------------------------------------+
  • ServingRuntime : définit l'image de conteneur et la configuration MLServer pour le service du modèle.

  • InferenceService : spécifie le modèle à charger et le ServingRuntime à utiliser. Il sert d'endpoint logique pour les requêtes d'inférence.

  • ModelMesh : achemine les requêtes entrantes depuis la passerelle d'entrée ASM vers le bon InferenceService. Il gère le chargement et la mise à l'échelle des modèles.

Prérequis

Avant de commencer, assurez-vous d'avoir :

Étape 1 : Créer un runtime personnalisé

Créez un ServingRuntime personnalisé pour servir un LLM Hugging Face avec un ajustement fin PEFT par prompt tuning. Cela implique trois parties : implémenter la classe du serveur de modèle, l'empaqueter dans une image Docker et créer la ressource Kubernetes.

Implémenter la classe du serveur de modèle

Le serveur de modèle hérite de la classe de base MLServer MLModel et implémente deux gestionnaires :

  • **load** : charge le LLM préentraîné, applique la configuration de prompt tuning PEFT et initialise un tokenizer. Le tokenizer permet au serveur d'accepter des entrées textuelles brutes plutôt que des tenseurs prétraités.

  • **predict** : tokenize le texte d'entrée, exécute l'inférence et décode la sortie pour obtenir un texte lisible.

L'implémentation complète se trouve dans le fichier peft_model_server.py :

peft_model_server.py

from typing import List

from mlserver import MLModel, types
from mlserver.codecs import decode_args

from peft import PeftModel, PeftConfig
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
import os

class PeftModelServer(MLModel):
    async def load(self) -> bool:
        self._load_model()
        self.ready = True
        return self.ready

    @decode_args
    async def predict(self, content: List[str]) -> List[str]:
        return self._predict_outputs(content)

    def _load_model(self):
        model_name_or_path = os.environ.get("PRETRAINED_MODEL_PATH", "bigscience/bloomz-560m")
        peft_model_id = os.environ.get("PEFT_MODEL_ID", "aipipeline/bloomz-560m_PROMPT_TUNING_CAUSAL_LM")
        self.tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, local_files_only=True)
        config = PeftConfig.from_pretrained(peft_model_id)
        self.model = AutoModelForCausalLM.from_pretrained(config.base_model_name_or_path)
        self.model = PeftModel.from_pretrained(self.model, peft_model_id)
        self.text_column = os.environ.get("DATASET_TEXT_COLUMN_NAME", "Tweet text")
        return

    def _predict_outputs(self, content: List[str]) -> List[str]:
        output_list = []
        for input in content:
            inputs = self.tokenizer(
                f'{self.text_column} : {input} Label : ',
                return_tensors="pt",
            )
            with torch.no_grad():
                inputs = {k: v for k, v in inputs.items()}
                outputs = self.model.generate(
                    input_ids=inputs["input_ids"], attention_mask=inputs["attention_mask"], max_new_tokens=10, eos_token_id=3
                )
                outputs = self.tokenizer.batch_decode(outputs.detach().cpu().numpy(), skip_special_tokens=True)
            output_list.append(outputs[0])
        return output_list

Le serveur de modèle lit la configuration à partir de variables d'environnement :

Variable d'environnement Valeur par défaut Description
PRETRAINED_MODEL_PATH bigscience/bloomz-560m Chemin ou ID du modèle Hugging Face pour le LLM de base
PEFT_MODEL_ID aipipeline/bloomz-560m_PROMPT_TUNING_CAUSAL_LM ID de configuration de prompt tuning PEFT
DATASET_TEXT_COLUMN_NAME Tweet text Nom de la colonne utilisé pour le champ de texte d'entrée

Construire l'image Docker

Empaquetez le serveur de modèle et ses dépendances dans une image Docker compatible avec ModelMesh.

Dockerfile

# TODO: choose appropriate base image, install Python, MLServer, and
# dependencies of your MLModel implementation
FROM python:3.8-slim-buster
RUN pip install mlserver peft transformers datasets
# ...

# The custom MLModel implementation should be on the Python search path
# instead of relying on the working directory of the image. If using a
# single-file module, this can be accomplished with:
COPY --chown=${USER} ./peft_model_server.py /opt/peft_model_server.py
ENV PYTHONPATH=/opt/

# environment variables to be compatible with ModelMesh Serving
# these can also be set in the ServingRuntime, but this is recommended for
# consistency when building and 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=peft-model

# With this setting, the implementation field is not required in the model
# settings which eases integration by allowing the built-in adapter to generate
# a basic model settings file
ENV MLSERVER_MODEL_IMPLEMENTATION=peft_model_server.PeftModelServer

CMD mlserver start ${MLSERVER_MODELS_DIR}

L'image expose deux ports : gRPC sur 8001 et HTTP sur 8002. La définition de MLSERVER_MODEL_IMPLEMENTATION indique à MLServer quelle classe charger, ce qui rend inutile un fichier de paramètres de modèle séparé.

Créer la ressource ServingRuntime

Définissez un ServingRuntime qui pointe vers votre image Docker et configure l'environnement MLServer.

sample-runtime.yaml

apiVersion: serving.kserve.io/v1alpha1
kind: ServingRuntime
metadata:
  name: peft-model-server
  namespace: modelmesh-serving
spec:
  supportedModelFormats:
    - name: peft-model
      version: "1"
      autoSelect: true
  multiModel: true
  grpcDataEndpoint: port:8001
  grpcEndpoint: port:8085
  containers:
    - name: mlserver
      image:  registry.cn-beijing.aliyuncs.com/test/peft-model-server:latest
      env:
        - name: MLSERVER_MODELS_DIR
          value: "/models/_mlserver_models/"
        - name: MLSERVER_GRPC_PORT
          value: "8001"
        - name: MLSERVER_HTTP_PORT
          value: "8002"
        - name: MLSERVER_LOAD_MODELS_AT_STARTUP
          value: "true"
        - name: MLSERVER_MODEL_NAME
          value: peft-model
        - name: MLSERVER_HOST
          value: "127.0.0.1"
        - name: MLSERVER_GRPC_MAX_MESSAGE_LENGTH
          value: "-1"
        - name: PRETRAINED_MODEL_PATH
          value: "bigscience/bloomz-560m"
        - name: PEFT_MODEL_ID
          value: "aipipeline/bloomz-560m_PROMPT_TUNING_CAUSAL_LM"
        # - name: "TRANSFORMERS_OFFLINE"
        #   value: "1"
        # - name: "HF_DATASETS_OFFLINE"
        #   value: "1"
      resources:
        requests:
          cpu: 500m
          memory: 4Gi
        limits:
          cpu: "5"
          memory: 5Gi
  builtInAdapter:
    serverType: mlserver
    runtimeManagementPort: 8001
    memBufferBytes: 134217728
    modelLoadingTimeoutMillis: 90000

Déployez le ServingRuntime :

kubectl apply -f sample-runtime.yaml

Vérifiez que le runtime est disponible :

kubectl get servingruntimes -n modelmesh-serving

Résultat attendu :

NAME                AGE
peft-model-server   10s

Le runtime peft-model-server doit apparaître dans la sortie.

Étape 2 : Déployer le service d'inférence

Créez une ressource InferenceService pour lier votre modèle au ServingRuntime défini à l'étape 1. L'InferenceService constitue l'endpoint logique que ModelMesh utilise pour acheminer les requêtes d'inférence vers le modèle.

peft-demo-isvc.yaml

apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
  name: peft-demo
  namespace: modelmesh-serving
  annotations:
    serving.kserve.io/deploymentMode: ModelMesh
spec:
  predictor:
    model:
      modelFormat:
        name: peft-model
      runtime: peft-model-server
      storage:
        key: localMinIO
        path: sklearn/mnist-svm.joblib

Champs de configuration :

Champ Valeur Description
modelFormat.name peft-model Doit correspondre au format déclaré dans le ServingRuntime
runtime peft-model-server Indique à ModelMesh quel runtime sert ce modèle
serving.kserve.io/deploymentMode ModelMesh Annotation requise qui instruit KServe de déployer via ModelMesh plutôt que via des pods autonomes

Déployez l'InferenceService :

kubectl apply -f peft-demo-isvc.yaml

Vérifiez que l'InferenceService est prêt :

kubectl get inferenceservices -n modelmesh-serving

Résultat attendu :

NAME        URL    READY   AGE
peft-demo          True    30s

Attendez que la colonne READY affiche True avant de poursuivre. Si le statut reste False, consultez la section Dépannage.

Étape 3 : Envoyer une requête d'inférence

Envoyez une requête POST au modèle déployé via la passerelle d'entrée ASM. La requête utilise le protocole d'inférence KServe v2.

MODEL_NAME="peft-demo"
ASM_GW_IP="<IP-address-of-the-ingress-gateway>"
curl -X POST -k http://${ASM_GW_IP}:8008/v2/models/${MODEL_NAME}/infer -d @./input.json

Remplacez l'espace réservé suivant par votre valeur réelle :

Espace réservé Description Exemple
<IP-address-of-the-ingress-gateway> IP externe de votre passerelle d'entrée ASM 192.168.1.100

Le corps de la requête (input.json) suit le format du protocole d'inférence v2. Encodez le texte d'entrée en Base64 dans le champ bytes_contents :

{
    "inputs": [
        {
          "name": "content",
          "shape": [1],
          "datatype": "BYTES",
          "contents": {"bytes_contents": ["RXZlcnkgZGF5IGlzIGEgbmV3IGJpbm5pbmcsIGZpbGxlZCB3aXRoIG9wdGlvbnBpZW5pbmcgYW5kIGhvcGU="]}
        }
    ]
}

Dans cet exemple, bytes_contents est la forme encodée en Base64 de "Every day is a new beginning, filled with opportunities and hope".

Réponse attendue

Une inférence réussie renvoie une réponse JSON contenant la sortie du modèle dans bytesContents (également encodée en Base64) :

{
 "modelName": "peft-demo__isvc-5c5315c302",
 "outputs": [
  {
   "name": "output-0",
   "datatype": "BYTES",
   "shape": [
    "1",
    "1"
   ],
   "parameters": {
    "content_type": {
     "stringParam": "str"
    }
   },
   "contents": {
    "bytesContents": [
     "VHdlZXQgdGV4dCA6IEV2ZXJ5IGRheSBpcyBhIG5ldyBiaW5uaW5nLCBmaWxsZWQgd2l0aCBvcHRpb25waWVuaW5nIGFuZCBob3BlIExhYmVsIDogbm8gY29tcGxhaW50"
    ]
   }
  }
 ]
}

Décodez la valeur bytesContents depuis le Base64 pour vérifier le résultat :

Tweet text : Every day is a new binning, filled with optionpiening and hope Label : no complaint

Le modèle a classifié le texte d'entrée avec l'étiquette no complaint, ce qui confirme le bon fonctionnement du service d'inférence.

Dépannage

Problème Cause Solution
Le pod ServingRuntime reste en état Pending CPU ou mémoire insuffisants dans le cluster Ajoutez des nœuds ou réduisez les requests de ressources dans la spécification du ServingRuntime
L'InferenceService n'atteint jamais l'état Ready: True Délai dépassé lors du chargement du modèle ou échec du téléchargement Vérifiez les journaux du pod avec kubectl logs -n modelmesh-serving <pod-name>. Augmentez modelLoadingTimeoutMillis pour les téléchargements lents. Pour les clusters isolés, définissez TRANSFORMERS_OFFLINE et HF_DATASETS_OFFLINE sur "1" et préchargez les modèles dans le stockage local
curl renvoie une erreur de connexion refusée Passerelle d'entrée mal configurée ou mauvaise IP/port Vérifiez l'IP de la passerelle d'entrée ASM et confirmez que le port 8008 est exposé
Sortie du modèle inattendue Incompatibilité entre le modèle et la configuration PEFT Confirmez que PRETRAINED_MODEL_PATH et PEFT_MODEL_ID pointent vers des configurations de modèle et d'ajustement compatibles

Étapes suivantes