Vista geral
Este guia mostra como publicar grandes modelos de linguagem (GMLs) de última geração, como o DeepSeek-R1 671B ou o Llama 3.1 405B no Google Distributed Cloud (apenas software) em hardware sem sistema operativo com unidades de processamento gráfico (GPUs) em vários nós.
Este guia demonstra como usar tecnologias portáteis de código aberto, como o Kubernetes, o vLLM e a API LeaderWorkerSet (LWS), para implementar e publicar cargas de trabalho de IA/ML em clusters bare metal. O Google Distributed Cloud expande o GKE para utilização num ambiente nas instalações, ao mesmo tempo que oferece as vantagens do controlo detalhado, da escalabilidade, da resiliência, da portabilidade e da rentabilidade do GKE.
Contexto
Esta secção descreve as principais tecnologias usadas neste guia, incluindo os dois MDIs usados como exemplos neste guia: DeepSeek-R1 e Llama 3.1 405B.
DeepSeek-R1
O DeepSeek-R1, um modelo de linguagem (conteúdo extenso) com 671 mil milhões de parâmetros da DeepSeek, foi concebido para inferência lógica, raciocínio matemático e resolução de problemas em tempo real em várias tarefas baseadas em texto. O Google Distributed Cloud processa as exigências computacionais do DeepSeek-R1, suportando as respetivas capacidades com recursos escaláveis, computação distribuída e rede eficiente.
Para saber mais, consulte a documentação do DeepSeek.
Llama 3.1 405B
O Llama 3.1 405B é um modelo de linguagem (conteúdo extenso) da Meta concebido para uma vasta gama de tarefas de processamento de linguagem natural, incluindo geração de texto, tradução e resposta a perguntas. O Google Distributed Cloud oferece a infraestrutura robusta necessária para suportar as necessidades de preparação e publicação distribuídas de modelos desta escala.
Para saber mais, consulte a documentação do Llama.
Serviço Kubernetes gerido do Google Distributed Cloud
O Google Distributed Cloud oferece uma vasta gama de serviços, incluindo o Google Distributed Cloud (apenas software) para bare metal, que é adequado para implementar e gerir cargas de trabalho de IA/AA no seu próprio centro de dados. O Google Distributed Cloud é um serviço Kubernetes gerido que simplifica a implementação, o dimensionamento e a gestão de aplicações contentorizadas. O Google Distributed Cloud fornece a infraestrutura necessária, incluindo recursos escaláveis, computação distribuída e rede eficiente, para processar as exigências computacionais dos MDIs.
Para saber mais sobre os principais conceitos do Kubernetes, consulte o artigo Comece a saber mais sobre o Kubernetes. Para saber mais sobre o Google Distributed Cloud e como ajuda a dimensionar, automatizar e gerir o Kubernetes, consulte a vista geral do Google Distributed Cloud (apenas software) para bare metal.
GPUs
As unidades de processamento gráfico (GPUs) permitem acelerar cargas de trabalho específicas, como a aprendizagem automática e o processamento de dados. O Google Distributed Cloud suporta nós equipados com estas GPUs potentes, o que lhe permite configurar o cluster para um desempenho ideal em tarefas de aprendizagem automática e tratamento de dados. O Google Distributed Cloud 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.
Para saber mais, consulte o artigo Configure e use GPUs NVIDIA.
LeaderWorkerSet (LWS)
O LeaderWorkerSet (LWS) é uma API de implementação do Kubernetes que aborda padrões de implementação comuns de cargas de trabalho de inferência de vários nós de IA/ML. A publicação em vários nós tira partido de vários pods, cada um dos quais potencialmente executado num nó diferente, para processar a carga de trabalho de inferência distribuída. O LWS permite tratar vários pods como um grupo, simplificando a gestão da publicação de modelos distribuídos.
vLLM e publicação em vários anfitriões
Quando publicar MDIs computacionalmente intensos, recomendamos que use o vLLM e execute as cargas de trabalho em GPUs.
O vLLM é uma framework de publicação de LLMs de código aberto altamente otimizada que pode aumentar a taxa de transferência de publicação em GPUs, com funcionalidades como as seguintes:
Implementação do transformador otimizada com PagedAttention
Processamento em lote contínuo para melhorar o débito geral da publicação
Publicação distribuída em várias GPUs
Com MDIs/CEs especialmente intensivos em termos computacionais que não cabem num único nó de GPU, pode usar vários nós de GPU para publicar o modelo. O vLLM suporta a execução de cargas de trabalho em GPUs com duas estratégias:
O paralelismo de tensores divide as multiplicações de matrizes na camada do transformador em várias GPUs. No entanto, esta estratégia requer uma rede rápida devido à comunicação necessária entre as GPUs, o que a torna menos adequada para executar cargas de trabalho em vários nós.
O paralelismo de pipeline divide o modelo por camada ou verticalmente. Esta estratégia não requer uma comunicação constante entre as GPUs, o que a torna uma melhor opção quando executa modelos em vários nós.
Pode usar ambas as estratégias no serviço de vários nós. Por exemplo, quando usar dois nós com oito GPUs H100 cada, pode usar ambas as estratégias:
Paralelismo de pipeline bidirecional para dividir o modelo nos dois nós
Paralelismo de tensores de oito vias para dividir o modelo nas oito GPUs em cada nó
Para saber mais, consulte a documentação do vLLM.
Objetivos
Prepare o seu ambiente com um cluster do Google Distributed Cloud no modo Autopilot ou Standard.
Implemente o vLLM em vários nós no seu cluster.
Use o vLLM para publicar o modelo através do
curl
.
Antes de começar
- Certifique-se de que tem um cluster bare metal com, pelo menos, um conjunto de nós de trabalho que tenha dois nós de trabalho, cada um configurado com oito GPUs NVIDIA H100 de 80 GB.
- Crie uma conta Hugging Face, se ainda não tiver uma.
Aceda ao modelo
Pode usar os modelos Llama 3.1 405B ou DeepSeek-R1.
DeepSeek-R1
Gere um token de acesso
Se ainda não tiver um, gere um novo token da Hugging Face:
Clique em O seu perfil > Definições > Tokens de acesso.
Selecione Novo token.
Especifique um nome à sua escolha e uma função de, pelo menos,
Read
.Selecione Gerar um token.
Llama 3.1 405B
Gere um token de acesso
Se ainda não tiver um, gere um novo token da Hugging Face:
Clique em O seu perfil > Definições > Tokens de acesso.
Selecione Novo token.
Especifique um nome à sua escolha e uma função de, pelo menos,
Read
.Selecione Gerar um token.
Prepare o ambiente
Para configurar o seu ambiente, siga estes passos:
Defina os seguintes parâmetros na estação de trabalho do administrador:
gcloud config set project PROJECT_ID export PROJECT_ID=$(gcloud config get project) export HF_TOKEN=HUGGING_FACE_TOKEN export IMAGE_NAME= gcr.io/PROJECT_ID/vllm-multihost/vllm-multihost:latest
Substitua os seguintes valores:
PROJECT_ID
: o ID do projeto associado ao seu cluster.HUGGING_FACE_TOKEN
: o token do Hugging Face gerado a partir da secção Aceda ao modelo anterior.
Crie um segredo do Kubernetes para as credenciais do Hugging Face
Crie um segredo do Kubernetes que contenha o token do Hugging Face através do seguinte comando:
kubectl create secret generic hf-secret \
--kubeconfig KUBECONFIG \
--from-literal=hf_api_token=${HF_TOKEN} \
--dry-run=client -o yaml | kubectl apply -f -
Substitua KUBECONFIG
pelo caminho do ficheiro kubeconfig para o cluster no qual pretende alojar o MDG.
Crie a sua própria imagem de vários nós do vLLM
Para facilitar a comunicação entre nós para o vLLM, pode usar o Ray. O repositório LeaderWorkerSet fornece um Dockerfile que inclui um script bash para configurar o Ray com o vLLM.
Para criar a sua própria imagem de vários nós de vLLM, tem de: clonar o repositório LeaderWorkerSet, criar uma imagem Docker com o Dockerfile fornecido (que configura o Ray para comunicação entre nós) e, em seguida, enviar essa imagem para o Artifact Registry para implementação no Google Distributed Cloud.
Crie o contentor
Para criar o contentor, siga estes passos:
Clone o repositório LeaderWorkerSet:
git clone https://github.com/kubernetes-sigs/lws.git
Crie a imagem.
cd lws/docs/examples/vllm/build/ && docker build -f Dockerfile.GPU . -t vllm-multihost
Envie a imagem para o Artifact Registry
Para garantir que a sua implementação do Kubernetes pode aceder à imagem, armazene-a no Artifact Registry no seu Google Cloud projeto:
docker image tag vllm-multihost ${IMAGE_NAME}
docker push ${IMAGE_NAME}
Instale o LeaderWorkerSet
Para instalar o LWS, execute o seguinte comando:
kubectl apply --server-side \
--kubeconfig KUBECONFIG \
-f https://github.com/kubernetes-sigs/lws/releases/latest/download/manifests.yaml
Valide se o controlador LeaderWorkerSet está a ser executado no espaço de nomes lws-system
através do seguinte comando:
kubectl get pod -n lws-system --kubeconfig KUBECONFIG
O resultado é semelhante ao seguinte:
NAME READY STATUS RESTARTS AGE
lws-controller-manager-5c4ff67cbd-9jsfc 2/2 Running 0 6d23h
Implemente o servidor de modelos vLLM
Para implementar o servidor do modelo vLLM, siga estes passos:
Crie e aplique o manifesto, consoante o MDG que quer implementar.
DeepSeek-R1
Crie um manifesto YAML,
vllm-deepseek-r1-A3.yaml
, para o servidor do modelo vLLM:apiVersion: leaderworkerset.x-k8s.io/v1 kind: LeaderWorkerSet metadata: name: vllm spec: replicas: 1 leaderWorkerTemplate: size: 2 restartPolicy: RecreateGroupOnPodRestart leaderTemplate: metadata: labels: role: leader spec: nodeSelector: cloud.google.com/gke-accelerator: nvidia-h100-80gb containers: - name: vllm-leader image: IMAGE_NAME env: - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token command: - sh - -c - "/vllm-workspace/ray_init.sh leader --ray_cluster_size=$(LWS_GROUP_SIZE); python3 -m vllm.entrypoints.openai.api_server --port 8080 --model deepseek-ai/DeepSeek-R1 --tensor-parallel-size 8 --pipeline-parallel-size 2 --trust-remote-code --max-model-len 4096" resources: limits: nvidia.com/gpu: "8" ports: - containerPort: 8080 readinessProbe: tcpSocket: port: 8080 initialDelaySeconds: 15 periodSeconds: 10 volumeMounts: - mountPath: /dev/shm name: dshm volumes: - name: dshm emptyDir: medium: Memory sizeLimit: 15Gi workerTemplate: spec: containers: - name: vllm-worker image: IMAGE_NAME command: - sh - -c - "/vllm-workspace/ray_init.sh worker --ray_address=$(LWS_LEADER_ADDRESS)" resources: limits: nvidia.com/gpu: "8" env: - 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 sizeLimit: 15Gi --- apiVersion: v1 kind: Service metadata: name: vllm-leader spec: ports: - name: http port: 8080 protocol: TCP targetPort: 8080 selector: leaderworkerset.sigs.k8s.io/name: vllm role: leader type: ClusterIP
Aplique o manifesto executando o seguinte comando:
kubectl apply -f vllm-deepseek-r1-A3.yaml \ --kubeconfig KUBECONFIG
Llama 3.1 405B
Crie um manifesto YAML,
vllm-llama3-405b-A3.yaml
, para o servidor do modelo vLLM:apiVersion: leaderworkerset.x-k8s.io/v1 kind: LeaderWorkerSet metadata: name: vllm spec: replicas: 1 leaderWorkerTemplate: size: 2 restartPolicy: RecreateGroupOnPodRestart leaderTemplate: metadata: labels: role: leader spec: nodeSelector: cloud.google.com/gke-accelerator: nvidia-h100-80gb containers: - name: vllm-leader image: IMAGE_NAME env: - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token command: - sh - -c - "/vllm-workspace/ray_init.sh leader --ray_cluster_size=$(LWS_GROUP_SIZE); python3 -m vllm.entrypoints.openai.api_server --port 8080 --model meta-llama/Meta-Llama-3.1-405B-Instruct --tensor-parallel-size 8 --pipeline-parallel-size 2" resources: limits: nvidia.com/gpu: "8" ports: - containerPort: 8080 readinessProbe: tcpSocket: port: 8080 initialDelaySeconds: 15 periodSeconds: 10 volumeMounts: - mountPath: /dev/shm name: dshm volumes: - name: dshm emptyDir: medium: Memory sizeLimit: 15Gi workerTemplate: spec: containers: - name: vllm-worker image: IMAGE_NAME command: - sh - -c - "/vllm-workspace/ray_init.sh worker --ray_address=$(LWS_LEADER_ADDRESS)" resources: limits: nvidia.com/gpu: "8" env: - 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 sizeLimit: 15Gi --- apiVersion: v1 kind: Service metadata: name: vllm-leader spec: ports: - name: http port: 8080 protocol: TCP targetPort: 8080 selector: leaderworkerset.sigs.k8s.io/name: vllm role: leader type: ClusterIP
Aplique o manifesto executando o seguinte comando:
kubectl apply -f vllm-llama3-405b-A3.yaml \ --kubeconfig KUBECONFIG
Veja os registos do servidor de modelos em execução com o seguinte comando:
kubectl logs vllm-0 -c vllm-leader \ --kubeconfig KUBECONFIG
O resultado deve ser semelhante ao seguinte:
INFO 08-09 21:01:34 api_server.py:297] Route: /detokenize, Methods: POST INFO 08-09 21:01:34 api_server.py:297] Route: /v1/models, Methods: GET INFO 08-09 21:01:34 api_server.py:297] Route: /version, Methods: GET INFO 08-09 21:01:34 api_server.py:297] Route: /v1/chat/completions, Methods: POST INFO 08-09 21:01:34 api_server.py:297] Route: /v1/completions, Methods: POST INFO 08-09 21:01:34 api_server.py:297] Route: /v1/embeddings, Methods: POST INFO: Started server process [7428] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
Publique o modelo
Configure o encaminhamento de portas para o modelo executando o seguinte comando:
kubectl port-forward svc/vllm-leader 8080:8080 \
--kubeconfig KUBECONFIG
Interaja com o modelo através do curl
Para interagir com o modelo através do curl, siga estas instruções:
DeepSeek-R1
Num novo terminal, envie um pedido para o servidor:
curl http://localhost:8080/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-ai/DeepSeek-R1",
"prompt": "I have four boxes. I put the red box on the bottom and put the blue box on top. Then I put the yellow box on top the blue. Then I take the blue box out and put it on top. And finally I put the green box on the top. Give me the final order of the boxes from bottom to top. Show your reasoning but be brief",
"max_tokens": 1024,
"temperature": 0
}'
O resultado deve ser semelhante ao seguinte:
{
"id": "cmpl-f2222b5589d947419f59f6e9fe24c5bd",
"object": "text_completion",
"created": 1738269669,
"model": "deepseek-ai/DeepSeek-R1",
"choices": [
{
"index": 0,
"text": ".\n\nOkay, let's see. The user has four boxes and is moving them around. Let me try to visualize each step. \n\nFirst, the red box is placed on the bottom. So the stack starts with red. Then the blue box is put on top of red. Now the order is red (bottom), blue. Next, the yellow box is added on top of blue. So now it's red, blue, yellow. \n\nThen the user takes the blue box out. Wait, blue is in the middle. If they remove blue, the stack would be red and yellow. But where do they put the blue box? The instruction says to put it on top. So after removing blue, the stack is red, yellow. Then blue is placed on top, making it red, yellow, blue. \n\nFinally, the green box is added on the top. So the final order should be red (bottom), yellow, blue, green. Let me double-check each step to make sure I didn't mix up any steps. Starting with red, then blue, then yellow. Remove blue from the middle, so yellow is now on top of red. Then place blue on top of that, so red, yellow, blue. Then green on top. Yes, that seems right. The key step is removing the blue box from the middle, which leaves yellow on red, then blue goes back on top, followed by green. So the final order from bottom to top is red, yellow, blue, green.\n\n**Final Answer**\nThe final order from bottom to top is \\boxed{red}, \\boxed{yellow}, \\boxed{blue}, \\boxed{green}.\n</think>\n\n1. Start with the red box at the bottom.\n2. Place the blue box on top of the red box. Order: red (bottom), blue.\n3. Place the yellow box on top of the blue box. Order: red, blue, yellow.\n4. Remove the blue box (from the middle) and place it on top. Order: red, yellow, blue.\n5. Place the green box on top. Final order: red, yellow, blue, green.\n\n\\boxed{red}, \\boxed{yellow}, \\boxed{blue}, \\boxed{green}",
"logprobs": null,
"finish_reason": "stop",
"stop_reason": null,
"prompt_logprobs": null
}
],
"usage": {
"prompt_tokens": 76,
"total_tokens": 544,
"completion_tokens": 468,
"prompt_tokens_details": null
}
}
Llama 3.1 405B
Num novo terminal, envie um pedido para o servidor:
curl http://localhost:8080/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "meta-llama/Meta-Llama-3.1-405B-Instruct",
"prompt": "San Francisco is a",
"max_tokens": 7,
"temperature": 0
}'
O resultado deve ser semelhante ao seguinte:
{"id":"cmpl-0a2310f30ac3454aa7f2c5bb6a292e6c",
"object":"text_completion","created":1723238375,"model":"meta-llama/Meta-Llama-3.1-405B-Instruct","choices":[{"index":0,"text":" top destination for foodies, with","logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":5,"total_tokens":12,"completion_tokens":7}}
O que se segue?
- Saiba mais sobre as GPUs no Google Distributed Cloud.
- Explore o repositório do GitHub do vLLM e a documentação.
- Explore o repositório do GitHub do LWS