1. 简介
在此 Codelab 中,您将学习如何将向量搜索与 Vertex AI 嵌入相结合,从而使用 AlloyDB AI。本实验是专门介绍 AlloyDB AI 功能的实验合集中的一个。如需了解详情,请参阅文档中的 AlloyDB AI 页面。

前提条件
- 对 Google Cloud 控制台有基本的了解
- 具备命令行界面和 Cloud Shell 方面的基本技能
学习内容
- 如何部署 AlloyDB 集群和主实例
- 如何从 Google Compute Engine 虚拟机连接到 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 来检查其可用性。在大多数 Codelab 中,您都需要引用项目 ID,该 ID 通常用占位符 PROJECT_ID 标识。
- 此外,还有第三个值,即部分 API 使用的项目编号,供您参考。如需详细了解所有这三个值,请参阅文档。
启用结算功能
设置个人结算账号
如果您使用 Google Cloud 积分设置了结算,则可以跳过此步骤。
如需设置个人结算账号,请点击此处在 Cloud 控制台中启用结算功能。
注意事项:
- 完成本实验的 Cloud 资源费用应低于 3 美元。
- 您可以按照本实验末尾的步骤删除资源,以避免产生更多费用。
- 新用户符合参与 $300 USD 免费试用计划的条件。
启动 Cloud Shell
虽然可以通过笔记本电脑对 Google Cloud 进行远程操作,但在此 Codelab 中,您将使用 Google Cloud Shell,这是一个在云端运行的命令行环境。
在 Google Cloud 控制台 中,点击右上角工具栏中的 Cloud Shell 图标:

或者,您也可以按 G 键,然后按 S 键。如果您位于 Google Cloud 控制台中,或者使用此链接,此序列将激活 Cloud Shell。
预配和连接到环境应该只需要片刻时间。完成后,您应该会看到如下内容:

这个虚拟机已加载了您需要的所有开发工具。它提供了一个持久的 5 GB 主目录,并且在 Google Cloud 中运行,大大增强了网络性能和身份验证功能。您在此 Codelab 中的所有工作都可以在浏览器中完成。您无需安装任何程序。
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 集群之前,请在 VPC 中分配一个可用的专用 IP 范围,以供未来的 AlloyDB 实例使用。如果您没有该服务账号,则需要创建该服务账号,并将其分配给内部 Google 服务使用,之后您便可以创建集群和实例。
创建专用 IP 范围
您需要在 VPC 中为 AlloyDB 配置专用服务访问配置。这里假设您的项目中有“默认”VPC 网络,它将用于所有操作。
创建专用 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 虚拟机才能使用该数据库。
部署 GCE 虚拟机
在 AlloyDB 集群所在的区域和 VPC 中创建 GCE 虚拟机。
在 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 客户端
在已部署的虚拟机上安装 PostgreSQL 客户端软件
连接到虚拟机:
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:~$
在虚拟机内运行以下命令来安装软件:
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 从虚拟机连接到主实例。
在同一 Cloud Shell 标签页中,打开与 instance-1 虚拟机的 SSH 会话。
使用记下的 AlloyDB 密码 (PGPASSWORD) 值和 AlloyDB 集群 ID 从 GCE 虚拟机连接到 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 授予必要权限
向 AlloyDB 服务代理添加 Gemini Enterprise Agent Platform 权限。
使用顶部的“+”号打开另一个 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 虚拟机会话中,执行以下命令:
创建数据库:
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 虚拟机中,执行以下命令:
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 虚拟机中,执行以下命令:
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 密码,通过 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 基于生成的向量嵌入运行相似度搜索。
SQL 查询可以从同一 psql 命令行界面执行,也可以从 AlloyDB Studio 执行。任何多行和复杂输出在 AlloyDB Studio 中效果更好。
连接到 AlloyDB Studio
如需打开 AlloyDB Studio,请执行以下步骤:
- 在 Google Cloud 控制台中,前往 AlloyDB for PostgreSQL 的集群页面。
- 选择主实例以打开其 Web 界面。
3. 然后,点击左侧的 AlloyDB Studio:

- 选择
quickstart_db数据库、用户 postgres,提供记录的密码,然后点击“Authenticate”(进行身份验证)。

此操作会打开 AlloyDB Studio 界面。
- 选择“未命名的查询”标签页以打开 SQL 编辑器。

系统随即会打开一个编辑器,您可以在其中运行 SQL 命令,如下图所示:

如果您更喜欢使用命令行 psql,请按照替代路线操作,并从虚拟机 SSH 会话连接到数据库,如前几章中所述。
运行相似度搜索
运行查询,获取与客户请求最相关的可用产品列表。传递给 Gemini Enterprise Agent Platform 上的嵌入模型(与我们用于为产品生成嵌入的模型相同)的搜索词组,用于获取“What kind of fruit trees grow well here?”的向量值。
运行查询:
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 运行“将 AlloyDB AI 集成到 Gemini Enterprise Agent Platform 中”来获得生成式模型的相同回答,也可以实现类似的结果。您必须先注册 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 模式,您可以像创建和维护任何其他索引一样创建和维护索引。不过,如果您启用 AUTO 模式,则可以创建不需要您进行任何维护的索引。您可以在文档中详细了解所有选项。我们没有足够的行来以自动模式创建索引,因此您将以手动模式创建索引。
在 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"}]
输出中显示相同的“Cherry Tree”。
验证索引使用情况:
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.
现在我们可以销毁虚拟机了
删除 GCE 虚拟机
在 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. 恭喜
恭喜您完成此 Codelab。
本实验是“利用 Google Cloud 构建可用于生产用途的 AI”学习路线的组成部分。
- 探索完整课程,弥合从原型设计到生产的差距。
- 使用 #
#ProductionReadyAI分享您的进度。
所学内容
- 如何部署 AlloyDB 集群和主实例
- 如何从 Google Compute Engine 虚拟机连接到 AlloyDB
- 如何创建数据库并启用 AlloyDB AI
- 如何将数据加载到数据库中
- 如何使用 AlloyDB Studio
- 如何在 AlloyDB 中使用 Gemini Enterprise Agent Platform 嵌入模型
- 如何使用 Gemini Enterprise Agent Platform Studio
- 如何使用 Gemini Enterprise Agent Platform 生成式模型丰富结果
- 如何使用向量索引提升性能
13. 调查问卷
输出如下: