问题:RAG 跟不上节奏
知识库只有在检索速度够快时才有用。当我们在 JieGou 中推出 RAG 支持时,整个流程是可以运行的 —— 文档被分块、生成嵌入向量、注入到提示词中。但性能数据讲述了另一个故事。
一个包含 705 篇文档的知识库需要 约 160 秒才能检索到相关上下文。这意味着每次 recipe 执行、每个 workflow 步骤、每次触及知识库的 agent 对话,都要在 LLM 开始生成之前付出数分钟的延迟代价。
对于交互式场景 —— 客服人员查找政策文档、销售代表在对话中调取产品规格 —— 160 秒是完全不可接受的。
我们需要在不增加基础设施复杂度的前提下,将检索时间压缩到一秒以内。
第一阶段:Firestore 原生向量搜索
最初的检索方式是从 Firestore 加载所有嵌入向量,在应用代码中计算余弦相似度,然后返回 top-k 结果。这种方式简单且正确,但与文档数量呈线性扩展关系。
第一步优化是利用 Firestore Vector Search(基于 ScaNN 索引)将相似度搜索移至 Firestore 内部。我们不再将 705 个嵌入向量全部拉到内存中计算距离,而是让 Firestore 原生处理最近邻搜索。
变化
- 优化前:获取所有嵌入向量 → 在 Node.js 中计算余弦相似度 → 排序 → 取 top-k
- 优化后:通过
findNearest()发起一次 Firestore 查询 → 直接返回 top-k
这消除了 O(n) 级别的数据传输和计算开销。Firestore 的向量索引使用近似最近邻算法,以微小的召回率损失换取了大规模集合上的巨大速度提升。
结果
705 篇文档的冷查询从 约 160 秒降至约 10 秒。提升了 16 倍 —— 但对交互式工作流来说仍然太慢。
第二阶段:混合检索与降级策略
并非每个查询都能从向量搜索中获得同等收益。有些知识库足够小,暴力搜索反而比向量索引查询的开销更低。还有些文档不太适合做嵌入(表格、代码片段、结构化数据)。
我们实现了一套混合检索策略:
- 优先尝试向量搜索 —— 如果 Firestore 向量索引存在且知识库有嵌入向量,使用
findNearest() - 降级到暴力搜索 —— 如果向量搜索失败、不可用或返回结果过少,加载嵌入向量并在应用代码中计算相似度
- 合并去重 —— 将两条路径的结果合并,按文档 ID 去重,按相似度分数重新排序
混合方案确保检索永远不会失败。如果 Firestore 向量索引尚未创建(例如在新配置的环境中),系统会优雅地降级到原始的暴力搜索路径。
usedVectorSearch 标志
每次检索操作现在都会在其追踪 span 中包含一个 usedVectorSearch 布尔值。这让我们可以监控哪些查询走的是快速路径,哪些降级了,并识别出需要创建索引或重新生成嵌入向量的知识库。
第三阶段:Redis 缓存加速热查询
最后一步优化针对的是重复查询 —— 在短时间窗口内,对同一个知识库提出相同问题。这在生产环境中经常发生:
- 多个 workflow 步骤查询同一个 FAQ 知识库
- Agent 对话在每一轮都重新检索上下文
- 批量执行中 50 个条目查询相同的参考文档
我们添加了按文档粒度的 Redis 缓存,TTL 为 10 分钟:
- 在运行相似度搜索之前,通过
(knowledgeBaseId, queryEmbeddingHash)作为键检查 Redis 缓存 - 缓存命中时立即返回 —— 完全不需要 Firestore 查询
- 缓存未命中时,运行混合检索流程并缓存结果
结果
| 场景 | 优化前 | 优化后 |
|---|---|---|
| 冷查询,705 篇文档 | 约 160 秒 | 约 10 秒 |
| 热查询(Redis 命中) | 约 160 秒 | <1 秒 |
| 小型知识库(<50 篇文档) | 约 5 秒 | 约 2 秒 |
| 批量 50 条,同一知识库 | 总计约 8,000 秒 | 约 10 秒 + 49 次 <1 秒 |
批量场景是缓存带来最大收益的地方。第一个条目承担冷查询成本;剩余 49 个条目命中 Redis,以毫秒级返回。
架构:零外部依赖
一个关键的设计约束是不增加额外基础设施。许多 RAG 平台要求你配置和管理一个专用的向量数据库 —— Pinecone、Weaviate、Qdrant、Milvus。每一个都会增加:
- 又一个需要部署和监控的服务
- 又一组需要管理的凭证
- 又一个供应商的计费维度
- 又一个流水线中的故障点
JieGou 的方案仅使用你已有的基础设施:
| 组件 | 用途 | 已有? |
|---|---|---|
| Firestore | 向量索引 + 文档存储 | ✅ 你的主数据库 |
| Redis | 查询结果缓存 | ✅ 已用于限流和会话管理 |
| 应用代码 | 暴力搜索降级方案 | ✅ 运行在你现有的 Pod 中 |
不需要 Pinecone。不需要 Weaviate。不需要配置、保护或付费任何新基础设施。
这对你的工作流意味着什么
更快的 recipe 执行
每个使用知识库的 recipe 在热查询时现在可以在一秒内检索到上下文。重复使用场景下,生成前的”思考中…”等待已成为过去。
可行的批量处理
对同一知识库处理数百个条目的批量执行现在变得可行。第一个条目预热缓存;其余条目快速通过。
即时响应的 Agent 对话
对话式 Agent 在每一轮都会重新查询知识库。有了 Redis 缓存,第 2 轮到第 N 轮的上下文检索只需毫秒,而不是重新运行相似度搜索。
可观测的检索过程
usedVectorSearch 追踪标志意味着你可以看到每次执行使用的具体检索路径。如果某个知识库持续降级到暴力搜索,你就知道它需要关注。
立即体验
如果你已经在使用 JieGou 知识库,这些优化已经上线 —— 无需任何配置更改。你现有的知识库将自动受益于 Firestore 向量搜索和 Redis 缓存。
如果你还没有设置知识库:
- 在 JieGou 控制台中进入 Knowledge Bases
- 上传文档或从 URL 导入
- 将知识库关联到任意 recipe 或 workflow
- 看着检索在一秒内完成
Firestore 原生向量搜索、混合检索和 Redis 缓存的组合,让你的 AI 自动化获得公司特定的上下文,而无需承受延迟代价 —— 也无需管理任何额外的基础设施。