1. 2026年谈相关度排序:先看"简单匹配"在哪失灵
我在一个中文搜索项目里接手相关度优化时,第一周就被一个现象震住了:系统明明已经能搜到正确答案,可它永远排不到第一位。查了日志才发现,模型把大量权重给了"词面重合度",于是满屏关键词堆砌的低质量页面,轻松压过了真正解答用户问题的页面。那一刻我意识到,问题不在词典,不在分词,而在整个相关度理念还停留在"简单匹配"时代。
1.1 字面匹配的边界:索引里有这个词,不等于结果相关
到了2026年,很多中文系统的第一版依旧是经典检索模型:query分词之后查倒排索引,用TF-IDF或者BM25打分,再套一层业务规则,把类目、地域、时效性的权重叠上去。这套组合拳在十年前够用,在今天只能说"能用",而且是勉强能用。
为什么?因为用户表达需求的方式已经彻底变了。十年前用户搜"冰箱",输入的就是"冰箱"两个字。现在用户会输入"小户型租房用的迷你冰箱",会输入"能放化妆品的保鲜小柜子",甚至直接语音说"那个可冷藏的小冰箱哪个牌子好"。字面匹配系统收到这些query会做什么?分词、找词面重叠。结果里只要包含"冰箱"二字,它就判定相关,用户真正关心的容量、体积、摆放场景、噪音水平,一个都没进排序模型。
这就是典型的"索引里有这个词,不等于结果相关"。词面匹配能保证的是"词出现了",但它完全回答不了"这正好是用户要的那个东西吗"。说得再直白一点,简单匹配把相关性当成了一道判断题:query里的词出现了,结果就是相关;没出现,就是不相关。而真实世界的相关性是一道问答题,需要结合意图、场景、内容质量一起回答。
1.2 中文分词的连锁误差:一个切错,全链路跑偏
中文处理的第一步是分词,分词本身就是个误差源。我在项目里见过不少排序事故,追根溯源都是分词惹的祸。
举个例子,用户搜"乒乓球拍卖完了",系统如果切成"乒乓球/拍卖/完了",倒排索引里命中的全是二手拍卖、艺术品交易之类的页面,真正的"乒乓球拍"销售页排到了十万八千里外。再比如"研究生物科学",可以理解成"研究/生物科学",也可以理解成"研究生/物科学",意思完全是两个方向。分词错误一旦进倒排索引,词频统计错了,IDF算出的重要程度也错了,后面的打分全跟着错。
这还不是最麻烦的。中文分词对口语、缩写、网络新词特别不友好。每年的新词热词一出来,分词词典不更新,检索就瞎一阵子。前几年有个项目做内容社区的搜索,用户天天搜某个新出的梗,系统分不清这是在说人还是说事,相关度被一个没有及时更新的词典直接拉垮。修复手段不外乎持续加自定义词典、调分词器参数,但这些都是防守,不是进攻——它能保证"切得比较对",却保证不了"理解得对"。
1.3 长尾表达与同义改写:字面零重合,语义高度相关
真正让简单匹配体系崩溃的,是"字面零重合但语义高度相关"的query对。内容库里有篇文章标题是"2026年春季新款轻薄笔记本电脑推荐",用户搜索"适合出差带的办公本"。关键词层面几乎零重合,但语义上高度相关。传统检索模型在这里直接哑火——不是打分低,是根本召不回来。
召不回来意味着什么?意味着后面的所有环节都没有工作可做。再强的排序模型,也只能排"被召回的候选",召回层就把路堵死了。
有人会说,那我多维护几组同义词不行吗?词级映射确实能解决一部分问题,"笔记本"和"办公本"、"出差"和"便携"这类关系都可以映射。但"适合出差带的办公本"和"轻薄长续航的本子"之间,中间隔着无数层隐含推理,同义词表永远填不完这个坑。业内人士有句话我说过很多次:同义词表是个无底洞。
2. 告别"词面匹配":重建相关性的定义与度量
2.1 相关性是分级别的,不是非黑即白
动手改造之前,先把"相关"这个词拆开。很多团队直接按"相关/不相关"二分类做标注,这个粒度太粗了。线上排序的本质是"相对比较",它需要区分"稍差"和"很差",因为排序结果里通常只有一部分能展示给用户。
这些年我比较习惯把相关性分成四个级别:
| 级别 | 描述 | 例子 |
|---|---|---|
| L0 完全无关 | 与query意图毫无关系 | query"空调遥控器说明书",结果是"空调安装服务介绍" |
| L1 弱相关 | 有话题上的字面关联,但不解决需求 | query"空调遥控器说明书",结果是"该品牌全部产品列表" |
| L2 中等相关 | 提供部分信息,如参数、功能列表 | query"空调遥控器说明书",结果是"该型号遥控器按键图解" |
| L3 强相关 | 直接命中需求,答案或资源明确 | query"空调遥控器说明书",结果是"该型号说明书PDF下载页" |
分级标注的好处是,训练排序模型时可以直接用等级当目标,也可以把等级对转成pairwise偏好数据。这比简单打"好/坏"标签要精细得多,模型学到的边界也更接近真实的排序需求。
2.2 词面相似度只能当特征,不能当结论
过去我们把"匹配"当成了排序的目标函数,这是本末倒置。词面相似度、编辑距离、Jaccard系数、匹配词数,这些指标应该降级成特征,而不是扮演判定标准。
原因很直接:词面高相似的query-文章对里,存在大量"看着相关其实无关"的反例;词面零重叠的,又存在大量"看着无关其实正解"的正例。只有让数据说话,把词面信息塞进模型当特征,让模型自己去学习它在不同场景下的权重,才能摆脱"唯字面论"的惯性。
我在内部培训时常打一个比方:词面相似度是"这个人看起来眼熟",真正的相关性是"这个人正好能帮你解决问题"。眼熟不等于能办事。落地时要注意,凡是还在直接拿词面重合率作为最终排序依据的系统,无论上线了多少年,都值得推倒重来。改造的第一步,就是把它请下决策席位。
2.3 排序目标要围绕"意图满足程度"设计
重定义了相关性层级,接下来要重定排序的目标函数。2026年的中文相关度排序,目标应该是"意图满足程度",而不是"词面重合程度"。拆开来说有几点:
- 先识别query背后的意图类别:找资源、求答案、比价格、看评价、下单动作。
- 再判断文档是否针对该类意图给出直接响应:有没有答案文本、下载链接、价格明细、评价内容。
- 最后结合场景微调:新用户还是老用户、PC端还是移动端、时间窗口是不是特殊档期。
一句话总结这个转变:相关度排序从"词"的匹配,进化为"需求"的匹配。这是整个技术改造的大方向,也是后面所有技术选型的前提。
3. 核心链路拆解:召回、粗排、精排与重排
3.1 召回层:多路召回与分数融合
排序的前提是先召回。单一检索路径在中文场景里特别容易漏,所以第一件事就是把召回从"单路"改成"多路"。常用的三路召回我列一下:
- 词法召回:BM25或者查询似然模型,负责捕获精确词面匹配,确定性最高,适合型号、代码、专有名词这类查询。
- 语义召回:双塔结构的向量模型,query和文档分别编码成向量,用向量距离召回语义相近的候选,负责兜住"字面零重合"的漏网之鱼。
- 业务强制召回:按类目、品牌、地域、时间等业务条件直接圈定候选集合,保证某些场景下答案不会因为分数不够而缺席。
多路召回各路的分数分布、范围、含义都不一样,不能直接相加。我比较常用的解法是:对每一路单独做分位数变换或者归一化,把分数压到统一的尺度,然后给定一个初始权重。权重怎么调?先跑基线,再靠A/B测试慢慢迭代,不要指望第一版就拟合出完美权重。
实战中我特别推荐"分层召回+粗排打分"的结构。召回阶段把候选集从百万级压到千级,粗排用轻量模型(比如十几个特征的GBDT)从千级压到百级,精排再把百级压到个位。千万别试图让一个模型覆盖全部规模,那样不是精度不够,就是延迟直接爆表。
关键提示:召回阶段宁可多召回,也不要漏召回。向量召回解决的是"有没有这个可能",精排解决的才是"到底该不该排前面"。前期多给候选,后期排序才有腾挪空间。
3.2 语义向量召回:模型选型与相似度计算的细节
语义召回的核心是双塔模型。query塔和文档塔各自编码,线上预先算好文档向量存进向量检索引擎,query来了实时编码再检索。关键细节就藏在"怎么选模型"和"怎么算相似度"里。
模型要在中文语料上做领域适应。通用模型对通用说法还行,对垂直行业词、口语化表达就不敏感。拿电商场景举例,要把"红色显瘦连衣裙"和"酒会礼服"关联起来,需要的是时尚领域语料训练过的模型,通用模型很难做对这类匹配。没有领域数据时,先用通用中文模型顶着,有预算就做领域微调,算是性价比最高的投入之一。
相似度计算方面,常见的是内积和余弦相似度。内积对向量模长敏感,适合文档已经预先归一化的场景;余弦相似度天然带归一化,更稳定。选哪个的原则很简单:训练时用的什么目标函数,上线就用什么度量方式。训练时用softmax内积,上线就用内积;训练时用余弦,上线就用余弦。训练和推理度量不一致,效果一定会打折。
还有一个很多新手容易犯的错:向量召回的top K设得太小。我看到不少项目把ANN检索的top K设成50、100,理由是"够精排用了"。实际上向量召回噪音偏大,候选集给太小,精排可施展的空间就非常有限。我自己一般把向量召回从100放到300甚至500,反正精排还有一层细打分,前期多一点候选,后期排序更有余地。
3.3 精排与重排:树模型、跨编码器和LLM的搭配
精排层的任务,是把召回来的候选按相关度排好。2026年再看精排,主流路线基本是三类搭配着用。
第一类是特征驱动的树模型,比如LambdaMART这类排序学习模型。优势在于可解释性强、特征工程直接、上线快。中文场景下的相关性特征很丰富:词面覆盖率、编辑距离、BM25分数、query和文档的名词重叠度、点击率、停留时长、类目一致性等。把这些特征喂给GBDT,多数场景下已经能比字面匹配高出明显一截。
第二类是跨编码器结构的深度语义模型。把query和文档拼成一个输入序列,让模型内部做token级交互。相比双塔,跨编码器的精度明显更高,但推理成本也高,因为每一对query和文档都要过一次前向计算。最合适的用法是把它放在精排保下来的小候选集上做重排,比如从粗排留出的50个候选中挑出最后的10个。
第三类是LLM重排。做法可以很轻:把query和文档一起喂给模型,要求输出一个相关度分数或者"是/否/不确定"判断;也可以做列表式重排,把10个候选一起给模型,让它输出排序结果。LLM重排的理解能力确实强,能处理复杂的隐含需求,但代价是延迟和成本。稳妥的配置是让LLM只对精排Top N做"最后一道质检",或者把它输出的分数与模型分数融合,而不是全量候选跑一遍。
3.4 相关性分数的融合:别被"分数豪夺"带偏
多路召回、多个模型打分之后,必然面临融合问题。这里最常见的坑是"分数豪夺":某个模型的分数数值范围大,融合后直接把其他分数淹没。我见过一个项目,语义分数范围在0到1,词法分数在0到30,融合公式直接相加,结果语义分数几乎不起作用,等于白做一路召回。
比较稳的解法是走排序学习的路子。不要手工设计融合公式,而是把BM25分数、语义分数、业务分都作为特征,拿标注好的排序数据去训练一个融合模型,让模型自己学每个分数在不同场景的权重。前期如果标注数据量不够,可以先做简单的加权融合作为过渡,但一定要把"切换成学习权重"写进迭代计划,否则融合逻辑会一直停留在手工调参的半成品状态。
4. 中文场景独有的排序细节:歧义、行业词与混合表达
4.1 歧义消解:同一个词,在不同场景里是不同实体
中文的歧义问题在排序里格外突出,因为同一个词经常对应完全不同的实体。"苹果"可以是水果,也可以是数码品牌;"小米"可以是粮食,也可以是手机品牌;"华为"既是人名化品牌,也可能是那段历史的特定称呼。字面匹配系统碰到这类query会怎么排?谁包含这个词谁就相关,结果一半排的是水果种植技术,另一半是手机评测,真实意图被彻底淹没。
处理歧义没有捷径,常规手段是建实体层。把query先做实体识别,判断它指向的是哪个实体,再去实体对应的候选池里做排序。识别的手段可以从规则、词典出发,逐步升级到序列标注模型。实体消解做得越好,后面的排序越不容易被歧义干扰。
4.2 行业词表与动态词:垂直场景的知识注入
中文场景做相关度排序,行业知识是绕不开的。同样一个词,在普通搜索和垂直领域里含义完全不同。"梯度下降"在机器学习场景是算法,在物理场景是现象描述;"复权"是金融术语,普通用户可能听着像'恢复权利'。垂直系统如果不用行业词表做词典扩展、query改写和实体识别,模型很难把行业特有的表达和通用表达关联起来。
另一个细节是动态词。新梗、新品牌、新缩写每年都在出现。我的经验是,给语义向量模型和检索系统各配一条"新词热词更新通道",每周例行跑一遍新增词的召回命中情况。词表更新不用追求大而全,重点是"核心高频新词在出现后有快速生效的机制"。这才是2026年应对内容快速迭代的正确姿势。
4.3 时效性、地域性与中英混合表达
中文场景的时效性特征比很多语言都要强。同样搜"春节旅游攻略",1月搜和6月搜的需求完全不同;搜"最新款手机",三个月前的结果就已经失去排序价值。时效性怎么进排序?可以做成一个衰减特征,也可以做成一个独立的重排规则。我在项目里常用"文档发布时间+类目时效敏感度"来计算一个时效分,再和相关性分数做融合。
地域性也类似。搜"哪里学游泳",北京用户和上海用户要的结果完全不一样。有地域属性的query,要优先用ip和地理信息做候选的过滤或加分。中英混合表达同样常见,"iPhone价格"、"B2B网站有哪些",这类query对分词和词典都有额外要求。混合表达处理得好不好,往往直接决定一批高频query的排序体验。
5. 从零落地一套混合相关度排序系统
5.1 数据与标注:先统一"什么是相关"的口径
再好的模型,也怕标注数据的口径不统一。所以落地的第一步,永远是标注规范。
标注规范里最重要的是把相关性层级定义得足够具体,配正反例。比如L3的定义不能只说"强相关",要说"直接回答问题、提供可下载资源、给出明确价格信息"这类可观测标准。标注前搞一轮试标,让两三个标注员独立标同一批样本,算一下一致性。一致性低的维度,要么是定义模糊,要么是样本本身太难,两条路都得先解决。
标注样本的来源也要讲究。不能只从线上点击日志里抽,那样偏向热门query;也不能只随机抽,那样正例太稀疏。我用过的组合是从三处抽:随机中长尾query、线上曝光过的query-文档对、语义召回新召回的样本。这样训练集覆盖的分布才相对健康。
5.2 离线评估与线上验证:NDCG不是万能的
离线评估指标,最常用的是NDCG、MRR、MAP这几个排序指标。NDCG对位置敏感,适合衡量"高质量结果是否排在前列";MRR只看第一个正确答案的位置,适合问答场景。中文相关度项目里,我一般同时看两个指标:NDCG@10加上一个业务自定义指标,比如"首屏强相关比例"。
不过离线指标只能参考,不能迷信。离线分数涨了,不代表线上体验一定好。真正的试金石是线上实验。上线前把query样本分成测试集,做一次"新旧系统结果人工盲评"也是很好的兜底手段,成本不高,效果直观。
5.3 上线节奏:灰度、A/B与回归机制
混合排序系统的上线,我强烈建议分层灰度,不要一把梭。第一周放开5%流量,只观察延迟和基础漏斗指标;没问题放到20%,开始看核心业务指标;逐步放大到50%、100%。每一步回滚方案都要提前准备好,因为位置类实验的副作用往往要过几天才会显现。
A/B实验要注意的一点是,排序系统改了之后,"曝光分布"会变,旧的点击率数据可能失真。所以评估新排序时,不能只看点击率本身,还要看"结果是否更符合query意图"这类更接近本质的信号。最好的状态是,线上有一个实时的人工申诉和反馈通道,用户对某个结果说"这不是我要的",告警能推送到排序负责人手里,形成快速迭代闭环。
6. 真实项目里的几种翻车现场与补救经验
6.1 标注一致性崩了,模型学了错误答案
有个项目花了一个月标注数据,结果训练出来的模型离线指标不升反降。排查时发现,标注规范里"中等相关"和"弱相关"的边界写得太模糊,两个标注员对同样的query-文档对,一个标L2,一个标L1。模型在两个等级之间来回摇摆,排序结果自然显得"没有主见"。
补救的办法是从标注规范下手。我重新整理了标注手册,把每个级别配了三个正例和三个反例,并专门设了一条规则:拿不准的时候标低不标高。规范改完后重新洗了一轮数据,模型效果立刻稳定下来。这件事给我的教训是,数据的质量工程优先级永远高于模型结构的选型。
6.2 向量召回在高频口语词上失效
另一个翻车现场是语义召回对高频口语词特别不敏感。用户搜"怎么把照片传到电脑上",向量模型召回的是一堆"手机连接电脑"的老教程,真正讲无线传输、系统自带功能的新文章反而排后。原因是训练语料里这类口语化长尾表达太少,向量空间里根本学不出正确的邻近关系。
补救分两步。第一步,把线上真实query定期回流到训练集,做持续学习;第二步,针对高频口语query建立一批人工编辑的"query改写对",把这些改写对当成硬约束引入,确保模型至少在这些case上不再犯错。持续学习加人工约束双管齐下,"口语失效"的比例才降下来。
6.3 延迟预算超了,重排成了"不可用"的算法
还有一次,方案设计得很理想:召回后用跨编码器重排,再加LLM打分。结果上线后发现P95延迟飙升到八百毫秒以上,接口直接被打爆。问题在于跨编码器是全量候选跑,LLM又对Top 10逐个打分,都是吃计算的大户。
补救方案是给重排降级:跨编码器只跑粗排后的Top 30,LLM一次只处理一个列表、输出一个排序,整个过程从逐条打分改成批量判断。改造后P95延迟回到三百毫秒以内,排序质量几乎没有下降。这个case让我越来越确认一个原则:2026年做相关度排序,不是把最贵的模型堆上去就好,而是把每一层算力花在刀刃上——先让便宜的路由处理绝大多数候选,再用贵重的模型处理真正需要精细判断的那几个位置。
回看这几年在中文相关度排序上踩过的坑,最大的感受是:技术方案再多,也替代不了对"用户到底想要什么"的理解。模型选型、召回路径、特征工程都是手段,把query背后的真实需求读懂,才是排序问题的终极答案。希望这份指南能让后来者少走一些弯路,直接从"告别简单匹配"的正确起点出发。