1. 先别急着给向量数据库办葬礼
“向量数据库已死”这个说法,最近在圈子里传得挺凶。我第一反应是:又来了。每隔一两年,总有人要给某个技术判死刑,前几年是“关系型数据库已死”,再往前是“REST 已死”,结果呢?都活得好好的,只是角色变了。
这次的风向不太一样。核心争议点在于:当 Agent 需要检索信息时,到底应该先把工具调用的能力给它,还是先把索引建好?换句话说,是让 Agent 自己决定什么时候去查、查什么,还是我们提前把知识库整理成向量索引,让它直接查?
这个问题之所以被吵起来,是因为它触及了一个真实的痛点:很多团队花大力气搭了一套向量检索流水线,结果 Agent 用起来效果并不好——要么召回不准,要么延迟太高,要么维护成本压不住。于是有人开始反思:是不是方向错了?
我的判断是:向量数据库没有死,但它的定位正在发生根本性变化。它从一个“万能检索层”变成了“Agent 工具箱里的一件工具”。这个变化不是技术上的死亡,而是架构上的归位。这篇文章我会从实际项目经验出发,把这个问题拆开揉碎讲清楚:什么时候该先给工具,什么时候该先建索引,以及怎么判断你的场景适合哪条路。
如果你正在做 Agent 相关的检索功能,或者正在纠结要不要上向量数据库,这篇文章应该能帮你省下不少试错时间。
2. 向量数据库到底解决了什么问题,又在哪里碰了壁
2.1 向量检索的本质:把“意思差不多”变成“距离足够近”
先把这个东西说清楚。向量数据库的核心能力就一件事:把文本、图片、音频这些东西通过嵌入模型转成一串数字(向量),然后在高维空间里找距离最近的邻居。距离近,就代表语义相似。
举个例子。“今天天气怎么样”和“外面下雨了吗”,字面上几乎没有重叠词,但嵌入之后这两个句子的向量距离会很近。传统关键词检索(比如 Elasticsearch 的倒排索引)就做不到这一点,因为它依赖词项匹配。
这个能力在 RAG(检索增强生成)场景里非常有用。你有一堆文档,用户问一个问题,你不可能把整堆文档都塞给大模型,上下文窗口不够,成本也扛不住。所以你先用向量检索找出最相关的几段,再喂给模型。这就是最经典的“先建索引”路线。
2.2 为什么有人觉得它“不行了”
问题出在真实场景的复杂度上。我踩过的坑大致分三类:
第一类:召回质量不稳定。嵌入模型对领域术语、缩写、代码片段的理解经常翻车。你搜“OOM 怎么排查”,它可能给你召回一堆讲“内存管理原理”的文档,而真正讲排查步骤的那篇排在第十位。这不是向量数据库的错,是嵌入模型的语义空间和你的业务语义空间没对齐。
第二类:多跳推理搞不定。用户问“上个季度哪个区域的退货率最高,原因是什么”,这需要先查销售数据、再查退货记录、再做聚合分析。向量检索只能做单次相似度匹配,它没法帮你做多步推理。这时候 Agent 需要的是调用工具(查数据库、跑计算),而不是查索引。
第三类:维护成本被低估。文档一更新,索引就得重建;嵌入模型一换,全量向量都得重算;数据量上千万之后,内存和查询延迟都是真金白银。很多团队上线前没算这笔账,上线后发现运维成本比开发成本还高。
所以“向量数据库已死”这个说法,准确翻译应该是:把向量数据库当成唯一检索方案的思路已经死了。它该退回到它该在的位置——Agent 工具箱里的一件工具,而不是整个检索架构的地基。
3. Agent 检索的两条路线:先给工具还是先建索引
3.1 路线一:先给工具,让 Agent 自己决定怎么查
这条路的思路是:我不提前建索引,而是给 Agent 一组工具——比如“执行 SQL 查询”“调用搜索 API”“读取文件”“访问某个数据接口”——然后让 Agent 根据用户的问题,自己决定调哪个工具、传什么参数。
这么做的好处很明显:
- 灵活性高:Agent 可以根据问题动态选择检索策略,不需要你提前预判所有查询模式。
- 数据新鲜度好:直接查源数据,不存在索引滞后的问题。
- 适合结构化数据:查订单、查库存、查日志这类场景,SQL 比向量检索精准得多。
但坑也很明显:
- 依赖 Agent 的规划能力:如果模型不够强,它可能选错工具、传错参数,甚至陷入循环调用。
- 延迟不可控:每次都要实时查源系统,响应时间取决于后端服务的速度。
- 工具描述要写得极其清楚:工具的名称、参数、返回值、适用场景,都得在提示词里说明白,否则 Agent 根本不知道怎么用。
我实测下来,这条路线适合数据源明确、查询模式相对固定、但对实时性要求高的场景。比如内部运维助手,Agent 需要查监控指标、查部署记录、查日志,这些数据都在固定系统里,给几个封装好的工具比建索引靠谱得多。
3.2 路线二:先建索引,让 Agent 查现成的向量库
这条路就是经典的 RAG 架构:提前把文档切块、嵌入、存入向量数据库,Agent 需要检索时直接查索引。
好处是:
- 检索速度快:向量相似度计算是高度优化的,毫秒级返回。
- 语义匹配强:适合非结构化文本,比如文档、邮件、聊天记录。
- 架构简单:不需要 Agent 做复杂的工具规划,检索逻辑是确定的。
但限制也很明显:
- 索引更新有延迟:新文档进来要重新嵌入和入库,做不到实时。
- 召回质量依赖嵌入模型:模型选不好,效果直接打折。
- 不适合精确查询:比如“查一下订单号 12345 的状态”,向量检索可能给你召回一堆相似订单,而不是精确匹配那一条。
所以这条路线适合文档量大、查询以语义相似为主、对实时性要求不高的场景。比如企业知识库问答、客服话术推荐、技术文档检索。
3.3 关键判断:你的场景到底需要哪种检索
我把判断逻辑整理成了一张表,你可以直接对照自己的场景:
| 判断维度 | 优先给工具 | 优先建索引 |
|---|---|---|
| 数据类型 | 结构化数据(数据库、API) | 非结构化文本(文档、邮件) |
| 查询模式 | 精确查询、聚合计算 | 语义相似、模糊匹配 |
| 实时性要求 | 高,需要查最新数据 | 低,可以接受索引延迟 |
| 数据更新频率 | 频繁更新 | 相对稳定 |
| Agent 能力 | 规划能力强,能选工具 | 规划能力弱,需要确定性检索 |
| 运维成本 | 低,不需要维护索引 | 高,需要维护嵌入和索引 |
实际项目中,这两条路线往往不是二选一,而是组合使用。Agent 先判断问题类型:如果是精确查询,调工具;如果是语义检索,查索引。这个判断逻辑可以写在 Agent 的系统提示词里,也可以用一个轻量的分类器来做路由。
4. 实操:怎么搭一套混合检索的 Agent
4.1 整体架构设计
我以“企业内部知识助手”为例,讲一下我实际搭过的一套架构。需求是:员工可以问技术文档相关的问题,也可以查内部系统的数据(比如“上周的部署记录”“某个服务的当前状态”)。
整体分三层:
第一层:查询路由。用户问题进来后,先判断类型。如果是“怎么配置”“如何排查”这类语义问题,走向量检索;如果是“查一下”“列出”这类精确查询,走工具调用。路由可以用一个小的分类模型,也可以直接用大模型做 few-shot 判断。
第二层:检索执行。向量检索走嵌入模型 + 向量数据库;工具调用走封装好的 API 或 SQL 查询。
第三层:结果融合。把检索结果和工具返回结果合并,交给大模型生成最终回答。
这个架构的好处是:每条路线做自己最擅长的事,不互相将就。
4.2 向量索引的搭建细节
如果你决定建索引,有几个参数必须认真调:
切块大小(chunk size)。我试过 256、512、1024 三种。256 太碎,语义不完整;1024 太大,召回精度下降。最后落在 512 左右,配合 50 到 100 的重叠(overlap),效果比较稳。重叠的作用是防止关键信息被切在边界上。
嵌入模型选择。中文场景我一般用 BGE 系列或者 M3E,英文场景可以用 text-embedding-3-small 这类。选模型的核心指标不是榜单分数,而是在你自己的数据上做召回测试。我通常会标 100 条查询,人工判断 top-5 里有没有正确答案,算一个召回率。
距离度量。余弦相似度(cosine)最常用,适合大多数文本场景。如果向量已经归一化,内积(inner product)和余弦等价,计算更快。欧氏距离(L2)在文本场景用得少,但在图像检索里常见。
索引类型。数据量小于 100 万,用 Flat 索引就行,暴力搜索,精度最高。超过 100 万,考虑 IVF 或者 HNSW。HNSW 查询快、精度高,但内存占用大;IVF 内存友好,但需要调 nprobe 参数平衡速度和精度。
注意:索引类型没有绝对优劣,只有适不适合。我见过有人上来就上 HNSW,结果内存爆了,其实他的数据量用 Flat 完全够。
4.3 工具调用的封装要点
工具这条路,核心是把接口封装得让 Agent 能看懂、能用对。我总结几个关键点:
工具描述要具体。不要写“查询数据库”,要写“根据订单号查询订单状态,输入参数为订单号字符串,返回订单状态和更新时间”。描述越具体,Agent 选错的概率越低。
参数校验要做在工具内部。不要指望 Agent 每次都传对参数。工具内部要做类型检查、范围检查,传错了返回明确的错误信息,Agent 看到错误信息后可以自我纠正。
返回结果要精简。工具返回的数据不要一股脑塞给 Agent,要做裁剪。比如查数据库返回 100 行,你只返回前 10 行加一个总数,剩下的让 Agent 决定要不要翻页。
超时和重试要设好。工具调用可能失败,要有超时机制和有限次重试。我一般设 5 秒超时,重试 2 次,还失败就返回错误让 Agent 决定下一步。
4.4 路由逻辑的实现
路由是这套架构的关键。我试过两种方案:
方案一:提示词路由。在系统提示词里写清楚什么情况走检索、什么情况走工具,让大模型自己判断。优点是实现简单,缺点是稳定性依赖模型能力,偶尔会判断错。
方案二:分类器路由。训练一个小的文本分类模型,输入用户问题,输出“检索”或“工具”。优点是稳定、快,缺点是需要标注数据。
我现在的做法是混合:先用规则做粗筛(比如问题里包含“查一下”“列出”“统计”就走工具),规则覆盖不到的再用提示词路由。这样既保证了常见情况的稳定性,又保留了灵活性。
5. 常见问题与排查技巧实录
5.1 召回不准怎么办
这是最高频的问题。排查顺序我一般是:
- 先看切块:把召回结果对应的原文块打出来,看语义是否完整。如果块被切碎了,调切块策略。
- 再看嵌入模型:拿几条 bad case,手动算一下查询和正确答案的向量距离,看是不是模型本身的问题。如果是,换模型或者做微调。
- 最后看查询改写:用户的问题往往很短,信息量不够。可以加一步查询改写,用大模型把用户问题扩展成更完整的检索 query。
实操心得:我习惯在检索层加一个“重排序”(rerank)步骤。先用向量检索召回 top-20,再用一个交叉编码器(cross-encoder)对这 20 条做精排,取 top-5。这一步能把召回准确率提升 10 到 20 个百分点,代价是增加几十毫秒延迟,很值。
5.2 Agent 选错工具怎么破
常见原因有三个:工具描述不清楚、工具太多导致选择困难、模型能力不够。
对应的解法:
- 工具描述加上“适用场景”和“不适用场景”,帮 Agent 划清边界。
- 工具数量控制在 5 到 7 个以内,太多就分组,先选组再选工具。
- 如果模型能力确实不够,考虑用更小的模型做工具选择,把选择逻辑从生成逻辑里拆出来。
5.3 延迟太高怎么优化
延迟主要来自三块:嵌入计算、向量检索、大模型生成。
- 嵌入计算可以缓存,相同 query 不用重复算。
- 向量检索选合适的索引类型,HNSW 的 efSearch 参数调小一点能提速。
- 大模型生成可以用流式输出,让用户先看到部分结果。
如果工具调用延迟高,考虑加缓存层,或者把常用查询预计算好。
5.4 索引更新与数据一致性
向量索引的更新是个麻烦事。我的做法是:
- 文档更新时,先更新源数据,再异步触发索引重建。
- 索引重建期间,旧索引继续服务,新索引建好后原子切换。
- 对于删除操作,用软删除标记,定期做全量重建清理。
这套机制不复杂,但能避免“查不到刚更新的文档”这类问题。
| 常见问题 | 排查方向 | 解决手段 |
|---|---|---|
| 召回不准 | 切块、嵌入模型、查询改写 | 调切块、换模型、加重排序 |
| 选错工具 | 工具描述、工具数量、模型能力 | 细化描述、分组、拆选择逻辑 |
| 延迟高 | 嵌入、检索、生成 | 缓存、调索引参数、流式输出 |
| 索引不同步 | 更新机制 | 异步重建、原子切换、软删除 |
6. 我的选型建议:别站队,看场景
回到标题的问题:Agent 检索,先给工具还是先建索引?
我的答案是:看你的数据形态和查询模式,不要站队。
如果你的数据是结构化的、查询是精确的、实时性要求高,先给工具。向量数据库在这个场景里帮不上什么忙,硬上只会增加复杂度。
如果你的数据是非结构化的、查询是语义的、可以接受索引延迟,先建索引。向量检索在这个场景里仍然是最高效的方案。
如果两者都有,做混合架构,用路由把请求分到正确的路径上。
向量数据库没有死,它只是从“唯一答案”变成了“其中一个选项”。这个变化对做 Agent 的人来说是好事——我们终于不用把所有问题都塞进一个向量检索的框里了。
最后分享一个我踩过的坑:早期做 Agent 检索时,我总想用一个方案解决所有问题,结果向量检索和工具调用互相打架,效果都不好。后来拆开之后,每条路线各司其职,整体效果反而上了一个台阶。架构设计里,“分开”往往比“统一”更难,但也更有效。