编程与 AI12 分钟阅读更新于 2026-07-30

向量数据库是什么:从相似性搜索到 MMR 与 metadata 过滤

围绕Vectorstores、Similarity Search、Failure modes 和 Retrieval 章节,讲清向量数据库如何保存向量、原文与 metadata,为什么基础相似性搜索会重复或错召回,以及 MMR、metadata 过滤和压缩检索怎样改进结果。

相关工具

向量数据库存的不是“聪明文本”,而是可检索的索引

前面讲完 Embedding,很多人会自然以为:文本既然已经变成向量,下一步只要把这些数字存起来就行。这个理解只说对了一半。向量数据库确实要保存向量,但它真正有价值的地方,是把向量、原文片段、来源信息和检索能力绑在一起,让 RAG 系统能在提问时快速找到可用依据。

文中的示例先用文档加载器读入 Matplotlib 资料,再用文本切分器得到 27 个 split,随后调用 Embedding 模型把每个 split 转成向量,最后用 Chroma.from_documents 写入向量库。这里有一个细节很重要:写进去的不是孤立向量,而是 documents、embedding、persist_directory 这几类信息一起进入系统。也就是说,向量库既要知道“这段文字在语义空间里的位置”,也要知道“这段文字原文是什么、来自哪里、以后能不能被重新加载”。

如果只保存向量,系统即使算出某个向量和用户问题很接近,也没法把可读的资料交给大模型,更没法给用户标注来源。一个合格的 RAG 向量库,至少要让每个 chunk 对应三层信息:第一层是 embedding 向量,用来做相似度比较;第二层是 page_content,也就是最后可能塞进提示词的原文;第三层是 metadata,比如文件名、页码、章节、版本、chunk_id。少了任何一层,后面的检索都会变得不好解释、不好排查。

RAG 向量数据库写入路径图,展示 chunks、Embedding、metadata、向量数据库和持久化存储的关系
向量数据库写入链路

从切分后的 chunk 到 Embedding,再到向量、原文和 metadata 一起入库,最后通过持久化目录保留下来。

一次相似性搜索是怎么发生的

文中用“Matplotlib 是什么?”这个问题演示了最基础的 similarity_search。流程并不绕:用户问题先被转成 query embedding,向量库再拿这个 query embedding 和库里的文档向量做比较,最后返回最相近的 Top-K 文档。示例里 k=3,返回的第一段就包含 Matplotlib 的定义:它是 Python 里常用的绘图库,可以帮助使用者创建静态、动态和交互式可视化。

这就是 RAG 里最朴素、也最常见的一跳检索。它不要求用户写出和文档完全一样的关键词,只要问题语义接近,就有机会命中相关资料。比如用户问“Matplotlib 怎么画图”“Python 的绘图库是什么”,如果文档里有 Matplotlib 的介绍,Embedding 检索通常能把它排到前面。

但要注意,similarity_search 返回的是“相似片段”,不是“最终答案”。它只是把可能有用的证据捞出来,后面还要交给大模型组织语言、处理上下文、判断是否足够回答。把这一步想清楚,很多问题就不会混在一起:检索召回错了,是向量库、切分、metadata 或资料质量的问题;召回正确但回答说偏了,才更像是生成层的问题。

Top-K 的第一个坑:重复内容会挤占结果

资料 很快展示了一个典型失败场景:把同一份 资料 重复加载进知识库后,再做相似性搜索,Top-K 里会出现重复 chunk。这个结果一点也不奇怪,因为向量库只是在找“和问题最相似”的片段。两段内容如果完全一样,它们的向量也会非常接近,当然可能一起排到前面。

问题在于,RAG 需要的通常不是三段一模一样的证据,而是几段互相补充的资料。假设用户问一个概念,Top-3 全是同一段定义的重复拷贝,大模型拿到的上下文看起来很多,实际上信息密度很低。更糟的是,真正能补充限制条件、示例或注意事项的片段,可能因为重复内容占坑而排不进前几名。

所以,向量数据库不是资料越多越好。重复 资料、重复网页、版本相近但没有标注的文档,都会让检索结果变得臃肿。建库前做去重,写入时保留 chunk_id 和 source,检索后做结果去重,都是很实际的工程动作。它们没有模型调参听起来酷,但对答案质量的影响很直接。

普通相似性搜索和 MMR 检索对比图,展示重复召回与多样化召回的区别
相似性搜索与 MMR 的差别

普通 Top-K 容易被相似或重复片段占满;MMR 会在相关性之外加入多样性,让召回结果更互补。

MMR 给检索结果补上多样性

后文介绍了 MMR,也就是 Maximal Marginal Relevance。它的思路很朴素:结果既要和用户问题相关,也要尽量彼此不重复。普通 similarity_search 只盯着相关性分数,MMR 会在挑选后续结果时考虑“这段和已经选中的内容是不是太像”。

这对 RAG 很有用。用户问“Matplotlib 是什么”,第一段返回定义很合理;第二段、第三段如果继续返回同样的定义,价值就有限。MMR 更希望后面的片段能补充安装、组件、Figure、Axes 或示例代码之类的信息。这样交给大模型的上下文更立体,回答也更容易从“背一句定义”变成“讲清一个问题”。

不过,MMR 不是万能修复器。它能缓解重复结果,但不能替代干净的资料库。如果知识库里重复内容太多,或者 chunk 切得很乱,MMR 也只能在有限空间里做选择。更稳妥的做法是把资料清洗、合理切分、去重、MMR 和检索评估一起做,而不是指望某一个参数把问题全部抹平。

Top-K 的第二个坑:语义相似不等于条件正确

另一个失败例子更接近真实业务:用户问“第二讲中对 Figure 说了些什么?”,相似性搜索的前几个结果却混入了第一讲的内容。原因并不复杂,第一讲里也可能出现 Figure、绘图、对象结构这些相近概念;从语义向量看,它们确实相关。但用户真正限定的是“第二讲”,这是一条结构条件,不只是语义条件。

这类问题如果只靠提示词提醒大模型“请回答第二讲”,通常不够稳。因为大模型看到的上下文如果已经混入第一讲,它还是可能顺着错误资料回答。更可靠的做法,是在检索前就利用 metadata 过滤,把 source、lecture、page、version 这类条件先卡住,再在过滤后的候选集里做向量相似度排序。

文中还提到 SelfQueryRetriever 的思路:让模型从用户问题中抽取检索条件,比如把“第三讲”“回归分析”这类信息转成 metadata filter,再交给检索器执行。这个设计的重点不是让模型直接编答案,而是让模型帮助生成结构化查询。换句话说,判断材料范围这件事,尽量发生在检索层,而不是等答案写完后再补救。

metadata 过滤和上下文压缩检索流程图,展示过滤、向量召回、相关句抽取和回答生成
metadata 过滤与压缩检索

先用来源、页码或章节缩小候选范围,再从命中的 chunk 中抽取真正相关的句子,减少无关上下文。

压缩检索:先召回,再只保留有用句子

当 chunk 比较长时,另一个问题会出现:召回片段整体相关,但里面真正有用的可能只有两三句话。文中用 ContextualCompressionRetriever 做了演示:先通过基础检索器找到候选文档,再用 LLMChainExtractor 从文档里抽取和问题相关的句子,最后把更短、更聚焦的内容交给生成模型。

这个动作很像给上下文做一次“整理”。它不是重新写文档,而是把无关句子折掉,只留下回答问题需要的部分。对于长 资料、课程讲义、产品手册,这一步尤其有价值。否则模型上下文里塞满了旁枝信息,既浪费 token,也容易让答案跑偏。

不过 资料 也提醒了一个细节:如果基础检索器召回了重复文档,压缩后仍然可能得到重复内容。压缩解决的是“片段太宽”的问题,不解决“候选重复”的问题。所以更好的组合是:metadata 先限制范围,MMR 控制结果多样性,压缩检索再减少无关文字。三者解决的问题不同,放在一起才像一个能上线的检索链路。

向量库不是唯一检索方式

同时补充了 SVM、TF-IDF 等其他 retriever。在示例里,面对“Matplotlib 是什么?”这类语义问题,VectorDB 的结果更稳定;SVM 和 TF-IDF 也能检索,但命中效果并不总是理想。这个对比很有价值,因为它没有把向量检索神化。

关键词检索适合精确名称、编号、错误码、API 字段;向量检索适合自然语言问题、同义表达和概念解释;metadata 过滤适合章节、来源、时间、权限、版本这些结构条件。真实知识库通常不是单选题,而是把几种检索方式组合起来。比如先按产品线和版本过滤,再用关键词锁定错误码,同时用向量检索补充相近描述,最后做重排。

所以选向量数据库时,不要只问“哪个库最强”。更应该问:它能不能方便地保存 metadata,能不能持久化,能不能支持过滤和 MMR,能不能看到每次召回的 source 和 score,能不能和现有业务数据打通。RAG 的质量不是某一个组件的功劳,而是整条检索链路是否可控。

落地时先盯住三件事

第一,入库资料要干净。重复文件、乱码、页眉页脚、目录残片、错位表格,都会变成向量库里的噪声。很多时候,检索效果差不是 Embedding 模型不够先进,而是被送去 embedding 的文本本身就不适合检索。

第二,metadata 要提前设计。文件名、章节、页码、业务分类、版本、发布时间、权限范围,这些字段看起来普通,却决定了后面能不能做精确过滤。没有 metadata 的向量库,就像只有书页没有书名和目录的图书馆,能翻到内容,但很难稳定地翻对。

第三,要单独评估检索层。准备一批真实问题,只看 Top-1、Top-3、Top-K 是否命中正确资料,是否有重复,是否来自正确章节。不要只看最终回答顺不顺。大模型很会把错误上下文讲得像真的,只有把检索结果摊开看,才能知道问题到底出在资料、切分、向量库、过滤条件还是生成提示词。

向量数据库在 RAG 里并不是一个神奇黑盒。它更像一套索引系统:把文档切片、向量表示、来源信息和检索策略组织起来。用得粗糙时,它只能返回“看起来相似”的片段;用得细一点,它才能把正确、互补、可引用的资料交给模型。差别往往就在这些不显眼的工程细节里。

常见问题

向量数据库能替代 MySQL 吗?

不能。向量数据库主要解决语义相似检索,MySQL 更适合结构化数据、事务、精确查询和报表分析。RAG 应用中两者经常配合使用。

为什么相似性搜索会召回重复内容?

因为它优先找和问题最相似的片段。如果资料库里有重复文档或近似 chunk,Top-K 很容易被这些片段占满,需要去重或使用 MMR 改善结果。

metadata 过滤和提示词过滤有什么区别?

metadata 过滤发生在检索前或检索中,能先缩小候选资料范围;提示词过滤发生在生成阶段,模型已经看到了材料,稳定性通常不如前置过滤。

RAG、知识库与长期记忆

继续阅读

返回专题