Ajuste os modelos abertos Gemma com várias GPUs no GKE

Este tutorial mostra como otimizar o modelo de linguagem (conteúdo extenso) (MDI/CE) Gemma, uma família de modelos abertos, usando unidades de processamento gráfico (GPUs) no Google Kubernetes Engine (GKE) com a biblioteca Transformers da Hugging Face. O ajuste fino é um processo de aprendizagem supervisionada que melhora a capacidade de um modelo pré-treinado para realizar tarefas específicas atualizando os respetivos parâmetros com um novo conjunto de dados. Neste tutorial, vai transferir os modelos da família Gemma pré-treinados de 2 mil milhões de parâmetros do Hugging Face e ajustá-los num cluster do GKE Autopilot ou Standard.

Este guia é um bom ponto de partida se precisar do controlo detalhado, da escalabilidade, da resiliência, da portabilidade e da rentabilidade do Kubernetes gerido ao ajustar um MDG.

Prática recomendada:

Experimente a nossa solução Vertex AI se precisar de uma plataforma de IA gerida unificada para criar e apresentar rapidamente modelos de ML de forma económica.

Contexto

Ao publicar o Gemma com GPUs no GKE com a biblioteca de transformadores, pode implementar uma solução de publicação de inferência robusta e pronta para produção com todas as vantagens do Kubernetes gerido, incluindo escalabilidade eficiente e maior disponibilidade. Esta secção descreve as principais tecnologias usadas neste guia.

Gemma

O Gemma é um conjunto de modelos de inteligência artificial (IA) generativa leves e disponíveis abertamente, lançados ao abrigo de uma licença aberta. Estes modelos de IA estão disponíveis para execução nas suas aplicações, hardware, dispositivos móveis ou serviços alojados.

Neste guia, apresentamos o Gemma para a geração de texto. Também pode ajustar estes modelos para se especializarem na realização de tarefas específicas.

O conjunto de dados que usa neste documento é b-mc2/sql-create-context.

Para saber mais, consulte a documentação do Gemma.

GPUs

As GPUs permitem-lhe acelerar cargas de trabalho específicas executadas nos seus nós, como a aprendizagem automática e o processamento de dados. O GKE oferece uma variedade de opções de tipos de máquinas para a configuração de nós, incluindo tipos de máquinas com GPUs NVIDIA H100, L4 e A100.

Antes de usar GPUs no GKE, considere concluir o seguinte percurso de aprendizagem:

  1. Saiba mais sobre a disponibilidade da versão atual da GPU
  2. Saiba mais sobre as GPUs no GKE

Transformadores do Hugging Face

Com a biblioteca Transformers da Hugging Face, pode aceder a modelos pré-treinados de vanguarda. A biblioteca Transformers permite-lhe reduzir o tempo, os recursos e os custos computacionais associados à preparação completa do modelo.

Neste tutorial, vai usar as APIs e as ferramentas da Hugging Face para transferir e otimizar estes modelos pré-preparados.

Aceda ao modelo

Para aceder aos modelos Gemma para implementação no GKE, primeiro tem de assinar o contrato de consentimento de licença e, em seguida, gerar um token de acesso do Hugging Face.

Tem de assinar o contrato de consentimento para usar o Gemma. Siga estas instruções:

  1. Aceda à página de consentimento do modelo em Kaggle.com.
  2. Valide o consentimento através da sua conta do Hugging Face.
  3. Aceite os termos do modelo.

Gere um token de acesso

Para aceder ao modelo através do Hugging Face, precisa de um token do Hugging Face.

Siga estes passos para gerar um novo token se ainda não tiver um:

  1. Clique em O seu perfil > Definições > Tokens de acesso.
  2. Selecione Novo token.
  3. Especifique um nome à sua escolha e uma função de, pelo menos, Write.
  4. Selecione Gerar um token.
  5. Copie o token gerado para a área de transferência.

Prepare o seu ambiente

Neste tutorial, vai usar o Cloud Shell para gerir recursos alojados no Google Cloud. O Cloud Shell vem pré-instalado com o software de que precisa para este tutorial, incluindo o kubectl e a CLI gcloud.

Para configurar o seu ambiente com o Cloud Shell, siga estes passos:

  1. Na Google Cloud consola, inicie uma sessão do Cloud Shell clicando em Ícone de ativação do Cloud Shell Ativar Cloud Shell na Google Cloud consola. Esta ação inicia uma sessão no painel inferior da consola. Google Cloud

  2. Defina as variáveis de ambiente predefinidas:

    gcloud config set project PROJECT_ID
    export PROJECT_ID=$(gcloud config get project)
    export CONTROL_PLANE_LOCATION=CONTROL_PLANE_LOCATION
    export CLUSTER_NAME=CLUSTER_NAME
    export HF_TOKEN=HF_TOKEN
    export HF_PROFILE=HF_PROFILE
    

    Substitua os seguintes valores:

    • PROJECT_ID: o seu Google Cloud ID do projeto.
    • CONTROL_PLANE_LOCATION: a região do Compute Engine do plano de controlo do seu cluster. Indique uma região que suporte o tipo de acelerador que quer usar, por exemplo, us-central1 para GPUs L4.
    • CLUSTER_NAME: o nome do cluster.
    • HF_TOKEN: o token do Hugging Face que gerou anteriormente.
    • HF_PROFILE: o ID do perfil do Hugging Face que criou anteriormente.
  3. Clone o repositório de código de exemplo do GitHub:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    cd kubernetes-engine-samples/ai-ml/llm-finetuning-gemma
    

Crie e configure Google Cloud recursos

Siga estas instruções para criar os recursos necessários.

Crie um cluster e um node pool do GKE

Pode publicar o Gemma em GPUs num cluster do GKE Autopilot ou Standard. Para escolher o modo de funcionamento do GKE mais adequado às suas cargas de trabalho, consulte o artigo Escolha um modo de funcionamento do GKE.

Prática recomendada:

Use o Autopilot para uma experiência do Kubernetes totalmente gerida.

Piloto automático

No Cloud Shell, execute o seguinte comando:

gcloud container clusters create-auto CLUSTER_NAME \
    --project=PROJECT_ID \
    --location=CONTROL_PLANE_LOCATION \
    --release-channel=rapid \
    --cluster-version=1.29

Substitua os seguintes valores:

  • PROJECT_ID: o seu Google Cloud ID do projeto.
  • CONTROL_PLANE_LOCATION: a região do Compute Engine do plano de controlo do seu cluster. Indique uma região que suporte o tipo de acelerador que quer usar, por exemplo, us-central1 para GPUs L4.
  • CLUSTER_NAME: o nome do cluster.

O GKE cria um cluster do Autopilot com nós de CPU e GPU, conforme solicitado pelas cargas de trabalho implementadas.

Standard

  1. No Cloud Shell, execute o seguinte comando para criar um cluster Standard:

    gcloud container clusters create CLUSTER_NAME \
        --project=PROJECT_ID \
        --location=CONTROL_PLANE_LOCATION \
        --workload-pool=PROJECT_ID.svc.id.goog \
        --release-channel=rapid \
        --num-nodes=1
    

    Substitua os seguintes valores:

    • PROJECT_ID: o seu Google Cloud ID do projeto.
    • CONTROL_PLANE_LOCATION: a região do Compute Engine do plano de controlo do seu cluster. Indique uma região que suporte o tipo de acelerador que quer usar, por exemplo, us-central1 para GPUs L4.
    • CLUSTER_NAME: o nome do cluster.

    A criação do cluster pode demorar vários minutos.

  2. Execute o seguinte comando para criar um node pool para o cluster:

    gcloud container node-pools create gpupool \
        --accelerator type=nvidia-l4,count=8,gpu-driver-version=latest \
        --project=PROJECT_ID \
        --location=CONTROL_PLANE_LOCATION \
        --node-locations=CONTROL_PLANE_LOCATION-a \
        --cluster=CLUSTER_NAME \
        --machine-type=g2-standard-96 \
        --num-nodes=1
    

    O GKE cria um único node pool que contém duas GPUs L4 para cada nó.

Crie um segredo do Kubernetes para as credenciais do Hugging Face

No Cloud Shell, faça o seguinte:

  1. Configure kubectl para comunicar com o cluster:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION
    

    Substitua os seguintes valores:

    • CONTROL_PLANE_LOCATION: a região do Compute Engine do plano de controlo do cluster.
    • CLUSTER_NAME: o nome do cluster.
  2. Crie um segredo 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 -
    

    Substitua $HF_TOKEN pelo token do Hugging Face que gerou anteriormente ou use a variável de ambiente, se a tiver definido.

Crie um contentor de ajuste com o Docker e o Cloud Build

Este contentor usa o código PyTorch e Hugging Face Transformers para otimizar o modelo Gemma pré-preparado existente.

  1. Crie um repositório Docker do Artifact Registry:

    gcloud artifacts repositories create gemma \
        --project=PROJECT_ID \
        --repository-format=docker \
        --location=us \
        --description="Gemma Repo"
    

    Substitua PROJECT_ID pelo seu Google Cloud ID do projeto.

  2. Crie e envie a imagem:

    gcloud builds submit .
    
  3. Exporte o IMAGE_URL para utilização posterior neste tutorial.

    export IMAGE_URL=us-docker.pkg.dev/PROJECT_ID/gemma/finetune-gemma-gpu:1.0.0
    

Execute uma tarefa de ajuste preciso no GKE

Nesta secção, implementa a tarefa de ajuste fino do Gemma. Um controlador de tarefas no Kubernetes cria um ou mais pods e garante que executam com êxito uma tarefa específica.

  1. Abra o ficheiro finetune.yaml.

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: finetune-job
      namespace: default
    spec:
      backoffLimit: 2
      template:
        metadata:
          annotations:
            kubectl.kubernetes.io/default-container: finetuner
        spec:
          terminationGracePeriodSeconds: 600
          containers:
          - name: finetuner
            image: $IMAGE_URL
            resources:
              limits:
                nvidia.com/gpu: "8"
            env:
            - name: MODEL_NAME
              value: "google/gemma-2b"
            - name: NEW_MODEL
              value: "gemma-2b-sql-finetuned"
            - name: LORA_R
              value: "8"
            - name: LORA_ALPHA
              value: "16"
            - name: TRAIN_BATCH_SIZE
              value: "1"
            - name: EVAL_BATCH_SIZE
              value: "2"
            - name: GRADIENT_ACCUMULATION_STEPS
              value: "2"
            - name: DATASET_LIMIT
              value: "1000"
            - name: MAX_SEQ_LENGTH
              value: "512"
            - name: LOGGING_STEPS
              value: "5"
            - name: HF_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_api_token
            volumeMounts:
            - mountPath: /dev/shm
              name: dshm
          volumes:
          - name: dshm
            emptyDir:
              medium: Memory
          nodeSelector:
            cloud.google.com/gke-accelerator: nvidia-l4
          restartPolicy: OnFailure
  2. Aplique o manifesto para criar a tarefa de ajuste fino:

    envsubst < finetune.yaml | kubectl apply -f -
    

    Esta instrução substitui o IMAGE_URL pela variável no manifesto.

  3. Monitorize a tarefa executando o seguinte comando:

    watch kubectl get pods
    
  4. Verifique os registos da tarefa executando o seguinte comando:

    kubectl logs job.batch/finetune-job -f
    

    O recurso Job transfere os dados do modelo e, em seguida, otimiza o modelo em todas as oito GPUs. Este processo pode demorar até 20 minutos.

  5. Após a conclusão da tarefa, aceda à sua conta do Hugging Face. É apresentado um novo modelo com o nome HF_PROFILE/gemma-2b-sql-finetuned no seu perfil do Hugging Face.

Publique o modelo otimizado no GKE

Nesta secção, implementa o contentor vLLM para publicar o modelo Gemma. Este tutorial usa uma implementação do Kubernetes para implementar o contentor vLLM. Uma implementação é um objeto da API Kubernetes que lhe permite executar várias réplicas de pods distribuídas entre os nós num cluster.

  1. Crie o seguinte manifesto serve-gemma.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: vllm-gemma-deployment
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: gemma-server
      template:
        metadata:
          labels:
            app: gemma-server
            ai.gke.io/model: gemma-2b
            ai.gke.io/inference-server: vllm
            examples.ai.gke.io/source: user-guide
        spec:
          containers:
          - name: inference-server
            image: docker.io/vllm/vllm-openai:v0.10.0
            resources:
              requests:
                cpu: "2"
                memory: "7Gi"
                ephemeral-storage: "10Gi"
                nvidia.com/gpu: 1
              limits:
                cpu: "2"
                memory: "7Gi"
                ephemeral-storage: "10Gi"
                nvidia.com/gpu: 1
            command: ["python3", "-m", "vllm.entrypoints.openai.api_server"]
            args:
            - --model=$(MODEL_ID)
            - --tensor-parallel-size=1
            env:
            - name: LD_LIBRARY_PATH
              value: ${LD_LIBRARY_PATH}:/usr/local/nvidia/lib64
            - name: MODEL_ID
              value: google/gemma-2b
            - name: HUGGING_FACE_HUB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_api_token
            volumeMounts:
            - mountPath: /dev/shm
              name: dshm
          volumes:
          - name: dshm
            emptyDir:
                medium: Memory
          nodeSelector:
            cloud.google.com/gke-accelerator: nvidia-l4
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: llm-service
    spec:
      selector:
        app: gemma-server
      type: ClusterIP
      ports:
        - protocol: TCP
          port: 8000
          targetPort: 8000
  2. Crie a variável de ambiente para o novo MODEL_ID:

    export MODEL_ID=HF_PROFILE/gemma-2b-sql-finetuned
    

    Substitua HF_PROFILE pelo ID do perfil do Hugging Face que criou anteriormente.

  3. Substitua MODEL_ID no manifesto:

    sed -i "s|google/gemma-2b|$MODEL_ID|g" serve-gemma.yaml
    
  4. Aplique o manifesto:

    kubectl apply -f serve-gemma.yaml
    

    Um pod no cluster transfere os pesos do modelo do Hugging Face e inicia o motor de publicação.

  5. Aguarde até que a implementação esteja disponível:

    kubectl wait --for=condition=Available --timeout=700s deployment/vllm-gemma-deployment
    
  6. Veja os registos da implementação em execução:

    kubectl logs -f -l app=gemma-server
    

O recurso de implementação transfere os dados do modelo. Este processo pode demorar alguns minutos. O resultado é semelhante ao seguinte:

INFO 01-26 19:02:54 model_runner.py:689] Graph capturing finished in 4 secs.
INFO:     Started server process [1]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

Certifique-se de que o modelo é totalmente transferido antes de avançar para a secção seguinte.

Publique o modelo

Nesta secção, interage com o modelo.

Configure o encaminhamento de portas

Assim que o modelo for implementado, execute o seguinte comando para configurar o encaminhamento de porta para o modelo:

kubectl port-forward service/llm-service 8000:8000

O resultado é semelhante ao seguinte:

Forwarding from 127.0.0.1:8000 -> 8000

Interaja com o modelo através do curl

Numa nova sessão de terminal, use curl para conversar com o seu modelo:

O comando de exemplo seguinte destina-se ao TGI:

USER_PROMPT="Question: What is the total number of attendees with age over 30 at kubecon eu? Context: CREATE TABLE attendees (name VARCHAR, age INTEGER, kubecon VARCHAR)"

curl -X POST http://localhost:8000/generate \
  -H "Content-Type: application/json" \
  -d @- <<EOF
{
    "prompt": "${USER_PROMPT}",
    "temperature": 0.1,
    "top_p": 1.0,
    "max_tokens": 24
}
EOF

A saída seguinte mostra um exemplo da resposta do modelo:

{"generated_text":" Answer: SELECT COUNT(age) FROM attendees WHERE age > 30 AND kubecon = 'eu'\n"}

Consoante a sua consulta, pode ter de alterar o max_token para obter um melhor resultado. Também pode usar o modelo ajustado por instruções para uma melhor experiência de chat.