首页/AI/RAG 与向量库速查/中文分词与 BM25 效果
Embedding 与检索50 条

中文分词与 BM25 效果

中文 BM25 效果强依赖分词:IK(ik_max_word / ik_smart)与 jieba 等粒度不同、召回不同;产品型号与专名建议加入自定义词典保护。

RAG 与向量库速查AI更新于 2026-10-13

中文分词与 BM25

BM25 是词项匹配模型:文档与查询被切成词项后按词频、文档频率与文档长度打分。中文没有天然空格,分词粒度直接决定召回——切得太碎则长词片段匹配不上,切得太粗则短语命中被漏掉。Elasticsearch 常用的 IK 插件提供两套分析器:ik_max_word 在索引时做细粒度切分以提高召回,ik_smart 在查询时做粗粒度切分以减少噪声,这是常见的组合。产品型号、品牌与缩写必须加入自定义词典,否则会被切坏,检索永远命不中。

基本信息

框架Elasticsearch / OpenSearch + analysis-ik 插件
分析器ik_max_word(细粒度)、ik_smart(粗粒度)
常用组合索引用 ik_max_word,查询用 ik_smart
打分参数BM25 默认 k1=1.2、b=0.75
词典自定义词典扩展专名;更新后需重建索引

典型使用场景

  • 中文知识库的关键词一路:与向量检索组成混合检索,兜住专名与型号
  • 技术文档检索:产品名、版本号、命令名必须原样命中
  • 多语言语料:按语种配置不同分析器,避免用英文分析器切中文
  • 召回骤降排查:先看查询词被切成什么,再判断是词典问题还是分析器问题
  • 接入新词表:上线前在新词上做正反向用例验证,确认索引与查询两侧行为一致

字段映射与分析器

字段映射与分析器
PUT kb_chunks
{
  "settings": { "analysis": { "analyzer": { "ik_smart_q": { "type": "custom",
      "tokenizer": "ik_smart" } } } },
  "mappings": { "properties": {
    "content": { "type": "text",
      "analyzer": "ik_max_word",          // 索引:细粒度提高召回
      "search_analyzer": "ik_smart" } } }   // 查询:粗粒度减少噪声
}

验证分词结果

验证分词结果
GET _analyze
{ "analyzer": "ik_max_word", "text": "ruijie RG-S2910 交换机" }
# 输出 tokens 列表:确认型号未被切碎
# 若被切碎,把型号加入自定义词典后重建索引

分析器选择的影响

配置召回精确度适用
索引/查询都用 ik_max_word高偏低短查询、术语不规范的语料
索引 max + 查询 smart较高较高通用中文检索,推荐起点
索引/查询都用 ik_smart偏低高查询词本身就是完整术语
未装插件用标准分析器极低不可用仅英文或数字场景
自定义词典更新后,新词只对新写入的文档生效:倒排索引里已经切碎的文档必须重建(或 reindex)才能被命中,这一点常被忽略。

易错点

  • 索引与检索都用一个粗粒度分词器,长词片段漏匹配,专名检索不到
  • 词典更新后未重建索引,新词在倒排里查不到,测试环境还以为是缓存问题
  • 用英文分析器处理中文,文档被逐字切开,BM25 分数失去意义
  • 自定义词典塞进过多通用词,把本应切分的短语变成整体词项,查询侧反而失配
  • 只评估向量检索的效果就上线,关键词一路没有评测,混合检索里那一路长期无效

数据来源与参考

  • IK Analysis 插件项目文档(github.com/infinilabs/analysis-ik)
  • Elasticsearch 官方文档(Text analysis)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌