1. 项目背景与核心价值
在当今信息爆炸的时代,美食推荐系统已经从简单的菜谱数据库进化为能够理解用户个性化需求的智能助手。这个毕业设计项目结合了Django框架的稳健性和LLM大模型的智能分析能力,打造了一个能够深度理解用户口味偏好、饮食习惯和营养需求的美食推荐引擎。
为什么这个组合特别有前景?Django作为Python生态中最成熟的Web框架之一,提供了完整的MVT架构和丰富的插件生态,特别适合快速构建数据密集型应用。而LLM大模型(如GPT、LLaMA等)在自然语言处理、上下文理解和个性化推荐方面展现出了惊人的能力。将两者结合,我们就能突破传统推荐系统只能基于简单标签匹配的局限。
这个系统的独特之处在于:
- 实现了从"用户输入关键词"到"理解用户真实意图"的跨越
- 能够分析菜谱文本中的隐含信息(如烹饪难度、适合场合等)
- 可以根据用户历史行为动态调整推荐策略
- 支持多模态交互(文字描述、语音输入、图片识别等)
提示:在实际开发中,很多同学容易陷入"为了用大模型而用大模型"的误区。正确的做法是先明确传统推荐系统的痛点,再针对性引入LLM能力。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计
2.1 整体架构方案
系统采用分层架构设计,各层之间通过定义良好的接口通信:
code复制[前端层]
Django模板 + Bootstrap/Vue.js
↓
[业务逻辑层]
Django Views + 推荐算法
↓
[数据处理层]
Django ORM + Pandas + LLM接口
↓
[数据存储层]
PostgreSQL(结构化数据) + Redis(缓存) + 向量数据库(可选)
2.2 关键技术选型分析
Django框架选择理由:
- 完善的Admin后台:适合快速构建数据管理界面
- ORM支持:简化数据库操作,特别适合学生项目
- 安全性:内置CSRF防护、SQL注入防护等
- 社区生态:丰富的第三方包(Django REST framework等)
LLM集成方案对比:
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| API调用(如OpenAI) | 开发简单、效果稳定 | 有调用成本、依赖网络 | 快速验证原型 |
| 本地部署(LLaMA等) | 数据隐私性好 | 硬件要求高 | 对数据敏感的项目 |
| 微调预训练模型 | 可定制性强 | 需要标注数据 | 专业领域应用 |
个人经验:对于毕业设计,建议先用API方案快速验证核心功能,后期再考虑本地部署。我曾在一个类似项目中,先用GPT-3.5接口实现基础推荐,答辩前两周才切换为本地部署的LLaMA2,节省了大量初期开发时间。
2.3 数据流设计
典型的美食推荐数据流:
- 用户输入:"想要做一道适合周末聚餐的素食主菜"
- 前端通过AJAX发送到Django后端
- Django调用LLM接口进行意图识别:
python复制def analyze_intent(text): prompt = f"""分析以下美食请求的深层需求: 用户输入:{text} 输出JSON格式:{"occasion":"","diet":"","cooking_time":"","flavor":""}""" response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[{"role":"user","content":prompt}] ) return json.loads(response.choices[0].message.content) - 根据解析结果查询数据库:
python复制recipes = Recipe.objects.filter( occasion__contains=intent['occasion'], category='vegetarian', cooking_time__lte=90 ).order_by('-rating')[:10] - 二次精排:用LLM对初筛结果进行个性化排序
3. 核心功能实现细节
3.1 菜谱数据采集与处理
数据来源方案对比:
| 来源 | 采集方式 | 数据处理难点 | 适合阶段 |
|---|---|---|---|
| 公开API(如Edamam) | 直接调用 | 字段可能不完整 | 原型开发 |
| 爬虫采集 | BeautifulSoup/Scrapy | 反爬措施、数据清洗 | 中期完善 |
| 人工录入 | Django Admin | 耗时但质量高 | 核心数据 |
数据结构设计示例:
python复制class Recipe(models.Model):
title = models.CharField(max_length=200)
ingredients = models.TextField() # 结构化存储更佳
steps = models.TextField()
cooking_time = models.IntegerField()
difficulty = models.CharField(max_length=20)
occasion = models.CharField(max_length=100) # 聚餐/日常/节日等
dietary = models.CharField(max_length=100) # 素食/无麸质等
flavor_profile = models.CharField(max_length=100) # 甜/辣等
image = models.ImageField(upload_to='recipes/')
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
踩坑提醒:初期我直接将菜谱步骤存为纯文本,后来发现LLM处理结构化数据效果更好。改进方案是将步骤拆分为单独的Step模型,每个步骤包含序号、描述、预计时间等字段。
3.2 推荐算法实现
混合推荐策略:
-
基于内容的过滤:
python复制from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity def content_based_recommend(query, n=5): # 将菜谱文本向量化 tfidf = TfidfVectorizer(stop_words='english') tfidf_matrix = tfidf.fit_transform([r.description for r in Recipe.objects.all()]) # 计算相似度 query_vec = tfidf.transform([query]) similarities = cosine_similarity(query_vec, tfidf_matrix) # 返回最相似的n个菜谱 similar_indices = similarities.argsort()[0][-n:][::-1] return [Recipe.objects.all()[i] for i in similar_indices] -
LLM增强的协同过滤:
- 传统协同过滤需要大量用户行为数据
- 使用LLM生成模拟用户偏好数据:
python复制def generate_synthetic_preferences(): prompt = """生成10个虚拟用户的饮食偏好示例,包含: - 年龄 - 饮食限制 - 口味偏好 - 烹饪经验 输出为JSON列表""" response = openai.ChatCompletion.create(...) return json.loads(response.choices[0].message.content)
-
实时上下文感知:
- 分析用户当前会话中的隐含信息
- 示例:当用户提到"感冒了",自动推荐清淡易消化的食物
3.3 用户画像构建
动态用户画像数据结构:
python复制class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
explicit_preferences = models.JSONField(default=dict) # 用户手动设置
implicit_preferences = models.JSONField(default=dict) # 通过行为分析
def update_from_conversation(self, chat_history):
prompt = f"""根据以下对话更新用户饮食偏好:
{chat_history}
当前画像:{self.explicit_preferences}
输出更新后的JSON(只返回JSON)"""
response = openai.ChatCompletion.create(...)
self.explicit_preferences.update(json.loads(response))
self.save()
画像更新时机:
- 用户显式反馈(评分/收藏)
- 隐式行为(浏览时长、搜索词)
- 会话分析(与聊天机器人的对话)
4. 系统优化与部署
4.1 性能优化方案
缓存策略:
-
Redis缓存热门推荐结果
python复制from django.core.cache import cache def get_recommendations(user_id): cache_key = f"recs_{user_id}" result = cache.get(cache_key) if not result: result = compute_recommendations(user_id) # 耗时计算 cache.set(cache_key, result, timeout=3600) return result -
预计算常用推荐组合
python复制from celery import shared_task @shared_task def precompute_recs(): for user in User.objects.all(): get_recommendations(user.id) # 触发缓存
LLM调用优化:
- 批量处理请求
- 使用更小的模型处理简单任务
- 设置合理的超时和重试机制
4.2 部署方案对比
| 方案 | 所需资源 | 适合场景 | 示例配置 |
|---|---|---|---|
| 传统VPS | 2核4G起步 | 预算有限 | Nginx + Gunicorn + PostgreSQL |
| 云服务 | 按需付费 | 灵活扩展 | AWS Lightsail / 阿里云ECS |
| 无服务 | 事件驱动 | 间歇使用 | Vercel + Supabase + Cloudflare Workers |
Docker部署示例:
dockerfile复制FROM python:3.9
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "foodrec.wsgi"]
性能监控:
- Django Silk:分析请求性能
- Prometheus + Grafana:监控系统指标
- Sentry:错误追踪
4.3 安全注意事项
-
LLM API安全:
- 不要在前端直接调用API
- 使用Django的缓存机制存储常用响应
- 设置合理的速率限制
-
数据安全:
python复制# settings.py SECURE_SSL_REDIRECT = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True -
用户隐私:
- 匿名化处理用户行为数据
- 提供数据导出和删除功能
- 使用django-allauth实现安全的第三方登录
5. 项目扩展方向
5.1 多模态交互扩展
-
图像识别输入:
python复制def recognize_ingredients(image): # 使用CLIP等模型 response = openai.Image.create_variation( image=image, n=1, size="256x256" ) return parse_ingredients(response['data'][0]['url']) -
语音交互:
- 使用Whisper进行语音识别
- 通过ElevenLabs生成语音回复
5.2 高级分析功能
-
营养分析:
python复制def analyze_nutrition(recipe): prompt = f"""计算以下菜谱的营养成分: {recipe} 输出JSON格式:{"calories":"","protein":"","fat":""}""" # 调用LLM或专用API -
成本估算:
- 对接超市API获取实时价格
- 使用LLM解析"适量"等模糊量词
5.3 社交功能增强
-
用户生成内容:
- 菜谱创作工具
- 烹饪成果分享社区
-
社交化推荐:
python复制def get_friends_recs(user): friends = user.social_connections.all() return Recipe.objects.filter( creator__in=friends ).order_by('-rating')
6. 毕业设计答辩要点
6.1 技术亮点展示
-
传统与AI技术的结合:
- 展示没有LLM时的基础推荐
- 对比引入LLM后的效果提升
-
数据处理流程可视化:
- 使用Pandas Profiling生成数据报告
- 展示LLM如何理解模糊查询
6.2 演示技巧
-
准备典型场景:
- "家里只有鸡蛋和西红柿"
- "想做一道惊艳朋友的西餐"
-
处理意外输入:
- 故意输入模糊查询展示系统鲁棒性
- 演示错误恢复流程
6.3 常见问题准备
-
技术选择类:
- "为什么选择Django而不是Flask?"
- "如何处理LLM的响应延迟?"
-
业务逻辑类:
- "如何解决用户冷启动问题?"
- "系统推荐不符合饮食限制怎么办?"
-
扩展性类:
- "如何支持更多菜系?"
- "用户量增大后的架构调整方案?"
答辩经验:提前录制几个典型场景的演示视频作为备用。我曾遇到现场网络问题导致LLM无法响应,这时播放预录视频顺利完成了演示。
