当你在搜索框输入“精通 Python”,搜索引擎的使命是从几百万份网页里找出最匹配的那几份。这像极了 HR 从海量简历里筛选候选人。早期的方法(TF-IDF)只会数“Python“在简历里出现几次,出现多就排前面——简单但容易被耍:有人把关键词抄 30 遍,简历却空洞无物。后来,一位名叫 BM25 的”资深招聘官“登场了。他带来了一套更聪明的打分逻辑:关键词在简历里出现的次数要有”边际递减“(写 3 次和写 10 次差别不大);关键词在全行业简历中越稀缺越值钱;简历越长,关键词的”浓度“越可疑,分数要打折。这三条规则对应的数学表达,就是 BM25 的概率排序公式。而 k1 和 b 正是这位招聘官手里两个可旋转的”经验旋钮“。本文将用”招聘官筛选简历”这条线索,带你彻底看懂 BM25 的原理、参数调优与工程实践。
对搜索工程师而言,BM25 是信息检索的“基本功”——无论做 Elasticsearch、Lucene 还是向量检索混合系统,理解 k1/b 的物理含义,才能让召回排序效果稳步提升。
可视化演示
通过交互滑块实时观察k1词频饱和参数和b长度归一化参数对BM25打分的影响,理解概率排序的核心机制。
本节配有交互动效(进入视口后自动加载,约 3KB)。
词频饱和曲线 TF 增大时分值趋向饱和上限 k1+1 k1 越小饱和越快,高频词惩罚越强 f(tf) = tf·(k1+1) / (tf+k1) 拖动 k1 滑块观察曲线形态变化
概率排序起源
最早的招聘官(TF-IDF)非常朴素:数一数“Python“在简历里出现几次,出现多就排前面。但他很快被现实打脸——有人把”精通 Python”复制粘贴二十遍,照样靠前,可内容空洞。更麻烦的是,简历越长,关键词出现的绝对次数天然越多,这对篇幅短的优秀简历极不公平。数词频的老办法,既防不住堆砌,也做不到跨篇幅公平。
于是搜索学者引入了概率检索模型。它的核心思想脱胎于决策论:与其机械地数词频,不如估算“这份简历在多大概率上与招聘需求相关”。文档与查询的相关性被建模成一个二分类问题——相关或不相关,而排序依据就是“相关的概率是否压倒不相关的概率”。BM25 正是这一思想在 20 世纪 90 年代由 Robertson 和 Walker 在 Okapi 系统中落地实现的算法,它把概率排序原则化成了可分解的加性打分公式。
新一代招聘官 BM25 不再死记词频次数,而是为每个词、每份简历计算“相关概率的贡献分”。从这篇起,数词频的效率工具退休了,概率论正式上岗。这也是搜索工程师理解一切现代检索模型的起点。
- 相关性标记$R=1$ 表示文档与查询相关,$R=0$ 表示不相关——“这份简历是否匹配这个岗位”是判断的出发点。
- 后验概率$P(R=1|d,q)$ 是在已知查询 $q$ 和文档 $d$ 的条件下,文档相关的概率——招聘官看着简历和需求,心里判断“匹配”的把握程度。
- 排序准则当相关概率大于不相关概率时,文档排在前面——把握大的候选人优先进入初筛名单。
- 对数比值BM25 进一步取 $\log \frac{P(R=1|d,q)}{P(R=0|d,q)}$,把连乘的概率关系变成连加的得分,方便逐词分解。
BM25核心公式
BM25 这位资深招聘官手里有一张细细打磨过的打分表,上面有三项加在一起才给出最终分数:关键词在全行业简历中的稀缺程度、关键词在本简历中命中的次数(但设置了上限)、以及简历篇幅带来的稀释修正。这三项分别对应 IDF、词频饱和项和文档长度归一化。
完整打分公式不长,但每一项都对应一个招聘直觉。假设查询 $Q$ 包含 $n$ 个词,文档 $D$ 的得分是每个查询词贡献的累加:
公式里的三块各自负责一件事:$IDF(q_i)$ 衡量词有多稀罕,分子分母中的 $tf_i$ 负责“出现次数越多分越高但涨得越慢”,最后的 $\frac{|D|}{avdl}$ 配合 $b$ 完成长度归一化。
这张打分表的设计哲学是:稀缺词给高分,重复词设上限,长文摊薄浓度。招聘官明白,一份简历的价值不在于关键词喊了多少遍,而在于稀缺技能的点名率、关键经验的出现密度,以及整体篇幅是否注水。这个公式就是 BM25 在工业界屹立二十余年的基石。
- 对查询词求和$\sum_{i=1}^{n}$ 把查询中每个词的贡献累加——招聘官把"Python"“三年经验”“后端”几个加分项逐项计分再汇总。
- IDF权重$IDF(q_i)=\ln\left(1+\frac{N-df+0.5}{df+0.5}\right)$,$N$ 是简历总数,$df$ 是包含该词的简历数——写“精通”的有 900 份,写“量子计算”的只有 2 份,后者含金量高得多。
- 词频饱和项$\frac{tf_i\cdot(k_1+1)}{tf_i+k_1}$ 是词频贡献,$k_1$ 控制饱和速度——提 3 次"Python"有明显加分,提 30 次和提 90 次几乎没有差别。
- 长度归一化$\frac{|D|}{avdl}$ 是文档相对平均长度的比例,$b$ 决定惩罚力度——两页简历里出现 10 次"Python"和半页简历里出现 10 次,含金量完全不同。
k1参数调优
招聘官很快注意到一个现象:候选人把“团队协作”写在自我评价里一次,他记住了;写在六个项目描述里各一次、外加技能栏两次,他并没有觉得这人更厉害八倍。k1 就是用来刻画这种“边际递减效应”的旋钮——它决定词频从 1 涨到 10 的加分斜率有多陡,以及从 30 涨到 100 时得分还剩下多少增长空间。
从数学上看,词频饱和项是一个分子分母都含 $tf$ 的分式。$k_1$ 取值通常在 $[0,3]$,默认 $1.2$。$k_1$ 越大,词频越难饱和,意味着需要更多重复才能达到分数平台;$k_1$ 越小,词频很快见顶。极端情况 $k_1=0$ 时,整个分式恒等于 1,词频彻底不参与打分,剩下纯粹的 IDF 排序。
调 k1 就像调整招聘官对“车轱辘话”的耐心:耐心大(k1 大),候选人多提几次关键词还能继续加分;耐心小(k1 小),重复两三遍就腻了。实际业务里,如果搜索结果总被长段落中的高频词霸占,就应该调低 k1;如果发现关键词只出现一次和出现三次没区别,那就调高 k1。
- 零词频得零分$tf=0$ 时分子为 $0$,整个式子为 $0$——简历里压根没提这个技能,这项不得分。
- 饱和上限$tf \to \infty$ 时 $TF_{\text{sat}} \to k_1+1$——无论重复多少遍,单项贡献最高也就到 $k_1+1$。
- 半饱和位置当 $tf=k_1$ 时,$TF_{\text{sat}}=\frac{k_1+1}{2}$,正好是峰值的一半——k1 数值越大,达到半饱所需的重复次数越多。
- 退化情形$k_1=0$ 时 $TF_{\text{sat}}=1$ 恒成立——词频完全失效,退化成只按稀缺度排序。
b参数调优
同样的内容,写成一页纸的简历和写成十页纸的论文,招聘官对后者的“关键词浓度”必然打问号:不是说你写得多的词不重要,而是篇幅越长,词的密度越稀。b 就是调节“因为篇幅长而扣分”力度的旋钮,它控制长度归一化的强度,范围 $[0,1]$,默认 $0.75$。
长度归一化的作用点在分母的 $B$ 项上。$B$ 由两部分混合而成:常数 $1$ 和文档相对长度 $\frac{|D|}{avdl}$。$b=0$ 时 $B$ 恒等于 1,长度完全不参与计算;$b=1$ 时 $B$ 完全等于相对长度,长文档的词频贡献被按比例压缩。默认 0.75 的含义是:大多数语料里长度确实会稀释信息,但长文档往往信息量也更大,所以要留出 25% 的容忍度。
调 b 的实战经验:如果语料里都是统一格式的短新闻标题,长度差异不大,b 设 0.5 甚至更低都无所谓;如果文档既有几十字的商品名又有几千字的说明书,长度方差巨大,b 就应该往 0.9 以上调。招聘官手里这个“篇幅偏见旋钮”,拧多大取决于你所在的行业简历长度有多参差。
- 平均长度基准$avdl$ 是语料库中全部文档的平均词数——简历库的平均篇幅就是一个比较基准。
- 相对长度$\frac{|D|}{avdl}>1$ 代表比平均文档长,小于 $1$ 代表比平均短——某份简历是平均篇幅的 1.5 倍,这项就是 1.5。
- 加权混合$(1-b)+b\cdot\frac{|D|}{avdl}$ 在常数 1 和相对长度之间做线性混合——b 越大,相对长度的话语权越大。
- 极端行为$b=0$ 时 $B=1$ 长度失效;$b=1$ 时 $B=\frac{|D|}{avdl}$ 完全按长度比例惩罚。
工程部署实践
打分表设计好了,招聘系统要上线了。搜索引擎里最常见的落地载体是 Elasticsearch,它的默认相似度算法就是 BM25,并且允许直接配置 $k_1$ 和 $b$。但把参数的调节落到真实业务,不是拍脑袋定两个数那么简单,而是一套流程:收集查询日志 → 人工标注相关性 → 网格搜索参数 → 离线评估 → 在线 A/B 验证。
离线评估最常用的指标是 NDCG(归一化折损累积增益)。它衡量“系统给出的排序有多接近理想排序”。做法很直白:先按人工标注的相关性等级算出一个理想排序的总分,再用系统实际排序总分除以理想总分,得到一个 $[0,1]$ 的比值。比值越接近 1,说明系统排得越接近专家心目中的完美顺序。配合网格搜索,就能在验证集上选出一组最优的 $k_1$ 和 $b$。
招聘官的打分系统上线后,不是一劳永逸。每次语料更新、查询分布变化,都要重跑一遍评估:先把 k1、b 放到网格里穷举,再用 NDCG 挑最优组合,最后小流量 A/B 确认不伤用户体验。这个过程听起来繁琐,却正是搜索工程师日常工作中让“老招聘官”持续进化、稳定发挥的关键。
- 相关等级$rel_i$ 是第 $i$ 位结果的相关性打分(通常人工标注为 0~3)——招聘官给每份简历打“匹配度分”。
- 位置折扣$\log_2(i+1)$ 让排名越靠后的结果得分折扣越大——第 3 名和第 8 名即使匹配度相同,用户看到第 8 名的可能性也小得多。
- 累计增益$DCG@k$ 是按位置折扣后累计的前 $k$ 项得分——系统给到用户的前 10 份简历的总效用。
- 归一化比值$NDCG@k$ 是实际排序与理想排序的比值——理想排序 $IDCG$ 由完美排序计算而来,比值越接近 1 越好。
与稠密检索对比
公司里来了位 AI 招聘官(稠密检索)。他不用看关键词,直接“理解”语义——候选人写“我负责过数据管道建设”,他能意识到这跟“数据工程”相关。但这位 AI 也不是万能的:问他“YOLOv8 源码里的 loss.py”,他可能答非所问,因为他没见过这个词。这跟 BM25 恰好相反:老招聘官严格按关键词匹配,遇到生僻专有名词反而精确无比。
两者是两种不同的表示方式。BM25 把文档表示为稀疏的词汇向量,每个维度是一个词,非零值就是该词的词频贡献;稠密检索则用神经网络把文档和查询编码成 128~768 维的稠密向量,用余弦相似度打分。前者可解释、零训练成本、冷启动即用;后者能处理同义改写,但需要训练数据、算力开销大、可解释性差。工业界的主流做法不是二选一,而是让两位招聘官一起打分:
老招聘官胜在精准与透明,AI 招聘官赢在懂得变通。最终的招聘系统里,两位各自打分、加权汇总:遇到型号、代码、人名等专有名词,BM25 把住底线;遇到口语化、同义改写,稠密检索兜住语义。理解了 BM25,你就理解了混合检索里那一半“确定性”从何而来。
- 归一化$\hat{s}_{\text{BM25}}$ 和 $\hat{s}_{\text{dense}}$ 是经过 min-max 或 z-score 归一化后的分数——两位招聘官的打分先被拉平到同一把尺子上。
- 权重融合$\alpha \in [0,1]$ 是 BM25 的权重,$1-\alpha$ 是稠密检索的权重——公司决定“老招聘官意见占几成”。
- 加权求和总得分是两者加权和——最终名单综合了关键词匹配和语义理解两路意见。
- 调优目标$\alpha$ 通过网格搜索在验证集上以 NDCG 为目标确定——反复试不同权重,挑让排序质量最高的那个组合。
AI 应用场景
电商商品搜索排序
阶段:召回与排序阶段
解决的问题:用户在电商平台搜“无线蓝牙耳机”时,商品标题长短差异极大。有的标题老老实实写 10 个字,有的标题堆满“官方正品 超长续航 蓝牙5.3 入耳式 降噪 防水…”长达 60 字。如果只按词频排序,长标题商品几乎垄断前排,短标题优质商品被淹没。BM25 的 b 参数能自动惩罚过长标题;k1 参数则防止同义词堆砌刷分。
具体案例:某电商平台对 500 万商品标题建立索引,初始使用默认 k1=1.2、b=0.75,搜索“蓝牙耳机”时 Top10 里 7 个是超长堆词标题。将 b 调高到 0.9 后,长标题商品的过度优势被摊薄,短标题的知名品牌商品重新回到前排,点击率提升 18%。
企业知识库部署与调优
阶段:索引构建与参数调优阶段
解决的问题:企业内部知识库文档长度方差极大:规章制度条目往往不足 50 词,项目复盘报告动辄 5000 词。直接用默认 BM25 参数,长文档凭借词频天然碾压短文档。需要通过离线标注 + NDCG 评估,针对语料长度分布定制 k1 和 b。
具体案例:某律所检索系统收录 20 万篇裁判文书与法条,法条短(约 100 词)、判决书长(约 3000 词)。工程师采集 2000 条真实查询并人工标注相关性后,用网格搜索得到最优参数 k1=1.5、b=0.95。上线后检索“民间借贷利率上限”等查询,NDCG@10 从 0.58 提升到 0.71,法条命中率显著提高。
混合检索搭建智能问答
阶段:召回融合阶段
解决的问题:智能客服系统中,用户问题口语化严重(“我买的东西一直不到怎么办”),纯 BM25 匹配不到知识库里的标准问法(“物流延迟处理流程”);而纯稠密检索在遇到“订单号 ORDER202412345”这类精确专有信息时又容易出错。混合检索把 BM25 和向量召回按权重融合,各取所长。
具体案例:某电商客服机器人将 BM25 与 BERT 向量召回融合,α 初始设为 0.4。离线评测发现专有名词类问题的 NDGG 在 α=0.6 时最佳,于是按问题类型动态调节:含订单号/型号走 BM25 权重高,口语化问题走向量权重高。最终整体问题解决率提升 25%。
Python 演示
import mathfrom collections import Counter class MiniBM25: def __init__(self, docs, k1=1.2, b=0.75): self.k1 = k1 self.b = b self.docs = docs self.doc_len = [len(d.split()) for d in docs] self.avgdl = sum(self.doc_len) / len(docs) self.df = Counter() for d in docs: for w in set(d.split()): self.df[w] += 1 self.N = len(docs) def idf(self, term): return math.log(1 + (self.N - self.df[term] + 0.5) / (self.df[term] + 0.5)) def score(self, query, doc_idx): doc_words = self.docs[doc_idx].split() tf_map = Counter(doc_words) dl = self.doc_len[doc_idx] total = 0.0 for t in query.split(): tf = tf_map.get(t, 0) if tf == 0: continue b_term = (1 - self.b) + self.b * dl / self.avgdl denom = tf + self.k1 * b_term total += self.idf(t) * (tf * (self.k1 + 1)) / denom return total def search(self, query, top_k=3): scores = [(i, self.score(query, i)) for i in range(len(self.docs))] return sorted(scores, key=lambda x: x[1], reverse=True)[:top_k] def print_result(results, docs): for rank, (idx, score) in enumerate(results, start=1): label = "短" if docs[idx].split().__len__() < 10 else "长" print(f"第{rank}名: [文档{idx}|{label}] 得分={score:.4f} | {docs[idx][:36]}...") if __name__ == "__main__": docs = [ "Python backend API with Python Flask", "Python developer uses Python for data", "API design best practices for backend", "Python Python Python backend API Python", ] bm = MiniBM25(docs, k1=1.2, b=0.75) query = "Python backend API" print("默认参数 k1=1.2, b=0.75:") print_result(bm.search(query), docs) print("\n调高 b 到 1.0 (强长度惩罚):") bm1 = MiniBM25(docs, k1=1.2, b=1.0) print_result(bm1.search(query), docs)
self.df = Counter()统计每个词出现在多少篇文档中,这是 IDF 计算的基础,对应“关键词在简历库里有多稀罕”。return math.log(1 + (self.N - self.df[term] + 0.5) / (self.df[term] + 0.5))用平滑的对数形式计算 IDF,避免分母为零,也保证稀有词权重不爆炸。b_term = (1 - self.b) + self.b * dl / self.avgdl这就是公式里的 B 项:文档相对长度的加权混合,是 b 参数发挥作用的唯一位置。denom = tf + self.k1 * b_term分母同时包含词频和长度修正,k1 在这里与 b_term 相乘,两个旋钮由此耦合。total += self.idf(t) * (tf * (self.k1 + 1)) / denom把 IDF 与饱和词频项相乘并累加,得到文档对查询的总分。scores = [(i, self.score(query, i)) for i in range(len(self.docs))]遍历所有文档逐一打分,再按分数降序返回前 top_k 个结果。
常见误区
误区“k1 控制词频加分,那我把它调到 5,关键词写得多就能拿更高分,排序效果肯定更好。”
正解k1 过大会让词频几乎不饱和,“写 5 次”和“写 50 次”的分数差距被无限放大,长文档里反复出现的关键词会堆出离谱高分,反而淹没了真正稀缺词的贡献。BM25 防堆砌的核心恰恰是边际递减,k1 默认 1.2 时,词频到 6 次左右就达到峰值一半,之后增长非常平缓。k1 越大,这个“半饱点”越靠后,作弊式堆词的空间就越大。
为何常见:人的直觉是“重复多就该加分多”,但忽略了 BM25 的饱和设计初衷——防止关键词堆砌。调参时没有配合 NDCG 等离线指标验证,单凭“分数变大了”误判为效果变好。
误区“官方给 b 默认 0.75,那就是为所有场景调好的,直接抄作业就行。”
正解b 的最优值与语料长度分布强相关。如果语料里文档长度高度一致(如新闻标题),b 设 0.75 与 0.5 差别不大;如果长度方差极大(如专利全文 vs 摘要),默认 0.75 可能惩罚不足或过重。正确做法是拿一批真实查询和人工标注,在验证集上用网格搜索试探 b 在 0.4~1.0 之间的表现,而不是幻想有一套万能参数。
为何常见:默认值来自 TREC 等标准评测集,标准集多为长度适中的文本,跟真实业务语料的长度分布差异巨大。“默认就是最优”的思维惯性让许多工程师跳过了调优步骤。
误区“IDF 不是写在词典里的值吗?就像'Python'的 IDF 固定是 2.5,跟语料没关系。”
正解IDF 完全由语料决定:$IDF=\ln(1+\frac{N-df+0.5}{df+0.5})$,其中 $N$ 是文档总数,$df$ 是含该词的文档数。新增一批文档后,$N$ 和 $df$ 都会变化,IDF 必须重建索引时重算。在增量索引的 Elasticsearch 集群里,同一词的 IDF 在不同索引分片间可能略有差异,这正说明它不是词的“先天属性”。
为何常见:很多检索工具把 IDF 缓存成静态表,加上“逆文档频率”听起来像词的固有统计量,让人觉得它是类似词性的稳定属性。实际上它与语料规模、领域分布紧密绑定。
误区“现在都上深度学习向量检索了,BM25 这种数词频的算法是恐龙,该被淘汰了。”
正解稠密检索在口语化改写、同义词匹配上有优势,但在精确专有名词(产品型号、订单号、人名、代码标识符)、冷启动无训练数据、需要解释“为什么召回这篇”的场景下,BM25 依然明显占优。实际工业系统普遍采用混合检索:BM25 保证精确召回的下限,向量检索拉高语义召回的上限。把 BM25 从系统里移除,很多线上搜索的准确率会立刻下跌。
为何常见:媒体和厂商过度渲染深度学习检索的效果,让人误以为更强。忽视了 BM25 零成本、高可解释、稳定可靠的工程优势,以及混合检索才是主流的事实。
面试题
Q1. BM25 中的 k1 参数主要用于控制什么?
- A.词频饱和的速度← 正确答案
- B.文档长度惩罚强度
- C.词的稀缺度加权
- D.查询扩展的力度
答案:A。k1 控制词频从 1 涨到 N 时分数增长的快慢,k1 越大饱和越慢。长度惩罚由 b 控制,稀缺度由 IDF 决定。正如招聘官对“重复提关键词”的耐心程度由 k1 刻画。
Q2. 当 b=0 时,BM25 的长度归一化行为是什么?
- A.完全不进行长度惩罚← 正确答案
- B.长度惩罚达到最强
- C.词频得分趋于饱和
- D.IDF 权重完全失效
答案:A。b=0 时 B=(1-0)+0×( |D|/avdl )=1,长度项消失,长短文档在长度维度上一视同仁。相当于招聘官完全不因简历篇幅打折。
Q3. BM25 相对于 TF-IDF 的改进包括哪些方面?
- A.为词频设定饱和度← 正确答案
- B.引入文档长度归一化← 正确答案
- C.使用语义向量编码
- D.基于概率排序设计← 正确答案
答案:ABD。BM25 用饱和函数限制词频无限增长、用 avdl 归一化文档长度,并从概率检索模型推导而非启发式定义。语义向量编码是稠密检索的做法,不属于 BM25。
Q4. 当 k1=0 时,BM25 的打分会退化成什么形式?
- A.只按 IDF 加权排序← 正确答案
- B.等价于经典 TF-IDF
- C.变成布尔检索模型
- D.完全失去排序能力
答案:A。k1=0 时饱和项 (k1+1)tf/(tf+k1) 恒等于 1,词频不参与计算,最终分数只剩 IDF 累加。就像招聘官完全不看关键词出现次数,只看“这张简历里写了多稀缺的技能”。
Q5. BM25 常用的默认参数值是多少?
- A.k1=1.2, b=0.75← 正确答案
- B.k1=0.75, b=1.2
- C.k1=2.0, b=0.5
- D.k1=1.5, b=1.0
答案:A。BM25 的默认参数通常取 k1=1.2、b=0.75,这是 Robertson 在 TREC 评测中总结的经验起点。实际业务需要围绕语料调优,但面试和框架默认值都以这对参数为准。
Q6. 某语料中文档长度从 20 词到 2000 词不等,最适合采用哪种参数策略?
- A.增大 k1 使词频更饱和
- B.调高 b 值增强长度惩罚← 正确答案
- C.调低 b 值降低长度影响
- D.将 k1 设为 0 禁用词频
答案:B。长度方差极大时,长文档天然词频高,若不加强长度惩罚会垄断排名。调高 b 使 B 项更接近 |D|/avdl,长文档的词频贡献被显著压缩。k1 与长度问题无关,禁用词频更是矫枉过正。
Q7. BM25 的 IDF 使用 ln(1+(N-df+0.5)/(df+0.5)) 形式的核心目的是?
- A.平滑处理避免除零与负值← 正确答案
- B.加速计算提高查询性能
- C.统一量纲使与词频可比
- D.实现简单便于部署调优
答案:A。+0.5 的平滑项防止 df 等于 N 时分子为零导致取对数出现负无穷或除零,ln(1+x) 保证结果恒非负,同时让集合外罕见词也不至于无穷大。这保证了打分的数值稳定性。
Q8. 构建 BM25 与稠密检索的混合排序时,下列做法合理的有?
- A.两路分数归一化后加权融合← 正确答案
- B.α 权重通过离线评测确定← 正确答案
- C.直接求和无须任何归一化
- D.融合后按总分排序返回← 正确答案
答案:ABD。BM25 分数与余弦相似度量纲完全不同,直接求和会让某一方主导,必须先归一化。α 应基于验证集上的 NDCG 等指标网格搜索确定,最后用融合总分排序。C 省略归一化是常见错误。
Q9. BM25 属于哪一类信息检索模型?
- A.概率检索模型← 正确答案
- B.布尔逻辑模型
- C.向量空间模型
- D.统计语言模型
答案:A。BM25 源自 Robertson 的概率检索框架,核心是估计文档与查询相关的概率并据此排序。向量空间模型以余弦相似度为代表,语言模型走生成概率路线,都与 BM25 不同源。
Q10. 在 Elasticsearch 中调整 BM25 的 k1 和 b,应使用哪个配置?
- A.索引的 similarity 配置← 正确答案
- B.分词的 tokenizer 配置
- C.查询的 filter 配置
- D.文本的 analyzer 配置
答案:A。ES 中 BM25 属于 similarity(相似度)模块,通过 "similarity": {"bm25": {"k1": 1.2, "b": 0.75}} 配置。tokenizer、analyzer 处理分词与文本分析,filter 用于结果过滤,与打分参数无关。