链载Ai

标题: 为什么说多模态是推荐系统破局的关键?来自饿了么一线的实战复盘 [打印本页]

作者: 链载Ai    时间: 昨天 22:35
标题: 为什么说多模态是推荐系统破局的关键?来自饿了么一线的实战复盘

引言

推荐系统作为互联网时代连接用户与信息的核心技术,正在经历从传统协同过滤向多模态智能推荐的重要变革。随着深度学习技术的快速发展,特别是大语言模型和多模态预训练技术的成熟,推荐系统开始从单纯依赖用户行为ID特征转向充分利用商品图像、文本描述等丰富内容信息的新范式。

笔者有幸于24年下半年和25年初深度参与了饿了么首页店铺推荐场景的多模态推荐系统设计与实现,以及生成式ranking前期技术方案的探索实践。在此过程中,在多模态推荐技术发展脉络、实践挑战以及生成式推荐技术方法探索等方面收获颇丰。趁着25年上半年总结的机会,希望将这些学习路径、技术探索过程、思考感悟以及实践经验进行系统性的完整回顾,整理成文作为学习笔记与大家分享交流。

文章主要内容包括:

希望这份总结能够为同样在多模态/生成式推荐领域探索的技术同学提供一些参考。

一、传统推荐算法向多模态的演进

1.1 传统方法回顾

推荐系统的基础架构通常由用户特征、物料特征和交互预测模块组成。在传统基于深度神经网络(DNN)的推荐系统中,特征工程是核心环节,其中ID类特征的处理尤为重要,其常见类别与处理流程如下:

用户ID特征:

物料ID特征:

特征编码:

ID特征的Embedding层通常不进行独立训练,而是与下游预测任务端到端联合优化。以下是一个典型的训练架构示例:

source: https://zhuanlan.zhihu.com/p/570911435

特征处理说明:

1. 用户基础特征:直接输入Embedding层;

2. 用户历史行为特征:序列item分别Embedding后拼接,经池化形成综合表征;

3. 候选item特征:当前曝光物料的特征向量;

训练任务设计:

实现方式:

评估指标:

然而,传统架构的ID特征方法存在一些本质局限:如新物料缺乏交互历史导致的冷启动问题,以及ID特征无法捕捉物料内容语义信息的问题。这些局限性推动了推荐算法的持续演进和创新。

1.2 技术演进

1.2.1 推荐算法的多元化发展(2018-2023)

注意力机制引入:DIN(KDD 2018)[1]在传统Embedding+MLP范式基础上,通过引入目标注意力机制(Target Attention)实现用户兴趣的动态建模。每个历史item与候选item进行向量减法运算后与原始序列向量拼接,输入全连接网络,生成反映用户动态兴趣的最终表征,突破了简单池化的信息损失限制。

图神经网络应用:以LightGCN(SIGIR 2020)[2]为代表,通过建模用户-物品交互图捕捉高阶协同过滤信号,简化图卷积网络结构并显著提升推荐效果。

对比学习引入:受计算机视觉启发,SGL(SIGIR 2021)[3]和CL4SRec(ICDE 2022)[4]等工作将对比学习应用于推荐系统,通过数据增强策略缓解数据稀疏性问题。

预训练范式探索:UniSRec(CIKM 2022)[5]和P5(RecSys 2022)[6]等工作借鉴NLP预训练经验,实现跨域知识迁移和统一任务建模,为推荐系统引入了预训练-微调的新范式。

1.2.2 大语言模型与多模态推荐的结合探索(2023-2024)

上述技术演进虽然在模型架构和学习范式上取得了显著进展,但本质上仍局限于ID特征和少量结构化特征的建模。随着深度学习在计算机视觉和自然语言处理领域的突破,特别是预训练大模型的成熟,推荐系统开始探索如何利用商品图片、描述文本等丰富的多模态内容信息。

2023年以来,大语言模型技术的快速发展为多模态推荐提供了新的技术基础,推荐算法开始从纯ID特征建模转向ID特征与多模态内容特征的深度融合。

1.2.2.1 多模态推荐的价值与挑战

多模态特征的引入主要解决了传统推荐系统的三大痛点:长尾item和长尾用户的行为序列数据不足问题、新item和新用户的冷启动问题、跨场景的推荐特征迁移问题。

然而,多模态推荐面临两个核心技术挑战:一是如何使多模态表征对齐推荐中的user-item交互关系,即在语义层面定义推荐中的相似item;二是稠密语义特征与稀疏ID特征如何联合训练,两类特征在维度、更新频率、训练方式等方面存在显著差异。

1.2.2.2 代表性工作及其技术创新

小红书AlignRec(2024.03):

AlignRec: Aligning and Training in Multimodal Recommendations

LLM2Vec

AlignRec通过联合训练策略系统性地解决了多模态推荐的核心挑战:

针对核心挑战的解决思路:AlignRec采用联合训练对齐策略,通过特征聚合模块将ID特征与多模态特征融合后,基于item融合特征相似度关系建模item语义特征,实现了深度融合而非简单拼接。

值得注意的是,AlignRec通过图文对自身mask训练得到融合表征的方式,大致等价于图文表征直接相加而缺乏对比学习。这种设计导致模型在基础表征阶段缺乏对item整体表征间相似度关系的理解,因此需要完全依靠后续的Aggregation Module通过LightGCN等复杂机制来重新建立内容与ID表征的对齐关系。

此外,小红书的Notellm系列工作[8,9]也同样值得关注,感兴趣的读者可进一步阅读相关论文。

阿里妈妈SimTier & MAKE(2024.07):

Enhancing Taobao Display Advertising with Multimodal Representations: Challenges, Approaches and Insights

SimTier & MAKE提出了基于语义交互关系的对齐策略,强调多模态特征的纯粹性:

针对核心挑战的解决思路:与AlignRec不同,SimTier完全从语义层面着手定义相似item,利用用户的搜索-购买行为链避免多模态特征退化为ID特征。这种策略的核心理念是保持多模态特征的语义纯粹性,避免被ID特征的协同过滤信号"污染"。

快手QARM(2024.11):

QARM: Quantitative Alignment Multi-Modal Recommendation at Kuaishou

QARM提出了基于ID交互关系的对齐策略,强调适配真实推荐场景:

针对核心挑战的解决思路:QARM采用基于ID特征交互关系定义相似item的策略,使多模态表征更适配User-Item交互行为分布。这与阿里妈妈的方案形成了有趣的对比:QARM认为应该让多模态特征适配现有的推荐交互模式,而阿里妈妈认为这样会使多模态特征退化为ID特征,应该完全从语义层面定义相似性。

1.2.2.3 技术路线总结与发展趋势

从这些工作可以看出,业界在多模态推荐的两大核心挑战上形成了不同的技术路线:

多模态表征对齐策略:

稠密与稀疏特征融合方案:

这些探索表明,多模态推荐正在从简单的特征拼接向深度语义对齐演进,不同的技术路线反映了对"语义纯粹性"与"行为适配性"平衡的不同理解,为后续生成式推荐的发展奠定了重要基础。

1.3 总结

综上所述,推荐算法正在从传统ID特征向多模态内容特征演进:早期的注意力机制、图神经网络奠定了动态建模基础,近期的对比学习、预训练方法提升了特征表征能力,而最新的AlignRec、SimTier、QARM等工作则直接探索了多模态信息在推荐中的应用。

这一演进过程中,多模态表征技术成为了关键的技术基础。无论是AlignRec的BEIT-3交叉注意力机制,还是QARM的语义ID量化编码,都依赖于高质量的多模态特征表示。同时,业界在多模态表征对齐策略上形成了不同的技术路线,反映了对"语义纯粹性"与"行为适配性"平衡的不同理解。这些技术探索和设计思考为构建有效的多模态推荐系统提供了重要指导,也为后续生成式推荐的发展奠定了坚实基础。因此,深入理解多模态表征技术的发展脉络和设计原则,对于构建高效的多模态推荐系统至关重要。

二、多模态表征技术发展

2.1 文本表征的两种范式

随着大语言模型的发展,文本表征技术形成了两种主要的技术路线,它们在架构设计和训练策略上存在显著差异:

2.1.1 Encoder-only架构表征

Encoder-only架构的表征方式是文本表征如BERT、GTE的主流方法。

架构特点:

全局特征提取策略:

典型工作:

GTE

2.1.2 Decoder-only架构表征

随着LLM的快速发展,为在表征技术上有效利用LLM强大的世界知识,以LLM2Vec[13]为代表的Decoder-only文本表征工作开始盛行,GTE同样发布了基于qwen的decoder-only类系列模型。

LLM2Vec

架构适配:

全局特征提取策略:

训练方法创新:

1. MNTP(masked next token prediction):

2.无监督对比学习:

2.1.3 Qwen3 Embedding(SOTA)

作为当前文本表征领域的代表性工作,Qwen3 Embedding[14]展现了decoder-only架构的最新发展水平:

双模型设计:

三阶段训练策略:

Stage 1 - 大规模数据合成(仅训练Embedding模型):

Stage 2 - 高质量数据精炼(双模型联合训练):

Stage 3 - 模型融合优化(双模型权重融合):

技术创新点:

2.2 视觉表征的核心方法

视觉表征技术主要围绕如何从图像数据中提取高层语义特征展开,形成以下主流范式:

2.2.1 CNN架构表征(以ResNet为代表)

架构特点:

全局特征提取策略:

训练优化:

2.2.2 Transformer架构表征(以ViT为代表)

架构适配:

全局特征提取策略:

训练方法创新:

1. 掩码图像建模(MIM):

2. 自监督对比学习:

2.2.3 两种视觉表征范式对比

特征维度

CNN架构

Transformer架构

表征能力

在小数据集上表现稳定

大规模预训练下效果更优

特征提取方式

局部到全局

全局注意力交互

位置信息处理

卷积固有感应

需显式位置编码

数据依赖性

相对低数据需求

需大规模预训练

计算效率

优化程度高

高分辨率计算昂贵

当前趋势

在特定场景仍有价值

主流视觉表征方法

文本表征与视觉表征技术的发展为多模态融合奠定了坚实基础,两种模态的表征方法在设计理念和技术实现上既有相似性又有互补性,为后续的跨模态对齐和融合提供了丰富的技术选择。

2.3 图文多模态表征核心方法

多模态表征技术根据不同模态信息的融合方式,主要分为协同表征和联合表征两大类技术路线:

2.3.1 协同表征方法:双塔架构的多模态对齐

协同表征方法采用独立的编码器分别处理不同模态信息,通过对比学习等方式实现跨模态对齐。

2.3.1.1CLIP[17]:奠定双塔对比学习基础

架构设计:

训练机制:

特点:

2.3.1.2ALBEF[18]:增强的多模态融合

架构改进:

多任务训练:

ALBEF

技术创新:

2.3.1.3 其他协同表征工作

在CLIP和ALBEF的基础上,还涌现出DeCLIP、FLAVA、CoCa等改进工作。DeCLIP通过多个预训练任务(图像自监督、文本自监督、跨模态自监督)用更少数据达到相近效果;FLAVA引入更多预训练任务如MIM和MMM损失;CoCa在ALBEF基础上加入解码器增强生成能力。这些工作在协同表征框架下不断优化训练策略和任务设计,但基本架构思路保持一致,此处不再一一展开。

2.3.2 联合表征方法:统一架构的深度融合

联合表征方法使用统一的模型架构同时处理多种模态信息,实现更深层次的跨模态理解。

2.3.2.1 早期探索工作

早期的联合表征探索包括VLMO、BLIP、BEiT-3等工作,它们的共同特点是从双塔结构向统一架构发展:VLMO通过Multiway Transformer实现模态共享;BLIP提出编码器-解码器混合架构并引入bootstrapping数据清洗;BEiT-3结合多种方法形成统一大模型。这些工作推动了多模态技术从双塔协同向统一建模的转变,为后续的VLM统一表征奠定了重要基础。

2.3.2.2VLM2Vec范式[19]:统一多模态表征的新突破

VLM2Vec

核心理念:将LLM2Vec的思路迁移至了多模态表征领域,直接基于预训练的多模态大模型训练得到多模态表征模型,充分利用其世界知识。

技术实现:

四大训练任务:

技术优势:

2.3.2.3GME[20]:统一多模态表征的典型实现

GME

核心理念:基于VLM2Vec范式,构建统一的多模态表征模型,解决传统方法需要部署多个独立模型或依赖OCR/Caption转换导致的信息损失问题。

技术实现:

三类检索任务:

技术优势:

2.3.3 技术发展趋势与展望

从协同表征到联合表征的演进反映了多模态技术的发展方向,但两种范式在不同场景下各有优劣:

联合表征的优势:统一架构实现深度跨模态融合,单模型处理多种任务,部署便捷,代表技术发展主流趋势。

协同表征的持续价值:

场景依赖的技术选择:

2.4 总结

通过对多模态表征技术发展脉络的梳理,我们可以看到该领域呈现出多元化发展态势:文本表征从Encoder-only向Decoder-only架构演进,视觉表征从CNN向Transformer迁移,而多模态表征则形成了协同表征和联合表征两条并行发展的技术路线。

这一技术演进为推荐系统提供了丰富的多模态特征提取选择:协同表征方法如CLIP提供了成熟稳定的图文对齐能力,且能够灵活组合当前SOTA的单模态编码器;联合表征方法如VLM2Vec、GME则展现了更强的跨模态理解能力,但在模型选择和优化上相对固化。

基于这一技术发展脉络和实际业务需求,我们在24年S2面向饿了么首页店铺推荐场景设计了多模态推荐方案,通过三阶段训练策略系统性地解决了多模态特征预训练、用户查询对齐以及与传统ID特征融合等关键技术问题。

三、饿了么首页推荐场景下的多模态推荐实践

在饿了么首页店铺推荐场景的实际应用中,用户的决策过程往往由商户/商品的多模态内容信息直接驱动。当用户浏览推荐页面时,商户图片的视觉呈现、文字描述的吸引力等内容特征是其最先感知到的信息,这些多模态信息在很大程度上决定了用户的点击和购买行为。

然而,如前文所述,传统推荐系统主要依赖ID特征进行建模,难以有效利用这些丰富的内容信息。特别是在本地生活场景中,商户的视觉展示(如店铺logo、菜品图片)和文本描述(如特色标签、用户评价)对用户选择具有重要影响,但这些信息在传统ID建模中往往被忽略。

基于这一观察,我们提出了多模态推荐解决方案,核心思想是在传统ID特征基础上引入商户的图像和文本信息,通过多模态表征学习更好地建模商户间的语义相似性,从而提升推荐系统对用户兴趣的理解和预测能力。

3.1 系统架构设计

针对本地生活推荐场景的特殊性,我们构建了基于双塔模型表征的多模态推荐系统。考虑到首页商户推荐的业务特点,我们设计了层次化的商户内容表征建模方法。

3.1.1 商户表征建模策略

基于搜索行为建模的动机:

在推荐场景中,用户的搜索-购买行为链能够准确反映用户的真实兴趣偏好。相比于传统的基于点击或浏览行为的建模方式,搜索行为包含了用户的明确意图表达,而最终的购买转化则验证了这种意图的真实性。因此,我们选择基于用户搜索-购买行为模式来定义店铺内容与用户兴趣的语义相似性。

用户行为模式分析:

用户的搜索行为呈现多样化特点:既有"搜品找店"(如搜索"麻辣烫"寻找相关店铺),也有"直接搜店"(如搜索"海底捞"),还有复合搜索意图(如"川菜火锅")。这些不同的搜索模式反映了用户对店铺认知的多个维度。

店铺内容表征设计:

为匹配用户多样化的搜索-购买行为模式,我们采用了店铺整体表征的建模方法:

这种设计能够同时满足用户"看店铺品牌"和"看商品特色"的不同决策需求。

3.1.2 三阶段训练策略

基于商户表征建模的设计思路,我们制定了三阶段渐进式训练策略:

阶段一:领域适配预训练

在本地生活图文数据上进行跨模态对比学习,建立适配垂直领域的基础表征能力。该阶段需要同时训练三类图文对齐任务:

阶段二:行为驱动微调

利用真实的用户搜索-购买行为数据进行对齐训练。根据用户查询的复杂度和店铺表征的丰富度,训练数据包含单query-单图和多query-多图两类,通过混合训练确保模型能够处理不同复杂度的匹配场景,该阶段同样包含三类对齐任务:

通过多维度的对齐学习,确保商户整体表征能够全面捕捉用户的真实购买意图。

阶段三:特征融合优化

参考工作[10],通过SimTier和MAKE技术实现多模态表征与传统ID特征的有效整合。

这种层次化的建模方法既保证了商户表征的完整性,又通过渐进式训练策略确保了不同粒度特征的有效学习和融合。这种设计思路从用户真实行为出发,确保了店铺表征能够有效捕捉用户在推荐场景下的潜在兴趣。

整体建模

3.2 Pretrain对齐领域图文

3.2.1 训练数据构建策略

基于本地生活业务特点,我们设计了三类图文对齐数据:

商品级图文对:商品图片配合类目、属性信息,通过MLLM生成详细的recaption,突出菜品特色、口味、价格等关键信息。(MLLM来自本团队训练的垂域多模态大模型)

店铺级图文对:店铺头图结合名称、简介、品类信息,利用LLM进行描述扩充,强调店铺特色和服务亮点。

混合级图文对:店铺与商品多图组合,构造反映完整经营特征的综合描述。

3.2.2 模型架构设计

我们在模型架构上设计两种建模方案,一是采用双塔式编码架构(EVL-sep)建模,并通过跨模态投影将文本与视觉表征统一在128维,旨在提升计算效率的同时,充分利用SOTA的视觉与文本encoder的各自优势;二是采用联合表征(EVL-uni)建模,利用MLLM大模型统一表征能力,基于通义实验室推出的GME多模态表征模型实现图文统一encode。由于二者除建模外训练思路基本一致,本文重点针对效果更佳双塔架构的EVL-sep进行介绍:

视觉编码模块:

文本编码模块:

特征对齐机制:

这样的设计确保了:

1.维度统一:不同模态特征在相同的128维语义空间中进行比较;

2.计算效率:相比原始特征维度,128维大幅降低了相似度计算的复杂度;

3.表征质量:通过专门的投影层学习模态间的语义对应关系;

对比学习框架:

双塔结构通过InfoNCE损失进行跨模态对比学习,正样本为图文配对,负样本采用batch内随机采样。InfoNCE损失函数的定义与示例计算过程如下:

1. n个句子与n个对应的图片分别嵌入、分别过一个投影层(学单模转多模,并统一维度)、正则化,得到两个n*d_e的向量I和T;

2. 二者点积,结果是一个形状为ingFang SC", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.034em;font-style: normal;font-weight: normal;">[n, n]的余弦相似度矩阵,其中每个元素表示一个图像与一个文本的余弦相似度,作为logits。

3. logits与label算交叉熵损失(对角线即正确匹配项为label1,其他即错误匹配项为label0)。

3.2.3 评估

评估指标设计:

采用跨模态检索任务评估模型性能,使用Recall@k(k=1,5,10)作为核心指标。具体方法为:将测试集图像和文本分别编码为特征向量,通过余弦相似度计算实现Text-to-Image和Image-to-Text双向检索,评估正确匹配项在前k个结果中的召回率。测试集按商品单图、店铺单图、店铺+商品多图三个场景分层采样,确保与训练数据无重叠。

正负样本构造策略:

正样本构建:商品图片与recaption描述、商户logo与商户描述、商户整体表征与综合描述分别构成三类正样本对。

负样本采样:采用In-batch Negative Sampling结合困难负样本挖掘策略。困难负样本包括同类目不同商户的图文对,以及基于相似度计算选择的高相似度非匹配样本,提升模型的细粒度区分能力。

样本质量控制:通过规则过滤伪负样本,移除同一商户的不同表述组合,确保负样本的有效性。动态调整困难负样本比例,训练后期逐渐增加困难样本占比。

评估结果:

经过领域适配预训练的双塔式模型在跨模态检索任务上达到90.8%的整体召回率,显著优于SOTA通用模型GME-qwen2-vl-7b(3584维)的66.5%,在商品单项的图文搜索上达到93.7%的整体召回率,显著优于团队过往在商品图文搜索场景训练的MS-ALBEF(128维)的75.8%。在单图商品、单图商户、多图混合场景下分别达到93.7%、82.0%、96.7%的平均召回表现,验证了领域适配训练和精心设计的样本构造策略的有效性。

预训练效果对比-综合性能

3.3 SFT对齐用户偏好

3.3.1 用户偏好建模思路

预训练阶段虽然建立了多粒度的图文表征基础,但这些表征主要基于内容相似性,缺乏用户真实偏好的指导。在推荐场景中,我们需要理解用户的潜在兴趣,而用户的搜索-购买行为链恰好提供了这种兴趣的明确表达。我们的核心理念可归纳如下:

1. 行为即兴趣:用户的搜索查询直接反映其需求意图,最终的购买转化验证了这种意图的真实性

2. 语义桥梁:通过用户查询作为桥梁,可以建立店铺内容与用户兴趣之间的语义关联

3. 推荐适配:将基于搜索行为学到的语义相似性迁移到推荐场景,提升首页店铺推荐的精准度

3.3.2 训练数据构建

数据构建与质量控制:

基于用户搜索后产生购买转化的真实行为数据,构建<用户查询, 购买店铺图片, 购买店铺描述>三元组作为正样本。采用batch内其他店铺的图文信息作为负样本,同时引入困难负样本挖掘策略,选择与查询相似度较高但非匹配的样本进行训练。为确保数据代表性和质量,统计全量餐饮店铺的高频查询词,选择top10查询对应的top5成交店铺构建训练集。

数据类型与训练策略:

根据查询复杂度和店铺表征丰富度,训练数据包含两类:

在实际训练过程中,我们对比了两种训练策略:分阶段训练(先训练单图数据,再训练多图数据)和混合训练(同时训练两类数据)。实验发现,分阶段训练会导致模型在单图匹配任务上的性能显著下降,这是由于后期多图训练过程中模型对早期学习的单图匹配能力产生了遗忘。为了避免这种灾难性遗忘问题,我们最终采用了混合训练策略,在训练过程中同时使用单query-单图和多query-多图两类数据,确保模型在不同复杂度任务上的均衡表现。

3.3.3 特征融合与损失设计

多模态特征融合:

在双塔式架构基础上,我们增加了Fusion Module以实现多模特征融合,采用cross-attention机制作为多模态编码器,接收图像特征和文本特征作为输入,输出融合后的128维多模态表征。具体而言,我们对比了不同尺寸MLPFusion、TfnFusion、LmfFusion、T5Fusion等不同融合方案,最终参考工作[21],使用效果最佳的T5 Feature Fusion模块以更有效的建模跨模态交互信息。

多路对齐设计:

单一的图文对齐方法对不同模态信息的利用不够充分。虽然在多模态融合时同时使用了图像、文本信息,但无法保证输出的多模态特征能够平衡利用不同模态。可能出现查询与单一模态对齐良好,但与融合特征距离较远的情况,导致多模态信息没有很好地协同工作。

为使模型学到的表征能够充分利用图文信息,我们在微调阶段将预训练时的图文对齐任务扩展为多模态对齐任务,设计了三类对比学习损失:

损失函数实现:

每类对齐都采用对偶损失设计,即同时计算模态A到模态B和模态B到模态A的对比损失。通过温度参数τ对相似度进行缩放,使用softmax归一化后计算交叉熵损失。最终的多模态监督损失为各个对比损失的加权组合:Loss=w1*q2t loss + w2*q2i loss + w3*q2f loss

在loss权重分配上,消融对比发现2:2:6->3:3:4带来整体召回率由0.856->0.860的提升,证明各类loss在本场景任务中相当的重要性。

通过多模态对齐,从不同视角消除query、图像、文本、融合特征之间的表征差异。多种损失的叠加使得各个模态表征能够有效地建模到同一特征空间,并且使得图像和文本中的关键信息能够主导其多模态表征。

SFT建模

3.3.4 评估

为验证模型在真实业务场景下的表现,我们设计了基于搜索订单场景的评估框架。该评估方法通过计算用户查询与候选店铺/商品的多模态相似度进行排序,验证用户真实下单项在相似度排序结果中的位置。

具体而言,我们采用Order Hitrate@k作为核心评估指标,其中k取值为1/5/10/20/50,衡量用户真实下单项在按相似度排序的前k个结果中的命中情况。

测试样本构建策略:

评估维度划分:

按照用户查询意图将测试集划分为三个子集:商品名/商品品牌查询、商户品牌查询、店品混合意图查询,分别评估模型在不同搜索场景下的表现。

评估结果:

在Order Hitrate@k评估中,微调后的EVL-sep模型在多个基线模型对比中表现优异,整体平均命中率达到86.0%,位居所有测试模型之首。值得注意的是,EVL模型仅使用128维表征向量,却显著优于使用1536维、3584维表征的GME-Qwen2-VL系列模型。

各查询场景详细对比:

综合分析显示,EVL-sep模型通过精心设计的多模态融合架构和训练策略,在保证效果的同时大幅降低了存储和计算成本,特别是在混合意图查询这一核心业务场景下展现出显著优势,验证了我们技术方案的有效性。

SFT各任务效果对比

SFT综合效果对比

3.4 Cotrain特征融合优化

多模态与ID特征融合策略

多模态表征与传统ID特征的融合面临根本性挑战:基于用户行为的协同过滤与基于内容的多模态表征属于不同维度,学习方向的一致性较差。直接将多模态特征concat到推荐模型中效果有限,需要更有效的整合方式。

我们参考工作[10],采用了SimTier+MAKE技术解决这一问题。SimTier通过相似度分桶的方式实现多模态信息的"ID化":首先计算目标物品与用户历史交互物品的多模态表征相似度,然后将相似度区间划分为N个桶,统计各桶内的相似度数量形成N维特征向量,最后与原有ID特征拼接输入推荐模型。这种方法通过"ID化"降低了特征维度,提升了多模态信息与推荐模型的兼容性。

MAKE技术则解决了多模态特征与ID特征训练节奏不一致的问题。ID特征模型存在"one-epoch现象"(多轮训练导致过拟合),而多模态信息需要多轮训练才能充分学习。MAKE通过参数分离优化,将多模态表征参数与ID特征参数独立处理,允许多模态部分多轮训练而ID部分保持单轮训练,同时采用深度兴趣网络处理用户行为序列,实现多模态表征与ID特征的有效融合。

SimTier+MAKE

评估

经过第三阶段特征融合优化的联合训练,为推荐系统离线AUC指标带来显著提升:全量商户CTCVR AUC +0.19%,CTR AUC +0.17%。

3.5 编码实践经验总结

3.5.1 建模

灵活初始化策略与参数验证

支持多种初始化方式,包括配置+模型组合的直接初始化方法和分离预训练模型加载的初始化方法。参考transformers vision_text_dual_encoder实现from_vision_text_pretrained方法,通过from_vision_text_configs()实现双塔模型配置自动融合,支持不同类型的视觉与文本编码器。在模型初始化后通过torch.allclose()验证参数一致性,确保权重正确加载。

价值:提供灵活的模型构建方式,支持从分离的预训练模型构建多模态模型,以充分利用SOTA的视觉与文本encoder的各自优势。

def__init__(self, config=None, vision_model=None, text_model=None):  ... # 灵活初始化:支持配置和模型的多种组合 ifconfigisNoneand(vision_modelisNoneortext_modelisNone):   raiseValueError("Either a configuration or an vision and a text model has to be provided")  # 从预训练模型自动生成配置 ifconfigisNone:    config = EvlConfig.from_vision_text_configs(vision_model.config, text_model.config)  # 根据配置类型选择合适的视觉模型 ifvision_modelisNone:    ifisinstance(config.vision_config, CLIPVisionConfig):      vision_model = CLIPVisionModel(config.vision_config)   elifisinstance(config.vision_config, InternVisionConfig):      vision_model = InternVisionModel(config.vision_config)  ...@classmethoddeffrom_vision_text_pretrained(cls, vision_model_name_or_path:str, text_model_name_or_path:str, **kwargs): # 分布式下载协调  local_rank =int(os.getenv('LOCAL_PROCESS_RANK','0')) iflocal_rank ==0:    repo_download(repo_id=vision_model_name_or_path, local_dir=vis_load_dir)    repo_download(repo_id=text_model_name_or_path, local_dir=text_load_dir)    done_file.touch()  # 分别加载视觉和文本模型  vision_model = CLIPVisionModel.from_pretrained(vis_load_dir, **kwargs_vision)  text_model = AutoModel.from_pretrained(text_load_dir, **kwargs_text)  # 融合配置并初始化完整模型  config = EvlConfig.from_vision_text_configs(vision_model.config, text_model.config, **kwargs)  model = cls(config=config, vision_model=vision_model, text_model=text_model)     ... # 参数一致性验证 print("vision parameter allclose:", torch.allclose(    vision_model.embeddings.patch_embedding.bias.data,    model.vision_model.embeddings.patch_embedding.bias.data))  returnmodel, image_processor, tokenizer, processor

视觉压缩层优化与多图像处理

通过像素重排(pixel shuffle)实现特征压缩,将空间维度信息无损重组到通道维度:空间分辨率从H×W降至H/2×W/2,相应地通道维度扩展4倍。对于多图像输入,采用空间维度池化和批次维度平均融合的策略进行处理。

价值:减少75%的视觉token数量,为计算复杂度为O(n²d)的自注意力机制带来平方级的性能提升,同时适应多图场景,提升训练和推理效率。

defpixel_shuffle(self, x, scale_factor=0.5): """通过多步维度变换将空间信息重新分布到通道维度"""  n, w, h, c = x.size()  x = x.view(n, w,int(h * scale_factor),int(c / scale_factor))  x = x.permute(0,2,1,3).contiguous()  x = x.view(n,int(h * scale_factor),int(w * scale_factor),int(c / (scale_factor * scale_factor))) returnx.permute(0,2,1,3).contiguous()
defextract_feature(self, pixel_values): vit_embeds =self.vision_model(pixel_values=pixel_values).last_hidden_state[:,1:, :] # 重塑为2D并压缩 h = w =int(vit_embeds.shape[1] **0.5) vit_embeds = vit_embeds.reshape(vit_embeds.shape[0], h, w, -1) vit_embeds =self.pixel_shuffle(vit_embeds, scale_factor=self.downsample_ratio) vit_embeds =self.visual_projection(vit_embeds.reshape(vit_embeds.shape[0], -1, vit_embeds.shape[-1])) returnvit_embeds.mean(dim=1) # 空间维度池化

文本特征提取与T5融合架构

通过last_token_pool()实现文本序列最后有效token的池化,自适应处理左右padding格式。文本特征经过线性投影层映射到共享语义空间。采用T5FusionLayer实现深度跨模态融合,配置2层Transformer、12个注意力头,将文本和图像特征拼接后利用自注意力机制学习跨模态依赖关系。

价值:确保文本特征提取准确性,支持不同文本输入格式。相比简单MLP融合,T5架构能学习更复杂的跨模态依赖,提升检索和理解能力。

deflast_token_pool(self, last_hidden_states: Tensor, attention_mask: Tensor) -> Tensor: """提取序列最后一个有效token的特征,适配不同padding方式"""  left_padding = (attention_mask[:, -1].sum() == attention_mask.shape[0]) ifleft_padding:   returnlast_hidden_states[:, -1] else:    sequence_lengths = attention_mask.sum(dim=1) -1    batch_size = last_hidden_states.shape[0]   returnlast_hidden_states[torch.arange(batch_size, device=last_hidden_states.device), sequence_lengths]
# 文本投影层:直接线性映射到共享空间self.text_projection = nn.Linear(self.text_embed_dim,self.projection_dim, bias=False)
classT5FusionLayer(nn.Module): def__init__(self, feature_dim:int): super().__init__() conf_t5 = T5Config() conf_t5.num_layers =2 conf_t5.num_heads =12 conf_t5.d_model = feature_dim conf_t5.d_kv =64 self.t5_layers = T5Stack(conf_t5)
defforward(self, txt_feat, img_feat): # 拼接为序列输入,利用自注意力学习跨模态交互 combined_features = torch.cat([txt_feat.unsqueeze(1), img_feat.unsqueeze(1)], dim=1) transformer_output =self.t5_layers(inputs_embeds=combined_features, attention_mask=None, use_cache=False, return_dict=True) returntorch.mean(transformer_output.last_hidden_state, dim=1)

条件化多任务训练策略

建模时在模型forward函数中根据输入数据类型动态选择训练模式。存在query时执行三模态对比学习(query-text/image/fusion),否则执行双模态对比学习(text-image)。通过loss_weight参数平衡不同任务贡献度,采用双向对称CLIP损失确保训练稳定性。

价值:实现统一框架下的多阶段训练,支持预训练到微调的无缝切换。

defclip_loss(similarity: torch.Tensor) -> torch.Tensor: """双向对称CLIP损失"""  q2t_loss = contrastive_loss(similarity)  t2q_loss = contrastive_loss(similarity.t())return(q2t_loss + t2q_loss) /2.0
defforward(...): ...# 条件化训练策略iftype(query_input_ids) !=type(None): # 三模态对比学习模式(微调阶段) logits_q2t = torch.matmul(query_embeds, text_embeds.t()) * logit_scale logits_q2i = torch.matmul(query_embeds, image_embeds.t()) * logit_scale logits_q2f = torch.matmul(query_embeds, fusion_features.t()) * logit_scale loss =self.loss_weight[0]*clip_loss(logits_q2t) +self.loss_weight[1]*clip_loss(logits_q2i) +self.loss_weight[2]*clip_loss(logits_q2f) ...else: # 双模态对比学习模式(预训练阶段) logits_per_text = torch.matmul(text_embeds, image_embeds.t()) * logit_scale loss = clip_loss(logits_per_text) ...

特征标准化与温度缩放

对所有模态特征进行L2归一化确保单位球面分布,通过可学习的logit_scale参数调节相似度分布锐度。指数变换确保scale为正值。

价值:确保余弦相似度计算稳定性,提升对比学习效果。

#L2归一化+可学习温度缩放text_embeds=text_embeds/text_embeds.norm(dim=-1,keepdim=True)image_embeds=image_embeds/image_embeds.norm(dim=-1,keepdim=True)fusion_features=fusion_features/fusion_features.norm(dim=-1,keepdim=True)logit_scale=self.logit_scale.exp()#确保为正值logits=torch.matmul(query_embeds,text_embeds.t())*logit_scale

结构化输出类设计

SFTOutput继承CLIPOutput并扩展多模态输出字段,保存所有中间特征和相似度矩阵,支持灵活的返回格式。

价值:提供完整的模型输出信息,便于模型分析、调试和下游任务使用。

@dataclassclassSFTStage2Output(CLIPOutput): """扩展的多模态输出类,保存完整的中间结果"""  loss:Optional[torch.FloatTensor] =None  logits_q2t: torch.FloatTensor =None# query-text相似度  logits_q2i: torch.FloatTensor =None# query-image相似度  logits_q2f: torch.FloatTensor =None# query-fusion相似度  text_embeds: torch.FloatTensor =None  image_embeds: torch.FloatTensor =None  fusion_features: torch.FloatTensor =None  defto_tuple(self) ->Tuple[Any]:   returntuple(self[k]ifknotin["text_output","vision_output","query_output"]         elsegetattr(self, k).to_tuple()forkinself.keys())

训练超参设置

●SFT:单卡bs=8,ga=36,lr=2e-5(余弦退火,warmup0.05),weight_decay=0.1,max_grad_norm1.0,adam参数(0.9,0.95,1e-5,和默认值区别不大)○128卡,1400w样本,1600step,约4个epoch,训练时间4.5天■per_N=N/world_size■max_steps(1epoch)=per_N/(单卡bs*ga)■这里bsga尝试了不同组合旨在逼近gpu利用率上限○weight_decay:■即l2正则化,目的是让权重衰减到更小的值,在一定程度上减少模型过拟合的问题■更小的权值w,从某种意义上说,表示网络的复杂度更低,对数据的拟合更好(这个法则也叫做奥卡姆剃刀),这里拍了个常用值○梯度裁剪(防止梯度爆炸):■new_grad=grad*max_grad_norm/max(grad_norm,max_grad_norm)■grad_norm为所有参数的梯度的L2范数●PT参数基本一致,就bsga略大了些(bs=24,ga=16,毕竟少了融合模块和多个loss),也是4个epoch,873w样本,约2天

3.5.2 工程实现

动态分辨率预处理管道

基于宽高比的自适应图像切分算法,计算最优切分方案保持图像细节,添加缩略图维持全局信息。

价值:平衡图像语义完整性与计算效率,适应不同尺寸图像的处理需求。

defdynamic_preprocess(image, min_num=1, max_num=12, image_size=448, use_thumbnail=False): """基于宽高比的自适应图像切分""" # 计算最优切分比例  target_ratios =set((i, j)forninrange(min_num, max_num +1)           foriinrange(1, n +1)forjinrange(1, n +1)           ifi * j <= max_numandi * j >= min_num)  target_aspect_ratio = find_closest_aspect_ratio(aspect_ratio, target_ratios, ...)  ... # 按最优比例切分
processed_images = [ ]
foriinrange(target_aspect_ratio[0] * target_aspect_ratio[1]): # 计算切分区域并裁剪 ... processed_images.append(resized_img.crop(box)) # 添加缩略图保持全局上下文 ifuse_thumbnailandlen(processed_images) !=1: processed_images.append(image.resize((image_size, image_size))) ... returnprocessed_images

流式数据加载适配

transformers Trainer默认期望数据集实现__len__方法,流式数据加载需要自定义Trainer适配IterableDataset,支持分布式环境下的数据流处理。

价值:实现大规模数据流式加载,避免内存溢出。

classMyTrainer(Trainer): defget_train_dataloader(self) ->DataLoader:    ifisinstance(train_dataset, torch.utils.data.IterableDataset):      returnDataLoader(train_dataset, batch_size=self._train_batch_size,              collate_fn=data_collator, drop_last=True,              num_workers=self.args.dataloader_num_workers,              pin_memory=self.args.dataloader_pin_memory)

高效数据收集器设计

transformers Trainer中,data_collator用于将dataset中一个batch的输入数据转换为模型一个batch输入的形式,实现自定义DataCollator处理多模态输入的动态padding,可根据训练类型(预训练/微调)灵活处理query输入,确保批次内数据格式一致。

价值:提升数据加载效率,支持不同训练阶段的数据格式需求。

@dataclassclassMyDataCollator(object): """多模态数据收集器,支持动态padding和训练类型适配""" def__call__(self, instances:Sequence[Dict]) ->Dict[str, torch.Tensor]:   # 根据训练类型处理query   ifself.train_type =="sft":      query_input_ids = torch.nn.utils.rnn.pad_sequence(        query_input_ids, batch_first=True, padding_value=self.tokenizer.pad_token_id)      query_attention_mask = query_input_ids.ne(self.tokenizer.pad_token_id)   else:      query_input_ids, query_attention_mask =None,None      # 文本动态padding    text_input_ids = torch.nn.utils.rnn.pad_sequence(      text_input_ids, batch_first=True, padding_value=self.tokenizer.pad_token_id)      returndict(query_input_ids=query_input_ids, query_attention_mask=query_attention_mask,         text_input_ids=text_input_ids, text_attention_mask=text_input_ids.ne(self.tokenizer.pad_token_id),         pixel_values=pixel_values, return_loss=self.return_loss)

多线程图像拉取优化

配置8个图像拉取线程和16个数据读取线程,支持网络异常重试机制(最多10次,间隔5秒)。

价值:显著提升图像加载速度,减少IO等待时间。

# 多线程配置convert_args = {  PARALLEL_WORKER_NUM:8, # 8个图像拉取线程 'oss_pull_func':partial(ele_pull_resource_func, image_processor=image_processor)}train_dataset = DistributeDataset(data_args.tables, num_threads=16, capacity=1024, ...)

异常处理与容错机制

实现多层次异常处理,包括网络重试、数据完整性检查、图像格式转换异常捕获。失败时生成随机tensor兜底,确保训练不中断。

价值:提升训练稳定性,保证大规模训练可靠性。

# 网络重试 + 兜底机制defurl2image_pixel(image_urls_str, image_processor, max_sub_img_num=10):
pix_list=[ ]
forsub_url in sub_images[:max_sub_img_num]: timeout_counter=0 response="" whilenotresponse and timeout_counter <=10: try: response= requests.get(sub_url, stream=True).raw ifresponse: pixel_value_i= image_processor(images=Image.open(response).convert("RGB"), return_tensors="pt").pixel_values pix_list.append(pixel_value_i) exceptException: timeout_counter+=1 sleep(5) # 兜底处理 ifnotpix_list: print("cannot get right image, fake one!!") pix_list.append(torch.rand(1,3,448,448)) returntorch.cat(pix_list, dim=0)

分布式训练协调

mdl训练时,使用rank 0统一下载模型,其他进程等待完成信号,通过torch.distributed.barrier()实现同步。

价值:避免重复下载,确保分布式环境一致性。

local_rank= int(os.getenv("LOCAL_PROCESS_RANK","0"))iflocal_rank ==0: repo_download(repo_id=mos_model_uri, local_dir=load_dir) done_file.touch()
iftorch.distributed.is_initialized(): torch.distributed.barrier()else: whilenotos.path.exists(done_file): time.sleep(60)

3.5.3 踩坑经验

Config类兼容性问题

问题:自定义Config类在调用save_pretrained()时报错,提示必需参数为None

根本原因:transformers库在调用save_pretrained时,为了精简config参数,会用默认参数创建新config实例进行对比,只存储不同项。这会导致自动化地使用默认参数调用config类的__init__函数。

解决方案:

classDualConfig(PretrainedConfig):  model_type ="dual_model"  is_composition =True# 优先方案:标识为复合配置  def__init__(self, projection_dim=512, **kwargs):   super().__init__(**kwargs)      # 兜底方案:支持默认初始化    vision_config = kwargs.pop("vision_config",None)    text_config = kwargs.pop("text_config",None)      self.vision_config = vision_configifvision_configelseViTConfig()   self.text_config = text_configiftext_configelseBertConfig()

经验要点:

DataCollator与模型Forward参数对齐问题

问题:transformers的Trainer中,data_collator返回的字典key必须与模型forward方法的参数名严格对应,否则会出现参数传递错误。

核心原理:Trainer会将data_collator返回的字典直接解包传递给模型的forward方法:

# Trainer内部逻辑batch= data_collator(samples) # 返回 {"pixel_values": ..., "query_input_ids": ...}outputs= model(**batch)    # 直接解包传递

解决方案:确保参数名严格对应

# 模型forward方法定义defforward(  self,  query_input_ids:Optional[torch.LongTensor] =None,  text_input_ids:Optional[torch.LongTensor] =None,  pixel_values:Optional[Tuple[torch.FloatTensor]] =None,  query_attention_mask:Optional[torch.Tensor] =None,  text_attention_mask:Optional[torch.Tensor] =None,  return_loss:Optional[bool] =None,  **kwargs):
# DataCollator返回的字典key必须对应classMyDataCollator(Object): def__call__(self, batch) ->Dict: return{ "pixel_values": pixel_values, # ✓ 对应forward参数 "query_input_ids": input_ids, # ✓ 对应forward参数 "query_attention_mask": attention_mask,# ✓ 对应forward参数 "text_input_ids": input_ids, # ✓ 对应forward参数 "text_attention_mask": attention_mask, # ✓ 对应forward参数 "return_loss":True, # ✓ 对应forward参数 }

经验要点:

3.6 最终业务效果

整个系统采用分层部署架构:MDL平台负责双塔模型训练并生成多模态embedding,AOP平台接入多模态特征进行CTR/CTCVR联合训练,RTP平台部署最终模型用于在线推理服务。

3.6.1离线指标提升

多模态预训练效果:经过领域适配预训练的双塔模型在跨模态检索任务上整体召回率达到90.8%,显著超越SOTA通用模型GME-qwen2-vl-7b(66.5%)。

用户查询对齐效果:微调后的EVL-sep模型在搜索订单场景评估中平均命中率达到86.0%,仅使用128维表征却优于高维GME系列模型,在店品混合查询场景HR@1达到53.2%。

联合训练效果:经过多模态与ID特征融合优化,推荐系统离线AUC获得显著提升:全量商户CTCVR AUC +0.19%,CTR AUC +0.17%。

3.6.2 在线业务效果

多模态推荐系统上线后在饿了么首页店铺推荐场景取得显著业务提升:

四、展望-生成式推荐

随着大语言模型技术的快速成熟,生成式推荐作为新兴的技术范式引起了业界的广泛关注。大模型在语义理解、多模态信息处理和逻辑推理方面的优势,与传统推荐系统在协同信号和领域知识方面的专长形成了完美互补,为推荐技术向生成范式的演进提供了可能。

4.1 生成式建模的尝试

基于24年S2在多模态推荐的技术积累,项目组自25年初开始探索生成式ranking的建模思路,尝试将多模态表征能力与大语言模型的生成能力相结合,笔者也有幸参与了其中的初版方案建设之中。虽然初版方案由于infra方面问题落地存在卡点,但为笔者理解生成式推荐的技术挑战提供了宝贵经验,在这里仅对建模与训练思路进行分享。

4.1.1 特征体系重构与数据构建

推荐特征体系重构:

为适应大语言模型的输入需求,我们对传统推荐系统的特征体系进行了全面重构,梳理转义推荐大宽表中的900+推荐线上业务特征,深入分析各个特征在生成式范式下的可用性与使用方法,按照用户特征、商户特征、用户商户交叉特征、时空特征进行筛选分类,构建面向llm的推荐特征体系。

商户表征建模策略:

SFT+RL训练样本构建:

通过接入vLLM推理框架优化CoT刷数效率,构建100w+的高质量SFT冷启动样本。针对SFT阶段数据正例少、hitrate过低导致的RL阶段reward稀疏问题,采用对店品描述数据进行热销品去重、长度控制、不规范描述筛选等数据清洗方法,以提升数据质量。

在样本构建过程中,通过整合店铺、用户基本推荐口径,精简复购记录、清洗点击序列数据,打通训练中的商户描述查找拼接方式,优化冷启动SFT、RL训练数据流程,并构建推荐特征日滚表,生成1亿+RL训练样本。通过建立完整的数据pipeline,确保训练数据的时效性和质量稳定性,为大规模RL训练提供可靠的数据支撑。

4.1.2 模型架构设计

在上述特征体系和数据构建工作的基础上,我们设计了多模态融合的生成式ranking架构。

多模态融合架构: 参照多模态大模型(VLM)的设计思路,我们构建了店铺融合表征编码器(GME + Projector)与LLM的组合架构,实现多模态信息与文本生成能力的深度融合。

输入输出设计:

输入信息包括:

1. 时空信息:当前时间:2025年2月21日周五,13:54:00,我在近铁广场点外卖;

2. 个性化历史:我是男性,18岁,过去一年点过的外卖有:<shop pad>...;

3. 实时兴趣:我刚点击过 <shop pad>...;

4. 候选集:从以下店铺挑选20个用户最可能下单的店铺<special token1><shop pad><special token2><shop pad>,...;

输出信息包括:

思考链+候选店铺序号:<think>...</think><special token355>...<special token209>

核心建模流程:

1. 店铺Token预留机制:在配置中定义特殊的shop_pad_token(shop_token_index=151667),在prompt构建时将店铺位置用该特殊token填充。例如:

person_history_text= f"""用户是{data_dict["gender"]}性, {data_dict["user_type"]}, 年龄{data_dict["age"]}岁, 最近下单的店铺有<|shop_start|>{recent_order_shop_id_pad_str}<|shop_end|>"""

2. 文本嵌入生成:将设计好的prompt输入LLM的embedding层,得到包含预留位置的文本嵌入向量:

ifinputs_embedsisNone:  inputs_embeds =self.get_input_embeddings()(input_ids)

3. 店铺特征映射:通过店铺融合表征编码器获取店铺的多模态表征,并通过projector模块映射到与文本向量相同的维度空间:

shop_features =Noneifshop_input_idsisnotNone:  shop_features =self.get_shop_features(shop_input_ids=shop_input_ids)

4. 特征替换融合:根据配置的shop_token_index生成mask向量,标识prompt中店铺token的位置,然后用映射后的店铺特征替换对应位置的文本嵌入:

special_shop_mask = (  (input_ids == self.config.shop_token_index)  .unsqueeze(-1)  .expand_as(inputs_embeds)  .to(inputs_embeds.device))shop_features = shop_features.to(inputs_embeds.device, inputs_embeds.dtype)inputs_embeds = inputs_embeds.masked_scatter(special_shop_mask, shop_features)

5. 统一生成处理:将替换后的整体embedding输入LLM进行后续的生成处理,输出thinking过程和推荐结果:

outputs = self.language_model(  attention_mask=attention_mask,  position_ids=position_ids,  inputs_embeds=inputs_embeds, # ... 其他参数)logits = outputs[0]

架构优势:

这种设计既保持了LLM强大的文本生成能力,又充分利用了前期多模态推荐中积累的店铺表征能力。通过projector的维度映射和mask机制的精确替换,实现了结构化店铺信息与自然语言处理的有机结合。

4.1.3 训练策略

基于上述模型架构,我们设计了SFT+GRPO两阶段训练方案,通过思考链输出模式引导模型在强化学习过程中涌现推荐推理能力。

监督微调阶段(SFT):

训练架构:在上述建模方法的基础上,将文本模态数据(时空信息+个性化特征+行为序列)的嵌入表征与经过店铺编码器的店铺融合表征(历史下单、实时点击、候选750店铺)拼接后输入LLM decoder进行监督微调,输出thinking过程和推荐商户序号,实现店铺融合表征编码器(GME + Projector)与LLM解码器的联合训练。

关键技术思路:在thinking过程中需要体现商户的关键文本信息,通过训练过程中同步更新GME权重实现。具体机制为:thinking过程的token loss能够传递到GME模块更新权重,从而使模型在thinking中生成正确的商户描述token,实现多模态表征与文本生成的深度融合。

核心训练目标:

1. 训练thinking格式:使模型学会按照预定格式输出结构化的思考过程,为后续RL阶段的逻辑推理能力奠定基础

2. 提升hitrate:通过监督学习提高模型在推荐任务上的基础命中率,降低RL阶段的奖励稀疏度问题,为强化学习提供更好的起点

强化学习阶段(GRPO):

训练策略:在SFT冷启动基础上,采用GRPO(Group Relative Policy Optimization)算法进行强化学习优化。通过迭代多个版本的数据,使用用户最终下单行为作为reward信号进行模型优化。

能力涌现机制:SFT阶段主要确保输出格式的规范性和基础推荐能力,而推荐逻辑的合理性和复杂推理能力通过RL阶段自主涌现。在GRPO训练过程中,模型逐渐学会在thinking过程中产生更深层次的反思和推理,提升推荐结果的准确性和可解释性。

训练框架:基于集团内部的ScaleAligner训练框架(已开源为ROLL)进行适配,主要包括自定义RL数据集适配、模型额外key的传入适配(shop_input_ids, shop_attention_mask)以及自定义reward适配等关键模块等。

4.1.4 核心挑战与反思

虽然上述方案在理论设计和数据构建方面较为完整,但在实际实施过程中遇到了关键的技术挑战。我们将模型划分为店铺表征编码器(GME)和推荐预测LLM解码器两个独立模块,但发现该建模方案无法实现端到端的联合训练(cotrain),只能采用分段式训练策略。根本原因在于两个模块在训练过程中对资源的需求存在显著差异:店铺表征编码器需要大batch size(通常等于打分深度,如750个候选店铺),而推荐预测解码器需要大模型规模,两者同时训练会超出现有硬件资源限制,存在根本性的技术矛盾。由于上述技术挑战,该生成式推荐方案目前在工程落地方面存在卡点,但这一探索不仅为理解生成式推荐的技术难点和实现路径提供了宝贵经验,在特征体系设计和训练数据构建方面的工作也为后续相关项目提供了一定程度的复用价值。

4.2 主流的生成式推荐方法:量化编码+LLM

25年以来业界在生成式推荐领域涌现出诸多前沿进展,特别是量化编码+LLM的技术路线逐渐成为主流,标志着推荐系统正向生成范式的演进方向。基于前述4.1节实践中遇到的端到端训练挑战,我们可以理解为何量化编码+LLM会成为当前生成式推荐的主流技术路线。这种方案通过将用户行为和商户信息量化为离散的语义ID,然后利用LLM的自回归生成能力进行推荐,从根本上解决了多模态编码器与LLM解码器联合训练的技术难题。

4.2.1 核心技术思路

量化编码的价值:量化编码(主要基于RQ-VAE等技术)将连续的多模态表征转换为离散的语义token,使得传统推荐信息能够被LLM理解和处理。这种编码方式具有两个关键优势:相似商品的ID在编码空间中也相近,便于泛化和冷启动;层次化的编码过程能够从粗到细地感知语义信息。而在我们的生成式ranking场景下,其更核心的价值在于:缩小生成解空间,将LLM预测范围缩小至≤万级别的语义ID,显著降低LLM学习难度;对齐item特征与LLM语义空间,使得商户表征能够被LLM直接理解和处理,避免了多模态编码器与LLM解码器联合训练的资源冲突。

LLM生成范式:基于编码后的语义token,利用大语言模型的自回归生成能力直接生成推荐结果。这种方式不仅统一了推荐框架,还天然具备可解释性和交互能力,能够生成推荐理由和支持多轮对话。

技术优势:相比我们探索的多模态融合方案,量化编码+LLM避免了不同模块间的资源需求冲突,可以实现端到端训练;同时保持了强大的泛化能力和零样本推荐潜力,在召回环节、多模态理解、供给冷启动、长尾兴趣捕捉等方面展现出巨大潜力。

适配方案思考:基于量化编码技术,笔者对于4.1节所述建模方案的一个直观的优化思路是参考工作[22]的编码方案,一阶段冻结店铺融合表征编码器模型参数,以“将店铺表征压缩成 4 个离散码字,同时保证可重建”为训练目标,对量化编码模块(DNN Encoder+RQ VAE+DNN Decoder)进行离线训练;

TIGER

二阶段复用原版特征与数据,保持原始建模与训练思路不变(建模:LLM Decoder,输入:时空信息+个性化历史+实时兴趣+候选集,输出:思考链+候选店铺,训练:SFT+GRPO),只需要将原本方案中输入的店铺预留token以及预测目标中的店铺序号token,用量化编码模块产出的店铺4位码字替代即可,建模思路如下图:

4.2.2 业界前沿进展

当前业界在生成式推荐领域涌现出诸多创新工作,涵盖了量化编码优化、LLM与推荐系统融合、多模态信息处理、长序列建模等多个技术方向。这些工作在语义ID构建、特征对齐、训练策略等方面不断突破,推动着生成式推荐技术的快速发展。

由于生成式推荐是一个快速发展的新兴领域,相关技术细节和最新进展已有很多优秀文章进行了深入解读,本文不再一一展开。

结语

本文回顾了笔者在24年下半年至25年初参与多模态推荐和生成式推荐项目中的学习历程与技术实践。从传统推荐算法向多模态推荐的演进,到多模态表征技术的深入理解,再到生成式推荐的前沿探索,这一路走来既有成功的实践经验,也有未能落地的技术挑战,每一步都加深了对推荐系统技术发展趋势的认知。项目的顺利推进离不开很多伙伴的悉心指导与协作支持,在此表示诚挚的感谢。

通过饿了么首页店铺推荐场景的多模态推荐系统实践,我们验证了三阶段训练策略的有效性,也深刻体会到了多模态特征与传统ID特征融合的复杂性。而在生成式推荐的探索中,虽然遇到了端到端训练的技术瓶颈,但这些挑战恰恰指明了未来技术发展的方向。

推荐系统正站在一个重要的技术转折点上。从协同表征到联合表征,从匹配范式到生成范式,技术的每一次演进都在重新定义着推荐系统的能力边界。多模态推荐已经在工业界得到广泛应用,而生成式推荐作为新兴技术方向,正在快速发展并展现出巨大潜力。

作为这一技术变革的参与者和见证者,笔者将持续关注多模态推荐和生成式推荐技术的发展动态,在实践中不断学习和探索。希望这份总结能够为同样在这一领域探索的技术同学提供一些参考,也期待与更多同学交流学习,共同推动推荐系统技术的进步。







欢迎光临 链载Ai (https://www.lianzai.com/) Powered by Discuz! X3.5