首页/AI/AI 应用速查/BM25 关键词检索基线

BM25 关键词检索基线

BM25 是几十年验证过的词频检索算法:按词频与逆文档频率打分,配 k1/b 参数。中文需先分词(ik、jieba 等),是最便宜也最难被完全替代的检索基线。

AI 应用速查AI更新于 2026-10-13

BM25 是什么

BM25 是经过几十年验证的词频检索算法,打分由三部分构成:词频饱和、文档长度归一与逆文档频率。它有两个可调参数,k1 控制词频增长的饱和程度,b 控制长文档的惩罚力度。对错误码、型号、版本号、专有名词这类精确匹配查询,它至今仍然可靠,而且延迟低、打分可解释、不需要训练。中文场景的成败几乎全在分词上:不配分词器就退化成单字匹配,效果会差到让人误判关键词检索没有价值。

基本信息

打分构成词频饱和项加文档长度归一加逆文档频率
核心参数k1 控制词频饱和,b 控制长度惩罚,常见取值 1.2 与 0.75 附近
中文处理必须配分词器,如 Elasticsearch 的 ik、或 jieba 等分词库
常见实现Elasticsearch 与 OpenSearch、Lucene、PostgreSQL 全文检索、SQLite FTS5
主要优势可解释、低延迟、无训练成本、精确匹配能力强
主要局限不理解同义改写与语义近似,换个说法就搜不到

典型使用场景

  • 作为向量检索的对照基线:先跑通 BM25,再判断引入向量到底带来多少增益
  • 精确术语查询:错误码、设备型号、接口路径、版本号等高区分度内容
  • 混合检索的一路:与向量召回并列,用融合算法合并两路结果
  • 冷启动阶段内容少:没有足够数据评估 embedding 效果时先用关键词顶住
  • 需要可解释打分的场景:能说清某条结果为什么排前面,便于审计与调参

Elasticsearch 查询与调试

Elasticsearch 查询与调试
{
  "query": {
    "match": {
      "content": { "query": "SSE 断线重连", "operator": "or" }
    }
  },
  "size": 20,
  "_source": ["doc_id", "title"]
}

查看分词结果

查看分词结果
# 中文索引必须在 mapping 中指定分词器,否则默认按单字切分
curl -s 'localhost:9200/kb/_analyze' -H 'Content-Type: application/json' \
  -d '{"analyzer": "ik_max_word", "text": "SSE 断线重连"}'
# 检查点:确认关键词被切成有意义的词,而不是一个字一个词
curl -s 'localhost:9200/kb/_search?explain=true' -d @query.json  # 看打分构成,定位异常排序
# 分数只在本查询内可比,跨查询或跨索引比较没有意义

常见误区与处理

情形表现处理
未配中文分词器检索退化成单字匹配,噪声大指定 ik 或等价分词器并重建索引
k1 与 b 用默认值不调长文档或短文档排序失衡按语料长度分布实测调参
与向量分数直接比较阈值完全失真用排名融合,不要混比原始分数
同义词未配置换个说法搜不到维护同义词表并定期从搜索日志补充
只依赖关键词检索语义近似问题漏检严重与向量召回并行,按问题类型路由
BM25 分数是相对值,只在本查询的结果集内可比:把它和余弦相似度放在同一个阈值下判断,或者拿两次查询的分数绝对值比较,都会得出错误结论。
先跑通 BM25 基线再上向量是很划算的顺序:如果关键词检索已经满足大部分真实问题,向量化带来的切分、embedding 与索引维护成本可以先不引入。

易错点

  • 中文不配分词器:索引按单字切分,检索结果充满噪声,被误判为算法本身不行
  • 把 BM25 分数与向量余弦分数直接比较或统一设阈值:两种打分口径完全不同,阈值彻底失真
  • 换分词器后不重建索引:查询侧分词已变而索引仍是旧切分,命中率异常且难定位
  • 只维护正文不维护同义词与别名:用户用产品别名、缩写搜索时几乎搜不到
  • 把 BM25 当成已经过时的方案直接弃用:在精确匹配与可解释性上它仍是难以替代的一路

数据来源与参考

  • Robertson & Zaragoza, BM25 综述;Elasticsearch 官方文档

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌