Men-deploy model terbuka dengan container vLLM kustom

Meskipun berbagai opsi penayangan model Vertex AI sudah cukup untuk banyak kasus penggunaan, Anda mungkin perlu menggunakan image container Anda sendiri untuk menayangkan model di Vertex AI. Dokumen ini menjelaskan cara menggunakan image container kustom vLLM untuk menayangkan model di Vertex AI pada CPU, GPU, atau TPU. Untuk mengetahui informasi selengkapnya tentang model yang didukung vLLM, lihat dokumentasi vLLM.

Server vLLM API menerapkan protokol OpenAI API, tetapi tidak mendukung persyaratan permintaan dan respons Vertex AI. Oleh karena itu, Anda harus menggunakan Permintaan Inferensi Mentah Vertex AI untuk mendapatkan inferensi dari model yang di-deploy ke Vertex AI menggunakan Endpoint Prediksi. Untuk mengetahui informasi selengkapnya tentang metode Prediksi Mentah di Vertex AI Python SDK, lihat dokumentasi Python SDK.

Anda dapat mengambil model dari Hugging Face dan Cloud Storage. Pendekatan ini menawarkan fleksibilitas, yang memungkinkan Anda memanfaatkan hub model berbasis komunitas (Hugging Face) serta kemampuan transfer data dan keamanan yang dioptimalkan dari Cloud Storage untuk pengelolaan model internal atau versi yang di-fine-tune.

vLLM mendownload model dari Hugging Face jika token akses Hugging Face diberikan. Jika tidak, vLLM mengasumsikan model tersedia di disk lokal. Image container kustom memungkinkan Vertex AI mendownload model dari Google Cloud selain Hugging Face.

Sebelum memulai

  1. Di project Google Cloud Anda, aktifkan Vertex AI dan Artifact Registry API.

    gcloud services enable aiplatform.googleapis.com \
        artifactregistry.googleapis.com
    
  2. Konfigurasi Google Cloud CLI dengan project ID Anda dan lakukan inisialisasi Vertex AI SDK.

    PROJECT_ID = "PROJECT_ID"
    LOCATION = "LOCATION"
    import vertexai
    vertexai.init(project=PROJECT_ID, location=LOCATION)
    
    gcloud config set project {PROJECT_ID}
    
  3. Buat repositori Docker di Artifact Registry.

    gcloud artifacts repositories create DOCKER_REPOSITORY \
        --repository-format=docker \
        --location=LOCATION \
        --description="Vertex AI Docker repository"
    
  4. Opsional: Jika mendownload model dari Hugging Face, dapatkan token Hugging Face.

    1. Buat akun Hugging Face jika Anda belum memilikinya.
    2. Untuk model yang dibatasi seperti Llama 3.2, minta dan dapatkan akses di Hugging Face sebelum melanjutkan.
    3. Buat token akses: Buka Profil Anda > Setelan > Token Akses.
    4. Pilih New Token.
    5. Tentukan nama dan peran minimal Baca.
    6. Pilih Generate a token.
    7. Simpan token ini untuk langkah-langkah deployment.

Menyiapkan file build container

Dockerfile berikut membangun image container kustom vLLM untuk GPU, TPU, dan CPU. Container kustom ini mendownload model dari Hugging Face atau 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"]

Bangun image container kustom menggunakan Cloud Build. File konfigurasi cloudbuild.yaml berikut menunjukkan cara membuat image untuk beberapa platform menggunakan Dockerfile yang sama.

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

File tersedia di repositori GitHub googlecloudplatform/vertex-ai-samples. Buat clone repositori untuk menggunakannya:

git clone https://github.com/GoogleCloudPlatform/vertex-ai-samples.git

Buat dan kirim image container

Bangun image container kustom menggunakan Cloud Build dengan mengirimkan file cloudbuild.yaml. Gunakan penggantian untuk menentukan jenis perangkat target, yang dapat berupa GPU, TPU, atau CPU, dan image dasar yang sesuai.

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

Setelah build selesai, konfigurasi Docker untuk melakukan autentikasi dengan Artifact Registry:

gcloud auth configure-docker LOCATION-docker.pkg.dev --quiet

Mengupload model ke Model Registry dan men-deploy

Upload model Anda ke Vertex AI Model Registry, buat endpoint, dan deploy model dengan menyelesaikan langkah-langkah berikut. Contoh ini menggunakan Llama 3.2 3B, tetapi Anda dapat menyesuaikannya untuk model lain.

  1. Tentukan variabel model dan deployment. Tetapkan variabel DOCKER_URI ke image yang Anda buat pada langkah sebelumnya (misalnya, untuk GPU):

    DOCKER_URI = f"LOCATION-docker.pkg.dev/PROJECT_ID/DOCKER_REPOSITORY/vllm-gpu"
    

    Tentukan variabel untuk token Hugging Face dan properti model. Misalnya, untuk deployment GPU:

    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 = 1
    
  2. Mengupload model ke Model Registry. Fungsi upload_model berbeda sedikit bergantung pada jenis perangkat karena perbedaan argumen vLLM dan variabel lingkungan.

    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)
    
  3. Buat endpoint

    endpoint = aiplatform.Endpoint.create(display_name=f"model_name-endpoint")
    
  4. Deploy model ke endpoint. Deployment model mungkin memerlukan waktu 20 hingga 30 menit.

    # 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,
    )
    

    Untuk TPU, hapus parameter accelerator_type dan accelerator_count, lalu gunakan autoscaling_target_request_count_per_minute=60. Untuk CPU, hapus parameter accelerator_type dan accelerator_count, lalu gunakan autoscaling_target_cpu_utilization=60.

Memuat model dari Cloud Storage

Container kustom mendownload model dari lokasi Cloud Storage, bukan mendownloadnya dari Hugging Face. Saat Anda menggunakan Cloud Storage:

  • Tetapkan parameter model_id dalam fungsi upload_model ke Cloud Storage URI, misalnya, gs://<var>my-bucket</var>/<var>my-models</var>/<var>llama_3_2_3B</var>.
  • Hilangkan variabel HF_TOKEN dari env_vars saat Anda memanggil upload_model.
  • Saat memanggil model.deploy, tentukan service_account yang memiliki izin untuk membaca dari bucket Cloud Storage.

Membuat Akun Layanan IAM untuk akses Cloud Storage

Jika model Anda berada di Cloud Storage, buat akun layanan yang dapat digunakan endpoint Vertex Prediction untuk mengakses artefak model.

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"

Saat men-deploy, teruskan email akun layanan ke metode deploy: service_account=<var>SERVICE_ACCOUNT_EMAIL</var>.

Mendapatkan prediksi menggunakan endpoint

Setelah berhasil men-deploy model ke endpoint, verifikasi respons model menggunakan 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)

Contoh output:

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

Langkah berikutnya