向量库/检索:RAG / Agent 的“找资料”系统怎么做
很多人把“向量库”理解成“存 Embedding 的数据库”。这个说法不算错,但太浅。面试更想听到的是:向量库(Vector DB / Vector Store)解决的是“在高维向量空间里,快速、可控地找相似内容”,并把这件事稳定地接进 RAG / Agent 的在线链路。
0. 面试速答(30 秒版 TL;DR)
- 向量库的核心能力是 ANN(Approximate Nearest Neighbor,近似最近邻)检索:在“快”和“准”之间做可调的工程折中。
- 一条典型链路:切块 → 向量化 → 建索引(离线);问题向量化 → TopK 召回 →(过滤/混合检索)→ 重排 → 注入上下文(在线)。
- 检索系统的上限主要由:切块策略、Embedding 模型匹配、权限/过滤、混合检索、重排与评估方法决定;不是“换个更大模型”就能救。
- 向量库常见难点:过滤(metadata/权限)、索引选型(HNSW/IVF…)、更新与回滚(重建索引/版本化)、评估(Recall@K、nDCG、端到端命中率)。
1. 先把概念讲清楚
1.1 向量库(Vector DB / Vector Store)是什么
向量库可以理解成一套“检索基础设施”,至少包含:
- 向量存储:存 embedding(以及原文片段/引用信息/metadata)。
- 向量索引:支持 ANN,加速“找相似向量”。
- 检索算子:TopK、阈值、过滤、分页/游标、相似度分数等。
- 工程能力:分片、副本、持久化、备份、监控、权限、多租户。
1.2 检索(Retrieval)在 RAG / Agent 里处于什么位置
别把“检索”只当成一个 API 调用。更面试化的拆法是三段:
- 召回(Recall):从海量候选里捞出 TopK(先保证“不漏掉”)。
- 重排(Rerank):把 TopK 重新排序/过滤(再保证“更相关”)。
- 上下文注入(Contexting):把片段组织成模型更容易用的输入(最后保证“用得对”)。
2. 一条“向量库检索链路”长什么样
面试时你可以强调一句:向量库只是“召回层”的核心组件,但检索效果是整条链路共同决定的。
3. 你需要回答的“关键工程问题”
3.1 用什么相似度?余弦、点积、欧氏距离有什么区别?
- 余弦相似度(Cosine):关心方向,不关心长度;常见且好解释。
- 点积(Dot Product):既受方向也受向量长度影响;很多 embedding 模型/实现会配合归一化使用。
- 欧氏距离(L2):几何距离直观,但在高维空间里要关注分布与归一化。
面试更想听到的是“工程结论”:不要只换 metric,先确认向量是否归一化、doc/query 是否同模型同维度、以及你要的相似度语义是什么。
3.2 索引怎么选?为什么向量库能快?
暴力检索是 O(N);向量库通常靠 ANN 索引把它变成“近似更快”:
- HNSW:召回质量高、查询快,内存占用较大;更新相对友好,工程里很常见。
- IVF / PQ:更偏“压缩 + 分桶”,适合更大规模/更省内存的场景,但参数更敏感。
你不需要背公式,但要能说清:索引是在“延迟、召回率、内存、构建时间、更新成本”之间做权衡。
3.3 过滤(metadata / 权限)为什么难?
真实业务几乎一定有这些约束:
- 多租户:tenantId 必须隔离
- 权限:用户能看哪些文档/段落
- 时间:只要最近版本/最近 N 天
难点在于:向量相似度是连续空间,过滤是离散条件。解决思路通常是:
- 先过滤再向量检索(过滤能显著缩小候选集时)
- 先向量检索再过滤(过滤条件很稀疏或实现受限时)
- 预分片/预分区(按租户/权限域做物理隔离)
3.4 为什么要“混合检索 + 重排”?
向量检索擅长语义相似,但可能漏掉:
- 专有名词、代码符号、ID、精确短语(词法匹配更强)
因此常见组合是:
- Hybrid Search:BM25(词法) + 向量(语义)一起召回
- Rerank:用 cross-encoder 或 LLM/小模型对 TopK 做精排
一句话:向量召回保不漏,重排负责更准。
4. 如何评估“检索做得好不好”
不要上来就用“回答好不好”评价检索。更稳的做法是分层评估:
- 检索层指标(离线为主):
Recall@K、MRR、nDCG - 端到端指标(线上为主):引用命中率、答案可追溯率、拒答正确率、用户反馈、A/B
面试里可以补一句“经验结论”:先把检索的 Recall@K 做到可控,再谈生成质量与提示词。
5. 典型题 & 标准答法
5.1 “向量库和全文检索是不是互相替代?”
不是,常见结论是互补:
- 全文检索(BM25)强在精确词匹配、可解释性
- 向量检索强在语义泛化、同义改写
- 生产里经常做 Hybrid,再用重排融合
5.2 “为什么检索出来的片段看起来不相关?”
按排查优先级给答案:
- 切块是否合理(太大噪音多,太小语义碎)
- doc/query embedding 是否同模型同版本(混用最常见)
- 是否缺少过滤/权限导致捞到别的域内容
- TopK 与阈值策略是否合适(K 太小容易漏,太大噪音多)
- 是否需要混合检索/重排(对专有名词尤其有效)
5.3 “什么时候不需要向量库?”
如果满足任意一种,向量库可能是过度设计:
- 数据量很小(例如几百条),线性扫描 + 缓存就够
- 信息结构化且查询可枚举(直接 SQL / KV / 搜索引擎更稳)
- 结果必须完全可解释/可审计(优先规则/倒排/结构化检索)
6. 最小可运行的检索伪代码(Node.js / TypeScript)
type Chunk = {id: string; text: string; metadata: Record<string, unknown>};
type Hit = {chunk: Chunk; score: number};
async function retrieveTopK(opts: {
query: string;
tenantId: string;
topK: number;
}): Promise<Hit[]> {
const queryVector = await embed(opts.query); // doc/query 必须同模型同版本
const hits = await vectorDb.search({
vector: queryVector,
topK: opts.topK,
filter: {tenantId: opts.tenantId}, // 权限/租户过滤通常是必选项
});
return hits;
}
这段代码想表达的不是“API 长什么样”,而是面试要点:检索接口必须显式携带“过滤域/权限域”,并且 doc/query embedding 必须版本一致。
7. 常见坑(背下来能救命)
- Embedding 版本漂移:文档用旧模型向量化,查询用新模型;相似度直接失真。
- 只看 TopK,不设阈值:相似度很低也硬塞进上下文,导致模型被噪音带偏。
- 忽略权限过滤:不仅泄露数据,还会把检索质量打崩(跨域内容更“相似”)。
- 把“检索不准”当成“模型不行”:先做检索评估与重排,再调提示词。
- 更新不可控:文档变更后不重建索引/不做版本化,线上结果随机波动。
8. 速记要点(可背诵)
- 向量库 = 高维相似检索(ANN)+ 工程能力,不是“存向量”这么简单。
- 检索链路要分层:召回 → 重排 → 上下文注入。
- 生产难点:过滤/权限、索引权衡、混合检索、评估与版本化。
- 先做 Recall@K 再谈生成质量;检索差,后面都是“无米之炊”。