Ce tutoriel explique comment diffuser un grand modèle de langage (LLM) avec des GPU en mode Google Kubernetes Engine (GKE). Ce tutoriel crée un cluster GKE qui utilise plusieurs GPU L4 et prépare l'infrastructure GKE pour diffuser l'un des modèles suivants :
Selon le format de données du modèle, le nombre de GPU varie. Dans ce tutoriel, chaque modèle utilise deux GPU L4. Pour en savoir plus, consultez la page Calculer la quantité de GPU.
Avant de suivre ce tutoriel sur GKE, nous vous recommandons de vous familiariser avec la Présentation des GPU dans GKE.
Objectifs
Ce tutoriel est destiné aux ingénieurs MLOps ou DevOps ou aux administrateurs de plate-forme qui souhaitent utiliser les fonctionnalités d'orchestration GKE pour obtenir des inférences à partir d'un LLM.
Ce tutoriel couvre les étapes suivantes :
- Créer un cluster et des pools de nœuds
- Préparer votre charge de travail.
- Déployer votre charge de travail.
- Interagir avec l'interface du LLM.
Avant de commencer
Avant de commencer, effectuez les tâches suivantes :
- Activez l'API Google Kubernetes Engine. Activer l'API Google Kubernetes Engine
- Si vous souhaitez utiliser Google Cloud CLI pour cette tâche, installez puis initialisez gcloud CLI. Si vous avez déjà installé gcloud CLI, assurez-vous de disposer de la dernière version en exécutant la commande
gcloud components update
.
Certains modèles ont des exigences supplémentaires. Assurez-vous de remplir les conditions suivantes:
- Pour accéder aux modèles depuis Hugging Face, utilisez un jeton HuggingFace.
- Pour le modèle Mixtral 8x7b, acceptez les conditions du modèle Mixtral Mistral.
- Pour le modèle Llama 2 70b, assurez-vous de disposer d'une licence active pour les modèles Meta Llama.
Préparer votre environnement
Dans la console Google Cloud, démarrez une instance Cloud Shell :
Ouvrir Cloud ShellDéfinissez les variables d'environnement par défaut :
gcloud config set project PROJECT_ID export PROJECT_ID=$(gcloud config get project) export REGION=us-central1
Remplacez PROJECT_ID par l'ID du projet Google Cloud.
Créer un cluster GKE et un pool de nœuds
Vous pouvez diffuser les LLM sur des GPU dans un cluster GKE Autopilot ou GKE Standard. Nous vous recommandons d'utiliser un cluster GKE Autopilot pour une expérience Kubernetes entièrement gérée. Pour choisir le mode de fonctionnement GKE le mieux adapté à vos charges de travail, consultez la section Choisir un mode de fonctionnement GKE.
Autopilot
Dans Cloud Shell, exécutez la commande suivante :
gcloud container clusters create-auto l4-demo \ --project=${PROJECT_ID} \ --region=${REGION} \ --release-channel=rapid
GKE crée un cluster Autopilot avec des nœuds de processeur et de GPU, à la demande des charges de travail déployées.
Configurez
kubectl
de manière à communiquer avec votre cluster :gcloud container clusters get-credentials l4-demo --region=${REGION}
Standard
Dans Cloud Shell, exécutez la commande suivante pour créer un cluster standard qui utilise la fédération d'identité de charge de travail pour GKE :
gcloud container clusters create l4-demo --location ${REGION} \ --workload-pool ${PROJECT_ID}.svc.id.goog \ --enable-image-streaming \ --node-locations=$REGION-a \ --workload-pool=${PROJECT_ID}.svc.id.goog \ --machine-type n2d-standard-4 \ --num-nodes 1 --min-nodes 1 --max-nodes 5 \ --release-channel=rapid
La création du cluster peut prendre plusieurs minutes.
Exécutez la commande suivante pour créer un pool de nœuds pour votre cluster :
gcloud container node-pools create g2-standard-24 --cluster l4-demo \ --accelerator type=nvidia-l4,count=2,gpu-driver-version=latest \ --machine-type g2-standard-24 \ --enable-autoscaling --enable-image-streaming \ --num-nodes=0 --min-nodes=0 --max-nodes=3 \ --node-locations $REGION-a,$REGION-c --region $REGION --spot
GKE crée les ressources suivantes pour le LLM :
- Un cluster Google Kubernetes Engine (GKE) standard public.
- Un pool de nœuds avec le type de machine
g2-standard-24
réduit à 0 nœud. Vous n'êtes facturé pour aucun GPU tant que vous n'avez pas lancé de pods qui demandent des GPU. Ce pool de nœuds provisionne des VM Spot, dont la tarification est inférieure à celle des VM Compute Engine standard par défaut mais qui n'offrent aucune garantie de disponibilité. Vous pouvez supprimer l'option--spot
de cette commande et le sélecteur de nœudcloud.google.com/gke-spot
dans la configurationtext-generation-inference.yaml
pour utiliser des VM à la demande.
Configurez
kubectl
de manière à communiquer avec votre cluster :gcloud container clusters get-credentials l4-demo --region=${REGION}
Préparer votre charge de travail
La section suivante montre comment configurer votre charge de travail en fonction du modèle que vous souhaitez utiliser :
Llama 2 70b
Définissez les variables d'environnement par défaut :
export HF_TOKEN=HUGGING_FACE_TOKEN
Remplacez
HUGGING_FACE_TOKEN
par votre jeton HuggingFace.Créez un secret Kubernetes pour le jeton HuggingFace :
kubectl create secret generic l4-demo \ --from-literal=HUGGING_FACE_TOKEN=${HF_TOKEN} \ --dry-run=client -o yaml | kubectl apply -f -
Créez le fichier manifeste
text-generation-inference.yaml
suivant :Dans le fichier manifeste :
NUM_SHARD
doit être défini sur2
, car le modèle nécessite deux GPU NVIDIA L4.QUANTIZE
est défini surbitsandbytes-nf4
, ce qui signifie que le modèle est chargé en 4 bits au lieu de 32 bits. Cela permet à GKE de réduire la quantité de mémoire GPU nécessaire et d'améliorer la vitesse d'inférence. Cependant, la justesse du modèle peut diminuer. Pour savoir comment calculer le nombre de GPU à demander, consultez la section Calculer le nombre de GPU.
Appliquez le fichier manifeste :
kubectl apply -f text-generation-inference.yaml
Le résultat ressemble à ce qui suit :
deployment.apps/llm created
Vérifiez l'état du modèle :
kubectl get deploy
Le résultat ressemble à ce qui suit :
NAME READY UP-TO-DATE AVAILABLE AGE llm 1/1 1 1 20m
Affichez les journaux du déploiement en cours d'exécution :
kubectl logs -l app=llm
Le résultat ressemble à ce qui suit :
{"timestamp":"2024-03-09T05:08:14.751646Z","level":"INFO","message":"Warming up model","target":"text_generation_router","filename":"router/src/main.rs","line_number":291} {"timestamp":"2024-03-09T05:08:19.961136Z","level":"INFO","message":"Setting max batch total tokens to 133696","target":"text_generation_router","filename":"router/src/main.rs","line_number":328} {"timestamp":"2024-03-09T05:08:19.961164Z","level":"INFO","message":"Connected","target":"text_generation_router","filename":"router/src/main.rs","line_number":329} {"timestamp":"2024-03-09T05:08:19.961171Z","level":"WARN","message":"Invalid hostname, defaulting to 0.0.0.0","target":"text_generation_router","filename":"router/src/main.rs","line_number":343}
Mixtral 8x7b
Définissez les variables d'environnement par défaut :
export HF_TOKEN=HUGGING_FACE_TOKEN
Remplacez
HUGGING_FACE_TOKEN
par votre jeton HuggingFace.Créez un secret Kubernetes pour le jeton HuggingFace :
kubectl create secret generic l4-demo \ --from-literal=HUGGING_FACE_TOKEN=${HF_TOKEN} \ --dry-run=client -o yaml | kubectl apply -f -
Créez le fichier manifeste
text-generation-inference.yaml
suivant :Dans le fichier manifeste :
NUM_SHARD
doit être défini sur2
, car le modèle nécessite deux GPU NVIDIA L4.QUANTIZE
est défini surbitsandbytes-nf4
, ce qui signifie que le modèle est chargé en 4 bits au lieu de 32 bits. Cela permet à GKE de réduire la quantité de mémoire GPU nécessaire et d'améliorer la vitesse d'inférence. Toutefois, cela peut réduire la précision du modèle. Pour savoir comment calculer le nombre de GPU à demander, consultez la section Calculer la quantité de GPU.
Appliquez le fichier manifeste :
kubectl apply -f text-generation-inference.yaml
Le résultat ressemble à ce qui suit :
deployment.apps/llm created
Vérifiez l'état du modèle :
watch kubectl get deploy
Une fois le déploiement prêt, le résultat ressemble à ce qui suit. Pour quitter la lecture, appuyez sur
CTRL + C
:NAME READY UP-TO-DATE AVAILABLE AGE llm 1/1 1 1 10m
Affichez les journaux du déploiement en cours d'exécution :
kubectl logs -l app=llm
Le résultat ressemble à ce qui suit :
{"timestamp":"2024-03-09T05:08:14.751646Z","level":"INFO","message":"Warming up model","target":"text_generation_router","filename":"router/src/main.rs","line_number":291} {"timestamp":"2024-03-09T05:08:19.961136Z","level":"INFO","message":"Setting max batch total tokens to 133696","target":"text_generation_router","filename":"router/src/main.rs","line_number":328} {"timestamp":"2024-03-09T05:08:19.961164Z","level":"INFO","message":"Connected","target":"text_generation_router","filename":"router/src/main.rs","line_number":329} {"timestamp":"2024-03-09T05:08:19.961171Z","level":"WARN","message":"Invalid hostname, defaulting to 0.0.0.0","target":"text_generation_router","filename":"router/src/main.rs","line_number":343}
Falcon 40b
Créez le fichier manifeste
text-generation-inference.yaml
suivant :Dans le fichier manifeste :
NUM_SHARD
doit être défini sur2
, car le modèle nécessite deux GPU NVIDIA L4.QUANTIZE
est défini surbitsandbytes-nf4
, ce qui signifie que le modèle est chargé en 4 bits au lieu de 32 bits. Cela permet à GKE de réduire la quantité de mémoire GPU nécessaire et d'améliorer la vitesse d'inférence. Cependant, la justesse du modèle peut diminuer. Pour savoir comment calculer le nombre de GPU à demander, consultez la section Calculer la quantité de GPU.
Appliquez le fichier manifeste :
kubectl apply -f text-generation-inference.yaml
Le résultat ressemble à ce qui suit :
deployment.apps/llm created
Vérifiez l'état du modèle :
watch kubectl get deploy
Une fois le déploiement prêt, le résultat ressemble à ce qui suit. Pour quitter la lecture, appuyez sur
CTRL + C
:NAME READY UP-TO-DATE AVAILABLE AGE llm 1/1 1 1 10m
Affichez les journaux du déploiement en cours d'exécution :
kubectl logs -l app=llm
Le résultat ressemble à ce qui suit :
{"timestamp":"2024-03-09T05:08:14.751646Z","level":"INFO","message":"Warming up model","target":"text_generation_router","filename":"router/src/main.rs","line_number":291} {"timestamp":"2024-03-09T05:08:19.961136Z","level":"INFO","message":"Setting max batch total tokens to 133696","target":"text_generation_router","filename":"router/src/main.rs","line_number":328} {"timestamp":"2024-03-09T05:08:19.961164Z","level":"INFO","message":"Connected","target":"text_generation_router","filename":"router/src/main.rs","line_number":329} {"timestamp":"2024-03-09T05:08:19.961171Z","level":"WARN","message":"Invalid hostname, defaulting to 0.0.0.0","target":"text_generation_router","filename":"router/src/main.rs","line_number":343}
Créer un service de type ClusterIP
Créez le fichier manifeste
llm-service.yaml
suivant :apiVersion: v1 kind: Service metadata: name: llm-service spec: selector: app: llm type: ClusterIP ports: - protocol: TCP port: 80 targetPort: 8080
Appliquez le fichier manifeste :
kubectl apply -f llm-service.yaml
Déployer une interface de chat
Utilisez Gradio pour créer une application Web qui vous permet d'interagir avec votre modèle. Gradio est une bibliothèque Python dotée d'un wrapper ChatInterface qui crée des interfaces utilisateur pour les chatbots.
Llama 2 70b
Créez un fichier nommé
gradio.yaml
:Appliquez le fichier manifeste :
kubectl apply -f gradio.yaml
Recherchez l'adresse IP externe du service :
kubectl get svc
Le résultat ressemble à ce qui suit :
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gradio-service LoadBalancer 10.24.29.197 34.172.115.35 80:30952/TCP 125m
Copiez l'adresse IP externe présente dans la colonne
EXTERNAL-IP
.Consultez l'interface du modèle depuis votre navigateur Web en utilisant l'adresse IP externe avec le port exposé :
http://EXTERNAL_IP
Mixtral 8x7b
Créez un fichier nommé
gradio.yaml
:Appliquez le fichier manifeste :
kubectl apply -f gradio.yaml
Recherchez l'adresse IP externe du service :
kubectl get svc
Le résultat ressemble à ce qui suit :
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gradio-service LoadBalancer 10.24.29.197 34.172.115.35 80:30952/TCP 125m
Copiez l'adresse IP externe présente dans la colonne
EXTERNAL-IP
.Consultez l'interface du modèle depuis votre navigateur Web en utilisant l'adresse IP externe avec le port exposé :
http://EXTERNAL_IP
Falcon 40b
Créez un fichier nommé
gradio.yaml
:Appliquez le fichier manifeste :
kubectl apply -f gradio.yaml
Recherchez l'adresse IP externe du service :
kubectl get svc
Le résultat ressemble à ce qui suit :
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gradio-service LoadBalancer 10.24.29.197 34.172.115.35 80:30952/TCP 125m
Copiez l'adresse IP externe présente dans la colonne
EXTERNAL-IP
.Consultez l'interface du modèle depuis votre navigateur Web en utilisant l'adresse IP externe avec le port exposé :
http://EXTERNAL_IP
Calculer le nombre de GPU
Le nombre de GPU dépend de la valeur de l'option QUANTIZE
. Dans ce tutoriel, QUANTIZE
est défini sur bitsandbytes-nf4
, ce qui signifie que le modèle est chargé en 4 bits.
Un modèle avec 70 milliards de paramètres nécessiterait au moins 40 Go de mémoire GPU, à raison de 70 milliards fois 4 bits (70 milliards x 4 bits= 35 Go) en prenant en compte une surcharge de 5 Go. Dans ce cas, un GPU L4 ne disposerait pas de suffisamment de mémoire. Par conséquent, les exemples de ce tutoriel utilisent la mémoire de deux GPU L4 de mémoire (2 x 24 = 48 Go). Cette configuration est suffisante pour exécuter Falcon 40b ou Llama 2 70b sur les GPU L4.
Effectuer un nettoyage
Pour éviter que les ressources utilisées lors de ce tutoriel soient facturées sur votre compte Google Cloud, supprimez le projet contenant les ressources, ou conservez le projet et supprimez les ressources individuelles.
Supprimer le cluster
Pour éviter que les ressources que vous avez créées dans ce guide ne soient facturées sur votre compte Google Cloud, supprimez le cluster GKE :
gcloud container clusters delete l4-demo --region ${REGION}