1. 簡介
在本程式碼研究室中,您將瞭解如何結合向量搜尋與 Vertex AI 嵌入功能,使用 AlloyDB AI。本實驗室是 AlloyDB AI 功能專屬實驗室系列的一部分。詳情請參閱說明文件中的 AlloyDB AI 頁面。

必要條件
- 對 Google Cloud 和控制台有基本瞭解
- 熟悉指令列介面和 Cloud Shell 的基本操作
課程內容
- 如何部署 AlloyDB 叢集和主要執行個體
- 如何從 Google Compute Engine VM 連線至 AlloyDB
- 如何建立資料庫並啟用 AlloyDB AI
- 如何將資料載入資料庫
- 如何使用 AlloyDB Studio
- 如何在 AlloyDB 中使用 Gemini Enterprise Agent Platform 嵌入模型
- 如何使用 Gemini Enterprise Agent Platform Studio
- 如何使用 Gemini Enterprise Agent Platform 生成模型擴充結果
- 如何使用向量索引提升效能
軟硬體需求
- Google Cloud 帳戶和 Google Cloud 專案
- 網路瀏覽器,例如 Chrome
2. 設定和需求條件
專案設定
- 登入 Google Cloud 控制台。如果沒有 Gmail 或 Google Workspace 帳戶,請先建立帳戶。
請改用個人帳戶,而非公司或學校帳戶。
- 建立新專案或重複使用現有專案。如要在 Google Cloud 控制台中建立新專案,請在標題中按一下「選取專案」按鈕,開啟彈出式視窗。

在「選取專案」視窗中,按下「新專案」按鈕,開啟新專案的對話方塊。

在對話方塊中輸入偏好的專案名稱,然後選擇位置。

- 專案名稱是這個專案參與者的顯示名稱。Google API 不會使用專案名稱,且專案名稱可隨時變更。
- 專案 ID 在所有 Google Cloud 專案中不得重複,且設定後即無法變更。Google Cloud 控制台會自動產生專屬 ID,但您可以自訂 ID。如果不喜歡系統產生的 ID,可以產生另一個隨機 ID,或提供自己的 ID 並檢查是否可用。在大多數程式碼研究室中,您需要參照專案 ID,通常會以 PROJECT_ID 預留位置識別。
- 請注意,部分 API 會使用第三個值,也就是「專案編號」。如要進一步瞭解這三種值,請參閱說明文件。
啟用計費功能
設定個人帳單帳戶
如果使用 Google Cloud 抵免額設定計費,則可略過此步驟。
如要設定個人帳單帳戶,請前往這裡在 Cloud 控制台中啟用帳單功能。
注意事項:
- 完成本實驗室的 Cloud 資源費用應不到 $3 美元。
- 您可以按照本實驗室結尾的步驟刪除資源,以免產生後續費用。
- 新使用者可獲得價值 $300 美元的免費試用期。
啟動 Cloud Shell
雖然您可以透過筆電遠端操作 Google Cloud,但在本程式碼研究室中,您將使用 Google Cloud Shell,這是可在雲端執行的指令列環境。
在 Google Cloud 控制台中,點選右上角工具列的 Cloud Shell 圖示:

你也可以依序按下 G 和 S 鍵。如果您位於 Google Cloud 控制台,或使用這個連結,這個序列會啟用 Cloud Shell。
佈建並連線至環境的作業需要一些時間才能完成。完成後,您應該會看到如下的內容:

這部虛擬機器已預先安裝所有必要的開發工具,並提供永久的 5 GB 主目錄,而且可在 Google Cloud 運作,大幅提升網路效能並強化驗證功能。您可以在瀏覽器中完成本程式碼研究室的所有作業。您不需要安裝任何軟體。
3. 事前準備
啟用 API
輸出內容:
如要使用 AlloyDB、Compute Engine、網路服務和 Gemini Enterprise Agent Platform,請在 Google Cloud 雲端專案中啟用各自的 API。
啟用 API
在終端機的 Cloud Shell 中,確認專案 ID 已設定完畢:
gcloud config set project [YOUR-PROJECT-ID]
設定 PROJECT_ID 環境變數:
PROJECT_ID=$(gcloud config get-value project)
啟用所有必要的 API:
gcloud services enable alloydb.googleapis.com \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
servicenetworking.googleapis.com \
aiplatform.googleapis.com
預期的輸出內容:
student@cloudshell:~ (test-project-001-402417)$ gcloud config set project test-project-001-402417
Updated property [core/project].
student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project)
Your active configuration is: [cloudshell-14650]
student@cloudshell:~ (test-project-001-402417)$
student@cloudshell:~ (test-project-001-402417)$ gcloud services enable alloydb.googleapis.com \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
servicenetworking.googleapis.com \
aiplatform.googleapis.com
Operation "operations/acat.p2-4470404856-1f44ebd8-894e-4356-bea7-b84165a57442" finished successfully.
如要瞭解各項已啟用的 API,請參閱說明文件。
4. 部署 AlloyDB
建立 AlloyDB 叢集前,請在虛擬私有雲中分配可用的私人 IP 範圍,供日後的 AlloyDB 執行個體使用。如果沒有,請建立該帳戶,並指派給內部 Google 服務使用,之後就能建立叢集和執行個體。
建立私人 IP 範圍
您需要在 AlloyDB 的虛擬私有雲中設定私人服務存取權。這裡的假設是專案中具有「預設」虛擬私有雲網路,且所有動作都會使用該網路。
建立私人 IP 範圍:
gcloud compute addresses create psa-range \
--global \
--purpose=VPC_PEERING \
--prefix-length=24 \
--description="VPC private service access" \
--network=default
使用分配的 IP 範圍建立私人連線:
gcloud services vpc-peerings connect \
--service=servicenetworking.googleapis.com \
--ranges=psa-range \
--network=default
預期的控制台輸出內容:
student@cloudshell:~ (test-project-402417)$ gcloud compute addresses create psa-range \
--global \
--purpose=VPC_PEERING \
--prefix-length=24 \
--description="VPC private service access" \
--network=default
Created [https://www.googleapis.com/compute/v1/projects/test-project-402417/global/addresses/psa-range].
student@cloudshell:~ (test-project-402417)$ gcloud services vpc-peerings connect \
--service=servicenetworking.googleapis.com \
--ranges=psa-range \
--network=default
Operation "operations/pssn.p24-4470404856-595e209f-19b7-4669-8a71-cbd45de8ba66" finished successfully.
student@cloudshell:~ (test-project-402417)$
建立 AlloyDB 叢集
在 us-central1 區域中建立 AlloyDB 叢集
定義 postgres 使用者的密碼。您可以自行定義密碼,也可以使用隨機函式產生密碼
export PGPASSWORD=`openssl rand -hex 16`
預期的控制台輸出內容:
student@cloudshell:~ (test-project-402417)$ export PGPASSWORD=`openssl rand -hex 12`
請記下 PostgreSQL 密碼,以供日後使用:
echo $PGPASSWORD
日後以 postgres 使用者身分連線至執行個體時,需要使用該密碼。請儲存這個密碼,後續步驟會用到。
預期的控制台輸出內容:
student@cloudshell:~ (test-project-402417)$ echo $PGPASSWORD bbefbfde7601985b0dee5723 (Note: Yours will be different!)
建立免費試用叢集
如果您從未使用過 AlloyDB,可以建立免費試用叢集:
設定地區和叢集名稱的環境變數:
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
執行指令來建立叢集:
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION \
--subscription-type=TRIAL
預期的控制台輸出內容:
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION \
--subscription-type=TRIAL
Operation ID: operation-1697655441138-6080235852277-9e7f04f5-2012fce4
Creating cluster...done.
在同一個 Cloud Shell 工作階段中,為叢集建立 AlloyDB 主要執行個體。如果連線中斷,您需要再次定義區域和叢集名稱環境變數。
gcloud alloydb instances create $ADBCLUSTER-pr \
--instance-type=PRIMARY \
--cpu-count=8 \
--region=$REGION \
--cluster=$ADBCLUSTER
預期的控制台輸出內容:
student@cloudshell:~ (test-project-402417)$ gcloud alloydb instances create $ADBCLUSTER-pr \
--instance-type=PRIMARY \
--cpu-count=8 \
--region=$REGION \
--availability-type ZONAL \
--cluster=$ADBCLUSTER
Operation ID: operation-1697659203545-6080315c6e8ee-391805db-25852721
Creating instance...done.
建立 AlloyDB Standard 叢集
如果這不是專案中的第一個 AlloyDB 叢集,請繼續建立標準叢集。如果您已建立免費試用叢集,請略過這個步驟。
設定地區和叢集名稱的環境變數:
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
執行指令來建立叢集:
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION
預期的控制台輸出內容:
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION
Operation ID: operation-1697655441138-6080235852277-9e7f04f5-2012fce4
Creating cluster...done.
在同一個 Cloud Shell 工作階段中,為叢集建立 AlloyDB 主要執行個體。如果連線中斷,您需要再次定義區域和叢集名稱環境變數。
gcloud alloydb instances create $ADBCLUSTER-pr \
--instance-type=PRIMARY \
--cpu-count=2 \
--region=$REGION \
--cluster=$ADBCLUSTER
預期的控制台輸出內容:
student@cloudshell:~ (test-project-402417)$ gcloud alloydb instances create $ADBCLUSTER-pr \
--instance-type=PRIMARY \
--cpu-count=2 \
--region=$REGION \
--availability-type ZONAL \
--cluster=$ADBCLUSTER
Operation ID: operation-1697659203545-6080315c6e8ee-391805db-25852721
Creating instance...done.
5. 連線至 AlloyDB
AlloyDB 是透過僅限私人的連線部署,因此您需要安裝 PostgreSQL 用戶端的 Compute Engine VM,才能使用資料庫。
部署 GCE VM
在與 AlloyDB 叢集相同的區域和 VPC 中建立 GCE VM。
在 Cloud Shell 執行下列指令:
export ZONE=us-central1-a
gcloud compute instances create instance-1 \
--zone=$ZONE \
--create-disk=auto-delete=yes,boot=yes,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-13 AND family!=debian-13-arm64" --format="value(name)") \
--scopes=https://www.googleapis.com/auth/cloud-platform
預期的控制台輸出內容:
student@cloudshell:~ (test-project-402417)$ export ZONE=us-central1-a
gcloud compute instances create instance-1 \
--zone=$ZONE \
--create-disk=auto-delete=yes,boot=yes,image=projects/debian-cloud/global/images/$(gcloud compute images list --filter="family=debian-13 AND family!=debian-13-arm64" --format="value(name)") \
--scopes=https://www.googleapis.com/auth/cloud-platform
Created [https://www.googleapis.com/compute/v1/projects/test-project-402417/zones/us-central1-a/instances/instance-1].
NAME: instance-1
ZONE: us-central1-a
MACHINE_TYPE: n1-standard-1
PREEMPTIBLE:
INTERNAL_IP: 10.128.0.2
EXTERNAL_IP: 34.71.192.233
STATUS: RUNNING
安裝 Postgres 用戶端
在已部署的 VM 上安裝 PostgreSQL 用戶端軟體
連線至 VM:
gcloud compute ssh instance-1 --zone=us-central1-a
預期的控制台輸出內容:
student@cloudshell:~ (test-project-402417)$ gcloud compute ssh instance-1 --zone=us-central1-a Updating project ssh metadata...working..Updated [https://www.googleapis.com/compute/v1/projects/test-project-402417]. Updating project ssh metadata...done. Waiting for SSH key to propagate. Warning: Permanently added 'compute.5110295539541121102' (ECDSA) to the list of known hosts. Linux instance-1 6.12.101+deb13-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.101-1 (2026-08-05) x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. student@instance-1:~$
在 VM 內執行下列指令,安裝軟體:
sudo apt-get update
sudo apt-get install --yes postgresql-client
預期的控制台輸出內容:
student@instance-1:~$ sudo apt-get update sudo apt-get install --yes postgresql-client Get:1 file:/etc/apt/mirrors/debian.list Mirrorlist [30 B] Get:2 file:/etc/apt/mirrors/debian-security.list Mirrorlist [39 B] Hit:3 https://deb.debian.org/debian trixie InRelease Get:4 https://deb.debian.org/debian trixie-updates InRelease [47.3 kB] Get:5 https://deb.debian.org/debian trixie-backports InRelease [54.0 kB] Get:6 https://deb.debian.org/debian-security trixie-security InRelease [43.4 kB] Hit:10 https://packages.cloud.google.com/apt google-compute-engine-trixie-stable InRelease ...redacted... update-alternatives: using /usr/share/postgresql/17/man/man1/psql.1.gz to provide /usr/share/man/man1/psql.1.gz (psql.1.gz) in auto mode Setting up postgresql-client (17+278) ... Processing triggers for man-db (2.13.1-1) ... Processing triggers for libc-bin (2.41-12+deb13u3) ...
連線至執行個體
使用 psql 從 VM 連線至主要執行個體。
在同一個 Cloud Shell 分頁中,開啟連往 instance-1 VM 的 SSH 工作階段。
使用記下的 AlloyDB 密碼 (PGPASSWORD) 值和 AlloyDB 叢集 ID,從 GCE VM 連線至 AlloyDB:
export PGPASSWORD=<Noted password>
export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
export INSTANCE_IP=$(gcloud alloydb instances describe $ADBCLUSTER-pr --cluster=$ADBCLUSTER --region=$REGION --format="value(ipAddress)")
psql "host=$INSTANCE_IP user=postgres sslmode=require"
預期的控制台輸出內容:
student@instance-1:~$ export PGPASSWORD=CQhOi5OygD4ps6ty student@instance-1:~$ export PROJECT_ID=$(gcloud config get-value project) export REGION=us-central1 export ADBCLUSTER=alloydb-aip-01 export INSTANCE_IP=$(gcloud alloydb instances describe $ADBCLUSTER-pr --cluster=$ADBCLUSTER --region=$REGION --format="value(ipAddress)") psql "host=$INSTANCE_IP user=postgres sslmode=require" psql (17.10 (Debian 17.10-0+deb13u1), server 17.9) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off, ALPN: postgresql) Type "help" for help. postgres=>
關閉 psql 工作階段:
exit
6. 準備資料庫
建立資料庫、啟用 Agent Platform AI 整合功能、建立資料庫物件,以及匯入資料。
授予 AlloyDB 必要權限
將 Gemini Enterprise Agent Platform 權限新增至 AlloyDB 服務代理。
使用頂端的「+」符號開啟另一個 Cloud Shell 分頁。

在新開啟的 Cloud Shell 分頁中執行下列指令:
PROJECT_ID=$(gcloud config get-value project)
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \
--role="roles/aiplatform.user"
預期的控制台輸出內容:
student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project) Your active configuration is: [cloudshell-11039] student@cloudshell:~ (test-project-001-402417)$ gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \ --role="roles/aiplatform.user" Updated IAM policy for project [test-project-001-402417]. bindings: - members: - serviceAccount:service-4470404856@gcp-sa-alloydb.iam.gserviceaccount.com role: roles/aiplatform.user - members: ... etag: BwYIEbe_Z3U= version: 1
在分頁中執行「exit」指令,關閉分頁:
exit
建立資料庫
建立資料庫快速入門。
在 GCE VM 工作階段中執行下列指令:
建立資料庫:
psql "host=$INSTANCE_IP user=postgres" -c "CREATE DATABASE quickstart_db"
預期的控制台輸出內容:
student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres" -c "CREATE DATABASE quickstart_db" CREATE DATABASE student@instance-1:~$
啟用 Vertex AI 整合功能
在資料庫中啟用 Vertex AI 整合功能和 pgvector 擴充功能。
在 GCE VM 中執行下列指令:
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE"
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS vector"
預期的控制台輸出內容:
student@instance-1:~$ psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE" psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "CREATE EXTENSION IF NOT EXISTS vector" CREATE EXTENSION CREATE EXTENSION student@instance-1:~$
匯入資料
下載準備好的資料,然後匯入新資料庫。
在 GCE VM 中執行下列指令:
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_products from stdin csv header"
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_inventory from stdin csv header"
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_stores from stdin csv header"
預期的控制台輸出內容:
student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" SET SET SET SET SET set_config ------------ (1 row) SET SET SET SET SET SET CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE TABLE ALTER TABLE CREATE SEQUENCE ALTER TABLE ALTER SEQUENCE ALTER TABLE ALTER TABLE ALTER TABLE student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_products from stdin csv header" COPY 941 student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_inventory from stdin csv header" COPY 263861 student@instance-1:~$ gsutil cat gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv |psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db" -c "\copy cymbal_stores from stdin csv header" COPY 4654 student@instance-1:~$
7. 計算嵌入
匯入資料後,你可以在 cymbal_products 表格中找到產品資料,在 cymbal_inventory 表格中找到各商店的可用產品數量,在 cymbal_stores 表格中找到商店清單。您需要根據產品說明計算向量資料,並使用 google_ml.embedding 等函式。如要進一步瞭解使用的技術,請參閱說明文件。
為幾列資料生成嵌入內容很容易,但如果我們有數千列資料,該如何有效率地完成這項作業?本節說明如何為大型資料表產生及管理嵌入內容。如要進一步瞭解不同選項和技巧,請參閱指南。
啟用快速生成嵌入項目
使用 AlloyDB 執行個體 IP 和 postgres 密碼,從 VM 透過 psql 連線至資料庫:
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
確認 google_ml_integration 擴充功能版本。
SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';
版本必須為 1.5.2 以上。以下是輸出內容範例:
quickstart_db=> SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration'; extversion ------------ 1.6 (1 row)
預設版本應為 1.6 以上,但如果執行個體顯示較舊的版本,可能需要更新。檢查執行個體是否已停用維護作業。
確認 google_ml_integration.enable_faster_embedding_generation 資料庫旗標已設為開啟。在同一個 psql 工作階段中,檢查旗標的值:
show google_ml_integration.enable_faster_embedding_generation;
如果旗標位置正確,預期輸出內容如下:
quickstart_db=> show google_ml_integration.enable_faster_embedding_generation; google_ml_integration.enable_faster_embedding_generation ---------------------------------------------------------- on (1 row)
如果旗標值顯示「off」,則必須更新執行個體。請按照說明文件所述,使用網頁控制台或 gcloud 指令執行這項操作。
退出 psql 工作階段:
exit;
如要使用 gcloud 更新旗標,請執行:
export PROJECT_ID=$(gcloud config get-value project)
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
gcloud beta alloydb instances update $ADBCLUSTER-pr \
--database-flags google_ml_integration.enable_faster_embedding_generation=on \
--region=$REGION \
--cluster=$ADBCLUSTER \
--project=$PROJECT_ID \
--update-mode=FORCE_APPLY
這可能需要幾分鐘,但最終標記值應會切換為「開啟」。完成後即可繼續進行後續步驟。
建立嵌入欄
使用 psql 連線至資料庫,並建立向量資料類型的虛擬資料欄,供 cymbal_products 資料表中的嵌入函式使用。
psql "host=$INSTANCE_IP user=postgres dbname=quickstart_db"
連線至資料庫後,在 psql 工作階段中執行:
ALTER TABLE cymbal_products ADD COLUMN embedding vector(768);
這項指令會建立虛擬資料欄,用於日後的嵌入。
預期的控制台輸出內容:
quickstart_db=> ALTER TABLE cymbal_products ADD COLUMN embedding vector(768); ALTER TABLE quickstart_db=>
以 50 列為一批生成嵌入項目。在同一個 psql 工作階段中執行下列指令:
啟用計時功能,測量所需時間:
\timing
執行下列指令:
CALL ai.initialize_embeddings(
model_id => 'text-embedding-005',
table_name => 'cymbal_products',
content_column => 'product_description',
embedding_column => 'embedding',
batch_size => 50
);
主控台輸出內容顯示,產生嵌入內容的時間不到 2 秒:
quickstart_db=> CALL ai.initialize_embeddings(
model_id => 'text-embedding-005',
table_name => 'cymbal_products',
content_column => 'product_description',
embedding_column => 'embedding',
batch_size => 50
);
NOTICE: Initialize embedding completed successfully for table cymbal_products
CALL
Time: 1458.704 ms (00:01.459)
quickstart_db=>
您可以嘗試不同的批次大小,看看執行時間是否會有所變化。
根據預設,如果對應的 product_description 欄位更新,或插入全新資料列,系統不會重新整理嵌入內容。但您可以透過設定參數 incremental_refresh_mode 來完成這項操作。
建立「product_embeddings」product_embeddings欄,並設為自動更新:
ALTER TABLE cymbal_products ADD COLUMN product_embedding vector(768);
CALL ai.initialize_embeddings(
model_id => 'text-embedding-005',
table_name => 'cymbal_products',
content_column => 'product_description',
embedding_column => 'product_embedding',
batch_size => 50,
incremental_refresh_mode => 'transactional'
);
在表格中插入新資料列。
INSERT INTO "cymbal_products" ("uniq_id", "crawl_timestamp", "product_url", "product_name", "product_description", "list_price", "sale_price", "brand", "item_number", "gtin", "package_size", "category", "postal_code", "available", "product_embedding", "embedding") VALUES ('fd604542e04b470f9e6348e640cff794', NOW(), 'https://example.com/new_product', 'New Cymbal Product', 'This is a new cymbal product description.', 199.99, 149.99, 'Example Brand', 'EB123', '1234567890', 'Single', 'Cymbals', '12345', TRUE, NULL, NULL);
查詢資料表,比較兩個嵌入資料欄:
SELECT uniq_id,embedding, (product_embedding::real[])[1:5] as product_embedding FROM cymbal_products WHERE uniq_id='fd604542e04b470f9e6348e640cff794';
輸出內容顯示 product_embedding 會自動填入,而 embedding 則維持空白:
quickstart_db=> SELECT uniq_id,embedding, (product_embedding::real[])[1:5] as product_embedding FROM cymbal_products WHERE uniq_id='fd604542e04b470f9e6348e640cff794';
uniq_id | embedding | product_embedding
----------------------------------+-----------+---------------------------------------------------------------
fd604542e04b470f9e6348e640cff794 | | {0.015003494,-0.005349732,-0.059790313,-0.0087091,-0.0271452}
(1 row)
Time: 3.295 ms
8. 執行相似度搜尋
使用 AlloyDB AI,根據生成的向量嵌入執行相似度搜尋。
您可以從同一個 psql 指令列介面執行 SQL 查詢,也可以改用 AlloyDB Studio。AlloyDB Studio 更適合處理多列和複雜的輸出內容。
連線至 AlloyDB Studio
如要開啟 AlloyDB Studio,請執行下列步驟:
- 前往 Google Cloud 控制台的 AlloyDB for PostgreSQL 叢集頁面。
- 選取主要執行個體,開啟其網頁介面。
3. 然後點選左側的 AlloyDB Studio:

- 選取
quickstart_db資料庫和 postgres 使用者,提供記下的密碼,然後按一下「驗證」。

這個動作會開啟 AlloyDB Studio 介面。
- 選取「未命名的查詢」分頁,開啟 SQL 編輯器。

系統會開啟編輯器,讓您執行 SQL 指令,如下圖所示:

如果您偏好使用 psql 指令列,請按照替代路徑操作,並從 VM SSH 工作階段連線至資料庫,如先前章節所述。
執行相似度搜尋
執行查詢,取得與客戶要求最相關的可用產品清單。傳遞至 Gemini Enterprise Agent Platform 嵌入模型的搜尋詞組 (與我們用來為產品生成嵌入的詞組相同),取得「這裡適合種植哪種果樹?」的向量值。
執行查詢:
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
(cp.embedding <=> embedding('text-embedding-005','What kind of fruit trees grow well here?')::vector) as distance
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
distance ASC
LIMIT 10;
預期的輸出內容如下:
quickstart_db=> SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
(cp.embedding <=> embedding('text-embedding-005','What kind of fruit trees grow well here?')::vector) as distance
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
distance ASC
LIMIT 10;
product_name | description | sale_price | zip_code | distance
-------------------------+----------------------------------------------------------------------------------+------------+----------+---------------------
Cherry Tree | This is a beautiful cherry tree that will produce delicious cherries. It is an d | 75.00 | 93230 | 0.43922018972266397
Meyer Lemon Tree | Meyer Lemon trees are California's favorite lemon tree! Grow your own lemons by | 34 | 93230 | 0.4685112926118228
Toyon | This is a beautiful toyon tree that can grow to be over 20 feet tall. It is an e | 10.00 | 93230 | 0.4835677149651668
California Lilac | This is a beautiful lilac tree that can grow to be over 10 feet tall. It is an d | 5.00 | 93230 | 0.4947204525907498
California Peppertree | This is a beautiful peppertree that can grow to be over 30 feet tall. It is an e | 25.00 | 93230 | 0.5054166905547247
California Black Walnut | This is a beautiful walnut tree that can grow to be over 80 feet tall. It is a d | 100.00 | 93230 | 0.5084219510932597
California Sycamore | This is a beautiful sycamore tree that can grow to be over 100 feet tall. It is | 300.00 | 93230 | 0.5140519790508755
Coast Live Oak | This is a beautiful oak tree that can grow to be over 100 feet tall. It is an ev | 500.00 | 93230 | 0.5143126438081371
Fremont Cottonwood | This is a beautiful cottonwood tree that can grow to be over 100 feet tall. It i | 200.00 | 93230 | 0.5174774727252058
Madrone | This is a beautiful madrona tree that can grow to be over 80 feet tall. It is an | 50.00 | 93230 | 0.5227400803389093
系統會提供 10 項產品,這些產品的說明與搜尋詞組的語意相近,並依距離排序,最相似的產品會顯示在最上方。
9. 改善回覆內容
您可以運用查詢結果改善用戶端應用程式的回應,並將提供的查詢結果做為基礎生成式語言模型提示的一部分,準備有意義的輸出內容。
為此,您需要產生含有向量搜尋結果的 JSON,然後將產生的 JSON 新增至 Agent Platform 中生成式 AI 模型的提示,藉此建立有意義的輸出內容。第一個步驟會生成 JSON,接著在 Agent Platform Studio 中進行測試,最後一個步驟則會將所有內容併入一個 SQL 陳述式,供應用程式使用。
以 JSON 格式產生輸出內容
修改查詢,以 JSON 格式產生輸出內容,並只傳回一個資料列,傳遞至 Agent Platform
執行查詢:
WITH trees as (
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
cp.uniq_id as product_id
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
(cp.embedding <=> embedding('text-embedding-005','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
輸出內容中的 JSON:
[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]
在 Vertex AI Studio 中執行提示
使用生成的 JSON,在 Vertex AI Studio 中將其做為生成式 AI 模型提示的一部分
在 Google Cloud 控制台中開啟 Gemini Enterprise Agent Platform Studio。

在介面中撰寫提示:

輸入下列提示詞:
You are a friendly advisor helping to find a product based on the customer's needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
Here is the list of products:
{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}
The customer asked "What tree is growing the best here?"
You should give information about the product, price and some supplemental information

以下是執行提示時的結果:

答案會包含價格、說明,以及模型根據樹木和地點資訊從外部來源取得的補充資訊。
在 PSQL 中執行提示
如要達到類似結果,請在資料庫中直接執行 SQL,透過 Gemini Enterprise Agent Platform 整合 AlloyDB AI,從生成模型取得相同的回覆。您必須先註冊,才能使用 gemini-3.6-flash 模型。
註冊 gemini-3.6-flash 模型:
在 AlloyDB Studio 中執行下列指令:
CALL google_ml.create_model(
model_id => 'gemini-3.6-flash',
model_request_url => 'https://aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/global/publishers/google/models/gemini-3.6-flash:generateContent',
model_provider => 'google',
model_type => 'llm'
);
您隨時可以從 google_ml.model_info_view 中選取資訊,驗證已註冊的模型清單。
SELECT model_id,model_type FROM google_ml.model_info_view WHERE model_id ILIKE '%flash%';
以下是輸出內容範例
quickstart_db=> SELECT model_id,model_type FROM google_ml.model_info_view WHERE model_id ILIKE '%flash%';
model_id | model_type
-----------------------+------------
gemini-3.6-flash | llm
gemini-2.0-flash | llm
gemini-2.5-flash | llm
gemini-2.0-flash-lite | llm
gemini-2.5-flash-lite | llm
(5 rows)
您現在可以使用 SQL,將子查詢中產生的 JSON 做為 gemini-3.6-flash 模型的提示詞。
在 psql 或 AlloyDB Studio 工作階段中,執行下列查詢:
WITH trees AS (
SELECT
cp.product_name,
cp.product_description AS description,
cp.sale_price,
cs.zip_code,
cp.uniq_id AS product_id
FROM
cymbal_products cp
JOIN cymbal_inventory ci ON
ci.uniq_id = cp.uniq_id
JOIN cymbal_stores cs ON
cs.store_id = ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
(cp.embedding <=> embedding('text-embedding-005',
'What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1),
prompt AS (
SELECT
'You are a friendly advisor helping to find a product based on the customer''s needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","product_description":"some description","sale_price":10}
Here is the list of products:' || json_agg(trees) || 'The customer asked "What kind of fruit trees grow well here?"
You should give information about the product, price and some supplemental information' AS prompt_text
FROM
trees),
response AS (
SELECT
google_ml.predict_row( model_id =>'gemini-3.6-flash',
request_body => json_build_object('contents',
json_build_object('role',
'user',
'parts',
json_build_object('text',
prompt_text))))->'candidates'->0->'content'->'parts'->0->'text' AS resp
FROM
prompt)
SELECT
REPLACE(resp::text, '\n', CHR(10))
FROM
response;
預期的輸出內容如下。由於生成式 AI 模型具有不確定性,輸出結果可能有所不同:
"Hello there! I'd be delighted to help you pick out a wonderful fruit tree for your space. Based on our local selection, a fantastic option that grows very well is the **Cherry Tree**! Here are the details on this beautiful tree: * **Product:** Cherry Tree * **Price:** $75.00 ### Why it's a great choice: * **Delicious Harvest:** It produces tasty, fresh cherries right in your backyard. * **Size & Benefits:** It's a deciduous tree that grows to about 15 feet tall, making it ideal for providing both lovely shade and a bit of privacy. * **Year-Round Beauty:** It features lush, dark green leaves throughout the summer that transform into a stunning red in the autumn. * **Growing Requirements:** Cherry trees thrive best in cool, moist climates with sandy soil, and are perfectly suited for USDA hardiness zones 4 through 9. Please let me know if you have any questions about planting or if you'd like help adding this to your order!"
10. 建立向量索引
由於這個資料集很小,回應時間主要取決於與 Gemini Enterprise Agent Platform 模型的互動。不過,當您查詢數百萬個向量時,向量搜尋本身可能會耗用大量回應時間,並增加資料庫的負載。如要提升搜尋效能,可以建立向量索引。
建立 ScaNN 索引
如要建構 ScaNN 索引,必須啟用額外擴充功能。alloydb_scann 擴充功能提供介面,可使用 Google ScaNN 演算法處理近似最鄰近 (ANN) 向量索引。
在 AlloyDB Studio 中執行:
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
索引可以在 MANUAL 或 AUTO 模式下建立。系統預設會啟用「MANUAL」模式,您可以建立及維護索引,就像其他索引一樣。但如果啟用「自動」模式,您就能建立索引,不需要自行維護。如要詳細瞭解所有選項,請參閱說明文件。我們沒有足夠的資料列,無法在「自動」模式中建立索引,因此您將以「手動」模式建立索引。
在 AlloyDB Studio 中執行:
CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products
USING scann (embedding cosine)
WITH (num_leaves=10, max_num_levels = 1);
如要瞭解如何調整索引參數,請參閱說明文件。
預期輸出內容:
quickstart_db=> CREATE INDEX cymbal_products_embeddings_scann ON cymbal_products USING scann (embedding cosine) WITH (num_leaves=10, max_num_levels = 1); CREATE INDEX quickstart_db=>
比較回覆
重複使用我們在語意搜尋中取得最高值的查詢:
WITH trees as (
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
cp.uniq_id as product_id
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
(cp.embedding <=> embedding('text-embedding-005','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
預期輸出內容:
[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]
輸出內容中會顯示相同的「櫻桃樹」。
驗證索引使用情形:
EXPLAIN (analyze)
WITH trees as (
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
cp.uniq_id as product_id
FROM
cymbal_products cp
JOIN cymbal_inventory ci on
ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
cs.store_id=ci.store_id
AND ci.inventory>0
AND cs.store_id = 1583
ORDER BY
(cp.embedding <=> embedding('text-embedding-005','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
預期輸出內容 (為求明確而經過編輯):
...
Aggregate (cost=27.24..27.25 rows=1 width=32) (actual time=0.964..0.965 rows=1 loops=1)
-> Subquery Scan on trees (cost=18.91..27.23 rows=1 width=142) (actual time=0.953..0.954 rows=1 loops=1)
-> Limit (cost=18.91..27.22 rows=1 width=158) (actual time=0.948..0.949 rows=1 loops=1)
-> Nested Loop (cost=18.91..7126.86 rows=855 width=158) (actual time=0.948..0.948 rows=1 loops=1)
-> Nested Loop (cost=18.63..7103.59 rows=855 width=907) (actual time=0.931..0.931 rows=1 loops=1)
-> Index Scan using cymbal_products_embeddings_scann on cymbal_products cp (cost=18.21..343.15 rows=942 width=903) (actual time=0.906..0.908 rows=2 loops=1)
Order By: (embedding <=> '[-0.106554024,0.035774965,-0.027267234,-0.045653425,-0.03286045,0.02124319...
從輸出內容中,您可以看到查詢使用的是「Index Scan using cymbal_products_embeddings_scann on cymbal_products」。
查詢會傳回與建立索引前相同的櫻桃樹,顯示在搜尋結果頂端。由於近似最鄰近 (ANN) 索引會犧牲絕對準確率來換取搜尋速度,因此與未建立索引的精確搜尋相比,以索引為基礎的查詢有時可能會傳回略有差異的頂端結果。不過,向量索引可大幅提升效能,同時維持高準確度。
如要進一步探索,可以試用其他向量索引類型,或在說明文件頁面上尋找更多整合 LangChain 的實驗室和範例。
11. 清理環境
完成實驗室後,請終止 AlloyDB 執行個體和叢集。
刪除 AlloyDB 叢集和所有執行個體
使用 force 選項終止叢集,這也會刪除叢集中的所有執行個體。
如果終端機已中斷連線,請重新連線,並在 Cloud Shell 中定義專案和環境變數:
gcloud config set project <YOUR_PROJECT_ID>
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
export PROJECT_ID=$(gcloud config get-value project)
刪除叢集:
gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force
預期的控制台輸出內容:
student@cloudshell:~ (test-project-001-402417)$ gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force All of the cluster data will be lost when the cluster is deleted. Do you want to continue (Y/n)? Y Operation ID: operation-1697820178429-6082890a0b570-4a72f7e4-4c5df36f Deleting cluster...done.
刪除 AlloyDB 備份
刪除叢集的所有 AlloyDB 備份:
for i in $(gcloud alloydb backups list \
--filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" \
--format="value(name)" \
--sort-by=~createTime) ; do \
gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done
預期的控制台輸出內容:
student@cloudshell:~ (test-project-001-402417)$ for i in $(gcloud alloydb backups list --filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" --format="value(name)" --sort-by=~createTime) ; do gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done Operation ID: operation-1697826266108-60829fb7b5258-7f99dc0b-99f3c35f Deleting backup...done.
現在可以刪除 VM 了
刪除 GCE VM
在 Cloud Shell 執行下列指令:
export GCEVM=instance-1
export ZONE=us-central1-a
gcloud compute instances delete $GCEVM \
--zone=$ZONE \
--quiet
預期的控制台輸出內容:
student@cloudshell:~ (test-project-001-402417)$ export GCEVM=instance-1
export ZONE=us-central1-a
gcloud compute instances delete $GCEVM \
--zone=$ZONE \
--quiet
Deleted
12. 恭喜
恭喜您完成本程式碼研究室。
這個實驗室屬於「Google Cloud 學習路徑:打造可用於正式環境的 AI」的一部分。
- 探索完整課程,從設計原型開始,一步步把專案投入正式環境。
- 使用主題標記
#ProductionReadyAI分享你的進度。
涵蓋內容
- 如何部署 AlloyDB 叢集和主要執行個體
- 如何從 Google Compute Engine VM 連線至 AlloyDB
- 如何建立資料庫並啟用 AlloyDB AI
- 如何將資料載入資料庫
- 如何使用 AlloyDB Studio
- 如何在 AlloyDB 中使用 Gemini Enterprise Agent Platform 嵌入模型
- 如何使用 Gemini Enterprise Agent Platform Studio
- 如何使用 Gemini Enterprise Agent Platform 生成模型擴充結果
- 如何使用向量索引提升效能
13. 問卷調查
輸出內容: