1. 概览
如今,使用 AI 构建应用从何处着手?对于我们大多数人来说,这通常始于一个简单的问题:“模型是否真的能帮助解决我一直在思考的问题?”这正是 Google AI Studio 的用武之地。您可以在这里快速设计任何原型。我一直想改造厨房,我猜 Gemini 能帮上忙,但我是一名工程师,而不是总承包商。我甚至不确定该问什么问题,因为需要考虑的因素太多了:法规、固定装置等。因此,让我们先将问题分解,让 Gemini 为我们生成一个非常详细的提示,然后生成完整的装修计划,并直观呈现改造效果!但请稍等。从这里开始,我该如何真正帮助企业实现规模化发展?输入 AGENTS!!!
智能体是一种自主程序,它会与 AI 模型对话,使用其拥有的工具和上下文执行基于目标的操作,并且能够根据事实自主做出决策!
智能体开发套件 (ADK)
智能体开发套件 (ADK) 是一个灵活的模块化框架,用于开发和部署 AI 智能体。ADK 支持通过将多个不同的代理实例组合成多代理系统 (MAS) 来构建复杂的应用。
在 ADK 中,多智能体系统是指一个应用,其中不同的智能体(通常形成层次结构)通过协作或协调来实现更大的目标。以这种方式构建应用具有显著优势,包括增强的模块化、专业化、可重用性、可维护性,以及使用专用工作流代理定义结构化控制流的能力。
构建内容
准备好从我们的原型 PROMPT 转到构建智能体了吗?我们将创建一个代理,以帮助生成厨房改造项目的提案文档。在本实验中,您将:
- 使用 ADK 构建一个简单的智能体来生成装修提案文档
- 将生成的装修提案文档存储在 Cloud Storage 存储分区中
- 在 Cloud Shell 和代理网页输出中测试代理
要求
2. 准备工作
创建项目
- 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。
- 确保您的 Cloud 项目已启用结算功能。了解如何检查项目是否已启用结算功能。
- 此外,如果您正在阅读本文,并希望获得一些赠金来帮助您开始使用 Google Cloud 和 ADK,请使用此链接 兑换赠金。
- 您可以按照此处的说明兑换。请注意,此链接仅在 2025 年 7 月 15 日之前有效,可用于兑换。
- 点击此链接,激活 Cloud Shell。您可以点击 Cloud Shell 中的相应按钮,在 Cloud Shell 终端(用于运行云命令)和编辑器(用于构建项目)之间切换。
- 连接到 Cloud Shell 后,您可以使用以下命令检查自己是否已通过身份验证,以及项目是否已设置为您的项目 ID:
gcloud auth list
- 在 Cloud Shell 中运行以下命令,以确认 gcloud 命令了解您的项目。
gcloud config list project
- 如果项目未设置,请使用以下命令进行设置:
gcloud config set project <YOUR_PROJECT_ID>
- 确保已安装 Python 3.9 及更高版本
如需了解其他 gcloud 命令和用法,请参阅文档。
3. 原型
前往 Google AI Studio。开始输入提示。我的提示如下:
I want to renovate my kitchen, basically just remodel it. I don't know where to start. So I want to use Gemini to generate a plan. For that I need a good prompt. Give me a short yet detailed prompt that I can use.
调整和配置右侧的参数,以获得最佳回答。
根据这个简单的描述,Gemini 为我生成了一个非常详细的提示,让我可以开始装修了!实际上,我们是使用 Gemini 来让 AI Studio 和我们的模型提供更出色的回答。您还可以根据自己的应用场景选择要使用的不同模型。
我们选择了 Gemini 2.5 Pro。这是一个思考模型,这意味着我们可以获得更多输出令牌,在本例中最多可获得 65K 个令牌,用于生成长篇分析和详细文档。启用 Gemini 2.5 Pro 后,系统会显示 Gemini 思考框,该模型具有原生推理能力,可以处理长上下文请求。
请参阅下方的响应代码段:

AI Studio 分析了我的数据,并生成了橱柜、台面、防溅挡板、地板、水槽、内聚性、调色板和材料选择等所有这些内容。Gemini 甚至还会注明信息来源!
现在,尝试使用不同的提示,看看创意如何变为现实。
- 复制此提示并将其粘贴到提示编辑器中:
Add flat and circular light accessories above the island area for my current kitchen in the attached image.
- 附上您当前厨房的照片(您也可以使用我的厨房示例图片)。
- 将模型更改为“Gemini 2.0 Flash 预览版图片生成”,以便您能够生成图片。
我获得了以下输出:

这就是 Gemini 的强大之处!
从理解视频、原生图片生成到借助 Google 搜索建立真实信息依据,有些功能只能通过 Gemini 构建。
在 AI Studio 中,您可以获取此原型,然后获取 API 密钥,并使用 Vertex AI ADK 的强大功能将其扩展为完整的代理应用。
4. ADK 设置
现在,我们前往在“准备工作”部分中激活的 Cloud Shell 终端:
- 创建并激活虚拟环境(推荐)
在 Cloud Shell 终端中,创建虚拟环境:
python -m venv .venv
激活虚拟环境:
source .venv/bin/activate
- 安装 ADK
pip install google-adk
5. 项目结构
- 在 Cloud Shell 终端中,在所需项目位置为您的 agentic 应用创建一个根目录:
mkdir agentic-apps
- 在主目录中,创建一个特定于当前项目的文件夹:
mkdir renovation-agent
- 前往 Cloud Shell 编辑器,然后创建以下项目结构(先创建空文件):
renovation-agent/
__init__.py
agent.py
requirements.txt
.env
6. 源代码
- 前往“init.py”,并更新为以下内容:
from . import agent
- 前往 agent.py,然后使用以下路径中的以下内容更新该文件:
在 agent.py 中,我们导入必要的依赖项,从 .env 文件中检索配置参数,并定义 root_agent,该代理会生成提案文档并将其存储在 Cloud Storage 存储分区中。为了完成 Cloud Storage 步骤,我们将使用名为 store_pdf 的工具。
注意:目前,PDF 尚未设置格式!根据社区开发者的 PR,以下代码段已包含在此处 [未经测试],您可以随意将其纳入 store_pdf 方法中:
doc = SimpleDocTemplate(
pdf_buffer,
pagesize=letter,
rightMargin=0.75 * inch,
leftMargin=0.75 * inch,
topMargin=0.75 * inch,
bottomMargin=0.75 * inch
)
styles = getSampleStyleSheet()
story = []
# --- CUSTOM STYLES FOR HEADERS ---
# Define a new style for section headers
styles.add(ParagraphStyle(name='SectionHeader',
parent=styles['Normal'],
fontName='Helvetica-Bold', # Make it bolder
fontSize=14, # Make it slightly larger
leading=16, # Line spacing
spaceAfter=0.15 * inch, # Space after the header
spaceBefore=0.25 * inch, # Space before the header
textColor=black # Ensure color is bright/black (default is usually black, but explicit is good)
))
# Define a style for the main document title
styles.add(ParagraphStyle(name='DocumentTitle',
parent=styles['Normal'],
fontName='Helvetica-Bold',
fontSize=20,
leading=24,
spaceAfter=0.25 * inch,
alignment=TA_CENTER, # Center align the title
textColor=black
))
# ---------------------------------
paragraphs_raw = pdf_text.split('\n\n')
# Heuristic for the garbled line issue (as before, temporary)
if paragraphs_raw and len(paragraphs_raw[-1]) < 50 and any(char in paragraphs_raw[-1] for char in ['io', 'og', 'al', 'op']):
logger.warning("Detected potentially garbled last paragraph. Attempting to trim/omit.")
paragraphs_raw[-1] = "11. Entire Agreement:\nThis proposal constitutes the entire agreement between the parties and supersedes all prior discussions and agreements."
for i, para_text in enumerate(paragraphs_raw):
para_text = para_text.strip()
if not para_text:
continue
# Special handling for the main document title (PROPOSAL DOCUMENT)
if i == 0 and "PROPOSAL DOCUMENT" in para_text.upper():
p = Paragraph("PROPOSAL DOCUMENT", styles['DocumentTitle'])
story.append(p)
story.append(Spacer(1, 0.15 * inch)) # Add space after the title
# Skip the rest of this initial block if it's just the title
remaining_text_lines = para_text.splitlines()[1:]
if remaining_text_lines:
formatted_text = "<br/>".join(remaining_text_lines)
p = Paragraph(formatted_text, styles['Normal'])
story.append(p)
story.append(Spacer(1, 0.1 * inch))
continue # Move to the next paragraph
# Check if the paragraph looks like a section header (e.g., starts with a number and dot or just bold text)
# This is a heuristic and might need fine-tuning based on actual proposal content variability.
is_section_header = False
# Check for numbered sections (e.g., "1. Scope of Work:")
if para_text.startswith(('1.', '2.', '3.', '4.', '5.', '6.', '7.', '8.', '9.', '10.', '11.')):
is_section_header = True
# Check for Exhibit headers (e.g., "Exhibit A: Cabinet Design") or Roman numeral headings
elif para_text.startswith(('Exhibit ', 'I.', 'II.', 'III.', 'IV.', 'V.', 'VI.', 'VII.')):
is_section_header = True
# Check for specific known headers
elif para_text.strip().upper() in ["IN WITNESS WHEREOF,", "EXHIBITS:"]:
is_section_header = True
if is_section_header:
p = Paragraph(para_text, styles['SectionHeader'])
story.append(p)
# No additional Spacer here, as SectionHeader style has spaceAfter
else:
formatted_text = para_text.replace('\n', '<br/>')
p = Paragraph(formatted_text, styles['Normal'])
story.append(p)
story.append(Spacer(1, 0.1 * inch)) # Standard space after body paragraphs
doc.build(story)
pdf_buffer.seek(0)
# Upload the PDF to GCS
storage_client = storage.Client()
bucket = storage_client.bucket(STORAGE_BUCKET)
blob = bucket.blob(PROPOSAL_DOCUMENT_FILE_NAME)
blob.upload_from_file(pdf_buffer, content_type="application/pdf")
logger.info(f"Successfully uploaded PDF to gs://{STORAGE_BUCKET}/{PROPOSAL_DOCUMENT_FILE_NAME}")
except Exception as e:
logger.error(f"Error writing text to PDF and uploading: {e}")
raise
finally:
if 'pdf_buffer' in locals():
pdf_buffer.close()
return "Successfully uploaded PDF to GCS!!"
- 确保您拥有 Cloud Storage 存储分区
用于存储代理生成的提案文档。创建该服务账号并配置访问权限,以便我们使用 Vertex AI 创建的智能体系统可以访问该服务账号。具体方法如下:
https://cloud.google.com/storage/docs/creating-buckets#console
将存储分区命名为“next-demo-store”。如果您将其命名为其他名称,请务必更新 .env 文件(在“设置环境变量”步骤中)中 STORAGE_BUCKET 的值。
- 如需设置对存储分区的访问权限,请前往 Cloud Storage 控制台,然后前往您的存储分区(在本例中,存储分区名称为“next-demo-storage”:https://console.cloud.google.com/storage/browser/next-demo-storage)。
依次前往“权限”>“查看主账号”>“授予访问权限”。选择“allUsers”作为正文,并选择“Storage Object User”作为角色。
Make sure to not enable "prevent public access". Since this is a demo/study application we are going with a public bucket. Remember to configure permission settings appropriately when you are building your application.
- 创建依赖项列表
在 requirements.txt 中列出所有依赖项。您可以从 repo 中复制此内容。
单代理系统源代码说明
agent.py 文件使用智能体开发套件 (ADK) 定义了厨房改造多智能体系统的结构和行为。下面我们来分解一下关键组件:
代理定义
根代理(编排器):proposal_agent
root_agent 充当此单代理系统的编排器。它会接收初始装修请求,并根据请求的需求确定要调用哪些工具。
然后,根代理会收集工具的回答,并将它们合并起来,为用户提供全面的回答。在本例中,我们只有一个工具“store_pdf”。
7. 数据流和关键概念
用户通过 ADK 界面(终端或网页界面)发起请求。
- 根代理收到请求。
- 根代理会分析请求,并在需要时将其路由到工具。
- “store_pdf”工具旨在将翻新的文本内容写入 PDF 文件,然后将其上传到 Google Cloud Storage。
- 然后,该代理会将响应返回给根代理。
- 根代理会合并响应,并向用户提供最终输出。
LLM(大语言模型)
智能体主要依靠 LLM 来生成文本、回答问题和执行推理任务。LLM 是智能体能够理解和响应用户请求的“大脑”。我们在此应用中使用的是 Gemini 2.5。
Google Cloud Storage
用于存储生成的装修方案文档。您需要创建一个存储分区,并授予代理访问该存储分区所需的权限。
Cloud Run(可选)
OrderingAgent 使用 Cloud Run functions 与 AlloyDB 进行交互。Cloud Run 提供了一个无服务器环境,用于执行代码以响应 HTTP 请求。
AlloyDB
如果您使用的是 OrderingAgent,则需要设置 AlloyDB 数据库来存储订单信息。
.env 文件
.env 文件用于存储 API 密钥、数据库凭据和存储分区名称等敏感信息。请务必确保此文件的安全性,并且不要将其提交到代码库中。它还存储代理和 Google Cloud 项目的配置设置。root_agent 或支持函数通常会从此文件中读取值。确保在 .env 文件中正确设置了所有必需的变量。这包括 Cloud Storage 存储分区名称
8. 模型设置
代理理解用户请求和生成回答的能力由大语言模型 (LLM) 提供支持。您的代理需要安全地调用此外部 LLM 服务,这需要身份验证凭据。如果没有有效的身份验证,LLM 服务会拒绝代理的请求,并且代理将无法正常运行。
- 从 Google AI Studio 获取 API 密钥。
- 在下一步中,您将设置 .env 文件,并将
<<your API KEY>>替换为您的实际 API 密钥值。
9. 环境变量设置
- 在此代码库中,为模板 .env 文件中的参数设置值。在我的示例中,.env 包含以下变量:
GOOGLE_GENAI_USE_VERTEXAI=FALSE
GOOGLE_API_KEY=<<your API KEY>>
GOOGLE_CLOUD_LOCATION = us-central1 <<or your region>>
GOOGLE_CLOUD_PROJECT = <<your project id>>
PROJECT_ID = <<your project id>>
GOOGLE_CLOUD_REGION=us-central1 <<or your region>>
STORAGE_BUCKET = next-demo-store <<or your storage bucket name>>
将占位符替换为您的值。
10. 运行代理
- 使用终端,前往智能体项目的父级目录:
cd agentic-apps/renovation-agent
- 安装所有依赖项
pip install -r requirements.txt
- 您可以在 Cloud Shell 终端中运行以下命令来执行代理:
adk run .
- 您可以运行以下命令,在 ADK 配置的 Web 界面中运行该应用:
注意:您必须从智能体项目文件夹外部运行此命令,退出该文件夹,然后再运行此命令:
adk web
- 使用以下提示进行测试:
user>>
Hello. Generate Proposal Document for the kitchen remodel requirement in a proper format that applies to a renovation contract. Remember this text will eventually be stored as a pdf file so make sure to have the formatting appropriate. I have no other specification.
11. 结果
对于命令 adk run .result is as follows"


…

您可以验证装修提案文档是否已在 Cloud Storage 存储分区中创建。
12. 部署到 Cloud Run
- 在项目根文件夹中创建一个名为 Dockerfile 的文件:
cd agentic-apps/renovation-agent
- 从 GitHub 代码库复制内容
https://github.com/AbiramiSukumaran/adk-renovation-single-agent/blob/main/Dockerfile
到此 Dockerfile 文件中。
- 使用以下命令在 Cloud Run 上进行部署:
adk deploy cloud_run --project=abis-345004 --region=us-central1 --service_name=renovation-agent --app_name=renovation-app --with_ui .
大功告成。部署完成后,您应该会在终端中看到端点,该端点即可供您使用。
13. 清理
为避免系统因本博文中使用的资源向您的 Google Cloud 账号收取费用,请按照以下步骤操作:
- 在 Google Cloud 控制台中,前往管理资源页面。
- 在项目列表中,选择要删除的项目,然后点击删除。
- 在对话框中输入项目 ID,然后点击关停以删除项目。
14. 恭喜
恭喜!您已成功使用 ADK 创建并与多智能体应用互动!多代理系统旨在通过自动执行提案生成、许可检查和订单状态跟踪等任务来简化厨房改造流程。每个代理都有特定的角色,而根代理会协调它们的活动,以提供全面的解决方案。该系统利用 LLM、Google Cloud 服务以及可能的外部 API 来实现其功能。点击此处可查看产品文档。