1. 简介
本 Codelab 将向您展示如何使用 Gemini 文件搜索在 Agentic 应用中启用 RAG。您将使用 Gemini 文件搜索功能来提取文档内容并为其编制索引,而无需担心分块、嵌入或向量数据库的细节。
学习内容
- RAG 的基础知识以及我们为何需要它。
- Gemini 文件搜索的定义及其优势。
- 如何创建文件搜索存储区。
- 如何将自己的自定义文件上传到文件搜索商店。
- 如何将 Gemini 文件搜索工具用于 RAG。
- 使用 Google 智能体开发套件 (ADK) 的优势。
- 如何在基于 ADK 构建的智能体解决方案中使用 Gemini 文件搜索工具。
- 如何将 Gemini 文件搜索工具与 Google“原生”工具(例如 Google 搜索)搭配使用。
您将执行的操作
- 创建 Google Cloud 项目并设置开发环境。
- 使用 Google Gen AI SDK(但不使用 ADK)创建一个简单的基于 Gemini 的代理,该代理能够使用 Google 搜索,但没有 RAG 功能。
- 证明其无法针对定制信息提供准确、高质量的信息。
- 创建一个 Jupyter 笔记本(您可以在本地运行,也可以在 Google Colab 上运行),用于创建和管理 Gemini 文件搜索存储区。
- 使用笔记本电脑将自定义内容上传到文件搜索商店。
- 创建一个附加了文件搜索存储区的代理,并证明该代理能够生成更优质的回答。
- 将初始的“基本”代理转换为 ADK 代理,并添加 Google 搜索工具。
- 使用 ADK 网页界面测试智能体。
- 使用“智能体即工具”模式将文件搜索存储区纳入 ADK 智能体中,以便我们能够同时使用文件搜索工具和 Google 搜索工具。
2. 什么是 RAG 以及我们为什么需要它
所以…检索增强生成。
如果您来到这里,可能已经知道什么是 Google Analytics,但我们还是快速回顾一下,以防万一。LLM(例如 Gemini)非常出色,但存在一些问题:
- 它们总是过时的:它们只知道在训练期间学到的知识。
- 它们并非无所不知:当然,这些模型非常庞大,但并非无所不知。
- 它们不知道您的专有信息:它们拥有广泛的知识,但没有读过您的内部文档、博客或 Jira 工单。
因此,当您向模型询问它不知道答案的问题时,您通常会得到不正确的回答,甚至会得到编造的回答。通常,模型会自信地给出这个错误答案。我们将此称为幻觉。
一种解决方案是将我们的专有信息直接转储到对话上下文中。对于少量信息,这种方法还不错,但当信息量很大时,很快就会出现问题。具体而言,这会导致以下问题:
- 延迟时间:模型响应速度越来越慢。
- 信号衰减,也称为“中间丢失”:模型无法再从垃圾数据中过滤出相关数据。模型会忽略大部分上下文。
- 费用:因为 token 需要付费。
- 上下文窗口耗尽:此时,Gemini 将不会执行您的请求。
解决此问题的更有效方法是使用 RAG。它只是一个从您的数据源中查找相关信息(使用语义匹配)并将这些数据的相关块与您的问题一起提供给模型的过程。它让模型立足于您的实际情况。
其工作原理是导入外部数据,将数据切分为块,将数据转换为向量嵌入,然后将这些嵌入存储到合适的向量数据库中并为其编制索引。

因此,为了实现 RAG,我们通常需要考虑以下方面:
- 启动向量数据库(Pinecone、Weaviate、Postgres with pgvector...)。
- 编写分块脚本来分割文档(例如 PDF、Markdown 等)。
- 使用嵌入模型为这些块生成嵌入(向量)。
- 将向量存储在向量数据库中。
但朋友不会让朋友过度设计。如果我告诉您,有一种更简单的方法呢?
3. 前提条件
创建 Google Cloud 项目
您需要一个 Google Cloud 项目才能运行此 Codelab。您可以使用现有项目,也可以创建新项目。
确保您的项目已启用结算功能。如需了解如何查看项目的结算状态,请参阅本指南。
请注意,完成此 Codelab 不会产生任何费用。最多几美分。
继续操作,准备好您的项目。我会等。
克隆演示代码库
我创建了一个包含此 Codelab 的引导式内容的代码库。您会需要的!
在终端或集成到 Google Cloud Shell 编辑器中的终端中运行以下命令。Cloud Shell 及其编辑器非常方便,因为您需要的所有命令都已预安装,并且一切都可以“开箱即用”。
git clone https://github.com/derailed-dash/gemini-file-search-demo cd gemini-file-search-demo
此树显示了代码库中的关键文件夹和文件:
gemini-file-search-demo/ ├── app/ │ ├── basic_agent_adk/ # Agent with Google Search, using ADK framework │ │ └── agent.py │ ├── rag_agent_adk/ # Agent with Google Search and File Search, using ADK framework │ │ ├── agent.py │ │ └── tools_custom.py │ ├── sdk_agent.py # Agent using GenAI SDK (no ADK) with Google Search tool │ └── sdk_rag_agent.py # Agent using GenAI SDK (no ADK) with Gemini File Search tool ├── data/ │ └── story.md # Sample story with "bespoke content" to use with Gemini File Search Store ├── notebooks/ │ └── file_search_store.ipynb # Jupyter notebook for creating and managing Gemini File Search Store │ ├── .env.template # Template for environment variables - make a copy as .env ├── Makefile # Makefile for `make` commands ├── pyproject.toml # Project configuration and dependencies └── README.md # This file
在 Cloud Shell 编辑器或您偏好的编辑器中打开此文件夹。(您使用过 Antigravity 吗?如果还没有,不妨现在试一试。)
请注意,该代码库包含一个示例故事“The Wormhole Incursion”,位于文件 data/story.md 中。我与 Gemini 共同撰写了这篇文章!讲述的是达兹博指挥官和他麾下的一支由智能星舰组成的战队的故事。(我从游戏《Elite Dangerous》中获得了一些灵感。)这个故事充当了我们的“定制知识库”,其中包含 Gemini 不知道的具体事实,而且 Gemini 无法使用 Google 搜索来查找这些事实。
设置开发环境
为方便起见,我提供了一个 Makefile 来简化您需要运行的许多命令。您只需运行类似 make <target> 的命令,而无需记住具体命令。不过,make 仅在 Linux / MacOS / WSL 环境中可用。如果您使用的是 Windows(不含 WSL),则需要运行 make 目标包含的完整命令。
# Install dependencies with make make install # If you don't have make... uv sync --extra jupyter
在 Cloud Shell 编辑器中运行 make install 时,您会看到以下内容:

创建 Gemini API 密钥
如需使用 Gemini Developer API(使用 Gemini 文件搜索工具需要此 API),您需要一个 Gemini API 密钥。获取 API 密钥的最简单方法是使用 Google AI Studio,它提供了一个便捷的界面,可用于获取 Google Cloud 项目的 API 密钥。如需了解具体步骤,请参阅本指南。
创建 API 密钥后,请复制并妥善保管该密钥。
现在,您需要将此 API 密钥设置为环境变量。我们可以使用 .env 文件来实现此目的。将随附的 .env.example 复制为名为 .env 的新文件。文件内容应如下所示:
export GEMINI_API_KEY="your-api-key" export MODEL="gemini-2.5-flash" export STORE_NAME="demo-file-store"
请将 your-api-key 替换为您的实际 API 密钥。现在,它应该如下所示:

现在,请确保已加载环境变量。为此,您可以运行以下命令:
source .env
4. 基本代理
首先,我们来建立一个基准。我们将使用原始的 google-genai SDK 来运行一个简单的代理。
代码
您可以查看 app/sdk_agent.py。这是一个最小实现,可执行以下操作:
- 实例化
genai.Client。 - 启用
google_search工具。 - 大功告成。不使用 RAG。
浏览代码,确保您了解代码的作用。
运行
# With make make sdk-agent # Without make uv run python app/sdk_agent.py
我们来问它一个一般性问题:
> What is the stock price of Google?
它应该使用 Google 搜索来查找当前价格,并正确回答:

现在,我们来问一个它不知道如何回答的问题。它要求代理已读过我们的故事。
> Who pilots the 'Too Many Pies' ship?
它应该会失败,甚至产生幻觉。我们来看看:

果然,模型无法回答该问题。它根本不知道我们在说什么!
现在,输入 quit 以退出代理。
5. Gemini 文件搜索功能:说明

Gemini 文件搜索功能实际上是以下两项功能的组合:
- 全托管式 RAG 系统:您提供一组文件,Gemini 文件搜索会为您处理分块、嵌入、存储和向量索引编制。
- 智能体意义上的“工具”:您只需在智能体定义中添加 Gemini 文件搜索工具作为工具,并将该工具指向文件搜索存储区即可。
但最重要的是:它内置于 Gemini API 本身。这意味着,您无需启用任何其他 API 或部署任何单独的产品即可使用它。因此,它确实是out-of-the-box的。
Gemini 文件搜索功能
其功能包括:
- 分块、嵌入、存储和索引的详细信息已从开发者(即您)的角度进行了抽象。这意味着您无需了解(或关心)嵌入模型(顺便说一句,它是 Gemini Embeddings),也无需了解生成的向量存储在何处。您无需做出任何向量数据库决策。
- 它开箱即用,支持大量文档类型。包括但不限于:PDF、DOCX、Excel、SQL、JSON、Jupyter 笔记本、HTML、Markdown、CSV,甚至 zip 文件。您可以点击此处查看完整列表。因此,举例来说,如果您想让代理根据包含文本、图片和表格的 PDF 文件进行回答,则无需对这些 PDF 文件进行任何预处理。只需上传原始 PDF 文件,剩下的工作交给 Gemini 即可。
- 我们可以为任何上传的文件添加自定义元数据。这对于在运行时过滤我们希望工具使用的文件非常有用。
数据存储位置
您上传了一些文件。Gemini 文件搜索工具已获取这些文件,创建了块和嵌入,并将它们放在了某个位置。但具体在哪里呢?
答案:文件搜索存储区。这是用于存放嵌入内容的全托管式容器。您无需了解(或在意)此操作在后台是如何完成的。您只需以编程方式创建一个,然后将文件上传到其中即可。
价格实惠!
存储和查询嵌入内容是免费的。因此,您可以根据需要存储任意时长的嵌入内容,并且无需为此存储空间付费!
事实上,您唯一需要付费的是在上传/编入索引时创建嵌入内容。在撰写本文时,此费用为每 100 万个 token 0.15 美元。这相当便宜。
6. 如何使用 Gemini 文件搜索?
分为两个阶段:
- 在文件搜索存储区中创建并存储嵌入内容。
- 从代理查询文件搜索商店。
第 1 阶段 - 使用 Jupyter 笔记本创建和管理 Gemini 文件搜索存储区
此阶段是您最初需要执行的步骤,之后每当您想更新商店时,也需要执行此阶段。例如,当您有新文档要添加时,或者当源文档发生更改时。
此阶段不需要打包到已部署的 agentic 应用中。当然,您可以根据需要选择是否这样做。例如,如果您想为代理应用的管理员用户创建某种界面。但通常情况下,只需运行一些按需代码即可。一种按需运行此代码的绝佳方式?Jupyter 笔记本!
《恋恋笔记本》
在编辑器中打开 notebooks/file_search_store.ipynb 文件。如果系统提示您安装任何 Jupyter VS Code 扩展程序,请继续安装。
如果我们将其在 Cloud Shell 编辑器中打开,则会显示如下内容:

我们逐个运行单元格。首先,执行包含所需导入内容的 Setup 单元格。如果您之前未运行过笔记本,系统会要求您安装所需的扩展程序。请继续执行该操作。然后,系统会要求您选择内核。选择“Python environments...”,然后选择之前运行 make install 时安装的本地 .venv:

然后,执行以下操作:
- 运行“仅限本地”单元格以拉取环境变量。
- 运行 “客户端初始化”单元格,以初始化 Gemini Gen AI 客户端。
- 运行 “检索商店”单元格,其中包含用于按名称检索 Gemini 文件搜索商店的辅助函数。
现在,我们准备好创建商店了。
- 运行 “创建商店(一次性)”单元格以创建商店。我们只需执行一次此操作。如果代码运行成功,您应该会看到一条消息,其内容为
"Created store: fileSearchStores/<someid>" - 运行“查看商店”单元格,看看其中的内容。此时,您应该会看到该集合包含 0 个文档。
太棒了!我们现在已准备好 Gemini 文件搜索商店。
上传数据
我们想将 data/story.md 上传到商店。执行以下操作:
- 运行用于设置上传路径的单元。这指向我们的
data/文件夹。 - 运行下一个单元格,该单元格会创建用于将文件上传到商店的实用函数。请注意,此单元格中的代码还使用 Gemini 从每个上传的文件中提取元数据。我们会提取这些值,并将其作为自定义元数据存储在商店中。(您无需执行此操作,但这样做很有用。)
- 运行该单元以上传文件。请注意,如果我们之前上传过同名文件,笔记本会先删除现有版本,然后再上传新版本。您应该会看到一条消息,表明文件已上传。

第 2 阶段 - 在代理中实现 Gemini 文件搜索 RAG
我们创建了一个 Gemini 文件搜索存储区,并将故事上传到其中。现在,我们可以在代理中使用文件搜索存储区了。我们来创建一个使用文件搜索存储区而非 Google 搜索的新代理。请查看 app/sdk_rag_agent.py。
首先要注意的是,我们实现了一个函数,用于通过传入商店名称来检索商店:
def get_store(client: genai.Client, store_name: str) -> types.FileSearchStore | None:
"""Retrieve a store by display name"""
try:
for a_store in client.file_search_stores.list():
if a_store.display_name == store_name:
return a_store
except Exception as e:
logger.error(f"Error listing stores: {e}")
return None
有了商店后,使用它就像将它作为工具附加到代理一样简单,如下所示:
file_search_tool = types.Tool(file_search=types.FileSearch(file_search_store_names=[store.name]))
运行 RAG 代理
我们按如下方式启动它:
make sdk-rag-agent # Or, without make: uv run python app/sdk_rag_agent.py
我们来问一下之前的代理无法回答的问题:
> Who pilots the 'Too Many Pies' ship?
回答是什么?

成功!从回答中可以看出:
- 我们的文件存储区用于回答问题。
- 找到了 5 个相关块。
- 回答完全正确!
输入 quit 以关闭智能体。
7. 将代理转换为使用 ADK
Google 智能体开发套件 (ADK) 是一款开源模块化框架和 SDK,可供开发者构建智能体和智能体系统。借助它,我们可以轻松创建和编排多智能体系统。尽管 ADK 针对 Gemini 和 Google 生态系统进行了优化,但它仍不限模型、与部署无关,并且可与其他框架兼容。如果您尚未用过 ADK,请前往 ADK 文档了解详情。
使用 Google 搜索的基本 ADK 代理
您可以查看 app/basic_agent_adk/agent.py。在此示例代码中,您可以看到我们实际上实现了两个代理:
- 一个
root_agent,用于处理与用户的互动,并提供主要系统指令。 - 使用
google.adk.tools.google_search作为工具的单独SearchAgent。
root_agent 实际上使用 SearchAgent 作为工具,该工具通过以下代码行实现:
tools=[AgentTool(agent=search_agent)],
根代理的系统提示如下所示:
You are a helpful AI assistant designed to provide accurate and useful information.
If you don't know the answer, use the SearchAgent to perform a Google search.
Do not attempt to search more than ONCE.
If the search yields no relevant results or returns unrelated content, you MUST immediately respond with: "I could not find any information about that."
Do NOT retry the search with different terms. Do NOT ask for clarification. FAIL FAST.
试用代理
ADK 提供了许多开箱即用的接口,可供开发者测试其 ADK 代理。其中一个界面是 Web 界面。这样,我们就可以在浏览器中测试代理,而无需编写任何界面代码!
我们可以通过运行以下命令来启动此界面:
make adk-playground # Or, without make: uv run adk web app --port 8501 --reload_agents
请注意,该命令会将 adk web 工具指向 app 文件夹,该工具会自动发现实现 root_agent 的任何 ADK 代理。我们来试试看:

几秒钟后,应用即可使用。如果您在本地运行代码,只需将浏览器指向 http://127.0.0.1:8501 即可。如果您在 Cloud Shell 编辑器中运行,请点击“网页预览”,然后将端口更改为 8501:

界面显示后,从下拉菜单中选择 basic_agent_adk,然后我们就可以向它提问了:

目前为止,一切顺利!Web 界面甚至会显示根代理何时委托给 SearchAgent。这是一项非常实用的功能。
现在,我们来问它一个需要了解我们故事的问题:

亲自尝试一下吧。您应该会发现,它会按照指示快速失败。
将文件搜索存储区纳入 ADK 代理
现在,我们将把所有内容整合在一起。我们将运行一个能够同时使用文件搜索存储区和 Google 搜索的 ADK 代理。查看 app/rag_agent_adk/agent.py 中的代码。
此代码与上一个示例类似,但有以下几个重要区别:
- 我们有一个根代理,用于编排两个专业代理:
- RagAgent:使用 Gemini 文件搜索存储区的定制知识专家
- SearchAgent:通用知识专家 - 使用 Google 搜索
- 由于 ADK 尚未为
FileSearch提供内置封装容器,因此我们使用自定义封装容器类FileSearchTool来封装 FileSearch 工具,该类会将file_search_store_names配置注入到低级模型请求中。此功能已在单独的脚本app/rag_agent_adk/tools_custom.py中实现。
此外,还有一些需要注意的“陷阱”。在撰写本文时,您无法在同一请求中同时使用原生 GoogleSearch 工具和 FileSearch 工具来查询同一代理。如果您尝试这样做,会收到类似如下的错误消息:
错误 - 发生了错误:400 INVALID_ARGUMENT。{‘error': {‘code': 400, ‘message': ‘Search as a tool and file search tool are not supported together', ‘status': ‘INVALID_ARGUMENT'}}
错误:400 INVALID_ARGUMENT。{‘error': {‘code': 400, ‘message': ‘Search as a tool and file search tool are not supported together', ‘status': ‘INVALID_ARGUMENT'}}
解决方案是将这两个专业代理实现为单独的子代理,并使用“代理即工具”模式将它们传递给根代理。最重要的是,根代理的系统指令非常明确地指导用户先使用 RagAgent:
您好!我是一款旨在提供准确实用信息的 AI 助理。
您可以联系以下两位专家客服人员:
- RagAgent:用于从内部知识库获取定制信息。
- SearchAgent:用于从 Google 搜索获取一般信息。
请始终先尝试 RagAgent。如果这样无法得出有用的答案,请尝试使用 SearchAgent。
最终测试
像之前一样运行 ADK 网页界面:
make adk-playground # Or, without make: uv run adk web app --port 8501 --reload_agents
这次,请在界面中选择 rag_agent_adk。我们来看看实际应用场景:
我们可以看到,它会根据问题选择合适的子代理。
8. 总结
恭喜您完成此 Codelab!
您已经从一个简单的脚本转变为支持多智能体的 RAG 系统;整个过程无需编写一行嵌入代码,也无需实现向量数据库!
我们了解到:
- Gemini 文件搜索是一种托管式 RAG 解决方案,可节省时间和精力。
- ADK 为我们提供了构建复杂多智能体应用所需的结构,并通过 Web 界面等接口为开发者提供便利。
- "Agent-as-a-Tool"模式可解决工具兼容性问题。
希望本实验对您有所帮助。我们下次再见!