基于AWS Trainium与vLLM的冷启动推荐优化技术

本文探讨利用vLLM在AWS Trainium芯片上构建冷启动推荐系统,通过大语言模型生成用户兴趣画像,结合T5编码器与FAISS向量检索技术,实现零样本推理与高效候选集检索,并分析模型规模与编码器配置对推荐效果的影响。

基于AWS Trainium与vLLM的冷启动推荐优化技术

推荐系统中的冷启动问题不仅涉及新用户或新物品场景,更核心的是系统初始阶段完全缺乏个性化信号。当新用户首次访问或新内容上线时,由于缺乏行为历史数据,推荐引擎无法识别用户兴趣,导致所有用户被归入宽泛的通用类别。这不仅会降低点击率和转化率,还可能在使用户流失后系统仍未能学习到其偏好。

传统解决方案(如协同过滤、矩阵分解或热门列表)缺乏弥补信号间隙的细粒度能力,其通用化推荐很快会显得过时。设想另一种方案:从第一天起就能生成详细的兴趣画像。通过利用大语言模型(LLM)进行零样本推理,可以合成丰富且上下文感知的用户和物品嵌入向量,无需等待数周的交互数据——从而将冷启动转化为热欢迎。

本文演示如何利用vLLM进行可扩展推理,并使用某中心的深度学习容器(DLC)简化模型打包与部署流程。我们将通过结构化提示生成兴趣扩展,将其编码为嵌入向量,使用FAISS检索候选集,并应用验证机制确保结果可靠性。同时将冷启动挑战构建为科学实验:对比LLM与编码器组合效果,快速迭代推荐指标,并展示每种配置的明确投资回报率。

解决方案架构

冷启动解决方案基于某中心的EC2 Trainium芯片构建。为简化模型部署,我们采用集成了某中心Neuron SDK的DLC容器,该SDK安装了经Neuron优化的PyTorch模块,并预装了最新的Trainium驱动和运行时环境。

图:基于AWS Trainium与vLLM & NxD的冷启动推荐流水线

通过Neuron的分布式库NeuronX Distributed(NxD)实现大模型在多Trainium芯片上的分片处理,该库与vLLM无缝集成。NxD通过最小代码变更管理多实例间的模型分区,支持甚至70B参数LLM的并行推理。这种结合——Trainium芯片、Neuron工具链和vLLM——为机器学习工程师提供了灵活、经济高效且生产就绪的解决方案,支持实验不同LLM与编码器配置,并在不修改核心模型代码的情况下快速迭代推荐质量指标。

后续章节将在Jupyter Notebook中编排实验流程,提供可复现的端到端工作流:从加载数据、设计结构化提示,到生成嵌入向量和FAISS候选检索,并包含可视化推荐性能的交互式图表。在生产深入探讨部分,我们将逐步讲解参考实现:将Neuron优化的LLM和编码器打包为DLC镜像,部署在支持自动扩缩容的某中心弹性Kubernetes服务(EKS)上,使推理层能自动适应需求变化的同时优化成本与性能。

利用LLM扩展用户兴趣画像

本文使用Kaggle上的某中心图书评论数据集(mohamedbakhet/amazon-books-reviews),该数据集包含数万本书籍的真实用户评论和元数据。通过这个丰富集合,我们可以模拟冷启动场景——新用户仅有一条评论或点赞——并评估基于Meta Llama 8B和70B蒸馏模型的兴趣扩展生成丰富用户画像的效果。

我们使用LLM从最小初始数据中丰富新用户画像。例如,若用户仅评论过一本科幻小说,LLM会推断相关子主题(如银河帝国、赛博朋克反乌托邦或太空探索)作为用户可能喜欢的扩展兴趣。我们采用结构化提示将用户现有活动嵌入简明指令中以确保一致性和相关性,示例如下:

1
2
3
4
5
6
prompt = (
    f"The user has shown interest in: {user_review_category}.\n"
    "Suggest 3–5 related book topics they might enjoy.\n"
    "Respond with a JSON list of topic keywords."
)
expanded_topics = llm.generate([prompt])[0].text

通过约束LLM输出格式(要求返回JSON格式的主题关键词数组),我们避免自由形式的发散响应,获得可预测的兴趣扩展列表。现代生成模型(如Meta的Llama)具有广博的领域知识和类人推理能力,能关联相关概念,通过单条评论推断深层用户偏好,成为强大的冷启动助推器。这些合成兴趣成为推荐流水线的新信号,即使用户历史极少也能从某中心评论集合中检索和排序书籍。

开发者可尝试从十亿到七百亿参数的Llama变体,以确定哪种模型产生区分度最高且最相关的扩展。这些发现将指导生产环境模型选择,决定EC2 Trainium和Inferentia实例的规模配置,为实时用户A/B测试奠定基础以验证实际场景性能。

编码用户兴趣与检索相关内容

获得扩展兴趣后,下一步是将这些兴趣和书籍目录转化为可比较的向量。我们探索三种规模的Google T5编码器(base、large和XL),研究嵌入维度如何影响匹配质量。具体步骤如下:

  1. 加载各尺寸编码器
  2. 将图书摘要编码为单个NumPy矩阵并归一化
  3. 基于归一化向量构建FAISS索引以实现快速最近邻搜索
  4. 以相同方式编码扩展兴趣文本,查询FAISS检索前k个最相似书籍
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from transformers import T5Tokenizer, T5EncoderModel
import faiss
import numpy as np

content_texts = df["review/summary"].tolist()
encoder_sizes = ["t5-base", "t5-large", "t5-xl"]
top_k = 5

for size in encoder_sizes:
    tokenizer = T5Tokenizer.from_pretrained(size)
    model = T5EncoderModel.from_pretrained(size)
    
    inputs = tokenizer(content_texts, return_tensors="pt", truncation=True, padding=True)
    outputs = model(**inputs)
    content_embs = outputs.last_hidden_state.mean(dim=1).detach().cpu().numpy().astype("float32")
    faiss.normalize_L2(content_embs)
    
    index = faiss.IndexFlatIP(content_embs.shape[1])
    index.add(content_embs)
    
    interest = "space opera with political intrigue"
    enc = tokenizer([interest], return_tensors="pt", truncation=True, padding=True)
    interest_emb = model(**enc).last_hidden_state.mean(dim=1).detach().cpu().numpy().astype("float32")
    faiss.normalize_L2(interest_emb)
    
    distances, indices = index.search(interest_emb, top_k)
    recommendations = [content_texts[i] for i in indices[0]]
    
    print(f"\nTop {top_k} recommendations using {size}:")
    for title in recommendations:
        print(" -", title)

通过比较各编码器规模对FAISS平均距离(即兴趣与内容间的差异度)和实际推荐标题的影响,可评估匹配质量。替换不同编码器家族(如SentenceTransformers)仅需更换模型和分词器导入即可实现。

评估与提升推荐质量

为每个LLM-编码器对生成FAISS索引并计算每个扩展兴趣查询与其前10个邻居的平均距离后,可精确了解各模型嵌入向量的聚类紧密度。下图显示了各组合的平均距离:1B和3B模型几乎坍缩为零,而8B和70B模型(尤其是较大编码器)产生逐渐增大的距离,表明其生成更丰富、区分度更高的推荐信号。

图:不同模型与编码器的平均FAISS距离

图表显示1B和3B模型的平均FAISS距离为零,意味着其扩展兴趣嵌入基本一致且无区分度。相比之下,8B模型与t5-base组合产生约0.5的距离,随t5-large和t5-xl编码器进一步上升,表明较大编码器能捕获更多模型细微差异。70B模型仅在与XL编码器组合时带来小幅提升,其额外成本带来的收益有限。

实际应用中,Llama 8B LLM与base或large T5编码器组合可在嵌入空间产生清晰分离,且无需承担70B模型更高的推理时间和资源消耗。

比较模型与编码器对嵌入分布的影响

为观察LLM规模与编码器等级如何塑造嵌入空间,可测量每个LLM-编码器对中代表性扩展兴趣向量与其前10个邻居的平均FAISS距离。下图并排展示这些平均值,可立即发现1B和3B模型坍缩至零,8B模型跃升至0.5左右并随编码器增大而上升,70B模型仅在XL尺度下带来微小扩展。这有助于选择最小组合的同时保持冷启动推荐所需的嵌入多样性。

图:不同LLM与编码器尺寸的FAISS距离

评估Llama变体与编码器间的推荐重叠以平衡一致性与新颖性

在后续分析中,构建基础的recommend_books辅助函数:针对不同LLM规模和编码器选择,加载对应的扩展兴趣DataFrame,读取其FAISS索引,重建第一个嵌入作为替代查询,并返回前k个书籍标题。使用该工具,首先测量单LLM下每对编码器的推荐一致性(比较base与large、base与XL、large与XL),随后分别测量固定编码器下每对LLM规模的一致性。最后聚焦8B模型(如下图),绘制其编码器重叠热力图,显示base与large共享前5推荐中40%的项目,而XL编码器差异更大——说明更换编码器会改变推荐中一致性与新颖性的平衡。

图:8B模型的编码器重叠热力图

对于8B模型,热力图显示t5_base与t5_large共享前5推荐的40%,t5_base与t5_xl重叠40%,而t5_large与t5_xl仅重叠20%,表明XL编码器相比其他组合引入了最多新标题。

调整tensor_parallel_size实现最优成本性能

为平衡推理速度与资源成本,我们测量了在trn1.32xlarge实例上使用Llama 3.1 8B模型扩展用户兴趣时,增加Neuron张量并行度对延迟的影响。在tensor_parallel_size值为2、8、16和32时运行相同的零样本扩展工作负载。如图表所示,P50延迟从TP=2时的2480毫秒下降74%至TP=16时的650毫秒,随后在TP=32时微降至532毫秒(额外下降18%)。成本性能图表显示,超过TP=16后,并行度翻倍大致使成本翻倍,但仅带来17%的延迟提升。

图:延迟与张量并行规模的关系

实际应用中,设置tensor_parallel_size=16可提供最佳权衡:在获取模型分片带来的大部分加速的同时,避免最大并行度下急剧递减的收益和更高的核心小时成本,如下图所示。

图:成本性能与张量并行规模的关系

上图可视化Llama 8B测试的成本性能比,强调TP=16在收益平台期前提供最平衡的效率。

后续步骤

确定模型、编码器及最优配置(如序列长度和批大小)后,下一步是部署模型并定义生产工作流,用于生成编码后的扩展兴趣以实现与更多内容的匹配。

结论

本文展示了如何通过某中心Trainium、Neuron SDK和可扩展LLM推理解决冷启动挑战,通过丰富稀疏用户画像实现从第一天起提供更好推荐。

重要的是,实验表明更大模型和编码器并不总是意味着更好结果。虽然它们能产生更丰富信号,但收益往往无法证明额外成本的合理性。实践发现8B LLM与T5-large编码器组合能在性能和效率间达到最佳平衡。

该方法帮助团队识别最优模型-编码器对,而非假定越大越好,从而在成本效益优化的基础设施上交付高质量推荐。


本文基于某中心技术博客内容编译,聚焦冷启动推荐系统中的LLM应用与优化实践。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计