支持私有化部署
AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


BM25:RAG中的文本相关性排序

发布日期:2025-05-19 13:03:19 浏览次数: 1545 作者:AI取经路
推荐语

深入探索BM25算法在RAG系统中的关键作用与实现细节。

核心内容:
1. BM25算法在RAG检索阶段的应用
2. BM25判断相关性的方法与公式
3. BM25与TF-IDF的比较及优势分析

杨芳贤
53A创始人/腾讯云(TVP)最具价值专家


-正文-

BM25 是一个文本相关性排序算法。

在 RAG 系统的检索阶段,它能快速地从海量文档中找到与查询最匹配的候选段落,为后续的生成模型提供更加聚焦的上下文。

BM25 可以独立使用,也可以和 dense 检索联合构建更强的 hybrid 检索器

  • 1. BM25是做什么的?
  • 2. BM25是怎么判断相关性的?
    • 2.1 词频 (Term Frequency, TF)
    • 2.2 逆文档频率 (Inverse Document Frequency, IDF)
    • 2.3 文档长度
  • 3. BM25的实现原理和公式
  • 4. 例子:计算BM25分数
    • 4.1 文档信息
    • 4.2 假设查询  为:“模型 算法 性能”
    • 4.3 计算 IDF (使用 BM25 的 IDF 公式):
    • 4.4 计算每个文档的 TF-IDF 分数
    • 4.5 计算每个文档的 BM25 分数
    • 4.6 和TF-IDF的对比分析:
  • 5. BM25的优势
  • 6. 使用LangChain实现BM25检索
  • 总结

-- 领取学习资料大礼包,见文末

当用户提出问题时,RAG(检索增强生成,Retrieval-Augmented Generation)首先会从海量数据中“检索”出相关的文档片段,然后将这些检索结果提供给LLM模型,以生成更准确、更可靠的答案。

信息检索是 RAG 的基石,而实现高效准确的检索,需要依赖各种排序和匹配算法。

在信息检索领域,既有基于向量相似度的现代方法,也有基于关键词的传统方法。

TF-IDF(词频-逆文档频率,Term Frequency-Inverse Document Frequency)是经典的关键词匹配算法之一,而 BM25(Best Matching 25)则是在 TF-IDF 基础上发展起来的一种更先进的算法。

BM25在信息检索领域久经验证且广泛应用,在 RAG 的检索阶段扮演着重要角色。

相关阅读:TF-IDF:理解“关键词”的价值

1. BM25是做什么的?

Okapi BM25(BM 是最佳匹配的缩写)是一种用来估计文档与给定搜索查询相关性的排序函数。

排序函数的名称是 BM25。完整的名称是Okapi BM25。

Okapi 是第一个使用它的系统的名称,即 1980 年代和 1990 年代在伦敦城市大学实施的 Okapi 信息检索系统。

简单来说,BM25是一个用来计算“用户查询”和“文档”之间相关性分数的算法。分数越高,说明文档与用户查询越相关。

在RAG的检索阶段,当用户输入一个查询时,BM25会计算这个查询与知识库中每一个文档的相关性分数,然后把得分最高的几个文档挑出来,交给生成模型。

2. BM25是怎么判断相关性的?

BM25的核心思想和你平时找信息时的感觉很像:

2.1 词频 (Term Frequency, TF)

如果一个词在文档中出现的次数越多,那么这个文档可能就越和这个词相关。

比如,你搜索“苹果手机”,如果一个文档里“苹果”和“手机”这两个词出现了很多次,那它很可能就是讲苹果手机的。

但是, BM25不会无限制地强调高词频,它有一个“饱和”的概念。 想象一下你吃苹果,吃第一个很开心,吃第二个也不错,但吃到第十个可能就没那么开心了。

BM25认为词频的贡献会逐渐趋于平缓,达到一定次数后,再增加词频对相关性的提升效果有限。

2.2 逆文档频率 (Inverse Document Frequency, IDF)

一个词在整个文档集合中出现的文档数量越少,它就越能区分文档的主题,因此它的重要性越高。

比如,“的”、“是”、“在”这些词几乎在所有文档里都会出现,它们对判断文档主题没什么帮助,IDF值就很低。

但像“BM25”、“RAG”、“Transformer”这些词,只会在特定领域的文档中出现,它们的IDF值就很高,更能说明文档是关于这些主题的。

2.3 文档长度

BM25会考虑文档的长度。一篇只有 100 个字的新闻报道里提到了两次“人工智能”,和一本 10 万字的百科全书里提到了两次“人工智能”。很明显,前者的主题更可能集中在“人工智能”上。

BM25会倾向于认为,一个词在短文档中出现,比在长文档中出现更能体现相关性。它会通过一个机制来“惩罚”过长的文档,避免它们仅仅因为词多而获得高分。

BM25就是结合了这三个主要因素,通过一个公式来计算最终的相关性分数。公式里还有一些参数(比如),可以调整词频饱和度和文档长度的影响程度。

3. BM25的实现原理和公式

现在我们来看看BM25是如何通过公式来实现这些想法的。

BM25计算查询  和文档  之间相关性分数  的基本思想是,将查询  中的每个词  的相关性贡献加起来。

公式可以左右滑动

对于查询中的 每一个词  ,它对文档  的贡献分数由以下几部分决定:

  1. 词  在文档  中的词频 (Term Frequency):

  2. 词  的逆文档频率 (Inverse Document Frequency ):

    这是衡量词  在整个文档集合中的稀有程度。计算公式通常是:

  •  是文档集合中的总文档数

  •  是包含词  的文档数量

  • 这里的  函数和  是为了平滑处理,避免某些词出现文档数为0或时出现问题。

IDF值越高,说明词越稀有,越重要。

  1. 词频饱和部分:

    这一部分用来处理词频的饱和问题,公式是:

  • 词频: 是词  在文档  中的词频;

  • 饱和参数: 是一个正参数,控制词频(TF)对文档得分的影响,通常取值在  到  之间通常能获得较好的结果。

  • 文档长度归一化(惩罚长文档) :

    这一部分用来处理文档长度的影响。

    公式中的  表示文档  的长度 与整个文档集合的平均文档长度 的比值。

    它使用一个参数  来控制文档长度归一化的程度。参数  通常取值在  到  之间。当  时,不进行文档长度归一化;   当  时,进行完全的文档长度归一化;

拆完会发现,BM25 的结构就是三块:

  • IDF:筛掉没用的高频词
  • TF 饱和:限制关键词堆砌带来的加分
  • 文档长度归一化:短文优先、长文降权

整个公式就是在模仿我们人类“找关键词”、“判断重点”、“嫌弃水词多”的一系列直觉,只不过变成了数学语言。

4. 例子:计算BM25分数

为了更好地说明 BM25 相较于 TF-IDF 在处理文档长度和词频饱和度方面的优势,我们使用一个包含 3 篇文档的文档集合进行演示。

为了简化,我们假设这些文本已经经过了分词处理。

  • 文档 A: 机器学习 模型 训练 算法 性能 (长度 5)

  • 文档 B: 深度学习 模型 神经网络 训练 大数据 算力 优化 性能 (长度 8)

  • 文档 C: 算法 效率 优化 性能 (长度 4)

4.1 文档信息

  • 总文档数 

  • 文档 A 长度 

  • 文档 B 长度 

  • 文档 C 长度 

  • 平均文档长度 

4.2 假设查询  为:“模型 算法 性能”

查询中的词是  “模型”,  “算法”,  “性能”。

4.3 计算 IDF (使用 BM25 的 IDF 公式):

  • 词“模型”出现在文档 A 和文档 B 中,

  • 词“算法”出现在文档 A 和文档 C 中,

  • 词“性能”出现在文档 A, 文档 B 和文档 C 中,

4.4 计算每个文档的 TF-IDF 分数

我们使用标准的 TF-IDF 公式:

词频 (TF):

TF-IDF 分数计算:

  • 文档 A:

  • 文档 B:

  • 文档 C:

TF-IDF 排名结果:

根据 TF-IDF 分数,文档排名为:

文档 A (0.998) > 文档 B (0.528) = 文档 C (0.528)

在这个简单的 TF-IDF 计算中,文档 B 和文档 C 的得分相同,因为它们都包含查询中的两个词,且这些词的 IDF 值相同。TF-IDF 在这种形式下没有考虑文档长度对相关性的影响。

4.5 计算每个文档的 BM25 分数

假设 ,,

首先计算每个文档的长度归一化项:

  • 文档 A (长度 5): 

  • 文档 B (长度 8): 

  • 文档 C (长度 4): 

然后使用 BM25 公式计算每个词在文档中的贡献并求和:

文档 A (D_A, 软长度归一化项 ≈ 0.91):

  • 词“模型” (TF=1, IDF≈0.47): 

  • 词“算法” (TF=1, IDF≈0.47): 

  • 词“性能” (TF=1, IDF≈0.058): 

文档 B (D_B, 软长度归一化项 ≈ 1.31):

  • 词“模型” (TF=1, IDF≈0.47): 

  • 词“算法” (TF=0): 0

  • 词“性能” (TF=1, IDF≈0.058): 

文档 C (D_C, 软长度归一化项 ≈ 0.78):

  • 词“模型” (TF=0): 0

  • 词“算法” (TF=1, IDF≈0.47): 

  • 词“性能” (TF=1, IDF≈0.058): 

BM25 排名结果:

根据 BM25 分数,文档排名为:

文档 A (1.055) > 文档 C (0.609) > 文档 B (0.445)

4.6 和TF-IDF的对比分析:

通过这个新的例子,我们可以更清楚地看到 BM25 和 TF-IDF 在排名上的区别:

  • TF-IDF 排名: 文档 A (0.998) > 文档 B (0.528) = 文档 C (0.528)

  • BM25 排名: 文档 A (1.055) > 文档 C (0.609) > 文档 B (0.445)

尽管文档 B 和文档 C 都包含查询中的两个词,且这些词的 IDF 值相同,但 BM25 给予了文档 C 更高的分数,并将其排在了文档 B 的前面。这是因为:

文档长度归一化: 文档 C (长度 4) 比平均文档长度 (≈ 5.67) 短,BM25 的软长度归一化项 (≈ 0.78) 小于 1,这会提升文档 C 中词的贡献。文档 B (长度 8) 比平均文档长度长,软长度归一化项 (≈ 1.31) 大于 1,这会降低文档 B 中词的贡献。

这个例子有效地展示了 BM25 如何通过文档长度归一化来调整相关性分数,使其排名结果更符合“短文档如果包含查询词,可能更聚焦于该主题”的直觉,从而在信息检索中产生更精确的排名,这对于 RAG 系统召回高质量的相关文档至关重要。

5. BM25的优势

TF-IDF和BM25都是基于词频(TF)和逆文档频率(IDF)思想的文本检索算法,但在RAG场景中,BM25更加常用,因为它解决了TF-IDF在实际信息检索中的一些主要局限性,提供了更优越的排名效果。

BM25可以看作是TF-IDF的一个优化版本,它在TF的饱和度、文档长度归一化以及IDF的平滑处理上做得更好。

除了传统的基于关键词的检索方式( TF-IDF 和 BM25),现在很多 RAG 系统会使用基于向量的 dense 检索,但其实在一些实际场景中,BM25 依然非常有竞争力,特别是在以下几类任务中表现尤为出色:

  • 文本长度比较短、术语明确的任务(比如产品问答):关键词信号本身已经很强,不需要复杂的语义建模;
  • 数据集规模不算大、或者对 embedding 的训练不够充分的情况下,BM25 往往能提供更稳定的基础检索效果;
  • 作为 hybrid 检索的一部分:很多高性能的 RAG 系统其实是“稀疏 + 稠密”结合的—用 BM25 提供关键词召回的精度,再用向量召回补充语义覆盖,最后融合排序(re-ranking)提升整体检索效果。

所以 BM25 在某些任务中非常实用,它也可以作为构建复杂多阶段检索系统的第一步。

6. 使用LangChain实现BM25检索

LangChain 提供了一个内置的 BM25 实现。以下是使用 LangChain 实现 BM25 检索的基本步骤:

# 安装必要的库
# pip install jieba rank_bm25


from langchain.schema import Document
from langchain_community.retrievers import BM25Retriever

import jieba


def chinese_tokenizer(text):
    return list(jieba.cut(text))


# 示例文档内容
doc_contents = [
    "人工智能 技术 发展 迅速 机器学习 人工智能 重要 分支",
    "自然语言处理 人工智能 另一个 重要 分支 文本分析 自然语言处理 常见 应用",
    "技术 发展 带来 了 很多 新的 应用 领域",
    "这是一个关于自然语言处理的额外文档,包含更多文本分析的内容。"
]

# 将文档内容转换为 LangChain 的 Document 对象列表
documents = [Document(page_content=content) for content in doc_contents]

# 创建 BM25 检索器
# 默认情况下,k=4,即返回最相关的4个文档
# BM25Retriever默认分词器是针对英文的,需要传入中文分词器,避免分词错误导致检索排序不准
retriever = BM25Retriever.from_documents(documents, k=2, preprocess_func=chinese_tokenizer)

# 定义查询
query = "人工智能 技术 应用"

# 执行检索
relevant_docs = retriever.invoke(query)

# 打印检索结果
print(f"对于查询 '{query}', 检索到的相关文档:")
for i, doc in enumerate(relevant_docs):
    print(f"\n--- 文档 {i + 1} ---")
    print(doc.page_content)

总结

总的来说,BM25 是一个兼具简单性、可解释性和高效性的文本相关性排序算法。

在 RAG 系统的检索阶段,它能在不依赖训练的前提下,快速地从海量文档中找到与查询最匹配的候选段落,为后续的生成模型提供更加聚焦的上下文。

BM25 可以独立使用,也可以和 dense 检索联合构建更强的 hybrid 检索器。

53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费场景POC验证,效果验证后签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

添加专属顾问

回到顶部

加载中...

扫码咨询