Entrega un LLM en GPU L4 con Ray


En esta guía, se muestra cómo entregar modelos de lenguaje grande (LLM) con Ray y el complemento Ray Operator con Google Kubernetes Engine (GKE).

En esta guía, puedes entregar cualquiera de los siguientes modelos:

En esta guía, también se abordan técnicas de entrega de modelos, como la multiplexación y la composición de modelos, que son compatibles con el framework de Ray Serve.

Información general

El framework de Ray proporciona una plataforma de IA/AA de extremo a extremo para el entrenamiento, el entrenamiento detallado y la inferencia de cargas de trabajo de aprendizaje automático. Ray Serve es un framework en Ray que puedes usar para entregar LLM populares de Hugging Face.

Según el formato de datos del modelo, la cantidad de GPU varía. En esta guía, tu modelo puede usar una o dos GPUs L4.

En esta guía se abarcan los siguientes pasos:

  1. Crea un clúster de GKE Autopilot o Standard con el complemento Ray Operator habilitado.
  2. Implementa un recurso de RayService que descargue y entregue un modelo de lenguaje grande (LLM) de Hugging Face.
  3. Implementa una interfaz de chat y dialoga con los LLM.

Antes de comenzar

Antes de comenzar, asegúrate de haber realizado las siguientes tareas:

  • Habilita la API de Google Kubernetes Engine.
  • Habilitar la API de Google Kubernetes Engine
  • Si deseas usar Google Cloud CLI para esta tarea, instala y, luego, inicializa gcloud CLI. Si ya instalaste gcloud CLI, ejecuta gcloud components update para obtener la versión más reciente.
  • Crea una cuenta de Hugging Face, si todavía no la tienes.
  • Asegúrate de tener un token de Hugging Face.
  • Asegúrate de tener acceso al modelo de Hugging Face que deseas usar. Por lo general, se otorga mediante la firma de un acuerdo y la solicitud de acceso al propietario del modelo en la página del modelo de Hugging Face.
  • Asegúrate de tener cuota de GPU en la región us-central1. Para obtener más información, consulta Cuota de GPU.

Prepara el entorno

  1. En la consola de Google Cloud, inicia una instancia de Cloud Shell:
    Abrir Cloud Shell

  2. Clona el repositorio de ejemplo:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
    cd kubernetes-engine-samples/ai-ml/gke-ray/rayserve/llm
    export TUTORIAL_HOME=`pwd`
    
  3. Configura las variables de entorno predeterminadas:

    gcloud config set project PROJECT_ID
    export PROJECT_ID=$(gcloud config get project)
    export COMPUTE_REGION=us-central1
    export CLUSTER_VERSION=CLUSTER_VERSION
    export HF_TOKEN=HUGGING_FACE_TOKEN
    

    Reemplaza lo siguiente:

    • PROJECT_ID: El ID del proyecto de Google Cloud.
    • CLUSTER_VERSION: la versión de GKE que se usará. Debe ser 1.30.1 o una versión posterior.
    • HUGGING_FACE_TOKEN: Tu token de acceso de Hugging Face.

Crea un clúster con un grupo de nodos de GPU

Puedes entregar un LLM en GPU L4 con Ray en un clúster de GKE Autopilot o Standard con el complemento Ray Operator. Por lo general, recomendamos que uses un clúster de Autopilot para una experiencia de Kubernetes completamente administrada. En su lugar, elige un clúster estándar si tu caso de uso requiere alta escalabilidad o si deseas más control sobre la configuración del clúster. 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.

Usa Cloud Shell para crear un clúster de Autopilot o Standard:

Autopilot

Crea un clúster de Autopilot con el complemento Ray Operator habilitado:

gcloud container clusters create-auto rayserve-cluster \
    --enable-ray-operator \
    --cluster-version=${CLUSTER_VERSION} \
    --location=${COMPUTE_REGION}

Estándar

Crea un clúster estándar con el complemento Ray Operator habilitado:

gcloud container clusters create rayserve-cluster \
    --addons=RayOperator \
    --cluster-version=${CLUSTER_VERSION} \
    --machine-type=g2-standard-24 \
    --location=${COMPUTE_ZONE} \
    --num-nodes=2 \
    --accelerator type=nvidia-l4,count=2,gpu-driver-version=latest

Crea un secreto de Kubernetes para las credenciales de Hugging Face

En Cloud Shell, crea un Secret de Kubernetes de la siguiente manera:

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

    gcloud container clusters get-credentials ${CLUSTER_NAME} --location=${COMPUTE_REGION}
    
  2. Crea un Secret de Kubernetes que contenga el token de Hugging Face:

    kubectl create secret generic hf-secret \
      --from-literal=hf_api_token=${HF_TOKEN} \
      --dry-run=client -o yaml | kubectl apply -f -
    

Implementa el modelo de LLM

El repositorio de GitHub que clonaste tiene un directorio para cada modelo que incluye una configuración de RayService. La configuración de cada modelo incluye los siguientes componentes:

  • Implementación de Ray Serve: La implementación de Ray Serve, que incluye la configuración de recursos y las dependencias del entorno de ejecución
  • Model: El ID del modelo de Hugging Face.
  • Clúster de Ray: El clúster subyacente de Ray y los recursos necesarios para cada componente, incluidos los pods principales y de trabajo.

Gemma 2B IT

  1. Implementa el modelo:

    kubectl apply -f gemma-2b-it/
    
  2. Espera a que el recurso de RayService esté listo:

    kubectl get rayservice gemma-2b-it -o yaml
    

    El resultado es similar a este:

    status:
      activeServiceStatus:
        applicationStatuses:
          llm:
            healthLastUpdateTime: "2024-06-22T02:51:52Z"
            serveDeploymentStatuses:
              VLLMDeployment:
                healthLastUpdateTime: "2024-06-22T02:51:52Z"
                status: HEALTHY
            status: RUNNING
    

    En este resultado, status: RUNNING indica que el recurso de RayService está listo.

  3. Confirma que GKE haya creado el Service para la aplicación Ray Serve:

    kubectl get service gemma-2b-it-serve-svc
    

    El resultado es similar a este:

    NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
    gemma-2b-it-serve-svc   ClusterIP   34.118.226.104   <none>        8000/TCP   45m
    

Gemma 7B IT

  1. Implementa el modelo:

    kubectl apply -f gemma-7b-it/
    
  2. Espera a que el recurso de RayService esté listo:

    kubectl get rayservice gemma-7b-it -o yaml
    

    El resultado es similar a este:

    status:
      activeServiceStatus:
        applicationStatuses:
          llm:
            healthLastUpdateTime: "2024-06-22T02:51:52Z"
            serveDeploymentStatuses:
              VLLMDeployment:
                healthLastUpdateTime: "2024-06-22T02:51:52Z"
                status: HEALTHY
            status: RUNNING
    

    En este resultado, status: RUNNING indica que el recurso de RayService está listo.

  3. Confirma que GKE haya creado el Service para la aplicación Ray Serve:

    kubectl get service gemma-7b-it-serve-svc
    

    El resultado es similar a este:

    NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
    gemma-7b-it-serve-svc   ClusterIP   34.118.226.104   <none>        8000/TCP   45m
    

Llama 2 7B

  1. Implementa el modelo:

    kubectl apply -f llama-2-7b/
    
  2. Espera a que el recurso de RayService esté listo:

    kubectl get rayservice llama-2-7b -o yaml
    

    El resultado es similar a este:

    status:
      activeServiceStatus:
        applicationStatuses:
          llm:
            healthLastUpdateTime: "2024-06-22T02:51:52Z"
            serveDeploymentStatuses:
              VLLMDeployment:
                healthLastUpdateTime: "2024-06-22T02:51:52Z"
                status: HEALTHY
            status: RUNNING
    

    En este resultado, status: RUNNING indica que el recurso de RayService está listo.

  3. Confirma que GKE haya creado el Service para la aplicación Ray Serve:

    kubectl get service llama-2-7b-serve-svc
    

    El resultado es similar a este:

    NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
    llama-2-7b-serve-svc    ClusterIP   34.118.226.104   <none>        8000/TCP   45m
    

Llama 3 8B

  1. Implementa el modelo:

    kubectl apply -f llama-3-8b/
    
  2. Espera a que el recurso de RayService esté listo:

    kubectl get rayservice llama-3-8b -o yaml
    

    El resultado es similar a este:

    status:
      activeServiceStatus:
        applicationStatuses:
          llm:
            healthLastUpdateTime: "2024-06-22T02:51:52Z"
            serveDeploymentStatuses:
              VLLMDeployment:
                healthLastUpdateTime: "2024-06-22T02:51:52Z"
                status: HEALTHY
            status: RUNNING
    

    En este resultado, status: RUNNING indica que el recurso de RayService está listo.

  3. Confirma que GKE haya creado el Service para la aplicación Ray Serve:

    kubectl get service llama-3-8b-serve-svc
    

    El resultado es similar a este:

    NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
    llama-3-8b-serve-svc    ClusterIP   34.118.226.104   <none>        8000/TCP   45m
    

Mistral 7B

  1. Implementa el modelo:

    kubectl apply -f mistral-7b/
    
  2. Espera a que el recurso de RayService esté listo:

    kubectl get rayservice mistral-7b -o yaml
    

    El resultado es similar a este:

    status:
      activeServiceStatus:
        applicationStatuses:
          llm:
            healthLastUpdateTime: "2024-06-22T02:51:52Z"
            serveDeploymentStatuses:
              VLLMDeployment:
                healthLastUpdateTime: "2024-06-22T02:51:52Z"
                status: HEALTHY
            status: RUNNING
    

    En este resultado, status: RUNNING indica que el recurso de RayService está listo.

  3. Confirma que GKE haya creado el Service para la aplicación Ray Serve:

    kubectl get service mistral-7b-serve-svc
    

    El resultado es similar a este:

    NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
    mistral-7b-serve-svc    ClusterIP   34.118.226.104   <none>        8000/TCP   45m
    

Entrega el modelo

Los modelos Llama2 7B y Llama3 8B usan la especificación de chat de la API de OpenAI. Los otros modelos solo admiten la generación de texto, que es una técnica que genera texto en función de una instrucción.

Configura la redirección de puertos.

Configura la redirección de puertos al servidor de inferencia:

Gemma 2B IT

kubectl port-forward svc/gemma-2b-it-serve-svc 8000:8000

Gemma 7B IT

kubectl port-forward svc/gemma-7b-it-serve-svc 8000:8000

Llama2 7B

kubectl port-forward svc/llama-7b-serve-svc 8000:8000

Llama 3 8B

kubectl port-forward svc/llama-3-8b-serve-svc 8000:8000

Mistral 7B

kubectl port-forward svc/mistral-7b-serve-svc 8000:8000

Interactúa con el modelo con curl

Usa curl para chatear con tu modelo:

Gemma 2B IT

En una sesión de terminal nueva, haz lo siguiente:

curl -X POST http://localhost:8000/ -H "Content-Type: application/json" -d '{"prompt": "What are the top 5 most popular programming languages? Be brief.", "max_tokens": 1024}'

Gemma 7B IT

En una sesión de terminal nueva, haz lo siguiente:

curl -X POST http://localhost:8000/ -H "Content-Type: application/json" -d '{"prompt": "What are the top 5 most popular programming languages? Be brief.", "max_tokens": 1024}'

Llama2 7B

En una sesión de terminal nueva, haz lo siguiente:

curl http://localhost:8000/v1/chat/completions     -H "Content-Type: application/json"     -d '{
      "model": "meta-llama/Llama-2-7b-chat-hf",
      "messages": [
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "What are the top 5 most popular programming languages? Please be brief."}
      ],
      "temperature": 0.7
    }'

Llama 3 8B

En una sesión de terminal nueva, haz lo siguiente:

curl http://localhost:8000/v1/chat/completions     -H "Content-Type: application/json"     -d '{
      "model": "meta-llama/Meta-Llama-3-8B-Instruct",
      "messages": [
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "What are the top 5 most popular programming languages? Please be brief."}
      ],
      "temperature": 0.7
    }'

Mistral 7B

En una sesión de terminal nueva, haz lo siguiente:

curl -X POST http://localhost:8000/ -H "Content-Type: application/json" -d '{"prompt": "What are the top 5 most popular programming languages? Be brief.", "max_tokens": 1024}'

Debido a que los modelos que entregaste no conservan ningún historial, cada mensaje y respuesta se debe enviar de vuelta al modelo para crear una experiencia de diálogo interactivo. En el siguiente ejemplo, se muestra cómo puedes crear un diálogo interactivo con el modelo Llama 3 8B:

Crea un diálogo con el modelo a través de curl:

curl http://localhost:8000/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{
      "model": "meta-llama/Meta-Llama-3-8B-Instruct",
      "messages": [
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "What are the top 5 most popular programming languages? Please be brief."},
        {"role": "assistant", "content": " \n1. Java\n2. Python\n3. C++\n4. C#\n5. JavaScript"},
        {"role": "user", "content": "Can you give me a brief description?"}
      ],
      "temperature": 0.7
}'

El resultado es similar a este:

{
  "id": "cmpl-3cb18c16406644d291e93fff65d16e41",
  "object": "chat.completion",
  "created": 1719035491,
  "model": "meta-llama/Meta-Llama-3-8B-Instruct",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Here's a brief description of each:\n\n1. **Java**: A versatile language for building enterprise-level applications, Android apps, and web applications.\n2. **Python**: A popular language for data science, machine learning, web development, and scripting, known for its simplicity and ease of use.\n3. **C++**: A high-performance language for building operating systems, games, and other high-performance applications, with a focus on efficiency and control.\n4. **C#**: A modern, object-oriented language for building Windows desktop and mobile applications, as well as web applications using .NET.\n5. **JavaScript**: A versatile language for client-side scripting on the web, commonly used for creating interactive web pages, web applications, and mobile apps.\n\nNote: These descriptions are brief and don't do justice to the full capabilities and uses of each language."
      },
      "logprobs": null,
      "finish_reason": "stop",
      "stop_reason": null
    }
  ],
  "usage": {
    "prompt_tokens": 73,
    "total_tokens": 245,
    "completion_tokens": 172
  }
}

Conéctate a la interfaz de chat (opcional)

Puedes usar Gradio para compilar aplicaciones web que te permitan interactuar con tu modelo. Gradio es una biblioteca de Python que tiene un wrapper ChatInterface que crea interfaces de usuario para chatbots. En el caso de Llama 2 7B y Llama 3 7B, instalaste Gradio cuando implementaste el modelo de LLM.

  1. Configura la redirección de puertos al Service gradio:

    kubectl port-forward service/gradio 8080:8080 &
    
  2. Abre http://localhost:8080 en tu navegador para chatear con el modelo.

Cómo entregar varios modelos con multiplexación de modelos

La multiplexación de modelos es una técnica que se usa para entregar varios modelos dentro del mismo clúster de Ray. Puedes enrutar el tráfico a modelos específicos con encabezados de solicitud o con el balanceamiento de cargas.

En este ejemplo, crearás una aplicación multiplexada de Ray Serve que consta de dos modelos: Gemma 7B IT y Llama 3 8B.

  1. Implementa el recurso RayService:

    kubectl apply -f model-multiplexing/
    
  2. Espera a que el recurso de RayService esté listo:

    kubectl get rayservice model-multiplexing -o yaml
    

    El resultado es similar a este:

    status:
      activeServiceStatus:
        applicationStatuses:
          llm:
            healthLastUpdateTime: "2024-06-22T14:00:41Z"
            serveDeploymentStatuses:
              MutliModelDeployment:
                healthLastUpdateTime: "2024-06-22T14:00:41Z"
                status: HEALTHY
              VLLMDeployment:
                healthLastUpdateTime: "2024-06-22T14:00:41Z"
                status: HEALTHY
              VLLMDeployment_1:
                healthLastUpdateTime: "2024-06-22T14:00:41Z"
                status: HEALTHY
            status: RUNNING
    

    En este resultado, status: RUNNING indica que el recurso de RayService está listo.

  3. Confirma que GKE haya creado el Service de Kubernetes para la aplicación Ray Serve:

    kubectl get service model-multiplexing-serve-svc
    

    El resultado es similar a este:

    NAME                           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
    model-multiplexing-serve-svc   ClusterIP   34.118.226.104   <none>        8000/TCP   45m
    
  4. Configura la redirección de puertos a la aplicación de Ray Serve:

    kubectl port-forward svc/model-multiplexing-serve-svc 8000:8000
    
  5. Envía una solicitud al modelo Gemma 7B IT:

    curl -X POST http://localhost:8000/ -H "Content-Type: application/json" --header "serve_multiplexed_model_id: google/gemma-7b-it" -d '{"prompt": "What are the top 5 most popular programming languages? Please be brief.", "max_tokens": 200}'
    

    El resultado es similar a este:

    {"text": ["What are the top 5 most popular programming languages? Please be brief.\n\n1. JavaScript\n2. Java\n3. C++\n4. Python\n5. C#"]}
    
  6. Envía una solicitud al modelo Llama 3 8B:

    curl -X POST http://localhost:8000/ -H "Content-Type: application/json" --header "serve_multiplexed_model_id: meta-llama/Meta-Llama-3-8B-Instruct" -d '{"prompt": "What are the top 5 most popular programming languages? Please be brief.", "max_tokens": 200}'
    

    El resultado es similar a este:

    {"text": ["What are the top 5 most popular programming languages? Please be brief. Here are your top 5 most popular programming languages, based on the TIOBE Index, a widely used measure of the popularity of programming languages.\r\n\r\n1. **Java**: Used in Android app development, web development, and enterprise software development.\r\n2. **Python**: A versatile language used in data science, machine learning, web development, and automation.\r\n3. **C++**: A high-performance language used in game development, system programming, and high-performance computing.\r\n4. **C#**: Used in Windows and web application development, game development, and enterprise software development.\r\n5. **JavaScript**: Used in web development, mobile app development, and server-side programming with technologies like Node.js.\r\n\r\nSource: TIOBE Index (2022).\r\n\r\nThese rankings can vary depending on the source and methodology used, but this gives you a general idea of the most popular programming languages."]}
    
  7. Para enviar una solicitud a un modelo aleatorio, excluye el encabezado serve_multiplexed_model_id:

    curl -X POST http://localhost:8000/ -H "Content-Type: application/json" -d '{"prompt": "What are the top 5 most popular programming languages? Please be brief.", "max_tokens": 200}'
    

    El resultado es uno de los resultados de los pasos anteriores.

Cómo crear varios modelos con la composición de modelos

La composición de modelos es una técnica que se usa para componer varios modelos en una sola aplicación. La composición de modelos te permite encadenar entradas y salidas en varios LLM y escalar tus modelos como una sola aplicación.

En este ejemplo, compilas dos modelos, Gemma 7B IT y Llama 3 8B, en una sola aplicación. El primer modelo es el modelo de asistente que responde las preguntas proporcionadas en la instrucción. El segundo modelo es el de resumen. El resultado del modelo de asistente se encadena a la entrada del modelo de resumen. El resultado final es la versión resumida de la respuesta del modelo del asistente.

  1. Implementa el recurso RayService:

    kubectl apply -f model-composition/
    
  2. Espera a que el recurso de RayService esté listo:

    kubectl get rayservice model-composition -o yaml
    

    El resultado es similar a este:

    status:
      activeServiceStatus:
        applicationStatuses:
          llm:
            healthLastUpdateTime: "2024-06-22T14:00:41Z"
            serveDeploymentStatuses:
              MutliModelDeployment:
                healthLastUpdateTime: "2024-06-22T14:00:41Z"
                status: HEALTHY
              VLLMDeployment:
                healthLastUpdateTime: "2024-06-22T14:00:41Z"
                status: HEALTHY
              VLLMDeployment_1:
                healthLastUpdateTime: "2024-06-22T14:00:41Z"
                status: HEALTHY
            status: RUNNING
    

    En este resultado, status: RUNNING indica que el recurso de RayService está listo.

  3. Confirma que GKE creó el Service para la aplicación Ray Serve:

    kubectl get service model-composition-serve-svc
    

    El resultado es similar a este:

    NAME                           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
    model-composition-serve-svc    ClusterIP   34.118.226.104   <none>        8000/TCP   45m
    
  4. Envía una solicitud al modelo:

    curl -X POST http://localhost:8000/ -H "Content-Type: application/json" -d '{"prompt": "What is the most popular programming language for machine learning and why?", "max_tokens": 1000}'
    
  5. El resultado es similar a este:

    {"text": ["\n\n**Sure, here is a summary in a single sentence:**\n\nThe most popular programming language for machine learning is Python due to its ease of use, extensive libraries, and growing community."]}
    

Borra el proyecto

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Borra los recursos individuales

Si usaste un proyecto existente y no quieres borrarlo, puedes borrar los recursos individuales.

  1. Borra el clúster:

    gcloud container clusters delete rayserve-cluster
    

¿Qué sigue?