Exibir um LLM em GPUs L4 com Ray

Este guia mostra como disponibilizar modelos de linguagem grandes (LLMs) usando o Ray e o complemento Ray Operator com o Google Kubernetes Engine (GKE). O framework do Ray fornece uma plataforma completa de IA/ML para treinamento, treinamento detalhado e inferência de cargas de trabalho de ML. O Ray Serve é um framework do Ray que pode ser usado para disponibilizar LLMs conhecidos do Hugging Face.

Antes de ler este guia, confira se você conhece o modelo que quer disponibilizar neste tutorial. É possível veicular qualquer um dos seguintes modelos:

Esta página é destinada a engenheiros de machine learning (ML) e administradores e operadores de plataforma que facilitam cargas de trabalho de ML. Para saber mais sobre papéis comuns e tarefas de exemplo referenciados no conteúdo do Google Cloud , consulte Tarefas e funções de usuário comuns do GKE.

Abordamos as etapas a seguir:

  1. Crie um cluster do GKE Autopilot ou do Standard com o complemento do operador do Ray ativado.
  2. Implante um recurso do RayService que baixa e disponibiliza um modelo de linguagem grande (LLM) do Hugging Face.
  3. Implante uma interface de chat e converse com LLMs.

Antes de começar

Antes de começar, verifique se você realizou as tarefas a seguir:

  • Ative a API Google Kubernetes Engine.
  • Ativar a API Google Kubernetes Engine
  • Se você quiser usar a Google Cloud CLI para essa tarefa, instale e, em seguida, inicialize a CLI gcloud. Se você instalou a CLI gcloud anteriormente, instale a versão mais recente executando o comando gcloud components update. Talvez as versões anteriores da CLI gcloud não sejam compatíveis com a execução dos comandos neste documento.
  • Crie uma conta do Hugging Face caso ainda não tenha uma.
  • Verifique se você tem um token do Hugging Face.
  • Verifique se você tem acesso ao modelo do Hugging Face que quer usar. Isso geralmente é concedido com a assinatura de um contrato e a solicitação de acesso ao proprietário do modelo na página do modelo do Hugging Face.
  • Verifique se você tem uma cota de GPU na região us-central1. Para saber mais, consulte Cota de GPU.

Preparar o ambiente

  1. No console do Google Cloud , inicie uma instância do Cloud Shell:
    Abrir o Cloud Shell

  2. Clone o repositório de amostra:

    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. Defina as variáveis de ambiente padrão:

    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
    

    Substitua:

    • PROJECT_ID: o Google Cloud ID do projeto.
    • CLUSTER_VERSION: a versão do GKE a ser usada. Precisa ser 1.30.1 ou mais recente.
    • HUGGING_FACE_TOKEN: seu token de acesso do Hugging Face.

Criar um cluster com um pool de nós de GPU

É possível disponibilizar um LLM em GPUs L4 com Ray em um cluster do GKE Autopilot ou Standard usando o complemento do Operador do Ray. Recomendamos que você use um cluster do Autopilot para ter uma experiência totalmente gerenciada do Kubernetes. Escolha um cluster Standard se o caso de uso exigir alta escalonabilidade ou se você quiser mais controle sobre a configuração do cluster. Para escolher o modo de operação do GKE mais adequado para suas cargas de trabalho, consulte Escolher um modo de operação do GKE.

Use o Cloud Shell para criar um cluster Autopilot ou Standard:

Autopilot

Crie um cluster Autopilot com o complemento do operador do Ray ativado:

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

Standard

Crie um cluster Standard com o complemento do Operador do Ray ativado:

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

Criar um Secret do Kubernetes para as credenciais do Hugging Face

No Cloud Shell, crie um Secret do Kubernetes assim:

  1. Configure kubectl para se comunicar com o cluster:

    gcloud container clusters get-credentials ${CLUSTER_NAME} --location=${COMPUTE_REGION}
    
  2. Crie um Secret do Kubernetes que contenha o token do Hugging Face:

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

Implantar o modelo LLM

O repositório do GitHub clonado tem um diretório para cada modelo que inclui uma configuração do RayService. A configuração de cada modelo inclui os seguintes componentes:

  • Implantação do Ray Serve: a implantação do Ray Serve, que inclui configuração de recursos e dependências de tempo de execução.
  • Modelo: o ID do modelo do Hugging Face.
  • Cluster do Ray: o cluster do Ray e os recursos necessários para cada componente, incluindo pods principais e de worker.

Gemma 2B IT

  1. Implante o modelo:

    kubectl apply -f gemma-2b-it/
    
  2. Aguarde até que o recurso do RayService esteja pronto:

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

    O resultado será assim:

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

    Nesta saída, status: RUNNING indica que o recurso do RayService está pronto.

  3. Confirme se o GKE criou o Serviço para o aplicativo Ray Serve:

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

    O resultado será assim:

    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. Implante o modelo:

    kubectl apply -f gemma-7b-it/
    
  2. Aguarde até que o recurso do RayService esteja pronto:

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

    O resultado será assim:

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

    Nesta saída, status: RUNNING indica que o recurso do RayService está pronto.

  3. Confirme se o GKE criou o Serviço para o aplicativo Ray Serve:

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

    O resultado será assim:

    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. Implante o modelo:

    kubectl apply -f llama-2-7b/
    
  2. Aguarde até que o recurso do RayService esteja pronto:

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

    O resultado será assim:

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

    Nesta saída, status: RUNNING indica que o recurso do RayService está pronto.

  3. Confirme se o GKE criou o Serviço para o aplicativo Ray Serve:

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

    O resultado será assim:

    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. Implante o modelo:

    kubectl apply -f llama-3-8b/
    
  2. Aguarde até que o recurso do RayService esteja pronto:

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

    O resultado será assim:

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

    Nesta saída, status: RUNNING indica que o recurso do RayService está pronto.

  3. Confirme se o GKE criou o Serviço para o aplicativo Ray Serve:

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

    O resultado será assim:

    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. Implante o modelo:

    kubectl apply -f mistral-7b/
    
  2. Aguarde até que o recurso do RayService esteja pronto:

    kubectl get rayservice mistral-7b -o yaml
    

    O resultado será assim:

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

    Nesta saída, status: RUNNING indica que o recurso do RayService está pronto.

  3. Confirme se o GKE criou o Serviço para o aplicativo Ray Serve:

    kubectl get service mistral-7b-serve-svc
    

    O resultado será assim:

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

Disponibilizar o modelo

Os modelos Llama2 7B e Llama3 8B usam a especificação de chat da API OpenAI. Os outros modelos oferecem suporte apenas à geração de texto, que é uma técnica que gera texto com base em comandos.

Configurar o encaminhamento de portas

Configure o encaminhamento de portas para o servidor de inferência:

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

Interagir com o modelo usando curl

Use o curl para conversar com o modelo:

Gemma 2B IT

Em uma nova sessão do terminal:

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

Em uma nova sessão do terminal:

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

Em uma nova sessão do terminal:

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

Em uma nova sessão do terminal:

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

Em uma nova sessão do terminal:

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}'

Como os modelos que você disponibilizou não retêm nenhum histórico, cada mensagem e resposta precisa ser enviada de volta ao modelo para criar uma experiência de conversa interativa. O exemplo a seguir mostra como criar uma conversa interativa usando o modelo Llama 3 8B:

Crie um diálogo com o modelo usando 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
}'

O resultado será assim:

{
  "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
  }
}

(Opcional) Conectar-se à interface de chat

É possível usar o Gradio para criar aplicativos da Web que permitam interagir com seu modelo. O Gradio é uma biblioteca Python que tem um wrapper ChatInterface que cria interfaces de usuário para chatbots. Para o Llama 2 7B e o Llama 3 7B, você instalou o Gradio ao implantar o modelo de LLM.

  1. Configure o encaminhamento de portas para o Serviço gradio:

    kubectl port-forward service/gradio 8080:8080 &
    
  2. Abra http://localhost:8080 no navegador para conversar com o modelo.

Disponibilizar vários modelos com a multiplexação de modelos

A multiplexação de modelos é uma técnica usada para disponibilizar vários modelos no mesmo cluster do Ray. É possível rotear o tráfego para modelos específicos usando cabeçalhos de solicitação ou balanceamento de carga.

Neste exemplo, você cria um aplicativo multiplexado do Ray Serve com dois modelos: Gemma 7B IT e Llama 3 8B.

  1. Implante o recurso do RayService:

    kubectl apply -f model-multiplexing/
    
  2. Aguarde até que o recurso do RayService esteja pronto:

    kubectl get rayservice model-multiplexing -o yaml
    

    O resultado será assim:

    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
    

    Nesta saída, status: RUNNING indica que o recurso do RayService está pronto.

  3. Confirme se o GKE criou o Serviço do Kubernetes para o aplicativo do Ray Serve:

    kubectl get service model-multiplexing-serve-svc
    

    O resultado será assim:

    NAME                           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
    model-multiplexing-serve-svc   ClusterIP   34.118.226.104   <none>        8000/TCP   45m
    
  4. Configure o encaminhamento de portas para o aplicativo do Ray Serve:

    kubectl port-forward svc/model-multiplexing-serve-svc 8000:8000
    
  5. Envie uma solicitação ao modelo de TI do Gemma 7B:

    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}'
    

    O resultado será assim:

    {"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. Envie uma solicitação para o 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}'
    

    O resultado será assim:

    {"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. Envie uma solicitação para um modelo aleatório excluindo o cabeçalho 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}'
    

    A saída é uma das saídas das etapas anteriores.

Criar vários modelos com a composição de modelos

A composição de modelos é uma técnica usada para compor vários modelos em um único aplicativo. A composição de modelos permite encadear entradas e saídas em vários LLMs e dimensionar seus modelos como um único aplicativo.

Neste exemplo, você cria um aplicativo com dois modelos, o Gemma 7B IT e o Llama 3 8B. O primeiro é o modelo de assistente que responde às perguntas fornecidas no comando. O segundo modelo é o de resumo. A saída do modelo de assistente é encadeada na entrada do modelo de resumo. O resultado final é a versão resumida da resposta do modelo de assistente.

  1. Implante o recurso do RayService:

    kubectl apply -f model-composition/
    
  2. Aguarde até que o recurso do RayService esteja pronto:

    kubectl get rayservice model-composition -o yaml
    

    O resultado será assim:

    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
    

    Nesta saída, status: RUNNING indica que o recurso do RayService está pronto.

  3. Confirme se o GKE criou o Serviço para o aplicativo do Ray Serve:

    kubectl get service model-composition-serve-svc
    

    O resultado será assim:

    NAME                           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
    model-composition-serve-svc    ClusterIP   34.118.226.104   <none>        8000/TCP   45m
    
  4. Envie uma solicitação ao 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. O resultado será assim:

    {"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."]}
    

Excluir o projeto

  1. No console Google Cloud , acesse a página Gerenciar recursos.

    Acessar "Gerenciar recursos"

  2. Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir .
  3. Na caixa de diálogo, digite o ID do projeto e clique em Encerrar para excluí-lo.

Excluir recursos individuais

Se você usou um projeto existente e não quer excluí-lo, exclua os recursos individuais.

  1. Exclua o cluster:

    gcloud container clusters delete rayserve-cluster
    

A seguir