1. 概览
想象一下,一款时尚应用不仅能帮助您找到完美的服装,还能提供实时造型建议,而这一切都得益于尖端的生成式 AI 集成!在本次讲座中,我们将探讨如何使用 AlloyDB 的向量搜索功能以及 Google 的 ScaNN 索引构建这样一款应用,从而以极快的速度搜索搭配的服装并提供即时时尚建议。
我们还将深入探讨 AlloyDB 的 ScaNN 索引如何优化复杂查询,以生成个性化风格建议。我们还将使用 Gemini 和 Imagen 这两款强大的生成式 AI 模型,为您提供创意造型灵感,甚至直观呈现您的专属造型。整个应用都基于无服务器架构构建,可确保为用户提供顺畅且可扩缩的体验。
挑战:该应用旨在通过提供个性化的服装搭配建议,帮助那些在时尚方面难以做出决定的人。此外,它还有助于避免因服装搭配规划而产生的决策疲劳。
解决方案:服装推荐应用可为用户提供智能、个性化且富有吸引力的时尚体验,同时展示 AlloyDB、生成式 AI 和无服务器技术的能力。
构建内容
在本实验中,您将:
- 创建 AlloyDB 实例并加载电子商务数据集
- 在 AlloyDB 中启用 pgvector 和生成式 AI 模型扩展程序
- 根据商品说明生成嵌入
- 在无服务器 Cloud Run Functions 中部署解决方案
- 将图片上传到 Gemini,并生成图片描述提示。
- 根据提示以及电子商务数据集嵌入生成搜索结果。
- 添加其他提示以自定义提示并生成风格建议。
- 在无服务器 Cloud Run Functions 中部署解决方案
要求
2. 架构
应用的总体架构如下所示:

以下部分重点介绍了教程的上下文流程:
提取:
第一步是将零售数据(库存、产品说明、客户互动)注入 AlloyDB。
Analytics Engine:
我们将使用 AlloyDB 作为分析引擎来执行以下操作:
- 上下文提取:引擎会分析 AlloyDB 中存储的数据,以了解产品、类别、客户行为等之间的关系(如适用)。
- 嵌入创建:为用户查询和 AlloyDB 中存储的信息生成嵌入(文本的数学表示形式)。
- Vector Search:该引擎会执行相似度搜索,将查询嵌入与产品说明、评价和其他相关数据的嵌入进行比较。这会标识 25 个最相关的“最近邻”。
Gemini 建议:
图片字节数组会通过 Vertex AI API 传递给 Gemini 模型,同时传递的还有提示,要求提供上衣的文字说明以及下装搭配建议。
AlloyDB RAG 和向量搜索:
系统会使用上衣的说明来查询数据库。查询会将搜索文本(Gemini 模型针对搭配下装的建议)转换为嵌入,并对存储在数据库中的嵌入执行向量搜索,以找到最近邻(匹配结果)。AlloyDB 数据库中的向量嵌入使用 ScaNN 索引进行索引,以提高召回率。
回答图片生成:
经过验证的回答会以 JSON 数组的形式进行结构化处理,整个引擎会打包到从 Agent Builder 调用的无服务器 Cloud Run 函数中。
Imagen 图片生成:
系统会将用户的样式提示、用户选择的建议和任何个性化请求相结合,以提示 Imagen 3 使用现有图片。样式化图片是根据此提示使用 Vertex AI API 生成的。
3. 准备工作
创建项目
- 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。
- 确保您的 Cloud 项目已启用结算功能。了解如何检查项目是否已启用结算功能。
- 您将使用 Cloud Shell,这是一个在 Google Cloud 中运行的命令行环境,它预加载了 bq。点击 Google Cloud 控制台顶部的激活 Cloud Shell (
)。 - 连接到 Cloud Shell 后,使用以下命令验证您是否已通过身份验证,以及项目是否已设置为您的项目 ID:
gcloud auth list
- 运行以下命令,确认未来的 gcloud 命令将正确识别您的项目。
gcloud config list project
- 如果项目未设置,请使用以下命令明确设置项目:
gcloud config set project <YOUR_PROJECT_ID>
- 启用所需的 API。
点击链接以启用 API。
如果您忘记启用任何 API,可以随时在实施过程中启用。
如需详细了解 gcloud 命令和用法,请参阅文档。
4. 数据库设置
在本实验中,我们将使用 AlloyDB 作为数据库来存储零售电子商务数据集。它使用集群来存储所有资源,例如数据库和日志。每个集群都有一个主实例,可提供对数据的接入点。表是存储数据的实际资源。
接下来,我们将创建一个 AlloyDB 集群、实例和表,用于加载电子商务数据集。
创建集群和实例
- 在 Google Cloud 控制台中,搜索 AlloyDB。在 Cloud 控制台中查找大多数页面的简单方法是使用控制台的搜索栏进行搜索。
- 点击创建集群。

- 使用以下值创建集群和实例:
- 集群 ID:“
shopping-cluster” - 密码:“
alloydb” - 与 PostgreSQL 15 兼容
- 地区:“
us-central1” - 联网:“
default”

- 在“网络”中,选择默认网络后,系统会显示以下选项。点击设置连接以设置默认网络。

- 选择使用自动分配的 IP 范围,然后点击继续。查看信息后,点击创建连接。

等待默认网络创建完成。
- 在“配置主实例”中,将“实例 ID”设置为“
shopping-instance"”。

- 点击创建集群,完成集群设置,如下所示:

5. 数据注入
现在,我们来添加一个包含商店相关数据的表格。等待实例创建完成。创建完成后,您可以使用在创建集群时设置的凭据登录 AlloyDB。
向 AlloyDB 数据库进行身份验证
- 在 Google Cloud 控制台中,前往 AlloyDB。选择主集群,然后在左侧导航栏中点击 AlloyDB Studio:

- 输入以下详细信息以对 AlloyDB 数据库进行身份验证:
- 用户名:“
postgres” - 数据库:“
postgres” - 密码:“
alloydb”
成功通过 AlloyDB Studio 身份验证后,您可以在编辑器标签页中输入 SQL 命令。您可以使用第一个编辑器标签页右侧的加号添加多个编辑器窗口。

您将在编辑器窗口中输入 AlloyDB 命令,并根据需要使用“运行”“格式化”和“清除”选项。
启用扩展程序
为了构建此应用,我们将使用“pgvector"”和“google_ml_integration"”扩展程序。
- 借助 pgvector 扩展程序,您可以存储和搜索向量嵌入。
- google_ml_integration 扩展程序提供用于访问 Vertex AI 预测端点以在 SQL 中获取预测结果的函数。
- 运行以下 DDL 以启用这些扩展程序:
CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector;
- 运行以下 SQL 命令,验证扩展程序是否已安装:
select extname, extversion from pg_extension;
创建表
- 使用以下 DDL 语句创建表:
CREATE TABLE
apparels ( id BIGINT,
category VARCHAR(100),
sub_category VARCHAR(50),
uri VARCHAR(200),
image VARCHAR(100),
content VARCHAR(2000),
pdt_desc VARCHAR(5000),
embedding vector(768) );
成功执行上述命令后,您应该能够在
十个地址。下图显示了一个示例:

注入数据
在此实验中,我们有一个包含约 200 条记录的 SQL 文件作为测试数据。它包含 id, category, sub_category, uri, image 和 content。其他字段将在稍后的实验中填写。
- 将 SQL 文件中的 20 行/插入语句复制到 AlloyDB Studio 的新编辑器标签页中,然后点击 RUN。
- 展开“探索器”部分,直到您看到名为
apparels的表。 - 点击菜单图标 [⋮],然后点击查询。系统会在新的编辑器标签页中打开 SELECT 语句。

- 点击运行以验证是否已插入行。
向用户授予权限
我们将向 postgres 用户授予从 AlloyDB. 内生成嵌入的权限。在 AlloyDB Studio 中,运行以下语句,向用户 postgres 授予对 embedding 函数的执行权限:
GRANT EXECUTE ON FUNCTION embedding TO postgres;
为 AlloyDB 服务账号授予 Vertex AI User 角色
我们将使用 Vertex AI 中的文本嵌入模型来生成嵌入,为此,请向 AlloyDB 服务账号授予 Vertex AI User 角色。
在 Google Cloud 控制台中,点击 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"
6. 构建上下文
为了创建嵌入,我们需要一个 context,即我们想要包含在单个字段中的所有信息。为此,我们将创建一个商品说明,并将其存储在 apparels 表的 pdt_desc 列中。
在我们的示例中,我们将使用每件商品的所有信息,但当您使用自己的数据执行此操作时,可以随意设计数据,只要您认为对自己的业务有意义即可。
在 AlloyDB Studio 编辑器标签页中,运行以下命令,使用情境数据更新 pdt_desc 字段:
UPDATE
apparels
SET
pdt_desc = CONCAT('This product category is: ', category, ' and sub_category is: ', sub_category, '. The description of the product is as follows: ', content, '. The product image is stored at: ', uri)
WHERE
id IS NOT NULL;
此 DML 使用表中的所有可用字段和其他依赖项(如果您的使用情形中有)中的信息创建简单的上下文摘要。为了更精确地整理信息和创建上下文,您可以随意处理数据,只要您认为对自己的业务有意义即可。
7. 为上下文创建嵌入
计算机处理数字比处理文本容易得多。嵌入系统会将文本转换为一系列浮点数,这些浮点数应能表示文本,无论文本的措辞如何、使用何种语言等。
考虑描述海边位置。它可能被称为“"on the water”“beachfront”“walk from your room to the ocean”“sur la mer”“на берегу океана”等。这些术语看起来各不相同,但它们的语义含义(或机器学习术语中的嵌入)应该非常接近。
现在,数据和上下文已准备就绪,我们将运行 SQL,以将商品描述 ((pdt_desc) 列的嵌入内容添加到字段 embedding 中的表中。您可以使用各种嵌入模型。我们使用的是 Vertex AI 中的 text-embedding-005。
- 在 AlloyDB Studio 中,运行以下命令以生成嵌入,并使用其存储的数据的嵌入更新
pdt_desc列:
UPDATE
apparels
SET
embedding = embedding( 'text-embedding-005',
pdt_desc)
WHERE
TRUE;
- 运行以下命令,验证是否已生成嵌入内容:
SELECT
id,
category,
sub_category,
content,
embedding
FROM
Apparels
LIMIT 5;
以下是一个嵌入向量示例,它看起来像一个浮点数数组,对应于查询中的示例文本,如下所示:

8. 执行向量搜索
现在,表、数据和嵌入都已准备就绪,接下来我们来针对用户搜索文本执行实时向量搜索。
假设用户的搜索文本为“pink color, casual, pure cotton tops for women”
如需查找与此查询匹配的内容,请运行以下 SQL 查询:
SELECT
id,
category,
sub_category,
content,
pdt_desc AS description
FROM
apparels
ORDER BY
embedding <=> embedding('text-embedding-005',
'pink color, casual, pure cotton tops for women')::vector
LIMIT
5;
我们来详细了解一下此查询:
在此查询中,
- 用户的搜索文字为:“
I want womens tops, pink casual only pure cotton.” - 我们将使用
embedding()方法和模型text-embedding-005将此搜索文本转换为嵌入。在最后一步中,我们已将嵌入函数应用于表中的所有项,因此这一步应该很熟悉。 - “
<=>”表示使用余弦相似度距离方法。您可以在 pgvector 的文档中找到所有可用的相似度衡量指标。 - 我们将嵌入方法的结果转换为向量数据类型,以便与存储在数据库中的向量兼容。
- LIMIT 5 表示我们希望提取搜索文本的 5 个最近邻项。
以下示例展示了此 SQL 查询的响应:

从搜索结果中可以看出,匹配项与搜索文本非常接近。尝试更改颜色,看看结果有何变化。
AlloyDB ScaNN 索引,可提升查询性能
现在,假设我们想使用 ScaNN 索引来提高此向量搜索结果的性能(查询时间)、效率和召回率。
如果您想使用 ScaNN 索引,请尝试以下步骤:
- 由于我们已经创建了集群、实例、上下文和嵌入,因此只需使用以下语句安装 ScaNN 扩展程序:
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
- 创建 ScaNN 索引:
CREATE INDEX apparel_index ON apparels
USING scann (embedding cosine)
WITH (num_leaves=54);
在上述 DDL 中:
apparel_index是索引的名称。apparels是表名称。scann是索引方法。embedding是您要编制索引的表中的列。cosine是您要用于索引的距离方法。54是要应用于此索引的分区数量。设置为介于 1 到 1048576 之间的任意值。如需详细了解如何确定此值,请参阅对 ScaNN 索引进行调优。
根据 ScaNN 代码库中的建议,我们使用了数据点数量的平方根。在进行分区时,num_leaves 应大致为数据点数量的平方根。
- 使用以下查询检查索引是否已创建:
SELECT * FROM pg_stat_ann_indexes;
- 使用与不含索引时相同的查询执行 Vector Search:
select * from apparels
ORDER BY embedding <=> CAST(embedding('textembedding-gecko', 'white tops for girls without any print') as vector(768))
LIMIT 20
上述查询与我们在实验的第 8 步中使用的查询相同。不过,现在我们已使用 ScaNN 索引为该字段编制了索引。
- 使用简单搜索查询(有索引和无索引)进行测试。如需在不使用索引的情况下进行测试,您必须删除索引:
white tops for girls without any print
在已编入索引的嵌入数据上执行 Vector Search 查询时,上述搜索文本可带来优质的搜索结果和效率。使用索引后,效率大幅提高(就执行时间而言:不使用 ScaNN 时为 10.37 毫秒,使用 ScaNN 时为 0.87 毫秒)。如需详细了解此主题,请参阅这篇博文。
9. 使用 LLM 进行匹配验证
在继续操作并创建用于向应用返回最佳匹配项的服务之前,我们先使用生成式 AI 模型来验证这些潜在的回答是否确实相关且可以安全地与用户分享。
确保实例已为 Gemini 完成设置
- 验证是否已为集群和实例启用
google_ml_integration。在 AlloyDB Studio 中,运行以下命令:
show google_ml_integration.enable_model_support;
如果该值显示为 "on",您可以跳过接下来的 2 个步骤,直接前往设置
AlloyDB 和 Vertex AI 模型集成。
- 前往 AlloyDB 集群的主实例,然后点击修改主实例。

- 在高级配置选项中,展开“新数据库标志”部分,并确保
google_ml_integration.enable_model_support flag设置为“on”,如下所示:
3. 如果未设置为“on”,请将其设置为“on”,然后点击 UPDATE INSTANCE。
此步骤需要几分钟时间。
AlloyDB 和 Vertex AI 模型集成
现在,您可以连接到 AlloyDB Studio 并运行以下 DML 语句,以从 AlloyDB 设置 Gemini 模型访问权限,并在指定位置使用您的项目 ID。运行该命令之前,您可能会收到语法错误警告,但该命令应该可以正常运行。
- 在 Google Cloud 控制台中,前往 AlloyDB。选择主集群,然后在左侧导航栏中点击 AlloyDB Studio。
- 我们将使用
google_ml_integration扩展程序默认提供的gemini-1.5-pro:generateContent。
- 您可以在 AlloyDB Studio 中通过以下命令查看配置为可供访问的模型:
select model_id,model_type from google_ml.model_info_view;
- 运行以下命令,为数据库用户授予执行 ml_predict_row 函数的权限,以便使用 Google Vertex AI 模型运行预测:
GRANT EXECUTE ON FUNCTION ml_predict_row to postgres;
评估回答
虽然我们最终会在下一部分(将应用迁移到 Cloud Run)中使用一个大型查询,但为了确保查询的响应合理,该查询可能难以理解。
我们将逐个查看各个部分,这些部分最终会构建成我们最终使用的较大查询。
- 首先,我们会向数据库发送请求,以获取与用户查询最接近的 5 个匹配项。为了简单起见,我们对查询进行了硬编码,但请放心,稍后我们会将其插值到查询中。
我们纳入了 apparels 表中的商品说明,并添加了两个新字段:一个字段将说明与索引相结合,另一个字段包含原始请求。此数据正保存在名为 xyz 的表中,这是一个临时表名称。
CREATE TABLE
xyz AS
SELECT
id || ' - ' || pdt_desc AS literature,
pdt_desc AS content,
'I want womens tops, pink casual only pure cotton.' AS user_text
FROM
apparels
ORDER BY
embedding <=> embedding('text-embedding-005',
'I want womens tops, pink casual only pure cotton.')::vector
LIMIT
5;
此查询的输出将是与用户查询相关的5 个最相似的行。该
新表 xyz 将包含 5 行,其中每行都将包含以下列:
literaturecontentuser_text
- 为了确定回答的有效性,我们将使用一个复杂的查询,其中会说明如何评估回答。它使用
xyz表中的user_text和content作为查询的一部分。
"Read this user search text: ', user_text,
' Compare it against the product inventory data set: ', content,
' Return a response with 3 values: 1) MATCH: if the 2 contexts are at least 85% matching or not: YES or NO 2) PERCENTAGE: percentage of match, make sure that this percentage is accurate 3) DIFFERENCE: A clear short easy description of the difference between the 2 products. Remember if the user search text says that some attribute should not be there, and the record has it, it should be a NO match."
- 然后,我们将使用该查询来检查
xyz表中回答的“质量”。我们所说的“优劣”是指生成的回答与我们期望的回答的接近程度。
CREATE TABLE
x AS
SELECT
json_array_elements( google_ml.predict_row( model_id => 'gemini-1.5',
request_body => CONCAT('{
"contents": [
{ "role": "user",
"parts":
[ { "text": "Read this user search text: ', user_text, ' Compare it against the product inventory data set: ', content, ' Return a response with 3 values: 1) MATCH: if the 2 contexts are at least 85% matching or not: YES or NO 2) PERCENTAGE: percentage of match, make sure that this percentage is accurate 3) DIFFERENCE: A clear short easy description of the difference between the 2 products. Remember if the user search text says that some attribute should not be there, and the record has it, it should be a NO match."
} ]
}
] }'
)::json))-> 'candidates' -> 0 -> 'content' -> 'parts' -> 0 -> 'text'
AS LLM_RESPONSE
FROM
xyz;
predict_row以 JSON 格式返回结果。代码“-> 'candidates' -> 0 -> 'content' -> 'parts' -> 0 -> 'text'"”用于从该 JSON 中提取实际文本。如需查看返回的实际 JSON,您可以移除此代码。- 最后,若要获取 LLM 字段,只需从 x 表中提取该字段即可:
SELECT
LLM_RESPONSE
FROM
x;
- 这可以合并为单个查询,如下所示:
警告:如果您已运行上述查询来检查中间结果,
请务必在运行此查询之前从 AlloyDB 数据库中删除/移除 xyz 和 x 表,
SELECT
LLM_RESPONSE
FROM (
SELECT
json_array_elements( google_ml.predict_row( model_id => 'gemini-1.5',
request_body => CONCAT('{
"contents": [
{ "role": "user",
"parts":
[ { "text": "Read this user search text: ', user_text, ' Compare it against the product inventory data set: ', content, ' Return a response with 3 values: 1) MATCH: if the 2 contexts are at least 85% matching or not: YES or NO 2) PERCENTAGE: percentage of match, make sure that this percentage is accurate 3) DIFFERENCE: A clear short easy description of the difference between the 2 products. Remember if the user search text says that some attribute should not be there, and the record has it, it should be a NO match."
} ]
}
] }'
)::json))-> 'candidates' -> 0 -> 'content' -> 'parts' -> 0 -> 'text'
AS LLM_RESPONSE
FROM (
SELECT
id || ' - ' || pdt_desc AS literature,
pdt_desc AS content,
'I want womens tops, pink casual only pure cotton.' user_text
FROM
apparels
ORDER BY
embedding <=> embedding('text-embedding-005',
'I want womens tops, pink casual only pure cotton.')::vector
LIMIT
5 ) AS xyz ) AS X;
较大的查询是我们之前步骤中运行的所有查询的组合。结果会显示是否存在匹配项、匹配百分比以及分级说明。
请注意,Gemini 模型默认开启了流式传输功能,因此实际回答会分布在多行中:
10. 将应用迁移到 Web
现在,我们将托管此应用,以便可以通过互联网访问该应用。
创建 Cloud Run 函数
- 在 Google Cloud 控制台中,使用以下链接前往 Cloud Run Functions:
https://console.cloud.google.com/run/create?deploymentType=function
- 在“配置”中,将函数名称设置为“retail-engine”,并将区域选择为“us-central1”。
- 在“端点网址”中,选择运行时为 Java 17。
- 在“身份验证”中,选择允许未通过身份验证的调用。
- 展开容器、卷、网络、安全性,然后点击网络标签页。
- 选择连接到 VPC 以发送出站流量,然后点击使用无服务器 VPC 访问通道连接器。
- 在“网络”中,点击添加新的 VPC 连接器。启用 无服务器 VPC 访问通道 API(如果尚未启用)。
- 在“创建连接器”中,将名称设置为
alloydb-test-conn。 - 将区域设置为
us-central。 - 将“网络”值保留为 default,并将子网设置为 Custom IP Range(自定义 IP 范围),IP 范围为 10.8.0.0 或类似的可用的 IP 范围。
- 展开显示扩缩设置,并将实例数下限设置为 2,将实例数上限设置为 3。
- 选择实例类型为 f1-micro。以下内容显示了“创建连接器”选项:

- 点击“创建”以创建连接器。
- 在“流量路由”中,选择将所有流量路由到 VPC。
- 点击创建以创建函数。
部署应用
创建函数后,更新源代码并重新部署应用。
- 在 Cloud Run 中,点击服务标签页,然后点击 retail-engine 函数。
- 点击“来源”标签页。将默认的函数入口点设置为“
gcfv2.HelloHttpFunction”。 - 将 HelloHttpFunction.java 文件的内容替换为此 Java 文件中的内容。
- 根据 AlloyDB 实例和集群的详细信息,更新文件中的 AlloyDbJdbcConnector 详细信息。将
$PROJECT_ID替换为 AlloyDB 集群和实例的项目 ID。

- 将 pom.xml 文件的内容替换为此 XML 文件的内容。
- 点击保存并重新部署以部署函数。
11. 测试 retail-engine 应用
部署更新后的 Cloud Functions 函数后,您应该会看到以下格式的端点:
https://retail-engine-PROJECT_NUMBER.us-central1.run.app
您可以在 Cloud Shell 终端中运行以下命令来对其进行测试:
gcloud functions call retail-engine --region=us-central1 --gen2 --data '{"search": "I want some kids clothes themed on Disney"}'
或者,您也可以按如下方式测试 Cloud Run 函数:
PROJECT_ID=$(gcloud config get-value project)
curl -X POST https://retail-engine-$PROJECT_NUMBER.us-central1.run.app \
-H 'Content-Type: application/json' \
-d '{"search":"I want some kids clothes themed on Disney"}' \
| jq .
结果:

现在,我们已使用 AlloyDB 数据上的嵌入模型运行了相似度向量搜索,接下来可以着手创建应用,该应用将使用这些嵌入以及您的图片和提示来生成样式建议
12. 了解服装搭配建议流程
服装推荐应用是一个 sprint boot 应用,它配置为与我们在 AlloyDB 零售引擎应用中创建的嵌入搭配使用,并与 Gemini 和 Imagen 搭配使用,以生成服装造型选项。您还可以添加自定义提示,并即兴创作推荐内容。
不妨这样想:您将衣橱中一件亮粉色上衣的图片上传到此应用。当您点击“显示”后,应用会根据应用代码中设置的提示和 AlloyDB 数据库中的嵌入内容,生成与原始图片相符的多个选项。现在,您想知道蓝色项链搭配建议的服装会是什么效果,因此在这些行中添加提示,然后点击“风格”。系统会生成最终图片,其中包含原始图片和建议,以便搭配出合适的服装。
如需开始创建服装搭配建议应用,请按以下步骤操作:
- 在 Cloud Run 中,打开 retail-engine 应用,并记下应用的网址。这是我们将用于生成类似建议的嵌入内容代码库。
- 在 IDE 中,克隆 https://github.com/AbiramiSukumaran/outfit-recommender/ 代码库。在此练习中,所示步骤是在 Visual Studio Code IDE 中执行的。
git clone https://github.com/AbiramiSukumaran/outfit-recommender/
以下是应用目录中的一些重要文件:
src/main:应用文件和 HTML 所在的源目录:HelloWorldApplication.java:Spring Boot 应用的主要入口点。HelloWorldController.java:用于处理与服装推荐应用相关的 HTTP 请求的 Spring Boot REST 控制器。此文件用于处理 GET 和 POST 请求、处理用户提示、分析图片、与 AlloyDB 嵌入互动,以及向界面返回最终响应。此控制器会调用 GenerateImageSample 类。GenerateImageSample.java:包含连接到 Vertex AI、设置用户提示格式、向 Imagen 模型发出 API 调用、向控制器类返回预测图片的图片生成类。Resources:此目录包含生成应用界面所需的图片和 HTML 文件。Pom.xml:定义项目依赖项和配置。
- 在 Visual Studio Code 中,打开
HelloWorldController.java并根据 AlloyDB 实例的创建位置更新项目 ID 和位置的实例。

- 将
endpoint更新为您之前托管的 retail-engine 应用网址。

- 打开
GenerateImageSample.java,然后根据 AlloyDB 实例的创建位置更新项目 ID 和位置。

- 保存所有文件。
现在,我们将此应用部署到 Cloud Run 无服务器运行时。
13. 将应用迁移到 Web
现在,我们已将相关项目、位置和 retail-engine 应用详细信息添加到服装推荐器 Spring Boot 应用中,接下来可以将该应用部署到 Cloud Run。
我们将使用 Visual Code Studio 终端中的 gcloud run deploy 命令来部署应用。对于 Visual Studio Code,您可以安装 Google Cloud Code 扩展程序,以便开始使用 gcloud CLI。
如需部署应用,请按以下步骤操作:
- 在 IDE 中,打开克隆的目录并启动终端。对于 Visual Code Studio,请依次点击 Terminal(终端)> New Terminal(新终端)。
- 按照本文档中的说明安装 gcloud CLI。
- 如果您使用的是 Visual Code Studio,请点击扩展程序,搜索 Google Cloud Code 并安装该扩展程序。
- 在 IDE 终端中,运行以下命令以验证您的 Google 账号:
gcloud auth application-default login
- 将项目 ID 设置为 AlloyDB 实例所在的项目。
gcloud config set project PROJECT_ID
- 开始部署流程。
gcloud run deploy
- 在
Source code location中,按 Enter 键选择克隆的 GitHub 目录。 - 在
Service name中,输入服务的名称,例如 outfit-recommender,然后按 Enter 键。 - 在
Please specify a region中,输入 AlloyDB 实例和 retail-engine 应用的托管位置,例如 32 表示 us-central1,然后按 Enter 键。

- 在
Allow unauthenticated invocations to [..]中,输入 Y,然后按 Enter 键。
下图显示了应用的部署进度:

14. 测试服装推荐应用
成功将应用部署到 Cloud Run 后,您可以在 Google Cloud 控制台中看到该服务,如下所示:
- 在 Google Cloud 控制台中,前往 Cloud Run。
- 在“服务”中,点击您部署的服装推荐器服务。您应该会看到 retail-engine 和 outfit-recommender 服务,如下所示:

- 点击应用网址以打开推荐器应用界面。

The following is a sample URL that you will use:
https://outfit-recommender-22905290964.us-central1.run.app/style
部署的应用如下所示:

使用应用
如需开始使用该应用,请按以下步骤操作:
- 点击上传,然后上传服装的照片。
- 上传图片后,点击样式。该应用使用图片作为提示,并根据零售引擎应用中的提示生成底部选项,其中包含零售数据集的嵌入。
该应用会根据图片生成图片建议以及包含样式建议的提示。例如 A white semi-sheer button up blouse with pink floral patterns on it, with balloon sleeves.。
- 您可以向此自动生成的样式建议传递其他提示。例如
STYLE RECOMMENDATION: Cute brown skirt on a curly updo. Make it photo realistic. Accessorize with cherry earrings and burgundy plastic case sling bag.。 - 点击显示可查看最终样式。

15. 清理
为避免系统因本博文中使用的资源向您的 Google Cloud 账号收取费用,请按照以下步骤操作:
- 在 Google Cloud 控制台中,前往管理资源页面。
- 在项目列表中,选择要删除的项目,然后点击删除。
- 在对话框中输入项目 ID,然后点击关停以删除项目。
16. 恭喜
恭喜!您已成功使用 AlloyDB、pgvector 和 Vector Search 执行相似度搜索,并结合使用搜索结果和强大的 Imagen 模型来生成样式建议。