1. 概览
如今,使用 AI 构建应用从何处着手?对于我们大多数人来说,这通常始于一个简单的问题:“模型是否真的能帮助解决我一直在思考的问题?”这正是 Google AI Studio 的用武之地。您可以在这里快速设计任何原型。我一直想改造厨房,相信 Gemini 能帮上忙,但我是一名工程师,而不是总承包商。我甚至不确定该问什么问题,因为需要考虑的因素太多了:法规、固定装置等。因此,让我们先将问题分解,让 Gemini 为我们生成一个非常详细的提示,然后生成完整的装修计划,并直观呈现改造后的效果!但请稍等。从这里开始,我该如何真正帮助企业实现规模化发展?输入代理!!!
智能体是一种自主程序,它会与 AI 模型对话,使用其拥有的工具和上下文执行基于目标的运算,并且能够根据事实做出自主决策!
智能体开发套件 (ADK)
智能体开发套件 (ADK) 是一个灵活的模块化框架,用于开发和部署 AI 智能体。ADK 支持将多个不同的智能体实例组合成一个多智能体系统 (MAS),从而构建复杂的应用。
在 ADK 中,多智能体系统是指由不同智能体进行协作或协调以实现更大目标的应用(这些智能体通常会形成层次结构)。以这种方式构建应用具有显著优势,包括增强模块化、专业化、可重用性、可维护性,以及使用专用工作流智能体定义结构化控制流的能力。
构建内容
准备好从原型提示转到构建智能体了吗?我们将创建一个智能体,帮助生成厨房翻修项目的提案文档。在本实验中,您将:
- 使用 ADK 构建一个简单的智能体来生成装修提案文档
- 将生成的装修提案文档存储在 Cloud Storage 存储分区中
- 在 Cloud Shell 和代理 Web 输出中测试代理
要求
2. 准备工作
创建项目
- 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。
- 确保您的 Cloud 项目已启用结算功能。了解如何检查项目是否已启用结算功能。
- 点击此链接,激活 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 思考框。Gemini 2.5 Pro 具有原生推理能力,可以处理长上下文请求。
请参阅下方的响应代码段:

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 终端,在所需的项目位置为智能体应用创建一个根目录:
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 中复制此内容。
单智能体系统源代码说明
对于我们使用智能体开发套件 (ADK) 开发的厨房翻修多智能体系统,agent.py 文件将定义其结构和行为。我们来逐一了解各个主要组成部分:
代理定义
根智能体(编排器):proposal_agent
root_agent 将充当此单智能体系统的编排器。它会接收初始翻修请求,并根据请求中包含的需求确定要调用的工具。
然后,root_agent 会收集工具的回答并将它们组合起来,从而为用户提供全面的回答。在本例中,我们只有一个工具“store_pdf”。
7. 数据流和主要概念
用户通过 ADK 界面(终端或 Web 界面)发起请求。
- root_agent 收到请求。
- root_agent 会分析请求,并在需要时将其路由到工具。
- “store_pdf”工具旨在将翻新后的文本内容写入 PDF 文件,然后将其上传到 Google Cloud Storage。
- 然后,将回答返回给 root_agent。
- root_agent 将这些回答组合起来,向用户提供最终输出。
LLM(大语言模型)
智能体严重依赖 LLM 来生成文本、回答问题和执行推理任务。LLM 是助力智能体理解用户请求并提供回答的“大脑”。我们在此应用中使用的是 Gemini 2.5。
Google Cloud Storage
用于存储生成的翻修提案文档。您需要创建一个存储桶,并为智能体授予访问该存储桶所需的权限。
Cloud Run(可选)
OrderingAgent 使用 Cloud Run 函数与 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 .结果如下”


…

您可以验证装修提案文档是否已在 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 创建多智能体应用并与之互动!多智能体系统旨在通过自动执行提案生成、许可检查和订单状态跟踪等任务,简化厨房翻修流程。每个智能体都有特定的角色,root_agent 负责协调它们的活动,以提供全面的解决方案。该系统利用 LLM、Google Cloud 服务和可能的外部 API 来提供其功能。如需了解该系统,请点击此产品文档链接。