1. 从“统一召回与排序”说起这套方案到底在解决什么问题推荐系统做久了你会发现一个很拧巴的现象召回和排序明明是同一个目标的两个阶段却常常像两个部门各干各的。召回侧拼命扩大候选集生怕漏掉用户可能感兴趣的内容排序侧则对着几千条候选精雕细琢算力全花在打分上。结果就是召回阶段引入的噪声要靠排序阶段去擦屁股排序阶段又因为候选集太大而不得不做粗排截断一来一回信息损耗和算力浪费同时发生。“统一召回与排序”这个方向本质上就是想把这两步的边界打掉让召回阶段就带着排序的目标去学让排序阶段能直接受益于召回阶段更精准的表示。围绕这个思路目前业内比较有代表性的三条路线分别是OneRec、GRP和UniPinRec。这三个名字你可能在最近的论文和工程分享里频繁看到但它们各自解决的是什么问题、适合什么场景、落地时要注意什么很多人其实是一知半解的。这篇文章就是要把这三条路线拆开揉碎讲清楚。我会从设计动机、核心机制、实操要点、常见坑几个维度展开尽量用工程视角而不是论文视角来说。如果你正在做推荐系统的架构升级或者单纯想搞清楚“统一召回排序”到底怎么落地这篇内容应该能帮你省下不少查资料和踩坑的时间。提示本文涉及的所有模型名称和方案均来自公开技术讨论具体实现细节以实际业务场景为准不要盲目照搬。2. 三条路线的整体设计思路与选型逻辑2.1 为什么会出现“统一”这个需求先说说背景。传统推荐系统的漏斗结构是召回→粗排→精排→重排每一层都有明确的职责划分。召回负责从百万级物料里捞出几千条粗排把几千条压到几百条精排再对几百条做精细打分。这个结构在物料规模不大、用户行为稀疏的年代很好用因为每一层都可以独立优化工程上也容易并行。但问题随着规模增长越来越明显。第一召回和排序的目标不一致。召回通常用双塔模型优化的是内积相似度但内积相似度和最终的点击率、转化率并不是单调关系。第二多阶段之间的信息传递有损。召回阶段丢掉的物料排序阶段永远看不到哪怕它其实很适合用户。第三算力分配不合理。精排模型越来越复杂但只能处理几百条候选召回阶段却要用简单模型处理百万级物料算力花在了刀刃的反面。“统一召回与排序”就是想解决这三个问题。核心思路是让召回阶段就具备排序能力或者让排序阶段能直接处理更大规模的候选集。三条路线分别代表了三种不同的技术取舍。2.2 OneRec用生成式思路做统一OneRec 的核心思路是把推荐问题转化为序列生成问题。它不再区分召回和排序而是用一个统一的生成模型直接根据用户历史行为生成推荐列表。你可以把它理解成“推荐领域的GPT”——输入是用户的行为序列输出是推荐物料的序列。这种思路的优势很明显召回和排序在同一个模型里完成不存在信息损耗生成过程天然支持多样性控制因为你可以通过解码策略来调节输出的多样性而且生成模型可以很好地利用序列信息对用户兴趣的建模更充分。但挑战也很大。生成模型的推理成本高尤其是当物料规模很大的时候如何高效地做约束解码是个难题。另外生成模型容易陷入“安全区”总是推荐热门物料长尾物料的曝光机会被压缩。OneRec 在工程上需要解决的核心问题就是如何在保证生成质量的同时控制推理延迟和多样性。2.3 GRP用图结构打通召回与排序GRP 走的是另一条路。它不把推荐当成生成问题而是当成图上的节点排序问题。用户和物料都是图中的节点行为关系是边召回和排序统一在同一个图神经网络里完成。GRP 的核心创新在于它设计了一种分层图结构底层做粗粒度的邻居聚合上层做细粒度的交互建模从而在一个模型里同时实现召回和排序的功能。GRP 的优势在于它对关系数据的建模能力很强。如果你的场景里用户-物料交互图很丰富GRP 能很好地利用这些结构信息。而且图神经网络的推理可以做成增量式的新行为进来之后只需要更新局部子图不需要全量重算工程上比较友好。但 GRP 的难点在于图的构建和维护。图太大训练和推理都会很慢图太小又捕捉不到足够的关系信息。另外图神经网络有过平滑的问题层数多了之后节点表示会趋同反而降低区分度。GRP 在实际落地时通常需要配合采样策略和分层训练来解决这些问题。2.4 UniPinRec用统一表示空间做桥接UniPinRec 的思路介于前两者之间。它不改变召回和排序的基本结构而是通过一个统一的表示空间把两者桥接起来。具体来说UniPinRec 设计了一个共享的嵌入层召回和排序模型都从这个嵌入层出发但各自保留自己的网络结构。这样既保留了双塔召回的高效性又让排序模型能直接利用召回阶段的表示。UniPinRec 的最大优势是工程落地成本低。你不需要推翻现有的召回和排序架构只需要在嵌入层做统一然后设计一个联合训练的目标函数。对于已经在跑双塔召回和深度排序模型的团队来说UniPinRec 的迁移成本是最低的。但它的局限性也很明显统一表示空间的能力上限受限于嵌入层的容量。如果召回和排序对表示的需求差异很大共享嵌入层可能会成为瓶颈。另外联合训练的目标函数设计很关键召回损失和排序损失的权重需要仔细调节否则容易出现一方主导的情况。2.5 三条路线的选型对照维度OneRecGRPUniPinRec核心思路生成式统一图结构统一表示空间统一召回排序融合度完全融合完全融合部分融合工程落地成本高中低推理延迟高中低多样性控制解码策略调节图采样调节依赖嵌入层适合场景物料规模中等、序列行为丰富关系数据丰富、图结构明显已有双塔深度排序架构主要挑战推理成本、多样性图维护、过平滑嵌入层容量、损失权重选型的时候我个人的经验是如果你是从零开始搭建推荐系统且团队有生成模型的经验OneRec 值得尝试如果你的场景里社交关系、知识图谱等结构信息很重要GRP 更合适如果你已经有成熟的召回和排序系统想低成本升级UniPinRec 是最稳妥的选择。3. 核心细节解析与实操要点3.1 OneRec 的生成式解码与约束策略OneRec 最核心的技术点在于解码。生成模型输出的是一个概率分布但推荐场景要求输出的是物料ID序列而且这些物料必须是真实存在的。这就涉及到约束解码的问题。常见的做法是维护一个前缀树Trie把所有候选物料的ID构建成一棵树解码的时候只在树的合法路径上搜索。这样做的好处是保证生成的物料一定在候选集里但缺点是前缀树的内存占用很大尤其是物料ID很长的时候。另一种做法是分层解码。先把物料聚类成若干类别解码的时候先选类别再选类别下的具体物料。这样可以把搜索空间从百万级降到千级推理速度会快很多。但分层解码的缺点是类别划分的质量直接影响最终效果如果类别划分不合理生成的结果会很差。我在实际测试中发现OneRec 的解码温度参数很关键。温度太高生成的结果多样性好但相关性差温度太低生成的结果相关性好但容易重复推荐同一类物料。一般建议在0.7到1.0之间调节具体值要根据业务对多样性和相关性的权衡来定。注意OneRec 的推理延迟和序列长度强相关。如果用户行为序列很长建议先做序列压缩比如用注意力机制提取关键行为而不是把所有行为都喂给生成模型。3.2 GRP 的图构建与采样策略GRP 的图构建是决定效果的第一步。用户节点和物料节点之间的边通常来自行为数据但行为数据的稀疏性是个大问题。很多用户只有几次交互很多物料只有几十次曝光这样的图是很稀疏的图神经网络很难学到有效的表示。解决稀疏性的常见做法是引入辅助边。比如用户-用户之间的社交关系、物料-物料之间的内容相似度、用户-物料之间的属性匹配关系等。这些辅助边可以增加图的连通性让信息传播更充分。但辅助边的权重需要仔细调节否则会引入噪声。采样策略也很关键。全图训练不现实通常需要做邻居采样。常见的做法是固定采样邻居数量比如每个节点采样10个邻居。但这样做的缺点是采样方差大尤其是度数分布不均匀的时候。更好的做法是重要性采样根据边的权重来决定采样概率权重高的边被采样的概率大。GRP 还有一个容易被忽视的细节图的时间衰减。用户的行为是有时效性的三个月前的点击和昨天的点击重要性完全不同。所以在构建图的时候边的权重应该随时间衰减。常见的衰减函数是指数衰减半衰期根据业务场景来定一般电商场景半衰期在7到14天左右。3.3 UniPinRec 的联合训练与损失平衡UniPinRec 的核心在于联合训练。召回损失和排序损失需要同时优化但这两个损失的量级和收敛速度往往不同。如果直接相加通常会出现一方主导的情况。常见的做法是动态权重调整。比如用不确定性加权让模型自己学习两个损失的权重或者用梯度归一化让两个损失的梯度量级保持一致。我在实践中发现不确定性加权的效果比较稳定但需要额外的参数来建模不确定性增加了训练复杂度。另一个关键是嵌入层的更新频率。召回和排序对嵌入的更新需求不同召回需要嵌入更新快一些以便快速捕捉新行为排序需要嵌入稳定一些以便精细打分。如果共享嵌入层就需要在更新频率上做折中。常见的做法是召回侧用较高的学习率排序侧用较低的学习率通过分层学习率来调节。还有一个实操细节UniPinRec 的嵌入层维度选择。维度太低表示能力不足维度太高召回侧的内积计算会变慢。一般建议在64到256之间选择具体值要根据物料规模和算力预算来定。如果物料规模在百万级128维通常是个不错的起点。3.4 三条路线的共同技术底座虽然三条路线思路不同但它们都依赖一些共同的技术底座。首先是负采样策略。统一召回排序之后负样本的构造方式会直接影响模型效果。常见的负采样有随机负采样、曝光未点击负采样、困难负采样等。我的经验是困难负采样效果最好但需要配合去偏策略否则容易过拟合到困难样本。其次是特征工程。统一模型对特征的依赖更强因为召回和排序共享特征之后特征的噪声会被放大。所以特征清洗和特征选择在统一模型里比在分离模型里更重要。建议对特征做重要性分析把低重要性的特征去掉减少噪声。最后是评估体系。统一召回排序之后传统的召回率、排序AUC等指标不再适用需要设计新的评估指标。常见的做法是用端到端的指标比如推荐列表的点击率、转化率、多样性等。另外离线评估和在线评估的差距在统一模型里往往更大因为统一模型的泛化行为更复杂离线指标很难完全反映在线效果。4. 实操过程与核心环节实现4.1 数据准备与特征处理不管选哪条路线数据准备都是第一步。推荐系统的数据通常包括用户特征、物料特征、交互行为三类。用户特征包括人口属性、行为统计、兴趣标签等物料特征包括内容属性、统计特征、质量分等交互行为包括点击、购买、收藏、分享等。在统一召回排序的场景下数据准备有几个特殊要求。第一行为序列要完整保留不能只保留最近几次行为。因为统一模型需要从序列中学习用户兴趣的演化序列太短会丢失信息。第二时间特征要精细到小时级别因为统一模型对时效性更敏感。第三负样本的构造要统一召回和排序不能用不同的负采样策略否则联合训练会不稳定。特征处理方面数值特征做归一化或分桶类别特征做嵌入序列特征做池化或注意力聚合。这里有个细节序列特征的聚合方式对统一模型的影响很大。平均池化会丢失顺序信息注意力聚合能保留重要行为但计算量更大。我的建议是如果算力允许优先用注意力聚合如果算力紧张可以用GRU做序列编码效果介于两者之间。4.2 模型搭建与训练配置以 UniPinRec 为例模型搭建的大致流程是这样的。首先定义共享嵌入层用户特征和物料特征都映射到同一个嵌入空间。然后召回侧接一个双塔结构用户塔和物料塔分别做多层感知机最后做内积计算。排序侧接一个深度交叉网络把用户特征、物料特征、交叉特征拼接后做多层感知机。训练配置方面批量大小建议在1024到4096之间太小训练不稳定太大收敛慢。学习率用Adam优化器初始学习率1e-3配合余弦退火。训练轮数一般10到20轮就够了再多容易过拟合。正则化用Dropout和权重衰减Dropout率0.1到0.3权重衰减1e-5到1e-4。联合训练的损失函数可以写成# 伪代码示意 recall_loss binary_cross_entropy(recall_logits, recall_labels) rank_loss binary_cross_entropy(rank_logits, rank_labels) total_loss uncertainty_weighting(recall_loss, rank_loss)不确定性加权的实现方式是给每个损失引入一个可学习的方差参数损失除以方差再加上方差的对数。这样模型会自动调节两个损失的权重方差大的损失权重小方差小的损失权重大。4.3 离线评估与在线实验离线评估阶段我建议用多指标综合评估不要只看单一指标。召回侧看RecallK和HitRateK排序侧看AUC和GAUC端到端看NDCGK和多样性指标。另外建议做消融实验分别验证共享嵌入层、联合训练、负采样策略的贡献。在线实验阶段AB测试的流量分配要合理。统一模型的实验组和对照组建议按50/50分配实验周期至少一周覆盖完整的用户行为周期。观察指标除了点击率、转化率还要看多样性、新颖性、长尾覆盖率等。统一模型容易偏向热门物料所以长尾覆盖率是个很重要的监控指标。我在实际项目中发现统一模型上线初期通常会有几天的波动期因为模型需要适应在线数据的分布。建议在波动期内不要急于下结论等模型稳定后再评估效果。另外统一模型的冷启动表现通常比分离模型差因为统一模型对行为序列的依赖更强新用户的行为序列短模型很难做出好的推荐。解决方法是给新用户走单独的召回通道等行为积累到一定程度再切换到统一模型。4.4 推理优化与工程部署推理优化是统一模型落地的关键。OneRec 的推理成本最高通常需要专门的推理加速方案比如量化、蒸馏、缓存等。GRP 的推理可以做成增量式新行为进来只更新局部子图延迟可控。UniPinRec 的推理成本和传统双塔深度排序差不多工程上最容易落地。部署方面统一模型通常需要更大的内存和算力预算。建议做模型分片把嵌入层和上层网络分开部署嵌入层用参数服务器上层网络用GPU推理。另外建议做请求合并把多个用户的请求合并成一个批次推理提高GPU利用率。缓存策略也很重要。统一模型的输出可以缓存但缓存过期时间要短因为统一模型对时效性敏感。一般建议缓存5到10分钟具体值根据业务对时效性的要求来定。5. 常见问题与排查技巧实录5.1 训练不收敛或损失震荡这是统一模型最常见的问题。原因通常有三个损失权重不平衡、学习率太大、负样本构造有问题。排查思路是这样的。先看两个损失的曲线如果一方持续下降另一方持续上升说明损失权重不平衡需要调整权重或改用不确定性加权。如果两个损失都震荡说明学习率太大需要降低学习率或加梯度裁剪。如果损失下降很慢说明负样本太简单需要增加困难负样本的比例。我踩过的一个坑是联合训练的时候召回侧和排序侧的学习率设成一样结果召回侧收敛太快排序侧还没学好联合训练就结束了。后来改成召回侧学习率1e-3排序侧学习率1e-4效果就好了很多。5.2 在线效果不如离线离线指标很好上线之后效果却很差这是统一模型的另一个常见问题。原因通常是离线评估和在线评估的分布不一致。排查思路先看离线评估用的数据是不是和在线数据同分布。如果离线数据是历史数据在线数据是实时数据分布差异会很大。解决方法是用时间切分做离线评估用最近一周的数据做验证集而不是随机切分。另一个原因是离线评估没有考虑位置偏差。离线数据里的点击是在特定位置产生的模型学到的是位置相关的偏好而不是真实的兴趣。解决方法是在离线评估里做位置去偏或者用在线AB测试直接评估。5.3 多样性下降和长尾物料曝光不足统一模型容易偏向热门物料因为热门物料在训练数据里出现频率高模型学到的表示更充分。结果就是推荐列表里全是热门物料长尾物料没有曝光机会。解决方法有几个。第一在损失函数里加多样性正则惩罚推荐列表的重复度。第二在解码阶段做多样性控制比如用核采样或束搜索加多样性惩罚。第三在训练数据里做重采样给长尾物料更高的采样权重。我在实际项目里的做法是组合使用训练时给长尾物料加权解码时用核采样上线后监控长尾覆盖率。这样能把长尾覆盖率从不到10%提升到20%左右同时点击率没有明显下降。5.4 推理延迟过高OneRec 和 GRP 的推理延迟通常比传统模型高尤其是物料规模大的时候。排查思路先看延迟瓶颈在哪是嵌入查找、图聚合还是解码。如果是嵌入查找慢说明嵌入表太大需要做嵌入压缩或分片。如果是图聚合慢说明图太大需要做图采样或增量更新。如果是解码慢说明搜索空间太大需要做分层解码或前缀树剪枝。我遇到过一个案例GRP 的推理延迟在高峰期飙升到500毫秒排查后发现是图聚合的时候邻居数量太多。后来把邻居采样数量从50降到20延迟降到100毫秒以内效果只下降了不到1%。5.5 常见问题速查表问题现象可能原因排查方法解决措施训练不收敛损失权重不平衡观察两个损失曲线调整权重或改不确定性加权损失震荡学习率太大检查学习率设置降低学习率或加梯度裁剪在线效果差离线在线分布不一致对比离线在线数据分布用时间切分做离线评估多样性下降热门物料主导统计推荐列表的物料分布加多样性正则或重采样推理延迟高嵌入表或图太大分阶段测延迟嵌入压缩或图采样冷启动差行为序列太短分析新用户行为长度新用户走单独召回通道6. 三条路线的融合趋势与个人实践体会最近半年我观察到三条路线有融合的趋势。OneRec 的生成式思路开始被引入 GRP 和 UniPinRec比如用生成模型来做图上的节点采样GRP 的图结构也被用来增强 OneRec 的约束解码让生成的物料更符合图上的关系约束UniPinRec 的共享嵌入思路则被用来降低 OneRec 和 GRP 的推理成本。这种融合背后的逻辑是三条路线各有优劣单独用都有明显的短板组合起来能取长补短。比如 OneRec 的多样性问题可以用 GRP 的图采样来缓解GRP 的推理延迟可以用 UniPinRec 的共享嵌入来降低UniPinRec 的表示能力上限可以用 OneRec 的生成式目标来突破。我在最近的一个项目里尝试了 OneRec 和 UniPinRec 的混合方案用 UniPinRec 的共享嵌入做底层表示用 OneRec 的生成式解码做顶层输出。实测下来推理延迟比纯 OneRec 降低了40%多样性比纯 UniPinRec 提升了15%整体点击率提升了3%左右。当然这个方案还在迭代中联合训练的稳定性还需要进一步优化。最后分享一个小技巧不管选哪条路线都建议先做小规模验证不要一上来就全量替换。统一召回排序的改动很大涉及数据、模型、工程多个环节小规模验证能帮你快速发现致命问题避免全量上线后回滚的尴尬。我一般会先用10%的流量做验证跑两周左右确认核心指标没有明显下降再逐步扩量。
阅读完成 · 觉得有帮助?