
引言
面对大型语言模型(LLM)知识陈旧、容易幻觉的固有挑战,检索增强生成(RAG)技术已然成为构建可信、精准、知识渊博AI应用的行业基石。RAG的核心魅力在于它用强大的语义检索能力,为LLM实时注入了新鲜、准确的外部知识,它能真正理解用户的查询意图,从海量文档中找到与之"意思相近"而非仅仅"字面相同"的内容。<>
然而在语义理解背后横亘着一个巨大的工程挑战:如何确保在拥有数百万甚至数十亿文档的知识库中,检索出精准且全面的最相关的信息?系统的最终回答质量,在很大程度上取决于其检索模块的寻宝 能力,衡量这一能力的核心指标,便是召回率(Recall Rate)。
提升召回率并非仅仅是优化数据库或调整某个参数那么简单,它是一个复杂的系统工程,伴随了一条完整的技术链路:从源头的数据清洗 与文本分块 ,到嵌入模型 的选择,再到向量索引 的高效构建,直至混合检索 与智能排序等高级策略的应用。链条上的任何一环出现短板,都可能成为整体性能的瓶颈。
1. 什么是向量与维度?
在讨论索引与召回率之前,必须首先理解它们的操作对象------向量(Vector)。
在语义检索的语境下,使用一种名为**嵌入模型(Embedding Model)**的深度学习模型,将非结构化的文本翻译成一个由数百个浮点数组成的列表,即向量。这个向量可以被看作是该段文本在多维"语义空间"中的唯一坐标。在这个空间里,意思相近的文本,其坐标点也相互靠近。
- 向量 (Vector) :在语义空间中,一个词或一句话的"语义坐标"。它是一长串的浮点数,例如
[0.03, -0.21, 0.88, ..., -0.54]
。这个列表就是向量。- 维度 (Dimension) :这串浮点数列表的长度。如果我们用了768个数字来表示一个语义坐标,我们就说这个向量的维度是768。
即向量就是一组用来在某个空间中定位一个点的数字坐标;维度就是这组数字坐标的数量。
因此,问题就从"寻找意思相近的文本"转变成了一个纯粹的数学问题:"在一个高维空间中,如何快速找到与给定查询向量最接近的N个邻居向量?"
2. 检索系统的"黄金指标":召回率
召回率(Recall Rate) 是衡量检索系统性能的核心指标之一。它的定义非常直观:
在所有真正相关的文档中,检索系统成功的找回了多少条?
计算公式:

用一个捕鱼的例子来理解:
- 假设池塘里总共有100条鱼是想捕捞的目标鱼种(所有相关文档)。
- 撒了一网,捞上来80条鱼,其中有60条是目标鱼种(检索到的相关文档)。
- 那么这次捕捞的召回率就是
60 / 100 = 60%
。
在RAG系统中,召回率至关重要,如果一个用户的查询,其最关键的答案所在的文档块未能在检索阶段"被召回",那么无论后续的LLM有多么强大也无法根据一份缺失的信息凭空生成正确答案。
低召回率是RAG系统产生错误或不相关答案的首要原因。
3. 决定召回率上限的模型与数据
在深入研究如何通过索引技术加速检索之前,先建立一个认知:**检索系统的召回率上限,在数据被向量化的那一刻,就已经被基本确定了。**后续所有的索引和检索优化,都只是在"尽可能地逼近"这个上限。因此优化,须从源头开始。
3.1 嵌入模型(Embedding Model)
嵌入模型是整个语义检索系统的灵魂,它决定了对"相似性"理解的深度和广度。
3.1.1 核心作用
一个优秀的嵌入模型能够将复杂的人类语言(包括其上下文、一词多义、同义词、反义词等)映射到一个结构化的向量空间中。在这个空间里,"意思"的远近可以通过数学距离来衡量。正如您之前所理解的,它能轻易地将**"如何解决电动汽车的续航焦虑"** 与**"缓解新能源车里程焦虑的途径"**这两个语义相同但字面迥异的句子关联起来。
3.1.2 如何选择?
- 领域适应:一般用的都是通用模型。当然有可能的话在知识库高度垂直(比如我所在的行业规划与估价等业务领域)使用经过微调的模型会更好,将带来巨大的性能提升。
- 性能与成本的权衡:通常模型参数量越大、维度越高,其语义表达能力越强,但同时也会带来更高的计算开销(向量化速度慢)和存储成本(向量占用空间大)。需要根据业务场景的性能要求和成本预算进行权衡。
- 参考权威榜单:可以关注 MTEB(Massive Text Embedding Benchmark)等公开的权威评测榜单,它为不同模型在各类任务上的表现提供了数据驱动的参考。
3.1.3 嵌入过程的一些参数
-
normalize_embeddings
(向量归一化)布尔值参数。建议始终将
normalize_embeddings
设置为True
。这已经成为现代语义检索流程中的事实标准。它确保了你的相似度计算是在一个公平、一致的"单位球体"空间内进行的,能最准确地反映语义的远近。 -
prompt
/prompt_name
(提示词工程)尽量遵守并仔细阅读所选模型 Hugging Face 主页上的文档,若模型有 Prompt 要求,需要在代码中实现。
-
precision
(嵌入精度与量化)该参数决定了输出向量中每个数值的数据类型,,通常默认为
float32
。从
float32
降至int8
等低精度格式的过程,称为量化 ,量化的核心优势是大幅压缩存储空间 ,但这种压缩是有损的。最好始终以
float32
作为基准和默认选项,以保证最高的语义保真度。 -
对超长文本的处理(
max_length
)所有嵌入模型都有一个最大的输入序列长度,通常是512个Token。若一个文本块(chunk)超过了这个长度,大部分
encode
函数会默认无声地将其截断(Truncate),只处理前面的512个Token。这个问题可以与上游的文本分块(Chunking)阶段 联合解决,分块策略与模型的
max_length
相适配。确保切分出的任何一个独立的文本块其长度(经过Tokenize 后)都在模型的处理范围之内。相关调整参数:
padding='max_length'
:填充短文本至统一长度。truncation=True
:强制截断超长输入。
-
batch_size
(批处理大小)指模型在一次前向传播中同时处理的文本块(Chunk)数量,可通过增大
batch_size
,可以充分利用GPU的并行计算能力,实现数量级的速度提升。因为唯一限制因素是 GPU 显存 ,
batch_size
越大,占用的显存也越多,所以可以从一个值开始(32或64)逐步测试运行,直到找到那个既能充分利用显存、又不会导致程序崩溃的均衡值,这个值就是最佳性能配置。
3.1.4 Qwen3 Embedding
通义千问团队在 2025 年 6 月 6 日发布了 Qwen3 Embedding 文本嵌入系列模型,顺带聊一下。
Qwen3 Embedding提供三种参数规模:
模型名称 | 参数量 | 嵌入维度 | 上下文长度 | 适用场景 | 关键特性 |
---|---|---|---|---|---|
Qwen3-Embedding-0.6B | 0.6B | 1024(可调) | 32K | 边缘设备(手机/Raspberry Pi) | 低资源部署、多语言基础任务 |
Qwen3-Embedding-4B | 4B | 2560(可调) | 32K | 通用服务器/云服务 | 平衡性能与效率 |
Qwen3-Embedding-8B | 8B | 4096(可调) | 32K | 高性能计算/企业级应用 | 多语言SOTA、代码检索最优解 |
特性如下:
- 自定义嵌入维度:支持输出维度的动态调整,用户可依据存储和计算需求优化资源消耗。
- 指令感知(Instruct Aware) :通过指令模板定制输入格式(如
{Instruction}{Query}<|endoftext|>
),提升特定任务性能1%-5%。(这个特性实际没看懂) - 长上下文支持:全系支持 32K token 上下文,无需切片即可处理长文档(如合同、论文)
- 语言覆盖 :支持超过100种语言,包括主流自然语言(中/英/法等)和多种编程语言(Python/Java等)
- 性能表现优异:MTEB 多语言榜8B模型以70.58分排第一,超越Gemini Embedding的68.37分;对于中文进行优化等
- 云服务集成:阿里云百炼平台提供API服务,无需本地部署
Qwen3 Embedding vs 主流嵌入模型
模型 | 参数量 | MTEB多语言得分 | 代码检索(nDCG@10) | 上下文长度 | 多语言支持 |
---|---|---|---|---|---|
Qwen3-Embedding-8B | 8B | 70.58 | 80.68 | 32K | 100+ |
Gemini-Embedding | - | 68.37 | 75.20 | 8K | 50+ |
BGE-M3 | 1.5B | 63.22 | 40.88 | 8K | 100+ |
text-embedding-ada-002 | - | 65.10 | 72.50 | 8K | 50+ |
Sentence-BERT | 355M | 59.56 | 38.20 | 512 | 50+ |
3.3 重排模型(Reranking Model)
使用的位置在召回之后。
是一种专门用于对一个小范围的、已经经过初步筛选的文档列表 进行二次排序,以提升最终排序结果精准度的模型。它的核心作用是,在"召回(Recall)"阶段之后,执行"精排(Precision)"任务。它不负责从海量数据中捞取信息,而是负责对捞取上来的信息进行"去粗取精、优中选优"。
与嵌入模型不同,嵌入模型的速度极快,因为所有文档的向量可以被提前计算并索引(比如在 Milvus 中),查询时只需编码一次查询向量,然后进行高效的向量近邻搜索。重排模型的速度很慢 ,因为它必须为每一个"查询-文档对"都执行一次完整的前向传播计算。这导致它完全不适用于对海量文档库进行初筛。它不输出向量,而是直接输出一个单一的相关性分数(通常在0到1之间),表示这对"Query-Document"的匹配程度。
常见的开源 Reranking Model 有BAAI/bge-reranker-large
等。
3.2 文本分块(Chunking)策略
将长文档切分成合适的"知识单元"(Chunks),是直接影响检索质量的关键一步。分块的优劣,决定了每个向量所承载信息的信噪比。
3.2.1 核心权衡
- 分块太小:导致上下文信息丢失,形成语义孤岛。一个复杂的概念被硬生生从中间切开,任何一半都无法独立表达完整的含义。
- 分块太大:引入过多无关的"噪声",导致向量的主题被稀释。一个包含多个不同主题的大段落,其最终生成的向量会是一种平均主义的表达,缺乏针对性,难以被精准查询命中。
3.2.2 一些分块策略
- 固定大小分块(Fixed-Size Chunking) :最简单粗暴的方法。为了缓解其一刀切导致的语义割裂问题,通常会设置重叠区域(Overlap),即让每个块的末尾部分与下一个块的起始部分内容相同,以保证上下文的连续性。
- 递归字符分块(Recursive Character Text Splitting) :一种更智能的策略。它会尝试按一个预设的、有优先级的分隔符列表(比如
["\n\n", "\n", " ", ""]
等等)进行分割。它会优先尝试用段落符分割,如果分出的块仍然过大,它会退一步,尝试用换行符分割,以此类推。这在很大程度上尊重了文本的自然结构。 - 基于句子的分块(Sentence-Based Chunking):以自然句子为最小单元,组合多个句子成块(比如每块3句)。保留了句子级语义完整性,适合机器翻译、情感分析等任务,但块大小不均,长句子可能超Token限制,短句子导致信息稀疏,也依赖分词器质量,复杂标点或非标准文本易出错。
- 语义分块(Semantic Chunking):这是更先进的思路。不再依赖固定的长度或符号,而是利用嵌入模型本身来判断语义的连贯性。其基本思想是,将句子逐一向量化,并计算相邻句子(或句子组)之间的语义相似度。当相似度出现一个明显的"断崖"时,就认为这里是一个自然的语义边界,适合进行切分。
- 代理分块(Agentic Chunking):调用LLM识别自然分界点(如主题转换、章节结束),来模拟人类阅读逻辑进行分块。利用提示工程引导LLM输出分块。优点是可以理解深层语义,避免机械切割,在处理非结构化文本(小说、访谈)时效果卓越,但依赖 LLM 的能力,成本也较高。
3.3 严谨的数据预处理
"垃圾进,垃圾出"(Garbage In, Garbage Out)是数据科学的黄金法则,在RAG中同样适用。原始文档的质量直接决定了最终向量的质量。
- 核心任务 :
- 内容清洗:去除文档中所有与核心知识无关的内容,如网页的导航栏、页眉页脚、广告语、版权声明等。
- 格式转换与规范化:将复杂的格式(如PDF中的多栏布局、Word中的表格)转换为更简洁、更利于模型理解的格式(如Markdown)。统一处理文档中的空格、换行和特殊字符。
- 修复与增强:修正明显的拼写错误或OCR(光学字符识别)错误。在某些场景下,还可以考虑将专有名词的缩写展开(如将"AI"展开为"Artificial Intelligence"),以增强语义的明确性。
- 隐私与合规:清洗或脱敏文档中可能存在的个人身份信息或其他敏感数据。
4. 向量索引,效率的引擎
当面对数百万级别的向量数据时,通过暴力计算(将查询向量与库中每一个向量进行比较)来找出最近邻是完全不可行的,为了解决这个问题,向量索引(Vector Index) 应运而生。
**向量索引是一种为了加速高维向量相似度搜索而设计的复杂数据结构。**它通过对海量向量进行预先的组织和划分,使得在查询时无需与所有向量进行比较,从而实现数量级的速度提升。
但这种速度的提升并非没有代价,绝大多数高性能的向量索引算法都属于**近似最近邻(ANN, Approximate Nearest Neighbor)**搜索的范畴,"近似"意味着它们牺牲了一定的准确性(即召回率)来换取极致的查询速度,这需要在索引技术上做出权衡(Trade-off)。
5. 主流向量索引技术
不同的向量索引算法如同不同派系的武功,各有其长处和适用场景。以 Milvus 为例,以下是几种在向量数据库中广泛应用的主流索引类型。
5.1 FLAT(暴力检索)
-
工作原理:这就是我们前面提到的"暴力方法"。它不使用任何索引结构,就是简单地将查询向量与集合中所有向量进行逐一比较。
-
优点:
- 100%准确,召回率100%。
- 无需额外的索引构建时间。
-
缺点:
- 当数据量稍大(如超过百万)时,查询速度极慢,基本不具备实用性。
-
适用场景:
- 数据集非常小(例如低于10万)。
- 对查询结果的准确性有绝对要求,不容许任何误差的场景。
- 用于评估其他索引类型的准确率时,作为一个"黄金标准"进行对比。
5.2 IVF系列(倒排文件索引)
IVF (Inverted File) 是最经典、最直观的 ANN 索引之一。
- 原理 :
- 聚类(Clustering) :在构建索引时,算法会先从所有向量中选出
nlist
个代表性的向量作为"聚类中心"(centroids)。 - 分组(Grouping) :然后,将所有的向量根据距离远近,分配到离它最近的那个聚类中心所代表的"桶"里。这样,整个向量空间就被划分成了
nlist
个区域。 - 查询(Querying) :当一个查询向量进来时,它首先只跟
nlist
个聚类中心比较,找出最近的nprobe
个桶。然后,算法只在这nprobe
个桶内进行暴力搜索,从而极大地减少了需要比较的向量总数。
- 聚类(Clustering) :在构建索引时,算法会先从所有向量中选出
- 核心参数 :
nlist
:聚类中心的数量,即桶的数量。nlist
越大,数据划分得越细。nprobe
:查询时要去搜索的桶的数量。nprobe
越大,搜索范围越大,结果越精确,但速度越慢。
- 常见类型 :
- IVF_FLAT:在选定的桶内部,使用FLAT(暴力)方法进行搜索。它在速度和精度之间取得了很好的平衡。
- IVF_PQ :为了进一步提升性能和降低内存占用,它在IVF的基础上引入了**乘积量化(Product Quantization, PQ)**技术。PQ会将长向量压缩成短编码,从而减少了内存使用和计算量,但会带来额外的精度损失。适用于海量数据集且内存资源紧张的场景。
- 适用场景 :
- IVF_FLAT是通用场景下的"万金油",在大部分情况下都能提供良好的性能和高召回率。
- IVF_PQ适用于数十亿级别的超大规模数据集。
- 核心权衡 :
nprobe
参数是调节性能的关键。nprobe
值越大,搜索的区域越多,召回率越高,但查询耗时也越长。
5.3 HNSW(分层可导航小世界图)
HNSW (Hierarchical Navigable Small World) 是目前公认的性能最高的图索引算法之一。
- 工作原理 :它的思想是构建一个"高速公路网"。
- 构建图:它将向量看作图中的节点,并根据向量间的距离为它们建立连接(边),形成一个"小世界网络"(即网络中任意两点都能通过很少的步骤到达)。
- 分层:它不止构建一张图,而是构建一个多层的图结构。最顶层是最稀疏的"高速公路",越往下层越密集,类似城市快速路和地面道路。
- 查询:查询时,从顶层最稀疏的图开始,找到一个离查询目标最近的节点作为入口,然后"跳"到下一层,继续寻找更近的节点,依此类推,直到在最底层找到最终的近似最近邻。
- 核心参数 :
M
:图中每个节点的最大连接数。M
越大,图的连接性越好,构建索引越慢,但查询精度越高。efConstruction
:构建索引时搜索的邻居节点范围大小。越大,索引质量越高,但构建时间越长。ef
(或search_k
):查询时搜索的范围大小。越大,结果越精确,但速度越慢。
- 优点 :
- 查询性能极高,通常比IVF系列更快。
- 召回率也非常高,可以通过调整参数
ef
灵活控制。
- 缺点 :
- 构建索引时需要消耗大量内存。
- 索引文件本身也比较大。
- 适用场景 :
- 对查询性能(QPS,每秒查询数)有极高要求的场景。
- 内存资源相对充足。
- 核心权衡 :查询时的
ef
(search scope)参数是其性能调节器。ef
值越大,搜索时探索的路径和节点越多,召回率越高,但耗时也相应增加。
5.4 如何选择?
索引类型 | 数据规模 | 内存占用 | 查询性能 | 召回率(准确性) | 适用场景 |
---|---|---|---|---|---|
FLAT | < 1M | 中 | 极低 | 100% | 学术研究、小数据集、性能基准测试 |
IVF_FLAT | 1M - 100M | 中 | 高 | 高 | 通用,性能与准确性的最佳平衡点 |
HNSW | 1M - 100M | 高 | 极高 | 极高 | 对查询速度要求苛刻,内存充足 |
IVF_PQ | > 100M | 低 | 较高 | 中-高 | 海量数据集,对内存占用敏感 |
6. 索引与召回率
通过对索引的了解,可以得出一个重要的结论:
对于ANN索引而言,召回率不是一个固定的属性,而是一个可供调节的动态参数。
索引算法(如IVF和HNSW)的设计,通过nprobe
和ef
这样的参数将性能的控制权交到了开发者手中。可以在一个连续的光谱上进行选择:
- 追求极致速度 :设置一个较小的
nprobe
或ef
值。系统响应飞快,但可能会错失一些相关结果(召回率较低)。 - 追求极致准确 :设置一个较大的
nprobe
或ef
值。系统会更仔细地搜索,召回率接近100%,但响应时间会变慢。
最佳实践是,在满足业务可接受的延迟(Latency)前提下,通过不断实验,找到一个能提供最高召回率的参数配置。这通常需要在真实的硬件环境上,使用具有代表性的数据集进行压测和调优。
7. 高级检索与排序策略
通过前述步骤已经拥有了高质量的、经过合理分块和预处理的向量数据,之后便进入了召回阶段"最后一公里"------通过高级的检索与排序策略,在查询时尽可能地捞出最相关的结果。
7.1 策略性的索引调优
如上一节所述,针对数据量和硬件系统性地测试不同的索引类型(IVF_FLAT vs HNSW)及其关键参数,找到"最佳平衡点"。
7.2 扩大检索范围(Top-K)
在检索时可以选择返回更多的候选文档(例如,从Top-3增加到Top-5或Top-10)。这直接增加了包含正确答案的文档块被送入 LLM 的可能性,是提高最终答案质量最简单直接的方法之一。当然也要注意送入更多的文档快也会增加更多的"噪声",在 Top 数量的选择上也需要进行权衡。
7.3 融合词法与语义的混合检索
Milvus 在 2.4 版本中推出了 **混合检索(Hybrid Search)**功能,可以进一步的提高检索的质量。
混合检索(Hybrid Search) 是一种先进的检索策略,它将向量的语义相似度搜索与传统的关键词搜索(以及可选的结构化数据过滤)结合在一起,以提供比单一检索方法更精准、更全面的结果。
7.3.1 为什么需要混合检索?
纯粹的语义搜索在某些场景下存在会存在一些不足:
- 精确术语 :对于产品型号(如
MacBook Pro M3
)、错误码(ERROR_404_NOT_FOUND
)、法律条款编号等专有名词,用户可能期望的是精确匹配,而向量模型的"模糊"特性可能会泛化这些词语,导致召回不准。 - 关键词稀疏性:如果一个关键的、但在大型语料库中不常见的词(如一个新创公司的名字)是查询的核心,嵌入模型可能无法充分理解其重要性。
为了弥补这些不足,将向量搜索的"语义"能力与传统关键词搜索的"词法"能力结合起来,形成优势上的互补,即为混合检索。
7.3.2 混合检索(Milvus 2.4)
混合检索允许单个集合集成最多 10 个向量字段(如 filmVector
和 posterVector
),每个字段可代表不同模态数据(图像、音频、文本等)或不同嵌入模型生成的向量。用户可创建多个 AnnSearchRequest
实例,分别对不同向量字段执行近似最近邻(ANN)搜索,例如同时搜索电影的标题向量和海报向量 。
如何使用混合检索:
-
创建支持混合检索的集合(Collection)
pythonfrom pymilvus import FieldSchema, CollectionSchema, DataType, Collection # 1. 定义多样化的字段 pk_field = FieldSchema(name="pk", dtype=DataType.INT64, is_primary=True, auto_id=True) vector_field = FieldSchema(name="vector", dtype=DataType.FLOAT_VECTOR, dim=768) # 为关键词搜索准备的文本字段 text_field = FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=512) # 为过滤准备的标量字段 category_field = FieldSchema(name="category", dtype=DataType.VARCHAR, max_length=64) year_field = FieldSchema(name="release_year", dtype=DataType.INT64) # 2. 创建Schema schema = CollectionSchema( fields=[pk_field, vector_field, text_field, category_field, year_field], enable_dynamic_field=False ) # 3. 创建集合 collection = Collection(name="hybrid_rag_collection", schema=schema)
-
创建多种索引
python# 1. 为向量字段创建HNSW索引 index_params_vec = {"metric_type": "L2", "index_type": "HNSW", "params": {"M": 8, "efConstruction": 200}} collection.create_index(field_name="vector", index_params=index_params_vec) # 2. 为文本字段创建BM25索引 index_params_kw = {"index_type": "BM25", "params": {}} collection.create_index(field_name="text", index_params=index_params_kw) # 标量字段的索引通常会自动创建,无需手动操作 utility.wait_for_index_building_complete(collection.name) collection.load()
-
执行混合检索查询
python# 1. 准备查询数据 query_vector = [model.encode("家庭旅行车").tolist()] # 向量搜索的查询向量 query_text = "热泵空调" # 关键词搜索的查询文本 # 2. 构建向量搜索请求 vec_search_req = AnnSearchRequest(data=query_vector, anns_field="vector", param={"metric_type": "L2", "params": {"ef": 64}}, limit=10) # 3. 构建关键词搜索请求 kw_search_req = KeywSearchRequest(data=[query_text], anns_field="text", param={"index_type": "BM25"}, limit=10) # 4. 使用特定的 API hybrid_search() 执行混合搜索 res = collection.hybrid_search( reqs=[vec_search_req, kw_search_req], rerank=RRFRanker(), # 使用RRF算法进行结果融合 limit=5, # 在这里应用标量过滤 filter="release_year > 2023 AND category == 'SUV'" ) # 5. 处理结果 for hit in res[0]: print(f"ID: {hit.id}, Score: {hit.score}, Distance: {hit.distance}")
混合检索的查询延迟通常会高于单纯的向量搜索,但精度的提升也大大提高。
性能降低的原因:
- 多路并行计算:系统需要同时执行向量搜索和关键词搜索两个独立的计算任务,这自然比只做一个任务要耗时。
- 结果融合开销:在两路或多路检索完成后,还需要一个额外的步骤------结果融合(如RRF算法),来计算最终的综合排名。这个步骤虽然很快,但也是额外的计算开销。
- 过滤开销 :如果
filter
表达式非常复杂,过滤本身也会带来一定的性能开销。
但有趣的是,在某些情况下,性能也有可能会提升?
比如一个好的过滤条件,反而可能会大幅提升整体检索性能 。 一个WHERE category = 'SUV'
的过滤条件能将千万级的搜索空间瞬间缩小到只有十万级,那么后续的向量和关键词搜索将在这个极小的子集上进行,其速度会快得多。在这种情况下,过滤带来的性能增益甚至可能抵消掉多路检索和融合的开销。
我觉得很有意思。
7.3.3 Sparse-BM25 全文检索(Milvus 2.5)
到了 2.5 版本,Milvus 引入了 Sparse-BM25 全文搜索,对混合检索进行了增强。
核心内容:
-
内置 Tantivy 分词引擎,支持直接输入原始文本,自动完成分词→稀疏向量转换→检索全流程,无需手动预处理
pythonschema.add_field( field_name='text', dtype=DataType.VARCHAR, enable_analyzer=True, # 启用分词器 analyzer_params={"type": "english"}, # 配置英文分词 enable_match=True # 构建倒排索引 )
-
稀疏向量优化
- 图索引与量化技术:使用图索引替代倒排索引,结合乘积量化(PQ)和标量量化(SQ),减少 60% 内存占用,提升长文本查询效率 。
- 动态词频更新:分布式管理语料库词频,支持实时数据插入时的统计更新
-
混合检索增强
支持 向量检索 + BM25 全文检索 的深度融合
python# 创建全文检索请求(原始文本输入) text_req = AnnSearchRequest(query_text, "text_field", metric_type="BM25") # 创建向量检索请求 vector_req = AnnSearchRequest(query_vector, "vector_field") # 混合检索并应用RRF重排序 results = client.hybrid_search([text_req, vector_req], ranker=RRFRanker())
在查询速度上,百万级数据集,BM25 检索仅需 6ms ,较 Elasticsearch 提速 30倍 ;在并发能力上,文本匹配(Text Match)的 QPS 较 2.4 通配符匹配(Wildcard)提升 400倍。
2.5 版本从多模态到全模态的升级,突破向量字段限制,通过 Sparse-BM25 实现 非结构化文本与向量数据的统一处理 ,形成真正的多源异构数据检索能力,全文检索时延降至毫秒级,并发吞吐量提升 400 倍,基于 稀疏向量优化 替代了传统倒排索引,结合图索引与量化技术重构存储引擎。
7.3.4 Milvus 2.4 vs Milvus 2.4
功能维度 | Milvus 2.4 | Milvus 2.5 | 升级意义 |
---|---|---|---|
文本处理能力 | 需手动转换文本为稀疏向量 | 原生支持原始文本输入/输出 | 简化流程,降低开发门槛 |
混合检索架构 | 仅支持多向量字段融合 | 支持 向量+全文检索 深度融合 | 覆盖更广泛搜索场景 |
分词与索引 | 无内置分词器 | 集成 Tantivy 引擎,动态构建倒排索引 | 提升文本查询精度与速度 |
性能优化 | 依赖外部 BM25 工具,扩展性差 | 图索引+量化技术,内存占用降 60% | 支持亿级数据实时检索 |
适用场景扩展 | 多模态数据搜索 | 新增 关键字精确匹配(如序列号、术语) | 增强专业领域检索能力 |
总结
- 奠定基础
- 选好模型:选择与业务领域匹配、性能卓越的嵌入模型(如Qwen3-Embedding),并调整和设置各种关键参数进行调优。
- 切好文本:采用优秀和核实的文本分块策略,确保文本块大小适中,既包含完整上下文,又避免噪声干扰。
- 洗好数据 :在向量化之前,对原始文档进行严格的清洗和预处理。
- 精通检索
- 用对索引 :根据数据规模和性能要求,在 Milvus 中选择最合适的索引类型(通用选
IVF_FLAT
,性能优先选HNSW
)。 - 调优参数 :通过量化测试,找到索引查询参数(如
ef
,nprobe
)在召回率与延迟之间的最佳平衡点。
- 策略升级
- 混合检索 :结合向量搜索 的语义能力与BM25的关键词能力,弥补单一检索的短板,大幅提升结果的鲁棒性。
- 二次精排 (Re-ranking) :在初步召回一个较大的候选集后,使用重排模型进行二次精准排序,确保最终送入大语言模型的上下文质量最高。
提升RAG系统的召回率,并非一项单一的调优任务,而是一项贯穿数据处理、模型应用、索引构建到查询策略全链路的系统工程,必须从高质量的数据源头做起,通过科学的索引与查询策略逼近理论上限,并最终利用混合检索和重排等高级策略突破瓶颈,实现系统性能的全面跃升。