首页 / 资讯中心 / 文章详情

统一召回与排序:生成式推荐架构的工程实践与选型指南

统一召回与排序:生成式推荐架构的工程实践与选型指南 ★ FEATURED ARTICLE
1. 从“统一召回与排序”说起为什么这件事值得反复折腾推荐系统圈子里有个老生常谈的痛点召回和排序长期是两套班子、两条链路、两种目标。召回阶段追求的是“别漏”通常用多路并行、向量近邻、倒排索引这些手段把候选集从百万级压到千级排序阶段追求的是“排得准”用精排模型对千级候选做打分再经过重排、多样性打散最终呈现给用户十几条结果。这套架构跑了很多年稳定、可解释、各模块职责清晰但它的问题也随着规模增长越来越刺眼。第一个问题是目标不一致。召回模型通常用双塔结构用户塔和物品塔各自编码最后靠内积或余弦相似度衡量匹配度。这种结构天然存在信息瓶颈——用户和物品的特征在最后一刻才交互表达能力受限。而排序模型用的是交叉特征、深度交互两者对“什么是好候选”的理解根本不在一个频道上。结果就是召回可能把排序真正想要的物品漏掉排序又只能在召回给的候选里矮子里拔将军。第二个问题是链路误差累积。多路召回各自有阈值、有配额哪一路多给一点、哪一路少给一点全靠人工调参。召回的评估指标是召回率排序的评估指标是AUC或GAUC两个指标优化方向未必一致。更麻烦的是召回阶段看不到排序阶段的反馈排序阶段也改不了召回阶段的候选集整个系统是开环的。第三个问题是工程复杂度。多路召回意味着多套索引、多套服务、多套运维。向量检索、倒排索引、规则召回、热门兜底每一条路都要单独维护。排序侧又要做特征工程、模型训练、在线推理、A/B实验链路越长出问题的概率越大迭代速度越慢。所以“统一召回与排序”这个方向本质上是在问一个问题能不能用一套模型、一条链路同时完成从百万级到十级的筛选和排序这不是简单的模型替换而是对整个推荐系统架构的重构。最近圈子里讨论比较多的几条路线包括OneRec、GRP、UniPinRec这些思路虽然具体实现各有差异但核心逻辑是相通的用生成式或统一编码的方式把召回和排序揉进一个框架里。这篇文章不打算堆砌论文公式而是从一线工程视角把这几条路线的核心思路、关键细节、实操中会踩的坑尽量讲透。适合正在做推荐系统架构升级的工程师、算法同学以及对生成式推荐感兴趣但还没动手的读者。读完之后你至少能判断自己的业务场景适不适合走统一路线以及如果走第一步该从哪里下手。2. 三条路线的整体设计思路拆解2.1 为什么是“三条路线”而不是一条统一召回与排序听起来像一个目标但落到工程实现上至少有三种截然不同的切入方式。这三种方式对应着不同的业务约束、数据条件和团队能力没有绝对优劣只有适不适合。第一条路线是生成式统一建模代表思路是OneRec这类做法。核心想法是把推荐问题转化成序列生成问题用户的历史行为是一个序列模型自回归地生成下一个可能交互的物品。召回和排序不再是两个阶段而是同一个生成过程的不同步骤——生成候选的过程就是召回生成概率的高低就是排序。这条路线对数据量要求极高训练成本也大但理论上限最高因为它彻底消除了两阶段之间的信息断层。第二条路线是图结构统一传播GRPGraph-based Retrieval and Ranking Propagation是这类思路的典型。它利用用户-物品交互图通过图神经网络把召回和排序的信号在同一张图上传播。召回阶段用图的邻居扩散找候选排序阶段用图的边权重和节点嵌入做精排。这条路线适合交互关系丰富、图结构天然存在的场景比如社交推荐、电商关联推荐。第三条路线是统一编码与渐进式筛选UniPinRec是这类思路的代表。它不追求一步到位生成最终结果而是用一个统一的编码器把用户和物品映射到同一空间然后通过多级筛选逐步缩小候选集。每一级筛选都是同一个模型的不同层或不同头召回和排序共享底层表示只在顶层做任务区分。这条路线工程落地相对平滑对现有架构改动最小适合大多数团队作为过渡方案。2.2 三条路线的共同底层逻辑虽然实现差异很大但这三条路线共享几个核心设计原则理解这些原则比记住具体模型结构更重要。第一统一表示空间。无论哪条路线都要求用户和物品在同一语义空间里可比较。传统双塔的问题是用户塔和物品塔各自独立训练最后靠内积对齐信息损失大。统一路线要么用共享编码器要么用交叉注意力让用户和物品的表示在训练过程中就相互影响。这背后的逻辑很简单如果召回和排序要用同一套表示那这套表示必须在训练时就看到两阶段的目标。第二端到端可微。召回阶段通常涉及Top-K选择这是一个离散操作不可微梯度传不回去。统一路线的关键突破之一就是用可微的近似方法替代硬Top-K。比如用Gumbel-Softmax做松弛或者用可学习的稀疏注意力让召回阶段的梯度能传到排序阶段反之亦然。没有这个统一训练就是一句空话。第三多目标融合。召回关心覆盖率排序关心精度统一模型必须同时优化多个目标。常见做法是共享底层参数顶层用多任务学习每个任务一个头。但这里有个坑不同任务的梯度尺度可能差几个数量级直接相加会导致某个任务主导训练。实践中通常用不确定性加权或梯度归一化来处理。第四渐进式计算。从百万级到十级计算量不可能一步到位。统一路线通常采用渐进式筛选先粗筛到万级再精筛到千级最后精排到十级。每一级用不同的计算预算但共享同一套表示。这跟传统多路召回精排的区别在于筛选过程是模型驱动的不是规则驱动的而且各级之间梯度连通。2.3 选型时该看哪些指标面对这三条路线怎么判断哪个适合自己我一般看四个维度。维度生成式统一图结构统一统一编码渐进筛选数据量要求极高需要亿级交互高需要丰富图结构中等百万级即可训练成本很高自回归生成慢较高图传播开销大可控与现有模型接近工程改动大需要重写链路中需要图存储和采样小可复用现有特征冷启动表现差依赖历史序列中依赖图连通性好编码器可泛化可解释性低生成过程黑盒中图路径可追溯高各级筛选可监控如果你的业务有海量用户行为序列团队有生成式模型经验可以尝试生成式路线。如果业务天然有图结构比如社交或电商图结构路线值得考虑。如果只是想平滑升级现有系统统一编码渐进筛选是最稳妥的起点。3. 核心细节解析与实操要点3.1 统一表示空间怎么建统一表示空间是三条路线的地基。建得不好后面怎么调都白搭。这里的关键是共享编码器的设计。传统双塔是用户一个编码器、物品一个编码器最后内积。统一路线要求用户和物品的表示在训练过程中就相互影响。常见做法有三种第一种是共享底层任务特定顶层。底层用同一个Transformer或MLP处理用户和物品的原始特征顶层再分用户头和物品头。这样底层表示是共享的顶层各自适配。好处是训练稳定坏处是底层可能学到一些对两个任务都不太专精的通用特征。第二种是交叉注意力编码。用户序列和物品特征在编码器内部就做交叉注意力让用户表示直接看到物品信息物品表示也直接看到用户信息。这种方式表达能力强但计算复杂度高训练时要注意显存。第三种是对比学习对齐。用户和物品各自编码但训练时用对比损失拉近正样本对的距离推远负样本对。这种方式不需要交叉计算工程上最轻量但需要精心设计负采样策略。实操中我建议从第一种开始稳定后再尝试第二种。第三种适合作为辅助损失不建议单独使用。注意统一表示空间的维度不要设得太小。传统双塔常用64维或128维统一路线因为要承载召回和排序双重任务建议至少256维否则信息瓶颈会很严重。3.2 可微Top-K的几种实现方式召回阶段的Top-K选择是统一训练的最大障碍。硬Top-K不可微梯度断流。解决办法有几种各有适用场景。Gumbel-Softmax松弛是最常见的做法。它把离散的选择操作近似成连续分布采样训练时用软采样推理时用硬选择。优点是理论成熟缺点是温度参数难调——温度太高近似太软学不到稀疏性温度太低梯度方差大训练不稳定。实践中通常用退火策略从高温逐渐降到低温。稀疏注意力是另一种思路。用可学习的稀疏掩码替代硬Top-K让模型自己学哪些位置该保留。优点是端到端可训练缺点是稀疏度不好控制容易学出稠密解。直通估计器Straight-Through Estimator最简单粗暴前向用硬Top-K反向直接把梯度传过去假装选择操作不存在。优点是实现简单缺点是梯度有偏训练初期可能震荡。可微排序是更精细的做法用Softmax近似排序操作让排序位置的梯度可传。适合排序阶段也需要可微的场景。我的经验是中小规模场景用直通估计器就够了简单有效。大规模场景建议用Gumbel-Softmax加退火虽然调参麻烦但上限更高。3.3 多目标梯度冲突怎么解统一模型要同时优化召回和排序目标梯度冲突是必然的。常见表现是召回损失下降排序损失上升或者反过来。严重的时候模型直接训崩。解决思路分两类。一类是损失加权给不同任务的损失乘不同权重。权重可以是固定的也可以动态调整。动态调整常用不确定性加权让模型自己学每个任务的噪声参数噪声大的任务权重自动降低。另一类是梯度操作比如PCGrad把冲突的梯度投影到正交方向消除相互干扰。实操中我建议先用不确定性加权实现简单效果稳定。如果还不行再上PCGrad。但要注意PCGrad计算开销大训练时间可能翻倍。还有一个容易被忽略的点任务之间的样本空间可能不一致。召回任务用的是全量物品排序任务只用曝光物品。如果直接混在一起训练召回任务的负样本会淹没排序任务的正样本。解决办法是分阶段训练先训召回再联合微调或者用重要性采样调整样本权重。3.4 渐进式筛选的层级设计统一编码渐进筛选的核心是层级设计。从百万级到十级分几级、每级保留多少候选、每级用什么计算都需要仔细权衡。我一般建议分三级粗筛、精筛、精排。粗筛从百万级到万级用轻量级模型或向量检索计算预算最小精筛从万级到千级用中等复杂度模型可以引入交叉特征精排从千级到十级用最复杂的模型充分交互。每级的候选数怎么定粗筛保留万级是因为万级以内的精筛计算量可控精筛保留千级是因为千级以内的精排可以在线实时计算。如果业务对延迟敏感可以压缩到粗筛五千、精筛两百、精排二十。层级之间的表示共享是关键。粗筛和精筛用同一套底层表示精排可以在此基础上加交叉层。这样梯度可以从精排传回粗筛实现端到端优化。注意层级之间的候选集要有重叠。如果粗筛漏掉的物品精筛永远看不到那粗筛的召回率就是整个系统的上限。实践中通常让粗筛保留的候选数是精筛的2到3倍给精筛留足选择空间。4. 实操过程与核心环节实现4.1 数据准备与特征工程统一路线的数据准备和传统推荐有相似之处但有几个关键差异。用户序列的构造是重中之重。生成式路线和统一编码路线都依赖用户行为序列序列的质量直接决定模型上限。序列构造要注意几点时间跨度不要太长通常取最近30到90天行为类型要统一点击、购买、收藏可以混但要加类型嵌入序列长度要截断或填充通常取50到200太短信息不足太长训练慢。物品特征的统一编码也很关键。传统召回和排序用的物品特征可能不一样召回用ID和类别排序用更丰富的属性。统一路线要求物品特征在召回和排序阶段一致所以需要提前对齐。我的做法是建一个统一的物品特征表包含ID、类别、属性、统计特征所有阶段都从这里取。负采样策略需要特别设计。召回阶段的负样本通常是全量物品随机采排序阶段的负样本是曝光未点击。统一训练时如果直接用召回负样本排序任务会学到太多容易区分的负例泛化差。建议用混合负采样一部分随机负样本一部分曝光未点击负样本比例大概7:3。特征归一化容易被忽略。用户特征和物品特征的尺度可能差很多直接拼接会导致某些特征主导。建议对连续特征做分桶或标准化离散特征做嵌入。特别是统计类特征比如点击率、转化率分布可能极度偏斜最好做对数变换或分位数归一化。4.2 模型训练的关键参数统一模型的训练参数比传统模型更敏感这里列几个我实测下来比较稳的配置。参数建议值说明学习率1e-4到3e-4比传统精排小因为统一模型参数多Batch size1024到4096太小梯度噪声大太大显存不够序列长度50到200根据业务行为密度调整嵌入维度256到512召回排序共享不能太小温度参数0.1到1.0Gumbel-Softmax用从1.0退火到0.1多任务权重动态调整用不确定性加权初始权重1:1训练轮数3到10看验证集通常比传统模型少训练过程中要重点监控几个指标召回任务的RecallK排序任务的AUC以及两者的联合指标。如果Recall上升但AUC下降说明召回和排序在打架需要调整多任务权重。如果两者都下降可能是学习率太大或数据有问题。还有一个实操技巧预热训练。先用召回任务单独训几个epoch让底层表示学到基本的用户物品匹配关系再加入排序任务联合训练。这样比直接联合训练稳定得多收敛也更快。4.3 在线推理的工程实现统一模型的在线推理和传统两阶段有本质区别。传统是召回服务返回候选排序服务打分两个服务独立部署。统一模型要么是一个大服务要么是多个级联服务共享表示。如果是一个大服务推理延迟是最大挑战。百万级候选不可能全部过一遍大模型。解决办法是级联推理第一级用轻量级模型或向量检索快速筛到万级第二级用中等模型筛到千级第三级用完整模型精排。每一级都是同一个模型的不同部分共享底层参数。如果是多个级联服务关键是表示传递。第一级输出的用户表示和候选表示要传给第二级避免重复计算。实践中通常把用户表示缓存在内存里候选表示存在向量数据库里级联时直接取用。延迟优化还有几个技巧量化把模型权重从FP32降到FP16或INT8推理速度能提升2到4倍剪枝去掉不重要的注意力头或神经元缓存热门用户的表示和热门物品的表示可以缓存避免重复计算。注意在线推理的候选集要留一定的随机性。如果每级筛选都是确定性的系统会陷入信息茧房。实践中通常在粗筛阶段保留一定比例的随机候选或者用温度采样替代硬Top-K。4.4 离线评估与在线实验统一模型的评估不能只看传统指标。召回率、AUC这些指标仍然要看但不够。还需要看几个统一模型特有的指标。端到端一致性召回阶段认为好的候选排序阶段是否也认为好。可以用召回Top-K和排序Top-K的重叠率来衡量重叠率太低说明两阶段没对齐。梯度健康度训练时监控各任务的梯度范数如果某个任务的梯度范数远大于其他任务说明权重需要调整。候选覆盖率最终呈现的结果中有多少来自不同召回路径。统一模型容易收敛到少数热门物品覆盖率下降是常见问题。在线实验方面统一模型的A/B实验周期要比传统模型长。因为统一模型改变了整个链路短期指标可能波动大需要至少两周的观察期。实验组和对照组的流量要足够大否则统计显著性不够。我踩过的一个坑统一模型上线初期点击率可能下降但人均停留时长和次日留存上升。这是因为统一模型更注重长期价值短期点击率不是唯一目标。所以实验指标要综合考虑不能只看CTR。5. 常见问题与排查技巧实录5.1 训练不收敛怎么办统一模型训练不收敛是最常见的问题表现是损失震荡、梯度爆炸或消失。排查思路按优先级来。先看学习率。统一模型参数多学习率通常要比传统模型小一个数量级。如果用的是1e-3先降到1e-4试试。如果还不行加warmup前1000步线性增长。再看梯度裁剪。统一模型梯度容易爆炸特别是生成式路线。梯度裁剪阈值设1.0到5.0超过就截断。如果裁剪后还不收敛检查损失函数是否有数值不稳定比如log(0)或除以零。然后看多任务权重。如果某个任务的损失远大于其他任务梯度会被它主导。用不确定性加权或手动调整权重让各任务损失在同一量级。最后看数据。检查特征是否有NaN或Inf序列是否有异常长度负采样是否有问题。数据问题导致的训练失败占一半以上但最容易被忽略。5.2 召回率上不去怎么调统一模型的召回率通常比传统多路召回低因为传统多路召回是“三个臭皮匠顶个诸葛亮”每路都有独特视角。统一模型只有一个视角容易漏。提升召回率的办法有几个。增加序列长度让模型看到更多历史行为增加嵌入维度提升表示容量调整温度参数让Top-K选择更软保留更多候选增加负样本多样性让模型学到更细粒度的区分。还有一个技巧多视角编码。用多个编码器头分别编码用户序列的不同方面比如短期兴趣、长期兴趣、品类偏好最后融合。这样既保持了统一框架又有多路召回的多样性。5.3 在线延迟超标怎么优化统一模型在线延迟超标是工程落地的最大障碍。优化思路分三层。模型层量化、剪枝、蒸馏。量化最直接FP16通常无损INT8可能掉点但速度提升明显。剪枝要去掉冗余的注意力头实测能减30%参数不掉点。蒸馏用大模型教小模型适合对延迟极度敏感的场景。工程层级联推理、缓存、批处理。级联推理前面讲过核心是每级计算量递减。缓存要缓存用户表示和热门物品表示命中率能到50%以上。批处理把多个请求合并推理GPU利用率能提升3到5倍。架构层异步推理、预计算。异步推理把召回和排序拆成两个异步阶段召回先返回粗排结果排序结果后到再更新。预计算适合用户表示变化不频繁的场景离线算好存起来在线直接查。5.4 常见问题速查表问题可能原因排查方法解决方案训练损失震荡学习率太大打印梯度范数降低学习率加warmup召回率低序列太短/嵌入太小对比传统召回增加序列长度和嵌入维度排序AUC下降多任务冲突监控各任务梯度调整权重用PCGrad在线延迟高模型太大/级联太多分阶段计时量化剪枝减少级联层数结果多样性差硬Top-K太确定统计品类分布加温度采样保留随机候选冷启动差依赖历史序列看新用户指标加内容特征用图结构补充显存不够Batch太大/序列太长看显存占用梯度累积混合精度训练5.5 几个容易踩的坑坑一直接替换现有链路。统一模型不是即插即用的它改变了整个系统的假设。建议先离线对比再小流量实验最后逐步放量。直接全量替换出了问题回滚都来不及。坑二忽略特征一致性。召回和排序用的特征如果不一致统一模型学到的表示就是扭曲的。上线前一定要做特征对齐检查确保两阶段看到的物品特征完全相同。坑三过度追求统一。不是所有场景都适合统一。如果业务本身召回和排序的目标差异极大比如召回要覆盖长尾排序要推热门强行统一可能两边都不讨好。这种情况下混合架构可能更合适。坑四忽视可解释性。统一模型是黑盒出了问题很难定位。建议在关键环节加监控比如每级筛选的候选分布、各任务的损失曲线、梯度范数变化。没有监控的统一模型上线就是赌博。坑五训练数据泄漏。统一模型用全量数据训练容易把未来信息泄漏到过去。比如用用户第10天的行为预测第5天的点击这在传统两阶段中不容易发生但统一模型中序列和标签混在一起很容易搞错。构造训练样本时一定要严格按时间切分。6. 我个人在实际操作中的几点体会统一召回与排序这个方向我前后跟过几个项目有成功的也有翻车的。最大的体会是统一不是目的效果才是。不要为了统一而统一如果传统两阶段跑得好好的没必要折腾。只有当两阶段之间的信息断层成为瓶颈或者工程复杂度已经拖累迭代速度时统一才值得考虑。另一个体会是渐进式比一步到位靠谱。三条路线中统一编码渐进筛选最容易落地因为它对现有架构改动最小。可以先从共享底层表示开始召回和排序共用一套嵌入顶层各自微调。跑通了再尝试更激进的统一比如可微Top-K和端到端训练。这样风险可控团队也有学习曲线。最后分享一个小技巧用传统模型做教师。统一模型训练初期可以用传统召回和排序模型的输出作为软标签让统一模型去拟合。这样收敛更快效果也更稳。等统一模型训好了再逐步去掉教师信号让它自己学。这个思路在多个项目上验证过能省不少调参时间。这个方向还在快速演进新的思路层出不穷。但底层逻辑是不变的让召回和排序看到同一个世界用同一套语言对话。至于具体用什么模型、什么架构都是实现手段。抓住这个核心就不会被各种新名词带偏。
阅读完成 · 觉得有帮助?
咨询建站