问题出现得很突然,日志倒是留得挺全。混合检索里 BM25 那一路召回总是 0 条,向量那一路正常。索引是用 jieba 分词后灌进去的,查询串是「发票怎么开」,服务端日志里 term 一个都没命中。

刚开始盯着「BM25 字段没指定 analyzer,按标准分词器切中文」,折腾了半个多小时,排掉了。

原因不止一个,得分开看。索引和查询用了不同的分词器配置。也可能是停用词表把查询里的实词也一起滤掉了。

少数情况下是查询串没走同一套预处理,全半角和大小写不一致。

动手时先对比索引与查询的分词结果

python -c "import jieba;print(list(jieba.cut('发票怎么开')))"

给字段显式指定中文 analyzer 后重建

curl -X PUT http://localhost:9200/kb -H 'Content-Type: application/json' -d @mapping.json

再往下用 explain 看 term 的命中情况

curl 'http://localhost:9200/kb/_search?explain=true' -H 'Content-Type: application/json' -d '{"query":{"match":{"text":"发票怎么开"}}}'

剩下的就是把停用词表里的实词移除后重跑召回

python recall_probe.py --query 发票怎么开 --topk 10

怎么算真的好了,看的是同一批现象。同一查询 BM25 能召回十条以上,分数随相关度递减,混合后的前三命中正确文档。

补一句。中文 BM25 出问题九成在分词和 analyzer,先看 explain 输出里有没有切出实词,再谈权重。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。

作者 9823189