BM25全文检索

概述

BM25是一种经典的全文检索排序算法,常用于搜索引擎、RAG和文档检索。它的核心目标是:根据用户查询中的关键词,判断哪些文档最相关,并给这些文档打分排序。

你可以把BM25理解成,比简单关键词匹配更聪明的TF-IDF( Term Frequency-Inverse Document Frequency , 词频-逆文档频率 )。

比如用户搜索:

latex 复制代码
GitNexus MCP Stdio

系统里有3篇文档:

latex 复制代码
文档A:GitNexus MCP Server使用Stdio通信
文档B:MCP支持Stdio和SSE
文档C:GitNexus代码索引架构

BM25会分别计算这3篇文档和查询的相关性分数:

latex 复制代码
文档A:8.7
文档B:6.2
文档C:2.1

然后按分数排序返回:

latex 复制代码
文档A
文档B
文档C

BM25考虑3件事

关键词出现次数

比如搜索:

latex 复制代码
MCP Stdio

如果一篇文章里频繁出现:

latex 复制代码
MCP
Stdio

那么它通常会获得更高分。

但BM25不会认为出现越多越无限重要。

例如:

latex 复制代码
出现1次 → 提升明显
出现3次 → 继续提升
出现20次 → 提升已经很有限

这叫**词频饱和**。因为一个词出现100次,并不意味着相关性就是出现10次的10倍。


关键词的稀有程度

假设整个文档库里:

latex 复制代码
"the"出现100万次
"GitNexus"出现100次

那么搜索:

latex 复制代码
GitNexus

这个词的信息量明显更大。所以BM25会让稀有词获得更高权重。

这部分本质上就是IDF(Inverse Document Frequency, 逆文档频率),也就是说:一个词在整个语料库里越少见,它越有区分度。

比如:

latex 复制代码
"server" → 权重较低
"GitNexus" → 权重较高
"CompatibleStdioServerTransport" → 权重更高

文档长度

假设:

latex 复制代码
文档A:100字,其中MCP出现5次
文档B:10000字,其中MCP出现5次

虽然出现次数一样,但显然文档A更可能专门讨论MCP。所以BM25会做文档长度归一化。也就是说:短文档中关键词密集通常比长文档中偶尔出现关键词得分更高。

BM25公式

给定查询Q和文档D主要,经典形式可以写成:

$ score(D,Q)=\sum_{q_i\in Q}

IDF(q_i)

\cdot

\frac{f(q_i,D)(k_1+1)}

{f(q_i,D)+k_1(1-b+b\frac{|D|}{avgdl})} $

看几个变量:

  • f(q_i,D) 表示某个关键词在文档中出现几次。
  • IDF(q_i) 表示这个词有多稀有
  • \|D\| 表示当前文档长度
  • avgdl 表示所有文档的平均长度。
  • k1控制词频饱和程度, 常见k1 ≈ 1.2~2.0
  • b控制文档长度归一化程度,b ≈ 0.75
相关推荐
默_笙1 天前
🍙 给每个请求过安检:FastAPI 是怎么把校验写进类型注解的
python
小羊没烦恼!1 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
qq_426003961 天前
启动playwright录制codegen生成自动化测试脚本
python·自动化
虎头金猫1 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
长沙三为智能科技1 天前
家政小程序开发从0到上线:五阶段交付流程与验收清单
python
伞伞悦读1 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
只睡四小时1 天前
Canvas 弹道联机实战:700 行 + 固定时间步长
python·websocket·html5·游戏开发·canvas
C语言小火车1 天前
C/C++ 为什么需要编译器?
开发语言·c++
奇思妙想聪明勤奋的小羊1 天前
DeepAgents第5章:子Agent 与上下文隔离—让 Agent学会委派
人工智能·python·学习·语言模型
lpfasd1231 天前
2026年第38周GitHub趋势周报
python·科技·github