Si bien las diversas opciones de entrega de modelos de Vertex AI son suficientes para muchos casos de uso, es posible que debas usar tus propias imágenes de contenedor para entregar modelos en Vertex AI. En este documento, se describe cómo usar una imagen de contenedor personalizada de vLLM para entregar modelos en Vertex AI en CPU, GPU o TPU. Para obtener más información sobre los modelos compatibles con vLLM, consulta la documentación de vLLM.
El servidor de la API de vLLM implementa el protocolo de la API de OpenAI, pero no admite los requisitos de solicitud y respuesta de Vertex AI. Por lo tanto, debes usar una solicitud de inferencia sin procesar de Vertex AI para obtener inferencias de los modelos implementados en Vertex AI con un extremo de predicción. Si deseas obtener más información sobre el método Raw Prediction en el SDK de Vertex AI para Python, consulta la documentación del SDK de Python.
Puedes obtener modelos de Hugging Face y Cloud Storage. Este enfoque ofrece flexibilidad, lo que te permite aprovechar el centro de modelos impulsado por la comunidad (Hugging Face) y las capacidades optimizadas de transferencia de datos y seguridad de Cloud Storage para la administración interna de modelos o versiones ajustadas.
vLLM descarga los modelos de Hugging Face si se proporciona un token de acceso de Hugging Face. De lo contrario, vLLM supone que el modelo está disponible en el disco local. La imagen de contenedor personalizada permite que Vertex AI descargue el modelo desdeGoogle Cloud además de Hugging Face.
Antes de comenzar
En tu proyecto Google Cloud , habilita las APIs de Vertex AI y Artifact Registry.
gcloud services enable aiplatform.googleapis.com \ artifactregistry.googleapis.comConfigura Google Cloud CLI con tu ID del proyecto y, luego, inicializa el SDK de Vertex AI.
PROJECT_ID = "PROJECT_ID" LOCATION = "LOCATION" import vertexai vertexai.init(project=PROJECT_ID, location=LOCATION)gcloud config set project {PROJECT_ID}Crear un repositorio de Docker en Artifact Registry
gcloud artifacts repositories create DOCKER_REPOSITORY \ --repository-format=docker \ --location=LOCATION \ --description="Vertex AI Docker repository"Opcional: Si descargas modelos de Hugging Face, obtén un token de Hugging Face.
- Crea una cuenta de Hugging Face si no tienes una.
- Para los modelos con acceso restringido, como Llama 3.2, solicita y recibe acceso en Hugging Face antes de continuar.
- Genera un token de acceso: Ve a Tu perfil > Configuración > Tokens de acceso.
- Selecciona Token nuevo.
- Especifica un nombre y un rol de al menos Lectura.
- Selecciona Generate un token.
- Guarda este token para los pasos de implementación.
Prepara los archivos de compilación del contenedor
El siguiente Dockerfile compila la imagen de contenedor personalizada de vLLM para GPUs, TPUs y CPUs. Este contenedor personalizado descarga modelos de Hugging Face o Cloud Storage.
ARG BASE_IMAGE
FROM ${BASE_IMAGE}
ENV DEBIAN_FRONTEND=noninteractive
# Install gcloud SDK
RUN apt-get update && \
apt-get install -y apt-utils git apt-transport-https gnupg ca-certificates curl \
&& echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list \
&& curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg \
&& apt-get update -y && apt-get install google-cloud-cli -y \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /workspace/vllm
# Copy entrypoint.sh to the container
COPY ./entrypoint.sh /workspace/vllm/vertexai/entrypoint.sh
RUN chmod +x /workspace/vllm/vertexai/entrypoint.sh
ENTRYPOINT ["/workspace/vllm/vertexai/entrypoint.sh"]
Compila la imagen de contenedor personalizada con Cloud Build. El siguiente archivo de configuración de cloudbuild.yaml muestra cómo compilar la imagen para varias plataformas con el mismo Dockerfile.
steps:
- name: 'gcr.io/cloud-builders/docker'
automapSubstitutions: true
script: |
#!/usr/bin/env bash
set -euo pipefail
device_type_param=${_DEVICE_TYPE}
device_type=${device_type_param,,}
base_image=${_BASE_IMAGE}
image_name="vllm-${_DEVICE_TYPE}"
if [[ $device_type == "cpu" ]]; then
echo "Quietly building open source vLLM CPU container image"
git clone https://github.com/vllm-project/vllm.git
cd vllm && DOCKER_BUILDKIT=1 docker build -t $base_image -f docker/Dockerfile.cpu . -q
cd ..
fi
echo "Quietly building container image for: $device_type"
docker build -t $LOCATION-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/$image_name --build-arg BASE_IMAGE=$base_image . -q
docker push $LOCATION-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/$image_name
substitutions:
_DEVICE_TYPE: gpu
_BASE_IMAGE: vllm/vllm-openai
_REPOSITORY: my-docker-repo
Los archivos están disponibles en el repositorio de GitHub googlecloudplatform/vertex-ai-samples. Clona el repositorio para usarlos:
git clone https://github.com/GoogleCloudPlatform/vertex-ai-samples.git
Compila y envía la imagen del contenedor
Envía el archivo cloudbuild.yaml para compilar la imagen de contenedor personalizada con Cloud Build. Usa sustituciones para especificar el tipo de dispositivo de destino, que puede ser GPU, TPU o CPU, y la imagen base correspondiente.
GPU
DEVICE_TYPE="gpu"
BASE_IMAGE="vllm/vllm-openai"
cd vertex-ai-samples/notebooks/official/prediction/vertexai_serving_vllm/cloud-build && \
gcloud builds submit \
--config=cloudbuild.yaml \
--region=LOCATION \
--timeout="2h" \
--machine-type=e2-highcpu-32 \
--substitutions=_REPOSITORY=DOCKER_REPOSITORY,_DEVICE_TYPE=$DEVICE_TYPE,_BASE_IMAGE=$BASE_IMAGE
TPU
DEVICE_TYPE="tpu"
BASE_IMAGE="vllm/vllm-tpu:nightly"
cd vertex-ai-samples/notebooks/official/prediction/vertexai_serving_vllm/cloud-build && \
gcloud builds submit \
--config=cloudbuild.yaml \
--region=LOCATION \
--timeout="2h" \
--machine-type=e2-highcpu-32 \
--substitutions=_REPOSITORY=DOCKER_REPOSITORY,_DEVICE_TYPE=$DEVICE_TYPE,_BASE_IMAGE=$BASE_IMAGE
CPU
DEVICE_TYPE="cpu"
BASE_IMAGE="vllm-cpu-base"
cd vertex-ai-samples/notebooks/official/prediction/vertexai_serving_vllm/cloud-build && \
gcloud builds submit \
--config=cloudbuild.yaml \
--region=LOCATION \
--timeout="2h" \
--machine-type=e2-highcpu-32 \
--substitutions=_REPOSITORY=DOCKER_REPOSITORY,_DEVICE_TYPE=$DEVICE_TYPE,_BASE_IMAGE=$BASE_IMAGE
Una vez que finalice la compilación, configura Docker para que se autentique con Artifact Registry:
gcloud auth configure-docker LOCATION-docker.pkg.dev --quiet
Sube el modelo a Model Registry y, luego, impleméntalo
Para subir tu modelo a Vertex AI Model Registry, crear un extremo y, luego, implementar el modelo, completa estos pasos. En este ejemplo, se usa Llama 3.2 3B, pero puedes adaptarlo para otros modelos.
Define las variables del modelo y la implementación. Configura la variable
DOCKER_URIen la imagen que compilaste en el paso anterior (por ejemplo, para la GPU):DOCKER_URI = f"LOCATION-docker.pkg.dev/PROJECT_ID/DOCKER_REPOSITORY/vllm-gpu"Define variables para el token de Hugging Face y las propiedades del modelo. Por ejemplo, para la implementación de GPU, haz lo siguiente:
hf_token = "your-hugging-face-auth-token" model_name = "gpu-llama3_2_3B-serve-vllm" model_id = "meta-llama/Llama-3.2-3B" machine_type = "g2-standard-8" accelerator_type = "NVIDIA_L4" accelerator_count = 1Sube el modelo a Model Registry. La función
upload_modelvaría ligeramente según el tipo de dispositivo debido a los diferentes argumentos de vLLM y variables de entorno.from google.cloud import aiplatform def upload_model_gpu(model_name, model_id, hf_token, accelerator_count, docker_uri): vllm_args = [ "python3", "-m", "vllm.entrypoints.openai.api_server", "--host=0.0.0.0", "--port=8080", f"--model={model_id}", "--max-model-len=2048", "--gpu-memory-utilization=0.9", "--enable-prefix-caching", f"--tensor-parallel-size={accelerator_count}", ] env_vars = { "HF_TOKEN": hf_token, "LD_LIBRARY_PATH": "$LD_LIBRARY_PATH:/usr/local/nvidia/lib64", } model = aiplatform.Model.upload( display_name=model_name, serving_container_image_uri=docker_uri, serving_container_args=vllm_args, serving_container_ports=[8080], serving_container_predict_route="/v1/completions", serving_container_health_route="/health", serving_container_environment_variables=env_vars, serving_container_shared_memory_size_mb=(16 * 1024), # 16 GB serving_container_deployment_timeout=1800, ) return model def upload_model_tpu(model_name, model_id, hf_token, tpu_count, docker_uri): vllm_args = [ "python3", "-m", "vllm.entrypoints.openai.api_server", "--host=0.0.0.0", "--port=8080", f"--model={model_id}", "--max-model-len=2048", "--enable-prefix-caching", f"--tensor-parallel-size={tpu_count}", ] env_vars = {"HF_TOKEN": hf_token} model = aiplatform.Model.upload( display_name=model_name, serving_container_image_uri=docker_uri, serving_container_args=vllm_args, serving_container_ports=[8080], serving_container_predict_route="/v1/completions", serving_container_health_route="/health", serving_container_environment_variables=env_vars, serving_container_shared_memory_size_mb=(16 * 1024), # 16 GB serving_container_deployment_timeout=1800, ) return model def upload_model_cpu(model_name, model_id, hf_token, docker_uri): vllm_args = [ "python3", "-m", "vllm.entrypoints.openai.api_server", "--host=0.0.0.0", "--port=8080", f"--model={model_id}", "--max-model-len=2048", ] env_vars = {"HF_TOKEN": hf_token} model = aiplatform.Model.upload( display_name=model_name, serving_container_image_uri=docker_uri, serving_container_args=vllm_args, serving_container_ports=[8080], serving_container_predict_route="/v1/completions", serving_container_health_route="/health", serving_container_environment_variables=env_vars, serving_container_shared_memory_size_mb=(16 * 1024), # 16 GB serving_container_deployment_timeout=1800, ) return model # Example for GPU: vertexai_model = upload_model_gpu(model_name, model_id, hf_token, accelerator_count, DOCKER_URI)Crear un extremo.
endpoint = aiplatform.Endpoint.create(display_name=f"model_name-endpoint")Implementa el modelo en el extremo. La implementación del modelo puede tardar entre 20 y 30 minutos.
# Example for GPU: vertexai_model.deploy( endpoint=endpoint, deployed_model_display_name=model_name, machine_type=machine_type, accelerator_type=accelerator_type, accelerator_count=accelerator_count, traffic_percentage=100, deploy_request_timeout=1800, min_replica_count=1, max_replica_count=4, autoscaling_target_accelerator_duty_cycle=60, )En el caso de las TPU, omite los parámetros
accelerator_typeyaccelerator_count, y usaautoscaling_target_request_count_per_minute=60. En el caso de las CPU, omite los parámetrosaccelerator_typeyaccelerator_count, y usaautoscaling_target_cpu_utilization=60.
Carga modelos desde Cloud Storage
El contenedor personalizado descarga el modelo desde una ubicación de Cloud Storage en lugar de descargarlo desde Hugging Face. Cuando usas Cloud Storage, ocurre lo siguiente:
- Configura el parámetro
model_iden la funciónupload_modelcomo un URI de Cloud Storage, por ejemplo,gs://<var>my-bucket</var>/<var>my-models</var>/<var>llama_3_2_3B</var>. - Omitir la variable
HF_TOKENdeenv_varscuando llames aupload_model - Cuando llamas a
model.deploy, especifica unservice_accountque tenga permisos para leer desde el bucket de Cloud Storage.
Crea una cuenta de servicio de IAM para acceder a Cloud Storage
Si tu modelo está en Cloud Storage, crea una cuenta de servicio que los extremos de Vertex Prediction puedan usar para acceder a los artefactos del modelo.
SERVICE_ACCOUNT_NAME = "vertexai-endpoint-sa"
SERVICE_ACCOUNT_EMAIL = f"SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com"
gcloud iam service-accounts create SERVICE_ACCOUNT_NAME \
--display-name="Vertex AI Endpoint Service Account"
# Grant storage read permission
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:SERVICE_ACCOUNT_EMAIL" \
--role="roles/storage.objectViewer"
Cuando realices la implementación, pasa el correo electrónico de la cuenta de servicio al método deploy:
service_account=<var>SERVICE_ACCOUNT_EMAIL</var>.
Obtén predicciones con el extremo
Después de implementar correctamente el modelo en el extremo, verifica la respuesta del modelo con raw_predict.
import json
PROMPT = "Distance of moon from earth is "
request_body = json.dumps(
{
"prompt": PROMPT,
"temperature": 0.0,
},
)
raw_response = endpoint.raw_predict(
body=request_body, headers={"Content-Type": "application/json"}
)
assert raw_response.status_code == 200
result = json.loads(raw_response.text)
for choice in result["choices"]:
print(choice)
Resultado de ejemplo:
{
"index": 0,
"text": "384,400 km. The moon is 1/4 of the earth's",
"logprobs": null,
"finish_reason": "length",
"stop_reason": null,
"prompt_logprobs": null
}
¿Qué sigue?
- Elige una opción de servicio de modelos abiertos
- Usa modelos abiertos con el modelo como servicio (MaaS)
- Implementa modelos abiertos desde Model Garden
- Implementa modelos abiertos con contenedores compilados previamente