1.7.llm_recommend
LLM+推荐:概述
一些论文list
https://github.com/nancheng58/Awesome-LLM4RS-Papers
A Survey on Large Language Models for RecommendationRecommender Systems in the Era of Large Language Models (LLMs)
中科大LDS实验室的tutorial:XadC3O-large-language-models-for-recommendation-tutorial-slides.pdf
对应的datafun talk:当"狂飙"的大模型撞上推荐系统
生成式推荐综述:
Large Language Models for Generative Recommendation: A Survey and Visionary Discussions
A Review of Modern Recommender Systems Using Generative Models (Gen-RecSys)
一文梳理业界落地LLM4Rec的若干范式-数万字超长文(建议收藏)
推荐算法月报(2025.2):大模型的春风吹醒推荐算法,重磅大厂突破
推荐算法(2025.3.4):速看!阿里Meta的最新研究成果
一文梳理业界落地LLM4Rec的若干范式-数万字超长文(建议收藏)
综述
概况
How Can Recommender Systems Benefit from Large Language Models: A Survey 基于这个组织
CRM(conventional recommendation models)


where-LLM用于特征工程
user-item level特征增强
通过LLM的世界知识来获取更好的user/item表示
Llama4rec :prompt增强:在prompt里引入推荐模型的信息;数据增强:通过LLM给推荐模型增加样本;adaptive aggregation:llm和推荐模型各自打分并用融合公式融合
KAR:让LLM总结item得到item emb;让LLM总结user历史得到user emb,两个emb过一个mmoe做融合得到新的两个emb,给推荐模型用
SAGCN:通过LLM标识出用户对item的评论是属于哪些aspect的,然后u有A个emb,i也有A个emb,构建A个U-I图,然后揉在一起过GCN
CUP:把用户的一堆历史评论扔给chatgpt,让它总结出128个token,然后丢给双塔bert,另一个塔是item的描述,freeze bert底层,只tune上层
LLaMA-E:instruction formulating为写300个种子指令,让gpt作为teacher,对300个种子指令进行扩展,并由领域专家评估后,去重并保证质量,得到120k个指令作为训练集,再用lora去instruct tuning
EcomGPT:设置一系列的task(100多个task)来finetune BLOOMZ,包括命名实体识别、描述生成、对话intent提取等
instance-level样本生成
GReaT:把表格化(tabular)数据转成自然语言,然后打乱顺序,自回归地finetune一个LLM,再拿tune完的LLM来合成(synthesize)逼真的(realistic)表格化数据
ONCE:闭源LLM输出文本(user profiler、content summarizer、personalized content generator),给开源LLM得到user表示,item过开源LLM得到item表示,二者内积学ctr
Agent4Rec:先训一个推荐模型,然后构建一个多智能体系统,模拟和这个推荐模型交互,产出新的样本给推荐模型做数据增强
RecPrompt:给一个初始prompt,让LLM1得到推荐结果,拿一个monitor衡量这个结果和ground truth的mrr/ndcg,再用另一个LLM产出更好的prompt给第一个LLM用,如此迭代,得到一个best prompt
PO4ISR:给初始prompt,收集error case让模型反思原因并refine出新的prompt,再augment出另一个prompt,并UCB选出最好的prompt,如此迭代
BEQUE:query重写任务,SFT得到一个LLM,将其预测的若干个候选rewrites通过offline system的feedback得到排序,再通过PRO算法再tune LLM。
Agent4Ranking:query重写任务,多个人群当成多个agent,每个通过多轮对话产出一个rewrite,再合在一起经过bert+mmoe计算robust损失+accuracy损失。
where-LLM作为特征编码器
表示增强
统一的跨域推荐
where-LLM 用于打分函数
Text Is All You Need: Learning Language Representations for Sequential Recommendation 亚马逊发的
https://github.com/AaronHeee/RecFormer
where-LLM用于流水线控制(pipeline controller)
how-tune LLM & infer with CRM
how-not tune LLM & infer w/o CRM
how-not tune LLM & infer with CRM
how-tune LLM & infer w/o CRM
llm vs ID
SIGIR2023 | ID vs 模态: 推荐系统ID范式有望被颠覆?
Where to Go Next for Recommender Systems? ID- vs. Modality-based Recommender Models Revisited
https://github.com/westlake-repl/IDvs.MoRec
推荐生态系统
发现性
Diversifying by Intent in Recommender Systems,涨了dau等指标
LLM+推荐:生成索引
DSI
参考知乎:https://zhuanlan.zhihu.com/p/470182510
Transformer memory as a differentiable search index,提出的可微搜索索引(differentiable search index, DSI),拆成两个阶段:
indexing:建立文档和doc_id的一一映射
retrieval:根据query生成候选doc_ids
与Autoregressive Entity Retrieval提出的受限beam search的GENRE(代码https://github.com/facebookresearch/GENRE,解读Transformer中PrefixConstrainedLogitsProcessor类的解读)对比:
GENRE生成的目标是有具体语义的实体名
DSI生成的目标则是无任何语义的任意doc_id
Indexing方法
Inputs2Target:即doc_tokens->doc_id
Target2Inputs:即doc_id->doc_tokens
bidirectional:同时用上两面两个任务,并且在开始时加一个前缀,表明任务的方向
span corruption:参考T5(Exploring the limits of transfer learning with a unified text-to-text transformer),将doc_id当做前缀和doc_tokens拼起来,2个好处:
在索引时进行通用的预训练
实现doc_id作为去噪目标和输入的平衡
文档的表示
Direct Indexing:直接用文档的前L个单词当做文档的表示,并且保留单词的顺序。
Set Indexing:去掉文档中的重复的单词及停用词,然后和Direct Indexing一样的处理。
Inverted Index:随机对文档中的连续的k个单词(一个文档块)进行采样,并将它们与doc_id相关联
doc_id的表示
非结构化的原子标识符:直接对所有的文档使用一个随机但互不相同的的整数标识。假设一共有N篇文档需要检索,假设原来解码器输出有V个单词,现在有V+N个单词。
朴素的结构化字符串标识符:也使用一个随机的整数,但将这个整数当做一个字符串输出,用受限的beam search搜索前k个文档,因为需要保证输出的是数字。
语义结构化的标识符:先用BERT产出每个doc的emb,然后递归10-means,第一次得到0-9作为第1个数字,第二次的0-9作为第2个数字,可以得到一个树,文档的最终标识符就是从根节点到当前结点的路径对应的编号组合。只要一个节点的文档数大于,就继续分裂,当叶子的文档数小于c时,每个文档随机分配一个1到的id,拼到doc_id的最后。
训练方法
用seq2seq,即teacher forcing+交叉熵,有如下两种方式:
先对indexing进行预训练(memorization),再进行将query映射为docid的微调
用多任务的方式同时进行,两个任务用不同的标识符,这样做效果会好很多
后来有一篇Bridging the Gap Between Indexing and Retrieval for Differentiable Search Index with Query Generation,对应的github:https://github.com/ArvinZhuang/DSI-QG,他也同时尝试复现DSI:https://github.com/ArvinZhuang/DSI-transformers,主要有如下两个地方:
准备数据,doc_id
class IndexingTrainDataset(Dataset):
def __init__(
self,
path_to_data,
max_length: int,
cache_dir: str,
tokenizer: PreTrainedTokenizer,
):
self.train_data = datasets.load_dataset(
'json',
data_files=path_to_data,
ignore_verifications=False,
cache_dir=cache_dir
)['train']
self.max_length = max_length
self.tokenizer = tokenizer
self.total_len = len(self.train_data)
def __len__(self):
return self.total_len
def __getitem__(self, item):
data = self.train_data[item]
input_ids = self.tokenizer(data['text'],
return_tensors="pt",
truncation='only_first',
max_length=self.max_length).input_ids[0]
return input_ids, str(data['text_id'])
@dataclass
class IndexingCollator(DataCollatorWithPadding):
def __call__(self, features):
input_ids = [{'input_ids': x[0]} for x in features]
docids = [x[1] for x in features]
inputs = super().__call__(input_ids)
# label是doc_id
labels = self.tokenizer(
docids, padding="longest", return_tensors="pt"
).input_ids
# replace padding token id's of the labels by -100
# according to https://huggingface.co/docs/transformers/model_doc/t5#training
labels[labels == self.tokenizer.pad_token_id] = -100
inputs['labels'] = labels
return inputs
训练和预测
class IndexingTrainer(Trainer):
def __init__(self, restrict_decode_vocab, **kwds):
super().__init__(**kwds)
self.restrict_decode_vocab = restrict_decode_vocab
def compute_loss(self, model, inputs, return_outputs=False):
## 输入文章,预测doc_id
loss = model(input_ids=inputs['input_ids'],
attention_mask=inputs['attention_mask'], labels=inputs['labels']).loss
if return_outputs:
return loss, [None, None] # fake outputs
return loss
def prediction_step(
self,
model: nn.Module,
inputs: Dict[str, Union[torch.Tensor, Any]],
prediction_loss_only: bool,
ignore_keys: Optional[List[str]] = None,
) -> Tuple[Optional[torch.Tensor], Optional[torch.Tensor], Optional[torch.Tensor]]:
model.eval()
# eval_loss = super().prediction_step(model, inputs, True, ignore_keys)[0]
with torch.no_grad():
# greedy search
doc_ids = model.generate(
inputs['input_ids'].to(self.args.device),
max_length=20,
prefix_allowed_tokens_fn=self.restrict_decode_vocab,
early_stopping=True,)
return (None, doc_ids, inputs['labels'])
对解码空间的限制:
# docid generation constrain, we only generate integer docids.
SPIECE_UNDERLINE = "_"
INT_TOKEN_IDS = []
for token, id in tokenizer.get_vocab().items():
if token[0] == SPIECE_UNDERLINE:
if token[1:].isdigit():
INT_TOKEN_IDS.append(id)
if token == SPIECE_UNDERLINE:
INT_TOKEN_IDS.append(id)
elif token.isdigit():
INT_TOKEN_IDS.append(id)
INT_TOKEN_IDS.append(tokenizer.eos_token_id)
def restrict_decode_vocab(batch_idx, prefix_beam):
return INT_TOKEN_IDS
vq-vae & rq-vae
vq-vae
Neural discrete representation learning
https://github.com/zalandoresearch/pytorch-vq-vae
用在推荐:
Learning Vector-Quantized Item Representation for Transferable Sequential Recommenders
https://github.com/RUCAIBox/VQ-Rec
rq-vae
Autoregressive Image Generation using Residual Quantization
TIGER
Recommender Systems with Generative Retrieval
序列推荐的一些paper:
Session-based recommendations with recurrent neural networks:GRU4Rec首先把RNN用到推荐里
Neural attentive session-based recommendation:提出NARM(Neural Attentive Session-based Recommendation),在GRU里加了attention
Next item recommendation with self-attention:AttRec在metric learning里引入了self-attention
Self-attentive sequential recommendation:SASRec用了类似decoder-only的self-attention
S3-rec: Self-supervised learning for sequential recommendation with mutual information maximization:在预训练阶段引入了4个自监督的task,4个MIMM(mutual information maximization)
item-attribute MIM
sequence-item MIM:sequence和被mask掉的一个item间
sequence-attribute MIM
sequence-sequence MIM:sequence和被mask掉的连续item构成的片段间

这些方法都是学习item的向量,然后用MIPS去ANN,而TIGER(Transformer Index for GEnerative Recommenders)则是生成式地直接预测item的语义id



rq-vae的介绍:

原图里的下标有一些问题
经过encoder得到的(可以看成就是),,在第一个码本里ann找到最近的,得到
,在第2个码本里ann找到最近的,得到
,在第3个码本里ann找到最近的,得到
,在第4个码本里ann找到最近的,得到,
对应的semantic id就是(1,4,6,2),拿再去过decoder得到
最终的loss::
,sg是stop gradient,这里原始的rq-vae是算的看来有点diff
码本的emb通过moving average更新
rqvae的代码:https://github.com/kakaobrain/rq-vae-transformer/blob/main/rqvae/models/rqvae/quantizations.py#L237
VQ部分:
class VQEmbedding(nn.Embedding):
def compute_distances(self, inputs):
codebook_t = self.weight[:-1, :].t()
(embed_dim, _) = codebook_t.shape
inputs_shape = inputs.shape
assert inputs_shape[-1] == embed_dim
inputs_flat = inputs.reshape(-1, embed_dim)
# a^2
inputs_norm_sq = inputs_flat.pow(2.).sum(dim=1, keepdim=True)
# b^2
codebook_t_norm_sq = codebook_t.pow(2.).sum(dim=0, keepdim=True)
# (a-b)^2 = a^2 + b^2 - 2ab
distances = torch.addmm(
inputs_norm_sq + codebook_t_norm_sq,
inputs_flat,
codebook_t,
alpha=-2.0,
)
distances = distances.reshape(*inputs_shape[:-1], -1) # [B, h, w, n_embed or n_embed+1]
return distances
@torch.no_grad()
def find_nearest_embedding(self, inputs):
distances = self.compute_distances(inputs) # [B, h, w, n_embed or n_embed+1]
embed_idxs = distances.argmin(dim=-1) # use padding index or not
return embed_idxs
@torch.no_grad()
def _update_embedding(self):
n_embed = self.weight.shape[0] - 1
n = self.cluster_size_ema.sum()
normalized_cluster_size = (
n * (self.cluster_size_ema + self.eps) / (n + n_embed * self.eps)
)
self.weight[:-1, :] = self.embed_ema / normalized_cluster_size.reshape(-1, 1)
def forward(self, inputs):
embed_idxs = self.find_nearest_embedding(inputs)
if self.training:
if self.ema:
self._update_buffers(inputs, embed_idxs)
embeds = self.embed(embed_idxs)
if self.ema and self.training:
self._update_embedding()
return embeds, embed_idxs
RQ部分
class RQBottleneck(nn.Module):
def __init__(...):
codebooks = [VQEmbedding(self.n_embed[idx],
embed_dim,
decay=self.decay[idx],
restart_unused_codes=restart_unused_codes,
) for idx in range(self.code_shape[-1])]
self.codebooks = nn.ModuleList(codebooks)
def quantize(self, x):
r"""
Return list of quantized features and the selected codewords by the residual quantization.
The code is selected by the residuals between x and quantized features by the previous codebooks.
Arguments:
x (Tensor): bottleneck feature maps to quantize.
Returns:
quant_list (list): list of sequentially aggregated and quantized feature maps by codebooks.
codes (LongTensor): codewords index, corresponding to quants.
Shape:
- x: (B, h, w, embed_dim)
- quant_list[i]: (B, h, w, embed_dim)
- codes: (B, h, w, d)
"""
B, h, w, embed_dim = x.shape
residual_feature = x.detach().clone()
quant_list = []
code_list = []
aggregated_quants = torch.zeros_like(x)
for i in range(self.code_shape[-1]):
quant, code = self.codebooks[i](residual_feature)
# 就地操作,从residual_feature中减去quant的值,覆盖原来的值
residual_feature.sub_(quant)
aggregated_quants.add_(quant)
quant_list.append(aggregated_quants.clone())
code_list.append(code.unsqueeze(-1))
codes = torch.cat(code_list, dim=-1)
return quant_list, codes
def forward(self, x):
x_reshaped = self.to_code_shape(x)
quant_list, codes = self.quantize(x_reshaped)
commitment_loss = self.compute_commitment_loss(x_reshaped, quant_list)
quants_trunc = self.to_latent_shape(quant_list[-1])
quants_trunc = x + (quants_trunc - x).detach()
return quants_trunc, commitment_loss, codes
def compute_commitment_loss(self, x, quant_list):
r"""
Compute the commitment loss for the residual quantization.
The loss is iteratively computed by aggregating quantized features.
"""
loss_list = []
for idx, quant in enumerate(quant_list):
partial_loss = (x-quant.detach()).pow(2.0).mean()
loss_list.append(partial_loss)
commitment_loss = torch.mean(torch.stack(loss_list))
return commitment_loss
Tiger应用在排序
Better Generalization with Semantic IDs: A Case Study in Ranking for Recommendations
RecSys'24 | 谷歌:使用语义ID提升推荐系统ID Embed泛化性
meta提升id emb稳定性
Meta广告:提出使用语义ID提升推荐系统ID Embed稳定性
Enhancing Embedding Representation Stability in Recommendation Systems with Semantic ID
受限beam search相关
Diverse Beam Search: Decoding Diverse Solutions from Neural Sequence Models
Autoregressive entity retrieval:代码:https://github.com/facebookresearch/GENRE
Autoregressive Search Engines: Generating Substrings as Document Identifiers:例如一个item可以写成<IDS> 1023 <IDE> Urban Decay Eyeshadow Palette Naked Heat <AS> Makeup <AE> <AS> Eyes <AE>
,并通过wavelet tree存储,给定开始token(如<IDS>
或者<AS>
),可以在里找出所有可能的后续tokens。代码:https://github.com/facebookresearch/SEAL
百度的COBRA
Sparse Meets Dense: Unified Generative Recommendations with Cascaded Sparse-Dense Representations

和tiger很像,主要区别是除了原来rq的code,还加了个dense emb进去
rq部分freeze,dense是拿item的明文特征过一个bert得到的cls emb,bert是训练的
decode出来有两个东西,rq的code和dense

先beam search出m个rq的code出来
然后每一个code和原来的seq一起输入decoder,得到的pred就是dense,再拿这个dense去ann找n个item
最后对这m*n个item拿两个相似度融合出一个得分,取topk出来
LLM+推荐:输入ID
快手的RecGPT
RecGPT: Generative Personalized Prompts for Sequential Recommendation via ChatGPT Training Paradigm
https://zhuanlan.zhihu.com/p/699985083
Meta的HSTU(落地)
如何评价Meta最新推荐论文: 生成式推荐打败深度分层架构推荐?
背景
大规模推荐系统依赖高基数(high cardinality)、异质特性(heterogeneous features),每天要处理上百亿用户行为数据。将推荐系统重新定义为生成模型框架内的序列转化任务,提出HSTU(Hierarchical Sequential Transduction Unit),专为高基数、非稳态的流式推荐数据设计。
在公开数据集比基线NDCG+65.8%
在8192的序列长度上的处理速度比基于flash attention2的transformer快5.3-15.2倍。
1.5万亿(1.5 trillion)参数,线上ab测试指标+12.4%
在Breaking the curse of quality saturation with user-centric ranking中提到了NCE(normalized cross-entropy)指标:

可以发现,对于一个预训练好的模型来说,随着时间的变化,NCE的变化是很剧烈的,即数据分布是会漂移的,并不像nlp/cv一样有ground truth,所以传统推荐模型其实很难达到比较好的scaling能力。

需要克服的3个挑战:
推荐系统中的特征缺少显式的结构。序列建模(bert4rec、S3-rec等)在小规模数据集上效果不错,但工业界则需要异构特征(高基数的id、交叉特征、统计特征、历史点击率等)。
推荐系统使用十亿规模的动态词表,而nlp用的是10w的静态词表,要对上万候选进行target-aware操作(din、Cold等),训练和推理的代价很高。
大规模序列模型的计算成本是瓶颈。GPT-3在300B token的数据集上用上千个GPU训练1-2个月,而在推荐场景一天就有十亿级的活跃用户和十亿级的候选进行交互,用户序列在极端情况下有近10w(Twin: Two- stage interest network for lifelong user behavior modeling in ctr prediction at kuaishou),所以推荐系统每天要处理的tokens数量甚至比语言模型1-2个月处理的数量要大几个数量级
本文将用户action看成一个新的模态,2个主要的insights:
给定一个新的特征空间,核心的召回排序任务能被直接转换成生成式模型问题(序列直推任务,sequential transduction tasks)
这种范式能够系统性地解决传统推荐中的特征冗余、计算冗余、推理冗余,提升效率
Sequential Transduction Tasks
transductive learning(直推式学习) vs inductive learning(归纳式学习)https://www.zhihu.com/question/68275921/answer/529156908:
归纳式学习:训练只使用训练集,不使用测试集,训出的模型对测试集做预测,如监督学习。
直推式学习:训练时使用训练集,还使用测试集的特征,但不使用测试集的label,
异构特征的统一表示
稀疏特征:itemid、类目、城市、语言、社区等
先选出最长的时间序列作为主时间序列,例如用户的交互序列。
剩下的特征随时间变化较慢,如关注作者的属性。对于连续出现的片段(consecutive segment),只保留最开始的入口,这样对于主时间序列而言,并不会增加太多的序列长度。
数值型特征:这里指的是序列特征里每个item的统计特征,比如用户在时刻t对某个item的ctr。直接删了,因为DIN里提到随着序列长度增加,target-aware的序列建模方式能够捕捉到这种数值性特征

假设用户消费了9个item,
绿色的有7个时间步,全保留,作为主序列;
蓝色的有7个时间步,但只有G0和G1两种取值,所以对于连续的G0只保留第0个(出现在t1),扔到主序列的最前面去,连续的G1也只保留第0个(出现在t8),插到主序列最后一个的前面
黄色的全是H0,第0个出现在t7,所以保留t7,往主序列t8前面插入
将数值型特征替换为target-aware的cross attention得到causal-masked的特征
通过t0、t1、t2(包括t2)的特征生成t2的样本,以此类推
召回和排序的重定义
输入token序列,输出的token序列是通过mask序列得到的。
token对应的动态、非稳态词表是,用户交互的内容是
召回:预估,通过时间步i的用户特征预估,一般是直接选择来最大化特定的reward,和标准的自回归有两个不同:
的label并不一定是,因为用户可以对是负反馈
可能是比如人口属性等(因为是merge的序列,可能把城市之类的merge进来当做一个时间步),这个时候未定义的,要把它mask掉,即
排序:推荐中的排序需要在尽量早的阶段进行target-aware的交互,而标准的自回归这种交互往往比较迟,例如在encoder的输出才用上了softmax。因此,设计了一种target-aware的cross-attention
把action和x穿插起来得到新序列
对于action的位置,
对于content位置,使用一个小的nn将预估值转换成多任务的预估值(感觉是输入0-n,第n项保留,mask掉,拿去多目标地预估用户会用哪个action)
生成式训练
假设用户有个token,那么训练的复杂度就是,其中:
是self-attention的复杂度,通过flash attention可以达到
是FFN的复杂度
因为要自回归地算,可以理解为batch_size也是,加一个下三角的mask,所以在里还要乘一个
假设,那复杂度就是,太巨大了
但其实可以发现(这段是自己的理解),假设序列长度9,要预测第4个的时候,4-9的输入是mask掉的,但他们还是要进行后面的attention+ffn计算,其实是很浪费资源的,所以如上面“异构特征的统一表示”小节的那个图(生成主序列和辅助序列)所示,该模型直接只吐出x=x1-x3,y=x4作为训练样本就行了,这样既省掉了4-9的无用计算,也更便于并行(相比不拆batch的自回归)
假设采样第个用户的概率是,那么总的训练消耗就是
如果设置,那消耗就降到了。而在工业界中要实现这种采样其实很简单,在用户请求或者session结束的时候吐出训练样本就有了
生成式推荐中的高性能自注意力编码器

HSTU的单层包括3个部分:
其中,
是MLP,
和是激活函数,都是SiLU(Sigmoid-weighted linear units for neural network function approximation in reinforcement learning),其实就是Swish,即
是relative attention bias,考虑了位置和时间(参考T5论文,Exploring the limits of transfer learning with a unified text-to-text transformer),其实是在Self-attention with relative position representations一文提出的
对应到代码(https://github.com/facebookresearch/generative-recommenders/blob/main/modeling/sequential/hstu.py)里:
self._linear_dim: int = linear_hidden_dim
self._uvqk = torch.nn.Parameter(
torch.empty((embedding_dim, linear_hidden_dim * 2 * num_heads +
attention_dim * num_heads * 2)).normal_(mean=0, std=0.02),
)
##...
batched_mm_output = torch.mm(normed_x, self._uvqk)
if self._linear_activation == "silu":
batched_mm_output = F.silu(batched_mm_output)
elif self._linear_activation == "none":
batched_mm_output = batched_mm_output
# 其实就是先乘一个大矩阵,再拆成4份,等价于乘4个小矩阵
u, v, q, k = torch.split(
batched_mm_output,
[self._linear_dim * self._num_heads, self._linear_dim * self._num_heads,
self._attention_dim * self._num_heads, self._attention_dim * self._num_heads],
dim=1,
)
if self._normalization == "rel_bias" or self._normalization == "hstu_rel_bias":
if delta_x_offsets is not None:
padded_q, padded_k = cached_q, cached_k
flattened_offsets = delta_x_offsets[1] + torch.arange(start=0, end=B * n,
step=n, device=delta_x_offsets[1].device, dtype=delta_x_offsets[1].dtype)
padded_q = padded_q.view(B * n, -1).index_copy_(
dim=0, index=flattened_offsets, source=q,
).view(B, n, -1)
padded_k = padded_k.view(B * n, -1).index_copy_(
dim=0, index=flattened_offsets, source=k,
).view(B, n, -1)
else:
padded_q = torch.ops.fbgemm.jagged_to_padded_dense(
values=q, offsets=[x_offsets], max_lengths=[n], padding_value=0.0
)
padded_k = torch.ops.fbgemm.jagged_to_padded_dense(
values=k, offsets=[x_offsets], max_lengths=[n], padding_value=0.0
)
qk_attn = torch.einsum(
"bnhd,bmhd->bhnm",
padded_q.view(B, n, self._num_heads, self._attention_dim),
padded_k.view(B, n, self._num_heads, self._attention_dim),
)
if all_timestamps is not None:
qk_attn = qk_attn + self._rel_attn_bias(all_timestamps).unsqueeze(1)
qk_attn = F.silu(qk_attn) / n
qk_attn = qk_attn * invalid_attn_mask.unsqueeze(0).unsqueeze(0)
attn_output = torch.ops.fbgemm.dense_to_jagged(
torch.einsum(
"bhnm,bmhd->bnhd",
qk_attn,
torch.ops.fbgemm.jagged_to_padded_dense(v, [x_offsets], [n]).\
reshape(B, n, self._num_heads, self._linear_dim)
).reshape(B, n, self._num_heads * self._linear_dim),
[x_offsets],
)[0]
DLRM的3部分:
特征抽取:常见的基础版本是离散特征pooling,高级版本是din。HSTU本来就能做这种target-aware的attention
特征交互:常见的使用FMs、DCNv2、DHEN(DHEN: A Deep and Hierarchical Ensemble Network for Large-Scale Click-Through Rate Prediction,引入残差连接)。HSTU通过来实现,将attention pooled后的结果直接和其他特征算element-wise product。
这个做法受Neural collaborative filtering vs. matrix factorization revisited和Revisiting neural retrieval on accelerators的启发,用MLP来近似点积是很困难的。原因大概是nn需要调超参和足够的训练数据,在线算得又慢,而且本来内积效果就不错了,nn能带来的边际收益其实不明确。
因为已经用过SiLU了,所以可以看成是SwiGLU的变种(参考Glu variants improve transformer),因为前面在对比LLM激活函数时讲了,
表示转换:常见的如MoE、PLE等,主要思想就是对不同人群用特定的子网络。HSTU里的element-wise product也能达到MoE中的门控操作,只是可能有一个正则化因子的区别。
其实就是原来一般会拆成attention+ffn,而它这3个公式,前两个是attention,第3个就是attention求个norm,然后过一个swiglu的ffn,还有一点,这里的是过attention之前的,感觉起到了类似resnet的作用
pointwise聚合的注意力
用的是pointwise聚合的注意力,而不是transformer里的softmax,主要有如下两点考虑:
推荐中item的强度信息很重要,softmax会让这种强度失真,导致在预估(如时长)不准;如果只需要预估序,那其实softmax也可以,但推荐要同时预估序和值,所以要删掉softmax。
虽然softmax对噪声有鲁棒性,但不太适用于流式setting下的非稳态词表。做了一个模拟流式数据的实验,发现只去掉relative attention bias比relative attention bias并加上softmax会好得多
Transformers
.0442
.2025
HSTU (, Softmax)
.0617
.2496
HSTU ()
.0893
.3170
增加稀疏性
使用了一种高效的attention kernel的GPU算子,类似FlashAttention,能够将融合连续的矩阵操作(fuse back-to-back GEMMs),但能够 进行fully raggified(可能是不规则,即序列长度可变的??)的attention计算,本质是将attention计算转换为不同大小的分组GEMMs。因此,HSTU变成了memory-bound,并且能够以进行scale,其中,是样本的序列长度,是attention的维度,是寄存器的大小。
受Deep networks with stochastic depth启发,提出了SL(stochastic length)来增加用户历史序列的稀疏性,推荐系统中的用户行为往往有周期性,并且以不同形式呈现,因此引入稀疏性可以在效果不怎么损失的情况下显著减少encoder的代价,可以scale为
定义为一个函数,从原序列中选出长度为的子序列,具体方案如下:
即:
时,保留原始序列
时,有:
以的概率只保留长度的子序列
以的概率保留原始序列
对于,原来的attention相关的复杂度是,现在可以降低到。
其中的经过离线实验(原文附录D里),采用了feature-weighted sampler,即以的概率进行采样,其中表示用户和item 交互的时间和当前的时间差。
对稀疏性的改善如下,其中稀疏性指的是,越大表示短序列越多,即越稀疏(表示不SL,即直接使用原序列):
Alpha ()
seq_len=1,024
seq_len=2,048
seq_len=4,096
seq_len=8,192
1.6
71.5%
76.1%
80.5%
84.4%
1.7
56.1%
63.6%
69.8%
75.6%
1.8
40.2%
45.3%
54.1%
66.4%
1.9
17.2%
21.0%
36.3%
64.1%
2.0
3.1%
6.6%
29.1%
64.1%
最小化激活值的内存使用
在推荐系统中,大的batchsize很重要:
因此激活函数的内存占用就成为了主要的scaling瓶颈,这一点和llm不一样,llm一般是用小batchsize,并且内存主要由网络参数占据。HSTU设计了如下方式来减少激活函数的内存占用:
把attention外的linear layers从6减小到2,同时使用elementwise gating来降低MLP的计算(Transformer Quality in Linear Time和Efficiently modeling long sequences with structured state spaces)。第一篇对应的结构如下:

假设是embed size,是head数,是attention的dim,是ffn的hidden size,
将一些计算融合成一个op,包括、layer_norm、optional dropout和输出MLP,将每一层的激活的内存占用减小到了(以bf16计算,一个参数2字节)---没懂
自己的理解:layer_norm要存均值+方差,所以要,所以上面式子就是,U(),V(),Q和K(),QKV的norm(因为有均值和方差,所以是),QKV()
对比transformer,在attention后用了ffn和dropout,假设中间状态是,那么ffn包括layer_norm、linear、激活、linear、dropout,中间状态占用的就是,一般来说,,,
自己的理解:输入x(),linear(),linear(),dropout(约等于),layernorm一般是发生在最开始吧,所以应该是第一个改成吧,感觉不是在linear那里变成。。
然后,加上输入的input和input的layer_norm(),和qkv的映射,总的激活状态是---没懂
所以HSTU的设计能够让scaling达到大于两倍的更深的layers(14d vs 33d)
此外,词表中的id占用了极大的内存,对于10b的词表,512维的emb,Adam优化器,用fp32来存储emb和优化器状态要60TB的内存,因此,
将优化器状态存在DRAM里,从而每一个float在HBM的占用从12bytes降低到2bytes
cost-amortization(摊销)的预估scale up
对于召回来说,已经有很多加速方法了,例如MIPS的ANN加速,或者OTM等的beam search方法。
对于排序而言,提出了M-FALCON(Microbatched-Fast Attention Leveraging Cacheable OperatioNs),用于对个候选,序列长度为的输入进行预估
并行计算个候选,修改attention masks和 bias,使得这个候选的attention操作是完全一样的。从而将cross-attention的计算从缩减到了,因为相比要小得多
(可选)将个候选分成个microbatches,每个batch有个候选,从而在如下两个场合利用KV caching(Efficiently scaling transformer inference):
前向pass中,用于降低消耗
requests之间,降低长尾耗时
其他
发现了scaling-law:

快手的OneRec(听说比较扯淡)
OneRec: Unifying Retrieve and Rank with Generative Recommender and Preference Alignment
「快手」全链路统一建模|OneRec: Unifying Retrieve and Rank with Generative
效果&成本双突破!快手提出端到端生成式推荐系统OneRec!
召回排序合为一体的生成式推荐——根据历史session序列,预测下一个session。
阿里的HeteroRec(落地)
item有各种特征,如title、img、id等
左边:异构信息分解(HTFL)把1-T个item的各种特征(每个特征当成一个token)flatten成一个长序列,然后过一个causal transformer得到token粒度的输出list,再过一个item粒度的causal transformer得到item粒度的输出list
右边:个item,每一种特征把拼到一起过各自的tower,每个tower得到的感觉还是个输出,这个输出和左边的token粒度的输出List算个LMP,然后过一个item cross tower,我猜输出的是个item表示,和左边的item粒度输出List再算一个LMP
LMP:左边是,右边是,t1过个mlp预测t3,t1过另一个MLP预测t2,即multi-step预估

Meta的DTI(没落地)
Towards An Efficient LLM Training Paradigm for CTR Prediction

。。好像没啥,就是预测未来k个,并且设计了滑动窗口的mask(右下角)
华为的UniGRF(没落地)
美团的MTGR(落地)
MTGR: Industrial-Scale Generative Recommendation Framework in Meituan
听说是替换了精排
阿里的SORT-Gen(落地)
sigir'25「淘宝」多目标重排|A Generative Re-ranking Model for List-level
A Generative Re-ranking Model for List-level Multi-objective Optimization at Taobao
将用户的所有行为聚合成一条样本。每个行为包括四个方面:用户侧、位置、商品侧、精排打分,将行为序列送入tansformer中。
保序回归损失
生成方法:先设计不同的rankscore得到多路序列候选,再比较每一路的top1,决定召回哪一路。
纯价值驱动的列表生成可能有同质化的风险,导致多样性降低。引入相似度惩罚:
小红书的RankGPT(落地)
Towards Large-scale Generative Ranking
美团的UniROM(落地)
One Model to Rank Them All: Unifying Online Advertising with End-to-End Learning
Meta的RPG(没落地)
Generating Long Semantic IDs in Parallel for Recommendation

训练:
长语义ID(SID)构造:使用OPQ(optimized pq)将物品特征(文本、图像等)编码为SID(最多64个token),每个token来自不同codebook,编码物品语义子向量。相比RQ,OPQ没有token间的顺序依赖,适合并行生成,且信息分布更均衡。
多token预测(MTP):通过MTP损失函数,并行预测语义ID的所有token
infer:
图构建:将每个SID的64个token的embedding通过mean/max pooling成一个语义embedding。使用faiss存储这些embedding,并为每个语义ID搜索top-k个最相似的SID,作为图的边,构建一个的解码图。
迭代图传播:随机初始化b个SID beam,从这b个节点出发,沿图传播,从相邻的SID里保留得分最高的b个ID。迭代q次,生成最终的top-K推荐列表。
LLM+推荐:输入文本
华为的KAR(落地)
Towards Open-World Recommendation with Knowledge Augmentation from Large Language Models

LLM生成user侧的preference reasoning知识
LLM生成item侧的factual知识
这两部分知识输入一个encoder得到两个表示,然后再过个mmoe产出merge后reasoning augmented vec和fact augmented vec,一起作为CRM的输入特征。
对应的prompt如下:

看实验应该是用在召回,每个user和vec去找最像的k个item,但没法ann,只能暴力算
代码:https://github.com/YunjiaXi/Open-World-Knowledge-Augmented-Recommendation/blob/main/knowledge_encoding/utils.py,其实就是把模型输出的hidden states处理一下:
x = tokenizer(x, padding=True, truncation=True, max_length=512, return_tensors="pt",
return_attention_mask=True).to(device)
mask = x['attention_mask']
outputs = model(**x, output_hidden_states=True, return_dict=True)
pred = get_paragraph_representation(outputs, mask, aggregate_type)
def get_paragraph_representation(outputs, mask, pooler='cls', dim=1):
last_hidden = outputs.last_hidden_state
hidden_states = outputs.hidden_states
# Apply different poolers
if pooler == 'cls':
# There is a linear+activation layer after CLS representation
return outputs.pooler_output.cpu() # chatglm不能用,用于bert
elif pooler == 'cls_before_pooler':
return last_hidden[:, 0].cpu()
elif pooler == "avg":
return ((last_hidden * mask.unsqueeze(-1)).sum(dim) / mask.sum(dim).unsqueeze(-1)).cpu()
elif pooler == "avg_first_last":
first_hidden = hidden_states[1]
last_hidden = hidden_states[-1]
pooled_result = ((first_hidden + last_hidden) / 2.0 * mask.unsqueeze(-1)).sum(dim) / mask.sum(dim).unsqueeze(-1)
return pooled_result.cpu()
elif pooler == "avg_top2":
second_last_hidden = hidden_states[-2]
last_hidden = hidden_states[-1]
pooled_result = ((last_hidden + second_last_hidden) / 2.0 * mask.unsqueeze(-1)).sum(dim) / mask.sum(dim).unsqueeze(-1)
return pooled_result.cpu()
elif pooler == 'len_last': # 根据padding方式last方式也不一样
lens = mask.unsqueeze(-1).sum(dim)
# index = torch.arange(last_hidden.shape[0])
# print(index)
pooled_result = [last_hidden[i, lens[i] - 1, :] for i in range(last_hidden.shape[0])]
pooled_result = torch.concat(pooled_result, dim=0)
return pooled_result.cpu()
elif pooler == 'last':
if dim == 0:
return last_hidden[-1, :, :]
else:
return last_hidden[:, -1, :]
elif pooler == 'wavg':
# Get weights of shape [bs, seq_len, hid_dim]
weights = (
torch.arange(start=1, end=last_hidden.shape[1] + 1)
.unsqueeze(0)
.unsqueeze(-1)
.expand(last_hidden.size())
.float().to(last_hidden.device)
)
# Get attn mask of shape [bs, seq_len, hid_dim]
input_mask_expanded = (
mask
.unsqueeze(-1)
.expand(last_hidden.size())
.float()
)
# Perform weighted mean pooling across seq_len: bs, seq_len, hidden_dim -> bs, hidden_dim
sum_embeddings = torch.sum(last_hidden * input_mask_expanded * weights, dim=dim)
sum_mask = torch.sum(input_mask_expanded * weights, dim=dim)
pooled_result = sum_embeddings / sum_mask
return pooled_result.cpu()
else:
raise NotImplementedError
蚂蚁的BAHE(落地)
SIGIR'24 | 打破长度障碍:LLM增强的长文本用户行为CTR预测
Breaking the Length Barrier: LLM-Enhanced CTR Prediction in Long Textual User Behaviors

防止由于重复编码相同用户行为而产生的计算冗余:利用LLMs的预训练浅层提取来自用户序列的最细粒度的原子用户行为(例如购买星巴克、订酒店)的emb,并将它们存储在离线数据库中
从db里查出来,和item一起过LLMs的更深层可训练层
快手的LEARN(落地)
https://zhuanlan.zhihu.com/p/705497209
过往的llm+推荐的两种思路:
freeze LLM参数并适应推荐领域数据:将用户行为历史改写成文本prompt,直接丢给LLM生成top-k推荐结果,例如:
在推荐领域的特定文本数据集上微调LLM:利用LLM捕捉用户行为序列,通过设计提示prompt,使LLM学习用户和物品之间的潜在关系,在预测任务中理解用户的偏好变化和行为模式,从而更好地预测用户可能感兴趣的物品,例如:
上面两种方法可以看成是Rec-to-LLM,即将推荐这个target domain适配到LLM这个source domain上去,有如下缺点:
将用户历史全丢给LLM不现实:一方面开源的LLM目前只支持1k(baichuan)-4k(llama),不支持这么长的序列,另一方面复杂度和序列长度呈二次关系
微调的方案可能会出现灾难性遗忘(catastrophic forgetting):全参数微调,会让模型丢失在预训练过程中学到的开放世界的知识,而LoRA的效果也不好。原因:
domain gap:两个领域有巨大的差别(profound gap),Continual Learning of Large Language Models: A Comprehensive Survey发现了全量参数微调会导致LLM对原有知识domain的严重的灾难性遗忘。
训练目标不对齐(misalignment):LLM是next token prediction,学习大语料的general知识;finetune则主要是检索类的任务,强依赖用户-item的交互行为
其实有rec-to-llm和llm-to-rec两类想法

快手商业化把llm用到推荐的思路变化:

本文提出了LEARN(Llm-driven knowlEdge Adaptive RecommeNdation),实现了LLM-to-Rec,让LLM作为content extractor,推荐任务是训练目标。

Content EXtraction(CEX):输入item描述,过预训练的LLM(参数freeze)得到的每个token的输出pooling得到item的emb
Preference ALignment(PAL):把个输入一个content adapter(就是一个MLP),然后过12层的可训练的transformer得到个输出emb,最后再过一个online projection(也是一个MLP)降维到64,得到

假设用户点击了H+T个item,拆成1H和H+1H+T这两部分,
user tower:1~H的item输入CEX+PAL,得到H个输出
item tower:有3个,结构都是输入H+1~H+T的item,网络参数和user tower共享;infer时只输入一个item
item tower a:经过CEX得到,再经过PAL得到,和user tower一样用causal attention
item tower b:经过CEX得到,再经过PAL得到,使用self-attention,每个item只关注自己
item tower c:只经过CEX,直接得到
消融后发现item tower a效果最好,所以用了a
loss用的是pinnerformer的dense all action loss(PinnerFormer: Sequence Modeling for User Representation at Pinterest),即从1~H
里随机挑m个出来,每一个去预估H+1~H+T
里的随机一个正样本

在线使用时如下图,其中user emb和item emb就是两个tower的输出,会先concat并过个小fusion module得到fusion emb,然后一方面过个mlp算个cvr loss,另一方面和user emb、item emb还有其他特征concat再送给后面的模块正常算ranking loss

阿里的BEQUE(落地)
Large Language Model based Long-tail Query Rewriting in Taobao Search WWW24

multi-instructions的sft:基于在线日志,通过拒绝采样得到multi-instrunctions的SFT数据集,任务是重写query,还混合了质量分类、query改正、CoT任务
其中的3个task如下:
Quality Classification
Is this a good e-commerce query rewrite? Query: {query} Rewrite: {rewrite} System: {Yes or No}
Title Prediction
Please generate product titles that match input query Query: {query} System: {product title}
Chain of Thought
Your task is to rewrite the input query into a query that makes it easier to search for related products, and you are required to give the thought process and then the query rewriting result. The thought process and the query rewriting result are separated by a semicolon. Query: {query} System: {CoT}; {Rewrite}
offline feedback:用训好的LLM生成多个候选rewrites,构建了一个离线的淘宝系统,对这些候选rewrites进行搜索得到结果,并用结果的quality scores来对候选rewrites进行排序
objective alignment:基于候选的rewrites的排序,使用PRO方法(Preference ranking optimization for human alignment)来逼近这个排序。
给定顺序,preference probability如下,其中是reward函数:
对应的PRO loss如下,,:
应用:离线刷库,实验的gmv、单量都有收益,长尾query效果更好
小红书的NoteLLM(落地)
WWW'24 | 小红书NoteLLM: 大语言模型用于I2I笔记推荐
NoteLLM: A Retrievable Large Language Model for Note Recommendation
3个任务:
I2I笔记推荐任务: 给定目标笔记,基于LLM从内容池中找出top-k个相似笔记
主题标签生成任务:基于笔记的标题和内容, 用LLM生成对应的k个主题标签。
类目生成任务:基于笔记的标题、内容、主题标签,用LLM生成对应的类目。
笔记压缩prompt:
[bos]<instruction><input notes>The compression word is:"[EMB]".<output guidance><output>[eos]
其中的[EMB]是一个特殊token,类比bert里的[CLS]

生成式对比学习
生成式对比学习(Generative-Contrastive Learning,GCL)
通过统计共现信息,同时打压热门,得到item pair对
由于LLMs的自回归特性, 将[EMB]的前一个token对应的最后一个隐层输出经过一个linear layer得到一个d维向量
对于batchsize=B的batch来说,有B个pair对,即2B个item,那么对它们算一个对比学习的loss,其中的sim是cos相似度:
协同监督微调
协同监督微调(Collaborative Supervised Fine-Tuning,CSFT)将主题标签生成任务和类目生成任务联合训练,一个batch里40%的样本执行主题标签生成任务,剩下的60%做类目预测任务,然后走正常的语言模型自回归任务:
然后将这两个loss加权求和():
小红书的NoteLLM-2(落地)
Google的2个LLM(落地)
novelty LLM
Llms for user interest exploration in large-scale recommendation systems
对llm进行sft,输入用户喜欢的K个cluster,预测下一个cluster。

cluster包括了一系列短语,如(猫,狗,动物,宠物,小动物)可能是一个cluster,(船,轮船,皮划艇,独木舟)可能又是另一个cluster。使用的2级cluster,共761个取值。
基于gemini进行sft,拿7000多个样本(每个,组合,找到最高频共现的10个出来),bs=16,训了3000个step
线上生效:然后K=2,即只需要batch跑个组合的infer就行了。来一个用户,拿出他的2个cluster的组合,去存储里找到对应的预估的下一个cluster
2个LLM
User Feedback Alignment for LLM-powered Exploration in Large-scale Recommendation Systems

先拿novelty-llm开实验(也可以直接拿线上这路召回的结果),收集用户对推荐出来的这些类目的正负反馈,然后组织成pointwise或pairwise的语料,训练一个类似reward model的alignment-llm。

纯离线infer:用novelty llm采用比较高的temperature预测多次,然后用alignment llm打分选挑出topk的cluster,存起来给线上用。
实验对比线上基线的novelty-llm,pointwise和pairwise在多样性、正反馈动作率、完成率均有提升,鈤pointise训练得更快,所以最终推全pointwise
Google的惊喜度推荐(落地)
Serendipitous Recommendation with Multimodal LLM
基于Cluster Anchor Regularization to Alleviate Popularity Bias in Recommender Systems搞了一个4级的聚类,每个item属于某个树节点,每个节点有对应的自然语言描述。
惊喜度:2个item属于同一个中间节点,但不同的子节点,两个节点可以间隔若干层
拿惊喜度高的样本(一个context item_id,next item_id),即来sft一个MLLM,通过如下方式保证不同cluster的均衡
先把映射到其cluster ,得到
对每个context video ,聚合的满意度,即
对每个,选择最高的10个context videos丢到训练数据里去

prompt1、2、3都是直接输出预测的cluster,1和2是单模态(text/video),3是多模态(text+video)
prompt4是CoT,其实就是让模型先总结出当前视频的cluster,再预测下一个不同的cluster
衡量标准:
match rate:生成的描述是否是合法的cluster
recall:生成的描述和label的描述是不是完全一样
发现:
match rate不同prompt差不多,都能很快收敛到接近99%,而且video+CoT能大大加速这个收敛速度
video很重要,带上video的比text only要好很多
video+CoT比video略好
video+text不如video only,说明这个prompt3还比较粗暴
另外还发现帧数越多效果越好,但match rate的收敛速度不受影响
实际推理时用了能cover 80%展现的高热视频,只需要不到12小时就能推理完;后来做了增量更新版本,但因为高热视频变化不多,所以速度也可以接受
快手的LARM(落地)
LLM-Alignment Live-Streaming Recommendation

结合直播的特点:同一个直播间在不同时间段的内容不同,不同用户由于进房时间不同,看到同一个直播间的内容也不同。
整体思路还是比较简单的
输入直播间和主播的基础信息,拿100B的llm标出来一些数据(生成如下的问答pair对、以及对直播内容的总结与理解),去finetune一个7B的llm
用这个7B LLM产出emb(pooling)结合主播侧特征通过gating融合得到直播间emb,和user去双塔inbatch softmax
【这一步的时效性比较高,每30秒更新一次】拿上面融合过的emb,通过rq-vae进行聚类,把对应的code扔给线上推荐模型
qa类prompt:
Live-streaming information: #time, #images, #speeches, #comments, #author_information;
You need to pay attention to the fact that the person in the
live-streaming may not be the author himself, but someone else.
Please generate ten instruction questions as diverse as possible
based on the provided live-streaming information. These
questions are about facts or an understanding and evaluation
of relevant content. Do not ask any questions that cannot be
answered confidently.
Finally, you need to return the result in the following form:
1. {"Question":..., "Answer":...}
2. {"Question":..., "Answer":...}
总结类prompt:
Live-streaming information: #time, #images, #speeches, #comments, #author_information;
You need to pay attention to the fact that the person in the
live-streaming may not be the author himself, but someone else.
Complete the following tasks:
1. Describe the current events and content in the live broadcast
room in detail in one paragraph, including but not limited to:
Content: including detailed visual information, such as whether
there is text, the look and feel of the picture, the tone, etc.
#other_tasks,
Finally, you need to return the result in the form of json:
{ "Event and content": {
"Content": ...,
"Character": ...,
"Scene": ...,
"Event": ...,
"Atmosphere": ...,
"Highlights": ...,
"Target user group": ... },}
实验部分列了两个主场景的收益,但没有说实验流量
阿里的URM(落地?)
当购物用上大模型!阿里妈妈首发世界知识大模型,破解两大推荐难题
Large Language Models Are Universal Recommendation Learners

2个特殊token:
[UM]
对应的输出通过用户建模头映射到用户表示空间,用于候选商品的生成。如图,每个item对应一个[UM]
;[LM]
及其后续符号对应的输出通过语言模型头映射到文本空间,用于文本token的生成。

item emb的获取:
融合id emb,文本emb和图像emb
底层的文本encoder和图像encoder freeze,上层的mlp可训练
sft训练(应该就是下面那个模型)
Sequence-In-Set-Out:其实就是把[UM]
的输出拆成H个,每个去和item向量算相似度,再merge到u和i的相似度
最终sft的时候计算UM的loss和LM的loss,即图中的item和文本的loss

Spotify的LLM Preview生成
Transforming Podcast Preview Generation: From Expert Models to LLM-Based Systems
推荐算法(2025.6.3):Spotify的LLM应用,效果明显
蚂蚁的SLIM(没落地)
Can Small Language Models be Good Reasoners for Sequential Recommendation?

第一阶段:蒸馏大型GPT模型到较小的模型(如LLAMA2/3),来增强推理能力。
通过预设的 prompt,大模型生成推荐理由,这些理由基于预定义的模板。接着,
使用简化的推理模板请求小模型进行推荐和理由生成。
第二阶段:利用生成式Loss来微调小模型,使其具备推理能力。
模型训练完成,将通过prompt为用户行为提供T+1推理。
推理结果通过文本编码器(Text Encoder)转化为表征,这些表征将直接应用于线上模型。
OPPO的DLLM2REC(没落地)
在蚂蚁的SLIM的基础上,希望将LLAMA进一步压缩至更小的序列模型。在实验中遇到几个挑战:
蒸馏过程中教师模型的知识可靠性存疑
从语言模型到序列模型的蒸馏跨越了不同的模型类型,带来两个主要问题:
参数差距大,学生模型难以容纳教师模型的知识
语义不一致,因为序列模型与原始语言模型之间存在天然差异

包含两个关键部分:基于Ranking的蒸馏策略(Importance-aware Ranking Distillation)和Embedding对齐(Collaborative Embedding Distillation)
核心在于排名蒸馏,采取了如下三个策略
选择LLAMA2作为教师模型,认为其排名靠前的分值更高;
考虑LLM生成的描述与目标物品(Target Item)的接近程度,增加其排名;
若教师模型(Teacher Model)认为某物品是优质且排名靠前的,学生模型(Student Model)也会给予其更高排名。
通过这些策略,设计了Ranking Loss,用于蒸馏小型序列模型
其中,是teacher返回的topk结果,是训练集的序列数,,包括如下3部分:
position-aware weight:,是item 在teacher返回结果里的排名,是一个超参
confidence-aware weight:,且,是生成的item描述,是ground truth的item描述,分别通过一个llm encoder得到向量
consistency-aware weight:同时被teacher和student推荐的item更有可能是一个强正例
快手的LLM-CF(没落地)
2024'快手提出LLM-CF框架,借助LLM的链式思维(COT)推理提升推荐系统性能
CIKM24,Large Language Models Enhanced Collaborative Filtering
https://anonymous.4open.science/r/LLM-CF-AD78/readme.md
简单总结:
拿推荐数据对llama2做sft,再用CoT的prompt让llama2对user+item+label产出一个推理过程,并通过bge得到emb,构建一个CoT数据集。在线拿当前用户+item的特征从这个数据集里ann出k个cot example的emb,和其他特征一起输入一个decoder,输出给推荐模型的sharebottom,额外加了一个CoT emb的重建loss。
文中用到的instruction prompt参考(Recsys23的TALLRec: An Effective and Efficient Tuning Framework to Align Large Language Model with Recommendation和WWW24的ReLLa: Retrieval-enhanced Large Language Models for Lifelong Sequential Behavior Comprehension in Recommendation),把推荐变成了一个让模型输出yes/no的2分类任务。这里的是包括用户特征和当前item特征的文本描述,是点击的label(0/1)。

整体的框架如下:

离线:
finetune LLM使其具有推荐能力
使用CF的信息生成CoT Reasoning
构造一个in-context CoT数据集
在线:
检索和用户相似的in-context CoT examples,学习世界知识和Reasoning指导的CF特征,拿来给推荐系统用
离线部分
recgen-llama
如果直接用TALLRec的方法,会有灾难性遗忘,模型在原来的LLM benchmark上效果会下降很多,提出了一种简洁高效的全量参数微调方法,在general data和推荐能力上找到平衡,可能的做法
base:不微调,原始llama2
half:用一半的推荐数据全量参数微调
full:用全量推荐数据全量参数微调
LoRA:对Q和V矩阵加LoRA,设置rank=8
加噪声:NEFTune: Noisy Embeddings Improve Instruction Finetuning和HyPe: Better Pre-trained Language Model Fine-tuning with Hidden Representation Perturbation,用推荐数据finetune的时候,在input的embedding层加噪声
Wise-FT:Robust Fine-Tuning of Zero-Shot Models,这个引用量挺高的,https://github.com/mlfoundations/wise-ft,将pretrained和finetuned的权重加权融合:
RecGen:How Abilities in Large Language Models are Affected by Supervised Fine-tuning Data Composition发现通过mixed-data finetuning能够保持通用能力的情况下,提升数学和代码能力
对比下来发现,R3F在推荐和MMLU上都最差,full在推荐上效果最好但在MMLU上不太行,RecGen在推荐的效果还不错在MMLU也没降多少,所以将推荐数据和通用数据(如LIMA(Lima: Less is more for alignment)和alpaca-gpt4(Instruction tuning with gpt-4))混合。
CoT Reasoning生成
通过如下的CoT prompt ,可以实现如下过程:
用RecGen-llama系统性地分析用户的交互历史和反馈,建立一个详细的用户profile。
RecGen-llama对目标的新商品进行特征的详细描述。
RecGen-llama考虑用户画像与目标商品特性之间的契合度。
RecGen-llama反思用户在购买中可能对多样化的需求。
即RecGen-llama的输出是
其中的CoT prompt 是:
<<SYS>> As an AI model developed for analyzing consumer behavior, your task is to
generate a chain of thought that considers the following points:
1. Utilize the user's interaction history and review comments to summarize their profiles.
2. Introduce the target new item and detail its features precisely. In addition, integrate
information about items related to the current target new item ...
1. Contemplate the alignment between the user's profile and the features of the target item.
2. Reflect on the user's potential desire for diversity in their purchases.
Your output should be a clear and logical chain of thought... Ensure your analysis is
impartial... Focus should be on understanding factors that influence the user‘s decisionmaking regarding the target item. <</SYS>>
Please generate a chain of thought based on the user‘s … considering how these might
relate to their interest in the target new item.
{Recommendation Features}
User's decision-making: The user {Ground-Truth Label} the target new item.
Let's think step by step and develop the chain of thought for the above considerations.
Commence with the chain of thought immediately:
---------------
<<SYS>> 作为一个用于分析消费者行为的AI模型,您的任务是生成一条思维链,考虑以下几点:
1. 利用用户的互动历史和评论总结他们的个人画像。
2. 介绍目标新商品并详细说明其特点。此外,整合与当前目标新商品相关的其他商品信息。
3. 思考用户画像与目标商品特性之间的契合度。
4. 反思用户在购买中可能对多样化的需求。
您的输出应当是一个清晰且逻辑严谨的思维链,确保您的分析公正无偏,重点应放在理解影响用户决策的因素。<</SYS>>
请生成一个思维链,基于用户的……考虑这些因素可能如何影响他们对目标新商品的决策。
{Recommendation Features}
用户的决策:用户 {Ground-Truth Label} 目标新商品。
让我们一步一步地开发上述考虑因素的思维链。
立即开始思维链:
从原始的推荐数据集随机sample出M个,生成对应的,可以得到CoT数据集:
性能分析
训练:发现相比用全量数据训练,用一半的数据训出来的模型在MMLU上效果更好,在推荐上的效果差不多,所以可以用小数据集来finetune
生成:对比Towards Open-World Recom- mendation with Knowledge Augmentation from Large Language Model提出的KAR(用户特征和item特征相对固定,可以提前存生成结果),LLM-CF应用的场景有很多新用户和新item,但并不需要流式更新
在线部分

In-context CoT Examples Retrieval
对于上面的CoT数据集,拿对应的文本作为query,而数据集里的个examples对应的key是。
先通过BGE embedding(C-Pack: Packed Resources For General Chinese Embeddings)作为encoder把query 和keys 转成向量
然后通过ANN找出top K个examples
做了2个trick:
避免穿越,保证不包括未来的steps的交互信息
为了让正负例比例对下游任务不造成影响,保证中的正例和负例比例是1:1
In-context Chain of Thought Module
ICT模块将当成in-context examples,并把当成query,对应的ICT tokens就是
然后得到这些token对应的embs:
其中,(图中右上角橙色部分)
文本特征同样经过BGE encoder,
里的推荐特征则经过推荐模型的feature encoder得到,
CoT reasoning 则是通过text encoder和MLP映射
label 也是一个0/1的id对应的embedding
然后把经过若干层transformer decoder,得到输出的表示:
最终得到的表示可以是这个输出的last hidden state:
在各数据集上评估时,发现CoT examples的个数K=4效果就不错了,对应的ICT tokens 的长度也只有12左右。
Model Training
原来推荐的loss是,这里加上一个对CoT examples的emb的重建loss:
最终的loss如下
Efficiency Analysis of Online Service
图中的蓝色火焰部分需要在线计算,而因为,所以很轻量
Google的ILM(没落地)
Item-Language Model for Conversational Recommendation
适用场景如下,{user}可以看成一种特殊的{item},{history}是若干个item

参考BLIP-2(Blip-2: bootstrapping language-image pre-training with frozen image encoders and large language models)提出的Q-former:

引入了Q-former

phase1:表示学习,交替训练如下两类表示学习
item-text表示学习:
query的tokens和item的cf emb过cross attn后,拿cls的输出得到v1
text过attn得到v2
v1和v2算item-text对比学习
v2走一个自回归的任务(item grounded text generation)
item-item表示学习
query的tokens和item1的cf emb过cross attn后,拿cls的输出得到v1
query的tokens和item2的cf emb过cross attn后,拿cls的输出得到v2
v1和v2算item-item的对比学习
phase2:item-language model训练
Q-former的item encoder经过一个linear输入到LLM中
LLM参数freeze,只tune Q-former的参数和linear
Meta的EmbSum(没落地)
RecSys'24 | Meta:使用LLM的摘要能力提升内容推荐

user session encoding:先将用户k个行为序列化分成个session,每个session里有个content,这p个content的文本单独过transformer encoder(T5 small),拿开始的token(
[SOS]
)对应的输出当成文本表示user engagement summarization:将用户的历史丢到一个prompt里去,让llm总结出一段话,然后参考Leveraging Passage Retrieval with Generative Models for Open Domain Question Answering,把llm输出的所有tokens的hidden states concat在一起,再丢给T5 decoder,并加一个自回归的loss,其中表示生成的用户的summary,而是summary的长度

user poly embedding(upe):把decoder最后一个token(
[EOS]
)拿出来,和前面的k个session encoding一起得到一个,然后过一个poly-attention layer,得到用户的个兴趣表示,其中每个向量是,其中和是可训练的参数content poly embedding(cpe):和upe类似,k个session encoding换成当前item的encoder输出,UPE里的
[EOS]
换成当前content的下一个token即[SOS]
,然后得到个维表示融合:可以算出一个的相似矩阵,然后flatten,得到一个维的向量,同理算一下,得到的就是两个向量的内积,即相似度的得分了
百度的Agent4Ranking(没落地)
Agent4Ranking: Semantic Robust Ranking via Personalized Query Rewriting Using Multi-agent LLM

其中的rewrite模块如下,搞4个agent,模拟4个人群的人与LLM对话,最终得到符合人群特点的rewrite

其中的rank模块如下,是一个bert,输入原始query和4个rewrites,加上target item,MMOE,算5个query间的js散度(robust loss),以及综合输出和label的accuracy loss

丰田的SimUSER(没落地)
SimUSER: Simulating User Behavior with Large Language Models for Recommender System Evaluation
两阶段方法:
自一致的用户画像匹配,利用LLM从历史数据中抽取个性特征;
推荐系统评估,模拟具有个性、记忆、感知和决策模块的用户与推荐系统进行互动。
CUP(学术界)没中
Recommendations by Concise User Profiles from Review Text
把用户的一堆历史评论扔给chatgpt,让它总结出128个token,然后丢给双塔bert,另一个塔是item的描述,freeze bert底层,只tune上层
LLaMA-E(学术界)没中
LLaMA-E: Empowering E-commerce Authoring with Object-Interleaved Instruction Following
https://huggingface.co/DSMI/LLaMA-E#/
整体流程

instruction formulating: 为图中的任务写300个种子指令
seller :商家,包括商品名、风格、品牌等
customer :
explicit feature :用户的历史交互商品
implicit feature :根据历史交互推断出来的潜在兴趣
platform :为商家和用户建立链接
product correlation :不同商品间的差异和联系
platform background :不同电商平台的背景知识
instruction expansion: 让gpt作为teacher,对300个种子指令进行扩展,并由领域专家评估后,去重并保证质量,得到120k个指令作为训练集
针对结果是严格预定义好的,只重写instruction
[INST] Rewrite the following instruction while maintaining semantic consistency: [/INST] <seed instructions>
针对鼓励生成结果有多样性的,
结果生成:用上面重写过的instruction给LLM来获取结果
[INST] <expanded instructions> [/INST] <seed inputs>
结果重写:拿生成的结果给LLM生成更多样的表达
[INST] Rewrite the following generated response to diversify its expression: [/INST] <responses>
instruction tuning: 对self-attention的q、k、v、o参数进行lora
设计的任务

示例:
Ads Generation
Produce an advertisement for the specified product.
Create an advertisement for the specified product.
Produce an advertisement for the product mentioned below.
Generate an ad designated for the following product.
Prepare an advertisement for the product provided below.
Query-enhanced Title Rewriting
Rephrase the subsequent product title along with the query.
Revise the subsequent product title alongside the query.
Revise the product title below, incorporating the given query.
Revise the given product title in combination with the query.
Incorporate the following query to rewrite the product title.
Product Classification
To which category does the subsequent product belong?
Which category of this product belongs?
Identify the category to which the following product belongs.
What category does the listed product belong to?
Identify the category of the listed product.
Purchase Intent Speculation
Which category does the provided query imply the customer is interested in?
Based on the following query, which category does it indicate the customer is interested in?
What category is suggested by the following customer query’s apparent interest?
What category does the given query indicate the customer’s interest in?
Identify the category that the following query suggests the customer is interested in.
General E-commerce Q&A
How are my orders attributed to Offsite Ads?
Describe the process of attributing my orders to Offsite Ads.
Can you explain how my orders are attributed to Offsite Ads?
Please elaborate on the process of attributing my orders to Offsite Ads.
How are my orders linked to Offsite Ads?
对应的中文:
广告生成
为指定的产品制作一则广告。
为指定的产品创建一则广告。
为以下提到的产品制作一则广告。
为以下产品生成一则广告。
为提供的产品准备一则广告。
查询增强的标题重写
根据查询改写后续的产品标题。
根据查询修改后续的产品标题。
根据提供的查询修改以下的产品标题。
将给定的查询与产品标题结合进行修改。
使用以下查询重写产品标题。
产品分类
以下产品属于哪个类别?
这个产品属于哪个类别?
确定以下产品属于哪个类别。
列出的产品属于哪个类别?
确定列出产品的类别。
购买意图推测
提供的查询暗示用户感兴趣的类别是哪个?
根据以下查询,用户可能感兴趣的类别是什么?
以下用户查询暗示的兴趣类别是什么?
给定的查询表明用户感兴趣的类别是什么?
确定以下查询暗示用户感兴趣的类别。
通用电商问答
我的订单是如何归因到站外广告的?
描述我的订单归因到站外广告的过程。
你能解释一下我的订单是如何归因到站外广告的吗?
请详细说明我的订单归因到站外广告的过程。
我的订单是如何与站外广告关联的?
EcomGPT(学术界)AAAI24
EcomGPT: Instruction-tuning Large Language Model with Chain-of-Task Tasks for E-commerce
清华,AAAI 24

设置一系列的task(100多个task)来finetune BLOOMZ(OPT+BLOOM的instruction-following模型)
命名实体识别:输入描述,输出brand、attr、component、product等
描述生成:输入query和候选doc list,选出最match的k个
对话intent提取:输入对话和候选intents(使用咨询、恢复订单、退款异常等),选出对应intent
Llama4Rec(学术界)SIGIR24

prompt增强:在prompt里引入推荐模型的信息
相似用户也喜欢item4、item5
另一个推荐模型给出的预估是xxx
数据增强:通过LLM给推荐模型增加样本
直接推荐:给定2个候选item,LLM判断哪个更好
序列推荐:给定候选list,LLM给出topk
评分预测:给定候选item,LLM给出打分
adaptive aggregation:llm和推荐模型都给出排序,然后自定义融合公式算出融合分,得到最终排序
示例prompt如下

通过如上prompt构建一个instruct-tuning数据集,然后finetune一个llama2
SAGCN(学术界)ACM TOIS
https://github.com/HuilinChenJN/LLMSAGCN
通过LLM标识出用户对item的评论是属于哪些aspect的,然后u有A个emb,i也有A个emb,构建A个U-I图,然后揉在一起过GCN

拿一些数据先用prompt1让LLM粗略标出用户评论所属的aspects,然后merge并去重得到候选的aspects列表
把这个候选aspects列表(图中的蓝色文字)丢给prompt2,让LLM对所有用户的评论打标
然后为每个aspect构建一个graph,过GCN

GReaT(学术界)ICLR23
Language Models are Realistic Tabular Data Generators
ICLR2023,https://github.com/kathrinse/be_great
通过自回归的LLM合成(synthesize)逼真的(realistic)表格化(tabular)数据

finetune:
把表格转化为逗号分隔的自然语言
随机交换几个属性的位置得到训练语料
基于交换后的语料进行自回归的finetune

sample:
基于如下3种方式产出precondition:
只输入属性名,例如“年龄”
输入name-value pair,例如“年龄=26岁”
输入多个name-value pair:例如“年龄=59岁,教育程度是硕士”
然后调用LLM输出其他属性
再转化为表格格式
ONCE(学术界)WSDM24
ONCE: Boosting Content-based Recommendation with Both Open- and Closed-source Large Language Models
WSDM24

GENRE(generative recommendation):闭源LLM产出数据
user profiler: 输入用户行为历史得到的user profile,例如topics有哪些,地区是哪里,过完content encoder后,把对应的topics和地区的emb pooling一下,得到用户的profile表示
content summarizer: 输入item的文本content得到的总结
personalized content generator:输入新用户(readlist<5)比较短的历史,合成这个用户可能比较感兴趣的内容
DIRE(discriminative recommendation):对开源LLM进行改造
最后一层降维,并过一个attention得到一个表示
对32层的llama-7b,只用lora训练最上面的2层
ONCE:
GENRE产出的文本经过DIRE得到输出,其中user profiler用上面的方法处理一下,再和历史items的content summarizer的输出、personalized content generator的输出concat并过mlp得到user vec
item content的文本经过DIRE得到item vec
u和i算内积,学ctr
其中GENRE的3种数据如下:

Agent4Rec(学术界)SIGIR24
On Generative Agents in Recommendation SIGIR24
https://github.com/LehengTHU/Agent4Rec
核心代码是https://github.com/LehengTHU/Agent4Rec/blob/master/simulation/avatar.py,可以发现是用了langchain,包括其中的memory(请求openai的emb接口,本地faiss存)。
1000个真实用户,初始化1000个agent,3个数据集,搞了3000个agent,Agent模拟人的行为,点击、翻页、退出、打分、评价,评价标准:是否真的拟人
整体流程:
先在公开数据集上训一个推荐模型(mf/lightgcn等)
构建1000个agent,模拟和这个推荐模型交互,生成一些新的样本(假设推荐了xxx,你是不是会点?点了,正样本,没点负样本之类的)
加上这些新的样本再去重训推荐模型,发现效果有提升

3个module:
Profile module:
电影profile(流行度等+电影信息丢给gpt4产出的summary)
用户profile(社交属性、活跃度、从众心理(conformity)、diversity(更喜欢探索还是利用)、用户喜好tastes(用户历史行为丢给gpt4,让它总结用户喜欢什么不喜欢什么,会在用户有新行为后再update一下))
memory module:
factual memory: 过去看了哪些电影、动作是什么
emotional memory: 看完后的情绪表达
action module:
看/打分/反馈
满意度
翻页/退出
图中的推荐系统是一个现成的系统/算法,例如MF、lightgcn等
word版的笔记:https://github.com/daiwk/collections/blob/master/assets/multi-agents.docx
RecPrompt(学术界)CIKM24
RecPrompt: A Self-tuning Prompting Framework for News Recommendation Using Large Language Models CIKM24
https://github.com/Ruixinhua/rec-prompt

如图的loop,所有LLM都是调接口的,没有tune
news recommender:一个LLM,输入prompt如下,结果包括排序的list 以及解释(用户点击历史总结出来的topic list和对应的新闻list)
You serve as a personalized news recommendation system.
# Input Format
## User's History News
${history}
## Candidate News
${candidate}
# Output Format
Rank candidate news based on the user’s history news in
the format: "Ranked news: <START>C#, C#,..., C#<END>".
prompt optimizer:另一个LLM,用于生成更好的prompt。包括:
refinement instruction
推荐prompt
recommender的回答:、
ground truth ,
monitor给出的最佳template
observation instruction。
其中,refinement instruction形如:
You should generate an improved
template instruction based on the provided information.
observation instruction形如:
You should focus on how well the recommender’s response
aligns with the user’s click behavior by examining if
the topics from the user’s news history and candidate
news are accurately summarized and matched to the user’s
interests. Specifically, evaluate the clarity of topics
in the recommender’s answer, review the task description
for adequacy, and check the detail in the recommendation
process to ensure it reflects an analysis and summary
of user-interest topics.
monitor:对推荐list和ground truth计算MRR、ndcg,判断当前template是否比之前的有提升
衡量效果:看解释提取的topic的准确性和完整性:
准确性:分母是预测出来的n个topic,分子是有多少个和对应的文章topic是match的
完整性:分母是用户历史点过的topic数,分子是用户历史点过的文章数
PO4ISR(学术界)没中
Large Language Models for Intent-Driven Session Recommendations
https://github.com/llm4sr/PO4ISR

PromptInit:初始化prompt1,输入的数据填充prompt2
PromptOpt:通过self-reflection来优化初始prompt:
收集error cases并用prompt3来让LLM想出可能原因
LLM想出的原因+prompt4来refine出一个prompt5
基于prompt5+prompt6来改写/增强出一个prompt7
基于prompt5和prompt7通过UCB选出一个最优的prompt8
PromptSel:在3个domain上进行上述迭代,分别得到对应domain的最优prompt,也看了下这3个prompt在其他数据集上的表现,最终选出一个泛化性比较好的
Transrec(学术界)KDD24
Bridging Items and Language: A Transition Paradigm for Large Language Model-Based Recommendation KDD24
核心思想如下:

将一个item表示成3部分:id+title+attr,设计三种对应的instruct-tuning任务,其中||xx||+
是一个特殊标记,类似于标识任务类型,对应的代码:
if args.target == "id":
source = "Given the following purchase history of a user: "
+ "; ".join(titles) + ". "
source += "What is the next possible item to be purchased by the user?"
source += " || ID"
elif args.target == "attribute":
source = "Given the following categories of purchase history of a user: "
+ "; ".join(titles) + ". "
source += "What is the category of the next possible item to be purchased by the user?"
source += " || attribute"
if "\n" in source:
source = "".join(source.split('\n'))
if args.query_mode == "attribute":
targets = ["".join(t.split('\n')) for t in target]
if "\n" in target:
target = "".join(target.split('\n'))
if args.target == "id":
target = "|| " + target.strip() + " ##"
yield source + " || +", target
if args.target == "attribute":
for target in targets:
target = "## " + target.strip() + " @@"
yield source + " || +", target
然后是generation grounding,即引入一个特殊的数据结构(FM-index),并进行constrained beam search,让模型能生成候选集中的id/title/attr,然后再遍历全库候选,看不同facet的相似度(会考虑高热打压),加权融合出一个排序

FM-index:参考Autoregressive Search Engines: Generating Substrings as Document Identifiers:例如一个item可以写成
<IDS> 1023 <IDE> Urban Decay Eyeshadow Palette Naked Heat <AS> Makeup <AE> <AS> Eyes <AE>
,并通过wavelet tree存储,给定开始token(如<IDS>
或者<AS>
),可以在里找出所有可能的后续tokens。代码:https://github.com/facebookresearch/SEALconstrained beam search:参考Autoregressive entity retrieval:代码:https://github.com/facebookresearch/GENRE,另外,可以发现title是没有bos和eos的,这样在检索/生成title的时候,是可以检索/生成子串的,也就是论文提到的position-free,同样的方法也可以用在instruct tuning阶段。
E4SRec(学术界)没中
代码:https://github.com/HestiaSky/E4SRec/

把id引进来:先通过现有的推荐模型(如SASRec)得到id embed,然后通过一个linear得到和原始LLM的emb一样长的dim,再嵌入到llm里去,只有这个linear是可学习的
LLM的输出:看代码取的是最后一个词的hidden state,再过Linear映射回推荐模型的dim,再过一个softmax映射到id空间(当然,如果要用到工业界可以正常的召回采样方法,如sampled softmax之类的)
infer:和召回一样,ann
finetune部分代码的大概逻辑如下:
输入:把预训练好的item id emb当成一个nn.Embedding搞到模型里去,然后样本里的item id(每个id都是1-n的数)去查出对应的emb,和instruct的emb、response的emb(
### Response:
这种文字对应的emb)这3个emb一起concat起来作为模型输入label:假设有n个item,因为最后过了个softmax映射到n,所以label就是一个1-n之间的数
infer照理说应该是得到emb,然后去ann,但代码里偷懒了直接拿softmax后的1-n的结果
GPLR(学术界)SIGIR25
You Are What You Bought: Generating Customer Personas for E-commerce Applications
https://github.com/Hanc1999/YouAreWhatYouBought
只对5%-20%的用户用LLM标注,再结合随机游走算法推断全量用户角色,大幅降低标注成本(如1,000万用户年成本由240万降至50万美元)。
用户画像的定义与生成:
多维度可解释表示: 自然语言角色标签,如Bargain Hunters, Health Enthusiasts, Tech Savvy, and Busy Parents。
LLM驱动的角色生成:
原型用户标注:利用LLM分析部分原型用户的购买历史,自动生成如“健康生活倡导者”等标签。
Prompt工程:通过多阶段提示优化(初步生成、去重筛选和用户反馈校验),最终形成平台专属的角色标签集。
小样本LLM标注DUSample(Diversity-Uncertainty,多样性-不确定性):
从用户中筛选稀有角色用户和高不确定性用户(如购买行为难以归类的用户), 确保LLM标注的标签具有多样性,避免主流角色主导。
通过KL散度和熵计算用户的DU Score,优先标注多样得分高的用户,提升标签覆盖范围。
随机游走传播: 用户-商品二分图建模,角色亲和力矩阵:
通过随机游走概率矩阵计算用户间的行为相似性,结合原型用户的角色标签矩阵,得到所有用户与角色的亲和力;
假设相似购买行为的用户具有相同角色, 通过加权聚合原型用户的标签推断未标注用户的角色。
反向近似算法RevAff:
反向传播:从原型用户出发,反向计算其他用户的角色亲和力,避免全图矩阵运算。
误差控制:通过设定绝对误差阈值,仅保留影响大于阈值的传播路径
用户画像与推荐模型集成:将角色表示作为输入特征融入GCN
guided embedding
下面这些还没看。。
P5(学术界)RecSys22
微软的RecExplainer
RecExplainer: Aligning Large Language Models for Explaining Recommendation Models
https://github.com/microsoft/RecAI
新的一篇
Avoid Recommending Out-of-Domain Items: Constrained Generative Recommendation with LLMs
RecLM-ret通过检索机制,从域数据集中找到最相关的item
RecLM-cgen则使用约束生成策略,限制模型仅生成域内的item标题。
Google的STAR
STAR: A Simple Training-free Approach for Recommendations using Large Language Models
腾讯的ECR Recsys24
RecSys'24最佳长论文|腾讯ECR:富有情感的对话式推荐系统
Towards Empathetic Conversational Recommender Systems
微信的PRECISE Recsys24
微信PRECISE:多场景落地基于协同信号和语义信息的生成式序列推荐
PRECISE: Pre-training Sequential Recommenders with Collaborative and Semantic Information
MACRec(学术界)SIGIR24
把推荐系统拆成多个agent
MACRec: a Multi-Agent Collaboration Framework for Recommendation
其他
ACL2024的recgpt 这个好像没啥用,RecGPT: Generative Pre-training for Text-based Recommendation
LLM+Recommendation大模型推荐近期进展|含WWW, SIGIR, AAAI等顶会文章
ClickPrompt: CTR Models are Strong Prompt Generators for Adapting Language Models to CTR Prediction
recsys23的Leveraging Large Language Models for Sequential Recommendation 还有一篇Improving Sequential Recommendations with LLMs,对应的代码:https://github.com/dh-r/LLM-Sequential-Recommendation/tree/RecSys23
meta发的LLM-Rec: Personalized Recommendation via Prompting Large Language Models
CIKM 2024 | 大语言模型推荐中的协同过滤信号和语义信息的深度融合
Collaborative Cross-modal Fusion with Large Language Model for Recommendation
(toread)
生成式推荐最新进展 25年1月8号写的
Aligning Large Language Models with Recommendation Knowledge
LLM+推荐:其他套路
ExFM
GPT4规模大模型落地,Meta提ExFM框架:万亿参数基础大模型的工业级落地成为可能

图中的是FM(teacher,foudation model)在时刻的参数,是FM在时刻的数据集,V是VM(student, vertical model)的对应参数/数据集
co-distillation vs external distillation:
co-distillation:联合训练teacher和student,只拿student去serving。
缺点:训练成本很高,而且线上链路有多阶段的ranking,为每个ranking模型保留一个大的teacher是低效的
external distillation:单独训练teacher模型,是1-to-N的模式,一个teacher可以像foudation model一样指导多个student
流式训练:t时刻的数据训出对应的模型,t+1加载t时刻的数据训练出t+1时刻的模型
ExFM:
t-1的各VM数据聚合成t-1的FM数据,训练得到t-2的FM模型
t的各VM数据聚合成的t的FM数据,训练得到t-1的FM模型
DAS, data augmentation service:FM对每个VM数据进行预估,再加上对应的VM数据,产出VM的训练数据
Auxiliary Head和Student Adapter:使用DAS产出的数据,基于t-1的VM模型利用AH和SA训练得到t的VM模型

数据集生产:
将所有VM的特征和真实label聚合成一个shared dataset,
有很长的时间窗口等待feadback(例如ctr有5-90min,cvr有一天),在这个窗口中,FM可以使用VM的特征给出预估结果
然后从这个shared dataset中取出各VM对应的子数据集用于训练
FM ckpt的维护和更新:
FM有新的ckpt时,会通过SPD(一个db)发布
updater从SPD读到最新的ckpt版本,再写到zeus(一个基于zookeeper的分布式metadata存储)里去
DAS任务从zeus读取最新模型

真实label是,FM预估出来的label(pseudo-label)是,student包括两部分,backbone 和serving head ,其中是MLP,loss是交叉熵:
VM的loss是:
但用一个head来预估2个label会引入bias,所以引入AH(Auxiliary Head)来预估pseudo-label,即,其中是另一个MLP,这样就可以拆成2部分:
真实label的loss:
pseudo-label的loss:
引入以下3个方法强化FM的蒸馏效果:
gradient scaling(gs):AH对backbone的梯度乘一个
label scaling(ls):下式中的,同时要保证scale完的label不越界,即不超过1
loss weighting(lw):下式中的
进一步地,在的基础上再过个MLP,得到SA(student adapter),相应地,加上一个SA与真实label的loss:
然后,为了不让VM的梯度回传给SA,需要加一个stop-gradient,即
整体过程:
优化SA的参数:用$$$$\mathcal{L}_{\text {sta }}\left(\hat{y}^{S A}, y\right)$$
计算
优化VM的参数:用
按自己的理解重新画了下:

SLMRec
ICLR2025 | SLMRec: 重新思考大语言模型在推荐系统中的价值
SLMRec: Distilling Large Language Models into Small for Sequential Recommendation
提出了一种知识蒸馏的方法,使得小语言模型仅用13%的模型参数,取得了比现有大模型推荐方法略好的效果,并取得了在训练/推理阶段6.6x/8.0x的加速。
https://github.com/WujiangXu/SLMRec

teacher每m层分成一个block,共分为B个block;student每n层分为一个block,也是B个block
每个block里,算3个loss:
teacher和student间算2个loss:衡量方向的cos相似度,衡量模长的L2距离
student和真实label(target item)算loss
teacher frozen,只通过lora来训练student
KuaiMod
VLM as Policy: Common-Law Content Moderation Framework for Short Video Platform
首个短视频平台劣质内容判别基准测试:面向快手生态构建了短视频劣质内容分类体系,形式化定义了短视频内容判别任务,并基于真实场景中的用户反馈构建了首个短视频劣质内容判别基准测试。KuaiMod劣质内容分类体系包含4种主要的劣质类别以及15种细粒度劣质类别。基准测试包含1000条短视频样本,涵盖 15种细粒度劣质类别,完全由人工标注,并经过多轮数据清洗以保证正确性。
首个工业级自动化内容判别解决方案:KuaiMod是首个在工业场景下验证了部署价值的自动化内容质量判别解决方案,在快手平台多个场景下的部署结果表明,KuaiMod方案具有能够与人工判别相媲美的准确率。
基于用户反馈的强化学习训练+更新策略:区别于静态的规则或内容判别API,基于判例的劣质内容建模使得KuaiMod可以通过迭代训练数据完成判别策略的更新。为了保证实时性和准确率,我们设计了基于用户反馈的强化学习范式,利用用户的线上反馈构造新的训练数据,实现线上判别服务的天级更新。
GPSD
Scaling Transformers for Discriminative Recommendation via Generative Pretraining
生成式预训练:使用Transformer架构,基于用户行为序列进行自回归生成训练,预测下一项。
判别式训练:使用上面训练的Transformer,输入除了用户行为序列、候选项,还包括其他特征,输出分类概率。
提出五种参数转移策略:
无转移(NT):从头训练,作为基线。
全转移(FT):转移所有参数(稀疏+密集)。
稀疏转移(ST):仅转移稀疏参数(如嵌入表)。
全转移+稀疏冻结(FT&SF):转移所有参数并冻结稀疏参数。
稀疏转移+稀疏冻结(ST&SF):转移稀疏参数并冻结。

GAVE
sigir'25「快手」生成式出价-冠军方案|Generative Auto-Bidding with Value-Guided
Generative Auto-Bidding with Value-Guided Explorations
用序列(Decision Transformer)代替RL,再利用离线强化的方法去弥补没有模拟环境的缺点。DT的一些其他应用:
MDP假设是状态独立的,本质上忽略了竞价序列中的时序依赖关系。
自动出价:一般广告主会设置一个最低ROI(即价值/成本)作为约束,或者说是最大平均成本(CPA,即成本/价值),广告主给定的约束假设是。
DT
DT的输入(reward, state, action)三元组的序列,输出是预测的action,
注意:对于t时刻来讲,输入的是0到t-1时刻的r+s+a,但只输入了t时刻的r和s
:历史出价策略、剩余预算、广告的在线时间等
:出价因子,在广告的value上乘以a,
:t到t+1所有候选impression的总value,
RTG(return to go) :现在到未来的总收益,
GAVE

预测如下4个值:
当前时刻的action:
当前时刻的探索系数:,其实是就是在前面乘一个得到,然后约束一下的范围在0.5到1.5之间(sigmoid(x)+0.5就行)可以减轻OOD(Out-of-Distribution)问题。
假设是的RTG,而是的RTG,定义了如下的w(即比大的概率)
此外,还加了如下的辅助损失,其中和表示的是不更新梯度的和。第一个让接近真实值,第二个表示如果,即比大得比较多,第二项占主导,即让预测的action去你和探索的action ,反之让预测的action去你和实际的action
下一时刻的RTG值:,其实就是把CPA的约束加到RTG的计算里来:
下一时刻的价值分:
目标是如何高效探索,用了一个expectile regression(IQL里的思想,Offline Reinforcement Learning with Implicit Q-Learning),如下,其中是一个loss函数,用模型来预测的分位数,就是让预估价值去预测top百分之85的reward
而对于探索的reward 来讲,则不更新价值的梯度,即,只需要约束reward在价值附近就行
一些tokenizer方法
vq/rq codebook容易坍塌,即马太效应 lfq的熵损失函数能优化codebook利用率,即所有样本的,让xx更尖锐? 然后有个batch内的熵,让xx更平均? 两个相减可以提升表示能力的同时提升利用率
alit(Adaptive Length Image Tokenization via Recurrent Allocation):简单的图片不用那么多token,复杂的多一点
LLM+推荐小结
参考LLM建模方式
meta
item_id粒度的生成式
- 性别年龄等profile特征、action type也可以作为特殊的item_id - 输入item_id list,预测下一个item_id - 一种范式可以同时支持召回和排序
基于开源LLM
FFT:full finetuning
PT:prompt tuning
LAT:layerwise adapter tuning
OT:option tuning
T-FEW:few-shot peft
看着落地的
华为
item llm+user llm
- 让LLM总结item得到item emb; - 让LLM总结user历史得到user emb - 两个emb过一个mmoe做融合得到新的两个emb,给推荐模型用
音乐推荐 涨了播放量
frozen
快手
ItemLLM+user decoder
- item LLM固定,输入item特征得到item emb; - 输入item emb过user的12层trans算dense all-action loss, - 线上推荐模型里加user emb和item emb
广告cvr+收入
frozen
阿里
SFT+离线模拟+PRO
query重写任务,SFT得到一个LLM,将其预测的若干个候选rewrites通过offline system的feedback得到排序,再通过PRO算法再tune LLM
电商搜索,gmv+单量
FFT
看着没落地的
蚂蚁
蒸馏推荐理由
- 输入用户行为历史,大LLM(gpt)产出的推荐理由; - 小llm(llama2)去蒸馏这个理由拿小llm去给出全量user的推荐理由, - 通过BERT得到emb,给推荐模型用
FFT
快手
基于CoT数据集做RAG
- 拿推荐数据对llama2做sft,再用CoT的prompt让llama2对user+item+label产出一个推理过程,并通过bge得到emb,构建一个CoT数据集。 - 在线拿当前用户+item的特征从这个数据集里ann出k个cot example的emb,和其他特征一起输入一个decoder,输出给推荐模型的sharebottom,额外加了一个CoT emb的重建loss
FFT
2阶段训练+q-former
- phase1:表示学习,交替训练两类表示学习(item-text表示学习,item-item表示学习) - phase2:item-language model训练
frozen
meta
LLM摘要+t5 encoder
- 行为历史丢给LLM产出摘要,对应的hidden states给decoder自回归; - 历史item过t5 encoder并concat过poly; - item过t5 encoder过poly;
frozen
百度
agent rewrite+ bert ranking
query重写任务,多个人群当成多个agent,每个通过多轮对话产出一个rewrite,再合在一起经过bert+mmoe计算robust损失+accuracy损失。
frozen
纯学术界
LLM总结+bert双塔
把用户的一堆历史评论扔给chatgpt,让它总结出128个token,然后丢给双塔bert,另一个塔是item的描述,freeze bert底层,只tune上层
last layer FT
gpt扩展instruct
instruction formulating为写300个种子指令,让gpt作为teacher,对300个种子指令进行扩展,并由领域专家评估后,去重并保证质量,得到120k个指令作为训练集,再用lora去instruct tuning
lora
prompt增强+数据增强,finetune
- prompt增强:在prompt里引入推荐模型的信息; - 数据增强:通过LLM给推荐模型增加样本 - adaptive aggregation:llm和推荐模型各自打分并用融合公式融合
FFT
闭源LLM总结、开源LLM做encoder,u-i学ctr
闭源LLM输出文本(user profiler、content summarizer、personalized content generator),给开源LLM得到user表示,item过开源LLM得到item表示,二者内积学ctr
lora训开源,frozen闭源
两个LLM迭代出最佳prompt
给一个初始prompt,让LLM1得到推荐结果,拿一个monitor衡量这个结果和ground truth的mrr/ndcg,再用另一个LLM产出更好的prompt给第一个LLM用,如此迭代,得到一个best prompt
frozen
反思原因并refine/augment地迭代出最优的prompt
给初始prompt,收集error case让模型反思原因并refine出新的prompt,再augment出另一个prompt,并UCB选出最好的prompt,如此迭代
frozen
受限生成
- 将一个item表示成3部分:id+title+attr,设计三种对应的instruct-tuning任务; - 引入一个特殊的数据结构(FM-index),并进行constrained beam search,让模型能生成候选集中的id/title/attr, 再遍历全库候选,看不同facet的相似度(会考虑高热打压),加权融合出一个排序
lora
其他套路
工业界
学术界
讨论
我想输入用户历史行为,通过llm产出用户向量(64维的向量),这个向量可以是历史的总结,也可以是预测未来的一些什么东西,最终用在推荐系统的精排模型里,业界有什么好的方法吗
LLM for 检索
Gecko
谷歌DeepMind发布Gecko:专攻检索,与大7倍模型相抗衡
Gecko: Versatile Text Embeddings Distilled from Large Language Models

主要包括两阶段:
pre-finetuning:类似Large dual encoders are generalizable retrievers,自监督
finetuning:2-step llm distillation,提出了一个FRet数据集(Few-shot Prompted Retrieval dataset)
Pre-finetuning
2个数据集:
大型社区qa数据集:Large dual encoders are generalizable retrievers中的来自网上论坛和qa网站的问答pair对
去各种网站上爬了title-body的pair对,因为Text Embeddings by Weakly-Supervised Contrastive Pre-training发现这种自然出现的pair对对于pre-finetuning embedding模型很有用
pre-finetuning的目标是让模型看到大量的多样性语料,对于一个预训练的语言模型,长度为的句子对应的contextual向量,对于任务特征,数据集,得到的向量如下:
对于batchsize为的样本来说,inbatch负例,,其loss如下:
在这个阶段没有用hard负例,用了能适配设备的最大batchsize,这是Towards General Text Embeddings with Multi-stage Contrastive Learning和Text embeddings by weakly-supervised contrastive pre-training里的经验。
FRet

LLM-based Diverse Query Generation
从web语料中抽出一个段落,是一个固定的few-shot的prompt,让LLM生成任务描述和这个task的query
生成的任务t例如:
question answering:
Given a query, find a passage that has the answer to the query
fact checking:
Given a query, find a passage that allows you to check whether the query is true or not
为了保证多样性:
网页库本身就有很多的topic和很多的写作风格
在prompt里加多样的任务描述,来让模型生成的query保证多样性。
LLM-based Positive and Negative Mining
对于某个query ,之前的工作一般会直接把输入的段落当成正样本,但实践中发现一般比较长,而生成的query一般只关注其中一小部分,所以可能在整个语料库中有比更准确的答案。因此,通过如下方法构造了一个FRet数据集:
先把当成正样本,in-batch负例训一个embedding模型。
用这个模型从文档库中检索出top N的相似段落
用生成query的LLM给这N个文档排序,有两种排序方法:
query likelihood:参考Improving passage retrieval with zero-shot question generation,给定段落,衡量query 的likelihood,,其中的prompt参考PaRaDe: Passage Ranking using Demonstrations with Large Language Models包括了判断query likelihood的指令,以及一些相关query+段落的few-shot。基本思想是:如果q和p高度相关,那么从p生成q的概率应该很高。
relevance classification:参考Beyond yes and no: Improving zero-shot llm rankers via scoring fine-grained relevance labels,给定query 和段落后,衡量特定相关性label的log likelihood:。基本思想是:让LLM直接判断q和p的相关程度,并输出一个相关性标签。
通过标准的Reciprocal Rank Fusion(RRF,倒数融合,Reciprocal rank fusion outperforms condorcet and individual rank learning methods)方法得到rank函数,对上面两个方法的排序结果merge:...其实就是rankindex
基于得分筛选样本:
正样本:
hard负例:排名第位的样本,也可以从除了第1个外的N-1个里随机sample
Unified Fine-tuning Mixture
除了FRet,还融合了多个公开数据集:
Natural Questions:Natural Questions: A Benchmark for Question Answering Research
huggingface上的一些分类数据集
将这些数据集处理成一个统一的格式,发现不同的任务对prompt的格式敏感程度不同,,非对称任务(如BEIR)对格式更敏感,而对称任务的性能相对稳定。
对称格式(Symmetric Formatting):输入和目标使用相同的格式。
输入:task: {task} | query: {input}
目标:task: {task} | query: {target}
非对称格式(Asymmetric Formatting):输入和目标使用不同的格式。
输入:task: {task} | query: {input}
目标:title: {title} | text: {target}
参考One Embedder, Any Task: Instruction-Finetuned Text Embeddings,对于每个文本,找到另一个同样label是的样本当成正样本,随机找一个label不是的当作负样本。
实践中,在一个batch中,同一个可能出现overlap,会造成in-batch negatives中的false negative问题。参考poe的回复,即同一个mini-batch中假设有(x1, x1+, x1-) 和 (x2, x2+, x2-),可能出现x1+ 与 x2 或 x2+ 相同或非常相似的情况。那么:
对于x1来说,x1+是正例。
但是如果x1+ 与 x2 相同或非常相似,模型可能会错误地认为x1+应该与x2区分开来,因为x2是另一个样本的输入。
或者如果x1+ 与 x2+ 相同或非常相似,模型可能会混淆应该如何处理这个重叠的样本。
因为在理想情况下,x1+应该只是x1的正例,而不应该被视为任何其他样本的负例。但由于重叠,模型可能错误地将x1+视为x2或其他样本的负例。解决方法,给每个三元组分配唯一的id,让模型专注于在给定x的情况下,区分x+和x-。
有个数据集,每个数据集是,是任务描述,给定一个batch_size=B的batch,同batch里的其他query可以看成SamToNe: Improving Contrastive Loss for Dual Encoder Retrieval Models with Same Tower Negatives中说的same-tower negative(对同模态的效果比较好,例如这边都是query):
同时还参考Matryoshka representation learning的俄罗斯套娃加了一个MRL的loss,让模型适配不同的dim,gecko是768和256的dim
ChatRetriever
思想:原来输入的prompt是x,输出的response是y,添加t个特殊的[emb_i]
token,输入
然后训练的时候,每个生成的只看得到它前面的y,还有x后面的那t个特殊token:

对应的代码
def unified_model_forward(model, model_type: str, inputs: dict, normalize_emb: bool):
inputs.pop("sample_ids", None)
inputs.pop("input_texts", None)
if model_type in ['bge', 'llm_embedder']:
output = model(**inputs)
embs = output.last_hidden_state[:, 0]
elif model_type in set(['qwen', 'qwen_chat', 'qwen_chat_cot', 'qwen_chat_lora',
'qwen_chat_lora_eval', 'qwen_chat_cot_lora', 'qwen_chat_cot_lora_eval',
'qwen15_chat_cot_lora_eval', 'repllama', 'llama',
'repllama-train', 'repllama_v2', 'repllama_v2-train',
'repllama_v2-continue_train', 'repllama_chat',
'repllama_chat-train', 'repllama_chat_cot', 'repllama_chat_cot-train',
'mistrial_cot-train',
'mistrial_chat_cot-train', 'mistrial_cot', 'mistrial_chat_cot',
'qwen15', 'qwen15_chat',
'qwen15_chat_lora', 'qwen15_chat_cot_lora', 'qwen15_chat_cot']):
inputs['output_hidden_states'] = True
output = model(**inputs)
hidden_states = output.hidden_states[-1]
last_token_indices = inputs['attention_mask'].sum(dim=1) - 1
embs = hidden_states[torch.arange(hidden_states.size(0)), last_token_indices]
elif model_type in ['e5_mistrial', 'e5_mistrial-train']:
outputs = model(**inputs)
embs = last_token_pool(outputs.last_hidden_state, inputs['attention_mask'])
elif model_type in ['ance', 'gtr', 'splade']:
embs = model(**inputs)
elif model_type in ['bert']:
output = model(**inputs)
embs = output.pooler_output
else:
raise NotImplementedError("Model type {} is not supported now.".format(model_type))
if normalize_emb:
embs = torch.nn.functional.normalize(embs, p=2, dim=-1)
return embs
Instructor
One Embedder, Any Task: Instruction-Finetuned Text Embeddings
基于google的GTR(Generalizable T5-based dense Retrievers)模型(Large Dual Encoders Are Generalizable Retrievers)加了task instruction,用对比学习loss训练
LLM-Embedder(BGE)
Retrieve Anything To Augment Large Language Models和C-Pack: Packed Resources For General Chinese Embeddings这两个对应的是一样的代码
https://github.com/FlagOpen/FlagEmbedding
RepLLaMA
Fine-Tuning LLaMA for Multi-Stage Text Retrieval
E5_mistral-7b
Improving Text Embeddings with Large Language Models
GRIT
Generative Representational Instruction Tuning
https://github.com/ContextualAI/gritlm
LLM2Vec
LLM2Vec: Large Language Models Are Secretly Powerful Text Encoders
https://github.com/McGill-NLP/llm2vec
由3步组成:
Bi-directional:把causal mask干掉,改成全1mask
引入masked next token predtion任务:类似mlm,mask掉中间的词,拿周围的词预测
对比学习simcse:前两步让模型有了bi-directional的能力,把所有词的emb通过pooling(实验表明mean pooling最有效)得到句子表示,同一句话里mask掉几个词的为正例,不同句子为负例,对比学习
GDR
Generative Dense Retrieval: Memory Can Be a Burden
阿里搜索广告
SyCL
用LLM生成具有多个相关性级别的合成文档,结合列表式损失函数(Wasserstein距离),提升检索器的排名性能。
传统的密集检索器训练依赖对比学习和二元相关性标签(InfoNCE损失),即将文档分为正样本和负样本。这种方法存在两个主要局限:
忽略细微相关性差异:除了明确标注为相关的文档外,所有其他文档被同等视为负样本,无法反映实际的相关性程度。
对噪声敏感:二元标签无法充分利用数据的排名信息,且易受标注错误影响。
具体方法:
多级排名上下文生成:使用 MS MARCO 数据集的查询,提示LLM生成四篇不同相关性级别的合成文档。通过顺序生成确保相关性逐步降低,并使用随机采样(如句子长度和难度)增加多样性。分配标签:{3, 2, 1, 0},分别对应完美相关到无关。
Wasserstein 距离损失:不同于InfoNCE的逐对比较,Wasserstein 距离考虑整个文档集合的相关性分布。通过比较真实标签分布与预测得分分布,优化模型以更准确地排名文档。
RARE
Real-time Ad retrieval via LLM-generative Commercial Intention for Sponsored Search Advertising
gemini embedding
Gemini Embedding: Generalizable Embeddings from Gemini
BGE-code/VL
代码、多模态检索全面登顶SOTA!智源BGE向量模型三连击,并全面开放
UniME
Breaking the Modality Barrier: Universal Embedding Learning with Multimodal LLMs
阶段一:文本判别知识蒸馏

用纯文本数据来增强MLLM中LLM的嵌入能力,用了273k个句子对。
teacher:基于LLM的嵌入模型NV-Embed V2(对比训练中移除了causal mask)离线批量产出文本的emb
student:MLLM中把LLM部分剥离出来,输入prompt
Summary the above sentences in one word: \n”
,最后一个token的emb当成输出蒸馏:teacher和student间算KL散度,LoRA训练
推理时:
单模态输入:通过prompt的设置,决定只走对应的vision/text encoder
图片+文字输入:通过prompt,各自过模型,然后把输出的2个emb进行融合
阶段二:困难负样本增强指令微调

拿多模态的样本对来提升图文之间的对齐,用了662k个pair对:
query: img+prompt
doc: img
样本处理:
干掉false negative:有些负样本和query的相似度太高了,干掉
增加hard negative:除了正例和前面的false negative外,在负样本里找出k个和query最像的,当成hard negative
loss是infoNCE,然后用QLoRA来微调
代码:
import torch
from PIL import Image
from torch.nn import functional as F
from self_evaluate.utils.utils import init_model_and_transform
model_name = "phi35V"
base_model_path="DeepGlint-AI/UniME-Phi3.5-V-4.2B"
# model_name = "llava_16"
# base_model_path="DeepGlint-AI/UniME-LLaVA-1.6-7B"
if model_name == "phi35V":
img_prompt = '<|user|>\n<|image_1|>\nSummary above image in one word: <|end|>\n<|assistant|>\n'
text_prompt = '<|user|>\n<sent>\nSummary above sentence in one word: <|end|>\n<|assistant|>\n'
elif model_name == "llava_16":
img_prompt = "[INST] <image>\nSummary above image in one word: [/INST]"
text_prompt = "[INST] <sent>\nSummary above sentence in one word: [/INST]"
text = "A man is crossing the street with a red car parked nearby."
image_path = "figures/demo.png"
input_texts = text_prompt.replace('<sent>', text)
input_image_prompt = img_prompt
input_image = [Image.open(image_path)]
model, transform = init_model_and_transform(model_name, base_model_path)
inputs_text = transform(text=input_texts,
images=None,
return_tensors="pt",
padding=True)
for key in inputs_text: inputs_text[key] = inputs_text[key].to("cuda")
inputs_image = transform(text=input_image_prompt,
images=input_image,
return_tensors="pt",
padding=True).to("cuda")
with torch.no_grad():
emb_text = model(**inputs_text, output_hidden_states=True, return_dict=True).hidden_states[-1][:, -1, :]
emb_image = model(**inputs_image, output_hidden_states=True, return_dict=True).hidden_states[-1][:, -1, :]
emb_text = F.normalize(emb_text, dim=-1)
emb_image = F.normalize(emb_image, dim=-1)
Score = emb_image @ emb_text.T
print("Score: ", Score) # Score: 0.59
其中:
def init_model_and_transform(model_name, base_model_path):
if model_name == 'phi35V':
transform = AutoProcessor.from_pretrained("microsoft/Phi-3.5-vision-instruct",
trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(base_model_path,
device_map="cuda", trust_remote_code=True,
torch_dtype=torch.float16,
_attn_implementation='flash_attention_2')
elif model_name == "llava_16":
transform = LlavaNextProcessor.from_pretrained("llava-hf/llava-v1.6-mistral-7b-hf")
model = LlavaNextForConditionalGeneration.\
from_pretrained(base_model_path, device_map="cuda",
torch_dtype=torch.float16, low_cpu_mem_usage=True)
transform.tokenizer.padding_side = "left"
transform.tokenizer.padding = True
return model, transform
百度召回
Qwen3-emb
Qwen3 Embedding: Advancing Text Embedding and Reranking Through Foundation Models
架构

emb模型:
query:输入instruction+query,拿eos对应的emb作为输出
doc:不用instrunction,直接输入doc,拿eos对应的emb作为输出
rerank模型:输入instruction+query和doc,拿如下prompt的输出经过lm head输出yes/no的概率(是否匹配)
<|im_start|>system
Judge whether the Document meets the requirements
based on the Query and the Instruct provided.
Note that the answer can only be "yes" or "no".<|im_end|>
<|im_start|>user
<Instruct>: {Instruction}
<Query>: {Query}
<Document>: {Document}<|im_end|>
<|im_start|>assistant
<think>\n\n</think>\n\n
合成数据
数据:多样性,包括多语言、跨语言、多领域、多任务、长/短文本、代码检索
数据来源:
人工标注数据:搜索(MS MARCO)、qa、MNLI、SNLI等,大概10M
公开领域的弱监督数据:维基百科、redit、arxiv等,大概10亿,放弃了
大模型合成数据:用Qwen3为每个doc生成相关问题,理论上可以构建无限数据

根据文档,从一个比较大的角色库(比如大学生、小学生、公务员、商人等)里检索出若干个角色,用llm判断哪些角色适合这个文档,以及他们会问什么类型的问题(keyword/summary/逻辑推理),难度(大学/小学)、长度、语言,生成一个config
拿角色+文档+config再给llm,生成真实的用户问题
再用一个预训练好的emb模型先进行检索,过滤掉那些比较低质的数据(例如相似度太低或者根本检索不到相关文档)
训练

多阶段训练
stage1:Large-Scale Synthetic Data-Driven Weak Supervision Training:
stage2:High-Quality Synthetic Data Utilization in Supervised Fine Tuning: 从合成数据中筛选出高质量数据,以及人工标注的高质量数据
stage3:Model Merging: 对stage2中的多个ckpt进行merge
rerank模型里stage1没啥用,直接用stage2和3,loss是sft的loss,即对yes/no去算交叉熵
embedding模型是3阶段,用一个改进的对比学习来训:
负例:个hard neg 、batch内的其他query 、batch内的除了正负例的其他doc
计算负样本与query的相似度s1,正样本与query的相似度s2,如果s1比s2大超过一个阈值那就是false negative,即下面的
其中,
训练时的策略:
动态batchsize:训练数据长度不同,能接收的最大batchsize不同,所以对于不同长度用的bs不一样
gradient checkpointing:将大的bs切成小的sub-bs,先计算每个sub-bs的emb,因为gradient checkpointing不保存梯度,所以这个时候可以merge,merge完后再计算梯度
训练的时候带了MRL loss
模型融合原理:多个ckpt,可能分别擅长不同的task,通过对模型参数的线性/球面插值,可以merge出一个对各任务都不错的模型。
参考Improving general text embedding model: Tackling task conflict and data imbalance through model merging的slerp,基于球面插值的融合方法,给定2个ckpt,分别算一下和训练前ckpt的差值,称为任务向量。然后拿这2个任务向量和原来ckpt的点构成的平面,使得少量训练数据和一个loss,算出合适的夹角和模长得到新向量,再去和其他ckpt重复这个步骤进行merge。
训练的时候用的lora,emb和rerank的hard negative设计不一样
百度AI搜索
Towards AI Search Paradigm ..63页
该采用由多个LLM驱动的智能体构成的模块化体系(Master、Planner、Executor和Writer),能够动态适应从简单事实查询到复杂多阶段推理任务的各类信息需求。这些智能体通过动态协同的工作流程,评估查询复杂性,在Master的判断和指导下对应不同任务的特性的智能体动态组合,并针对复杂任务将问题分解为可执行的任务,并协调使用各种工具进行任务执行与内容合成。
传统推荐模型
Meta的MTMH

同时考虑target item与trigger item的相关性和个性化。
多目标loss包括如下两部分:
互动loss:正样本是trigger和target的共现,负样本是这个用户没交互过的item,用infoNCE loss
内容相似loss:label是预训练的content encoder的输出向量的内积,和MTMH输出的item内积算一个kl距离
输入item特征,经过MTMH后有2个head:
head1:只学互动loss,保证模型对高热的召回能力
head2:学多目标loss,即同时学互动和内容相似loss

content encoder的训练:对比学习
左边是text encoder(XLM-R-Large-550M)+vision encoder(VIT-H14-632M),只训练上面的mlp,输出是128dim
右边是text encoder,输入concept(感觉是类似类目、tag之类的东西),同样经过mlp输出128dim
serving:2个head分别建索引,在线同一个trigger分别从这2个索引召回,再merge
最后更新于
这有帮助吗?