它是什么
每次请求都用一个丰富的模型去给几百万个条目排序是不可能的:模型对每个条目的成本太高。搜索和推荐系统用一个漏斗解决它:一个便宜的、面向召回的阶段把几百万个候选缩到几千个,一个便宜的排序器再缩到几百个,然后一个昂贵的模型只给这一小批打分。每个阶段都用覆盖面换取精度和成本,并且各自有延迟预算。
Important
核心要点: 召回阶段负责召回,排序阶段负责精度。 前面的阶段要便宜而慷慨(永远不要丢掉任何合理的条目),把模型预算只花在幸存者身上,最后再应用确定性的策略(多样性、探索、过滤)。排序器是产品所在之处;召回只是管道。
何时需要它
“设计一个推荐系统”、“设计搜索排序”和”设计一个信息流排序器”都用这种形状。追问是每个阶段的延迟预算、特征如何提供服务、如何处理新条目和新用户,以及如何记录训练数据。
Note
面试信号: 带着数字给出漏斗(大约 5,000 个候选,然后 500,然后 top 50,每个阶段有一个毫秒预算),说明你推理过成本。说早期阶段是有意重叠、单个质量一般的,说明你理解它们的任务。
漏斗
| 阶段 | 输入到输出 | 每个条目的成本 | 任务 | 延迟示例 |
|---|---|---|---|---|
| 召回(Retrieval) | 数百万到约 5,000 | 很低(索引查找) | 不要漏掉合理的候选 | 约 40 ms,多个来源并行 |
| 轻量排序器 | 5,000 到约 500 | 低(小模型或点积) | 不要丢掉重量排序器最终的赢家 | 约 20 ms |
| 重量排序器 | 给 500 个打分 | 高(完整模型,几百个特征) | 按预测的互动或相关性排序 | 约 80 ms |
| 策略层 | 500 到 top 50 | 微不足道的规则 | 多样性、探索、业务过滤 | 约 10 ms |
各阶段的延迟加起来就是请求的预算(这里约 150 ms,再加网络)。
阶段 1:召回。 几个来源并行运行,各返回 1,000 到 2,000 个 id,然后合并去重:
- Embedding 最近邻: 在 ANN 索引里找离用户兴趣向量近的条目。
- 条目到条目的共现: “看了 X,就看 Y”,以最近的互动为种子。
- 热门: 带时间衰减的计数器,冷启动的主力。
- 新鲜条目: 按内容特征匹配最近上传的内容,是新内容的供给侧。
- 对搜索来说还有关键词召回: 倒排索引按 BM25 加近期性加权返回排名靠前的候选。
阶段 2:轻量排序。 梯度提升树、小型神经网络,或 two-tower 模型廉价地给所有候选打分。在 two-tower 模型里,用户和条目各有一个学习得到的 embedding,分数就是它们的点积:每个候选只需一次乘法,而且条目 embedding 可以预先算好。它唯一的任务是召回重量排序器的赢家。
阶段 3:重量排序。 从在线特征存储中批量读取,为 500 个候选填充大约 50 组特征,由完整模型预测每个条目的互动概率之类。特征分成几组:
| 组 | 例子 |
|---|---|
| 社交亲密度 | 作者是不是好友、好友的好友、最近有无互动 |
| 互动 | 点赞、评论、分享、近期增速 |
| 查询或上下文匹配 | BM25、标题匹配、话题标签匹配 |
| 内容 | 媒体类型、语言、长度 |
| 用户与会话 | 地区、语言、最近十分钟的行为(由请求本身计算) |
阶段 4:策略。 对分数应用确定性的、可调试的规则:多样性(按类别或作者设上限,用 MMR 风格的惩罚)、探索(一小部分位置给高不确定性的条目,为反馈回路提供新数据),以及业务过滤(已看过的抑制、完整性过滤)。
闭合回路:记录与训练
记录曝光时,要连同打分时刻原样的特征、模型版本和一个追踪 token 一起记录。这条记录就是明天的训练数据,而在服务时就写下它,才能让训练诚实。如果你之后再重建特征,你训练用到的就是模型当时并没有的信息,这叫 训练-服务偏差(training-serving skew),离线指标就不再能预测线上行为。
Caution
常见错误: 用事后重新计算的特征来训练,或用模型自己之前的排序挑选出来、没有任何探索的数据来训练。前者会虚高离线指标;后者会造成一个反馈回路:模型只会了解它已经展示过的东西。要在服务时记录特征,并保留一个探索的份额。
冷启动
新用户没有历史;新条目没有互动。漏斗用不依赖历史的来源来处理这两者:对新用户用热门和流行度,对新条目用基于内容的召回和一个新鲜条目来源,再加上探索位置,让新条目能获得它们的第一批信号。
Warning
生产实践: 每个阶段都有自己的故障模式和降级方案。如果重量排序器超时,就用轻量排序器的顺序;如果特征存储很慢,就用你手上有的特征打分并优雅降级。一个稍差的推荐页,好过一个错误页。
如何选择
| 情形 | 选择 | 原因 |
|---|---|---|
| 数百万候选 | 多来源的召回阶段 | 每个条目成本低的召回 |
| 对几千个做便宜的打分 | Two-tower 点积或小型树模型 | 每个候选一次乘法 |
| 对几百个做丰富的个性化 | 带在线特征存储的重量模型 | 把预算花在刀刃上 |
| 新条目或新用户 | 不依赖历史的来源加探索位置 | 冷启动 |
| 多样性和业务规则 | 确定性的策略层 | 可调试、可控 |
| 训练数据 | 在服务时记录特征 | 避免训练-服务偏差 |
相关
- 演练:设计推荐系统 — 推荐产品里端到端的漏斗。
- 演练:设计完整的排序系统 — 深入讲解各排序阶段及其延迟预算。
- 参考:近似最近邻索引 — 漏斗顶端的 embedding 召回来源。