En este instructivo, se muestra cómo implementar y entregar un modelo de lenguaje grande (LLM) con varias GPUs en GKE para una inferencia eficiente y escalable. Creas un clúster de GKE que usa varias GPU L4 y preparas la infraestructura para entregar cualquiera de los siguientes modelos:
Según el formato de datos del modelo, la cantidad de GPUs requeridas varía. En este instructivo, cada modelo usa dos GPUs L4. Para obtener más información, consulta Calcula la cantidad de GPU.
Este instructivo está dirigido a ingenieros de aprendizaje automático (AA), administradores y operadores de plataformas, y especialistas en datos y en IA que estén interesados en usar las capacidades de organización de contenedores de Kubernetes para entregar LLM. Para obtener más información sobre los roles comunes y las tareas de ejemplo a los que se hace referencia en el contenido de Google Cloud, consulta Roles y tareas comunes de los usuarios de GKE.
Antes de leer esta página, asegúrate de estar familiarizado con lo siguiente:
Prepara el entorno
En la Google Cloud consola, inicia una instancia de Cloud Shell:
Abrir Cloud ShellConfigura las variables de entorno predeterminadas:
gcloud config set project PROJECT_ID gcloud config set billing/quota_project PROJECT_ID export PROJECT_ID=$(gcloud config get project) export CONTROL_PLANE_LOCATION=us-central1
Reemplaza PROJECT_ID por tu Google Cloud ID del proyecto.
Crea un clúster de GKE y un grupo de nodos
Puedes entregar LLM en GPU en un clúster de GKE Autopilot o Standard. Te recomendamos que uses un clúster de Autopilot para una experiencia de Kubernetes completamente administrada. Para elegir el modo de operación de GKE que se adapte mejor a tus cargas de trabajo, consulta Elige un modo de operación de GKE.
Autopilot
En Cloud Shell, ejecuta el siguiente comando:
gcloud container clusters create-auto l4-demo \ --project=${PROJECT_ID} \ --location=${CONTROL_PLANE_LOCATION} \ --release-channel=rapid
GKE crea un clúster de Autopilot con nodos de CPU y GPU según lo solicitan las cargas de trabajo implementadas.
Configura
kubectl
para comunicarse con tu clúster:gcloud container clusters get-credentials l4-demo --location=${CONTROL_PLANE_LOCATION}
Estándar
En Cloud Shell, ejecuta el siguiente comando para crear un clúster estándar que use la federación de identidades para cargas de trabajo para GKE:
gcloud container clusters create l4-demo \ --location ${CONTROL_PLANE_LOCATION} \ --workload-pool ${PROJECT_ID}.svc.id.goog \ --enable-image-streaming \ --node-locations=${CONTROL_PLANE_LOCATION}-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 creación del clúster puede tomar varios minutos.
Ejecuta el siguiente comando para crear un grupo de nodos para el clúster:
gcloud container node-pools create g2-standard-24 --cluster l4-demo \ --location ${CONTROL_PLANE_LOCATION} \ --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 ${CONTROL_PLANE_LOCATION}-a,${CONTROL_PLANE_LOCATION}-c \ --spot
GKE crea los siguientes recursos para el LLM:
- Un clúster público de Google Kubernetes Engine (GKE) de edición Standard
- Un grupo de nodos con el tipo de máquina
g2-standard-24
en el que se redujo la escala verticalmente a 0 nodos. No se te cobrará por ninguna GPU hasta que inicies Pods que soliciten GPUs. Este grupo de nodos aprovisiona VMs Spot, que tienen un precio menor que las VMs estándar de Compute Engine predeterminadas y no proporcionan garantía de disponibilidad. Puedes quitar la marca--spot
de este comando y el selector de nodoscloud.google.com/gke-spot
en la configuracióntext-generation-inference.yaml
para usar VMs a pedido.
Configura
kubectl
para comunicarse con tu clúster:gcloud container clusters get-credentials l4-demo --location=${CONTROL_PLANE_LOCATION}
Prepara tu carga de trabajo
En esta sección, se muestra cómo configurar tu carga de trabajo según el modelo que deseas usar. En este instructivo, se usan implementaciones de Kubernetes para implementar el modelo. Un Deployment es un objeto de la API de Kubernetes que te permite ejecutar varias réplicas de Pods que se distribuyen entre los nodos de un clúster.
Llama 3 70b
Configura las variables de entorno predeterminadas:
export HF_TOKEN=HUGGING_FACE_TOKEN
Reemplaza
HUGGING_FACE_TOKEN
por tu token de HuggingFace.Crea un Secret de Kubernetes para el token de HuggingFace:
kubectl create secret generic l4-demo \ --from-literal=HUGGING_FACE_TOKEN=${HF_TOKEN} \ --dry-run=client -o yaml | kubectl apply -f -
Crea el siguiente manifiesto de Deployment
text-generation-inference.yaml
:En el manifiesto se muestra lo siguiente:
NUM_SHARD
debe ser2
porque el modelo requiere dos GPU NVIDIA L4.QUANTIZE
se configura comobitsandbytes-nf4
, lo que significa que el modelo se carga en 4 bits en lugar de 32 bits. Esto permite que GKE reduzca la cantidad de memoria de GPU necesaria y mejora la velocidad de inferencia. Sin embargo, la exactitud del modelo puede disminuir. Para aprender a calcular las GPU que se solicitarán, consulta Calcula la cantidad de GPU.
Aplica el manifiesto
kubectl apply -f text-generation-inference.yaml
El resultado es similar a este:
deployment.apps/llm created
Verifica el estado del modelo:
kubectl get deploy
El resultado es similar al siguiente:
NAME READY UP-TO-DATE AVAILABLE AGE llm 1/1 1 1 20m
Observa los registros de la implementación en ejecución:
kubectl logs -l app=llm
El resultado es similar al siguiente:
{"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
Configura las variables de entorno predeterminadas:
export HF_TOKEN=HUGGING_FACE_TOKEN
Reemplaza
HUGGING_FACE_TOKEN
por tu token de HuggingFace.Crea un Secret de Kubernetes para el token de HuggingFace:
kubectl create secret generic l4-demo \ --from-literal=HUGGING_FACE_TOKEN=${HF_TOKEN} \ --dry-run=client -o yaml | kubectl apply -f -
Crea el siguiente manifiesto de Deployment
text-generation-inference.yaml
:En el manifiesto se muestra lo siguiente:
NUM_SHARD
debe ser2
porque el modelo requiere dos GPU NVIDIA L4.QUANTIZE
se configura comobitsandbytes-nf4
, lo que significa que el modelo se carga en 4 bits en lugar de 32 bits. Esto permite que GKE reduzca la cantidad de memoria de GPU necesaria y mejora la velocidad de inferencia. Sin embargo, esto puede reducir la exactitud del modelo. Para aprender a calcular las GPU que se solicitarán, consulta Calcula la cantidad de GPU.
Aplica el manifiesto
kubectl apply -f text-generation-inference.yaml
El resultado es similar a este:
deployment.apps/llm created
Verifica el estado del modelo:
watch kubectl get deploy
Cuando el objeto Deployment está listo, el resultado es similar al siguiente:
NAME READY UP-TO-DATE AVAILABLE AGE llm 1/1 1 1 10m
Para salir de la visualización, escribe
CTRL + C
.Observa los registros de la implementación en ejecución:
kubectl logs -l app=llm
El resultado es similar al siguiente:
{"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
Crea el siguiente manifiesto de Deployment
text-generation-inference.yaml
:En el manifiesto se muestra lo siguiente:
NUM_SHARD
debe ser2
porque el modelo requiere dos GPU NVIDIA L4.QUANTIZE
se configura comobitsandbytes-nf4
, lo que significa que el modelo se carga en 4 bits en lugar de 32 bits. Esto permite que GKE reduzca la cantidad de memoria de GPU necesaria y mejora la velocidad de inferencia. Sin embargo, la exactitud del modelo puede disminuir. Para aprender a calcular las GPU que se solicitarán, consulta Calcula la cantidad de GPU.
Aplica el manifiesto
kubectl apply -f text-generation-inference.yaml
El resultado es similar a este:
deployment.apps/llm created
Verifica el estado del modelo:
watch kubectl get deploy
Cuando la implementación está lista, el resultado es similar al siguiente:
NAME READY UP-TO-DATE AVAILABLE AGE llm 1/1 1 1 10m
Para salir de la visualización, escribe
CTRL + C
.Observa los registros de la implementación en ejecución:
kubectl logs -l app=llm
El resultado es similar al siguiente:
{"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}
Crea un Service de tipo ClusterIP
Expón tus Pods de forma interna dentro del clúster para que otras aplicaciones puedan detectarlos y acceder a ellos.
Crea el siguiente manifiesto
llm-service.yaml
:apiVersion: v1 kind: Service metadata: name: llm-service spec: selector: app: llm type: ClusterIP ports: - protocol: TCP port: 80 targetPort: 8080
Aplica el manifiesto
kubectl apply -f llm-service.yaml
Implementa una interfaz de chat
Usa Gradio para crear una aplicación web que te permita interactuar con el modelo. Gradio es una biblioteca de Python que tiene un wrapper de ChatInterface que crea interfaces de usuario para chatbots.
Llama 3 70b
Crea un archivo llamado
gradio.yaml
:Aplica el manifiesto
kubectl apply -f gradio.yaml
Busca la dirección IP externa del Service:
kubectl get svc
El resultado es similar al siguiente:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gradio-service LoadBalancer 10.24.29.197 34.172.115.35 80:30952/TCP 125m
Copia la dirección IP externa de la columna
EXTERNAL-IP
.Para ver la interfaz del modelo desde tu navegador web, usa la dirección IP externa con el puerto expuesto:
http://EXTERNAL_IP
Mixtral 8x7b
Crea un archivo llamado
gradio.yaml
:Aplica el manifiesto
kubectl apply -f gradio.yaml
Busca la dirección IP externa del Service:
kubectl get svc
El resultado es similar al siguiente:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gradio-service LoadBalancer 10.24.29.197 34.172.115.35 80:30952/TCP 125m
Copia la dirección IP externa de la columna
EXTERNAL-IP
.Para ver la interfaz del modelo desde tu navegador web, usa la dirección IP externa con el puerto expuesto:
http://EXTERNAL_IP
Falcon 40b
Crea un archivo llamado
gradio.yaml
:Aplica el manifiesto
kubectl apply -f gradio.yaml
Busca la dirección IP externa del Service:
kubectl get svc
El resultado es similar al siguiente:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gradio-service LoadBalancer 10.24.29.197 34.172.115.35 80:30952/TCP 125m
Copia la dirección IP externa de la columna
EXTERNAL-IP
.Para ver la interfaz del modelo desde tu navegador web, usa la dirección IP externa con el puerto expuesto:
http://EXTERNAL_IP
Calcula la cantidad de GPUs
La cantidad de GPU depende del valor de la marca QUANTIZE
. En este
instructivo, QUANTIZE
se configura como bitsandbytes-nf4
, lo que significa que el modelo se
carga en 4 bits.
Un modelo de 70,000 millones de parámetros requeriría un mínimo de 40 GB de memoria de GPU, que equivale a 70,000 millones de veces 4 bits (70,000 millones x 4 bits = 35 GB) y considera una sobrecarga de 5 GB. En este caso, una sola GPU L4 no tendría suficiente memoria. Por lo tanto, en los ejemplos de este instructivo, se usan dos GPU L4 de memoria (2 x 24 = 48 GB). Esta configuración es suficiente para ejecutar Falcon 40b o Llama 3 70b en las GPU L4.