生成式推荐 GR:它到底在替代什么,又没替代什么
“生成式推荐” 最近一年是推荐系统里出现频率最高的词之一,但它在不同人嘴里其实指代的是完全不同的东西。一篇讲 LLM 接推荐的论文叫它 “生成式推荐”,一篇讲 RQ - VAE 做 semantic ID 的工作也叫它 “生成式推荐”,一个把召回 - 排序 - 重排合成一个 encoder-decoder 的工业系统也叫它 “生成式推荐”。
但这三件事在工程意义上几乎没有交集。
把它们混在一起讨论,就会出现两种很常见但都不太严谨的判断:
- 一种是 “GR 还只是噱头,工业用不上”
- 另一种是 “cascade 范式要被全面颠覆了”
这两种判断都假设 “GR” 是一个东西。但只要稍微拆一下就会发现:semantic ID 已经在多家厂上线、HSTU 在 Meta 上线、OneRec 在快手上线(至少 paper 是这么说的),与此同时大多数 LLM-as-Recommender 类工作的工业落地证据仍然非常少。这显然不是 “GR 是不是噱头” 这种 0 / 1 问题能描述清楚的。
所以本文真正想讨论的,不是 “GR 是不是未来”,而是这样一组更具体的问题:当 cascade(召回 - 粗排 - 精排 - 重排)已经支撑了十几年的工业推荐系统之后,GR 究竟在挑战哪一条假设?它替代了什么、又没替代什么?哪些已经被工业验证、哪些还停留在论文层面?
为了避免后面分章节的细节淹没主线,先把全文的主张提前讲一句:GR 不是 cascade 的全面替代,而是给 cascade 的每一环都打开了一扇 “用生成方式重新解题” 的门。但每扇门后面的工业难度差别极大,需要分层去看,不能一概而论。
Cascade 范式的三个隐含假设
要理解 GR 在挑战什么,先要把 cascade 范式的隐含假设拆清楚。cascade 范式之所以工作得很好,背后至少有三个长期成立的隐含假设。
假设 A:item 是离散原子
cascade 系统里,每个 item 用 hash ID + embedding 表征,item 之间的语义关系完全靠协同信号慢慢学。这件事在过去十几年是 work 的,但前提是:
- 行为信号足够稠密,每个 item 都能积累足够的共现
- item 词表增长速度可控,embedding table 撑得住
- 长尾不重要、新 item 占比不高,或者冷启可以靠 side feature 兜底
这三个前提,在大体量、UGC 驱动的现代内容平台上其实都开始动摇。每天新增的 item 数量、长尾占比、跨域迁移诉求,都让 hash ID 这套体系越来越吃力。
假设 B:每一步可以独立打分
这正是上一篇文章《个性化排序公式:从个性化精排到个性化混排再到全局重排》讲的:第一层做 pointwise \(s(u,i,x)\),第二层做混排,第三层做 listwise / Slate。这个假设其实包含两个层面:
- B1:每个 item 可以独立打分(pointwise)—— 给定 \((u, i)\),模型单独给出一个分数,不依赖列表里其它 item
- B2:多步级联能近似全局最优 —— 召回、精排、重排分层处理,假设” 局部最优累加起来≈全局最优”
这种分层之所以成立,是因为 cascade 默认局部最优能近似全局最优。
但列表内 item-item 相互作用不可忽略 —— 疲劳、互补、替代、位置依赖 —— 这个假设就会被打破。于是 listwise re-ranking、Generator-Evaluator、Slate optimization 这些方法被迫从” 后处理工具” 变成” 一等公民”。
假设 C:推荐场景不存在显著的 scaling law
这是过去很长一段时间不愿意承认、但又一直接受的事实:DLRM 风格的模型在参数维度上的 scaling 早就饱和了。
Meta 在 2022 年的 Understanding Scaling Laws for Recommendation Models (Ardalani et al., arXiv:2208.08489) 里第一次系统量化了这件事 ——DLRM 模型质量在数据和 compute 维度上仍然遵循 power law + constant 的形式,但参数维度的 scaling 已经 “out of steam”,继续加大参数带来的边际收益迅速消失。HSTU 论文在自己的 baseline 实验里又一次展示了同样的现象:传统 DLRM 的 quality-compute 曲线很快进入平台期,而 HSTU 的曲线则在三个数量级 compute 上持续遵循 power law。
这也正是推荐模型长期停留在亿级参数尺度的根本原因 —— 不是不想加大,而是加大没有收益。背后的微妙之处在于:不是 “推荐数据不够多”,而是 “传统 DLRM 架构在大规模行为序列上的表达能力被自身设计限制住了”。
GR 真正挑战的,恰好就是这三条假设:
| 假设 | cascade 的预设 | GR 的挑战方式 |
|---|---|---|
| A. item 是离散原子 | hash ID + emb,无结构 | semantic ID(RQ - VAE),层级化 token |
| B. 每一步可以独立打分 | 召回→排序→重排级联 | HSTU 挑战 B1(序列建模替代 pointwise);OneRec 挑战 B2(端到端生成整张列表) |
| C. 没有 scaling law | DLRM 加大未必更好 | HSTU 在三个数量级 compute 上验证 power-law |
这三条假设不是同时被挑战的,对应的 GR 工作也不是同一类。后面我们会看到,semantic ID 的工业证据已经相当充分;HSTU 挑战了 B1 和 C、有 Meta 的真实上线案例;而” 端到端生成整张列表”(挑战 B2)的公开工业证据主要来自快手 OneRec 技术谱系,跨公司独立验证仍然有限。这三件事不是一回事。
GR 将推荐重述成 “序列生成”
GR 的核心范式可以先粗略写成一句话:把推荐这件事,从 “给候选 item 打分排序” 重新表述成 “在用户行为序列上做生成式预测”。
但更严谨地说,GR 至少有广义和狭义两层:
- 广义 GR:把推荐从独立的 \((u,i)\) 判别式打分,改写成用户行为序列上的 next-action / sequential transduction。HSTU 属于这一层,它不一定生成 item token。
- 狭义 GR:进一步让模型自回归生成 item token / semantic ID,再映射回真实 item。TIGER、OneRec 属于这一层。
如果写成狭义 item-token 生成形式,可以表示为:
\[ p(i_t \mid i_{<t}, u) = f_\theta\big(\text{tokenize}(i_{<t}),\, u\big) \]
逐符号定义:
- \(i_t\):第 \(t\) 个待生成的 item(也就是 “推荐的下一个内容”)
- \(i_{<t}\):用户的历史交互序列(往往是按时间排好的 item 列表)
- \(\text{tokenize}(\cdot)\):item tokenizer,把单个 item 映射成若干个离散 token
- \(u\):用户侧信息(可以是用户 ID、画像、上下文等)
- \(f_\theta\):自回归生成模型或序列预测模型(TIGER / OneRec 直接生成 item token;HSTU 则更接近广义的 next-action 序列预测)
通俗一点说,传统 cascade 的视角是:
“给我一堆候选 item,我给每个 item 打分,然后排序输出。”
狭义 GR 的视角则是:
“给我用户过去的行为序列,我直接生成下一个 item(或下一段 item 序列)。”
广义 GR 和传统 cascade 在数学形式上已经不一样;狭义 GR 在工程实现上差异更大。下面这张对照表是全文的骨架:
| 维度 | 判别式 cascade | 生成式推荐 GR(典型形态) |
|---|---|---|
| item 表征 | hash ID + dense emb | semantic ID(狭义 GR)/ action token(广义 GR) |
| 单次决策对象 | 单 \((u, i)\) 的 score | 下一个 action / token |
| 列表生成方式 | 召回 → 排序 → 重排级联 | 自回归 decode(可一次性生成整段) |
| 训练目标 | 多目标加权 loss | next-token cross-entropy(+ 后续 reward 对齐) |
| Scaling Law | 经验上较弱 | HSTU 在 GPT-3 量级 compute 上验证存在 |
| 推理形态 | 矩阵乘 + ANN 检索 | 自回归 decode + beam search |
| 冷启动 | 依赖 side feature | semantic ID 自带语义层级 |
这里需要做一个边界说明,避免被字面意思误导:
- GR ≠ “把 LLM 接到推荐里”。LLM-as-Recommender 只是 GR 的一种形态,HSTU 这种从推荐数据从头训的工作甚至不依赖通用 LLM
- GR ≠ “端到端推翻 cascade”。即使是 OneRec 这种端到端 GR,也仍然保留了业务级混排和约束兜底等机制
- GR ≠ “一定要用 semantic ID”。HSTU 的官方实现里大部分还是 hash 体系,它挑战的是假设 B 和 C,不挑战假设 A
也就是说,GR 是一个范式集合,不是一个单一架构。后面三大技术支柱分别对应这个范式里三条独立但相互配合的技术线。
三大关键问题
GR 要工业落地,本质上需要解决三件事,它们恰好对应 GR 范式的三个核心环节:
- 怎么把 item 表征成模型能生成的 token?(Item Tokenization)—— 对应” item 表征” 环节
- 用什么架构来做这个序列生成?(生成式架构)—— 对应” 序列建模” 环节
- decode 出来的 token 序列,怎么对应回真实存在的 item?(解码与推理)—— 对应” token 回落” 环节
这三件事各自有自己的成熟方法、代表工作、落地难度,必须分开看,不能混在一起评价 GR 是否成熟。这也是为什么前面说” semantic ID 已经工业落地、HSTU 已上线、但端到端 GR 的独立验证仍然有限”—— 三个环节的成熟度完全不同。
Item Tokenization:semantic ID 与 RQ - VAE
核心问题:为什么 hash ID 撑不起 GR?
hash ID 的根本问题是相邻 ID 之间没有任何语义关系。在判别式 cascade 里这没问题 —— 反正 embedding 是查出来的,ID 本身只是一个查询索引,相邻 ID 长得像还是不像无所谓。
但到了 GR 范式里,模型要做的事情是 “生成 ID”。这就要求 ID 空间本身有结构:相似 item 的 ID 应该相似、模型才能从 “看过 A” 推断出 “可能也喜欢和 A 相似的 B”。hash ID 天然不具备这个性质,所以必须替换掉。
RQ - VAE 原理
Residual-Quantized VAE(RQ - VAE,残差量化变分自编码器)是目前 GR 里最主流的 item tokenizer。原理可以分成两步。
第一步:训一个 content encoder \(E\)
它接受 item 的内容信息(文本描述、图像、行为统计、类目等),输出一个 dense embedding:
\[ z = E(i) \]
第二步:把 \(z\) 残差量化成 \(L\) 个 codebook 索引
\[ \begin{aligned} r_0 &= z \\ c_l &= \arg\min_k \big\| r_{l-1} - e_k^{(l)} \big\| \quad l = 1, \dots, L \\ r_l &= r_{l-1} - e_{c_l}^{(l)} \end{aligned} \]
逐符号定义:
- \(r_l\):第 \(l\) 层的残差向量
- \(e_k^{(l)}\):第 \(l\) 个 codebook 中的第 \(k\) 个向量(每个 codebook 都是一个可学习的向量字典)
- \(c_l\):第 \(l\) 层匹配到的 codebook 索引
- \(L\):codebook 层数,工业实现里通常 3-4 层
每个 item 最终被表示成一个 token 元组 \((c_1, c_2, \dots, c_L)\),称为这个 item 的 semantic ID。
整个量化过程是” 用 codebook 一层一层逼近 \(z\)“的贪心过程。每一步都在做同一件事:”\(z\) 还有多少没编码到?拿当前这一层的 codebook 找一个最接近的 code 来补上”。展开来看:
- 初始化:\(r_0 = z\),含义是” 我还什么都没编码,整个 \(z\) 都待编码”。
- 第 1 层:在 codebook 1 里挑一个 code \(e_{c_1}^{(1)}\) 使它距离 \(r_0\) 最近,\(c_1 = \arg\min_k \|z - e_k^{(1)}\|\)。然后算” 还没编到的部分”:\(r_1 = z - e_{c_1}^{(1)}\)。
- 第 2 层:第 1 层已经把 \(e_{c_1}^{(1)}\) 这块” 用掉” 了,剩下的 \(r_1\) 还要继续逼近。所以第 2 层在 codebook 2 里挑离 \(r_1\) 最近的 code:\(c_2 = \arg\min_k \|r_1 - e_k^{(2)}\|\),新残差 \(r_2 = r_1 - e_{c_2}^{(2)}\)。
- 第 \(L\) 层:以此类推,每层” 领取” 前一层留下的残差。
走完 \(L\) 层后,把所有命中的 code 加起来,就近似还原了 \(z\):
\[ z \approx \sum_{l=1}^L e_{c_l}^{(l)} \]
也就是说,semantic ID \((c_1, \dots, c_L)\) 本质上就是一组离散索引,告诉你” 怎么用 \(L\) 个 codebook 里的向量把 \(z\) 重新组装出来”。重建越接近 \(z\),semantic ID 就越能保留 \(z\) 里的语义信息。
下面是一个简单的 k=3, L=3例子
- \(z = (1.0,\ 0.8)\)
- codebook 1 = \(\{(1.0,\ 1.0),\ (-1.0,\ 0.0),\ (0.0,\ -1.0)\}\)
- codebook 2 = \(\{(0.1,\ -0.1),\ (-0.1,\ 0.1),\ (0.2,\ 0.0)\}\)
- codebook 3 = \(\{(0.05,\ -0.05),\ (-0.05,\ 0.0),\ (0.0,\ 0.05)\}\)
semantic ID 构建过程如下
- 第 1 层:\(r_0 = (1.0,\ 0.8)\)。三个候选 code 离 \(r_0\) 的距离分别约 \(0.20,\ 2.15,\ 2.06\),最近的是第一个,所以 \(c_1 = 1\)。残差 \(r_1 = (1.0,\ 0.8) - (1.0,\ 1.0) = (0.0,\ -0.2)\)。
- 第 2 层:\(r_1 = (0.0,\ -0.2)\)。三个 code 距离分别约 \(0.14,\ 0.32,\ 0.28\),最近的是第一个,所以 \(c_2 = 1\)。残差 \(r_2 = (0.0,\ -0.2) - (0.1,\ -0.1) = (-0.1,\ -0.1)\)。
- 第 3 层:\(r_2 = (-0.1,\ -0.1)\)。三个 code 距离分别约 \(0.16,\ 0.11,\ 0.18\),最近的是第二个,所以 \(c_3 = 2\)。
最终 semantic ID 为 \((1,\ 1,\ 2)\)。重建:
\[ \hat{z} = (1.0,\ 1.0) + (0.1,\ -0.1) + (-0.05,\ 0.0) = (1.05,\ 0.9) \]
和真实 \(z = (1.0,\ 0.8)\) 的重建误差 \(\|z - \hat{z}\| \approx 0.11\)—— 层数越多、codebook 越大,重建越接近 \(z\),semantic ID 编码的信息越精细。
关于这个过程有几个关键点
- 贪心量化:每一步只看” 这一层选哪个 code 最近”,并不联合考虑后续层的选择。理论上联合优化能得到更精确的重建,但组合空间是 \(K^L\),不可行;贪心方案虽然不是全局最优,但训练和推理都是 \(O(L \cdot K)\),工程上才划得来。
- 量化是有损的:每一层都会留下 \(\|r_l - e_{c_l}^{(l)}\|\) 的残差。\(L\) 越大、\(K\) 越大,重建越精确,但 token 序列也越长、解码越慢 —— 这是 RQ - VAE 工程参数的根本 trade-off。
通俗一点说:就像把一本书先打粗类(“小说”),再在粗类内部打中类(“推理小说”),再在中类内部打细类(“本格推理”)。每一层都用一个小词表去刻画一个特定粒度的语义。相邻语义的 item 在前缀 token 上就会重合,模型自然就学到了” 相似 item 的 ID 也相似” 的结构。
为什么是” 残差 + 多层”,而不是直接一个大 codebook
这里有个很自然的疑问:如果想要 \(K^L\) 个不同的 ID,为什么不直接用一个大小为 \(K^L\) 的 codebook,做一次量化就好?
答案在于结构和泛化。一个大小为 \(K^L\) 的单层 codebook 需要学 \(K^L\) 个独立向量,每个 item 只命中其中一个,相邻 ID 之间没有任何关系 —— 这本质上又退化回了 hash ID。
RQ - VAE 不一样:每一层只学 \(K\) 个向量,总参数量是 \(L \cdot K\),但通过组合得到 \(K^L\) 个 semantic ID。更重要的是,第 \(l\) 层只负责编码前 \(l-1\) 层没编码到的信息 —— 这是” 残差” 二字的全部含义。也正因为这种递进结构,前缀 token 才天然带粗粒度语义。
怎么训练
RQ - VAE 是 encoder + \(L\) 个 codebook + decoder 一起端到端训的。这里 decoder 重建的是 item 的连续表征 \(z\)(或由 \(z\) 对应的 item feature representation),loss 由三部分组成:
\[ \mathcal {L}_{\text {RQ - VAE}} = \underbrace {\|z - \hat {z}\|^2}_{\text {重建}} + \underbrace {\sum_l \|\text {sg}(r_{l-1}) - e_{c_l}^{(l)}\|^2}_{\text {codebook 学习}} + \underbrace {\beta \sum_l \|r_{l-1} - \text {sg}(e_{c_l}^{(l)})\|^2}_{\text {commitment}} \]
- \(\hat{z}\):decoder 用量化后的 \(\sum_l e_{c_l}^{(l)}\) 重建出的 item 表征
- \(\text{sg}(\cdot)\):stop-gradient,阻断梯度回传
- \(\beta\):commitment 权重,VQ - VAE 默认 0.25
通俗解释:
- 重建 loss 让整个 codebook 组合能还原 item 表征
- codebook 学习 loss 让每个 codebook 向量慢慢靠近实际命中它的残差均值
- commitment loss 反过来约束 encoder 输出别离 codebook 太远
量化操作 \(\arg\min\) 是离散的、不可导,工程上用 straight-through estimator(STE) 解决:前向用量化值,反向时梯度直接绕过量化器传给 encoder。这是从 VQ - VAE 沿用的标准技巧。
codebook 里的向量从哪来
\(L\) 个 codebook 不是预先定好的字典,而是和 encoder / decoder 一起端到端学出来的可训练参数。每个 codebook 的学习过程在直觉上等价于在残差空间里做 K-means 聚类 ——\(K\) 个 code 慢慢演化成”\(K\) 个常见残差的聚类中心”。具体可以用上面 loss 里 \(\sum_l \|\text{sg}(r_l) - e_{c_l}^{(l)}\|^2\) 这一项直接做梯度更新,也可以用 EMA 把 code 维护成” 最近一段时间命中它的所有残差的均值”(VQ - VAE 论文里更推荐后者,更稳)。
训练完之后 codebook 一般被冻结,所有 item 都用这套固定 codebook 量化。但工业上要注意:随着 item 分布漂移、新类目出现,原 codebook 的量化质量会逐渐下降 —— 需要周 / 月级定期重训 RQ - VAE,重训后所有 item 的 semantic ID 也要全局重算,这是一个不可忽视的工程成本。
工程参数的常见取值
工业落地里有几个相对收敛的经验值:
| 参数 | 常见取值 | 说明 |
|---|---|---|
| codebook 大小 \(K\) | 256(或 512) | 太小表达力不够、太大容易 collapse |
| 层数 \(L\) | 3-4 | TIGER 用 4 层 |
| 有效词表 \(K^L\) | \(\sim 10^9\) 量级 | 足够覆盖百亿级 item 库 |
| commitment 权重 \(\beta\) | 0.25 | VQ - VAE 默认 |
| codebook 向量维度 | 32-128 | 由 content encoder 输出维度决定 |
也就是说,一个典型配置(\(K=256, L=4\))能产生约 43 亿个不同的 semantic ID,远超一般推荐系统的 item 规模。
工业落地最大的坑:codebook collapse
这是 RQ - VAE 实际部署里最常踩、最少被 paper 讨论的问题。
现象:训练若干轮后,几个 codebook 向量被反复命中,其余的几乎没被用过。比如 256 个 code 里实际活跃的只剩 30 个。这等价于把有效词表从 \(K^L\) 砍到 \(30^L\),表达力急剧下降,semantic ID 的层级结构也跟着塌掉。
根本原因:\(\arg\min\) 是赢者通吃。一旦某个 code 在初期被多命中几次,它的更新方向就会向命中它的那部分 item 的平均向量偏移,下一轮就更容易被命中,形成正反馈。
常见缓解办法:
- codebook reset:定期把长时间未命中的 code 替换成” 最难被解释的残差向量”(reservoir sampling)
- EMA 更新:用 exponential moving average 平滑 codebook 学习,避免被少数 batch 主导
- K-means 初始化:用训练集 residual 的 K-means 中心初始化 codebook,避免冷启偏差
- entropy regularization:在 loss 里加一项鼓励 code 命中分布的熵
这些办法在原始 RQ - VAE 论文和后续工作里都有提到,但实际配比和触发条件高度依赖具体业务的 item 分布,往往要在线上反复调。
代表性工作:TIGER
TIGER (Rajput et al., NeurIPS 2023, arXiv:2305.05065) 是这套范式最早、也最有代表性的工作。它做了三件事:
- 用 RQ - VAE 给每个 item 生成 semantic ID
- 用一个 T5 风格的自回归 transformer 学 “给定历史行为序列,生成下一个 item 的 semantic ID”
- 推理时用 beam search 生成候选 semantic ID,再映射回真实 item
TIGER 真正的范式级贡献,不是某个具体数字,而是它证明了一件事:
transformer memory 本身可以充当 semantic index—— 不需要单独的 ANN 索引,模型参数本身就承担了召回任务。
这件事在传统 cascade 视角下几乎是不可想象的:召回侧十几年来都是 “embedding + ANN” 这套范式,TIGER 第一次把它整个换成 “生成式 decoding”。
TIGER 的工程细节如下:
- Content encoder:sentence-T5,把 item 文本描述 encode 成 768 维向量
- 再投影到 32 维空间做 RQ
- \(K = 256\),\(L = 4\)
- 为了避免不同 item 量化到完全相同的 semantic ID(hash 冲突),TIGER 给每个 ID 元组多加了一个 disambiguating token(实际变成 5 个 token)
最后这个细节其实很重要:即使有 \(K^L \approx 4 \times 10^9\) 的有效词表,仍然会有不同 item 量化到同一个 ID,需要额外 token 区分。这也是为什么 paper 里很多 semantic ID 实际是 4-5 个 token,而不是干净的 4 个 —— 这种” 补丁” 在工业实现里是常态。
局限性
semantic ID 不是万能的,它的几个工程边界要看清楚:
- 词表大小 vs 表达力的 trade-off:codebook 层数 \(L\) 和每层大小 \(K\) 决定有效词表是 \(K^L\)。\(L\) 太小表达力不够、\(L\) 太大 token 序列太长 decode 慢
- 强依赖 content encoder 的质量:行为信号弱、内容信号也弱的 item(比如纯 ID 型短内容)依然冷启
- codebook 漂移:模型上线后,新 item 的 semantic ID 怎么分配?是否要定期重训 codebook?这些是不被 paper 讨论但工业必踩的坑
最后,RQ - VAE 不是 GR 发明的,它在图像(VQ - VAE)和语音里已经成熟多年。它解决的 “离散 item 没有结构”,是 TIGER / OneRec 这类 “生成 item token” 路线能成立的前提。HSTU 这类路线的 scaling law 与 semantic ID 相对正交;但对需要自回归生成 item 的路线来说,没有 semantic ID,后面的 constrained decoding、transformer-as-index 和端到端 slate generation 都很难成立。此外,即使一个团队不打算切完整的 GR,先把 semantic ID 当作 side feature 注入到现有 cascade 里,也已经能拿到冷启动和长尾上的收益
生成式架构的三条路线
GR 的” 架构” 这一支柱目前明确分成三条路线。它们形式上都叫” 生成式”,但解决的根本不是同一个问题,可落地性也相差极大。下面按工业可落地性从高到低依次介绍。
路线一:利用推荐数据训练一个生成式基础模型
代表工作是 Meta HSTU (arXiv:2402.17152, “Actions Speak Louder than Words”)。主要做的事情是:把 DLRM 时代的 “稀疏特征 + 多塔打分” 重新表述成 “用户行为序列上的序列建模”,然后用一个为推荐场景定制的 transformer 变体去把它做大。
先澄清一个容易误解的点:HSTU 里的 “生成式”,不是说它像 LLM 一样生成自然语言,也不是说它一定要生成 RQ - VAE semantic ID。它做的是更底层的重述:把用户历史行为看成一串 action token,模型根据过去的 action 序列去预测未来 action。这里的 action 可以包含 item ID、action type、timestamp、场景、设备、上下文特征等高基数稀疏信息。
也就是说,传统 DLRM / ranker 的输入更像一张 “当前请求的特征表”:
\[ s(u, i, x) = f_\theta(\text{user features}, \text{item features}, \text{context}) \]
HSTU 的输入则更像一条按时间展开的行为流:
\[ x_t = \mathrm{Embed}(i_t, a_t, c_t, \Delta t_t, \dots) \]
逐符号定义:
- \(i_t\):第 \(t\) 次交互的 item
- \(a_t\):交互动作,例如曝光、点击、完播、点赞、购买
- \(c_t\):当时的上下文,例如入口、设备、地域、场景
- \(\Delta t_t\):时间间隔或时间位置特征
- \(x_t\):把这些稀疏特征融合后的第 \(t\) 个 action 表征
训练目标也随之改变。传统 ranker 更常见的是 “给当前候选 item 打一个分”,HSTU 则是:
\[ p(x_{t+1} \mid x_{\le t}) = f_\theta(x_1, x_2, \dots, x_t) \]
通俗一点说,它不是只问 “这个用户现在会不会点这个 item”,而是在问 “这个用户一路走到现在,下一步最可能发生什么行为”。这就是 HSTU 相比传统 pointwise ranker 更接近生成式建模的地方。
在这个框架下,HSTU 相对标准 Transformer 做了三个关键改动。理解这些改动的关键在于:每一个改动都对应一个” 标准 Transformer 在推荐场景下的不适配”——HSTU 不是为了改而改,而是因为 NLP 里合理的默认假设到了推荐场景变成了阻碍。下面三个改动按重要性从高到低逐个来看。
改动一:训练目标从” 当前样本打分” 变成” 行为序列转导”
传统 ranker 的训练范式
传统 ranker 的训练范式是” 逐样本打分”:每条 \((u, i, \text{label})\) 样本独立贡献一个二分类 loss(点击 / 不点击)。这背后的假设是” 每个样本独立、目标可以拆成逐条累加”。
HSTU 改成” 序列转导”
HSTU 论文标题里的 Sequential Transducers 暗示了一个更根本的转变:训练目标从” 逐样本分类” 变成” 序列转导”。Transducer 的意思是:输入一段历史行为序列,输出未来行为或目标 action 的分布 —— 不是只服务某一个二分类 CTR 目标,而是把多个推荐任务(点击、完播、点赞、转化……)统一成序列上的预测问题。
用具体例子看两者的差异
这里差异最容易被” 都用 CE loss” 这个表面相似性掩盖,所以用一个具体例子讲清楚。假设线上日志里有这样一条用户行为:
用户 U 在某次 session 里依次做了 4 个动作: 1. 看了篮球视频 A,完播 2. 看了篮球视频 B,点赞 3. 看了美食视频 C,跳过 4. 看了篮球视频 D,完播
Pointwise ranker 的做法 —— 把这条 session 拆成 4 条独立样本:
| 样本 | 用户 | item | label |
|---|---|---|---|
| 1 | U | 篮球 A | 1(完播) |
| 2 | U | 篮球 B | 1(点赞) |
| 3 | U | 美食 C | 0(跳过) |
| 4 | U | 篮球 D | 1(完播) |
这 4 条样本在 batch 里可以打乱 —— 它们和” 用户 V 跳过游戏 E” 这种样本地位完全相同。每条样本独立算一个 binary CE,加起来就是 batch loss:
\[ \mathcal{L}_{\text{pointwise}} = -\big[\log \sigma(s(U, A)) + \log \sigma(s(U, B)) + \log(1 - \sigma(s(U, C))) + \log \sigma(s(U, D))\big] \]
历史序列(如果用了的话)只是作为特征进入 \(s(U, \cdot)\),不参与 loss 构造。
HSTU 的做法 —— 整条 session 作为一个训练样本,不拆。每个位置都贡献一个” 预测下一步” 的 loss 项:
| 位置 \(t\) | 输入 | 预测目标 | Loss 项 |
|---|---|---|---|
| 1 | \(x_1\)(看篮球 A 完播) | \(x_2\)(看篮球 B 点赞) | \(-\log p(x_2 \mid x_1)\) |
| 2 | \(x_1, x_2\) | \(x_3\)(看美食 C 跳过) | \(-\log p(x_3 \mid x_1, x_2)\) |
| 3 | \(x_1, x_2, x_3\) | \(x_4\)(看篮球 D 完播) | \(-\log p(x_4 \mid x_1, x_2, x_3)\) |
\[ \mathcal{L}_{\text{HSTU}} = -\big[\log p(x_2 \mid x_1) + \log p(x_3 \mid x_1, x_2) + \log p(x_4 \mid x_1, x_2, x_3)\big] \]
一条长度 \(T\) 的序列贡献 \(T-1\) 个 loss 项,每个位置都是一个” 给定前 \(t\) 步历史,预测第 \(t+1\) 步” 的多分类任务。
这两种方法的三个差异对比如下
| 维度 | Pointwise ranker | HSTU |
|---|---|---|
| 样本能否打乱 | 可以,session 拆成独立样本 | 不可以,顺序是 loss 的一部分 |
| Loss 形式 | binary CE 逐条累加 | 多分类 CE 在每个位置算 |
| 一条 session 贡献多少 loss | \(T\) 个(每个 \((u,i)\) 一个) | \(T-1\) 个(每个位置预测下一步) |
| 模型在预测什么 | 给 \((u, i)\) 打分 | 预测下一步 action |
| Item 之间是否独立 | 独立 | 通过 attention 互相影响 |
一个能体现差异的极端情况:假设用户 U 的 session 是” 看篮球 A → 看篮球 A → 看篮球 A → 看篮球 A”(连续看 4 次同一个视频)。
- Pointwise ranker:看到 4 条一模一样的样本 \((U, A, 1)\)。模型只会学到” 用户 U 喜欢篮球 A” 这个事实,重复 4 次的信号被压缩成” 对 A 的兴趣强度”
- HSTU:看到一条序列 \((x_1, x_2, x_3, x_4)\) 都是” 看篮球 A”。每个位置的 loss 都在问” 看完 A 之后下一步是什么”—— 模型会学到” 用户看完 A 之后还会再看 A” 这个序列依赖关系,而不只是” 用户喜欢 A” 这个静态偏好
这种” 重复行为本身就是信号” 的特征,pointwise loss 完全捕捉不到,但 HSTU 的 next-action loss 天然能捕捉 —— 这也是为什么 HSTU 在长历史行为建模上比 pointwise ranker 更有优势。
工程上的两种用法
工程上这种统一范式可以落到两种用法:
- 候选打分:给定用户历史和候选 item,把候选 item 作为未来 action 的一部分,预测它发生的概率或价值 —— 这是 HSTU 替代传统精排的用法
- 召回侧 user 编码:用 HSTU 把用户历史编码成一个强 user state 向量 \(A_t\),再投影成 query embedding,喂给 ANN 索引做检索 —— 这是 HSTU 替代传统双塔召回的用法
这里需要澄清一个容易混淆的点:HSTU 在召回侧并不” 生成 item token”。它只是替代了双塔里 user 侧的 encoder——item 侧仍然是 hash ID + embedding + ANN 索引。真正的” 生成式召回”(autoregressively 生成 item token 序列)是 TIGER / OneRec 那条路,需要 semantic ID,HSTU 官方实现不走这条路。这也是为什么 HSTU 论文标题里的 “Generative” 指的是序列建模方式(把推荐重述成 next-action 预测),不是指输出形态(生成 item token)—— 这两件事在 TIGER / OneRec 里绑在一起,但在 HSTU 里是分开的。
所以 HSTU 既可以被描述成 generative recommender,也可以落在排序 / 召回系统里使用。它真正替换的不是某一个模块名字,而是” 每个样本独立打分” 这个建模假设 —— 把推荐从” 判别问题” 重述成” 序列预测问题”。
HSTU 输出层结构示意
下面这张图总结了 HSTU 输出层在训练和推理两种场景下的工作方式:

需要强调的一个关键点:HSTU 的输出层不是 LLM 那种独立的 \(W_{output}\) 矩阵,而是” 双塔式点积” 结构 ——user state \(A_t\) 和 item embedding 做点积得到分数,item embedding 表在输入侧(编码历史序列)和输出侧(打分)共享同一份参数。这跟传统双塔召回模型的打分方式是一致的。
跟传统召回模型的相似性
说到这里会发现一个有意思的相似性:HSTU 的训练范式跟传统双塔召回模型非常像 —— 都是 user embedding 和 item embedding 做点积,都用 sampled softmax(正样本 + 采样负样本)训练。DSSM、YoutubeDNN、MIND 这些经典召回模型都是这个套路,HSTU 在输出层和 loss 层面继承了这一范式。
真正的差异在 user encoder:传统双塔把用户历史行为 pool 成一个向量(mean / sum)或浅层 MLP,HSTU 则用序列模型显式建模行为之间的依赖。所以更准确的说法是:
HSTU ≈ 把双塔召回的 user encoder 从” pooling / 浅层网络” 升级成” 序列模型”,但训练 loss(sampled softmax)和打分方式(点积)保留双塔召回的范式。
这也解释了为什么 HSTU 能同时落在精排和召回两个场景 —— 它的输出层结构本来就是双塔式点积,跟召回的打分方式天然兼容;而序列建模带来的 user state 质量提升,又让它能替代传统精排。一个模型,两种用法,背后是同一套训练和打分范式。
改动二:pointwise SiLU 替代 softmax attention
动机与 attention 基础
这项改动看起来只是换了一个激活函数,但它真正改变的是 attention 的语义:标准 softmax attention 输出的是” 加权平均”,HSTU 的 pointwise SiLU 输出的是” 证据累加”。
先解释一下 attention 在做什么。一句话概括:当前要预测的位置发出一个 query \(Q\),去历史里找相关信息;历史里每条行为都有个” 标签” \(K\) 和一个” 内容” \(V\)(这条行为携带的信息)。\(Q\) 和某个 \(K\) 算点积,得到一个” 相关性分数”—— 分数越大说明这条历史和当前问询越相关。然后按相关性分数聚合所有 \(V\),就得到了 attention 的输出。
为了把数字算清楚,我们把向量都简化成 1 维标量(实际模型里是多维向量,但 1 维足以说明问题)。
假设现在要预测” 用户对下一条篮球视频的兴趣”,所以问询 \(Q\) 是” 篮球方向”。历史里有两类视频:
| 历史行为 | 类型 | \(K\)(标签) | \(V\)(内容) | 与 \(Q\) 的相关性分数 \(s = Q \cdot K\) |
|---|---|---|---|---|
| 第 1 条 | 篮球 | 1.0 | 1.0 | 1.0 |
| 第 2 条 | 篮球 | 1.0 | 1.0 | 1.0 |
| 第 3 条 | 篮球 | 1.0 | 1.0 | 1.0 |
| 第 4 条 | 美食 | 0.1 | 0.2 | 0.1 |
也就是说,篮球视频的相关性分数都是 1.0(强相关),美食视频的相关性分数是 0.1(弱相关)。
接下来对比两个用户:用户 A 只有 1 条篮球历史,用户 B 就是上面这张表(3 条篮球 + 1 条美食),用户 C 有 100 条篮球历史。
Softmax attention 怎么算
标准 Transformer 的 attention 是这样的:先把每个相关性分数过 \(\exp\),再归一化成” 加起来等于 1” 的权重,最后用这些权重对 \(V\) 做加权平均。公式是:
\[ A = \sum_j \mathrm{softmax}(s_j) \cdot V_j,\quad \mathrm{softmax}(s_j) = \frac{e^{s_j}}{\sum_k e^{s_k}} \]
用户 A(1 条篮球):
- 分数:\([1.0]\)
- 归一化权重:\([1.0]\)(只有一个位置,权重自然是 1)
- 输出:\(1.0 \times 1.0 = \mathbf{1.0}\)
用户 B(3 条篮球 + 1 条美食):
- 分数:\([1.0, 1.0, 1.0, 0.1]\)
- \(\exp\) 后:\([2.72, 2.72, 2.72, 1.11]\)
- 总和:\(2.72 \times 3 + 1.11 = 9.27\)
- 归一化权重:\([0.294, 0.294, 0.294, 0.120]\)
- 输出:\(0.294 \times 1.0 + 0.294 \times 1.0 + 0.294 \times 1.0 + 0.120 \times 0.2 = 0.882 + 0.024 = \mathbf{0.906}\)
注意这里发生了什么:用户 B 比 A 多看了 2 条篮球,但输出反而从 1.0 跌到了 0.906—— 因为新增的 3 条篮球要和那条美食视频争抢同一个固定的权重预算 1,篮球每条只分到 0.294,把总权重拉低了。
用户 C(100 条篮球):
- 分数都是 1.0
- 归一化权重:每条 \(1/100\)
- 输出:\(100 \times (1/100) \times 1.0 = \mathbf{1.0}\)
把三个结果并排放:
| 用户 | 历史 | Softmax 输出 |
|---|---|---|
| A | 1 条篮球 | 1.0 |
| B | 3 篮球 + 1 美食 | 0.906 |
| C | 100 条篮球 | 1.0 |
问题立刻浮现:用户 A 只看了 1 条篮球,用户 C 看了 100 条 —— 两者的兴趣强度显然差 100 倍,但 softmax 给出的输出几乎完全一样。softmax 只能表达” 兴趣方向是什么”,表达不了” 兴趣强度有多大”。原因就是那个归一化:所有权重加起来被强制锁死成 1,无论历史里有 1 条还是 1000 条,注意力总量都固定。
Pointwise SiLU attention 怎么算
HSTU 的做法是:不要归一化,让每条历史独立贡献一份证据,最后直接相加。公式是:
\[ A_i = \sum_{j \le i} \mathrm{SiLU}(s_j) \cdot V_j,\quad \mathrm{SiLU}(x) = x \cdot \sigma(x) = \frac{x}{1 + e^{-x}} \]
这里 \(\mathrm{SiLU}\)(也叫 swish)是一个激活函数,它的形状是:输入 \(x\) 越大、输出越大;输入很小或为负时输出接近 0。它替代了 softmax 的归一化,但保留了” 对相关性分数做非线性变换” 这个作用。
先算两个要用到的 SiLU 值:
- \(\mathrm{SiLU}(1.0) = 1.0 \times \sigma(1.0) = 1.0 \times 0.731 = 0.731\)
- \(\mathrm{SiLU}(0.1) = 0.1 \times \sigma(0.1) = 0.1 \times 0.525 = 0.0525\)
用户 A(1 条篮球):
- 输出:\(\mathrm{SiLU}(1.0) \times 1.0 = 0.731 \times 1.0 = \mathbf{0.73}\)
用户 B(3 条篮球 + 1 条美食):
- 篮球贡献:\(3 \times \mathrm{SiLU}(1.0) \times 1.0 = 3 \times 0.731 = 2.193\)
- 美食贡献:\(\mathrm{SiLU}(0.1) \times 0.2 = 0.0525 \times 0.2 = 0.0105\)
- 输出:\(2.193 + 0.0105 = \mathbf{2.20}\)
用户 C(100 条篮球):
- 输出:\(100 \times \mathrm{SiLU}(1.0) \times 1.0 = 100 \times 0.731 = \mathbf{73.1}\)
三个结果并排放:
| 用户 | 历史 | Softmax 输出 | SiLU 输出 |
|---|---|---|---|
| A | 1 条篮球 | 1.0 | 0.73 |
| B | 3 篮球 + 1 美食 | 0.906 | 2.20 |
| C | 100 条篮球 | 1.0 | 73.1 |
差别一目了然:
- softmax 下,用户 A 和用户 C 输出几乎一样(1.0 vs 1.0),看不出强度差别
- SiLU 下,用户 C 的输出是用户 A 的 100 倍(73.1 vs 0.73),直接反映了” 看了 100 条” 和” 看了 1 条” 的兴趣强度差
这恰好对应推荐场景最关心的信号 ——“用户对篮球有多感兴趣” 本身就藏在” 互动了几次” 这个绝对数量里。
还原成真实模型里的多维向量形式
上面的例子为了能跟着算,把向量简化成了 1 维标量。真实模型里 \(Q, K, V\) 都是多维向量,但核心逻辑完全一样。先把几个容易被忽略的 transformer 基础讲清楚,免得后面的公式看不懂。
第一,\(Q, K, V\) 不是直接训练的参数,而是输入经过投影后的中间结果。HSTU 在第 \(t\) 步的输入是一个事件向量 \(x_t = \mathrm{Embed}(i_t, a_t, c_t, \Delta t_t, \dots)\)—— 它描述的是” 用户在第 \(t\) 步对哪个 item 做了什么动作、在什么场景下、距上次多久” 这整个事件。然后用三个共享的可训练权重矩阵 \(W_Q, W_K, W_V\) 把 \(x_t\) 投影成三种角色:
\[ q_t = W_q \tilde{x}_t,\quad k_t = W_k \tilde{x}_t,\quad v_t = W_v \tilde{x}_t \]
序列里所有位置共享同一组 \(W_Q, W_K, W_V\)—— 区别只在于输入 \(x_t\) 不同(篮球事件 vs 美食事件),所以投影出的 \(K\) 不同。篮球视频在例子里的 \(K=1.0\)、美食视频 \(K=0.1\),可以理解为” 学好的 \(W_K\) 把这两类事件投影到了不同的标签位置”。
第二,attention 真正做的事是把历史事件聚合成” 用户状态”。HSTU 在第 \(t\) 步用 attention 把 \(x_1, \dots, x_t\) 这串历史事件聚合成一个隐状态 \(A_t\)—— 这才是” 用户经历 \(t\) 步行为后的状态”,而 \(x_t\) 本身只是第 \(t\) 步那条事件。整个序列建模就是” 基于 \(x_1, \dots, x_t\) 算出状态 \(A_t\),再基于 \(A_t\) 预测第 \(t+1\) 步最可能发生什么行为” 的循环。
理解了这两点,再看两个公式的差异就清楚了。标准 Transformer 的 attention:
\[ A_i = \sum_{j \le i} \mathrm{softmax}(q_i^\top k_j) \cdot v_j,\quad \sum_j \alpha_{ij} = 1 \]
HSTU 的 pointwise normalized-less attention:
\[ A_i = \sum_{j \le i} \phi(q_i^\top k_j + b_{ij}) \cdot v_j,\quad \phi = \mathrm{SiLU} \]
逐符号定义:
- \(q_i, k_j, v_j\):query / key / value 向量,分别来自第 \(i\) 个和第 \(j\) 个位置(由上面的 \(W_Q, W_K, W_V\) 投影得到)
- \(b_{ij}\):可选的位置 / 时间 / 相对顺序 bias,用来表达” 多久以前发生的行为” 和” 当前行为” 的关系
- \(\phi\):激活函数。HSTU 用 SiLU(也叫 swish),不做 softmax 归一化
- \(A_i\):第 \(i\) 个位置从历史行为里聚合到的隐状态
- \(j \le i\):因果 mask,只允许当前位置看见过去,不能偷看未来
两个公式只差一个 softmax,但语义完全不同:softmax 输出” 加权平均”,SiLU 输出” 证据累加”。用一个粗糙的类比总结这个差别:
- softmax attention 像在问:“这 100 条历史里,哪几条最重要?请把总权重 1 分给它们。”
- pointwise SiLU attention 像在问:“每一条历史分别能提供多少证据?有用的就加上,没用的就少加或不加。”
为什么这对推荐场景特别重要,对 NLP 却没那么重要?这其实可以从 softmax 归一化在 NLP 里能成立的前提反推。softmax 把权重归一化成 1,本质上是假设” 历史位置之间是竞争关系”—— 一句话里的 token 是在有限上下文里互相解释,“哪个 token 更重要” 是合理的问题,归一化让模型能聚焦最相关的几条。但推荐行为序列完全不一样 —— 重复次数、连续互动、兴趣强度本身就是特征,行为之间不该争抢同一个注意力预算。HSTU 换成 pointwise SiLU,本质上就是承认” 在推荐场景下,加权平均这个 NLP 里合理的语义反而是错的,应该换成证据累加”。HSTU 论文在合成数据上观察到,这一差异能带来高达 44.7% 的 NDCG 差距。
改动三:保留 hash / sparse 体系,不强依赖 semantic ID
这一点正是改动一提到的观点,也是会非常容易被误解的点
TIGER / OneRec 这条生成式路线高度依赖 semantic ID—— 因为它们要” 生成 item”,必须先把 item 变成可生成的 token 序列。一个常见的误解是” HSTU 既然是 generative recommender,也应该依赖 semantic ID”。但 HSTU 的官方实现恰恰相反,大部分还在用 hash ID + sparse feature embedding。
为什么 HSTU 可以不依赖 semantic ID?
因为 HSTU 挑战的是 cascade 的假设 B 和 C 里它真正解决的那一部分,而不是全部。具体说:
- 挑战 B1(pointwise 独立打分):HSTU 用序列建模替代 pointwise 打分 —— 训练目标从” 逐样本分类” 变成” 序列转导”,item 之间通过历史序列隐式建模,不再是孤立的 \((u, i)\) 评分
- 挑战 C(没有 scaling law):HSTU 用 pointwise SiLU attention + 序列转导训练目标 + 工程配套优化,让推荐模型在三个数量级 compute 上遵循 power-law scaling,第一次系统性验证了推荐场景的 scaling law
- 不挑战 A(item 是离散原子):HSTU 官方实现里 item 仍然是 hash ID + sparse embedding,没有换成 semantic ID
- 不挑战 B2(多步级联能近似全局最优):HSTU 仍然落在级联系统里当精排或召回用,没有把召回/精排/重排合并成一个端到端模型
最后一点容易被误解。HSTU 论文标题里的 “Generative” 指的是建模方式上的生成式(把推荐重述成 next-action 预测),不是输出形态上的生成式(自回归生成 item token)。前者是 HSTU 做的事 —— 用序列建模替代独立打分;后者是 TIGER / OneRec 做的事 ——decode 出 semantic ID token 序列再映射回真实 item。HSTU 官方实现不生成 item token,所以仍然依赖 ANN 检索,仍然落在级联系统里使用。
真正挑战 B2(端到端替代 cascade)的是 OneRec—— 它用一个 encoder-decoder 一口气生成整张 list,把召回 + 排序 + slate 统一在一个生成框架里。这一点后面” GR 在召回/排序/列表生成的不同落地形态” 那张对照表会看得更清楚:HSTU 归到” 第一层精排”,OneRec 归到” 端到端”。
所以 HSTU 的核心是” 在行为序列上做可扩展的序列建模”,不是” 重新设计 item 表征”。hash ID 在 HSTU 里只是 action token 的一种 —— 只要行为序列建模能力够强,模型自己会学出 item 之间的关系,不一定非要换成 semantic ID。
HSTU 和 semantic ID 是正交的
所以 HSTU 和 semantic ID 是正交的两件事:
- 如果业务的主要瓶颈是冷启、长尾、item 表征无结构,semantic ID 更直接 —— 它能给新 item 一个有结构的位置
- 如果业务的主要瓶颈是行为序列建模能力和模型 scaling,HSTU 更直接 —— 它解决的是 backbone 能力,不是 item 表征
- 如果两者都成立,理论上可以把 semantic ID 作为 item 表征的一部分喂给 HSTU,但这只是锦上添花,不是 HSTU 成立的前提
这一点对实际落地很重要:不需要先做完 semantic ID 才能尝试 HSTU,两件事可以独立推进。
路线二:端到端生成式(OneRec / TIGER 系)
路线一是” 用推荐数据训 backbone,但不生成 item token”——HSTU 落在精排 / 召回,仍然是级联系统的一个模块。路线二则更激进:用推荐数据从头训一个 encoder-decoder,自回归生成 item token(semantic ID),把召回 + 排序 + slate 统一在一个生成框架里,目标是端到端替代 cascade。
代表工作是 OneRec (arXiv:2502.18965) 和 TIGER (arXiv:2305.05065)。两者架构思路相近,但落地程度完全不同 ——TIGER 停在学术验证阶段,OneRec 已在快手主站大规模上线(完整上线数据见 OneRec Technical Report, arXiv:2506.13695)。
OneRec 的一些核心改动如下
- encoder-decoder 结构:encoder 处理用户历史序列,decoder 自回归生成下一个(或下一组)item 的 semantic ID token
- session-wise list generation:不是逐个 item 预测,而是一次性生成整个 session 的 item 列表,让模型自己学 item 之间的相对关系和顺序
- 强依赖 semantic ID:因为要” 生成 item”,必须先把 item 表达成可生成的 token 序列(RQ - VAE semantic ID)—— 这跟 HSTU “不强依赖 semantic ID” 形成对比
- MoE 扩参:OneRec 的 decoder FFN 用 MoE,让模型从 0.015B 扩到 2.633B 参数仍遵循 scaling law
下图展示了 OneRec 这类端到端生成式推荐的核心流程:

整体分为五步(工程细节留到后面” 解码与推理” 一节展开):
- item → semantic ID(离线一次性):每个 item 通过 RQ - VAE 编码成一串 semantic ID token,相似 item 共享前缀。这一步是后续 constrained decoding 能高效裁剪路径的基础
- 用户历史 → encoder 隐状态(在线,每请求一次):用户历史序列(每个历史 item 也用 semantic ID 表示)输入 encoder 得到隐状态 \(H\)。这一步跟路线一 HSTU 编码用户状态一样,区别在下一步 ——HSTU 用 \(H\) 对候选打分,OneRec 用 \(H\) 驱动 decoder 生成
- decoder 自回归生成 semantic ID(session-wise):decoder 基于 \(H\),以
[BOS]起始,自回归生成一个完整 session(5-10 个 item)的 semantic ID 序列。这是路线二跟路线一最关键的区别 ——HSTU 候选由上游给定只负责打分,OneRec 模型自己生成整张列表 - constrained decoding 保证合法性:decoder 裸生成的 token 序列可能对应不到任何真实 item,工程上用 Trie-based constrained decoding 保证只生成合法 semantic ID
- semantic ID → 真实 item:合法 semantic ID 通过映射表查回真实 item,按生成顺序组成最终推荐列表
训练目标
路线二的训练目标是 next-token CE loss,对应” 给定历史和已生成的 token,预测下一个 semantic ID token”:
\[ \mathcal{L}_{\text{NTP}} = -\sum_{i=1}^{m} \sum_{j=0}^{L-1} \log P(c^{(j)}_i \mid [\text{BOS}], c^{(1)}_1, \dots, c^{(j-1)}_i; \Theta) \]
其中 \(m\) 是 session 内 item 数量,\(L\) 是每个 item 的 semantic ID 层数,\(c^{(j)}_i\) 是第 \(i\) 个 item 的第 \(j\) 层 codebook 索引。整个 session 的生成概率可以分解为(TIGER 的公式):
\[ P(\text{session} \mid \text{history}) = \prod_{i=1}^{m} \prod_{j=0}^{L-1} P(c^{(j)}_i \mid c^{(<j)}_i, \text{history}) \]
对齐阶段(IPA)不是只优化 DPO loss,而是把 NTP loss 和 DPO loss 加权相加作为联合训练目标(详见后面” 训练目标:从 next-token 到偏好对齐” 节):
\[ \mathcal{L} = \mathcal{L}_{\text{NTP}} + \lambda \mathcal{L}_{\text{DPO}} \]
路线二最独特的不是” 生成 item” 本身(TIGER 也生成 item),而是 session-wise list generation—— 一次生成整个 session 而不是单个 item。这带来两个好处:
- 建模 item 之间的相对关系和顺序:传统 pointwise/next-item 预测只能问” 下一个 item 是什么”,session-wise 能问” 这一整屏应该推什么、先后顺序如何”,让模型自己学 list 内部的依赖关系(比如篮球视频之后推体育周边比推美食更合理)
- 天然统一了召回 + 排序 + slate:传统 cascade 里” 召回拉候选 → 精排打分 → 重排出 slate” 三步,在 session-wise generation 里被压缩成” decoder 一次性生成整个 slate” 一步。这是路线二能挑战假设 B2(多步级联能近似全局最优)的根本原因 —— 它直接把多步级联替换成一步生成
自回归 decode 整张列表的延迟挑战非常严峻 ——beam search、constrained decoding、KV cache、MoE 稀疏激活等工程优化是 OneRec 能上线的关键。这些工程细节留到后面” 解码与推理” 一节统一展开,那里会以 OneRec 为具体例子把 constrained decoding、beam search、工业延迟约束这些通用机制串起来。
路线一和路线二都用推荐数据从头训,但两者在” 输出形态” 上完全不同:
| 维度 | 路线一(HSTU) | 路线二(OneRec) |
|---|---|---|
| 是否生成 item token | 否(双塔式点积打分) | 是(自回归生成 semantic ID) |
| 是否依赖 semantic ID | 不强依赖(hash ID 也行) | 强依赖(必须先生成 token) |
| 落在级联的哪一层 | 精排 / 召回(替换某一层) | 端到端(统一召回 + 排序 + slate) |
| 挑战的 cascade 假设 | B1(pointwise 独立打分)+ C(scaling law) | B2(多步级联能近似全局最优) |
| 推理方式 | 历史编码一次 + 候选并行打分 | 自回归 decode 整张列表 |
| 候选池保证 | 上游给定 / ANN 索引 | constrained decoding + Trie 裁剪 |
| 一次请求产出 | top-N 候选打分 | 一整张 session 列表 |
这个差异决定了两者落地的难度 ——HSTU 落在级联里某一层,工程上可以渐进替换;OneRec 是端到端替代 cascade,工程改造范围大得多,但天花板也高得多。
OneRec 是目前公开资料中最完整、最典型的端到端 GR 替代 cascade 工业案例之一。原始论文 OneRec (arXiv:2502.18965) 只报告了主站 watch-time +1.6% 一个上线数字,更完整的上线数据来自后续的 OneRec Technical Report (arXiv:2506.13695):
- 快手主站 + 极速版短视频主场景:承担约 25% QPS;App Stay Time 主站 +0.54%、极速版 +1.24%(OneRec + RM Selection vs 传统 cascade);LT7 主站 +0.05%、极速版 +0.08%。论文注明在快手 0.1% 的 App Stay Time 提升、0.01% 的 LT7 提升已算统计显著
- 本地生活场景:GMV +21.01%,订单量 +17.89%,付费用户 +18.58%,新客获取效率 +23.02%,已 100% QPS 全量切换(OneLoc 系列工作,见 arXiv:2508.14646)
- 运营成本(OPEX)仅为传统方案的 10.6%
但路线二也有其局限的地方
- 独立验证仍然有限:OneRec / OneLoc / OneRec V2 都来自快手技术谱系,公开资料已经覆盖短视频、本地生活等多个场景,但还缺少第二家公司在主流推荐场景里的同等级端到端验证。相比之下路线一(HSTU)有 Meta(HSTU 多产品上线)+ 美团 MTGR(arXiv:2505.18654,MTGR-large 已全量部署到美团外卖推荐主流量)两家独立上线。
- 改造范围大:端到端替代 cascade 意味着召回、排序、重排整个链路都要重构,工程改造比 HSTU 替换某一层大得多。
- 推理延迟挑战:自回归 decode 整张列表天然有劣势,OneRec V2 的 Lazy Decoder-Only 架构是这个方向最新的工程进展。
OneRec 的详细 RL 对齐方法(Iterative Preference Alignment)后面会单独展开,这里只讨论它在三条路线里的定位。
路线三:直接复用通用 LLM
这条路的核心论点是:通用 LLM 已经学到了丰富的世界知识和文本理解能力,把推荐改写成 prompt / instruction 任务即可,不需要从头训一个推荐基础模型。
这条路按时间顺序看三篇代表工作,正好能看出” 让 LLM 做推荐” 的演进逻辑:从一开始的” 让 LLM 生成一切”,逐渐退到” 让 LLM 只做精排打分”—— 每一退都是被推荐场景的现实约束逼出来的。
P5 (RecSys 2022, arXiv:2203.13366):最早的全面文本化尝试
P5 的思路是” 把推荐全面语言化”—— 基于 T5 encoder-decoder(223M 参数),把所有推荐数据(user-item 交互、用户描述、item 元数据、评论)都转成文本 prompt,然后用一个共享的语言建模目标在多个任务上预训练。P5 统一了五类任务:
- 评分预测(rating prediction):给 user-item 对预测评分
- 序列推荐(sequential recommendation):给历史交互序列预测下一个 item
- 解释生成(explanation generation):生成推荐理由文本
- 评论摘要(review summarization):把长评论总结成标题
- 评论偏好预测(review preference prediction):从评论预测评分
P5 最关键的设计选择是:item ID 被拆成 sub-word token—— 比如 item_7391 被 tokenize 成 item、_、7391 三个子词。这意味着 item 可以通过 decoder 自回归生成,跟 LLM 生成自然语言完全一样。P5 的卖点是” 一个模型多任务 + zero-shot 泛化”—— 预训练后能泛化到没见过的 prompt 和新 item。
但 P5 有一个明显问题:item ID 是当文本 token 生成的,没有任何机制保证生成的 ID 落在合法 item 池里。模型可能生成一个根本不存在的 item_99999,也可能生成一个语义上合理但 item 池里没有的 ID。这是把推荐当 NLP 做的必然代价 ——LLM 的词表是开放的,但推荐场景的 item 池是封闭的。
BIGRec (arXiv:2308.08434):承认生成结果需要 grounding
BIGRec 针对 P5 留下的” 生成 ID 不合法” 问题提出了 bi-step grounding 范式:
- Step 1(grounding):fine-tune LLM 让它生成 item 描述相关的 token,把 LLM 从语言空间” 接地” 到推荐空间
- Step 2(matching):用 LLM 的 latent representation,把生成的 token 映射到最接近的合法 item
也就是说,BIGRec 不再指望 LLM 生成的 token 序列本身就是合法 item ID,而是把它当成一个” 语义锚点”,再用最近邻搜索映射回合法 item 池。这跟 HSTU 那条路里” 输出层是双塔式点积 + ANN 检索” 的处理思路异曲同工 —— 都是承认生成端无法直接保证合法性,需要后处理映射。
但 BIGRec 论文还揭示了一个更深层的发现:纯 LLM 路线学习协同信号的效率和稳定性仍然不足。论文观察到,增加训练样本数量给 BIGRec 带来的边际收益很有限 —— 因为 LLM 的强语义先验会压制对统计信息(如热度、协同过滤信号)的学习。这一点对路线三的整体判断很关键:LLM 预训练里学到的是” 语言里的语义关联”,不是” 用户行为里的协同关联”—— 前者是语义信号,后者是统计信号,两者并不等价。
LlamaRec (PGAI@CIKM 2023, arXiv:2311.02089):干脆放弃生成 item,只让 LLM 做精排
LlamaRec 的思路是:既然 LLM 生成 item 有合法性问题和效率问题,那干脆不让 LLM 生成 item,只让它做精排打分。具体是两阶段:
- Stage 1(召回):用传统序列模型(SASRec / LRURec)做召回,拉回候选 item 集合
- Stage 2(精排):把用户历史和候选 item 都转成文本喂给 LLM,用 verbalizer 把 LLM 输出 logits 直接映射成候选 item 的概率分布
关键是 verbalizer 这个技巧 —— 把每个候选 item 对应到 LLM 词表里的一个特定 token(或一组 token),一次前向就能读出所有候选的 logit,不需要 autoregressive 生成。LlamaRec 用 LLaMA-2-7b + LoRA 微调,verbalizer 让它在一次前向里完成所有候选打分,绕开了 LLM 自回归 decode 慢的问题。
这个设计很巧妙:它把 LLM 的输出层从” 生成器” 改成了” 打分器”——LLM 不再生成 item,只是用它的语义理解能力对候选 item 评分。这跟 HSTU 的” 输出层是双塔式点积” 有异曲同工之处:两者都是” 用模型编码出 query / user state,再对候选 item 打分”,只是 HSTU 的 backbone 是序列模型、LlamaRec 的 backbone 是 LLM。
三篇论文反映的演进逻辑
把三篇放在一起看,路线三的演进方向非常清晰:
| 论文 | 年份 | LLM 的角色 | 如何保证 item 合法性 |
|---|---|---|---|
| P5 | 2022 | 生成 item ID | 不保证(生成 token 可能不是合法 ID) |
| BIGRec | 2023 | 生成 item 描述 token | 后处理映射(latent 最近邻) |
| LlamaRec | 2023 | 对候选 item 打分 | 候选由上游给定(LLM 不负责生成) |
演进方向是:从” 让 LLM 生成 item” 逐渐退到” 让 LLM 做打分”。每一退都是被推荐场景的现实约束逼出来的:
- P5 不保证合法性 → BIGRec 加 grounding 后处理
- BIGRec 的 grounding 仍然慢(要生成 + 映射),且纯 LLM 路线学习协同信号的效率不足 → LlamaRec 干脆放弃生成,只做打分
- 最终 LlamaRec 退到了” LLM 做精排” 的位置 —— 跟 HSTU 落在精排场景的位置重合,但 backbone 换成了 LLM
这个演进也解释了为什么路线三目前工业落地很少 —— 退到 LlamaRec 这一格,LLM 相比传统精排的优势只剩” 语义理解能力”,但在推理延迟、行为信号建模、训练成本上都处于劣势。LLM 的语义理解能力在” 长尾、冷启、对话式” 这些子场景有局部价值,但在” 行为数据极大、延迟要求严苛” 的主流推荐场景,这个优势不足以弥补延迟和成本的劣势。
两个工业延伸工作:HLLM 和 URM
P5/BIGRec/LlamaRec 都是学术工作,但路线三在工业侧有两个延伸值得单独提一下 —— 它们都是” 用 LLM 思想做推荐”,但走了跟纯 LLM-as-Recommender 不同的路:
- HLLM(ByteDance, arXiv:2409.12740):用两层 LLM 把” item 内容理解” 和” 用户行为建模” 解耦 ——Item LLM 负责把 item 的文本描述压成 content embedding,User LLM 负责在这些 embedding 上做行为建模。这种解耦在” item 内容信息丰富、行为信号相对稀疏” 的场景特别适合(比如长视频、电商商品),对冷启和长尾的提升非常显著 —— 这部分场景正是 LLM 的语义理解能力能真正发挥价值的地方
- URM(Alibaba, arXiv:2502.03041):把召回看成一个” 通用任务”—— 同一个模型既可以做 multi-scenario 召回、又可以做 multi-objective 召回、还可以做长尾召回。multi-query representation 让模型一次推理产出多组 query embedding,每个 query 对应不同的目标 / 场景。这其实是把 LLM 的 “instruction-following” 思想搬到推荐召回上
这两个工作的共同特点是:没有让 LLM 直接生成 item token,而是用 LLM 思想改造推荐系统内部某个模块。这比 P5 那条” 把推荐全面语言化” 的路子工业落地容易得多 —— 也是路线三里少数有公开工业 A / B 或测试证据的方向。
三条路线的差异
很多解读把 HSTU、OneRec、LLM-as-Recommender 当作” 类似的事情”,但仔细看一下就会发现,它们的起点、复用什么、适合什么场景,都完全不同:
| 维度 | 路线一(HSTU) | 路线二(OneRec) | 路线三(LLM-as-Recommender) |
|---|---|---|---|
| 起点 | 从推荐数据从头训 | 从推荐数据从头训 encoder-decoder | 从预训练 LLM fine-tune |
| 复用什么 | scaling law 本身 | scaling law + semantic ID + 端到端 | LLM 的世界知识 + 文本理解 |
| 是否生成 item token | 否(双塔式点积打分) | 是(自回归生成 semantic ID) | 部分生成(P5 / BIGRec),部分打分(LlamaRec) |
| 关键信号 | 行为序列 | 行为序列 + item 表征结构 | 文本描述 |
| 挑战的假设 | B1(pointwise)+ C(scaling law) | B2(多步级联)+ C(scaling law) | 主要是 B1(用 LLM 替代打分) |
| 适合场景 | 行为数据极大的 feed / 短视频 | 端到端统一召回 + 排序 + slate | 长尾、冷启、对话式 |
| 推理延迟 | 中(特化架构可深度优化) | 高(自回归 decode 整张列表) | 高(通用 LLM decode 慢) |
| 工业落地证据 | Meta(HSTU 多产品上线)+ 美团 MTGR(arXiv:2505.18654) | 快手主站 + 极速版上线 | 主流场景几乎没有,局部场景有 |
| 上线难度 | 高,但已被 Meta 验证可行 | 极高,工程改造范围大 | 高,工业案例非常少 |
| 工业证据强度 | 已验证(范式级贡献) | 端到端证据较完整,但主要来自同一技术谱系 | 学术有效,工业未验证 |
| 主要瓶颈 | 暂无明显瓶颈,Meta(HSTU)+ 美团(MTGR)两家独立大厂验证 | 改造范围大、推理延迟严峻,公开证据主要来自同一技术谱系 | 行为信号注入不足 + 推理延迟难压到几十毫秒;仅长尾/冷启/对话式有局部价值 |
解码与推理:让生成的 token 落到真实 item
核心问题:生成的 token 序列可能根本对应不到任何真实 item
一个自回归模型采样出的 token 序列,在普通 LLM 场景下可以是任意自然语言。但在 GR 里,生成的 semantic ID 必须能映射回一个真实存在、当前合法、当前未屏蔽的 item。否则推荐结果就是空气。
工程上解决这个问题有几条标准做法。下面以 OneRec 为具体例子把这套机制串起来 ——TIGER 的机制基本相同,只是没有上工业。
Beam search:避免贪心把高概率路径过早丢掉
最基础的做法。贪心 decode 每步选概率最高的 token,但 semantic ID 是多 token 序列 —— 某条路径第一步概率高但下一步无路可走(剩下 token 都不合法),贪心就会卡死。beam search 同时维持 top-k 条候选路径并行扩展,最后从完整路径里选总概率最高的。
OneRec 的 beam size 取到 128 量级 —— 这意味着每一步要同时维护 128 条路径的 KV cache 和概率,对显存和带宽都是压力。这个数字直接决定了 decode 的延迟下限。
Constrained / prefix-aware decoding:在合法集合上做 softmax
beam search 解决的是” 挑哪条路径”,constrained decoding 解决的是” 每一步只在合法 token 上做 softmax”。每一步 decode 时,先 mask 掉所有非法 token,再做 softmax 和采样,从源头杜绝生成空气 item。
semantic ID 的层级结构让这一步天然适配 Trie:
- 第一层 token 只能在” 训练集里出现过的第一层 codebook 索引” 里选
- 第二层 token 只能在” 给定第一层 token 后,训练集里出现过的第二层组合” 里选
- 以此类推
也就是说,semantic ID 的前缀就能裁剪掉绝大多数无效路径。OneRec 把所有合法 semantic ID 预先组织成一棵 Trie,decode 时每走一步就在 Trie 上推进一个节点,下一步的合法 token 集合就是这个节点的子节点 key 集合 —— 一次 mask 操作就能完成约束。
这一点是 TIGER 和 OneRec 都采用的关键工程技巧,也是路线二” 强依赖 semantic ID” 的工程原因 —— 如果没有 RQ - VAE 把 item 编码成有层级前缀的 semantic ID,constrained decoding 就退化成对全部 item ID 做 mask,失去前缀裁剪的效率优势。
与 ANN 的关系
这里有一个常见的误解需要澄清:GR 的生成式召回不是” 替代了 ANN”,更准确的说法是”用 transformer memory 替代了 ANN 索引”。也就是说,召回这件事变成了”模型参数本身就是 index”,而不是” 模型 + 外部 index”。这个区别在工程上很重要:模型重训意味着 index 重训,模型上线意味着 index 上线,两者不再可以独立部署。
工业延迟约束:自回归 decode 的最大瓶颈
传统精排在工业上几十毫秒结束战斗,自回归 decode 天然有劣势 —— 每一个 token 都要走一次前向。一个 session 要生成 5-10 个 item,每个 item 假设 3-4 层 semantic ID token,总共就是 15-40 步前向,再叠加 beam size 128 的并行扩展,naive 实现的延迟完全不可用。
OneRec 能上线,靠的是几项工程优化叠加把延迟压下来:
- KV cache:encoder 的隐状态和已生成 token 的 K / V 缓存复用,避免每步重复计算历史
- MoE 稀疏激活:decoder FFN 用 MoE,每个 token 只激活少量 expert,实际算量远小于 dense 模型 —— 这让模型能扩到 2.6B 参数仍遵循 scaling law,又不会让单步延迟爆炸
- float16 / 低精度推理:进一步压显存和带宽
OneRec V2(arXiv:2508.20900)的 Lazy Decoder-Only 架构号称把总计算减少 94%、训练资源减少 90%、模型 scale 到 8B 参数,是这个方向最新的工程进展 —— 它的核心思路是延迟部分 token 的解码,只在真正需要时才走完整 decoder,减少无效计算。
constrained decoding 和 transformer-as-index 这两件事本身已经被多家工业系统验证可行。但相比 cascade 范式下成熟的 ANN + 精排链路,自回归 decode 的延迟开销仍然显著更高。这是为什么直到现在,端到端 GR 主要在 “延迟相对宽松” 的内容 feed 场景上线,而搜索、广告这类对延迟极敏感的场景几乎没有看到。
训练目标:从 next-token 到偏好对齐
前面三大支柱讲的” 生成式架构” 用的是 next-token cross-entropy 训练。但这个 loss 天然只能优化” 下一个用户最可能交互的 item”—— 这只是一个 surrogate,不是推荐真正关心的目标。这一节单独讲 next-token loss 之外的对齐机制。
为什么单纯 next-token loss 不够
next-token loss 不解决的问题有四类:
- 多目标 trade-off:CTR、watch-time、转化、留存之间的权衡,next-token 没法显式表达
- 长期价值:session 深度、次日留存、复购,这些信号天然延迟、稀疏
- 业务约束:广告 load、营销感打散、品类多样性,这些硬约束不在生成模型的视野内
- exploration:模型只见过历史日志里的 token 组合,对没见过的组合没有探索动机
在 LLM 领域,这些问题对应的解决方案就是 RLHF(Reinforcement Learning from Human Feedback)。GR 沿用了 RLHF 的思想,但具体做法和 LLM 有几个关键差别。需要预先指出的是,RL 对齐能解决的只是软偏好类问题(多目标隐式权衡、长期价值、exploration);至于” 业务约束” 这一类 ——pacing、load 上限、score shading、calibration 这类硬约束和在线控制问题 ——next-token 范式天然不擅长,RL 也解不了,仍然要靠传统控制方法兜底(详见后面” GR 在 cascade 各层的落地形态” 一节关于第二层混排的讨论)。
OneRec 的 Iterative Preference Alignment
OneRec (arXiv:2502.18965) 是目前 GR 领域 RL 对齐最有代表性的工业方案。它的做法分五步:
第一步:训一个 reward model \(R_\phi\)
输入是 session 级别的生成序列(也就是一段被推荐给用户的 item 列表),输出是一个标量 reward。reward 的训练标签来自多目标业务结果 ——watch-time、互动、转化等真实指标。
第二步:用当前 policy 生成候选 session
用当前的 GR 模型(policy \(\pi_\theta\))通过 beam search 生成 \(K\) 条候选 session \(\{\pi^{(1)}, \dots, \pi^{(K)}\}\)。这里的 \(\pi\) 指代一条完整的推荐 session(不是数学符号 \(\pi_\theta\) 的 \(\pi\)),上下文会区分清楚。
第三步:构造 preference pair
用 reward model \(R_\phi\) 给每条候选打分,把 reward 最高的当 chosen (\(\pi^+\)),reward 最低的当 rejected (\(\pi^-\))。
第四步:NTP + DPO 联合对齐
OneRec 在 IPA 阶段不是只用 DPO loss,而是把 next-token loss 和 DPO loss 加权相加作为联合训练目标:
\[ \mathcal{L} = \mathcal{L}_{\mathrm{NTP}} + \lambda \mathcal{L}_{\mathrm{DPO}} \]
其中 DPO loss 的具体形式是:
\[ \mathcal{L}_{\mathrm{DPO}} = -\,\mathbb{E}\left[\log \sigma\!\left(\beta \log \frac{\pi_\theta(\pi^+)}{\pi_{\mathrm{ref}}(\pi^+)} - \beta \log \frac{\pi_\theta(\pi^-)}{\pi_{\mathrm{ref}}(\pi^-)}\right)\right] \]
逐符号定义:
- \(\pi_\theta\):当前 policy(GR 模型)
- \(\pi_{\mathrm{ref}}\):参考 policy——OneRec 里是上一轮迭代的 model \(M_t\)(不是 SFT 阶段 frozen 的 checkpoint),每轮迭代都会更新
- \(\pi^+, \pi^-\):reward 高 / 低的候选 session
- \(\beta\):温度系数,控制对齐强度。\(\beta\) 越大,policy 越紧贴偏好;\(\beta\) 越小,policy 越保守
- \(\sigma\):sigmoid 函数
- \(\lambda\):DPO loss 权重。论文里 DPO 样本相对 NTP 样本占比约 1%,\(\lambda\) 用来平衡两类 loss 的量纲
这里有两个关键点需要强调:
- NTP loss 始终保留:即使在 IPA 阶段,next-token loss 也没有丢掉 —— 它跟 DPO loss 一起作为联合 loss 训练,充当 anchor 防止 policy 漂得太远。如果只留 DPO loss、丢掉 NTP loss,policy 很快会被 reward model 的偏差带跑偏
- reference policy 是动态的:跟 LLM RLHF 里” SFT checkpoint frozen 当 reference” 的做法不同,OneRec 的 \(\pi_{\mathrm{ref}}\) 是上一轮 model \(M_t\),每轮迭代都会更新 —— 这是” iterative” 的另一层含义
通俗一点说,这个联合 loss 想做的事情是:让 policy 输出 \(\pi^+\) 的相对概率比 \(\pi^-\) 更高(DPO 部分),同时不能离参考 policy 太远(\(\beta\) 项),还要继续做好 next-token 预测(NTP 部分)。
第五步:迭代
用 \(\mathcal{L} = \mathcal{L}_{\mathrm{NTP}} + \lambda \mathcal{L}_{\mathrm{DPO}}\) 联合训练得到 \(M_{t+1}\) 后,再以 \(M_{t+1}\) 为新 policy 重新生成候选、重新用 reward model 打分、重新构造 preference pair、再联合训练 \(M_{t+2}\)。每一轮迭代里 NTP loss 都跟 DPO loss 一起参与训练,不是切到对齐阶段就丢掉。这个迭代过程是 OneRec 名字里” Iterative Preference Alignment” 的来源。
整个训练流程总结一下:先用纯 NTP loss 训一个 seed model(SFT 阶段)→ 进入 IPA 阶段,每轮迭代用 \(\mathcal{L}_{\mathrm{NTP}} + \lambda \mathcal{L}_{\mathrm{DPO}}\) 联合训练,reference policy 是上一轮 model(动态变化)。
GR 的 RL 和 LLM 的 RLHF 有什么本质区别
把 OneRec 和 LLM 的 RLHF 放在一起对比,最关键的差别是 preference pair 的来源:
LLM 的 RLHF 里,preference pair 是人类标注员逐条比较得到的。NLP 的输出空间是自然语言,标注成本可控。
GR 里没人愿意逐条比较推荐列表 —— 每次推荐都是几条到几十条 item,标注一个 session 就要几分钟,规模化做不了。所以 GR 的 preference pair 是从 reward model 合成的:reward model 自己模拟用户行为、自己生成 preference。
这件事的代价非常大。它意味着 GR 的 RL 对齐本质上变成了”model-based RL on a learned simulator”——simulator(reward model)本身的偏差就是新的风险来源。如果 reward model 学得不准,整套对齐就会沿着错误的方向跑。这一点在 OneRec 论文里没有特别强调,但是工业落地里必踩的坑。
需要进一步指出的是,reward model 自身也是从历史用户行为日志训出来的 —— 它的训练标签通常是 watch-time、互动、转化等多个业务指标的加权组合。这意味着 reward model 学到的是” 历史日志里已经出现的偏好分布”,对没出现过的 item 组合没有判断力。所以 GR + RL 对齐本质上承担两层偏差:(1) reward model 作为 simulator 的偏差,(2) reward model 训练标签本身的偏差(多目标加权 + 历史日志覆盖度)。第二层偏差跟传统推荐多目标建模是同一个问题,但 GR 因为依赖 reward model 合成 preference,这个偏差会被 DPO 放大。
GR 在 cascade 各层的落地形态
这一节是和上一篇文章《个性化排序公式》的显式呼应 —— 把 GR 范式逐层映射回 cascade,看每一层分别被颠覆、被重新打开、还是仍然无解。
上一篇把推荐分成三层:
- 第一层 精排:单 item 打分 \(s(u,i,x)\)
- 第二层 混排:业务级流量分配,带约束的在线控制
- 第三层 重排:列表组合优化,包含 listwise / Slate
加上召回,cascade 实际是四层。GR 对这四层的对应形态完全不同,对照如下:
| cascade 环节 | 传统做法 | GR 对应形态 | 代表工作 | 工业落地度 |
|---|---|---|---|---|
| 召回 | 双塔 + ANN | TIGER:生成式召回(transformer memory 替代 ANN);HSTU:序列建模 + ANN(user encoder 升级,item 侧不变) | TIGER / HSTU | TIGER 学术有效,工业级召回未验证;HSTU 高(Meta 上线) |
| 第一层精排 | pointwise / 多目标加权 | Autoregressive Ranking | HSTU | 高(Meta 上线) |
| 第三层重排 / Slate | listwise + Generator-Evaluator | 直接生成 slate | OneRec、Seq2Slate 系 | 中(快手上线) |
| 第二层混排(业务分流) | calibration + multiplier + pacing + score shading | 硬约束 / 在线控制部分 GR 当前不解决 | — | 低 |
前三层在前面三大支柱里已经分别讲过 TIGER / HSTU / OneRec 的细节,这里只点出它们跟 cascade 各层的对应关系;其中召回侧 GR 实际有两条不同路线(TIGER 生成式召回 vs HSTU 序列建模式召回),需要分开看。这一节真正想说的是最后一行 —— 第二层混排里硬约束和在线控制这部分,是 next-token 范式天然不擅长、GR 当前没法很好满足的盲区,放到最后单独展开。
召回
传统召回是 user / item 双塔学 embedding,离线建 ANN 索引,在线做近似最近邻检索。GR 在召回侧其实有两条不同路线,对应前面讲的两类工作:
HSTU 路线:序列建模式召回 —— 不生成 item token,只是把双塔里 user 侧的 encoder 升级成 HSTU 序列模型,把更强的 user state \(A_t\) 投影成 query embedding,再喂给 ANN 索引做检索;item 侧仍然是 hash ID + embedding + ANN(详见前面路线一 HSTU 的输出层讨论)。这条路线保留了 ANN 索引可独立部署、可独立更新的工程优势,但牺牲了” 泛化到没见过 item” 的能力。
TIGER 路线:生成式召回 —— 给定历史行为序列,自回归生成下一个 item 的 semantic ID(详见前面 Item Tokenization 节)。这一步相对双塔召回最本质的差别不是” 换了一种 retrieval 方法”,而是让召回侧第一次拥有了泛化到没见过的 item 的能力。双塔召回里,没出现在训练集的 item 几乎没法被召回;而 GR 召回里,只要新 item 的 semantic ID 落在已学过的前缀空间里,就有可能被生成出来。代价是 transformer memory 本身就是 index,模型重训意味着索引重训,两者不再可以独立部署(详见前面” 与 ANN 的关系” 段)。
需要特别区分两个层面 —— 召回任务和工业级召回 ——TIGER 只在第一个层面被验证过:
- 召回任务层面(已验证):TIGER 论文确实做的是召回任务的实验 —— 给定用户历史,生成下一个 item 的 semantic ID,再做 constrained decoding 映射回真实 item。这本身就是召回任务的形态,论文标题 “Generative Retrieval” 也明确把 TIGER 定位成生成式召回。
- 工业级召回层面(未验证):TIGER 论文用的 benchmark 是 Amazon Reviews 这类序列推荐学术数据集,对比的 SOTA 主要是 SASRec / BERT4Rec 等序列推荐模型,不是双塔召回模型;也没有在百万 / 亿级 item 池 + ANN 索引的工业召回场景下做实验。所以” vs 双塔 + ANN” 更多是范式层面的对比(用 transformer memory 替代 ANN 索引),不是论文实验直接对比出来的结论。
这两层区分是 TIGER 路线” 开放新可能性” 但工业落地证据相对薄弱的根源 —— 它在学术 benchmark 上证明生成式召回任务本身可行,但工业级召回能不能跑过成熟的” 双塔 + ANN” 链路,目前还没有公开证据。
这两条路线的工业落地度差别很大:TIGER 路线只在学术 benchmark(如 Amazon Reviews,对比对象是 SASRec / BERT4Rec 等序列推荐模型)上验证过生成式召回任务本身可行,没有在百万/亿级 item 池 + ANN 索引的工业召回场景下做过实验、也没有公开上线证据;HSTU 路线随 HSTU 在 Meta 多产品上线而天然带量。换句话说,召回侧真正已经在工业跑通的 GR 形态,是 HSTU 那条” 序列建模 + ANN” 的路,而不是 TIGER 那条” 完全生成式” 的路 —— 后者更像” 开放新可能性的方向”,前者是” 已经被验证的落地形态”。
第一层精排
HSTU 是对 cascade 第一层最根本的挑战 —— 不再 pointwise 打分,而是 next-action 序列预测(把推荐从” 逐 \((u,i)\) 打分” 重述成” 给定历史行为序列,预测下一步可能发生什么行为”)。不再把” 多目标加权” 当作核心,而是用 scaling law + 大模型容量自动学多目标之间的隐式权衡(详见前面路线一)。
跟前面三大支柱唯一需要在这里强调的差别是:HSTU 挑战的是上一篇里” 第一层打分公式 \(f_\theta(u,i,x)\)“这个数学形式本身,不是 item 表征。HSTU 没有用 semantic ID,官方实现里大部分还是 hash 体系 —— 这意味着即使一个团队不打算切 semantic ID,也可以独立尝试 HSTU。这一点是 GR 在精排和召回两层可落地性差异的根源。
第三层重排 / Slate
OneRec(arXiv:2502.18965)用一个 encoder-decoder 一口气生成整张 list,是上一篇里第三层最自然的演进。
上一篇把第三层方法分成三类:约束重排、列表重排、Slate 优化。其中” 列表重排” 最常见的工业实现是 Generator-Evaluator:generator 产出多条候选排列,evaluator 给每条排列打整体效用分。OneRec 把这两件事统一在一个 transformer 里:
- decoder 既是 generator(自回归生成排列),又通过 next-token loss 隐式承担 evaluator 的角色
- 训练时用 RQ - VAE semantic ID 表征 item,让” 相邻 item” 在 token 空间也相邻
- 用 DPO 做偏好对齐(详见前面” 训练目标:从 next-token 到偏好对齐” 节)
也就是说,OneRec 把 listwise 和 Slate 两件事统一在一个生成框架里,是上一篇第三层的” 下一代形态”。
第二层混排:硬约束与在线控制是 GR 当前盲区
这是这一节最重要的一段,也是最容易被忽略的一段。
上一篇里第二层混排做的事情是”多业务之间、带约束的流量分配”:calibration、multiplier、pacing、score shading、最小流量保护、广告 load 上限…… 这些问题需要区分两类来看:
- 软偏好类(多目标之间的隐式权衡、用户偏好对齐)—— 这一部分可以放进 GR 框架,用 DPO / reward 对齐来学(详见前面” 训练目标:从 next-token 到偏好对齐” 节)
- 硬约束 + 在线控制类(pacing、load 上限、score shading、calibration)—— 这一部分是 next-token 范式天然不擅长、GR 当前没法很好满足的盲区
后一类问题的共同特征是:它们不是” 预测下一个 token” 的问题,而是”在受约束的资源条件下做在线控制” 的问题。
next-token 范式天然不适合表达这类问题:
- pacing 控制器需要长时间窗口的反馈累积,next-token loss 是逐步的
- load 约束是硬约束、不是软偏好,DPO 风格的 reward 对齐不适合表达
- score shading 本质是一个对偶变量(影子价格)的在线估计,更像控制论问题而不是生成问题
- 各业务的 calibration 量纲对齐也不是” 生成” 能解决的
所以即使一个团队全面切了 GR,业务级混排层(第二层)里硬约束和在线控制这部分仍然要保留传统方法。这是 GR 工业落地非常重要、但很少被论文讨论的一个事实。
总的来说,GR 对第一层是颠覆性的(HSTU),对召回是开放新可能性的 ——TIGER 那条完全生成式召回是” 新可能性的方向”,HSTU 那条” 序列建模 + ANN” 是” 已被验证的落地形态”,对第三层是统一性的(OneRec);第二层混排里软偏好可放进 GR 框架,但硬约束与在线控制部分(pacing / load / score shading / calibration)next-token 范式天然不擅长,仍然要保留传统方法。
实际落地可行性判断
这一节把前面散落各处的判断收拢成一张可操作的清单。判断 GR 在具体业务上是否可行,关键不是” 它整体是不是噱头”,而是把它拆成若干独立技术点 —— 每个点的工业证据强度不同。下面先逐项过证据,再落到” 什么业务现在该试” 和” 怎么试”。
| 技术点 | 工业证据 | 主要依据 |
|---|---|---|
| Semantic ID / RQ-VAE | 已验证 | TIGER 实验充分;OneRec、HLLM 都依赖它;是生成 item token 路线的前提 |
| HSTU + 推荐 scaling law | 已验证(最强) | Meta 1.5T 参数上线 |
| 端到端 GR 替代 cascade | 短视频 / 本地生活已有公开验证,独立验证仍有限 | OneRec / OneLoc / OneRec V2 等快手技术谱系案例较完整,但跨公司验证不足 |
| LLM-as-Recommender(P5 / BIGRec / LlamaRec) | 学术有效,工业未验证 | benchmark 漂亮;延迟和行为信号注入两个根本问题没解决 |
| GR + DPO 偏好对齐 | 短视频已验证,稀疏 reward 未解 | OneRec 在 watch-time 上有效;稀疏 reward 场景没解 |
| GR 解决冷启动 | 证据较强 | semantic ID + content encoder 天然带语义结构;HLLM 长尾实验证据 |
| GR 替代业务级混排 | GR alone 不能替代 | pacing / load / calibration 仍需要外部控制器和传统在线控制机制 |
| GR 推理延迟 | 仍是瓶颈 | OneRec V2 砍掉 94% 算力是进展,但相比 cascade 仍偏高 |
如果一个业务同时满足下面多条,那么尝试 GR 是值得的:
- 行为数据量足够大:scaling law 才能起作用。一个粗略的经验门槛是亿级 DAU、十亿级日交互
- 主反馈稠密及时:短视频 watch-time、信息流停留这种 dense reward 是 GR + RL 对齐能起作用的前提
- 业务对 item 内容理解 / 冷启诉求强:内容平台、UGC 平台、跨域推荐
- 召回环节明显是瓶颈:双塔召回上限明显,长尾覆盖差,那么 generative retrieval 是收益最直接的入口
- 列表组合质量诉求高且目标相对单一:feed 场景的 slate generation 受益最大
反过来,如果业务有下面任何一条特征,那么短期内不建议把 GR 当作主要方向:
- 强约束、强多目标:广告、电商场景同时要管 load、pacing、calibration、营收。GR 可以学习部分软偏好,但很难单独承担这些硬约束和在线控制
- 推理延迟极敏感:搜索、广告 RTB 这种几十毫秒预算
- 业务数据规模不够大:scaling law 用不出来,反而被通用架构拖累
- 主反馈稀疏延迟:长留存、复购、转化为主目标的场景
如果决定推进 GR,一个相对稳健的路径是分阶段:
- 先把 semantic ID 落地,逐步替代 hash ID。这一步即使不上完整 GR,也能在冷启动和长尾上拿到收益
- 召回侧做 generative retrieval pilot,和现有双塔召回并行小流量验证
- 精排侧尝试 HSTU 风格的 scaling 实验,先看在自己业务上 scaling law 是否真的成立 —— 这是决定后续投入的关键决策点
- 当 1-3 都验证后,再考虑 slate generation + DPO 对齐
- 业务级混排层(带约束分流)保留传统方法,不要试图用 GR 替代全部
这个路径背后的逻辑是:每一步都保留了回退余地,每一步的 ROI 都可以独立评估。和直接” 端到端上 GR” 相比,工业风险低得多。
总结
回到标题的问题:GR 替代的不是 cascade 这个系统形态本身,而是 cascade 背后的一部分建模假设。
它首先替代的是 “item 只是无结构 ID” 的假设。semantic ID / RQ - VAE 把 item 从一个 hash key 变成有层级结构的 token,这对冷启动、长尾和生成式召回都很关键。但这主要服务于 TIGER / OneRec 这类生成 item token 的路线,并不是所有 GR 形态的前提。
它也替代了 “每个 item 可以独立打分” 的部分假设。HSTU 把推荐从 pointwise 打分推进到行为序列建模,并且在大规模 compute 下展示了推荐模型的 scaling law;OneRec 则更进一步,把召回、排序、slate 生成压进一个端到端生成框架里。两者都叫 GR,但工程含义完全不同:HSTU 更像是级联系统里的强 backbone,OneRec 才是在挑战 cascade 的整体链路。
但 GR 没有替代业务级混排和在线控制。pacing、load、calibration、score shading 这些问题本质上是带约束的资源分配,不是 next-token prediction。GR 可以学习软偏好和部分多目标权衡,但硬约束仍然需要外部控制器和传统机制兜底。
所以更准确的判断是:GR 不是 cascade 的终结,而是把推荐系统里的若干关键环节重新打开了。semantic ID 和 HSTU 的工业证据已经比较强;端到端 GR 以 OneRec 技术谱系为代表,短视频和本地生活场景已有公开验证,但跨公司独立验证仍然有限;LLM-as-Recommender 在主流推荐链路里仍更像局部增强,价值主要在长尾、冷启、内容理解和对话式场景。
如果一个业务行为数据极大、反馈稠密及时、约束相对单一,GR 值得系统性投入;如果业务延迟极敏感、硬约束很多、reward 稀疏且延迟,GR 更适合作为局部模块试验,而不是直接替代整套 cascade。
参考文献
- Understanding Scaling Laws for Recommendation Models (Ardalani et al., arXiv:2208.08489)
- Recommender Systems with Generative Retrieval (TIGER, NeurIPS 2023)
- Actions Speak Louder than Words: Trillion-Parameter Sequential Transducers for Generative Recommendations (HSTU, ICML 2024)
- OneRec: Unifying Retrieve and Rank with Generative Recommender and Iterative Preference Alignment
- OneRec Technical Report
- OneRec-V2 Technical Report
- OneLoc: Geo-Aware Generative Recommender Systems for Local Life Services
- HLLM: Enhancing Sequential Recommendations via Hierarchical Large Language Models for Item and User Modeling
- Large Language Models Are Universal Recommendation Learners (URM)
- P5: Recommendation as Language Processing
- LlamaRec: Two-Stage Recommendation using Large Language Models for Ranking
- BIGRec: A Bi-Step Grounding Paradigm for LLMs in Recommendation
- MTGR: Industrial-Scale Generative Recommendation Framework in Meituan (KDD 2025)
- 个性化排序公式:从个性化精排到个性化混排再到全局重排(本博客上一篇)