1. 概览
“会读的聊天机器人”时代即将结束。我们正迈入智能体视觉时代。
在此 Codelab 中,我们将实现确定性 AI 工程,即构建不进行猜测的 AI 系统的实践。当被要求统计复杂图片中的物品数量时,标准 AI 模型通常会“产生幻觉”(猜测)。在供应链中,猜测是危险的。如果 AI 猜测您有 12 件商品,而您实际上有 15 件,则会触发代价高昂的错误。
我们将利用 Gemini 3 Flash 中的全新思考、行动、观察循环构建一个自主供应链代理。它不仅会查看,还会调查。
确定性架构
我们将从“盲”系统和“失忆”系统开始。您将逐一手动“唤醒”它的感官:

- Eyes(视觉智能体):我们启用了 Gemini 3 Flash 的代码执行功能。模型不是预测令牌来猜测数字,而是编写 Python 代码 (OpenCV) 来确定性地计算像素。
- 记忆(供应商代理):我们通过 ScaNN(可扩缩的最近邻)启用 AlloyDB AI。这样,代理就可以在数百万个选项中,在几毫秒内准确回忆出某个零件的供应商。
- 握手(A2A 协议):我们使用标准化的 agent_card.json 实现代理对代理通信,使 Vision Agent 能够自主地从供应商代理订购库存。
构建内容
- 一种可对摄像头画面执行“视觉数学”运算的 Vision Agent。
- 由 AlloyDB ScaNN 提供支持的供应商代理,可实现高速向量搜索。
- 一个 Control Tower 前端,具有实时 WebSocket 更新功能,可直观呈现自主循环。
学习内容
- 如何设置具有向量嵌入和 ScaNN 索引的 AlloyDB。
- 如何使用 Gemini API 启用 Agentic Vision 和 gemini-3-flash-preview。
- 如何在 AlloyDB 中使用 <=>(余弦距离)运算符实现向量搜索。
- 如何使用 AlloyDB Python 连接器将代理连接到 AlloyDB。
- 如何使用 A2A protocol 进行动态代理发现。
要求
- 一个浏览器,例如 Chrome 或 Firefox
- 启用了结算功能的 Google Cloud 项目。
- Vision Agent 的 Gemini API 密钥(免费层级可在 Google AI Studio 中获取)。
2. 准备工作
创建项目
- 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。
- 确保您的 Cloud 项目已启用结算功能。了解如何检查项目是否已启用结算功能。
- 您将使用 Cloud Shell,它是在 Google Cloud 中运行的命令行环境。点击 Google Cloud 控制台顶部的“激活 Cloud Shell”。

- 连接到 Cloud Shell 后,您可以使用以下命令检查自己是否已通过身份验证,以及项目是否已设置为您的项目 ID:
gcloud auth list
设置数据库 [AlloyDB]
在开始之前,我们先预配数据库,这需要大约 15 分钟,因此我们先启动此操作。
- 点击下方按钮,在 Cloud Shell 中打开 AlloyDB 设置工具:
- 运行设置:
Sh run.sh
- 使用网页预览(眼睛图标 👁️ → 在端口 8080 上预览)打开设置界面。
- 输入项目 ID,选择一个区域(例如 us-central1),然后创建数据库密码。
⚠️ 请保存此密码,因为设置脚本会要求您提供此密码。
- 点击“开始部署”,然后等待大约 15 分钟,让集群完成预配。
获取代码
在 AlloyDB 进行预配期间(或预配完成后),在 Cloud Shell 中打开 Codelab 代码库:
⚠️ 重要提示:点击该按钮后,您会看到一个安全对话框。选中“信任代码库”复选框,然后点击“确认”。
或者,手动克隆:
git clone https://github.com/MohitBhimrajka/visual-commerce-gemini-3-alloydb.git
cd visual-commerce-gemini-3-alloydb
设置项目
在此 Cloud Shell 终端中,确认您的项目已设置:
gcloud config set project <YOUR_PROJECT_ID>
在 AlloyDB 上启用公共 IP
AlloyDB 完成预配后,启用公共 IP,以便 Python 连接器可以从 Cloud Shell 进行连接:
- 前往 AlloyDB 控制台
- 依次点击集群 → 主实例
- 点击“修改”
- 滚动到“公共 IP 连接”,然后选中“启用公共 IP”
- 点击“更新实例”
💡 注意:AlloyDB Python 连接器会处理身份验证和加密,您无需添加任何授权的外部网络。
授予 Vertex AI 权限
AlloyDB 服务账号需要 Vertex AI 访问权限才能生成嵌入。在同一 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"
运行设置脚本
现在运行设置脚本,该脚本将自动检测您的 AlloyDB 实例:
sh setup.sh
脚本的作用:
- 验证 gcloud CLI、身份验证、项目和 Python 3
- 检查并启用必需的 API(AlloyDB、Vertex AI、Compute、Service Networking)
- 提示输入 Gemini API 密钥
- 自动检测 AlloyDB 实例并提取区域、集群和实例名称
- 要求您提供数据库密码
- 生成 .env 配置文件
- 安装 Python 依赖项
3. 数据库设置
我们应用的核心是 AlloyDB for PostgreSQL。我们将利用其强大的向量功能和 ScaNN 索引来实现近乎实时的语义搜索,让客服人员能够在数毫秒内从数千条记录中找到匹配的商品目录。
在本部分中,您将从 AlloyDB Studio 中预配架构、植入数据并生成嵌入。
连接到 AlloyDB Studio
- 前往 AlloyDB 控制台中的 AlloyDB 实例
- 点击左侧导航栏中的 AlloyDB Studio
- 使用以下方式进行身份验证:
- 用户名:postgres
- 数据库:postgres
- 密码:您在创建集群期间设置的密码
启用扩展程序
AlloyDB 为向量和 AI 提供内置扩展程序。在 AlloyDB Studio 中运行以下 SQL:
CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS alloydb_scann CASCADE;
- google_ml_integration:启用 ai.embedding() 函数,以便直接从 SQL 调用 Vertex AI。
- vector:存储和查询 768 维向量嵌入。
- alloydb_scann:启用 Google 的 ScaNN 索引,以实现超快的向量搜索。
创建媒体文件表
DROP TABLE IF EXISTS inventory;
CREATE TABLE inventory (
id SERIAL PRIMARY KEY,
part_name TEXT NOT NULL,
supplier_name TEXT NOT NULL,
description TEXT,
stock_level INT DEFAULT 0,
part_embedding vector(768)
);
part_embedding 列存储来自 text-embedding-005 的 768 维向量。这是语义搜索的动力源。
插入示例数据
插入 20 个仓库商品目录项:
INSERT INTO inventory (part_name, supplier_name, description, stock_level) VALUES
('Cardboard Shipping Box Large', 'Packaging Solutions Inc', 'Heavy-duty corrugated cardboard shipping container, 24x18x12 inches', 250),
('Warehouse Storage Container', 'Industrial Supply Co', 'Stackable plastic storage bin with snap-lock lid, blue', 180),
('Product Shipping Boxes', 'Acme Packaging', 'Medium corrugated boxes for warehouse storage, 18x14x10 inches', 320),
('Industrial Widget X-9', 'Acme Corp', 'Heavy-duty industrial coupling for pneumatic systems', 50),
('Precision Bolt M4', 'Global Fasteners Inc', 'Stainless steel M4 allen bolt, 20mm length, grade A2-70', 200),
('Hexagonal Nut M6', 'Metro Supply Co', 'Galvanized steel hex nut M6, DIN 934 standard', 150),
('Phillips Head Screw 3x20', 'Acme Corp', 'Zinc-plated Phillips head wood screw, 3mm x 20mm', 500),
('Wooden Dowel 10mm', 'Craft Materials Ltd', 'Hardwood birch dowel rod, 10mm diameter x 300mm length', 80),
('Rubber Gasket Small', 'SealTech Industries', 'Buna-N rubber gasket, 25mm OD x 15mm ID, oil resistant', 120),
('Spring Tension 5kg', 'Mechanical Parts Co', 'Stainless steel compression spring, 5kg load capacity', 60),
('Bearing 6204', 'Bearings Direct', 'Deep groove ball bearing 6204-2RS, 20x47x14mm sealed', 45),
('Warehouse Shelf Boxes', 'Storage Systems Ltd', 'Standardized warehouse inventory boxes, corrugated, bulk pack', 400),
('Inventory Container Units', 'Supply Chain Pros', 'Modular stackable storage units for warehouse racking', 95),
('Aluminum Extrusion Bar', 'MetalWorks International', 'T-slot aluminum extrusion 20x20mm profile, 1 meter length', 110),
('Cable Tie Pack 200mm', 'ElectroParts Depot', 'Nylon cable ties, 200mm x 4.8mm, UV resistant black, pack of 100', 600),
('Hydraulic Hose 1/2 inch', 'FluidPower Systems', 'High-pressure hydraulic hose, 1/2 inch ID, 3000 PSI rated', 35),
('Safety Goggles Clear', 'WorkSafe Equipment Co', 'ANSI Z87.1 rated clear safety goggles, anti-fog coating', 275),
('Packing Tape Industrial', 'Packaging Solutions Inc', 'Heavy-duty polypropylene packing tape, 48mm x 100m, clear', 450),
('Stainless Steel Sheet 1mm', 'MetalWorks International', '304 stainless steel sheet, 1mm thickness, 300x300mm', 70),
('Silicone Sealant Tube', 'SealTech Industries', 'Industrial-grade RTV silicone sealant, 300ml cartridge, grey', 190);
授予嵌入权限
GRANT EXECUTE ON FUNCTION embedding TO postgres;
生成向量嵌入
此示例使用 AlloyDB 的内置 ai.embedding() 函数直接从 SQL 调用 Vertex AI 的 text-embedding-005 模型,无需使用 Python 代码:
UPDATE inventory
SET part_embedding = ai.embedding(
'text-embedding-005',
part_name || '. ' || description
)::vector
WHERE part_embedding IS NULL;
这会生成 768 维向量,用于捕获每个零件的名称和说明的语义。ScaNN 索引将使用这些数据进行极快的相似性搜索。[完成此调查问卷大约需要 3-5 分钟]
创建 ScaNN 索引
SET scann.allow_blocked_operations = true;
CREATE INDEX IF NOT EXISTS idx_inventory_scann
ON inventory USING scann (part_embedding cosine)
WITH (num_leaves=5, quantizer='sq8');
验证一切是否正常运行
SELECT part_name, supplier_name, stock_level,
(part_embedding IS NOT NULL) as has_embedding
FROM inventory
ORDER BY id;
您应该会看到 20 行,所有行的 has_embedding 均为 true。
4. 了解架构
在更改代码之前,我们先来了解一下系统的构建方式。该架构遵循渐进式“唤醒”模式:
代理堆栈
Vision Agent (agents/vision-agent/)
- agent.py - 核心 Gemini 3 Flash 逻辑。将图片发送到启用了代码执行功能的模型,以便模型编写 Python (OpenCV) 代码来确定性地统计商品数量。
- agent_executor.py - 将 A2A protocol 请求桥接到代理逻辑。
- main.py - 提供 /.well-known/agent-card.json 并处理请求的 Uvicorn A2A 服务器。
供应商代理 (agents/supplier-agent/)
- inventory.py - 通过 AlloyDB Python 连接器连接到 AlloyDB(无需身份验证代理)。包含执行 ScaNN 向量搜索的 find_supplier() 函数。
- agent_executor.py - 将 A2A protocol 与商品目录搜索逻辑相关联。
- main.py - 带有智能体卡片和健康状况端点的 Uvicorn A2A 服务器。
控制塔(前端)
- app.py - FastAPI + WebSocket 服务器,通过 A2A 发现代理,编排视觉 → 搜索 → 订购流水线,并向浏览器流式传输实时更新。
A2A 流程
- Control Tower 从每个代理读取 /.well-known/agent-card.json
- 发现功能(技能、端点)- 无需硬编码网址
- 将图片发送到 Vision Agent → 获取商品数量 + 说明
- 将说明作为嵌入查询发送给供应商代理 → 获得部分匹配结果
- 自主下单
AlloyDB 连接
供应商代理使用 AlloyDB Python 连接器,而不是传统的 Auth Proxy:
from google.cloud.alloydbconnector import Connector
connector = Connector()
conn = connector.connect(
inst_uri, # Full instance URI
"pg8000", # Driver
user="postgres",
password=DB_PASS,
ip_type="PUBLIC", # Cloud Shell uses Public IP
)
此驱动程序会自动处理 IAM 身份验证、SSL/TLS 和连接路由。稍后部署到 Cloud Run 时,只需将 ip_type 更改为“PRIVATE”,即可实现 VPC 访问。
5. 第 1 步:记忆(供应商代理)
供应商代理使用 AlloyDB ScaNN 记住数百万个零件。目前,它随附一个占位查询,即一个健忘症患者,无论您搜索什么内容,它都会返回找到的第一行。
The Audit: The Amnesiac
如果您现在查询供应商代理,它会返回随机结果。它没有相似性的概念。让我们解决这个问题。
启动供应商代理
A2A 服务器 (main.py) 委托给 agent_executor.py,后者将协议与 inventory.py 中的业务逻辑相关联。
pkill -f uvicorn #Kill all uvicorn processes
第 1 步:前往代理目录
cd agents/supplier-agent
第 2 步:安装依赖项
pip install -r requirements.txt
第 3 步:启动代理服务器
uvicorn main:app --host 0.0.0.0 --port 8082 > /dev/null 2>&1 &
> /dev/null 2>&1 & 在后台运行服务器并抑制输出,以免中断您的终端。
第 4 步:验证代理是否正在运行(启动后等待 2-3 秒)
curl http://localhost:8082/.well-known/agent-card.json
预期输出:包含代理配置的 JSON(应无错误地返回)
修复:实现 <=> 运算符
打开 agents/supplier-agent/inventory.py,找到第 60-70 行附近的 find_supplier() 函数。您会看到以下占位符:
# TODO: Replace this placeholder query with ScaNN vector search
sql = "SELECT part_name, supplier_name FROM inventory LIMIT 1;"
cursor.execute(sql)
将这两行代码替换为:
sql = """
SELECT part_name, supplier_name,
part_embedding <=> %s::vector as distance
FROM inventory
ORDER BY part_embedding <=> %s::vector
LIMIT 1;
"""
cursor.execute(sql, (embedding_str, embedding_str))
此操作的作用:
- <=> 是 PostgreSQL 中的余弦距离运算符
- ORDER BY part_embedding <=> %s::vector 用于查找最接近的匹配项(距离最短 = 语义最接近)
- %s::vector 将您的嵌入数组转换为 PostgreSQL 的向量类型
- ScaNN 索引会自动加快此查询的速度!
第 4 步:保存文件(Ctrl+S 或 Cmd+S)
现在,代理将使用语义搜索,而不是返回随机结果!
验证
测试 A2A 发现和清单:
curl http://localhost:8082/.well-known/agent-card.json

python3 -c "
from inventory import find_supplier
import json
vec = [0.1]*768
r = find_supplier(vec)
if r:
result = {'part': r[0], 'supplier': r[1]}
if len(r) > 2:
result['distance'] = float(r[2]) if r[2] else None
print(json.dumps(result))
else:
print('No result found')
"
预期:agent-card.json 返回代理卡片。此 Python 代码段会从植入的数据中返回零件和供应商。
6. 第 2 步:眼睛(视觉智能体)
在数据库可访问的情况下,我们使用 Gemini 3 Flash 唤醒眼睛。Vision Agent 通过代码执行功能执行“视觉数学”任务。
The Audit: The Hallucination
如果您向标准多模态模型询问“这张杂乱的图片中有多少个盒子?”,它会将图片视为静态快照并进行猜测。
- 模型回答:“我看到大约 12 个盒子。”
- 实际情况:有 15 个盒子。
- 结果:供应链故障。
解决方案:唤醒“思考-行动-观察”循环
我们启用了代码执行和 ThinkingConfig,以便模型编写 Python (OpenCV) 来确定性地进行计数。
- 打开 agents/vision-agent/agent.py。
- 找到 GenerateContentConfig 部分(大约在第 68-78 行)。
- 取消注释 thinking_config=types.ThinkingConfig(...) 块和 tools=[types.Tool(code_execution=...)]。
- 客户端已配置为使用环境变量中的 GEMINI_API_KEY。
文件:agents/vision-agent/agent.py
config = types.GenerateContentConfig(
temperature=0,
# CODELAB STEP 1: Uncomment to enable reasoning
thinking_config=types.ThinkingConfig(
thinking_level="MINIMAL", # Valid: "MINIMAL", "LOW", "MEDIUM", "HIGH"
include_thoughts=False # Set to True for debugging
),
# CODELAB STEP 2: Uncomment to enable code execution
tools=[types.Tool(code_execution=types.ToolCodeExecution)]
)
为什么 thinking_level="MINIMAL"?
对于此任务(通过执行代码来统计商品数量),“MINIMAL”可提供足够的推理来规划脚本并验证统计结果。使用“高”会增加 2-3 倍的延迟,但不会提高确定性任务的准确性。成本与性能优化 - 根据任务复杂程度调整推理深度。
性价比优化是生产 AI 工程的关键技能:根据任务复杂程度调整推理深度。
启动 Vision 代理
🔄 路径检查:如果您仍在 agents/supplier-agent/ 中,请先使用 cd ../.. 返回到代码库根目录
第 1 步:前往 Vision 代理目录
cd agents/vision-agent
第 2 步:安装依赖项
pip install -r requirements.txt
第 3 步:启动视觉代理服务器
uvicorn main:app --host 0.0.0.0 --port 8081 > /dev/null 2>&1 &
> /dev/null 2>&1 & 在后台运行服务器并抑制输出,以免中断您的终端。
验证
测试 A2A 发现:
curl http://localhost:8081/.well-known/agent-card.json
预期:包含代理名称和技能的 JSON。您将在第 8 步中使用控制塔界面测试实际的视觉计数。

7. 第 3 步:握手(A2A 智能体卡片)
我们的代理会看到问题(视觉),并知道供应商(记忆)。A2A protocol 支持动态发现,即前端通过读取每个代理的卡片来了解如何与该代理通信。
A2A 与传统 REST API
式 | 传统 REST | A2A 协议 |
端点发现 | 配置中的硬编码网址 | 通过 /.well-known/agent-card.json 实现动态更新 |
功能说明 | API 文档(面向人类) | 技能(机器可读) |
集成 | 每个服务的人工代码 | 语义匹配:“我需要库存搜索”→ 发现技能 |
已添加新代理 | 更新所有客户端的配置 | 零配置 - 自动发现 |
实际益处:在传统微服务中,如果您添加了第三个“物流代理”,则需要使用其网址和 API 契约来更新控制塔的代码。借助 A2A,控制塔会自动发现该智能体,并通过自然语言技能描述了解其功能。
因此,A2A 支持即插即用型智能体组合,这是自主系统的架构模式。
创建代理卡片
🔄 路径检查:如果您仍处于 agents/vision-agent/ 中,请先使用 cd ../.. 返回到代码库根目录
代理卡片已包含在 agents/supplier-agent/agent_card.json 中。打开并查看:
{
"name": "Acme Supplier Agent",
"description": "Autonomous fulfillment for industrial parts via AlloyDB ScaNN.",
"version": "1.0.0",
"skills": [{
"id": "search_inventory",
"name": "Search Inventory",
"description": "Searches the warehouse database for semantic matches using AlloyDB ScaNN vector search.",
"tags": ["inventory", "search", "alloydb"],
"examples": ["Find stock for Industrial Widget X-9", "Who supplies ball bearings?"]
}]
}
您可以根据自己的使用情形随意自定义名称、说明或示例。
重启供应商代理以加载卡:
第 1 步:停止正在运行的代理
pkill -f "uvicorn main:app.*8082"
第 2 步:前往代理目录
cd agents/supplier-agent
第 3 步:重新启动代理
uvicorn main:app --host 0.0.0.0 --port 8082 > /dev/null 2>&1 &
> /dev/null 2>&1 & 在后台运行服务器并抑制输出,以免中断您的终端。
第 4 步:验证新的智能体卡片(启动后等待 2-3 秒)
curl http://localhost:8082/.well-known/agent-card.json
预期输出:包含您填写完毕的名称、说明和技能的 JSON。

8. 第 4 步:控制塔
使用 FastAPI + WebSockets 运行 Control Tower 前端。它通过 A2A 发现代理,并通过实时更新编排整个循环。
启动所有服务
启动所有服务的最简单方法:
验证您是否位于代码库根目录中
pwd # Should end with: visual-commerce-gemini-3-alloydb
然后进行以下操作:
sh run.sh
此单个命令会启动:
- 端口 8081 上的 Vision Agent
- 端口 8082 上的供应商代理
- 端口 8080 上的 Control Tower
等待约 10 秒,以便所有服务完成初始化。
测试系统
访问 Control Tower:
- 点击 Cloud Shell 工具栏中的网页预览按钮(眼睛图标 👁️)
- 选择“在端口 8080 上预览”
- 系统会在新标签页中打开 Control Tower 信息中心
运行演示:
- 右上角:连接状态(绿色“Live”圆点)、演示/自动模式切换开关和音频控件
- 中心:主要工作流画布,可用于上传图片和直观呈现分析结果
- 侧边栏(在分析期间显示):工作流时间轴(左侧)、进度跟踪和代码查看器(右侧)
方法 1:快速入门(推荐)
- 在首页上,您会看到一个“快速入门”部分,其中包含示例图片
- 点击任意示例图片即可自动开始分析
- 观看自主工作流(约 30-45 秒)
方法 2:自行上传
- 拖放仓库/货架图片(PNG、JPG,大小不超过 10MB),或点击“浏览”
- 点击“Initiate Autonomous Workflow”(启动自主工作流)
- 观察 4 阶段流水线
会发生什么情况:
- 智能体发现:A2A protocol 模态框显示了 Vision Agent 和 Supplier Agent 卡片,其中包含技能和端点
- 视觉分析:Gemini 3 Flash 生成并执行 Python 代码 (OpenCV) 来统计商品数量。进度条显示子步骤。检测到的项目上的边界框叠加层。结果徽章显示“✓ 经过代码验证”或“~ 估计”
- 供应商匹配:AlloyDB ScaNN 向量搜索动画。显示搜索查询(例如“工业金属箱”)。结果卡片显示匹配的零件、供应商和置信度分数
- 订单已下达:包含订单 ID、数量和详细信息的收据卡片
提示:请保持演示模式开启状态(右上角),以便在演示时在每个阶段暂停。在 AUTO 模式下,工作流会持续运行。

刚刚发生了什么
控制塔使用 A2A 协议通过 /.well-known/agent-card.json 发现两个代理,协调视觉分析(Gemini 3 Flash,可执行代码),执行向量搜索 (AlloyDB ScaNN),并自主下单,所有这些操作都通过实时 WebSocket 更新完成。每个代理都通过 A2A 标准公开其功能,从而实现即插即用的组合,而无需自定义 SDK。了解详情:A2A 协议
问题排查
与路径相关的错误:
- 运行命令时显示“No such file or directory”:您不在代码库根目录下。
# Check where you are
pwd
# If you're lost, navigate to home and back to repo
cd
cd visual-commerce-gemini-3-alloydb
服务错误:
- “Address already in use”(地址已被使用):之前运行的进程仍处于活跃状态。
# Kill all services and restart
pkill -f uvicorn
sh run.sh # Or manually restart individual agents
- 服务未启动:检查端口是否被占用:
# Check which processes are using the ports
lsof -i :8080 # Control Tower
lsof -i :8081 # Vision Agent
lsof -i :8082 # Supplier Agent
- AlloyDB 拒绝连接:验证您的 AlloyDB 实例是否已启用公共 IP
9. 🎁 奖励:部署到 Cloud Run
可选 - 一切都在本地运行!但如果您想通过公开网址分享自己的创作,请执行以下操作:
# From repo root
sh deploy/deploy.sh
会出现什么情况:
- 读取您的 .env 配置
- 询问您的姓名(显示在已部署的应用中)
- 将所有 3 项服务部署为单个 Cloud Run 容器
- 授予用于 AlloyDB 访问权限的 IAM 角色
- 输出可共享的网址
打开您的网址的访问者会看到一个弹出式窗口:
10. 清理
为避免产生费用,请使用自动清理脚本销毁所有资源:
# From repo root
sh deploy/cleanup.sh
此操作可安全移除:
- AlloyDB 集群(主要费用驱动因素)
- Cloud Run 服务(如果已部署)
- 关联的服务账号
在删除任何内容之前,脚本会提示您进行确认。
11. 参考资料和拓展阅读材料
本 Codelab 中的所有技术声明均已通过 Google Cloud 和 Google AI 官方文档验证。
官方文档
Gemini 3 Flash:
- 代码执行 API:https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/code-execution-api
- 开发者指南:https://ai.google.dev/gemini-api/docs/gemini-3
- 模型文档:https://docs.cloud.google.com/vertex-ai/generative-ai/docs/models/gemini/3-flash
- 模型卡片:https://deepmind.google/models/gemini/flash/
AlloyDB AI 和 ScaNN:
- ScaNN 性能基准:https://cloud.google.com/blog/products/databases/how-scann-for-alloydb-vector-search-compares-to-pgvector-hnsw
- 了解 ScaNN 索引:https://cloud.google.com/blog/products/databases/understanding-the-scann-index-in-alloydb
- AlloyDB AI 深度剖析:https://cloud.google.com/blog/products/databases/alloydb-ais-scann-index-improves-search-on-all-kinds-of-data
- 调优最佳实践:https://docs.cloud.google.com/alloydb/docs/ai/best-practices-tuning-scann
- AlloyDB 文档:https://cloud.google.com/alloydb/docs
MCP Toolbox for Databases(替代方法):
价格信息:
- Gemini API 定价:https://ai.google.dev/gemini-api/docs/pricing
- AlloyDB 价格:https://cloud.google.com/alloydb/pricing
- Vertex AI 价格:https://cloud.google.com/vertex-ai/pricing
经过验证的性能声明
功能 | 领取 | 来源 |
ScaNN 与 HNSW(过滤后) | 速度提升 10 倍 | Google Cloud 博客(已验证) |
ScaNN 与 HNSW(标准) | 速度达到原来的 4 倍 | Google Cloud 博客(已验证) |
ScaNN 内存占用 | 小 3-4 倍 | Google Cloud 博客(已验证) |
ScaNN 索引构建时间 | 速度达到原来的 8 倍 | Google Cloud 博客(已验证) |
代码执行超时 | 最长 30 秒 | Google Cloud 文档(已验证) |
代码执行文件 I/O | 不支持 | Google Cloud 文档(已验证) |
温度=0 的行为 | 确定性输出 | 已经过社区验证 |
其他资源
Agent-to-Agent (A2A) 协议:
- A2A 可标准化代理发现和通信
- 在
/.well-known/agent-card.json中提供的智能体卡片 - 自主智能体协作的新兴标准
ScaNN 研究:
- 基于 12 年的 Google 研究
- 为 Google 搜索和 YouTube 提供支持,规模达数十亿
- 正式版发布时间:2024 年 10 月
- 第一个适用于百万到十亿向量的 PostgreSQL 向量索引
12. 挑战模式:提升智能体技能
您已构建一个可正常运行的自主供应链。准备好进一步探索了吗?这些挑战会将您学到的模式应用到新问题中。
挑战 1:基于图片的搜索(多模态嵌入)
当前流程:视觉智能体统计商品数量 → 生成文本查询 → 供应商智能体嵌入文本 → 搜索 AlloyDB
挑战:完全绕过文本,直接将剪裁后的图片发送给供应商代理。
提示:
- Vision Agent 的代码执行可以从货架图片中剪裁单个商品
- Vertex AI 的 multimodalembedding@001 模型可以直接嵌入图片
- 修改 inventory.py 以接受图片字节,而不是文本
- 更新了 A2A 技能说明,以表明“接受:image/jpeg 或 text”
重要性:对于外观复杂的部件(颜色变化、损坏、包装差异),视觉搜索的准确性更高。
挑战 2:可观测性 - 以透明赢得信任
当前状态:系统正常运行,但您无法查看“幕后”情况
挑战:检查 AlloyDB 的查询日志,以证明向量搜索正在执行。
步骤:
- 默认情况下,AlloyDB 会启用 Query Insights。如需对此进行验证,请运行以下命令:
gcloud alloydb instances describe INSTANCE_NAME \
--cluster=CLUSTER_NAME \
--region=us-central1 \
--format="value(queryInsightsConfig.queryPlansPerMinute)"
- 通过界面运行供应商搜索
- 查看实际执行的 SQL:
gcloud logging read \
'resource.type="alloydb.googleapis.com/Instance" AND textPayload:"ORDER BY part_embedding"' \
--limit 5 \
--format=json
预期输出:您将看到确切的 ORDER BY part_embedding <=> $1::vector LIMIT 1 查询以及执行时间。
重要性:可观测性有助于建立信任。当利益相关方询问“此代理如何做出决策?”时,您可以向他们展示查询计划,而不仅仅是输出。
挑战 3:多智能体组合
挑战:添加第三个代理(物流代理),该代理可根据仓库位置和商品重量计算运费。
架构:
- Vision Agent 输出:商品数量
- 供应商代理的输出:供应商位置
- 物流代理 (NEW) 输入:目的地、重量 → 输出:运费 + 预计到达时间
提示:A2A protocol 可让此操作变得非常简单,只需创建一个具有 calculate_shipping 技能的新代理卡片即可。控制塔会自动发现该账号。
您正在学习的模式:这是面向智能体的架构的核心,即由小型可组合的专家构建的复杂系统。
13. 总结
您已成功从生成式 AI 改用智能体 AI。
我们构建了:
- 视觉:我们已将“猜测”替换为代码执行(通过 API 密钥使用 Gemini 3 Flash)。
- 内存:我们已将“慢速搜索”替换为 AlloyDB ScaNN(通过 GCP)。
- 操作:我们将“API 集成”替换为 A2A 协议。
混合架构的优势:
此 Codelab 演示了一种混合方法:
- Vision Agent:使用 Gemini API(API 密钥)- 简单易用,提供免费层级,无需 GCP 结算
- 供应商代理:使用 GCP (Vertex AI + AlloyDB) - 企业级、符合法规要求
这是自治经济的架构。您可以保留此代码。
后续步骤