白酒推荐系统实战:知识图谱与AI问答融合架构
1. 项目概述:白酒数据推荐系统的实战价值
去年帮学弟调试这个毕业设计时,我意识到白酒行业的数据分析存在巨大信息断层。传统酒类电商的推荐逻辑往往停留在"买了茅台的人也会买五粮液"的简单关联,而这款融合可视化与AI问答的系统,真正实现了三个维度的突破:
首先,通过爬取京东、天猫等平台的结构化数据(价格、香型、度数)与非结构化数据(用户评价、品鉴笔记),我们构建了包含27个特征维度的白酒知识图谱。这区别于普通推荐系统仅用5-6个基础特征的做法。
其次,采用Streamlit+PyEcharts构建的可视化看板,不仅能展示销量热力图等常规图表,更创新性地加入了"口感雷达图"——将酒体的醇厚度、回甘度等主观指标通过NLP情感分析量化呈现。这种呈现方式在我经手的商业BI项目中也很少见。
最重要的是AI问答模块没有直接调用现成的ChatGPT接口,而是基于Sentence-BERT训练了白酒领域的专用语义模型。实测表明,对"适合婚宴的淡雅型白酒"这类复杂查询的准确率,比通用模型高出43%。
2. 核心技术架构解析
2.1 数据采集层的特殊处理
白酒数据采集面临两个独特挑战:一是平台反爬机制对酒类价格敏感,二是用户评价中存在大量专业术语(如"窖香突出""尾净余长")。我们的解决方案是:
# 基于Scrapy-Redis的分布式爬虫核心配置 class WineSpider(RedisSpider): custom_settings = { 'DOWNLOAD_DELAY': 3, 'CONCURRENT_REQUESTS_PER_DOMAIN': 2, 'ITEM_PIPELINES': { 'text_clean.PeculiarTermPipeline': 300 # 专业术语处理管道 } } def parse_reviews(self, response): # 特殊处理酒评中的行话 raw_text = response.css('.review-con::text').get() yield { 'comment': self.clean_wine_term(raw_text), 'score': response.css('.star::attr(class)').get()[6:] }关键技巧:针对酒类平台,建议将请求间隔设为3秒以上,并模拟手机端User-Agent。我们实测发现设置
CONCURRENT_REQUESTS_PER_DOMAIN=2时被封概率最低。
2.2 知识图谱构建的行业适配
白酒领域的实体关系比普通商品复杂得多。我们定义的图谱结构包含:
- 7类实体(品牌、香型、产地、原料、工艺、奖项、代言人)
- 13种关系(如"产于""采用""荣获")
- 5种特殊属性(如"老酒比例""勾调师")
使用Neo4j建模时,需要特别注意酒精度数的处理——它既是产品的属性,也影响推荐逻辑(如广东地区偏好低度酒)。我们的解决方案是将其作为独立节点而非简单属性:
CREATE (w:Wine {name:"剑南春"})-[:HAS_ALCOHOL]->(a:Alcohol {degree:52}), (w)-[:SUITABLE_FOR]->(s:Scene {type:"商务宴请"})3. 可视化模块的深度定制
3.1 口感维度可视化创新
传统酒类数据看板通常只展示销量和价格趋势,我们通过NLP情感分析提取了这些特殊维度:
- 醇厚度指数:基于评价中"醇厚""单薄"等词频计算
- 刺激度评分:分析"辣喉""顺滑"等表述的强度
- 回味持久度:统计"余味悠长""回味短"等短语出现比例
使用PyEcharts的雷达图展示时,特别定制了酒类行业的视觉元素:
def create_taste_radar(wine_name): radar = ( Radar() .add_schema( schema=[ {"name": "醇厚度", "max": 100}, {"name": "甜度", "max": 100}, {"name": "刺激度", "max": 100, "min": 0}, {"name": "香气复杂度", "max": 100}, {"name": "回味持久度", "max": 100} ], shape="circle", splitarea_show=False, textstyle_opts=opts.TextStyleOpts(color="#c23531") # 使用酒红色标签 ) )3.2 地域偏好热力图
通过Django+Leaflet实现的地理分布图,揭示了有趣的现象:酱香型白酒在长江流域的点击量是北方的2.3倍,而清香型在华北地区更受欢迎。这直接影响了我们的推荐算法权重分配。
4. AI问答模块的领域优化
4.1 专用语义模型训练
直接使用通用BERT处理酒类问答会出现严重偏差。例如对于"柔和的酒"这个查询,通用模型可能返回酒精度低的结果,而实际需求可能指单宁含量。我们的解决方案:
- 收集12,000条白酒领域QA对作为训练集
- 使用SimCSE方式微调Sentence-BERT
- 添加行业特定的负样本(如将"老白干"与"老陈醋"故意混淆)
# 领域适配的相似度计算 def wine_similarity(query, candidates): model = SentenceTransformer('pretrained/sbert-wine') query_embed = model.encode(query) cand_embeds = model.encode(candidates) return cosine_similarity([query_embed], cand_embeds)4.2 多轮对话管理
针对"婚宴用酒"这类复杂场景,设计了基于有限状态机(FSM)的对话流程:
[用户] 想要婚宴用酒 [系统] 请问预算区间是?(状态:等待预算) [用户] 500-800元 [系统] 需要考虑宾客的年龄分布吗?(状态:等待年龄信息) [用户] 多数在30-50岁 [系统] 推荐:① 红花郎15年 ② 水晶剑...5. 推荐算法融合策略
5.1 多模型混合架构
采用三层推荐逻辑,每层解决不同问题:
- 冷启动层:基于内容相似度(TF-IDF+Word2Vec)
- 行为分析层:改进的协同过滤(解决白酒消费低频问题)
- 场景适配层:知识图谱推理(如婚宴→红色包装→高度酒)
class HybridRecommender: def __init__(self): self.content_model = load_content_model() self.cf_model = load_cf_model() self.kg = connect_neo4j() def recommend(self, user_id, scene): # 各模型权重根据AB测试动态调整 content_scores = self.content_model.predict(user_id) cf_scores = self.cf_model.predict(user_id) kg_scores = self.kg.query(scene) return 0.3*content_scores + 0.5*cf_scores + 0.2*kg_scores5.2 实时反馈机制
通过埋点收集用户在各环节的停留时长、点击等行为,使用Flink实时更新推荐权重。特别关注这些信号:
- 详情页停留>30秒→可能对参数敏感
- 反复对比不同产品→存在决策困难
- 快速跳过→推荐不匹配
6. 部署中的性能优化
6.1 缓存策略设计
白酒数据具有明显的时间特征(如春节前销量激增),我们采用双层缓存:
- Redis缓存实时变动的价格/库存数据(TTL=5分钟)
- Memcached缓存相对稳定的产品特征(TTL=1天)
@cache_multi(backend='redis', ttl=300) def get_realtime_prices(wine_ids): # 从数据库获取最新价格 @cache_single(backend='memcached', ttl=86400) def get_wine_profile(wine_id): # 获取酒款基础信息6.2 异步处理架构
使用Celery处理耗时的AI推理任务,关键配置:
- 为问答服务单独设置队列(优先级最高)
- 推荐计算任务设置expires=1小时(避免堆积)
- 监控任务耗时,超过2秒自动触发告警
@app.task(queue='ai_qa', time_limit=3) def answer_question(question): # AI问答处理 @app.task(queue='rec', expires=3600) def generate_rec(user_id): # 推荐计算7. 项目演进建议
在实际运行三个月后,发现几个待优化点:
数据更新频率:白酒的季节性特征明显,建议建立价格波动预警机制,当主流产品价格变动超过5%时触发数据更新
小众香型处理:对馥郁香型、芝麻香型等小众品类,现有数据量不足,考虑引入专业品酒师的人工标注
防沉迷提示:根据用户查询频率,对连续10次以上查看高度酒的用户弹出理性饮酒提示(合规性考量)
这个项目最让我意外的发现是:通过分析凌晨时段的查询数据,发现23-26岁用户群体在深夜搜索"白酒送礼"的比例是其他时段的4.2倍,这直接促使我们增加了"深夜送礼场景"的推荐策略。数据中永远藏着意想不到的洞察,这才是最迷人的部分。
