跳到正文

查询文档相关性怎么算?

语义匹配、关键词匹配、BERT 模型实现对比

原题:在搜索引擎的排序系统中,如何计算查询与文档之间的相关性得分?请说明基于语义匹配、关键词匹配、深度学习模型(如BERT)等方法的实现方式。

RAG基础 · OPPO真题

回答与解析

搜索引擎的相关性计算经历了从关键词匹配→语义匹配→深度语义模型的演进,实际系统通常是多阶段级联。

一、关键词匹配:经典但有效

BM25 是工业界标配,核心思想:

  • 词频饱和度:TF 增长边际递减(用 k1 控制)
  • 文档长度归一化:避免长文档占优(用 b 控制)
  • IDF 惩罚常见词
score = Σ IDF(q_i) · [f(q_i,D)·(k1+1)] / [f(q_i,D) + k1·(1-b+b·|D|/avgdl)]

局限:词汇鸿沟、"苹果"歧义无法区分。

二、语义匹配:跨越词汇鸿沟

稠密向量检索(Dense Retrieval)

  • 查询和文档分别编码为向量,用 ANN(近似最近邻) 快速检索
  • 代表:DPR、Contriever,采用 双塔架构——编码器分离,可离线建索引,毫秒级响应

三、深度学习精排:BERT 及其变体

交互式架构(Cross-Encoder)

  • 拼接 [CLS] Query [SEP] Doc [SEP] 输入 BERT
  • [CLS] 输出过 MLP 得相关性分数
  • 效果最优但计算昂贵,仅用于 Top-K 重排

优化方向

  • ColBERT:延迟交互,token 级相似度,平衡效率与效果
  • Poly-encoder:多向量表示查询,兼顾速度与精度

四、RAG 场景的特殊考量

阶段 方法 职责
召回 向量检索(双塔)+ BM25 混合 高召回、低延迟
精排 Cross-Encoder / LLM 重排 高精确、可接受延迟

关键权衡:RAG 的检索延迟直接影响用户体验,通常用 向量召回 + 轻量精排,而非纯 BERT 交互式。

学习建议

建议系统学习该知识点

口语版讲法(约4分钟)

  • 一句话定位:相关性计算本质是召回与精排的权衡
  • 关键词匹配:BM25 为什么还是工业标配
  • 语义匹配:双塔与 ANN 的落地场景
  • 深度学习精排:BERT 交互式为什么只做重排
  • 落地风险与取舍:混合检索、延迟、一致性

这道题,我觉得面试官真正想问的是:在工业级系统里,你怎么在效果和效率之间做取舍。相关性计算不是选一个模型跑分就完事,它是一套级联流水线,不同阶段用不同方法,各有适用边界。

先说关键词匹配。别看现在大模型火,BM25 依然是工业界召回阶段的标配,没有之一。它的核心思想很简单:词频不是越高越好,增长有饱和,用参数 k1 控制;文档越长不一定越相关,用 b 做长度归一化;罕见词比常见词更有区分度,用 IDF 加权。公式我就不背了,但它的好处是确定性强、可解释、延迟极低。在客服退款场景里,用户问“退款多久到账”,BM25 能准确命中“退款到账时间”这个文档,因为它对“退款”和“到账”这种关键词非常敏感。但局限也很明显:词汇鸿沟,用户说“苹果”是水果还是手机,BM25 分不清;而且它完全基于字面匹配,语义上“退货”和“退款”相近,它就不行。

所以有了语义匹配,也就是 稠密向量检索。双塔架构,查询和文档分别编码成向量,用 ANN 近似最近邻检索。这个方法的优势是能跨越词汇鸿沟,把“我想投诉”和“对服务不满”映射到相近的向量空间。在商家满减政策检索里,用户问“凑单怎么优惠”,语义上能和“满300减50”这种文档匹配上,BM25 可能就漏了。但双塔有个大坑:离线建索引快,在线检索也快,但训练和调优成本高,而且对长尾 query 效果不稳定。如果训练数据覆盖不全,比如新出的促销活动,向量召回可能直接跑偏。所以工业界通常不会只用向量,而是 混合检索,BM25 和向量两条路都走,结果合并或加权,保证召回率高。

再精排阶段,用深度学习模型做交互式匹配。最典型的就是 Cross-Encoder,把查询和文档拼成 [CLS] query [SEP] doc [SEP] 输入 BERT,取 [CLS] 输出过 MLP 得到相关性分数。效果最好,但计算代价极大,没法对全量文档做,只能对召回的 top-K 重排。在订单异常检索场景,比如用户问“我付了款但订单显示未支付”,精排模型能理解“付了款”和“未支付”的矛盾关系,把最相关的客服话术排到前面。但要注意,如果召回的 top-K 里没有正确答案,精排再强也没用。所以上线我会特别关注召回阶段的 Recall@K,如果 K 不够大,精排就是空转。

最后说落地风险和前提。混合检索是常态,但混合不是简单拼凑,要处理分数归一化、延迟叠加、一致性等问题。比如 BM25 和向量分数怎么合并?我倾向用加权求和或级联,先向量粗筛再用 BM25 精调。另一个风险是 索引更新延迟:知识库文档有新增或修改,向量索引不能实时更新,如果用户刚上传了新政策,但索引还是旧的,召回就会漏。我会用双索引机制,base 索引定期重建,delta 索引增量插入,查询时合并,再用版本号做一致性校验。

还有一个延伸点值得注意:现在有些方案尝试用 ColBERT 这种延迟交互模型,在召回阶段做 token 级相似度,效果接近 Cross-Encoder 但速度快很多。不过它的索引存储量很大,对资源有要求。

所以整体上,我会把相关性计算看成一套流水线,关键词召回兜底,语义召回扩量,精排提精,每一步都有明确的适用边界和风险点。没有银弹,只有 trade-off。

关键一句:ColBERT 延迟交互在召回阶段做 token 级相似度,接近精排效果但速度快,不过索引存储量大。

面试官还可能这样问

  1. 问法 1 · 场景切入

    假设你在做一个电商搜索,用户搜“苹果手机”,结果里既有iPhone也有水果苹果。你怎么设计排序系统,让用户想要的iPhone排前面?

  2. 问法 2 · 层层追问

    搜索引擎里查询和文档的相关性你是怎么算的?……如果只用关键词匹配,遇到同义词怎么办?……那深度学习模型像BERT怎么用进来?

  3. 问法 3 · 直球架构

    设计一个排序系统的相关性计算模块,要求同时支持关键词匹配和语义匹配,还要能集成BERT这样的深度模型进行精排。你怎么设计?各阶段用什么方法?

同模块相关题目