news 2026/10/26 12:49:48

统一召回与排序:OneRec、GRP、UniPinRec三条技术路线落地实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
统一召回与排序:OneRec、GRP、UniPinRec三条技术路线落地实践

召回和排序这两个环节,过去几年在推荐系统圈子里一直是分开设计、分开优化的。做召回的团队盯着召回率、覆盖率,做排序的团队盯着AUC、GAUC,两边各自汇报各自的指标,中间用一份样本和一套特征勉强对齐。但真正做过线上系统的人都知道,这种割裂带来的问题非常致命:召回阶段丢掉的物品,排序阶段再怎么优化也救不回来;排序阶段学到的偏好信号,召回阶段根本感知不到。最近一段时间,围绕"统一召回与排序"的讨论明显多了起来,OneRec、GRP、UniPinRec 这几个词频繁出现在各种技术分享里,本质上都是在回答同一个问题——能不能用一套模型、一套目标、一套特征,把召回和排序这两件事一起做掉。

这篇文章不打算停留在概念层面。我会把"统一召回与排序"这个方向拆成三条可落地的技术路线,讲清楚每条路线背后的动机、核心机制、工程实现上的关键取舍,以及我在实际搭建和调试过程中踩过的坑。无论你是刚接触推荐系统的新人,还是已经在做召回或排序优化的工程师,都能从中找到可以直接参考的思路和操作细节。

1. 为什么召回与排序的割裂到了必须解决的地步

1.1 割裂架构的三个隐性成本

大多数推荐系统沿用"召回—粗排—精排—重排"的漏斗结构,这套结构在早期确实有效,因为当时算力和数据都不足以支撑全量建模。但到了今天,这套架构的隐性成本已经高到不容忽视。

第一个成本是目标不一致。召回阶段通常用双塔模型,优化的是内积相似度,本质上是一个度量学习目标;排序阶段用交叉特征加深度网络,优化的是点击率或转化率的预估精度。两个阶段优化的目标函数不同,导致召回阶段"觉得好"的物品,排序阶段未必认同。我见过不少案例,召回 Top500 里真正被排序打高分的只有几十个,剩下四百多个纯属陪跑,白白消耗了排序算力。

第二个成本是样本与特征的重复建设。召回要建一套样本(通常是曝光点击对),排序要建另一套样本(通常是精排阶段的曝光点击对),两套样本的负采样策略、时间窗口、特征口径往往不一致。特征方面,召回侧受限于双塔结构,只能用用户侧和物品侧各自独立的特征,无法使用交叉特征;排序侧则可以用丰富的交叉特征。这种不一致导致同一个用户在不同阶段被"理解"成不同的人。

第三个成本是误差累积。召回漏掉的物品,排序永远看不到;粗排过滤掉的物品,精排永远看不到。每一层漏斗都在做不可逆的截断,上游的微小误差会在下游被放大。有研究做过统计,在典型的三层漏斗中,召回阶段的召回率每下降1个百分点,最终排序阶段的理想上限会下降3到5个百分点。

1.2 统一建模到底"统一"了什么

很多人对"统一召回与排序"的理解停留在"用一个模型同时输出召回和排序结果",这个理解太窄了。真正的统一,至少包含三个层面。

目标统一:召回和排序共享同一个优化目标,通常是基于全量物品的软max或者采样软max。这样召回阶段学到的表示,天然就是为最终排序目标服务的,不存在目标错位。

特征统一:用户特征、物品特征、上下文特征、交叉特征在同一个模型里被统一处理。召回阶段也能用上交叉特征,排序阶段也能感知到全量物品的分布。

样本统一:用同一份样本训练,避免两套样本口径不一致带来的偏差。样本统一之后,负采样的策略也需要重新设计,因为全量软max的计算成本很高,必须用采样技巧来近似。

理解了这三个层面,再看 OneRec、GRP、UniPinRec 这些方案,就会发现它们其实是在这三个层面上做不同的取舍。有的方案优先解决目标统一,有的方案优先解决工程效率,有的方案在特征统一上做得更彻底。

1.3 三条路线的划分依据

我把当前主流的统一方案划分为三条路线,划分依据是它们如何处理"全量物品打分"这个核心难题。

第一条路线是生成式统一,代表方案是 OneRec。它的核心思路是把推荐问题转化为序列生成问题,用生成模型直接生成用户可能感兴趣的物品序列,从而绕开全量物品打分的计算瓶颈。

第二条路线是图结构统一,代表方案是 GRP。它的核心思路是用图神经网络把用户和物品放在同一张图里,通过图上的消息传递同时完成召回和排序,利用图的稀疏性来降低计算量。

第三条路线是双塔增强统一,代表方案是 UniPinRec。它的核心思路是在传统双塔基础上引入交叉特征和全量软max,通过工程优化让双塔也能用上交叉信息,从而在保持工程效率的同时逼近统一建模的效果。

这三条路线没有绝对的优劣,选择哪条取决于你的业务场景、算力预算和团队技术栈。下面我逐条拆解。

2. 生成式统一路线:OneRec 的序列生成思路

2.1 把推荐当成翻译问题来做的动机

OneRec 最核心的洞察是:推荐和机器翻译在形式上高度相似。机器翻译是给定源语言序列,生成目标语言序列;推荐是给定用户历史行为序列,生成未来可能交互的物品序列。既然翻译可以用生成模型做,推荐为什么不行?

这个类比一旦成立,很多问题就迎刃而解了。全量物品打分需要遍历所有物品,计算量随物品数量线性增长;而序列生成只需要自回归地生成下一个 token,计算量取决于生成序列的长度,与物品总数无关。这就从根本上绕开了全量打分的瓶颈。

但要把这个类比落地,需要解决三个关键问题:物品怎么表示成 token、生成模型怎么训练、生成结果怎么保证是用户真正感兴趣的。

2.2 物品 token 化的具体做法

物品 token 化是 OneRec 路线的第一步,也是最容易踩坑的一步。常见做法是用向量量化(如 RQ-VAE 或残差量化)把物品的 embedding 映射成离散 token。具体来说,先用双塔或图模型学出物品的稠密向量,然后用层次化量化把向量压缩成若干层级的离散编码,每一层对应一个 token。

这里有个关键细节:量化层数和码本大小的选择。层数太少,物品区分度不够,生成出来的 token 无法唯一对应到物品;层数太多,生成难度急剧上升,模型很难学到有意义的序列模式。我的经验是,对于百万级物品库,用3到4层量化、每层码本大小256到1024比较合适。这个配置下,理论编码空间是 256^3 到 1024^4,远大于物品总数,但实际使用的编码只占很小一部分,模型需要学会只生成有效的编码组合。

另一个细节是量化损失的权重。量化过程会引入信息损失,如果量化损失权重太低,物品向量被量化后语义漂移严重,生成模型学到的 token 序列和真实物品对不上;如果权重太高,又会压制推荐主任务的优化。实践中我一般把量化损失权重设在0.1到0.3之间,并且用退火策略,训练初期权重高一些保证量化质量,后期降低权重让主任务主导。

2.3 生成模型的训练目标与解码策略

OneRec 的生成模型通常用编码器-解码器结构。编码器处理用户历史行为序列,解码器自回归生成目标物品的 token 序列。训练目标是标准的交叉熵损失,即最大化目标 token 序列的似然。

但这里有个容易被忽略的问题:训练时的 teacher forcing 和推理时的自回归解码存在曝光偏差。训练时解码器看到的是真实的历史 token,推理时看到的是自己生成的 token,一旦前面生成错了,错误会累积。缓解方法有两种:一是用 scheduled sampling,训练时逐步用模型自己的生成结果替换真实 token;二是用 beam search 解码,保留多条候选路径,最后用排序模型对候选重排。

解码策略方面,我实测下来 beam search 的宽度设在5到10比较合适。宽度太小,候选多样性不够;宽度太大,计算量上升明显,而且收益递减。另外,生成结果需要做有效性校验,因为模型可能生成不存在的 token 组合,这些组合要直接过滤掉。

2.4 生成式路线的适用边界

OneRec 路线听起来很美,但它有明确的适用边界。首先,它更适合物品库相对稳定的场景,因为物品 token 化需要离线完成,物品库频繁变动会导致 token 表频繁重建。其次,它更适合序列依赖性强的场景,比如短视频、新闻、音乐这类用户行为有明显序列模式的业务。对于物品库巨大且长尾极长的电商场景,生成式路线的效果可能不如传统方案稳定。

还有一个工程上的现实问题:生成式模型的推理延迟通常比双塔高,因为自回归解码是串行的。如果业务对延迟极其敏感(比如要求10毫秒以内返回),生成式路线需要配合蒸馏或量化才能上线。

3. 图结构统一路线:GRP 的消息传递机制

3.1 用户-物品二部图的构建要点

GRP 路线的核心是把用户和物品放在同一张二部图里,用户节点和物品节点之间的边表示交互行为。这张图同时承载了召回和排序所需的信息:召回需要的是用户和物品的全局相似性,排序需要的是用户和物品的细粒度匹配信号,两者都可以通过图上的消息传递来获取。

构图时有几个关键决策。边的类型:是只用点击边,还是把曝光未点击也作为边?我的建议是把曝光未点击作为负边加入,但要用不同的边类型区分,让模型自己学习正负边的权重差异。边的权重:交互频次、交互时长、交互时间衰减都可以作为边权重的来源,具体用哪个取决于业务。图的分区:全量图可能非常大,需要做图分区,分区策略要保证同一用户的行为尽量落在同一分区,减少跨分区通信。

3.2 消息传递如何同时服务召回和排序

图神经网络的消息传递机制天然适合统一建模。在每一层消息传递中,用户节点聚合其邻居物品的信息,物品节点聚合其邻居用户的信息。经过多层传递后,每个节点都获得了融合了多跳邻居信息的表示。

召回阶段,用用户表示和物品表示的内积做近似最近邻搜索,快速筛选候选集。排序阶段,用用户表示、物品表示以及它们之间的边特征一起输入一个打分网络,输出精细的排序分数。关键在于,这两个阶段用的是同一套节点表示,只是使用方式不同。这就实现了特征层面的统一。

更进一步,GRP 可以在消息传递过程中引入注意力机制,让模型自动学习哪些邻居更重要。这个注意力权重既可以用于召回阶段的相似度计算,也可以用于排序阶段的特征构造,进一步强化了统一性。

3.3 图采样的工程实现细节

全量图的消息传递计算量很大,必须做图采样。常见的采样策略包括邻居采样、层采样和子图采样。邻居采样是最常用的,每个节点每层采样固定数量的邻居,控制计算量。层采样则是在不同层采样不同数量的邻居,通常浅层采样多、深层采样少。

这里有个我踩过的坑:采样数量对效果的影响是非线性的。采样数量从5增加到10,效果提升明显;从10增加到20,提升就很小了;超过20之后,甚至可能因为引入噪声而下降。所以不要盲目增大采样数量,要根据实际效果做消融实验。

另一个坑是采样带来的方差。每次训练用不同的采样结果,会导致梯度估计有方差,训练不稳定。缓解方法是增大 batch size,或者用多层采样取平均。我一般会把 batch size 设得比传统模型大2到4倍,配合学习率 warmup 来稳定训练。

3.4 图结构路线的性能瓶颈与优化

GRP 路线最大的瓶颈是图存储和消息传递的工程复杂度。全量图可能有数十亿条边,存储和访问都是挑战。实践中需要用分布式图存储引擎,并且把消息传递的计算尽量放在 GPU 上。

优化方向有几个。一是图压缩,把低频边合并或剪枝,减少图的规模。二是异步训练,把图采样和模型训练解耦,采样进程和训练进程并行运行。三是混合精度,消息传递用半精度计算,关键节点表示用全精度存储。这些优化手段组合使用,可以把训练效率提升数倍。

4. 双塔增强统一路线:UniPinRec 的工程折中

4.1 双塔模型为什么难以直接用交叉特征

双塔模型的结构决定了它只能用用户侧和物品侧各自独立的特征。用户塔输入用户特征,物品塔输入物品特征,两侧在最后一层才做内积。这种结构的好处是物品向量可以离线预计算,线上只需要做近似最近邻搜索,延迟极低。但坏处是无法使用交叉特征,因为交叉特征依赖于用户和物品的同时输入。

交叉特征对排序精度的贡献是巨大的。在传统排序模型里,用户-物品交叉特征往往是最重要的一类特征。双塔模型用不了交叉特征,导致它的排序能力天然弱于交叉模型。这就是为什么很多系统要用双塔做召回、用交叉模型做排序。

4.2 UniPinRec 的交叉特征注入方案

UniPinRec 的核心思路是:在保持双塔结构的前提下,尽可能把交叉信息注入进去。具体做法有几种。

第一种是后融合。双塔各自输出表示后,不直接做内积,而是拼接后过几层全连接网络。这样虽然还是双塔结构,但最后一层网络可以学到一些交叉信息。缺点是交叉发生在最后,表达能力有限。

第二种是特征蒸馏。先用一个交叉模型(比如 DeepFM 或 DCN)学出交叉特征的重要性,然后把这种重要性蒸馏到双塔模型里。具体来说,让双塔模型的输出逼近交叉模型的输出,从而间接学到交叉信息。

第三种是双塔交互层。在双塔的中间层引入轻量的交互模块,让两侧表示在中间就发生交互。这个交互模块要设计得足够轻量,否则会破坏双塔的工程优势。

我实测下来,第二种和第三种结合使用效果最好。先用蒸馏让双塔学到交叉模型的"知识",再用轻量交互层做补充,最终效果可以逼近交叉模型的90%以上,而推理延迟只有交叉模型的几分之一。

4.3 全量软max的近似计算技巧

UniPinRec 的另一个关键是全量软max。传统双塔用采样软max训练,只从全量物品里采样一部分作为负样本。采样软max的问题是负样本分布和真实分布有偏差,导致模型学到的表示有偏。

全量软max需要计算用户对所有物品的分数,计算量随物品数量线性增长。对于百万级物品库,这个计算量在训练时是可以接受的(因为可以批量并行),但在推理时不可接受。所以实践中通常用训练时全量软max、推理时近似最近邻搜索的组合。

全量软max的计算优化有几个技巧。一是分块计算,把物品分成若干块,逐块计算分数并累积梯度,避免一次性加载所有物品向量。二是梯度检查点,用时间换空间,减少显存占用。三是混合精度,分数计算用半精度,梯度累积用全精度。这些技巧组合使用,可以让全量软max在单机多卡上跑起来。

4.4 双塔增强路线的落地性价比

从落地角度看,UniPinRec 路线是三条路线里工程改动最小、风险最低的。因为它保留了双塔的基本结构,线上服务框架不需要大改,只需要替换模型和调整训练流程。对于已经在跑双塔召回的系统,迁移成本很低。

但它的上限也相对有限。因为双塔结构本身限制了交叉特征的表达能力,无论怎么增强,都很难达到完全统一建模的效果。所以这条路线适合追求快速落地、对效果提升要求适中的场景。如果你的业务已经跑通了双塔,想在不大改架构的前提下提升召回质量,UniPinRec 路线是首选。

5. 三条路线的选型对比与实操建议

5.1 从业务场景出发的选型矩阵

三条路线没有绝对优劣,关键看业务场景。我整理了一个选型矩阵,供参考。

维度生成式统一(OneRec)图结构统一(GRP)双塔增强统一(UniPinRec)
适合物品库规模百万级以下千万级以下百万到亿级
适合序列依赖强度强中弱到中
工程改动量大很大小
推理延迟中到高中低
效果上限高高中
团队技术栈要求生成模型经验图计算经验推荐系统常规经验
冷启动支持弱中强

从表里可以看出,如果你的业务是短视频或新闻这类序列依赖强的场景,且团队有生成模型经验,OneRec 路线值得尝试。如果是社交或电商这类图结构天然存在的场景,GRP 路线更合适。如果只是想快速提升现有双塔召回的效果,UniPinRec 路线最稳妥。

5.2 训练数据与样本构造的通用原则

无论选哪条路线,训练数据和样本构造都有一些通用原则。

样本要覆盖全漏斗。不要只用精排阶段的曝光点击样本,要把召回阶段、粗排阶段的样本也纳入进来,让模型看到完整的漏斗分布。否则模型学到的分布和线上实际分布有偏差。

负采样要分层。简单随机负采样容易采到太容易区分的负样本,对模型提升有限。实践中常用的是"难负样本挖掘",即用当前模型打分较高但实际未交互的物品作为负样本。但难负样本不能太多,否则训练不稳定。我一般把难负样本比例控制在20%到40%之间。

时间窗口要合理。样本的时间窗口太短,模型学不到长期偏好;太长,又会引入过时行为。我的经验是,用户行为序列用最近30到90天,物品特征用最近7到30天,具体根据业务节奏调整。

5.3 线上服务的延迟与一致性保障

统一建模之后,线上服务架构也需要相应调整。传统架构里召回和排序是两个独立服务,统一之后可以合并成一个服务,也可以保持两个服务但共享模型。

延迟保障方面,关键是模型推理的批处理和缓存。用户侧特征和物品侧特征可以缓存,避免每次请求都重新计算。模型推理用批处理,把多个请求合并成一个 batch,提高 GPU 利用率。

一致性保障方面,关键是训练和推理的特征口径一致。训练时用的特征,推理时必须能拿到,且计算逻辑要完全一致。这一点在统一建模里尤其重要,因为召回和排序共享特征,任何一侧的口径偏差都会影响整体效果。我一般会建一套特征校验流程,定期对比训练和推理的特征分布,发现偏差及时修复。

5.4 效果评估:不要只看单一指标

统一建模的效果评估,不能只看召回率或AUC。要建立一套完整的评估体系。

离线指标:召回率、覆盖率、AUC、GAUC、NDCG。这些指标要分阶段看,召回阶段看召回率和覆盖率,排序阶段看AUC和NDCG。

在线指标:点击率、转化率、人均时长、留存率。这些是最终的业务指标,但要注意它们受多种因素影响,不能单独归因于模型改动。

一致性指标:召回结果和排序结果的重合度。统一建模的理想状态是召回 TopK 和排序 TopK 高度重合,如果重合度低,说明统一程度不够。

我一般会做 A/B 实验,实验组用统一模型,对照组用传统分离模型,观察各项指标的变化。实验周期至少两周,避免短期波动误导结论。

6. 我在实操中踩过的坑与经验总结

6.1 物品 token 化的语义漂移问题

做 OneRec 路线时,我遇到的最大的坑是物品 token 化的语义漂移。量化过程会引入信息损失,导致量化后的 token 无法准确还原物品语义。表现就是生成模型生成的 token 序列,解码回物品后,和用户真实兴趣偏差很大。

排查这个问题的过程比较曲折。一开始我以为是生成模型的问题,调了各种超参都没用。后来做了个实验,把量化前后的物品向量拿出来对比,发现量化后的向量在语义空间里发生了明显偏移,相似物品的量化编码反而不相似。这才定位到是量化环节的问题。

解决方案是调整量化损失的权重和量化层数。我把量化损失权重从0.05提高到0.2,量化层数从2层增加到3层,语义漂移明显缓解。另外,我在量化后加了一个微调步骤,用量化后的编码重新训练物品向量,让编码和语义对齐。

6.2 图采样的方差导致训练不收敛

做 GRP 路线时,图采样的方差让我吃了不少苦头。每次训练用不同的采样结果,梯度估计方差很大,loss 曲线剧烈震荡,模型迟迟不收敛。

我试过几种缓解方法。增大 batch size 有效,但显存不够。降低学习率也有效,但训练太慢。最后用的是采样结果缓存加滑动平均:把最近若干轮的采样结果缓存起来,每次训练从缓存里采样,同时对缓存做滑动平均更新。这样既降低了方差,又保持了采样的多样性。

还有一个经验是,图采样不要每层都重新采样,可以让相邻层共享采样结果。这样既减少了采样开销,又降低了方差。

6.3 全量软max的显存爆炸

做 UniPinRec 路线时,全量软max的显存占用是个大问题。百万级物品,每个物品一个向量,加上梯度,显存很快就爆了。

我用了几个技巧组合解决。一是分块计算,把物品分成若干块,逐块计算分数和梯度,每块计算完就释放中间结果。二是梯度累积,小 batch 多次前向,累积梯度后再更新。三是混合精度,分数计算用半精度,梯度用全精度。这三个技巧组合使用,显存占用降到了原来的三分之一左右。

但要注意,混合精度训练需要配合 loss scaling,否则梯度下溢会导致训练失败。我一般用动态 loss scaling,让框架自动调整缩放因子。

6.4 统一模型的线上回滚预案

统一模型上线风险比传统模型高,因为它同时影响召回和排序,一旦出问题影响面很大。所以上线前必须准备好回滚预案。

我的做法是灰度发布加双跑对比。先在小流量上灰度,同时让统一模型和传统模型双跑,对比两者的输出。如果统一模型的输出和传统模型偏差过大,或者在线指标明显下降,立即回滚。

回滚预案要提前演练,确保回滚操作能在几分钟内完成。另外,统一模型的版本管理要清晰,每个版本对应的训练数据、特征口径、超参配置都要记录在案,方便问题定位。

6.5 团队协作中的认知对齐

最后说一个非技术但很重要的坑:团队协作中的认知对齐。统一建模涉及召回和排序两个团队,如果两个团队对"统一"的理解不一致,很容易出现各做各的、最后拼不起来的情况。

我的经验是,项目启动前先开一次对齐会,把统一的三个层面(目标、特征、样本)逐条讨论清楚,明确每个层面的负责人和交付物。项目过程中定期同步进展,发现偏差及时纠正。另外,评估指标要双方共同认可,避免各看各的指标、各说各的话。

统一召回与排序是个系统工程,技术方案只是其中一部分,团队协作和工程管理同样重要。三条路线各有适用场景,选型时要结合业务实际,不要盲目追新。落地过程中要小步快跑,先在小流量验证,再逐步放大。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/26 12:49:28

Kubernetes与OpenClaw管理平台集成实践指南

1. 项目概述:当Kubernetes遇上OpenClaw管理平台 在容器编排领域摸爬滚打多年,第一次接触cloud-claw-manager这个开源管理平台时,就被它独特的架构设计所吸引。这个基于OpenClaw框架构建的平台,本质上是一个面向云原生环境的智能管…

作者头像 李华
网站建设 2026/10/26 12:49:00

交换机底层转发逻辑与VLAN/STP环路排障配置实战

交换机这东西,很多刚入行的朋友觉得它"插上电就能用",直到某天办公室里一半人断网、机柜里指示灯疯闪,才发现这台铁盒子远没看上去那么老实。玄子Share这个系列里,我一直想把这些年摸过的设备、踩过的坑整理成一份能直接…

作者头像 李华
网站建设 2026/10/26 12:47:44

登录功能测试全攻略:从用例设计到自动化实践

1. 登录测试的核心价值与挑战登录功能作为系统入口,其稳定性直接影响用户体验和系统安全。在实际项目中,我发现80%的用户流失都发生在首次登录环节。一个典型的电商平台数据显示,登录失败率每降低1%,转化率就能提升2.3%。这让我意…

作者头像 李华
网站建设 2026/10/26 12:47:42

PyTorch实现花卉图像分类:ResNet与VGG对比实践

1. 项目概述:基于卷积神经网络的花卉图像检索系统 花卉图像检索系统是计算机视觉领域一个经典而实用的应用场景。这个项目使用PyTorch框架实现了三种主流卷积神经网络模型(ResNet50、VGG16和ResNet34)对花卉图像的分类与检索功能。在实际应用…

作者头像 李华
网站建设 2026/10/26 12:47:07

大模型输出测试难?DSH-Sharp 为 .NET 生态补齐语义断言层

开头先交代一下背景。我们团队在把 DeepSeek 系列模型接入 .NET 服务之前,天真地以为最难的环节是搞定模型调用的接口封装。真正开始写测试才发现,接口调用反而是最简单的部分,难的是“怎么证明模型输出是对的”。你没法用一个 Assert.Equal…

作者头像 李华
网站建设 2026/10/26 12:47:00

AI模型训练加速:数据清洗与学习率调优实战

1. 为什么你的AI模型训练总是慢如蜗牛? 每次启动训练脚本后,那个缓慢跳动的loss值是不是让你焦虑到想砸键盘?作为经历过上百次模型训练的老手,我完全理解这种痛苦。模型收敛速度慢不仅浪费计算资源,更会严重拖累项目进…

作者头像 李华