LLM在推荐系统中的应用:从冷启动到个性化的工程实践
引言传统推荐系统在冷启动问题上栽了多少跟头新用户没有历史行为新商品没有评分数据协同过滤和矩阵分解统统束手无策。LLM的出现为推荐系统带来了新的可能强大的语义理解能力、丰富的世界知识储备以及对用户自然语言偏好表达的准确解析。本文将深入探讨LLM增强推荐系统的工程架构从冷启动到实时个性化的完整实践方案。—## 一、LLM推荐系统的技术路线### 1.1 三种主要范式LLM推荐系统技术路线│├── 1. LLM-as-Recommender纯LLM推荐│ 直接用LLM生成推荐列表│ 优点零冷启动语义理解强│ 缺点无法实时不了解实时库存│├── 2. LLM-Enhanced RetrievalLLM增强检索│ LLM处理query传统算法做检索│ 优点可扩展结合实时数据│ 缺点两个系统需要协调│└── 3. LLM Embedding Hybrid混合架构 LLM生成语义向量向量库做ANN检索 优点语义准确 速度快 缺点向量更新延迟### 1.2 冷启动场景的对比| 场景 | 传统方案 | LLM方案 ||------|---------|---------|| 新用户 | 基于人口统计学推荐 | 自然语言询问偏好 || 新商品 | 无法推荐无行为数据 | 基于商品描述语义推荐 || 小众品类 | 稀疏数据效果差 | 迁移世界知识 || 跨域推荐 | 数据隔离难以迁移 | 语义空间统一 |—## 二、冷启动解决方案### 2.1 对话式偏好采集pythonfrom anthropic import Anthropicfrom typing import List, Dict, Optionalimport jsonclient Anthropic()class ConversationalPreferenceCollector: 通过对话采集用户偏好解决冷启动 SYSTEM_PROMPT 你是一个专业的推荐系统用户偏好分析师。通过自然对话了解用户偏好并以结构化JSON格式输出分析结果。对话原则1. 每次只问一个问题2. 问题要具体、有趣不要像问卷调查3. 从用户回答中推断隐性偏好4. 收集3-5轮信息后输出完整画像当你认为信息足够时输出json{ “profile_complete”: true, “preferences”: { “explicit”: […], // 用户明确表达的偏好 “inferred”: […], // 从回答中推断的偏好 “exclusions”: […] // 明确不喜欢的 }, “embedding_tags”: […] // 用于向量检索的标签} def __init__(self, domain: str 电商): self.domain domain self.conversation_history [] self.collected_profile None def start_conversation(self) - str: 开始偏好采集对话 initial_prompt f请帮我了解用户在{self.domain}领域的偏好开始采集对话。 response client.messages.create( modelclaude-3-5-sonnet-20241022, max_tokens500, systemself.SYSTEM_PROMPT, messages[{role: user, content: initial_prompt}] ) assistant_message response.content[0].text self.conversation_history.append({ role: assistant, content: assistant_message }) return assistant_message def process_response(self, user_input: str) - dict: 处理用户回答 Returns: { question: 下一个问题如果采集未完成, profile: 用户画像如果采集完成, done: bool } self.conversation_history.append({ role: user, content: user_input }) response client.messages.create( modelclaude-3-5-sonnet-20241022, max_tokens1000, systemself.SYSTEM_PROMPT, messagesself.conversation_history ) assistant_message response.content[0].text self.conversation_history.append({ role: assistant, content: assistant_message }) # 检查是否完成了画像采集 if profile_complete in assistant_message: try: # 提取JSON import re json_match re.search(r\{.*profile_complete.*\}, assistant_message, re.DOTALL) if json_match: profile json.loads(json_match.group()) self.collected_profile profile return {question: None, profile: profile, done: True} except: pass return { question: assistant_message, profile: None, done: False }# 使用示例collector ConversationalPreferenceCollector(domain书籍)question collector.start_conversation()print(fAI: {question})# 模拟用户对话responses [ 我喜欢科技和商业类书籍特别是关于AI和创业的, 最近在读《人工智能一种现代方法》, 不太喜欢纯理论的书更喜欢有实际案例的]for user_response in responses: print(f\n用户: {user_response}) result collector.process_response(user_response) if result[done]: print(\n✅ 用户画像采集完成:) print(json.dumps(result[profile], ensure_asciiFalse, indent2)) break else: print(fAI: {result[question]})### 2.2 商品语义向量化解决新商品冷启动问题pythonfrom openai import OpenAIimport numpy as npfrom dataclasses import dataclassopenai_client OpenAI()dataclassclass ProductEmbedding: product_id: str title: str embedding: np.ndarray metadata: dictclass ProductEmbeddingService: 商品语义向量化服务 EMBEDDING_MODEL text-embedding-3-large EMBEDDING_DIM 3072 def create_product_text(self, product: dict) - str: 将商品信息转化为富语义文本 parts [] if product.get(title): parts.append(f商品名称{product[title]}) if product.get(category): parts.append(f类别{product[category]}) if product.get(brand): parts.append(f品牌{product[brand]}) if product.get(description): parts.append(f描述{product[description][:500]}) if product.get(tags): parts.append(f标签{, .join(product[tags])}) if product.get(specs): specs_str , .join(f{k}:{v} for k, v in product[specs].items()) parts.append(f规格{specs_str}) # 使用LLM生成增强描述提升语义丰富度 if len(parts) 2: enhanced self._enhance_description(product) if enhanced: parts.append(f特征总结{enhanced}) return \n.join(parts) def _enhance_description(self, product: dict) - str: 使用LLM增强商品描述 response client.messages.create( modelclaude-3-5-haiku-20241022, max_tokens200, messages[{ role: user, content: f请用50字描述这个商品的核心特征和适合人群商品{product.get(title, )}类别{product.get(category, )}描述{product.get(description, )[:200]} }] ) return response.content[0].text def embed_product(self, product: dict) - ProductEmbedding: 生成商品向量 text self.create_product_text(product) response openai_client.embeddings.create( modelself.EMBEDDING_MODEL, inputtext, encoding_formatfloat ) embedding np.array(response.data[0].embedding) return ProductEmbedding( product_idproduct[id], titleproduct.get(title, ), embeddingembedding, metadata{ category: product.get(category), price: product.get(price), tags: product.get(tags, []) } ) def batch_embed( self, products: List[dict], batch_size: int 20 ) - List[ProductEmbedding]: 批量向量化控制API调用频率 results [] for i in range(0, len(products), batch_size): batch products[i:ibatch_size] # 批量生成文本 texts [self.create_product_text(p) for p in batch] # 批量请求embedding API response openai_client.embeddings.create( modelself.EMBEDDING_MODEL, inputtexts, encoding_formatfloat ) for j, (product, emb_data) in enumerate( zip(batch, response.data) ): results.append(ProductEmbedding( product_idproduct[id], titleproduct.get(title, ), embeddingnp.array(emb_data.embedding), metadata{category: product.get(category)} )) print(f已处理 {min(ibatch_size, len(products))}/{len(products)} 个商品) return results—## 三、实时个性化推荐### 3.1 用户意图解析pythonclass UserIntentParser: 解析用户实时意图 def parse_query( self, query: str, user_context: dict, history: List[dict] ) - dict: 解析用户查询意图 Returns: { intent_type: search|browse|compare|buy, expanded_query: 语义扩展后的查询, filters: {price_max: ..., category: ...}, preference_signals: [...] } history_summary if history: recent history[-5:] history_summary f\n最近浏览{, .join(h.get(title, ) for h in recent)} response client.messages.create( modelclaude-3-5-haiku-20241022, max_tokens500, messages[{ role: user, content: f分析用户的推荐需求返回JSON格式用户查询{query}用户等级{user_context.get(tier, standard)}{history_summary}返回{{ intent_type: search|browse|compare|buy, expanded_query: 扩展语义后的查询, filters: {{}}, preference_signals: [], suggested_categories: []}} }] ) try: return json.loads(response.content[0].text) except: return { intent_type: search, expanded_query: query, filters: {}, preference_signals: [] }### 3.2 推荐理由生成pythonclass RecommendationExplainer: 生成个性化推荐理由 def generate_explanation( self, user_profile: dict, product: dict, reason_type: str preference ) - str: 生成推荐理由 response client.messages.create( modelclaude-3-5-haiku-20241022, max_tokens100, messages[{ role: user, content: f为以下商品生成个性化推荐理由30字以内自然口语化商品{product.get(title)}用户偏好{, .join(user_profile.get(preferences, {}).get(explicit, [])[:3])}推荐原因类型{reason_type}示例格式因为你喜欢[偏好]这款[产品特点]很适合你 }] ) return response.content[0].text.strip()—## 四、生产架构设计### 4.1 整体系统架构pythonclass LLMRecommendationSystem: 完整的LLM推荐系统 def __init__(self, vector_store, cache): self.embedding_service ProductEmbeddingService() self.intent_parser UserIntentParser() self.explainer RecommendationExplainer() self.vector_store vector_store self.cache cache async def recommend( self, user_id: str, query: str, context: dict, top_k: int 10 ) - List[dict]: 主推荐流程 # 1. 加载用户画像 user_profile await self._load_user_profile(user_id) browse_history await self._load_history(user_id) # 2. 解析意图 intent self.intent_parser.parse_query( query, context, browse_history ) # 3. 生成查询向量 query_embedding self._embed_query( intent[expanded_query] ) # 4. 向量检索 candidates self.vector_store.search( query_embedding, top_ktop_k * 3, filtersintent.get(filters) ) # 5. 重排序基于用户偏好 reranked self._rerank_by_preference( candidates, user_profile )[:top_k] # 6. 生成推荐理由 results [] for product in reranked: explanation self.explainer.generate_explanation( user_profile, product ) results.append({ **product, recommendation_reason: explanation, score: product.get(score, 0) }) return results def _rerank_by_preference( self, candidates: List[dict], user_profile: dict ) - List[dict]: 基于用户偏好重排序 preferences set( user_profile.get(preferences, {}).get(explicit, []) user_profile.get(preferences, {}).get(inferred, []) ) exclusions set( user_profile.get(preferences, {}).get(exclusions, []) ) def score(product: dict) - float: base_score product.get(score, 0.5) tags set(product.get(metadata, {}).get(tags, [])) pref_match len(tags preferences) excl_match len(tags exclusions) return base_score pref_match * 0.1 - excl_match * 0.3 return sorted(candidates, keyscore, reverseTrue)—## 五、性能优化策略### 5.1 关键延迟控制pythonimport asynciofrom functools import lru_cacheclass OptimizedRecommender: 高性能推荐器 # LLM调用缓存相同意图缓存1小时 lru_cache(maxsize1000) def _cached_intent_parse(self, query_hash: str) - dict: pass async def fast_recommend( self, user_id: str, query: str, timeout: float 2.0 ) - List[dict]: 2秒内完成推荐 # 并发执行不相互依赖的任务 user_profile_task asyncio.create_task( self._load_user_profile(user_id) ) intent_task asyncio.create_task( self._parse_intent_async(query) ) # 等待两个任务完成 try: user_profile, intent await asyncio.wait_for( asyncio.gather(user_profile_task, intent_task), timeouttimeout * 0.5 # 各阶段只用一半时间 ) except asyncio.TimeoutError: # 降级使用缓存的向量直接检索 user_profile self._get_default_profile() intent {expanded_query: query, filters: {}} # 向量检索快速 embedding self._embed_query(intent[expanded_query]) candidates self.vector_store.search(embedding, top_k20) # 快速重排无LLM调用 reranked self._fast_rerank(candidates, user_profile) return reranked[:10]—## 六、总结LLM为推荐系统带来的核心价值1.零冷启动通过对话采集偏好新用户立即获得个性化推荐2.语义理解超越关键词匹配理解用户真实意图3.新商品推荐基于语义向量新商品立即可被推荐4.推荐可解释性自动生成自然语言推荐理由提升用户信任工程实践要点- 将LLM调用集中在低频但高价值的环节偏好采集、理由生成-实时路径使用向量检索不依赖LLM保证低延迟- 用户画像做持久化缓存避免重复采集- 设计降级策略LLM不可用时保持基础推荐能力LLM推荐系统不是要替代传统协同过滤而是在冷启动、语义理解、可解释性三个维度上形成有效补充共同构建更智能的推荐体系。