多くのユースケースでは、さまざまな Gemini Enterprise Agent Platform モデル サービング オプションが利用できますが、Gemini Enterprise Agent Platform でモデルをサービングするために独自のコンテナ イメージの使用が必要になる場合があります。このドキュメントでは、vLLM カスタム コンテナ イメージを使用して、CPU、GPU、TPU で Gemini Enterprise Agent Platform のモデルをサービングする方法について説明します。 vLLM でサポートされているモデルの詳細については、vLLM ドキュメントをご覧ください。
vLLM API サーバーは OpenAI API プロトコルを実装していますが、Gemini Enterprise Agent Platform のリクエストとレスポンスの要件はサポートしていません。したがって、 予測 エンドポイントを使用して Gemini Enterprise Agent Platform にデプロイされたモデルから推論を取得するには、 Gemini Enterprise Agent Platform 未加工の推論 リクエスト を使用する必要があります。Gemini Enterprise Agent Platform Python SDK の Raw Prediction メソッドの詳細については、 Python SDK のドキュメントをご覧ください。
Hugging Face と Cloud Storage の両方からモデルを取得できます。このアプローチは柔軟性が高く、コミュニティ主導のモデルハブ(Hugging Face)を利用できるだけでなく、内部モデル管理またはファインチューニング バージョンに Cloud Storage の最適化されたデータ転送機能とセキュリティ機能を活用できます。
Hugging Face アクセス トークンが指定されている場合、vLLM は Hugging Face からモデルをダウンロードします。それ以外の場合、vLLM はモデルがローカル ディスクで使用可能であると想定します。 カスタム コンテナ イメージを使用すると、Gemini Enterprise Agent Platform は Hugging Face に加えて Google Cloud からモデルをダウンロードできます。
始める前に
プロジェクトで、Gemini Enterprise Agent Platform API と Artifact Registry API を有効にします。 Google Cloud
gcloud services enable aiplatform.googleapis.com \ artifactregistry.googleapis.comプロジェクト ID を使用して Google Cloud CLI を構成し、Vertex AI SDK を初期化します。
PROJECT_ID = "PROJECT_ID" LOCATION = "LOCATION" import vertexai vertexai.init(project=PROJECT_ID, location=LOCATION)gcloud config set project {PROJECT_ID}Artifact Registry で Docker リポジトリを作成します。
gcloud artifacts repositories create DOCKER_REPOSITORY \ --repository-format=docker \ --location=LOCATION \ --description="Agent Platform Docker repository"省略可: Hugging Face からモデルをダウンロードする場合は、Hugging Face トークンを取得します。
- Hugging Face アカウントを作成します(まだ作成していない場合)。
- Llama 3.2 などのゲート付きモデルの場合は、続行する前に Hugging Face でアクセス権をリクエストして取得します。
- アクセス トークンを生成します。[Your Profile] > [Settings] > [Access Tokens] の順に移動します。
- [New Token] を選択します。
- 名前と、少なくとも Read ロールを指定します。
- [Generate a token] を選択します。
- このトークンはデプロイ手順で使用します。
コンテナ ビルドファイルを準備する
次の Dockerfile は、GPU、TPU、CPU 用の vLLM カスタム コンテナ イメージをビルドします。このカスタム コンテナは、Hugging Face または 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"]
Cloud Build を使用してカスタム コンテナ イメージをビルドします。次の cloudbuild.yaml 構成ファイルは、同じ 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
ファイルは googlecloudplatform/vertex-ai-samples GitHub リポジトリで入手できます。リポジトリのクローンを作成して使用します。
git clone https://github.com/GoogleCloudPlatform/vertex-ai-samples.git
コンテナ イメージをビルドして push する
cloudbuild.yaml ファイルを送信して、Cloud Build を使用してカスタム コンテナ イメージをビルドします。置換を使用して、ターゲット デバイスのタイプ(GPU、TPU、CPU など)と対応するベースイメージを指定します。
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
ビルドが完了したら、Artifact Registry で認証するように Docker を構成します。
gcloud auth configure-docker LOCATION-docker.pkg.dev --quiet
モデルを Model Registry にアップロードしてデプロイする
次の手順に沿って、モデルを Model Registry にアップロードし、エンドポイントを作成して、モデルをデプロイします。この例では Llama 3.2 3B を使用していますが、他のモデルに合わせて変更することもできます。
モデル変数とデプロイ変数を定義します。
DOCKER_URI変数を、前の手順でビルドしたイメージに設定します(GPU の場合など)。DOCKER_URI = f"LOCATION-docker.pkg.dev/PROJECT_ID/DOCKER_REPOSITORY/vllm-gpu"Hugging Face トークンとモデル プロパティの変数を定義します。たとえば、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モデルを Model Registry にアップロードします。
upload_model関数は、vLLM 引数と環境変数が異なるため、デバイスタイプによってわずかに異なります。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)エンドポイントを作成します。
endpoint = aiplatform.Endpoint.create(display_name=f"model_name-endpoint")モデルをエンドポイントにデプロイします。モデルのデプロイには 20~30 分かかることがあります。
# 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, )TPU の場合は、
accelerator_typeパラメータとaccelerator_countパラメータを省略して、autoscaling_target_request_count_per_minute=60を使用します。CPU の場合は、accelerator_typeパラメータとaccelerator_countパラメータを省略して、autoscaling_target_cpu_utilization=60を使用します。
Cloud Storage からモデルを読み込む
カスタム コンテナは、Hugging Face からダウンロードするのではなく、Cloud Storage からモデルをダウンロードします。Cloud Storage を使用する場合:
upload_model関数のmodel_idパラメータを Cloud Storage URI(例:gs://<var>my-bucket</var>/<var>my-models</var>/<var>llama_3_2_3B</var>)に設定します。upload_modelを呼び出すときは、env_varsからHF_TOKEN変数を省略します。model.deployを呼び出すときは、Cloud Storage バケットから読み取る権限を持つservice_accountを指定します。
Cloud Storage にアクセスするための IAM サービス アカウントを作成する
モデルが Cloud Storage にある場合は、Vertex Prediction エンドポイントがモデル アーティファクトにアクセスするために使用できるサービス アカウントを作成します。
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="Agent Platform Endpoint Service Account"
# Grant storage read permission
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:SERVICE_ACCOUNT_EMAIL" \
--role="roles/storage.objectViewer"
デプロイ時に、サービス アカウントのメールアドレスを deploy メソッド(service_account=<var>SERVICE_ACCOUNT_EMAIL</var>)に渡します。
エンドポイントを使用して予測を取得する
モデルをエンドポイントに正常にデプロイしたら、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)
出力例:
{
"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
}
次のステップ
- オープンモデルのサービング オプションを選択する
- Model as a Service(MaaS)を使用してオープンモデルを使用する
- Model Garden からオープンモデルをデプロイする
- ビルド済みコンテナを使用してオープンモデルをデプロイする