Infrastructure de service des modèles

Déployez et configurez les endpoints de modèles pour IBM Bob on-premises lorsque votre environnement ne fournit pas encore de solution de service des modèles.

Avant de connecter IBM Bob à un grand modèle de langage (LLM), vous devez avoir accès à un endpoint de modèle déployé. Bob IDE ne provisionne, n'héberge et ne gère pas l'infrastructure de service des modèles. Si votre organisation fournit déjà des endpoints de modèles via Red Hat OpenShift Container Platform (OCP) AI, des serveurs d'inférence GPU, des services IA cloud ou d'autres plateformes d'inférence, passez directement à Configuration de la passerelle d'inférence de modèles.

Choisissez l'option qui correspond le mieux à votre environnement et à vos exigences opérationnelles.

OptionQuand l'utiliser
OpenShift AI (sur cluster, OCI/ModelCar)Modèles air-gapped ou auto-hébergés ; Red Hat OpenShift AI déjà disponible sur le cluster
Endpoints de modèles cloud publicModèles frontier via AWS Bedrock, Azure OpenAI ou Google Vertex AI
Endpoints de modèles sur infrastructure privéeModèle servi sur des serveurs GPU séparés ou un cluster d'inférence dédié

Déployer des modèles avec OpenShift AI (sur cluster, OCI/ModelCar)

Red Hat OpenShift AI (RHOAI) est la plateforme recommandée pour servir des modèles sur cluster, y compris pour les déploiements air-gapped. L'approche privilégiée pour charger les poids des modèles est le pattern OCI/ModelCar : les fichiers du modèle sont intégrés dans une image OCI sous /models/ et poussés vers un registre privé. Lors du déploiement de l'InferenceService, KServe injecte un init container modelcar-init qui récupère l'image et copie les poids dans un volume partagé à /mnt/models/, à partir duquel le runtime de service (par exemple, vLLM) les charge. L'image du modèle est mise en cache sur le nœud après le premier pull ; les redémarrages ultérieurs sur le même nœud ignorent entièrement le téléchargement.

Prérequis :

  • Opérateur Red Hat OpenShift AI installé sur le cluster
  • KServe activé et configuré
  • Nœuds worker avec GPU activé avec l'opérateur NVIDIA GPU (ou équivalent) configuré
  • CLI oc authentifié auprès du cluster cible avec la permission de créer des ressources dans le namespace cible
  • Un registre de conteneurs privé accessible depuis le cluster, avec les identifiants pour y pousser des images

Configurer Red Hat OpenShift AI

Configurez les ressources DataScienceClusterInitialization et DataScienceCluster comme suit :

  • Désactivez serviceMesh.
  • Activez KServe en définissant managementState: Managed.
  • Configurez KServe pour utiliser le mode RawDeployment.
  • Supprimez tous les composants Red Hat OpenShift AI inutilisés.

Exemple de configuration KServe :

kserve:
  defaultDeploymentMode: RawDeployment
  nim:
    managementState: Managed
  rawDeploymentServiceConfig: Headed
  serving:
    ingressGateway:
      certificate:
        type: OpenshiftDefaultIngress
    managementState: Removed
    name: knative-serving
  managementState: Managed

Activer la prise en charge de ModelCar

La prise en charge de ModelCar est contrôlée par le ConfigMap inferenceservice-config dans le namespace redhat-ods-applications. La clé storageInitializer doit contenir "enableModelcar": true.

Vérifiez la configuration actuelle :

oc get configmap inferenceservice-config \
  -n redhat-ods-applications \
  -o jsonpath='{.data.storageInitializer}'

La sortie doit contenir :

{
  "enableModelcar": true,
  "cpuModelcar": "10m",
  "memoryModelcar": "15Mi"
}

Si enableModelcar est absent ou à false, mettez à jour le ConfigMap :

# Récupérer la valeur actuelle, fusionner l'indicateur et appliquer le patch
CURRENT=$(oc get configmap inferenceservice-config \
  -n redhat-ods-applications \
  -o jsonpath='{.data.storageInitializer}')
PATCHED=$(echo "$CURRENT" | python3 -c "
import json, sys
d = json.load(sys.stdin)
d['enableModelcar'] = True
print(json.dumps(d))
")
oc patch configmap inferenceservice-config \
  -n redhat-ods-applications \
  --type merge \
  -p "{\"data\":{\"storageInitializer\":$(echo $PATCHED | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')}}"

Redémarrez le contrôleur KServe pour appliquer la modification :

oc rollout restart deployment kserve-controller-manager -n redhat-ods-applications
oc rollout status deployment kserve-controller-manager -n redhat-ods-applications

Empaqueter les fichiers du modèle dans une image OCI

Téléchargez les poids du modèle depuis Hugging Face et empaquetez-les dans une image OCI. L'image doit avoir tous les fichiers du modèle sous le répertoire /models. Pour plus d'informations, voir la documentation KServe sur la préparation d'une image OCI avec des données de modèle. Pour les déploiements vLLM, incluez les fragments de modèle safetensors et excluez les anciens fichiers de checkpoint tels que .bin, .pt et original/*.

Exemple de Dockerfile :

FROM busybox:latest

# Poids du modèle -- fragments safetensors et index
COPY <model-name>/model-*.safetensors        /models/
COPY <model-name>/model.safetensors.index.json /models/

# Configuration du modèle
COPY <model-name>/config.json            /models/
COPY <model-name>/generation_config.json /models/

# Tokenizer
COPY <model-name>/tokenizer.json          /models/
COPY <model-name>/tokenizer_config.json   /models/
COPY <model-name>/special_tokens_map.json /models/

Si le modèle inclut un template de chat (par exemple, chat_template.jinja), ajoutez-le. Vous pouvez également copier l'intégralité du répertoire en une seule instruction, ce qui est plus simple mais inclut des fichiers dont vLLM n'a pas besoin :

FROM busybox:latest
COPY <model-name>/ /models/

Pousser l'image vers un registre privé

Poussez l'image OCI vers un registre de conteneurs privé accessible depuis le cluster :

<registry>/<project>/<model-name>:latest

Utilisez l'outil qui correspond à votre environnement (podman push, skopeo copy, un pipeline CI, etc.).

Créer le namespace cible et le secret d'extraction d'image

Créez le namespace du projet et configurez les identifiants pour extraire l'image du modèle.

Créez le namespace :

oc new-project <namespace>

Créez le secret d'extraction du registre :

# Secret d'extraction pour que KServe puisse extraire l'image du modèle de votre registre privé
oc create secret docker-registry model-registry-secret \
  --docker-server=<registry> \
  --docker-username=<username> \
  --docker-password=<password-or-token> \
  -n <namespace>

Créez un compte de service :

# Compte de service utilisé par le prédicteur KServe
oc create sa model-puller-sa -n <namespace>

Associez le secret d'extraction au compte de service :

# Attacher le secret d'extraction -- les deux commandes sont requises :
# oc secrets link couvre l'utilisation générale des secrets ;
# imagePullSecrets est nécessaire par le init container ModelCar de KServe spécifiquement
oc secrets link model-puller-sa model-registry-secret --for=pull -n <namespace>
oc patch serviceaccount model-puller-sa -n <namespace> \
  -p '{"imagePullSecrets": [{"name": "model-registry-secret"}]}'
Remarque :

Les deux commandes sont requises. L'entrée imagePullSecrets est utilisée par le container d'initialisation ModelCar lors de la récupération de l'image du modèle.

Créer un ServingRuntime

Déployez un ServingRuntime basé sur vLLM dans le namespace cible.

apiVersion: serving.kserve.io/v1alpha1
kind: ServingRuntime
metadata:
  name: vllm-runtime
  namespace: <namespace>
spec:
  multiModel: false
  supportedModelFormats:
    - name: pytorch
      autoSelect: true
  containers:
    - name: kserve-container
      image: vllm/vllm-openai:<version>
      ports:
        - containerPort: 3000
          protocol: TCP
      livenessProbe:
        httpGet:
          path: /health
          port: 3000
        periodSeconds: 30
        timeoutSeconds: 5
        failureThreshold: 3
      readinessProbe:
        httpGet:
          path: /health
          port: 3000
        periodSeconds: 10
        timeoutSeconds: 5
        failureThreshold: 3
      startupProbe:
        httpGet:
          path: /health
          port: 3000
        periodSeconds: 10
        timeoutSeconds: 5
        failureThreshold: 60

Appliquez la configuration du runtime :

oc apply -n <namespace> -f serving-runtime-vllm.yaml

Déployer l'InferenceService

Créez un InferenceService qui référence l'image OCI du modèle en utilisant un URI de stockage oci://.

Exigences de configuration clés :

  • Référencer le ServingRuntime créé précédemment.
  • Spécifier l'emplacement de l'image OCI dans storageUri.
  • Configurer les limites de ressources CPU, mémoire et GPU correspondant aux exigences du modèle.
  • Monter la mémoire partagée (/dev/shm) pour vLLM.
  • Configurer les arguments de runtime vLLM et les variables d'environnement.
apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
  name: <model-name>
  annotations:
    serving.kserve.io/autoscalerClass: external
    serving.kserve.io/deploymentMode: RawDeployment
spec:
  predictor:
    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
            - matchExpressions:
                - key: kubernetes.io/arch
                  operator: In
                  values:
                    - amd64
    tolerations:
      - key: nvidia.com/gpu
        operator: Exists
        effect: NoSchedule
    volumes:
      - name: shm
        emptyDir:
          medium: Memory
          sizeLimit: 64Gi
    model:
      modelFormat:
        name: pytorch
      runtime: vllm-runtime
      storageUri: "oci://<registry>/<namespace-or-project>/<model-name>:latest"
      resources:
        requests:
          cpu: "<cpu-request>"          # ex. "8"
        limits:
          cpu: "<cpu-limit>"            # ex. "16"
          memory: <memory-limit>        # ex. 96Gi -- dimensionner selon les besoins VRAM du modèle
          nvidia.com/gpu: "<gpu-count>" # ex. "1"
      volumeMounts:
        - name: shm
          mountPath: /dev/shm
      args:
        - /mnt/models/
        - --served-model-name=<model-name>
        - --port=3000
        - --enable-auto-tool-choice
        - --tool-call-parser=openai
      env:
        - name: HOME
          value: /tmp
        - name: MAX_LOG_LEN
          value: "100"        # tronquer les lignes de log vLLM pour éviter la surcharge des logs
        - name: HF_HUB_CACHE
          value: /tmp
        - name: TRITON_CACHE_DIR
          value: /tmp
        - name: XDG_CACHE_HOME
          value: /tmp
        - name: HF_HOME
          value: /tmp/hf_home
        - name: NUM_GPUS
          value: "<gpu-count>" # doit correspondre à la limite nvidia.com/gpu ci-dessus
        - name: CUDA_VISIBLE_DEVICES
          value: "<gpu-indices>" # ex. "0" pour un seul GPU ; "0,1" pour deux
        - name: VLLM_WORKER_MULTIPROC_METHOD
          value: spawn
        - name: LOGNAME
          value: vllm
        - name: USER
          value: vllm

Appliquez le manifeste InferenceService :

oc apply -n <namespace> -f isvc-<model-name>.yaml

Vérifier le déploiement

Surveillez l'état du déploiement, le démarrage du pod et les logs du runtime :

# Suivre l'InferenceService jusqu'à l'état Ready
oc get inferenceservice <model-name> -n <namespace> -w

# Suivre le démarrage du pod prédicteur
oc get pods -n <namespace> -w

# Suivre les logs du prédicteur (le chargement du modèle peut prendre plusieurs minutes une fois Running)
oc logs -f deployment/<model-name>-predictor -n <namespace>

Lorsque l'InferenceService signale READY: True, validez l'endpoint.

Vérifiez l'enregistrement du modèle et envoyez une requête d'inférence de test :

POD=$(oc get pods -n <namespace> \
  -l app=isvc.<model-name>-predictor \
  -o jsonpath='{.items[0].metadata.name}')

oc exec -n <namespace> "$POD" -c kserve-container -- \
  curl -fsS http://127.0.0.1:3000/v1/models

oc exec -n <namespace> "$POD" -c kserve-container -- \
  curl -fsS http://127.0.0.1:3000/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "<model-name>",
    "messages": [{"role": "user", "content": "Hello"}],
    "max_tokens": 50
  }'

Résolution des problèmes

ProblèmeCause possibleRésolution
ErrImagePullIdentifiants de registre manquants ou invalidesVérifiez que model-registry-secret existe, possède des identifiants valides et est lié à model-puller-sa en utilisant à la fois oc secrets link et le patch imagePullSecrets.
ImagePullBackOffSecret d'extraction d'image non configuré pour ModelCarAssurez-vous que le compte de service inclut l'entrée imagePullSecrets. Voir la commande oc patch serviceaccount à l'étape 3.
Le prédicteur reste dans Init:0/1Téléchargement de l'image du modèle en coursVérifiez les événements oc describe pod pour la progression Pulling/Pulled ; le temps d'extraction augmente avec la taille de l'image et la bande passante du registre.
Le prédicteur reste indéfiniment dans Init:0/1Fichiers du modèle introuvablesVérifiez que les fichiers du modèle sont stockés sous /models dans l'image OCI.
Engine core initialization failedDélai d'expiration de la compilation CUDA initialeLe premier démarrage peut prendre plus de temps pendant la génération des caches. Redémarrez et réessayez.
Échec du chargement du modèleFormat de fichier de modèle non pris en chargeUtilisez les fichiers safetensors de Hugging Face et excluez les anciens checkpoints.
Erreurs d'auto-test FIPS OpenSSLL'image du conteneur n'est pas compatible FIPSUtilisez une image vLLM compatible FIPS.
OutOfMemory / OOMKilledMémoire GPU insuffisanteAugmentez les ressources GPU, réduisez la longueur du contexte ou utilisez un modèle quantifié.
L'InferenceService reste en PendingRessources du cluster indisponiblesVérifiez la disponibilité des GPU et libérez des ressources des charges de travail inutilisées.

Ressources supplémentaires

Utiliser des endpoints de modèles cloud public

Utilisez cette option lorsque les modèles sont hébergés par un fournisseur cloud, tel qu'IBM watsonx, AWS Bedrock, Azure OpenAI ou Google Vertex AI.

Prérequis :

  • Connectivité HTTPS sortante (port 443) du cluster Red Hat OpenShift Container Platform (OCP) vers l'endpoint du service cloud.
  • Clés API valides, identifiants IAM ou identifiants d'authentification équivalents.

Avant de commencer :

Assurez-vous que :

  • Le déploiement du modèle est provisionné et actif.
  • Les identifiants d'authentification sont générés et stockés de manière sécurisée.
  • Les exigences de mise en réseau ou d'accès spécifiques au fournisseur sont satisfaites.

Une fois l'endpoint disponible, passez à Configuration de la passerelle d'inférence de modèles.

Utiliser des endpoints de modèles sur infrastructure privée

Utilisez cette option lorsque les modèles sont hébergés sur une infrastructure gérée par le client en dehors du cluster IBM Bob, telle que :

  • Des serveurs GPU dédiés
  • Des clusters OpenShift séparés
  • Des serveurs d'inférence bare-metal
  • Des plateformes IA d'entreprise

Prérequis :

  • L'endpoint du modèle expose une API compatible OpenAI.
  • La connectivité HTTPS existe entre le cluster IBM Bob et l'endpoint.
  • Les identifiants d'authentification sont disponibles en tant que secrets Kubernetes.

Avant de commencer :

Validez les points suivants :

  • La connectivité réseau du cluster vers l'endpoint.
  • La configuration TLS ou TLS mutuel, si requis.
  • Les politiques réseau et les pare-feux autorisent l'accès.
  • L'authentification de l'endpoint fonctionne correctement.

Une fois la connectivité et l'authentification vérifiées, passez à Configuration de la passerelle d'inférence de modèles.

Comment trouvez-vous ce sujet ?