news 2026/11/3 23:48:18

生成式召回实战:负采样与物品编码SID的工程落地

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
生成式召回实战:负采样与物品编码SID的工程落地

推荐系统这行做久了,会发现一个挺有意思的现象:每隔几年,就会有一批"老概念"被重新包装后回到台前。生成式召回就是这两年被讨论得特别多的一个方向,但很多人一上来就盯着"生成式"三个字,急着往 Transformer、Decoder、Beam Search 上套,反而把召回这件事最本质的两个环节给忽略了——负采样和物品编码。我自己的体会是,真正决定一个生成式召回系统能不能跑起来的,恰恰是这两块"脏活累活",而不是模型结构本身有多花哨。

这篇内容我想把生成式召回从头到尾捋一遍,重点放在负采样策略怎么设计、物品编码(尤其是 SID 和 tokenizer 这条线)怎么落地,以及这两者之间怎么配合。适合已经做过一段时间推荐、想往生成式方向转的同学,也适合正在评估要不要上生成式召回的团队做技术选型参考。我会尽量把每一步"为什么这么做"讲清楚,而不是只丢一堆结论。

1. 生成式召回到底在解决什么老问题

1.1 传统双塔召回的瓶颈在哪里

先说清楚背景,不然"生成式召回"这个词很容易被当成营销话术。传统召回主流是双塔结构:用户塔和物品塔各出一个向量,用内积或余弦算相似度,然后走 ANN 检索。这套东西成熟、稳定、工程化程度高,但它有几个绕不开的硬伤。

第一个硬伤是物品塔的表达能力被"独立编码"限制死了。物品塔对每个物品单独编码,物品和物品之间的交互信息、序列信息、上下文信息,很难在编码阶段就融合进去。你只能靠用户塔去"猜"用户想要什么,物品塔本身是静态的。

第二个硬伤是内积这个交互形式太弱。用户和物品的关系被强行压缩成一个标量相似度,很多复杂的、非线性的偏好模式根本表达不出来。比如"用户最近买了婴儿车,接下来大概率会看安全座椅"这种序列依赖,双塔很难建模。

第三个硬伤是召回和排序的目标割裂。召回阶段优化的是"能不能把相关物品捞出来",排序阶段优化的是"排得准不准",两者目标不一致,导致召回经常捞出一堆排序阶段根本不会用的候选。

生成式召回想解决的,就是让召回阶段本身具备更强的序列建模能力和生成能力,把"检索"变成"生成"。

1.2 生成式召回的核心思路转变

生成式召回最本质的转变,是把召回从"向量检索问题"重新定义成"序列生成问题"。具体来说,就是把每个物品映射成一串离散的 token(也就是物品编码 / SID),然后训练一个生成模型,输入用户的历史行为序列,直接自回归地生成用户下一个可能感兴趣的物品 token 序列。

这个思路的好处很直接:模型可以复用 NLP 领域已经非常成熟的序列建模能力,用户行为序列的时序依赖、长距离依赖都能被建模进去。而且生成过程本身是"条件生成",用户的历史行为就是条件,天然把上下文融合进来了。

但代价也很明显:物品必须被离散化,这就引出了物品编码这一整套工程问题;训练需要大量负样本,这就引出了负采样策略设计。这两件事做不好,模型再大也白搭。

提示:如果你的业务里物品数量在百万级以下,且用户行为序列比较短,传统双塔 + 精排的组合可能仍然是性价比最高的选择。生成式召回更适合物品规模大、序列依赖强、有充足训练资源的场景。

2. 负采样:生成式召回里最容易被低估的环节

2.1 为什么负采样在生成式召回里更关键

在传统双塔里,负采样主要影响的是对比学习的效果,采样策略不对,向量空间会塌缩或者分布偏移。但在生成式召回里,负采样的作用被放大了好几倍,原因在于生成模型的训练目标本身就是"区分正确 token 和错误 token"。

生成式召回通常用类似 next-token prediction 的目标:给定用户历史序列,预测下一个物品的 token。如果负样本全是随机采的,模型很快就能学会"只要不是历史里出现过的就是负样本"这种偷懒策略,泛化能力极差。更麻烦的是,生成式模型的输出空间是整个 token 词表,负样本的质量直接决定了模型对词表分布的建模精度。

我见过不少团队,模型结构调了半天,效果上不去,最后发现问题出在负采样上——采样分布和真实曝光分布差太远,模型学到的"负"根本不是业务意义上的"负"。

2.2 从随机负采样到难负样本挖掘

负采样的演进大致可以分几个阶段,每个阶段解决的问题不一样。

随机负采样是最基础的,从全量物品里均匀随机抽。优点是简单、无偏,缺点是绝大多数随机负样本太"容易"了,模型学不到有区分度的边界。在物品规模很大的时候,随机采到的负样本和正样本几乎不可能相似,梯度信号很弱。

曝光未点击负采样(in-batch negative 的一种变体)是从真实曝光日志里取"展示了但用户没点"的物品。这类负样本更接近真实分布,模型学到的边界更贴合业务。但它有个陷阱:曝光未点击里混着大量"用户根本没看到"的样本(比如排在很后面的),这些其实不算真正的负样本,直接拿来训练会引入噪声。

难负样本挖掘(hard negative mining)是往"和正样本相似但实际是负"的方向走。常见做法是用当前模型对候选池打分,取分数高但实际未交互的作为难负样本。这类样本梯度信号强,能显著提升模型区分能力。但难负样本用多了会导致训练不稳定,甚至让模型过拟合到某些伪负样本上。

混合采样是目前比较主流的做法:按一定比例混合随机负样本、曝光负样本和难负样本。比例怎么定,得看业务。我一般建议从 6:3:1 或者 5:3:2 开始调,难负样本占比不要超过 30%,否则训练很容易崩。

采样策略优点缺点适用阶段
随机负采样简单无偏,覆盖全词表梯度信号弱,学不到边界训练初期预热
曝光未点击贴近真实分布混入未曝光噪声训练中期
难负样本挖掘梯度强,区分度高易过拟合,训练不稳训练后期精调
混合采样兼顾覆盖与区分度比例需反复调全流程

2.3 负采样数量与训练效率的权衡

负样本数量不是越多越好。在生成式召回里,每个正样本配多少负样本,直接影响显存占用和训练速度。业界常见的做法是每个正样本配 100 到 1000 个负样本,具体取决于词表大小和 batch size。

这里有个经验公式可以参考:负样本数量大致等于词表大小的对数级别。比如词表有 10 万个 token,负样本数量在 500 到 1000 之间比较合适。太少学不动,太多边际收益递减还拖慢训练。

另外一个容易被忽略的点是负样本的时效性。物品是有生命周期的,用三个月前的曝光日志采负样本,可能采到的物品现在已经下架了。我一般建议负样本池按天滚动更新,保留最近 7 到 30 天的曝光数据,太老的直接丢弃。

注意:负采样策略一定要和评估指标对齐。如果你用 Recall@K 评估,那负样本分布要尽量贴近真实候选分布;如果用 AUC 评估,负样本分布可以更自由一些。指标和采样不一致,调参就是瞎调。

3. 物品编码:SID 与 tokenizer 的工程落地

3.1 为什么物品必须被离散化成 SID

生成式召回要求模型输出的是离散 token,所以每个物品必须映射成一个或多个 token,这个映射结果就是 SID(Semantic ID,语义 ID)。SID 的设计直接决定了生成模型的学习难度和召回效果。

最朴素的做法是给每个物品分配一个唯一的整数 ID,词表大小等于物品总数。但这样有个致命问题:物品数量动辄百万千万,词表太大,softmax 计算量爆炸,而且物品之间没有任何语义关联,模型学不到"相似物品应该有相似 token"这种先验。

所以主流做法是层次化 SID:把物品编码成多个层级的 token,比如三层,每层词表大小控制在几千到几万。这样总词表大小是各层词表之和,而不是乘积,计算量大幅下降。同时层次化结构天然带语义:第一层可能是粗粒度品类,第二层是细粒度品类,第三层是具体物品。

3.2 基于聚类的 SID 生成流程

层次化 SID 最常用的生成方式是层次聚类。具体流程大致是这样:

  1. 获取物品向量:用已有的双塔模型或者内容模型,给每个物品算一个 embedding。这个 embedding 要尽量包含语义信息,比如品类、价格带、风格等。

  2. 第一层聚类:对所有物品向量做 K-Means,聚成 K1 个簇,每个簇分配一个第一层 token。K1 一般取几千。

  3. 第二层聚类:在每个第一层簇内部再做 K-Means,聚成 K2 个簇,分配第二层 token。K2 一般也取几千。

  4. 第三层聚类:继续细分,直到每个簇内的物品数量足够少(比如几十个),或者达到预设层数。

  5. 冲突处理:如果两个物品最终 SID 完全相同,需要做去重处理,常见做法是加一层哈希或者用物品 ID 做后缀区分。

这个流程听起来简单,但实操里有几个坑。第一个坑是聚类数量怎么定。K1 太小,第一层区分度不够;K1 太大,第一层 token 太稀疏,模型学不好。我的经验是让每层词表大小和物品总数的比例保持在一个合理区间,比如物品 100 万,三层 SID,每层词表 3000 左右,那么平均每个 token 覆盖 100 万 / 3000 ≈ 333 个物品,这个粒度比较合适。

第二个坑是聚类特征的选择。如果只用协同过滤 embedding,聚出来的簇可能语义不连贯;如果只用内容特征,又丢失了行为信息。我一般建议用多模态融合的 embedding,协同信号和内容信号都带上。

3.3 tokenizer 设计中的常见误区

tokenizer 这块,很多人直接照搬 NLP 里的 BPE 或者 WordPiece,这是不对的。NLP 的 tokenizer 处理的是自然语言,词与词之间有天然的语言学边界;而物品序列没有这种边界,直接套用会导致 token 切分毫无语义。

生成式召回里的 tokenizer,本质上是"物品到 SID 的映射器",它的设计目标不是压缩,而是保持语义层次 + 控制词表规模 + 支持高效解码。所以更合理的做法是基于物品向量做量化或者聚类,而不是基于序列做子词切分。

还有一个误区是忽略解码效率。生成式召回在线上服务时,需要对每个用户生成候选,如果 SID 层数太多、每层词表太大,解码开销会很高。我见过有的方案用了五层 SID,每层词表上万,线上单次请求要几百毫秒,根本没法用。一般三层 SID、每层词表几千,是比较平衡的选择。

SID 层数每层词表总词表规模解码开销适用场景
1 层百万级百万级极高不推荐
2 层万级几万中等物品规模较小
3 层几千一万左右低主流推荐
4 层以上几千一万多低但层数多物品极多且需细粒度

3.4 SID 与负采样的联动设计

这两块不是独立的,SID 的结构会直接影响负采样的策略。如果 SID 是层次化的,那负采样也可以分层做:第一层 token 的负样本可以从全局采,第二层、第三层的负样本可以在对应父节点的兄弟节点里采。这样采出来的负样本天然带层次语义,模型学到的边界更合理。

举个例子,假设某个物品的 SID 是 [12, 345, 6789],那第一层负样本可以从所有第一层 token 里采,第二层负样本可以从第一层为 12 的其他第二层 token 里采,第三层负样本可以从第一层 12、第二层 345 的其他第三层 token 里采。这种"同父异母"的负样本,比全局随机负样本难得多,梯度信号也强得多。

我实测下来,分层负采样相比全局随机负采样,在 Recall@100 上能提升 3 到 5 个百分点,而且训练收敛更快。代价是实现复杂度高一些,需要维护 SID 的树形结构。

4. 从训练到线上:生成式召回的完整链路

4.1 训练数据的组织方式

生成式召回的训练数据,本质上是"用户行为序列 + 下一个物品 SID"的样本对。组织方式上有几个关键决策。

第一个决策是序列长度。太短,建模不了长距离依赖;太长,训练慢且显存吃紧。业界常见的是取最近 50 到 200 个行为。我一般建议从 100 开始,根据业务的行为密度调整。行为密集的业务(比如短视频)可以取长一点,行为稀疏的业务(比如大家电)取短一点。

第二个决策是序列的截断和填充策略。截断一般取最近的,填充用 padding token。这里有个细节:padding token 不能参与 loss 计算,否则模型会学到"预测 padding"这种无意义的目标。

第三个决策是样本的时间切分。训练集、验证集、测试集必须按时间切分,不能随机切。因为用户行为有时序性,随机切会导致信息泄漏,离线指标虚高。我一般按 8:1:1 的时间比例切,最近 10% 的数据做测试。

4.2 模型结构与解码策略

模型结构上,主流是 Encoder-Decoder 或者 Decoder-only。Encoder 处理用户历史序列,Decoder 自回归生成 SID。规模上,几亿到几十亿参数比较常见,再大就要考虑推理成本了。

解码策略是线上效果的关键。训练时用 teacher forcing,推理时用自回归生成。常见解码方式有贪心解码、Beam Search、Top-K 采样。贪心解码快但多样性差,Beam Search 效果好但慢,Top-K 采样介于两者之间。

我的经验是线上用 Beam Search,beam size 取 3 到 5,再大收益递减且延迟上升。同时要加长度惩罚,避免模型生成过短的 SID 序列(层数不足会导致无效物品)。

提示:解码时一定要做合法性校验。生成的 SID 可能对应不到任何真实物品(因为聚类时可能有空洞),这类无效 SID 要直接过滤掉,否则会污染候选集。

4.3 线上服务的工程挑战

生成式召回上线,工程上的挑战比离线训练大得多。主要难点有三个。

延迟。自回归生成是串行的,每生成一个 token 都要过一次模型,延迟天然比双塔的 ANN 检索高。优化手段包括:模型量化、KV Cache 复用、批量推理、限制 beam size 和生成长度。我见过的最优实践能把单次请求压到 20 毫秒以内,但需要不少工程投入。

候选去重。生成式召回可能对同一个用户生成重复物品,需要在解码阶段做去重,或者生成后统一去重。去重逻辑要高效,否则会成为新的瓶颈。

与现有召回通道的融合。生成式召回一般不会完全替代双塔,而是作为一路补充通道。多路召回的结果需要统一打分、截断,这里涉及到分数归一化的问题。生成式召回的分数(log 概率)和双塔的相似度分数不在一个量纲上,需要做校准。

4.4 效果评估与迭代节奏

评估生成式召回,离线指标主要看 Recall@K、NDCG@K,以及生成的有效率(生成结果中能对应到真实物品的比例)。线上则看 CTR、转化率、人均曝光物品数等。

迭代节奏上,我建议先跑通链路,再优化效果。很多团队一上来就追求 SOTA,结果链路都没打通,调参无从谈起。合理的节奏是:第一版用最简单的随机负采样 + 两层 SID,把训练和线上服务跑通;第二版加难负样本和三层 SID;第三版再做模型结构优化和工程加速。

5. 几个实操中反复踩到的坑

5.1 SID 冲突导致的召回空洞

聚类生成的 SID 会有冲突,两个不同物品映射到同一个 SID。如果不处理,模型生成这个 SID 时,你不知道该返回哪个物品,召回就会出现"空洞"或者返回错误物品。

处理方式有两种:一是聚类后做去重,冲突的物品重新分配到相邻簇;二是在 SID 后面加一层区分位。我倾向于第一种,因为加区分位会让 SID 层数变多,解码开销上升。去重时要注意保持簇的语义一致性,不能随便塞。

5.2 负样本分布偏移引发的指标虚高

离线评估时,如果负样本是从曝光日志里采的,而线上候选分布和曝光分布不一致,离线指标会虚高。我踩过这个坑:离线 Recall@100 到了 0.6,上线后实际召回率只有 0.3 出头。

解决办法是离线评估时用真实候选分布做负样本,或者至少做一次线上小流量 AB 验证,别完全信离线指标。另外,离线评估的负样本池要定期更新,别用几个月前的老数据。

5.3 解码阶段的重复生成问题

自回归生成有个经典问题:模型容易陷入重复循环,生成一串相同的 token。在生成式召回里,这会导致同一个物品被反复生成,浪费解码预算。

缓解手段包括:在解码时加 repetition penalty,对已经生成过的 token 降权;或者在训练时加入多样性正则,鼓励模型生成不同的 SID。我一般两个都用,repetition penalty 系数取 1.1 到 1.2 之间比较合适,太大反而会影响正常生成。

5.4 冷启动物品的编码难题

新物品没有行为数据,聚类时很难分配到合适的 SID。如果强行分配,可能落到一个语义不相关的簇里,导致召回效果差。

处理方式是用内容特征给冷启动物品做编码,先基于内容相似度分配一个临时 SID,等积累了一定行为数据后再重新聚类。另外,可以在 SID 里预留一部分"新物品 token",专门给冷启动物品用,等它们成熟后再迁移到常规 SID。

6. 我对生成式召回落地节奏的一点看法

做了几个生成式召回的项目之后,我最大的体会是:这东西的难点不在模型,而在数据和工程。模型结构网上有一堆开源实现,抄过来就能跑;但 SID 怎么设计、负样本怎么采、线上怎么加速,这些没有标准答案,得根据业务一点点磨。

如果让我给一个落地路线,我会这么排:先用现有双塔的 embedding 做层次聚类,生成三层 SID,把链路跑通;然后用混合负采样训练一个中等规模的生成模型,验证离线指标;接着做线上小流量,重点看延迟和候选质量;最后再考虑模型扩容和工程优化。整个过程快的话两三个月,慢的话半年,别指望一蹴而就。

另外,生成式召回和传统召回不是替代关系,而是互补关系。双塔在覆盖率和稳定性上仍然有优势,生成式召回在序列建模和个性化上更强。多路融合才是正解,别想着用一个模型解决所有问题。

最后分享一个我踩过的坑:别在 SID 设计还没稳定的时候就开始训大模型。SID 一变,之前训的模型全部作废,浪费的时间和算力非常可观。一定要先把 SID 方案定下来,跑几轮小模型验证,确认没问题了再上大模型。这个顺序搞反了,返工成本极高。

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

12种数据可视化图表全解析:从基础到高级应用

1. 数据可视化图谱全解析:从基础图表到高级呈现刚入行数据分析那会儿,我最头疼的就是明明得出了重要结论,却总被老板说"看不懂你的数据"。直到掌握了这些可视化"武器库",才真正体会到什么叫"让数据自己说…

作者头像 李华
网站建设 2026/11/3 23:45:50

SDD规格驱动开发入门:从读不懂到落地实践

1. 为什么SDD让不少程序员读起来像天书第一次接触SDD这个词,很多人脑子里蹦出来的第一反应是“这不就是写文档吗”。我当初也是这么想的,直到被一个真实项目按在地上摩擦之后,才明白SDD和“写文档”之间差了十万八千里。SDD,全称S…

作者头像 李华
网站建设 2026/11/3 23:45:21

LPDDR4/LPDDR4X 规格书精读:双通道、电源轨与时序训练

简介:面向硬件工程师、嵌入式开发者与移动存储选型人员,这份镁光MT53D规格书围绕LPDDR4/LPDDR4X统一产品展开,可用于核对电气参数、时序预算和封装设计,理解低功耗移动内存的性能边界。压缩包仅含1个PDF文件,大小9.67M…

作者头像 李华
网站建设 2026/11/3 23:43:54

WSL环境下高效安装与优化OpenClaw命令行工具

1. 项目概述OpenClaw作为一款开源的命令行工具,在开发者社区中因其高效的文件处理能力而备受推崇。对于Windows平台用户而言,通过WSL(Windows Subsystem for Linux)环境安装OpenClaw,既能保留Windows系统的易用性&…

作者头像 李华
网站建设 2026/11/3 23:41:10

运维转行云原生工程师:技能迁移与学习路线

1. 运维转行背景与痛点分析从事Linux运维工作三年后,我最终选择了裸辞转行。这不是一时冲动,而是经过长期思考后的决定。作为过来人,我深知运维岗位的酸甜苦辣。下面我将详细剖析促使我做出这个决定的关键因素,相信很多同行都能从…

作者头像 李华
网站建设 2026/11/3 23:38:44

Tessent Scan与ATPG实战指南:从扫描链构建到UDFM故障建模

简介:本资源是Mentor Graphics官方发布的Tessent Scan and ATPG用户手册(2017.3版),面向IC设计工程师、可测性设计(DFT)工程师及高校VLSI测试方向研究者,聚焦自动测试向量生成(ATPG&…

作者头像 李华