OneMall 是快手在 OneRec 之后针对电商场景推出的端到端生成式推荐框架。OneRec 主要面向娱乐短视频,OneMall 则要应对电商特有的三大挑战:
🎯 多品类物品
商品卡(Product-card)、购物短视频(Short-video)、直播(Live-streaming)具有截然不同的语义特征和推荐逻辑,一套 Tokenizer 需统一表达。
🪙 行为极度稀疏
电商决策链路长(曝光→点击→购买),正向行为信号远比娱乐内容稀少,模型需要更强的信号利用能力。
💰 单目标 GMV
电商 KPI 高度集中于 GMV,对模型精度要求更高;娱乐场景可以多目标均衡,电商必须向 GMV 对齐。
🤖 对标 LLM 范式
OneMall 完整对齐 LLM 的"预训练 + 后训练"思路:NTP 预训练 + RL 后训练,让推荐系统吃到 LLM 工程红利。
Tokenizer 是生成式推荐的基础——它决定了物品如何被编码成离散 token 序列(Semantic IDs)。OneMall 的 Tokenizer 必须同时满足:
- 真实语义:反映商品的实际相似关系(类目、品牌、风格相近)
- 业务语义:反映商品的商业关联(共购、互补、替代)
- 多品类适配:商品卡、短视频、直播各有不同的表示需求
解决方案是用 LLM 微调作为语义压缩骨干,再通过 Res-Kmeans + FSQ 两阶段量化生成多层 Semantic IDs。
2.1 Item2Item 数据过滤
OneMall 收集两类 Item2Item 对作为微调数据:
🛍️ 商业相关对
商品卡 ID → 商品卡 ID,来自双塔召回模型的近邻空间或 Swing 统计算法。每个商品最多出现 40 次(下采样消除曝光偏差),共 7000 万样本。
🎬 观看体验对
短视频 ID → 商品卡 ID,筛选条件:用户长看(1-5 分钟)某娱乐/电商短视频后,随后点击了某商品。额外过滤掉新闻/喜剧/舞蹈等无关类目,共 1200 万样本。
场景:某用户在看一个"运动达人穿装备打球"的短视频(长看了 3 分钟),随后点击了"某品牌跑鞋"。
这条 (短视频ID, 跑鞋ID) 就是一个高质量的"观看关联"正样本。
Tokenizer 微调后,运动类短视频和跑鞋类商品会在 embedding 空间里相互靠近,
使得模型在解码时能从"用户看了运动视频"这个上下文推断出"用户可能想买运动鞋"。
2.2 语义压缩骨干(LLM 微调)
模型结构:Swin-Transformer(视觉编码)+ Qwen2.5 1.5B(文本编码),特殊 token <EMB> 的最后隐状态作为最终 embedding。冻结 ViT,微调 Projector + LLM,目标函数为 InfoNCE 对比学习。
- 商品卡输入:主图(224×224)+ 商品标题
- 短视频输入:采样 6 帧图(224×224)+ 标题/OCR/ASR
- 直播:内容动态变化,不能提前生成,用双塔模型的 item tower embedding + 当前在售商品 SID 特征
2.3 Semantic ID 生成流程(ResKmeans + FSQ)
量化分两阶段:
-
1前两层:Res-Kmeans 残差量化
对 embedding 做逐层 K-Means,每层学到当前最优 codebook 后,用"原 embedding - 最近 codebook 向量"得到残差,再对残差做下一层 K-Means。生成 $c_1, c_2 \in \{1,\ldots,K\}$。 -
2第三层:FSQ(Finite Scalar Quantization)
用二值化 16-bit MLP 将残差 $m - C_1[c_1] - C_2[c_2]$ 量化为 4096 码。FSQ 预先固定 cluster 中心,确保分区均匀,大幅降低 SID 碰撞率(36% → 11%)。
- $M \in \mathbb{R}^{N \times d}$:随机采样的物品 embedding 集合(数千万条)
- $K$:每层 codebook 大小(通常 4096)
- $C_l \in \mathbb{R}^{K \times d}$:第 $l$ 层的 codebook(聚类中心矩阵)
- $\text{NearestRep}(M, C_l)$:对 $M$ 中每个向量找到 $C_l$ 中最近中心,返回对应中心向量
- $M_1$:第一层残差,即"原 embedding 减去最近中心后的差值"
假设某跑鞋商品 embedding 为 $m = [0.8, 0.3, -0.2, ...]$(128维):
1. 第一层 K-Means 找到最近 codebook 中心 $C_1[47]$(代表"运动鞋"大类),
残差 $m_1 = m - C_1[47]$(剩余更细粒度的语义差异)
2. 第二层 K-Means 对 $m_1$ 找到最近中心 $C_2[312]$(代表某品牌/价位子类),
残差 $m_2 = m_1 - C_2[312]$
3. FSQ 对 $m_2$ 做 4096 路编码,得 $c_3 = 1847$(精细区分同价位不同款式)
最终该跑鞋的 SID 为 $\{47, 312, 1847\}$,三层从粗到细刻画物品语义。
Kmeans 优化目标是最小化簇内距离,不考虑簇间距离,容易产生"中心坍塌"(多个中心靠得很近)。这导致不同商品被映射到同一 SID(碰撞率高达 36%,即一个 SID 对应多件商品),严重影响生成准确性。FSQ 预先固定均匀分布的中心,碰撞率降至 11%,Exclusive(每个 SID 唯一对应一件商品)比例从 86% 升至 95%。
OneMall 采用 Decoder-Only 架构,通过 Cross-Attention 注入用户行为序列,通过 Causal Self-Attention + Sparse MoE 自回归生成 Semantic IDs。
各压缩为 [B, M, D]
注入解码 query
+ Sparse MoE
3.1 Query-Former:长序列压缩
电商场景下用户行为序列极长(曝光序列可能有 1000+ 条),直接送入 Transformer 计算量爆炸。OneMall 借鉴 BLIP-2 的 Q-Former,用少量可学习 query 从长序列中提炼出紧凑表示。
- $Q_{\text{click}} \in \mathbb{R}^{M \times D}$:$M$ 个可学习 query 向量($M=10$,表示压缩后的表示数量)
- $H_{\text{click}} \in \mathbb{R}^{H \times D}$:用户点击序列的原始 embedding($H=500$,序列长度)
- $D$:embedding 维度(128)
- Q-Former 内部:query 对 $H$ 做 cross-attention,输出 $M$ 个浓缩后的向量
同样对购买序列($F_{\text{buy}}$)、曝光序列($F_{\text{exposure}}$)、物品侧特征($F_{\text{item}}$)各做一个 Q-Former 压缩,显著降低 Cross-Attention 的计算量(GFLOPs 降低 3.7×,性能损失极小)。
输入:用户最近 500 次点击的商品 embedding 矩阵 $H \in \mathbb{R}^{500 \times 128}$
Q-Former 有 10 个可学习 query($Q \in \mathbb{R}^{10 \times 128}$),每个 query 通过 cross-attention 从 500 条记录中"选出"自己关注的部分。
输出:$F_{\text{click}} \in \mathbb{R}^{10 \times 128}$,10 个 128 维向量,浓缩了 500 条历史的核心信息。
效果:GFLOPs 从 34.4 降至 9.2(节省 73%),HR@50 仅降低 0.5pp。
3.2 Cross-Attention:历史信息注入
将压缩后的多路用户历史(点击、曝光、购买)拼接,通过 $L$ 层 Cross-Attention 注入到解码侧的 SID token 序列中:
- $s^{L-1}_0$:第 $L-1$ 层的 BOS token 表示(解码侧初始 token)
- $s^{L-1}_{1,2,3}$:第 $L-1$ 层的三个 SID token 表示(自回归预测时逐步填充)
- $W^L_q, W^L_k, W^L_v \in \mathbb{R}^{D \times D}$:第 $L$ 层 Cross-Attention 的可学习参数矩阵
- $\{F_{\text{click}}, F_{\text{exposure}}, F_{\text{buy}}, \ldots\}$:各路压缩后的用户历史 embedding
3.3 Sparse MoE:扩展模型容量
Cross-Attention 之后,再经过 Causal Self-Attention(保持自回归约束)+ Sparse MoE FFN(扩展参数容量,但推理时只激活部分专家):
- $\text{CausalSelfAtt}$:带 causal mask 的标准自注意力,确保预测 $s_k$ 时只能看到 $s_1, \ldots, s_{k-1}$
- $\text{SparseMoE}$:稀疏专家混合 FFN(参考 DeepSeek-V3 的 loss-free 负载均衡)
- $+ \{s^{L-1}_0, \ldots\}$:残差连接
- 模型规模:0.5B 总参数,激活参数 0.1B(24 个专家,每次激活 2/24)
3.4 训练目标
两个同时优化的目标:
- $\{s_1^\star, s_2^\star, s_3^\star\}$:目标物品的真实三层 SID(ground-truth token 序列)
- $\mathcal{L}_{\text{NTP}}$:自回归 NTP 主目标,交叉熵损失
- $s^L_3$:解码最后一层(完整 SID 路径的终态隐向量)
- $f_{\text{item}}$:物品侧特征 tower 的输出 embedding(包含商品类目、价格、店铺等精细特征)
- $\mathcal{L}_{\text{contrastive}}$:辅助对比学习,让模型输出的隐向量与物品特征对齐(batch 内负样本)
问题:SID 是粗粒度的离散 token,无法区分同一 SID 路径下的相似商品。
例如 $\{47, 312, 1847\}$ 可能对应 20 款不同跑鞋,NTP loss 只能学到"生成这个 SID",不能区分是哪双鞋。
解决:让解码输出的隐向量 $s^L_3$ 通过 in-batch 对比学习与物品精细特征(价格、品牌、颜色等)对齐。
实验:加入对比学习辅助目标后,HR@50/100/500 分别提升 +1.5%/+1.7%/+1.7%。
NTP 训练让模型学会分布匹配,但不等于业务 KPI 最优。OneMall 引入以排序模型为奖励信号的 RL 后训练,让召回模型直接被排序模型的 CTR/CVR/GPM 指导。
4.1 奖励建模
在线排序模型(可使用全量特征:用户+物品+交叉特征)作为 Reward Model,输出多个预测概率,融合为单一奖励分:
- $\hat{y}_{\text{ctr}}$:排序模型预测的点击率
- $\hat{y}_{\text{ctcvr}}$:排序模型预测的点击转化率(CTCVR)
- $\hat{y}_{\text{egpm}}$:预测的电商毛利润(EGPM)
- $\alpha, \beta, \gamma$:手工设定的融合权重(本文 $\alpha=1.0, \beta=30.0, \gamma=1.0$,量级对齐)
- Advantage 计算:$A_i = \frac{r_i - \text{mean}(r)}{\text{std}(r)}$,batch 内归一化
4.2 DPO 和 GRPO 两种策略
OneMall 尝试了两种 RL 优化策略:
DPO(直接偏好优化)
将候选集按 Advantage 排序,取最高分的作正样本 $o_{\text{pos}}$,从低分候选中采样(或取最低分)一个作负样本 $o_{\text{neg}}$,构成单一偏好对送入 DPO loss。
GRPO(组相对策略优化)
从 $n$ 个候选中随机采样 $m$ 个,基于 Advantage 做 clip 截断的概率比优化。
- $\pi_\theta$:当前策略模型(Policy Model,正在被更新的参数)
- $\pi_{\theta_{\text{ref}}}$:参考模型(定期从 Policy 同步,frozen 作为基准)
- $o_{\text{pos}}$:正样本 SID 序列(Advantage 排序最高的候选)
- $o_{\text{neg}}$:负样本 SID 序列(Advantage 较低的候选)
- $\lambda$:偏好对比强度超参(0.1-0.5)
- $\delta$:加在分母上防止参考模型概率为零导致除零,是一个小正常数
- $\sigma$:sigmoid 函数,将内部对比分值映射到 $(0,1)$ 再取 $-\log$
- $m$:每次训练随机采样的候选数(从 $n$ 个候选里取 $m$ 个)
- $\pi_\theta(o_i|q) / (\pi_{\theta_{\text{ref}}}(o_i|q) + \delta)$:当前策略相对参考策略的概率比(分母加 $\delta$ 防除零)
- $\text{clip}(\cdot,\, 1-\epsilon,\, 1+\epsilon)$:将概率比截断在 $[1-\epsilon, 1+\epsilon]$ 内,防止单个样本主导更新(PPO-style 稳定训练)
- $A_i$:候选 $o_i$ 的 Advantage,由 Ranking Model 打分归一化得到($A_i = (r_i - \text{mean}(r))/\text{std}(r)$)
- $\epsilon$:clip 截断超参(通常 0.1-0.2)
- 取 $\min$ 而非直接相乘,是为了对正负 Advantage 做非对称处理(标准 PPO 写法)
最终联合损失:
传统流程:召回模型训练时只用 InfoNCE(用户是否点击),无法感知"点击后有没有买"。
OneMall RL:每次从训练流量中采样 2%,用当前召回模型做 Beam Search 生成 768 个候选;
排序模型对这 768 个候选分别打出 (CTR, CVR, GPM),融合为奖励分 $r$;
GRPO 用奖励 Advantage 更新召回模型,直接鼓励"生成高价值商品"。
结果:召回模型输出的 Top10 商品的 CTR/CTCVR/GPM 全部提升,打破了传统召回与排序目标不一致的壁垒。
5.1 Scaling 实验(短视频场景)
| 规模 | 层数 | Att-Dim | Expert | Acc-SID1 | Acc-SID2 | Acc-SID3 | HR@50 | HR@100 | HR@500 |
|---|---|---|---|---|---|---|---|---|---|
| 0.05B | 2 | 1024 | - | 14.5% | 43.9% | 61.0% | 32.9% | 41.3% | 60.5% |
| 0.1B | 4 | 1024 | - | 14.9% | 46.2% | 63.6% | 34.7% | 43.8% | 63.2% |
| 0.5B-A0.1B | 4 | 1024 | 12/2 | 16.0% | 50.6% | 69.3% | 44.7% | 56.0% | 74.2% |
| 1.3B-A0.1B | 4 | 1024 | 24/2 | 16.2% | 51.7% | 71.7% | 45.6% | 57.3% | 76.0% |
关键观察:dense 0.1B → sparse 0.5B-A0.1B 是最大跃升(HR@50 +10pp),说明 MoE 扩容效果显著。1.3B 相比 0.5B 进一步提升,Scaling 趋势持续。
5.2 基线对比(三品类场景)
| 场景 | 方法 | HR@50 | HR@100 | HR@500 |
|---|---|---|---|---|
| 商品卡 | SASRec-0.5B-A0.1B | 23.2% | 30.4% | 45.1% |
| TIGER-0.5B-A0.1B | 29.5% | 37.1% | 53.7% | |
| OneMall-0.5B-A0.1B | 34.3% | 40.9% | 59.3% | |
| 购物短视频 | SASRec-0.5B-A0.1B | 30.2% | 41.9% | 66.3% |
| TIGER-0.5B-A0.1B | 35.1% | 47.8% | 72.5% | |
| OneMall-0.5B-A0.1B | 44.7% | 56.0% | 74.2% | |
| 直播 | SASRec-0.5B-A0.1B | 53.9% | 58.8% | 68.4% |
| TIGER-0.5B-A0.1B | 57.3% | 63.5% | 73.7% | |
| OneMall-0.5B-A0.1B | 65.9% | 69.1% | 80.5% |
5.3 线上 A/B 实验
| 场景 | 曝光 | 点击 | 订单 | GMV |
|---|---|---|---|---|
| 商品卡 | +2.851% | +13.01% | +8.35% | +14.71% |
| 购物短视频 | +15.32% | +5.76% | +11.65% | +10.33% |
| 直播 | +2.78% | +2.53% | +4.47% | +4.90% |
三个场景全部正向,GMV 增益均超过 4.9%,最高达 14.71%。该系统已上线服务 4 亿日活用户。
🌟 核心亮点
- 多品类统一 Tokenizer:一套框架同时处理商品卡、短视频、直播三类异质物品,不同品类融入不同语义(商业/观看体验/动态),这是比 OneRec(纯娱乐短视频)更难的工程问题,做到了很好的统一。
- LLM 微调 Tokenizer:用 LLM(Qwen2.5 1.5B)的泛化能力解决长尾商品 embedding 质量差的问题,比纯协同过滤的 item tower 能更好覆盖冷启动物品。
- ResKmeans + FSQ 组合:用 FSQ 的规则均匀分区替代第三层 Kmeans,将 SID 碰撞率从 36% 降到 11%,是一个简单有效的工程 trick。
- Scaling Law 验证:证明电商生成式推荐同样存在 Scaling Law,MoE 是低推理成本扩容的关键路径。
- GRPO > DPO 的实证:在 e-commerce 推荐场景下,GRPO 的 group-level 归一化比 DPO 的 pairwise 对比提供更丰富的训练信号,值得借鉴。
⚠️ 值得注意的局限
- 直播 Tokenizer 问题:直播的 SID 用双塔模型 item tower embedding,而非 LLM 微调 embedding,语义能力相对较弱;动态商品变化的处理也只用了低学习率缓解,没有根本性解决。
- RL 只采样 2% 流量:RL 训练样本量受限,奖励信号覆盖范围有限,可能对长尾物品的价值估计不准。
- 手工融合权重:$\alpha=1.0, \beta=30.0, \gamma=1.0$ 是人工调参,不同业务场景需要重新调,缺乏自动化方法。
💡 对我们的启发
- 用 LLM 做 Tokenizer 是正途:纯协同信号(双塔)的 SID 会放大头部偏差,LLM 文本语义更均匀,尤其对长尾商品友好。
- Q-Former 是降低长序列成本的实用工具:3.7× GFLOPs 节省,性能几乎无损,适合迁移到其他需要多路长序列融合的场景。
- 排序模型作为奖励是工业 RL 的务实选择:不需要人工标注偏好对,直接复用已有排序模型,工程落地代价低。
- FSQ 解决 codebook collapse 是一个 trick:如果生成式推荐遇到 SID 碰撞率高的问题,用 FSQ 替换最后一层是一个成本很低的方案。