Entrega modelos abiertos de Gemma con GPUs en GKE con Triton y TensorRT-LLM


En este instructivo, se muestra cómo entregar un modelo grande de lenguaje (LLM) Gemma que usa unidades de procesamiento gráfico (GPU) en Google Kubernetes Engine (GKE) con la pila de entrega NVIDIA Triton y TensorRT‐LLM. En este instructivo, descargarás los modelos de Gemma ajustados a las instrucciones de los parámetros 2B y 7B y, luego, los implementarás en un clúster de GKE Autopilot o Standard mediante un contenedor que ejecuta Triton y TensorRT-LLM.

Esta guía es un buen punto de partida si necesitas el control detallado, la escalabilidad, la resiliencia, la portabilidad y la rentabilidad de Kubernetes administrado cuando implementas y entregas tus cargas de trabajo de IA/AA. Si necesitas una plataforma de IA administrada unificada para compilar y entregar modelos de AA con rapidez de forma rentable, te recomendamos que pruebes nuestra solución de implementación de Vertex AI.

Formación

La entrega de Gemma mediante GPU en GKE con Triton y TensorRT-LLM permite implementar una solución de entrega de inferencia sólida y lista para la producción con todos los beneficios de Kubernetes administrado, incluida la escalabilidad eficiente y una mayor disponibilidad. En esta sección, se describen las tecnologías clave que se usan en esta guía.

Gemma

Gemma es un conjunto de modelos de Inteligencia Artificial (IA) básicos y de disponibilidad general que se lanzan con una licencia abierta. Estos modelos de IA están disponibles para ejecutarse en tus aplicaciones, hardware, dispositivos móviles o servicios alojados. Puedes usar los modelos de Gemma para la generación de texto, pero también puedes ajustar estos modelos para tareas especializadas.

Para obtener más información, consulta la documentación de Gemma.

GPU

Las GPUs te permiten acelerar cargas de trabajo específicas que se ejecutan en tus nodos, como el aprendizaje automático y el procesamiento de datos. GKE proporciona una variedad de opciones de tipos de máquinas para la configuración de nodos, incluidos los tipos de máquinas con GPUs NVIDIA H100, L4 y A100.

Antes de usar las GPUs en GKE, te recomendamos que completes la siguiente ruta de aprendizaje:

  1. Obtén información sobre la disponibilidad actual de la versión de GPU.
  2. Obtén información sobre las GPUs en GKE.

TensorRT-LLM

NVIDIA TensorRT-LLM (TRT-LLM) es un kit de herramientas con una API de Python para ensamblar soluciones optimizadas para definir LLMs y compilar motores TensorRT que realizan inferencias de manera eficiente en las GPUs de NVIDIA. TensorRT-LLM incluye funciones como las siguientes:

  • Implementación optimizada de transformador con fusiones de capas, almacenamiento en caché de activación, reutilización de búfer de memoria y PagedAttention
  • Agrupación en lotes en tránsito o continuo para mejorar la capacidad de procesamiento general de la entrega
  • Paralelismo tensorial y paralelismo de canalización para la entrega distribuida en varias GPUs
  • Cuantización (FP16, FP8, INT8)

Para obtener más información, consulta la documentación de TensorRT-LLM.

Triton

NVIDIA Triton Inference Server es un servidor de inferencia de código abierto para aplicaciones de IA/AA. Triton admite inferencia de alto rendimiento en GPUs y CPUs de NVIDIA con backends optimizados, incluidos TensorRT y TensorRT-LLM. Triton incluye funciones como las siguientes:

  • Inferencia de varias GPU y varios nodos
  • Ejecución simultánea de varios modelos
  • Ensamble o encadenamiento de modelos
  • Agrupación en lotes estática, dinámica y continua o en tránsito de solicitudes de predicción

Para obtener más información, consulta la documentación de Triton.

Objetivos

Esta guía está dirigida a clientes de IA generativa que usan PyTorch, usuarios nuevos o existentes de GKE, ingenieros de AA, ingenieros de MLOps (DevOps) o administradores de plataformas que estén interesados en el uso de las capacidades de organización de contenedores de Kubernetes para entregar LLMs en hardware de GPU H100, A100 y L4.

Al final de esta guía, deberías poder realizar los siguientes pasos:

  1. Prepara tu entorno con un clúster de GKE en modo Autopilot.
  2. Implementa un contenedor con Triton y TritonRT-LLM en tu clúster.
  3. Usa Triton y TensorRT-LLM para entregar el modelo Gemma 2B o 7B a través de curl.

Antes de comenzar

  • Accede a tu cuenta de Google Cloud. Si eres nuevo en Google Cloud, crea una cuenta para evaluar el rendimiento de nuestros productos en situaciones reales. Los clientes nuevos también obtienen $300 en créditos gratuitos para ejecutar, probar y, además, implementar cargas de trabajo.
  • En la página del selector de proyectos de la consola de Google Cloud, selecciona o crea un proyecto de Google Cloud.

    Ir al selector de proyectos

  • Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.

  • Habilita la API necesaria.

    Habilita la API

  • En la página del selector de proyectos de la consola de Google Cloud, selecciona o crea un proyecto de Google Cloud.

    Ir al selector de proyectos

  • Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.

  • Habilita la API necesaria.

    Habilita la API

  • Asegúrate de tener los siguientes roles en el proyecto: roles/container.admin, roles/iam.serviceAccountAdmin

    Verifica los roles

    1. En la consola de Google Cloud, ve a la página IAM.

      Ir a IAM
    2. Selecciona el proyecto.
    3. En la columna Principal, busca la fila que tiene tu dirección de correo electrónico.

      Si tu dirección de correo electrónico no está en esa columna, no tienes ningún rol.

    4. En la columna Función de la fila con la dirección de correo electrónico, verifica si la lista de roles incluye los roles necesarios.

    Otorga los roles

    1. En la consola de Google Cloud, ve a la página IAM.

      Ir a IAM
    2. Selecciona el proyecto.
    3. Haz clic en Grant access.
    4. En el campo Principales nuevas, ingresa tu dirección de correo electrónico.
    5. En la lista Seleccionar un rol, elige un rol.
    6. Para otorgar funciones adicionales, haz clic en Agregar otro rol y agrega cada rol adicional.
    7. Haz clic en Guardar.

Prepare el entorno

En este instructivo, usarás Cloud Shell para administrar recursos alojados en Google Cloud. Cloud Shell tiene preinstalado el software que necesitarás para este instructivo, incluidos kubectl y la CLI de gcloud.

Para configurar tu entorno con Cloud Shell, sigue estos pasos:

  1. En la consola de Google Cloud, haz clic en Ícono de activación de Cloud Shell Activar Cloud Shell en la consola de Google Cloud para iniciar una sesión de Cloud Shell. Esto inicia una sesión en el panel inferior de la consola de Google Cloud.

  2. Configura las variables de entorno predeterminadas:

    gcloud config set project PROJECT_ID
    export PROJECT_ID=$(gcloud config get project)
    export REGION=REGION
    export CLUSTER_NAME=triton
    

    Reemplaza los siguientes valores:

    • PROJECT_ID: El ID del proyecto de Google Cloud.
    • REGION: Una región que admita el tipo de acelerador que deseas usar, por ejemplo, us-central1 para la GPU L4.

Obtén acceso al modelo

Para obtener acceso a los modelos Gemma, debes acceder a la plataforma Kaggle y obtener un token de la API de Kaggle.

Debes firmar el acuerdo de consentimiento para usar Gemma. Sigue estas instrucciones:

  1. Accede a la página de consentimiento del modelo en Kaggle.com.
  2. Accede a Kaggle si aún no lo has hecho.
  3. Haz clic en Solicitar acceso.
  4. En la sección Elegir cuenta para el consentimiento, selecciona Verificar mediante cuenta de Kaggle para usar tu cuenta de Kaggle para obtener consentimiento.
  5. Acepta los Términos y Condiciones del modelo.

Genera un token de acceso

Para acceder al modelo a través de Kaggle, necesitas un token de la API de Kaggle. Sigue estos pasos para generar un token nuevo si aún no tienes uno:

  1. En el navegador, ve a la configuración de Kaggle.
  2. En la sección API, haz clic en Crear token nuevo.

Se descargó un archivo con el nombre kaggle.json.

Sube el token de acceso a Cloud Shell

En Cloud Shell, sube el token de la API de Kaggle a tu proyecto de Google Cloud:

  1. En Cloud Shell, haz clic en Más > Subir.
  2. Selecciona Archivo y haz clic en Elegir archivos.
  3. Abre el archivo kaggle.json.
  4. Haz clic en Subir.

Crea y configura recursos de Google Cloud

Sigue estas instrucciones para crear los recursos necesarios.

Crea un clúster de GKE y un grupo de nodos

Puedes entregar Gemma 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 ${CLUSTER_NAME} \
  --project=${PROJECT_ID} \
  --region=${REGION} \
  --release-channel=rapid \
  --cluster-version=1.28

GKE crea un clúster de Autopilot con nodos de CPU y GPU según lo solicitan las cargas de trabajo implementadas.

Estándar

  1. En Cloud Shell, ejecuta el siguiente comando para crear un clúster estándar:

    gcloud container clusters create ${CLUSTER_NAME} \
        --project=${PROJECT_ID} \
        --location=${REGION}-a \
        --workload-pool=${PROJECT_ID}.svc.id.goog \
        --release-channel=rapid \
        --machine-type=e2-standard-4 \
        --num-nodes=1
    

    La creación del clúster puede tomar varios minutos.

  2. Ejecuta el siguiente comando para crear un grupo de nodos para el clúster:

    gcloud container node-pools create gpupool \
        --accelerator type=nvidia-l4,count=1,gpu-driver-version=latest \
        --project=${PROJECT_ID} \
        --location=${REGION}-a \
        --cluster=${CLUSTER_NAME} \
        --machine-type=g2-standard-12 \
        --num-nodes=1
    

    GKE crea un grupo de nodos único que contiene un nodo de GPU L4.

Crea un secreto de Kubernetes para las credenciales de Kaggle

En este instructivo, usas un secreto de Kubernetes para las credenciales de Kaggle.

En Cloud Shell, haz lo siguiente:

  1. Configura kubectl para comunicarse con tu clúster:

    gcloud container clusters get-credentials ${CLUSTER_NAME} --location=${REGION}
    
  2. Crea un secreto para almacenar las credenciales de Kaggle:

    kubectl create secret generic kaggle-secret \
        --from-file=kaggle.json \
        --dry-run=client -o yaml | kubectl apply -f -
    

Crea un recurso PersistentVolume para almacenar puntos de control

En esta sección, crearás un PersistentVolume respaldado por un disco persistente para almacenar los puntos de control del modelo.

  1. Crea el siguiente manifiesto trtllm_checkpoint_pv.yaml:

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: model-data
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 100G
  2. Aplica el manifiesto

    kubectl apply -f trtllm_checkpoint_pv.yaml
    

Descarga los archivos del motor de TensorRT-LLM para Gemma

En esta sección, ejecutarás un trabajo para descargar los archivos de motor de TensorRT-LLM y almacenar los archivos en el PersistentVolume que creaste antes. El trabajo también prepara archivos de configuración para implementar el modelo en el servidor de Triton en el siguiente paso. Este proceso puede demorar unos minutos.

Gemma 2B-it

El motor TensorRT-LLM se compila a partir del punto de control PyTorch de Gemma 2B-it (ajuste por instrucciones) de Gemma mediante la activación bfloat16, la longitud de la secuencia de entrada=2048 y la longitud de la secuencia de salida=1,024 GPU L4 orientadas. Puedes implementar el modelo en una sola GPU L4.

  1. Crea el siguiente manifiesto job-download-gemma-2b.yaml:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: fetch-model-scripts
    data:
      fetch_model.sh: |-
        #!/usr/bin/bash -x
        pip install kaggle --break-system-packages && \
    
        MODEL_NAME=$(echo ${MODEL_PATH} | awk -F'/' '{print $2}') && \
        VARIATION_NAME=$(echo ${MODEL_PATH} | awk -F'/' '{print $4}') && \
        ACTIVATION_DTYPE=bfloat16 && \
    
        TOKENIZER_DIR=/data/trt_engine/${MODEL_NAME}/${VARIATION_NAME}/${ACTIVATION_DTYPE}/${WORLD_SIZE}-gpu/tokenizer.model && \
        ENGINE_PATH=/data/trt_engine/${MODEL_NAME}/${VARIATION_NAME}/${ACTIVATION_DTYPE}/${WORLD_SIZE}-gpu/ && \
        TRITON_MODEL_REPO=/data/triton/model_repository && \
    
        mkdir -p /data/${MODEL_NAME}_${VARIATION_NAME} && \
        mkdir -p ${ENGINE_PATH} && \
        mkdir -p ${TRITON_MODEL_REPO} && \
    
        kaggle models instances versions download ${MODEL_PATH} --untar -p /data/${MODEL_NAME}_${VARIATION_NAME} && \
        rm -f /data/${MODEL_NAME}_${VARIATION_NAME}/*.tar.gz && \
        find /data/${MODEL_NAME}_${VARIATION_NAME} -type f && \
        find /data/${MODEL_NAME}_${VARIATION_NAME} -type f | xargs -I '{}' mv '{}' ${ENGINE_PATH} && \
    
        # copying configuration files
        echo -e "\nCreating configuration files" && \
        cp -r /tensorrtllm_backend/all_models/inflight_batcher_llm/* ${TRITON_MODEL_REPO} && \
    
        # updating configuration files
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/preprocessing/config.pbtxt tokenizer_dir:${TOKENIZER_DIR},tokenizer_type:sp,triton_max_batch_size:64,preprocessing_instance_count:1 && \
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/postprocessing/config.pbtxt tokenizer_dir:${TOKENIZER_DIR},tokenizer_type:sp,triton_max_batch_size:64,postprocessing_instance_count:1 && \
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/tensorrt_llm_bls/config.pbtxt triton_max_batch_size:64,decoupled_mode:False,bls_instance_count:1,accumulate_tokens:False && \
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/ensemble/config.pbtxt triton_max_batch_size:64 && \
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/tensorrt_llm/config.pbtxt triton_max_batch_size:64,decoupled_mode:False,max_beam_width:1,engine_dir:${ENGINE_PATH},max_tokens_in_paged_kv_cache:2560,max_attention_window_size:2560,kv_cache_free_gpu_mem_fraction:0.5,exclude_input_in_output:True,enable_kv_cache_reuse:False,batching_strategy:inflight_batching,max_queue_delay_microseconds:600,batch_scheduler_policy:guaranteed_no_evict,enable_trt_overlap:False && \
    
        echo -e "\nCompleted extraction to ${ENGINE_PATH}"
    ---
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: data-loader-gemma-2b
      labels:
        app: data-loader-gemma-2b
    spec:
      ttlSecondsAfterFinished: 120
      template:
        metadata:
          labels:
            app: data-loader-gemma-2b
        spec:
          restartPolicy: OnFailure
          containers:
          - name: gcloud
            image: us-docker.pkg.dev/google-samples/containers/gke/tritonserver:2.42.0
            command:
            - /scripts/fetch_model.sh
            env:
            - name: KAGGLE_CONFIG_DIR
              value: /kaggle
            - name: MODEL_PATH
              value: "google/gemma/tensorrtllm/2b-it/2"
            - name: WORLD_SIZE
              value: "1"
            volumeMounts:
            - mountPath: "/kaggle/"
              name: kaggle-credentials
              readOnly: true
            - mountPath: "/scripts/"
              name: scripts-volume
              readOnly: true
            - mountPath: "/data"
              name: data
          volumes:
          - name: kaggle-credentials
            secret:
              defaultMode: 0400
              secretName: kaggle-secret
          - name: scripts-volume
            configMap:
              defaultMode: 0700
              name: fetch-model-scripts
          - name: data
            persistentVolumeClaim:
              claimName: model-data
          tolerations:
          - key: "key"
            operator: "Exists"
            effect: "NoSchedule"
  2. Aplica el manifiesto

    kubectl apply -f job-download-gemma-2b.yaml
    
  3. Visualiza los registros del trabajo:

    kubectl logs -f job/data-loader-gemma-2b
    

    El resultado de los registros es similar al siguiente:

    ...
    Creating configuration files
    + echo -e '\n02-16-2024 04:07:45 Completed building TensortRT-LLM engine at /data/trt_engine/gemma/2b/bfloat16/1-gpu/'
    + echo -e '\nCreating configuration files'
    ...
    
  4. Espera a que se complete el trabajo:

    kubectl wait --for=condition=complete --timeout=900s job/data-loader-gemma-2b
    

    El resultado es similar al siguiente:

    job.batch/data-loader-gemma-2b condition met
    
  5. Verifica que el trabajo se haya completado correctamente (esto puede tardar unos minutos):

    kubectl get job/data-loader-gemma-2b
    

    El resultado es similar al siguiente:

    NAME             COMPLETIONS   DURATION   AGE
    data-loader-gemma-2b   1/1           ##s        #m##s
    

Gemma 7B-it

El motor TensorRT-LLM se compila a partir del punto de control PyTorch de Gemma 7B-it (ajuste de instrucciones) de Gemma mediante la activación bfloat16, la longitud de la secuencia de entrada=1,024 y la longitud de la secuencia de salida=512 GPU L4 orientadas. Puedes implementar el modelo en una sola GPU L4.

  1. Crea el siguiente manifiesto job-download-gemma-7b.yaml:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: fetch-model-scripts
    data:
      fetch_model.sh: |-
        #!/usr/bin/bash -x
        pip install kaggle --break-system-packages && \
    
        MODEL_NAME=$(echo ${MODEL_PATH} | awk -F'/' '{print $2}') && \
        VARIATION_NAME=$(echo ${MODEL_PATH} | awk -F'/' '{print $4}') && \
        ACTIVATION_DTYPE=bfloat16 && \
    
        TOKENIZER_DIR=/data/trt_engine/${MODEL_NAME}/${VARIATION_NAME}/${ACTIVATION_DTYPE}/${WORLD_SIZE}-gpu/tokenizer.model && \
        ENGINE_PATH=/data/trt_engine/${MODEL_NAME}/${VARIATION_NAME}/${ACTIVATION_DTYPE}/${WORLD_SIZE}-gpu/ && \
        TRITON_MODEL_REPO=/data/triton/model_repository && \
    
        mkdir -p ${ENGINE_PATH} && \
        mkdir -p ${TRITON_MODEL_REPO} && \
    
        kaggle models instances versions download ${MODEL_PATH} --untar -p /data/${MODEL_NAME}_${VARIATION_NAME} && \
        rm -f /data/${MODEL_NAME}_${VARIATION_NAME}/*.tar.gz && \
        find /data/${MODEL_NAME}_${VARIATION_NAME} -type f && \
        find /data/${MODEL_NAME}_${VARIATION_NAME} -type f | xargs -I '{}' mv '{}' ${ENGINE_PATH} && \
    
        # copying configuration files
        echo -e "\nCreating configuration files" && \
        cp -r /tensorrtllm_backend/all_models/inflight_batcher_llm/* ${TRITON_MODEL_REPO} && \
    
        # updating configuration files
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/preprocessing/config.pbtxt tokenizer_dir:${TOKENIZER_DIR},tokenizer_type:sp,triton_max_batch_size:64,preprocessing_instance_count:1 && \
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/postprocessing/config.pbtxt tokenizer_dir:${TOKENIZER_DIR},tokenizer_type:sp,triton_max_batch_size:64,postprocessing_instance_count:1 && \
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/tensorrt_llm_bls/config.pbtxt triton_max_batch_size:64,decoupled_mode:False,bls_instance_count:1,accumulate_tokens:False && \
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/ensemble/config.pbtxt triton_max_batch_size:64 && \
        python3 /tensorrtllm_backend/tools/fill_template.py -i ${TRITON_MODEL_REPO}/tensorrt_llm/config.pbtxt triton_max_batch_size:64,decoupled_mode:False,max_beam_width:1,engine_dir:${ENGINE_PATH},max_tokens_in_paged_kv_cache:2560,max_attention_window_size:2560,kv_cache_free_gpu_mem_fraction:0.5,exclude_input_in_output:True,enable_kv_cache_reuse:False,batching_strategy:inflight_batching,max_queue_delay_microseconds:600,batch_scheduler_policy:guaranteed_no_evict,enable_trt_overlap:False && \
    
        echo -e "\nCompleted extraction to ${ENGINE_PATH}"
    ---
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: data-loader-gemma-7b
      labels:
        app: data-loader-gemma-7b
    spec:
      ttlSecondsAfterFinished: 120
      template:
        metadata:
          labels:
            app: data-loader-gemma-7b
        spec:
          restartPolicy: OnFailure
          containers:
          - name: gcloud
            image: us-docker.pkg.dev/google-samples/containers/gke/tritonserver:2.42.0
            command:
            - /scripts/fetch_model.sh
            env:
            - name: KAGGLE_CONFIG_DIR
              value: /kaggle
            - name: MODEL_PATH
              value: "google/gemma/tensorrtllm/7b-it/2"
            - name: WORLD_SIZE
              value: "1"
            volumeMounts:
            - mountPath: "/kaggle/"
              name: kaggle-credentials
              readOnly: true
            - mountPath: "/scripts/"
              name: scripts-volume
              readOnly: true
            - mountPath: "/data"
              name: data
          volumes:
          - name: kaggle-credentials
            secret:
              defaultMode: 0400
              secretName: kaggle-secret
          - name: scripts-volume
            configMap:
              defaultMode: 0700
              name: fetch-model-scripts
          - name: data
            persistentVolumeClaim:
              claimName: model-data
          tolerations:
          - key: "key"
            operator: "Exists"
            effect: "NoSchedule"
  2. Aplica el manifiesto

    kubectl apply -f job-download-gemma-7b.yaml
    
  3. Visualiza los registros del trabajo:

    kubectl logs -f job/data-loader-gemma-7b
    

    El resultado de los registros es similar al siguiente:

    ...
    Creating configuration files
    + echo -e '\n02-16-2024 04:07:45 Completed building TensortRT-LLM engine at /data/trt_engine/gemma/7b/bfloat16/1-gpu/'
    + echo -e '\nCreating configuration files'
    ...
    
  4. Espera a que se complete el trabajo:

    kubectl wait --for=condition=complete --timeout=900s job/data-loader-gemma-7b
    

    El resultado es similar al siguiente:

    job.batch/data-loader-gemma-7b condition met
    
  5. Verifica que el trabajo se haya completado correctamente (esto puede tardar unos minutos):

    kubectl get job/data-loader-gemma-7b
    

    El resultado es similar al siguiente:

    NAME             COMPLETIONS   DURATION   AGE
    data-loader-gemma-7b   1/1           ##s        #m##s
    

Asegúrate de que el trabajo se haya completado correctamente antes de continuar con la siguiente sección.

Implementa Triton

En esta sección, implementarás un contenedor que usa Triton con el backend de TensorRT-LLM para entregar el modelo de Gemma que deseas usar.

  1. Crea el siguiente manifiesto deploy-triton-server.yaml:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: launch-tritonserver
    data:
      entrypoint.sh: |-
        #!/usr/bin/bash -x
        # Launch Triton Inference server
    
        WORLD_SIZE=1
        TRITON_MODEL_REPO=/data/triton/model_repository
    
        python3 /tensorrtllm_backend/scripts/launch_triton_server.py \
          --world_size ${WORLD_SIZE} \
          --model_repo ${TRITON_MODEL_REPO}
    
        tail -f /dev/null
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: triton-gemma-deployment
      labels:
        app: gemma-server
        version: v1
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: gemma-server
          version: v1
      template:
        metadata:
          labels:
            app: gemma-server
            ai.gke.io/model: gemma
            ai.gke.io/inference-server: triton
            examples.ai.gke.io/source: user-guide
            version: v1
        spec:
          containers:
          - name: inference-server
            image: us-docker.pkg.dev/google-samples/containers/gke/tritonserver:2.42.0
            imagePullPolicy: IfNotPresent
            resources:
              requests:
                ephemeral-storage: "40Gi"
                memory: "40Gi"
                nvidia.com/gpu: 1
              limits:
                ephemeral-storage: "40Gi"
                memory: "40Gi"
                nvidia.com/gpu: 1
            command:
            - /scripts/entrypoint.sh
            volumeMounts:
            - mountPath: "/scripts/"
              name: scripts-volume
              readOnly: true
            - mountPath: "/data"
              name: data
            ports:
              - containerPort: 8000
                name: http
              - containerPort: 8001
                name: grpc
              - containerPort: 8002
                name: metrics
            livenessProbe:
              failureThreshold: 60
              initialDelaySeconds: 600
              periodSeconds: 5
              httpGet:
                path: /v2/health/live
                port: http
            readinessProbe:
              failureThreshold: 60
              initialDelaySeconds: 600
              periodSeconds: 5
              httpGet:
                path: /v2/health/ready
                port: http
          securityContext:
            runAsUser: 1000
            fsGroup: 1000
          volumes:
          - name: scripts-volume
            configMap:
              defaultMode: 0700
              name: launch-tritonserver
          - name: data
            persistentVolumeClaim:
              claimName: model-data
          nodeSelector:
            cloud.google.com/gke-accelerator: nvidia-l4
          tolerations:
          - key: "key"
            operator: "Exists"
            effect: "NoSchedule"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: triton-server
      labels:
        app: gemma-server
    spec:
      type: ClusterIP
      ports:
        - port: 8000
          targetPort: http
          name: http-inference-server
        - port: 8001
          targetPort: grpc
          name: grpc-inference-server
        - port: 8002
          targetPort: metrics
          name: http-metrics
      selector:
        app: gemma-server
  2. Aplica el manifiesto

    kubectl apply -f deploy-triton-server.yaml
    
  3. Espera a que la implementación esté disponible:

    kubectl wait --for=condition=Available --timeout=900s deployment/triton-gemma-deployment
    
  4. Consulta los registros del manifiesto:

    kubectl logs -f -l app=gemma-server
    

    El recurso de implementación inicia el servidor de Triton y carga los datos del modelo. Este proceso puede tardar unos minutos (hasta 20 minutos o más). El resultado es similar al siguiente:

    I0216 03:24:57.387420 29 server.cc:676]
    +------------------+---------+--------+
    | Model            | Version | Status |
    +------------------+---------+--------+
    | ensemble         | 1       | READY  |
    | postprocessing   | 1       | READY  |
    | preprocessing    | 1       | READY  |
    | tensorrt_llm     | 1       | READY  |
    | tensorrt_llm_bls | 1       | READY  |
    +------------------+---------+--------+
    
    ....
    ....
    ....
    
    I0216 03:24:57.425104 29 grpc_server.cc:2519] Started GRPCInferenceService at 0.0.0.0:8001
    I0216 03:24:57.425418 29 http_server.cc:4623] Started HTTPService at 0.0.0.0:8000
    I0216 03:24:57.466646 29 http_server.cc:315] Started Metrics Service at 0.0.0.0:8002
    

Entrega el modelo

En esta sección, interactuarás con el modelo.

Configura la redirección de puertos

Ejecuta el siguiente comando para configurar la redirección de puertos al modelo:

kubectl port-forward service/triton-server 8000:8000

El resultado es similar al siguiente:

Forwarding from 127.0.0.1:8000 -> 8000
Forwarding from [::1]:8000 -> 8000
Handling connection for 8000

Interactúa con el modelo mediante curl

En esta sección, se muestra cómo puedes realizar una prueba de humo básica para verificar el modelo ajustado a las instrucciones implementadas. Para simplificar, en esta sección se describe el enfoque de prueba solo con el modelo 2B ajustado a instrucciones.

En una sesión de terminal nueva, usa curl para chatear con tu modelo:

USER_PROMPT="I'm new to coding. If you could only recommend one programming language to start with, what would it be and why?"

curl -X POST localhost:8000/v2/models/ensemble/generate \
  -H "Content-Type: application/json" \
  -d @- <<EOF
{
    "text_input": "<start_of_turn>user\n${USER_PROMPT}<end_of_turn>\n",
    "temperature": 0.9,
    "max_tokens": 128
}
EOF

En el siguiente resultado, se muestra un ejemplo de la respuesta del modelo:

{
  "context_logits": 0,
  "cum_log_probs": 0,
  "generation_logits": 0,
  "model_name": "ensemble",
  "model_version": "1",
  "output_log_probs": [0.0,0.0,...],
  "sequence_end": false,
  "sequence_id": 0,
  "sequence_start": false,
  "text_output":"Python.\n\nPython is an excellent choice for beginners due to its simplicity, readability, and extensive documentation. Its syntax is close to natural language, making it easier for beginners to understand and write code. Python also has a vast collection of libraries and tools that make it versatile for various projects. Additionally, Python's dynamic nature allows for easier learning and experimentation, making it a perfect choice for newcomers to get started.Here are some specific reasons why Python is a good choice for beginners:\n\n- Simple and Easy to Read: Python's syntax is designed to be close to natural language, making it easier for"
}

Soluciona problemas

  • Si recibes el mensaje Empty reply from server, es posible que el contenedor no haya terminado de descargar los datos del modelo. Vuelve a verificar los registros del Pod en busca del mensaje Connected, que indica que el modelo está listo para entregar.
  • Si ves Connection refused, verifica que tu redirección de puertos esté activa.

Limpia

Para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos usados en este instructivo, borra el proyecto que contiene los recursos o conserva el proyecto y borra los recursos individuales.

Borra los recursos implementados

Para evitar que se generen cargos en tu cuenta de Google Cloud por los recursos que creaste en esta guía, ejecuta el siguiente comando:

gcloud container clusters delete ${CLUSTER_NAME} \
  --region=${REGION}

¿Qué sigue?