1. 簡介
總覽
課程內容
- 如何使用 vLLM 在 Cloud Run RTX 6000 Pro GPU 上部署 Gemma 4 模型
- 如何使用 Agent Development Kit (ADK) 建立 AI 代理,並搭配使用 Gemma 4。
- 如何使用 BigQuery MCP 伺服器,授予 AI 代理 BigQuery 中結構化資料的存取權。
Gemma 4 是 Google DeepMind 開發的 Apache 2 授權開放權重模型系列。這些模型支援多模態和多種語言,具備推論能力,且架構效率高。
Cloud Run 是無伺服器容器環境,支援 GPU。
Agent Development Kit (ADK) 是開放原始碼的代理開發框架,可讓您建構、偵錯及部署企業級的可靠 AI 代理。
BigQuery 是全代管的無伺服器企業資料倉儲,可供您儲存、查詢及分析龐大的資料集。
Model Context Protocol (MCP) 可將大型語言模型 (LLM) 和 AI 應用程式/代理程式與外部資料來源的連結方式標準化。MCP 伺服器可讓您使用工具、資源和提示,執行動作並從後端服務取得最新資料。BigQuery MCP 伺服器可讓 AI 代理直接安全地分析 BigQuery 中的資料。這項全代管 MCP 伺服器可免去管理負擔,讓您專心開發智慧代理程式。
2. 設定和需求條件
首先,請設定預設專案和 Cloud Run 區域:
# set the project
gcloud config set project YOUR_PROJECT_ID
將 YOUR_PROJECT_ID 替換為 Google Cloud 專案 ID。
# set Cloud Run region
REGION="CLOUD-RUN-REGION"; gcloud config set run/region $REGION && echo $REGION > lab2rgn.txt
將 CLOUD-RUN-REGION 替換為下列其中一個 Cloud 區域:
us-central1asia-southeast1
以下是本程式碼研究室會用到的環境變數。您可以將這些變數儲存在環境檔案中,然後「來源」該檔案。請務必正確設定專案 ID 值,並視需要設定區域。
# Model name on HuggingFace Hub
export MODEL_NAME="google/gemma-4-31B-it"
# Cloud Run Service name
export SERVICE_NAME="gemma4-rtx-vllm-codelab"
# Cloud Project and Region for Cloud Run
export GOOGLE_CLOUD_PROJECT=$(gcloud config get project -q)
export GOOGLE_CLOUD_REGION=$(cat lab2rgn.txt 2> /dev/null || gcloud config get run/region -q)
# Service account for Cloud Run service
export SERVICE_ACCOUNT="vllm-service-sa"
export SERVICE_ACCOUNT_EMAIL="${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com"
# GCS Bucket for the model cache.
export MODEL_CACHE_BUCKET="${GOOGLE_CLOUD_PROJECT}-${GOOGLE_CLOUD_REGION}-hf-model-cache"
# Model cache location in GSC bucket
export GCS_MODEL_LOCATION="gs://${MODEL_CACHE_BUCKET}/model-cache/${MODEL_NAME}"
# Uncomment next line if loading gemma-4-31B-it directly from the public cache bucket
# export GCS_MODEL_LOCATION="gs://vertex-model-garden-public-us/gemma4/gemma-4-31B-it"
# VPC Network for Direct VPC Egress
export VPC_NETWORK="vllm-${GOOGLE_CLOUD_REGION}-net"
export VPC_SUBNET="vllm-${GOOGLE_CLOUD_REGION}-subnet"
export SUBNET_RANGE="10.8.0.0/26"
啟用本程式碼研究室所需的 API。API 變更可能需要 2 到 3 分鐘才會生效。
gcloud services enable --project "${GOOGLE_CLOUD_PROJECT}" \
run.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com \
iam.googleapis.com \
compute.googleapis.com \
vpcaccess.googleapis.com \
storage.googleapis.com \
bigquery.googleapis.com \
aiplatform.googleapis.com
3. 建立服務帳戶
如果建立 Cloud Run 服務或工作時未指定服務帳戶,Cloud Run 會使用 Compute Engine 預設服務帳戶。建議您為 Cloud Run 服務使用獨立的服務帳戶,避免服務以過多的權限執行。
建立 Cloud Run 服務的服務帳戶
gcloud iam service-accounts create ${SERVICE_ACCOUNT} \
--project "${GOOGLE_CLOUD_PROJECT}" \
--display-name "vLLM Service Account"
4. 設定 Cloud Storage
建立 Cloud Storage bucket 來儲存模型權重。這樣一來,Cloud Run 每次啟動服務執行個體時,就能使用直連虛擬私有雲輸出流量,更快下載模型權重。
搭配 vLLM 中的 Run:ai Model Streamer 功能,可大幅縮短模型載入時間。
建立 Bucket
請確認這是與 Cloud Run 服務位於同一位置的單一區域 bucket。
gcloud storage buckets create "gs://${MODEL_CACHE_BUCKET}" \
--uniform-bucket-level-access --public-access-prevention \
--project "${GOOGLE_CLOUD_PROJECT}" --location "${GOOGLE_CLOUD_REGION}"
5. 擷取及快取模型權重
接著,將 Gemma 4 模型下載至 Cloud Storage bucket。模型權重有數十 GB,可能無法先下載至本機電腦或 Cloud Shell。請改用 Cloud Build,並提供足夠的儲存空間來存放模型權重。
從共用的 Cloud Storage bucket 複製模型權重
Google Cloud 擁有可公開存取的 Cloud Storage bucket,其中包含 Gemma 4 模型權重。
如要將這些檔案複製到儲存空間 bucket,請執行下列指令:
gcloud builds submit --project="${GOOGLE_CLOUD_PROJECT}" --region="${GOOGLE_CLOUD_REGION}" --no-source \
--substitutions="_MODEL_NAME=${MODEL_NAME},_GCS_MODEL_LOCATION=${GCS_MODEL_LOCATION}" \
--config=/dev/stdin <<'EOF'
steps:
- name: 'gcr.io/google.com/cloudsdktool/google-cloud-cli:slim'
entrypoint: 'bash'
args:
- '-c'
- |
if [[ "$_GCS_MODEL_LOCATION" == *"vertex-model-garden-public-us"* ]]; then
echo "Using the public cache bucket."
exit 0
fi
gcloud config set storage/parallel_composite_upload_enabled True
gcloud config set storage/parallel_composite_upload_threshold 150M
gcloud config set storage/sliced_object_download_threshold 150M
MODEL_NAME="$_MODEL_NAME"
SHORT_NAME="$${MODEL_NAME#*/}"
gcloud storage cp -r -D "gs://vertex-model-garden-public-us/gemma4/$${SHORT_NAME}" "$_GCS_MODEL_LOCATION"
EOF
6. 設定直連虛擬私有雲輸出連線的網路
如要設定直連虛擬私有雲輸出,必須建立網路和子網路,並啟用Private Google Access。
這樣一來,Cloud Run 服務就能連線至 Google API 和服務 (包括 Cloud Storage) 使用的一組外部 IP 位址。
建立聯播網
gcloud compute networks create "$VPC_NETWORK" \
--subnet-mode=custom \
--bgp-routing-mode=regional \
--project "$GOOGLE_CLOUD_PROJECT"
建立子網路
gcloud compute networks subnets create "$VPC_SUBNET" \
--network="$VPC_NETWORK" \
--region="$GOOGLE_CLOUD_REGION" \
--range="$SUBNET_RANGE" \
--enable-private-ip-google-access \
--project "$GOOGLE_CLOUD_PROJECT"
7. 設定服務帳戶存取權政策
Cloud Run 服務帳戶需要權限,才能存取您建立的 Storage Bucket 中的模型權重。
gcloud storage buckets add-iam-policy-binding "gs://${MODEL_CACHE_BUCKET}" \
--member "serviceAccount:${SERVICE_ACCOUNT_EMAIL}" \
--role "roles/storage.admin" \
--project "${GOOGLE_CLOUD_PROJECT}"
8. 初始化設定變數
定義 vLLM 推論引擎和 Cloud Run 服務的變數。
# vLLM variables
export MAX_MODEL_LEN="32767" # 32767 to improve concurrency. Keep it empty to use model's maximim context length (256K)
export QUANTIZATION_TYPE="fp8" # Model quantization for faster performance and lower memory usage.
export KV_CACHE_DTYPE="fp8" # KV-cache quantization to save GPU memory.
export GPU_MEM_UTIL="0.95" # Fraction of GPU memory to be used by the vLLM engine.
export TENSOR_PARALLEL_SIZE="1" # Partitioning model across GPUs (1 here as we have only 1 GPU).
export MAX_NUM_SEQS="16" # Max concurrent requests vLLM processes in one batch.
# Cloud Run variables
export CLOUD_RUN_CPU_NUM=20
export CLOUD_RUN_MEMORY_GB=80
export CLOUD_RUN_MAX_INSTANCES=1
export CLOUD_RUN_CONCURRENCY=16
9. 部署至 Cloud Run
準備 vLLM 容器指令列
vLLM 需要大量參數,才能快速有效率地執行大型模型。這些參數會以引數形式傳遞至部署到 Cloud Run 的容器。
CONTAINER_ARGS=(
"vllm"
"serve"
"${GCS_MODEL_LOCATION}"
"--served-model-name" "${MODEL_NAME}"
"--enable-log-requests"
"--enable-chunked-prefill"
"--enable-prefix-caching"
"--generation-config" "auto"
"--enable-auto-tool-choice"
"--tool-call-parser" "gemma4"
"--reasoning-parser" "gemma4"
"--dtype" "bfloat16"
"--quantization" "${QUANTIZATION_TYPE}"
"--kv-cache-dtype" "${KV_CACHE_DTYPE}"
"--max-num-seqs" "${MAX_NUM_SEQS}"
"--gpu-memory-utilization" "${GPU_MEM_UTIL}"
"--tensor-parallel-size" "${TENSOR_PARALLEL_SIZE}"
"--load-format" "runai_streamer"
"--port" "8080"
"--host" "0.0.0.0"
)
if [[ "${MAX_MODEL_LEN}" != "" ]]; then
CONTAINER_ARGS+=("--max-model-len" "${MAX_MODEL_LEN}")
fi
export CONTAINER_ARGS_STR="${CONTAINER_ARGS[*]}"
部署 Cloud Run 服務
執行下列指令,部署 Cloud Run 服務。請注意 GPU 類型 (RTX 6000 Pro)、基礎映像檔 (pytorch-vllm-serve:gemma4),以及叫用服務時需要驗證 (--no-allow-unauthenticated)。
gcloud beta run deploy "${SERVICE_NAME}" \
--image="us-docker.pkg.dev/vertex-ai/vertex-vision-model-garden-dockers/pytorch-vllm-serve:gemma4" \
--project "${GOOGLE_CLOUD_PROJECT}" \
--region "${GOOGLE_CLOUD_REGION}" \
--service-account "${SERVICE_ACCOUNT_EMAIL}" \
--execution-environment gen2 \
--no-allow-unauthenticated \
--cpu="${CLOUD_RUN_CPU_NUM}" \
--memory="${CLOUD_RUN_MEMORY_GB}Gi" \
--gpu=1 \
--gpu-type=nvidia-rtx-pro-6000 \
--no-gpu-zonal-redundancy \
--no-cpu-throttling \
--max-instances ${CLOUD_RUN_MAX_INSTANCES} \
--concurrency ${CLOUD_RUN_CONCURRENCY} \
--network ${VPC_NETWORK} \
--subnet ${VPC_SUBNET} \
--vpc-egress all-traffic \
--set-env-vars "MODEL_NAME=${MODEL_NAME}" \
--set-env-vars "GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT}" \
--set-env-vars "GOOGLE_CLOUD_REGION=${GOOGLE_CLOUD_REGION}" \
--port=8080 \
--timeout=3600 \
--cpu-boost \
--startup-probe tcpSocket.port=8080,initialDelaySeconds=240,failureThreshold=40,timeoutSeconds=10,periodSeconds=15 \
--command "bash" \
--args="^;^-c;${CONTAINER_ARGS_STR}"
部署作業需要幾分鐘才能完成。完成後,您將擁有以 GPU 為動力的環境,透過自動調度資源的無伺服器基礎架構 (包括調度至零,即沒有流量就沒有費用),提供 Gemma 4 服務。
10. 測試服務
部署完成後,您可以使用 vLLM OpenAI 相容 API 與 Gemma 4 模型互動。
取得服務網址
擷取已部署 Cloud Run 服務的網址。
SERVICE_URL=$(gcloud run services describe $SERVICE_NAME --project "${GOOGLE_CLOUD_PROJECT}" --region "${GOOGLE_CLOUD_REGION}" --format 'value(status.url)')
echo "Service URL: $SERVICE_URL"
執行推論
使用 curl 將提示傳送至模型。
curl -s "$SERVICE_URL/v1/chat/completions" \
-H "Authorization: Bearer $(gcloud auth print-identity-token)" \
-H "Content-Type: application/json" \
-d '{
"model": "'"${MODEL_NAME}"'",
"messages": [
{"role": "user", "content": "Why is the sky blue?"}
],
"chat_template_kwargs": {
"enable_thinking": true
},
"skip_special_tokens": false
}' | jq -r '.choices[0].message.content'
11. 使用 Agent Development Kit 建立資料代理
編寫代理程式碼
在 Cloud Shell 終端機或本機終端機中,為代理程式應用程式建立根目錄:
mkdir data_agent
開啟 Cloud Shell 編輯器或其他文字編輯器,然後在 data_agent 目錄中建立 agent.py:
data_agent/
agent.py
agent.py
import os
import subprocess
from google.adk.agents import LlmAgent
from google.adk.models.lite_llm import LiteLlm
from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams
import google.auth
from google.auth.transport.requests import Request
from google.oauth2 import id_token
# Fetch Application Default Credentials (ADC)
application_default_credentials, project_id = google.auth.default()
application_default_credentials.refresh(Request())
# Retrieve Google Cloud project to use.
project_id = os.getenv("GOOGLE_CLOUD_PROJECT", project_id)
if not project_id:
raise ValueError("GOOGLE_CLOUD_PROJECT environment variable is not set.")
if os.getenv("GOOGLE_GENAI_USE_ENTERPRISE", "").lower() not in ["true", "1"]:
# Using Cloud Run for hosting LLM with LiteLLM wrapper
api_base = os.getenv(
"API_BASE",
os.environ.get("OPENAI_API_BASE", "")
).rstrip("/")
if not api_base:
raise ValueError("API_BASE environment variable is not set")
if not api_base.endswith("/v1"):
api_base += "/v1"
model_name = os.getenv("MODEL_NAME")
if not model_name:
raise ValueError("MODEL_NAME environment variable is not set")
# Format required by LiteLLM for OpenAI-compatible APIs
model_name=f"openai/{model_name}"
# To access the model's Cloud Run service,
# we need an identity token.
try:
model_service_token_string = id_token.fetch_id_token(Request(), api_base)
except Exception as e:
# Fallback with using gcloud CLI to get the identity token
model_service_token_string = subprocess.check_output(
f"gcloud auth print-identity-token -q",
shell=True
).decode().strip()
# Gemma 4 in vLLM requires additional parameters in the request body.
extra_body={
"chat_template_kwargs": {
"enable_thinking": True
},
"skip_special_tokens": False
}
# Configure the model with LiteLLM and an OpenAI-compatible endpoint
custom_model = LiteLlm(
model=model_name,
base_url=api_base,
api_key=model_service_token_string,
extra_body=extra_body
)
model = custom_model
else:
# Gemini API in Agent Platform fallback
model = "gemini-3.5-flash-lite"
# Initialize the MCP Toolset with the connection parameters
bigquery_toolset = MCPToolset(
connection_params=StreamableHTTPConnectionParams(
url="https://bigquery.googleapis.com/mcp",
headers={
"Authorization": f"Bearer {application_default_credentials.token}",
"x-goog-user-project": project_id, # This is used for billing
},
tool_filter=[
'get_dataset_info',
'list_table_ids',
'get_table_info',
# Using readonly is a security measure to prevent accidental data modification.
'execute_sql_readonly',
]
)
)
# Configure the agent
system_instruction = f"""
You are a helpful assistant that can answer questions about data in BigQuery.
To answer the user's question, use data you have access to by using tools `list_table_ids` and `get_table_info`.
Your data is in `bigquery-public-data.new_york_citibike` dataset
(Citi Bike trips and stations in the NYC area.
It includes trip records starting from September 2013 and is updated daily.)
Plan of action:
0. ALWAYS start by analyzing dataset.
1. Analyze your data, investigate schema and dimensions by querying distrinct values of columns using `execute_sql_readonly`.
Output information about tables, columns, their data types and sets of values (for dimensions).
Note which columns can be joined or used in aggregations/filters, and what type conversion may be needed for joining or aggregating.
DO NOT MAKE ASSUMPTIONS ABOUT DATA (structure, type, values, relationships) BASED ON YOUR PRIOR KNOWLEDGE. ALWAYS VERIFY YOUR ASSUMPTIONS.
2. Understand and interpret the user's question.
3. Formulate a plan to answer the user's question.
4. Write a SQL query to retrieve relevant data in necessary form.
This is where you must pay extra attention to column types and dimensions' sets of values.
5. Retrieve data by generating BigQuery SQL and using `execute_sql_readonly`.
Always use Dry Run to verify SQL correctness.
Use `{project_id}` to run BigQuery queries (`project_id` parameter of `execute_sql_readonly`).
Do not use LaTeX in your responses. When giving a final answer, use Markdown.
"""
root_agent = LlmAgent(
model=model,
name="data_agent",
instruction=system_instruction,
description="A helpful assistant that can answer questions using NYC Citibike data.",
tools=[bigquery_toolset]
)
ADK 也需要 __init__.py 和 requirements.txt 才能部署:
__init__.py必須匯入代理程式。requirements.txt列出 Python 依附元件:google-adk適用於 Agent Development Kit、litellm適用於 LiteLLM 程式庫 (ADK 會利用這個程式庫使用非 Gemini 模型),以及mcp適用於 Model Context Protocol 用戶端。
這些指令可協助您建立 __init__.py 和 requirements.txt:
echo "from . import agent" > data_agent/__init__.py
echo -e "google-adk==2.4.*\nlitellm\nmcp==1.29.*" > data_agent/requirements.txt
最終的資料夾結構應如下所示:
data_agent/
__init__.py
agent.py
requirements.txt
在本機試用代理程式
Agent Development Kit 隨附 adk CLI 工具,也就是用於測試代理的互動式終端機介面。這項功能適用於快速測試、指令碼互動和 CI/CD 管道。其中一項功能是 adk web - ADK 網頁介面,可讓您以簡單的互動方式開發及偵錯代理程式。ADK Web 不適用於正式環境部署,但可讓您輕鬆試用代理程式。
這個指令會啟動 adk web,在通訊埠 8080 啟動本機網路伺服器。
export API_BASE=$(gcloud run services describe $SERVICE_NAME \
--project $GOOGLE_CLOUD_PROJECT \
--region $GOOGLE_CLOUD_REGION \
--format 'value(status.url)')
# If Gemma 4 deployment failed, use Gemini fallback
if [[ "${API_BASE}" == "" ]]; then
export GOOGLE_GENAI_USE_ENTERPRISE=true
else
export GOOGLE_GENAI_USE_ENTERPRISE=false
fi
uv tool run --with litellm,"mcp==1.29.*" --from "google-adk[mcp]==2.4.*" adk web --allow_origins="*" --port 8080 .
服務啟動後,開啟本機 ADK 網頁:http://localhost:8080/。
如果您使用 Google Cloud Shell,請按一下「網頁預覽」 按鈕。
在 ADK 網頁版 UI 中,詢問代理可存取的資料:
What data do you have?
代理程式碼會使用部署至 Cloud Run 的 Gemma 4 模型。模型會使用 BigQuery MCP 工具探索 citibike 資料集。您將概略瞭解 Citibike 資料集中的可用資料表和欄位。
12. 將代理程式部署至 Cloud Run
這項指令會使用 ADK CLI 將代理部署至 Cloud Run。
export API_BASE=$(gcloud run services describe $SERVICE_NAME \
--project $GOOGLE_CLOUD_PROJECT \
--region $GOOGLE_CLOUD_REGION \
--format 'value(status.url)')
# If Gemma 4 deployment failed, use Gemini fallback
if [[ "${API_BASE}" == "" ]]; then
export GOOGLE_GENAI_USE_ENTERPRISE=true
else
export GOOGLE_GENAI_USE_ENTERPRISE=false
fi
uv tool run --from google-adk==2.4.0 \
adk deploy cloud_run \
--with_ui \
--project $GOOGLE_CLOUD_PROJECT \
--region $GOOGLE_CLOUD_REGION \
--service_name gemma4-data-agent \
--app_name data_agent \
data_agent \
-- \
--allow-unauthenticated \
--max-instances 1 \
--set-env-vars GOOGLE_GENAI_USE_ENTERPRISE=${GOOGLE_GENAI_USE_ENTERPRISE},MODEL_NAME="${MODEL_NAME}",API_BASE="${API_BASE}",GOOGLE_CLOUD_PROJECT="${GOOGLE_CLOUD_PROJECT}"
試用代理
我們使用 --with_ui 選項部署代理程式。使用 ADK 網頁介面部署代理。
- 在網路瀏覽器中開啟代理程式網址。
adk deploy指令傳回的網址,您也可以執行gcloud run services指令來擷取網址:
gcloud run services describe gemma4-data-agent \
--project $GOOGLE_CLOUD_PROJECT \
--region $GOOGLE_CLOUD_REGION \
--format 'value(status.url)'
- 請代理程式根據可用的 Citibike 資料進行推論:
We have budget for 3 coffee trucks.
We want to find the best city bike stations to place our coffee trucks.
代理程式應使用 BigQuery MCP 伺服器探索 Citibike 資料集、執行幾項 SQL 查詢,並傳回 3 個 Citibike 車站的清單。
13. 恭喜!
恭喜您完成本程式碼研究室!
建議您參閱 Cloud Run 說明文件。
涵蓋內容
- 如何在 Cloud Run RTX 6000 Pro GPU 上部署 Gemma 4 模型
- 如何設定直連虛擬私有雲輸出流量和 vLLM 模型串流,並搭配 Cloud Storage 加快服務啟動速度。
- 如何使用 Agent Development Kit 建立及部署 AI 代理,並使用 Gemma 4 LLM 和 BigQuery MCP 伺服器。
14. 清理
如要避免系統向您的 Google Cloud 帳戶收取本教學課程所用資源的費用,請刪除專案或個別資源。
選項 1:刪除資源
刪除 Cloud Run 服務
gcloud run services delete gemma4-data-agent \
--project "${GOOGLE_CLOUD_PROJECT}" \
--region "${GOOGLE_CLOUD_REGION}" \
--quiet
gcloud run services delete $SERVICE_NAME \
--project "${GOOGLE_CLOUD_PROJECT}" \
--region "${GOOGLE_CLOUD_REGION}" \
--quiet
刪除服務帳戶
gcloud iam service-accounts delete \
${SERVICE_ACCOUNT_EMAIL} \
--project "${GOOGLE_CLOUD_PROJECT}" \
--quiet
刪除 Cloud Storage bucket
gcloud storage rm --recursive gs://$MODEL_CACHE_BUCKET
刪除虛擬私有雲網路和子網路
gcloud compute networks subnets delete $VPC_SUBNET \
--region "${GOOGLE_CLOUD_REGION}" \
--project "${GOOGLE_CLOUD_PROJECT}" \
--quiet
gcloud compute networks delete $VPC_NETWORK \
--project "${GOOGLE_CLOUD_PROJECT}" \
--quiet
方法 2:刪除專案
如要刪除整個專案,請前往「管理資源」,選取您在步驟 2 中建立的專案,然後選擇「刪除」。刪除專案後,您必須在 Cloud SDK 中變更專案。如要查看所有可用專案的清單,請執行 gcloud projects list。如要使用指令列,也可以執行下列指令:
gcloud projects delete ${GOOGLE_CLOUD_PROJECT}