使用 Vertex AI Vector Search 与 Firestore 构建 Genkit 文档索引与检索(RAG)实战
【免费下载链接】genkitOpen-source framework for building agentic apps in JavaScript, Go, Dart, and Python, built and used in production by Google项目地址: https://gitcode.com/GitHub_Trending/ge/genkit
本文基于 Genkit 官方示例 js/testapps/vertexai-vector-search-firestore,深入讲解如何将 Vertex AI Vector Search(向量检索)与 Cloud Firestore(文档内容与元数据存储)结合,通过 Genkit 的索引器(Indexer)与检索器(Retriever)机制,搭建一条完整的 RAG(检索增强生成)数据管线。读完本文,你将掌握:从部署 Vertex AI Vector Search 索引、配置环境变量,到用 Genkit 定义indexFlow与queryFlow两个流程,并最终用genkit start启动服务进行索引与检索的完整闭环,同时理解底层@genkit-ai/vertexai/vectorsearch插件的实现原理。
前置条件(Prerequisites)
运行本示例前,需要确认以下基础环境与云端资源就绪:
- Node.js:本示例使用 TypeScript 编写,需要 Node.js 环境。
- PNPM:仓库使用 pnpm workspace 管理依赖,本示例依赖
workspace:*协议,因此必须使用 PNPM 安装。 - Vertex AI Vector Search 已部署的索引(Index)与索引端点(Index Endpoint):向量索引需先通过 Google Cloud Console 或
gcloud命令行完成创建、部署,并获取对应的公共域名与各类 ID。 - Firestore 实例:用于持久化存储文档内容与元数据,作为“文档仓库”(document store),同时需要 Google Cloud 服务账号的凭据文件。
此外,示例源码在 src/index.ts 中会对全部环境变量做一次性校验,任一变量缺失都会抛出Missing environment variables. Please check your .env file.,因此环境变量配置是整个示例能否启动的前提。
快速开始(Getting Started)
第一步:克隆仓库并安装依赖
Genkit 仓库采用 pnpm workspace 结构,示例通过workspace:*引用核心包(如genkit、@genkit-ai/vertexai),因此必须先让这些包可被解析:
cd js/testapps/vertexai-vector-search-firestore && pnpm i执行前请先按照仓库根目录 README.md 的指引构建核心包。示例的依赖清单可在 package.json 中查看,其中@genkit-ai/vertexai与firebase-admin是本节的两个关键运行时依赖。
第二步:配置环境变量
确保你已经在 Vertex AI Vector Search 中部署好了索引。在示例根目录创建.env文件,并设置以下变量(可参照仓库中的.env.example):
PROJECT_ID=your-google-cloud-project-id LOCATION=your-vertex-ai-location FIRESTORE_COLLECTION=your_firestore_collection_here VECTOR_SEARCH_PUBLIC_DOMAIN_NAME=your-vector-search-public-domain-name VECTOR_SEARCH_INDEX_ENDPOINT_ID=your-index-endpoint-id VECTOR_SEARCH_INDEX_ID=your-index-id VECTOR_SEARCH_DEPLOYED_INDEX_ID=your-deployed-index-id GOOGLE_APPLICATION_CREDENTIALS=path-to-your-service-account-key.json这些变量在 src/config.ts 中通过dotenv加载,逐项导出为常量供业务代码使用。各变量含义:
| 变量 | 用途 |
|---|---|
PROJECT_ID | Google Cloud 项目 ID,用于初始化 Firebase 与 Vertex AI 客户端 |
LOCATION | Vertex AI 区域,如us-central1 |
FIRESTORE_COLLECTION | 存储文档内容与元数据的 Firestore 集合名 |
VECTOR_SEARCH_PUBLIC_DOMAIN_NAME | 索引端点(Index Endpoint)的公共访问域名,形如xxx.vdb.vertexai.goog |
VECTOR_SEARCH_INDEX_ENDPOINT_ID | 索引端点 ID |
VECTOR_SEARCH_INDEX_ID | 向量索引 ID |
VECTOR_SEARCH_DEPLOYED_INDEX_ID | 已部署索引(Deployed Index)ID |
GOOGLE_APPLICATION_CREDENTIALS | 服务账号密钥 JSON 文件路径,用于认证 Google Cloud API |
第三步:运行示例
启动 Genkit 服务器,注册并暴露两个流程:
genkit start开发模式下也可以使用 package.json 中预设的脚本pnpm genkit:dev(内部执行genkit start -- tsx --watch src/index.ts),或直接以pnpm dev(tsx --watch src/index.ts)运行。
示例总体结构(Overview)
本示例演示了如何自定义“文档索引器”与“文档检索器”,将 Cloud Firestore 作为文档存储后端,并与 Vertex AI 深度集成,实现文档的索引与检索。核心组件包括:
- Firestore Document Indexer:把文档写入 Firestore 集合,并返回生成的文档 ID;
- Firestore Document Retriever:根据邻居(Neighbor)ID 从 Firestore 集合中读取文档;
- Genkit 配置:将 Vertex AI 插件与 Vector Search 插件接入 Genkit,配置项目、区域与向量搜索索引选项;
- 索引流程(Indexing Flow):
indexFlow,将文本输入转换为文档并写入索引; - 查询流程(Query Flow):
queryFlow,根据查询检索文档并按距离排序返回结果。
整个数据链路为:文本 → Embedding(text-embedding-004)→ Vertex AI Vector Search(向量相似度计算)→ Firestore(回源取回原始文档),其中向量索引负责“相似度检索”,Firestore 负责“内容存储”,二者通过 datapoint ID 关联。
Firestore Document Indexer:把文档写入 Firestore
示例通过@genkit-ai/vertexai/vectorsearch提供的工厂函数创建索引器,传入 Firestore 实例与集合名:
const firestoreDocumentIndexer: DocumentIndexer = getFirestoreDocumentIndexer( db, FIRESTORE_COLLECTION );从源码 js/plugins/vertexai/src/vectorsearch/vector_search/firestore.ts 可以看到其底层实现:对传入的每个Document,在指定集合中创建一个新文档引用db.collection(collectionName).doc(),以批量写(db.batch())的方式一次性写入{ content, metadata },最后batch.commit()并返回全部新文档 ID。这些 ID 随后会作为 Vertex AI Vector Search 的 datapoint ID,使向量与原始文档一一对应。
DocumentIndexer的类型定义(types.ts)明确其签名:输入Document[],输出Promise<string[]>(文档 ID 列表)。同时注释指出目前仅支持Streaming Update Indexers,即增量更新模式。
Firestore Retriever:按邻居 ID 回源取文档
检索器同样由工厂函数创建:
const firestoreDocumentRetriever: DocumentRetriever = getFirestoreDocumentRetriever(db, FIRESTORE_COLLECTION);底层实现(firestore.ts)的流程是:接收 Vertex AI Vector Search 返回的Neighbor[](每个邻居包含 datapoint 及其距离),逐个用neighbor.datapoint.datapointId作为文档 ID,读取collection.doc(id)的快照;若文档存在,则将原始content、metadata与邻居信息(如distance)合并,再通过DocumentDataSchema.safeParse校验并构造出Document返回。这样检索结果天然携带相似度距离,供上层排序使用。
Genkit 配置:接入 Vertex AI 与 Vector Search 插件
示例在 src/index.ts 中完成 Genkit 初始化,同时注册两个插件:
const ai = genkit({ plugins: [ vertexAI({ projectId: PROJECT_ID, location: LOCATION, googleAuth: { scopes: ['https://www.googleapis.com/auth/cloud-platform'], }, }), vertexAIVectorSearch({ projectId: PROJECT_ID, location: LOCATION, vectorSearchOptions: [ { publicDomainName: VECTOR_SEARCH_PUBLIC_DOMAIN_NAME, indexEndpointId: VECTOR_SEARCH_INDEX_ENDPOINT_ID, indexId: VECTOR_SEARCH_INDEX_ID, deployedIndexId: VECTOR_SEARCH_DEPLOYED_INDEX_ID, documentRetriever: firestoreDocumentRetriever, documentIndexer: firestoreDocumentIndexer, embedder: textEmbedding004, }, ], }), ], });关键点说明:
vertexAI插件:提供文本嵌入模型textEmbedding004(对应 Vertex AI 的text-embedding-004,embedder.ts 中以embedderRef注册,维度 768、支持文本输入),以及模型生成等能力。vertexAIVectorSearch插件:vectorSearchOptions数组中每个元素代表一套“索引 + 文档仓库”绑定关系,将向量索引(indexId/indexEndpointId/deployedIndexId/publicDomainName)与自定义的documentRetriever、documentIndexer、embedder组合在一起。- 插件实现(js/plugins/vertexai/src/vectorsearch/index.ts)会在存在
vectorSearchOptions时,调用内部的vertexAiIndexers与vertexAiRetrievers把默认的索引器、检索器动作注册进 Genkit。 vectorSearchOptions中每个配置项的类型定义见 types.ts:除四类 ID 与域名外,还可选配embedder(默认嵌入器)与embedderOptions。
定义流程:indexFlow 与 queryFlow
示例定义了两个 Genkit 流程,均使用 Zod schema 约束输入输出,并借助ai.index/ai.retrieve高层 API 与注册的索引器、检索器交互。
索引流程 indexFlow
src/index.ts 中,indexFlow接收一组datapoints,每个 datapoint 包含文本text与可选的过滤条件:
restricts:分类限制(namespace + allowList/denyList),用于元数据过滤;numericRestricts:数值限制(valueInt/valueFloat/valueDouble+ namespace),用于数值范围过滤。
流程内将每个 datapoint 通过Document.fromText(dp.text, metadata)转为 GenkitDocument,随后调用:
await ai.index({ indexer: vertexAiIndexerRef({ indexId: VECTOR_SEARCH_INDEX_ID, displayName: 'firestore_index', }), documents, });vertexAiIndexerRef引用此前注册的 Vertex AI 索引器动作,ai.index会先对文档调用embedder(text-embedding-004)生成向量,再写入 Vertex AI Vector Search 索引,同时由documentIndexer将原文与元数据写入 Firestore。
查询流程 queryFlow
src/index.ts 中,queryFlow的输入为查询文本query、返回条数k,以及可选的restricts与numericRestricts(数值过滤额外支持op运算符:OPERATOR_UNSPECIFIED、LESS、LESS_EQUAL、EQUAL、GREATER_EQUAL、GREATER、NOT_EQUAL)。
流程执行逻辑:
const queryDocument = Document.fromText(query, metadata); const res = await ai.retrieve({ retriever: vertexAiRetrieverRef({ indexId: VECTOR_SEARCH_INDEX_ID, displayName: 'firestore_index', }), query: queryDocument, options: { k }, });ai.retrieve内部会:先用 embedder 对查询文本编码 → 调用 Vertex AI Vector Search 的FindNeighbors找到 top-k 个近邻 → 交由documentRetriever从 Firestore 按邻居 ID 取回原文与元数据。最后,输出对结果按distance降序排列,并附带length(命中条数)与time(耗时毫秒,用performance.now()统计)。
Neighbor与各类过滤 Schema 的 Zod 定义(RestrictionSchema、NumericRestrictionSchema、NeighborSchema等)均可在 types.ts 中查看,它们直接对应 Vertex AI IndexDatapoint 的 protobuf 结构,保证与云端 API 的字段一一映射。
启动服务器与整体架构
流程定义完成后,调用startFlowsServer()启动 Genkit 服务器,将indexFlow、queryFlow以 HTTP 端点形式暴露,供 Dev UI 或外部调用。
本示例的架构可以概括为三层协作:
┌──────────────────────────────┐ 文本/查询 ──► Genkit(embedder + index/retrieve) │ │ │ ▼ ▼ ▼ Vertex AI Vector Search Firestore(原文+元数据) 向量索引 / FindNeighbors 按 datapoint ID 回源- 向量索引层:Vertex AI Vector Search,负责高维向量的相似度计算与过滤(restricts / numericRestricts);
- 文档存储层:Firestore,负责保存
content与metadata,是“回源”的数据仓库; - 编排层:Genkit 插件体系,通过
vertexAIVectorSearch将两层绑定,并通过ai.index/ai.retrieve提供统一编程接口。
该模式与仓库中 js/plugins/vertexai/README.md 描述的 RAG 用法一致,且同一套vertexAIVectorSearch插件还支持 BigQuery 后端(对应getBigQueryDocumentIndexer/getBigQueryDocumentRetriever,vectorsearch/index.ts),如需对比可查看 bigquery.ts。
结语与扩展方向
本示例演示了 Genkit 与 Vertex AI 插件在“文档索引 + 检索”上的最小闭环:以 Firestore 为文档仓库、以 Vertex AI Vector Search 为向量检索引擎,通过自定义DocumentIndexer/DocumentRetriever实现解耦与定制。你可以在此基础上:
- 将 Firestore 替换为其他存储(如 BigQuery、PostgreSQL),仅需实现同样的
DocumentIndexer/DocumentRetriever契约; - 在
indexFlow中增加分块(chunking)与清洗逻辑,提升检索质量; - 在
queryFlow中串联生成模型,形成完整的 RAG 问答链路; - 利用
restricts与numericRestricts做租户隔离、类目过滤、价格区间等精细化检索。
本示例基于 Apache License 2.0 开源,完整代码见 src/index.ts,插件源码见 js/plugins/vertexai/src/vectorsearch,测试用例可参考 tests/vectorsearch 目录。
【免费下载链接】genkitOpen-source framework for building agentic apps in JavaScript, Go, Dart, and Python, built and used in production by Google项目地址: https://gitcode.com/GitHub_Trending/ge/genkit
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考