OneRec 提出了一种统一的生成式推荐系统架构,打破了传统“召回-粗排-精排”级联式推荐流程,使用单一生成模型同时完成召回与排序任务。该系统由快手团队研发,并成功部署于短视频主场景。
Online A/B Test 表现:
模型 | 总观看时长 | 平均观看时长 |
---|---|---|
OneRec-1B + IPA | +1.68% | +6.56% |
User positive action sequence,将短视频的多模态表征,通过量化的方式离散化成token序列
对于每个视频 v i \mathbf{v}_i vi,会包含:
这一部分是图中最左边部分,主要作用如下:
模块 | 功能 |
---|---|
嵌入(Embedding) | 把视频的文本、图像、音频等模态编码为 dense 向量 e ∈ R d \mathbf{e} \in \mathbb{R}^d e∈Rd |
对齐(Alignment) | 把不同模态编码结果投射到统一推荐语义空间,通过对比学习构建语义一致性 |
嵌入部分快手使用的是自己的多模态LLM, 这个没有公开,我们可以用自己知道的猜下:
模态 | 内容 |
---|---|
文本 | 标题、描述、标签(可用 BERT 编码) |
图像 | 封面图、视频首帧(可用 CLIP/VIT 编码) |
音频 | BGM 音频或音素(可用 Wav2Vec、YAMNet) |
结构化特征 | 视频长度、发布时间、作者等级等(dense vector) |
这些 encoder 可能是 frozen,或者微调部分参数(如 projection head)
可能使用以下融合机制之一:
h_concat = concat([h_text, h_img, h_audio, h_struct]) # → ℝ^1472
h_fused = MLP(h_concat) # → ℝ^1024
将文本为 query,图像/音频为 key/value 做一次 cross-attention:
h_text = BERT(text)
h_img = ViT(image)
h_audio = Wav2Vec(audio)
h_fused = MultiModalAttention(query=h_text, key=[h_img, h_audio], value=[h_img, h_audio])
h_fused = Pooling(h_fused) → ℝ^1024
到这里就是论文公开的部分了。
采用 InfoNCE 对比学习:
正样本对:用户历史点击 + 当前正样本(Trigger–Target)
负样本对:同 batch 中其他 item
损失形式:
L contrastive = − log exp ( sim ( e trig , e tgt ) / τ ) ∑ j exp ( sim ( e trig , e j ) / τ ) \mathcal{L}_{\text{contrastive}} = -\log \frac{\exp(\text{sim}(e_{\text{trig}}, e_{\text{tgt}})/\tau)}{\sum_{j} \exp(\text{sim}(e_{\text{trig}}, e_j)/\tau)} Lcontrastive=−log∑jexp(sim(etrig,ej)/τ)exp(sim(etrig,etgt)/τ)
所有多模态输入 → 一个统一语义空间下的向量 e i ∈ R 1024 e_i \in \mathbb{R}^{1024} ei∈R1024
所有模态嵌入向量会被拼接或加权融合为一个统一的 e i ∈ R d \mathbf{e}_i \in \mathbb{R}^d ei∈Rd,如 d = 1024 d=1024 d=1024。
这一部分是图中中间部分,将嵌入 e i \mathbf{e}_i ei 编码为离散语义 token 序列(例如
),具体的每一个item会生成3个token,item之间使用Sep分隔
主要思想是利用之前的文章QARM: Quantitative Alignment Multi-Modal Recommendation at Kuaishou 进行序列化编码,主要的原理叫Residual Vector Quantization(RVQ),核心原理是通过几个离散化token序列代表原来稠密的dense向量。
我们来看个实际例子
输入向量:
x = [4.1, 2.8]
三层聚类中心(简化示意):
[[0,0], [3,2], [6,1], [5,5]]
[[0,0], [1,1], [-1,-1], [2,-2]]
[[0,0], [0.5,0.5], [-0.5,-0.5], [1,1]]
Tokenizer 运行过程:
[3,2]
最接近 x
[4.1, 2.8] - [3,2] = [1.1, 0.8]
[1.1, 0.8]
,找到 [1,1]
最近[0.1, -0.2]
[0.1, -0.2]
,找到 [0,0]
最近最终输出:
token(x) = [1, 1, 0]
表示:
x ≈ codebook_1[1] + codebook_2[1] + codebook_3[0]
= [3,2] + [1,1] + [0,0] = [4, 3]
对比原始向量:
[4.1, 2.8]
[4.0, 3.0]
下面讲快手的优化
快手采用了Balanced KMeans对聚类进行了优化,因为传统的聚类会有token collapse问题(有些中心被大量item占据,但是有些中心却没有人是用,这样的话模型就学不到token)
想法(注意,这段文章中没有出现)
给定:
实现方式一:容量限制型 KMeans(Hard Balanced)
每个聚类最多分配 N / K + δ N/K + \delta N/K+δ 个样本:
这样可确保最终每个中心分配样本数近似相等。
⚙️ 实现方式二:Soft Balanced with Penalty
加入“频次惩罚项”,例如每个中心在选样本时加上一个 penalty:
effective_dist i , j = ∥ x i − c j ∥ 2 + λ ⋅ f j \text{effective\_dist}_{i,j} = \|x_i - c_j\|^2 + \lambda \cdot f_j effective_disti,j=∥xi−cj∥2+λ⋅fj
其中:
这种方式在训练中平滑惩罚热门中心,促使样本选择更冷门的 token。
模型整体结构由一个Transformer Encoder和Transformer Decoder组合而成。
类似语言模型:
P( | )
P( | , )
…用户历史行为序列,tokenized 后变成一串 token(每个 item = 3 tokens):
[SEP] <a_6> <b_1> <c_5> [SEP] <a_2> <b_1> <c_7> ...
Embedding Layer
d_model
维(如 768/1024)向量×N/2 层 Encoder Block(如 N=12,共用 6 层)
输出
对应每个 token 的 contextual 表示:
E_output = [e₁, e₂, ..., e_L],L = token 序列长度,eᵢ ∈ ℝ^{d_model}
这些 token-level 表达作为 decoder cross-attn 的 key/value。
Decoder 从 [BOS]
开始生成推荐目标 token 序列, 每次预测一个token,直到生成特殊token[EOS]为止,所生成组合成一个Session,:
Session = [BOS] <a_9> <b_7> <c_1> [BOS] <a_4> <b_5> <c_4> [BOS] ...[EOS]
每一步预测当前 token,前面 token 已知。
Embedding Layer
×N/2 层 Decoder Block(MoE支持)
输出
对每个输入 token,输出下一 token 的概率分布:
D_output = [p₁, p₂, ..., p_L],pᵢ ∈ ℝ^{V}(V 为 token vocabulary size)
用于计算 token-level cross-entropy loss(Next Token Prediction)
未完待续