每年毕设季节我都会看到一大批"美食推荐系统"的题目,说实话,大部分都做成了换皮的商品管理系统:用户管理、菜谱增删改查、简单的评分推荐,答辩的时候放两张截图就算完事。但如果你在这个题目里加一个"大模型",整个项目的高度就完全不同了——它不再是一个CRUD演示,而是一个从传统推荐算法到LLM应用、从关系型数据管理到数据分析可视化的综合性系统。这篇博文我打算把Django+大模型美食推荐系统这个毕设题目从选题逻辑到系统架构、从推荐方案到数据分析和最后的交付文档,完整拆开讲一遍。我带过不少做这类系统的学生,这篇里大部分内容都是从那些项目里沉淀下来的实际方案和踩坑记录,适合正在选题或者已经开干、但不太清楚"大模型和大数据"部分该落到什么程度的同学参考。
1. 这个选题为什么值得做:从"凑数项目"到"技术融合亮点"
1.1 美食推荐系统不新鲜,新鲜的是技术组合
先说句实在话:纯粹的美食推荐系统,在推荐算法层面已经没什么可折腾的了。用户-菜谱-评分这三张表,加上协同过滤或者简单的内容推荐,本科毕设里一抓一大把。但"含大模型量"不同。这几年无论是企业面试还是毕业答辩,关注点都在"你如何把LLM落到实际业务里",而不是"你调用了哪个大模型的API做了个聊天机器人"。美食推荐系统恰好是一个特别自然的落地场景——推荐系统需要理解用户偏好、理解菜品语义、生成个性化推荐理由,这些全是传统算法做不好、大模型却能轻松胜任的地方。
所以这个选题的竞争力不在"推荐"二字,而在"传统推荐+LLM增强+数据分析"这三个技术栈的融合。你等于用一个题目同时覆盖了后端开发、算法设计、大模型应用、数据处理与可视化四个方向,答辩的时候任何一个方向的评委都能找到他想听的东西。
1.2 这个项目适合什么样的人选
实话实说,这个题目比普通的CRUD系统至少多出30%-50%的工作量,不是所有人都适合。我建议符合下面两种情况的同学选它:
- 你有Python基础,Django哪怕只会写Model和View,但愿意花时间读文档、调接口。大模型的接入本身不复杂,难点在业务整合,如果你的Python功底不够,后面容易卡壳。
- 你对"推荐系统"和"数据可视化"至少有一个方向有真实兴趣。这个题目最怕的就是两部分都敷衍,最后做出来四不像。
如果只是想要一个稳妥、省事的毕设,那我建议老老实实做一个普通的美食管理系统加一个简单的协同过滤,别硬上大模型。但如果你确实想在毕设里体现一点技术含量,也愿意花时间,那这个题目的上限非常高——我见过有学生把推荐解释、菜谱问答、饮食数据分析全部做完,最后论文直接被院里推优的。
2. 系统架构与技术选型:Django如何扛起一台"大模型+大数据"应用
2.1 整体分层设计
先给一个经过实际项目验证的分层架构,你在做系统设计章节的时候可以直接参考:
- 表现层(前端):HTML模板+Bootstrap或Vue,图表用ECharts。推荐理由生成、菜谱详情、数据分析看板都在这一层展示。
- 应用层(Django Views):负责用户请求处理、业务逻辑编排、调用推荐服务和LLM服务。
- 服务层(Service模块):包括推荐引擎(召回排序)、LLM服务封装(推荐解释、菜谱问答、语义标签提取)、数据分析模块(统计计算、聚类分析)。
- 数据层:MySQL存业务数据(用户、菜谱、评分、收藏),Redis做缓存(热门菜谱、大模型响应缓存),如果需要存储向量,可以用一个轻量的向量存储(如Chroma或者直接存PostgreSQL的pgvector)。
这个分层的核心原则是:大模型相关逻辑绝对不能散落在View函数里,必须独立成Service模块。原因有两个:一是方便替换模型,今天用这个API,明天想换另一个,只改Service层;二是答辩的时候你能清楚地讲出"我把大模型能力封装成了服务接口",这是架构思维的体现。
2.2 Django后端:为什么不是FastAPI、Spring Boot
我特意让学生在毕设里用Django,不只是因为题目要求,而是Django在毕设场景下确实有不可替代的优势。Django自带Admin管理后台,菜谱、用户、分类这些数据的管理界面几乎零成本搞定;自带ORM和迁移机制,建表改表比手写SQL省太多事;自带模板、表单、认证体系,你完全不需要额外折腾用户登录注册。
你可能会问,大模型调用通常是异步任务,Django同步请求-响应模型够用吗?我的答案是:毕设场景足够。每次推荐解释的生成控制在2-3秒内,用户可接受,也不需要Celery。如果你想做得更专业,可以给Django配一个后台任务队列(比如用Celery加Redis),把LLM调用放到异步任务里,但这不是必选项。我的建议是:第一版全部同步实现在2-3秒内返回,跑通之后有余力再上异步,不要一上来就引入Celery增加无谓的复杂度。
2.3 数据处理和分析模块的位置
"大数据毕业设计"这个标签,落到实际操作层面,并不是真的让你搭Hadoop集群。你真正要做的是把这几个部分做好:
- 数据规模:菜谱数据至少准备几千到上万条。可以通过爬虫获取(要注意爬取频率和数据合法性),也可以找公开数据集。数据量达标了,"大数据分析"才说得上话。
- 数据预处理:写一个完整的清洗脚本,包括缺失值处理、去重、文本归一化、标签整理,把"脏数据"变成可分析的"干净数据",这个环节非常重要,答辩时往这一讲,懂行的评委立刻知道你不是在糊弄。
- 分析维度:后续章节细讲,但大概要覆盖菜品分类分布、食材使用频率、热量营养结构、用户口味偏好等多个维度。
- 可视化呈现:用ECharts或者Plotly输出交互式图表,做成一个数据看板页面,让分析结果可视、可读、可操作。
我反复跟学生强调:毕设里的"大数据",重点是数据链路的完整性——采集、清洗、存储、分析、可视化、决策反馈。你把这六步讲清楚了,比任何大数据框架都更有说服力。
3. 推荐系统的核心实现:召回、排序与"有温度"的推荐理由
3.1 召回层:基于协同过滤和内容相似度的候选集生成
推荐系统第一步是召回——从几千道菜里挑出几十道候选。这一步用大模型做代价太高也没必要,传统算法足够。我推荐在毕设里做两种召回渠道,将来写论文也能形成对比实验:
- 基于物品的协同过滤(Item-Based CF):用户对菜谱评分或收藏之后,计算菜谱之间的相似度矩阵。相似度的依据是"哪些菜品经常被同一用户操作"。创建用户-菜谱交互矩阵,用余弦相似度或皮尔逊相关系数计算菜品相似度,然后对用户操作过的菜找最相似的N道菜。这是最经典的方法,推荐结果稳定,而且可以在系统里清晰地用表格展示"因为A,所以推荐B"。
- 基于内容的召回(Content-Based):对菜谱的名称、食材、分类、标签做文本向量化。可以用TF-IDF,也可以用预训练模型(如Sentence-BERT)将菜谱描述编码成向量,再用余弦相似度计算内容相似度。后者效果明显更好,但需要注意模型体积和推理时间,可以离线先算好所有菜谱的向量,存数据库,召回时只查一次。
两种召回各取TopN(比如各取30),合并去重后得到60道左右的候选集,交给排序层。
伪代码大致是这样:
def recall(user_id, top_n=30): # 基于物品协同过滤召回 interacted = get_user_interacted_items(user_id) cf_candidates = item_cf_recall(interacted, top_n=top_n) # 基于内容相似度召回 content_candidates = content_based_recall(interacted, top_n=top_n) # 合并、按综合得分排序 merged = merge_and_score(cf_candidates, content_candidates) return merged[:top_n]3.2 排序层:大模型作为排序器如何工作
召回之后,你手上有几十道候选菜,这时候让大模型做排序。大模型没有办法直接对几十道菜的数值分数排序——这是大模型不擅长的事,你不能让LLM做一个"精确计算"。所以我的方案不是让大模型打分排序,而是让大模型的语义理解能力帮传统排序做增强。
具体做法:
- 给大模型一个用户画像,包括用户的口味偏好标签(比如"爱吃辣""偏爱素食""对海鲜过敏")、历史交互菜品的口味倾向。
- 把候选菜谱的标签和描述作为上下文丢给模型,让模型输出一个语义匹配评分:1-5分,表示这道菜在"语义层面"和用户偏好的匹配程度。
- 把语义匹配评分和传统算法的排序分数加权融合,得出最终排序。
举例来说,用户历史爱点"麻辣香锅""水煮肉片",召回里有"宫保鸡丁"和"清蒸鲈鱼",传统协同过滤可能因为数据稀疏给两者差不多分,但大模型看一眼就知道"宫保鸡丁"更符合这个用户的重口味偏好,语义匹配分天然更高。这一层就是整个系统最出彩的部分,答辩时评委对这个机制一定会感兴趣。
提示词模板给一个可以照着改的版本:
你是一个美食推荐助手。下面是我整理的用户偏好:{user_profile} 候选菜谱列表如下:{candidate_list} 请对每道菜与用户偏好的语义匹配程度进行打分(1-5分),只输出JSON格式结果: {"items": [{"dish_id": 1, "score": 4.2, "reason": "用户偏好重口味,该菜品以麻辣为特色"}]}这里有个操作细节:必须要求大模型输出结构化JSON,并且用response_format之类的参数固定格式。不要让模型自由发挥,否则解析结果会搞到你崩溃。
3.3 推荐解释生成:让系统会说话
这是我在项目里最喜欢的一个模块,也是大模型最能"秀肌肉"的地方。传统推荐系统只能说"根据你的收藏推荐",但大模型可以生成一段有温度的话:
"看你最近常搜川菜,今天推荐的这道辣子鸡用的是鸡腿肉,比起鸡胸更嫩,而且我觉得你会喜欢它的干辣椒配花生米的香气。要不要试一下?"
生成推荐理由有三种做法,效果从低到高:
- 模板拼接(最基础):把用户标签和菜品标签拼成固定句式。效果僵硬,但胜在稳定。
- 标签+LLM扩写(推荐):先提取用户偏好标签和菜品味型标签,让大模型基于标签生成解释。比纯模板自然得多,又比把全部上下文丢给模型省Token。
- 全上下文+多轮对话(进阶):把用户历史行为和这道菜的特征全部送入模型,让模型自由发挥。效果最好,但要注意输出长度和审查问题。
我的建议是选第二种。第三种如果处理不好容易让模型"脑补"出用户没点过的菜,反而在答辩时被问倒。还有很重要的一个体验细节:推荐理由不要每次打开页面都重新生成,生成一次就缓存到Redis,至少缓存一天。不然用户刷新一次页面,理由变了,观感非常差,而且你的API账单会很难看。
4. 菜谱食谱数据分析:从数据清洗到可视化看板的完整链路
4.1 数据获取与预处理
数据是整个项目的地基。菜谱数据从哪里来?公开数据集、爬虫、手动标注都可以,但不管来源是什么,你必须构建一个连贯的数据获取-清洗流程。我建议至少准备:
- 菜谱名称、分类口味标签(川菜、粤菜、甜点等)
- 食材清单(包含用量信息,后面做营养分析要用)
- 烹饪步骤(文本描述)
- 热量、蛋白质、脂肪、碳水等营养数据(能从食材估算最好)
- 浏览量、收藏量、评分等行为数据(可以自动生成模拟数据)
清洗环节要注意几个坑:食材名称不统一("土豆"和"马铃薯")、标签格式不一致(有的空格分隔有的逗号分隔)、营养数据缺失。写一个Python清洗脚本,用Pandas处理,核心逻辑包括全表去重、缺失值填充策略(营养数据缺失可以按食材均值估算)、标签标准化映射。
4.2 分析维度与可视化方案
数据分析模块建议做一个"数据看板"页面,包含以下维度,每个维度配对应的图表:
- 菜品分类分布:饼图或环形图,看八大菜系和甜点主食各占多少比例。
- 食材使用频率TopN:条形图,统计哪些食材出现频率最高。
- 热量区间分布:直方图,查看菜品的能量分布规律,明确"清淡菜"和"热量炸弹"的比例。
- 口味标签共现分析:用气泡图或矩形树图展示"辣"和"川菜"、"甜"和"烘焙"等标签之间的关联关系。
- 用户操作行为分析:折线图展示某个时间段内收藏、评分、浏览的趋势变化。
每个分析维度建议配一段文字结论,比如"从食材高频榜看,辣椒、蒜、姜三大基础调味食材在数据集中占有主导地位"。答辩时这种"图表+数据洞察"的组合非常加分,证明你不只是画了图,是真的做了分析思考。
4.3 让数据分析支撑推荐决策
这里有个容易忽略但又特别能出彩的点:数据分析结果要反过来服务推荐系统。比如高热度菜品、高评分菜品的标签分布可以作为推荐系统的全局热门候选;聚类分析可以将菜谱划分为"重口型""清淡型""甜口型"等口味簇,辅助构建用户画像;某些食材的可替代关系可以在推荐时考虑"用户不吃的食材"做排除。
也就是说,让数据分析模块成为推荐系统的一个上游输入,而不是一个孤立的、展示用的页面。这一条如果能讲清楚,你的系统在逻辑上就形成了一个完整的闭环:数据采集 -> 分析 -> 画像 -> 推荐 -> 反馈 -> 再分析。这是真正拉开和普通毕设差距的地方。
5. 大模型接入的实战细节:API选择、提示词模板、成本与降级策略
5.1 模型选型与部署方式
这个问题在答疑群里被问了无数次。明确说结论:别自己微调,也尽量别自己本地部署一个十几B的大模型。你的机器没有足够的显存,推理慢,还会耽误进度。最优选择是用成熟的大模型API服务,国内可直连的模型服务不少,选一个你觉得文档顺手、有免费额度的用就行。等系统功能全部跑通之后,如果你想展示"部署能力",可以用Ollama在本地跑一个小参数的模型做一个降级备选,但这属于加分项,不是必选。
选择模型时重点考虑三个维度:语义理解能力(推荐解释和排序打分都依赖它)、输出稳定性(必须是中文能力扎实的模型)、响应速度(推荐场景3秒内返回比较好)。
5.2 提示词模板设计与上下文管理
提示词模板是整个大模型模块最核心的工程点。实操中我会把模板拆成三部分管理:
- System Prompt:定义角色和行为边界。比如"你是专业的美食推荐助手,只回复与菜谱推荐、饮食偏好相关的内容,不回答无关问题"。
- User Context:动态拼入用户画像和当前请求相关的数据(候选菜品、历史偏好、排除食材等)。
- Output Constraint:严格指定输出格式,并要求"只输出JSON,不要额外内容"。这一步能省掉后面大量解析代码。
一个常见坑:上下文太长。如果你把所有候选菜谱的完整描述都塞进Prompt,不仅慢,还费钱。解决办法是抽特征:只传菜名、标签、核心食材、热量这几个关键字段,把完整描述留在系统里供展示用。我实测过,只传摘要字段的效果和传全文几乎一样,成本却少了一半以上。
5.3 缓存、超时与降级处理
调用大模型API有一个毕设里几乎必遇的情况:线上服务偶发超时或报错。处理不好,用户刷到推荐页直接白屏,开题的时候会被答辩老师抓住这个痛点削弱整体印象。我的建议是做一个三层兜底:
- 第一层:Redis缓存。同一用户同一场景的推荐解释6小时内不重新生成,直接命中缓存。
- 第二层:超时控制。用requests或者httpx调大模型API时设置明确的超时时间(5秒),超时后触发本地兜底逻辑。
- 第三层:本地模板兜底。大模型挂了就用"根据你的{标签}偏好,为你推荐{菜品名}"这类模板生成推荐理由。
前端的处理也要做:推荐解释区域先渲染骨架屏或"生成中..."的占位符,大模型响应返回后再替换,而不是整个页面等接口。这三层做完,无论线上API怎么抽风,你的系统都能正常演示,这个健壮性设计本身就是答辩时的亮点。
6. 毕业设计四件套:源码、LW文档、PPT、演示讲解的准备技巧
6.1 源码工程如何组织才不像demo
很多学生的源码树一眼看去就是"随手写的练习",对自己很不利。我给学生的统一要求是:源码目录必须体现业务分层,至少要有apps/(业务模块)、services/(核心服务:推荐、LLM、数据分析)、utils/(通用工具)、scripts/(数据清洗、数据导入)这几个目录。每个服务模块内部再按职责拆成文件:recommender.py、llm_service.py、data_analyzer.py。
另外很重要但容易被忽略的两件小事:一是配置文件和环境变量要分开,用python-decouple或django-environ管理密钥,千万别把API Key硬编码在代码里且随源码一起提交。答辩老师如果看到源码里有硬编码密钥,印象分会降不少。二是代码里必须写关键注释和README,说明怎么迁移数据库、怎么配置大模型API、怎么跑数据清洗脚本。这三样加起来,给人的第一印象就是"这是个正经工程"。
6.2 LW文档的写作重心
LW文档(也就是任务书、开题报告、论文这类文档材料)的写作,最忌变成"流水账"。你不能把系统操作流程写完了事,必须体现技术深度。按照我的经验,论文主体要重点突出这几块:
- 传统推荐算法的原理与实现细节(协同过滤计算过程、相似度公式、数学推导)
- 大模型增强推荐的设计动机与技术方案(为什么需要大模型、语义匹配逻辑、与协同过滤的融合策略)
- 数据分析的方法论与结果解读(数据清洗步骤、图表设计、分析结论)
- 系统测试,特别是推荐效果的评估(命中率、用户满意度问卷、与传统方法对比实验)
这里强烈建议做一个对比实验:同一个用户,一组只看协同过滤结果,一组看"协同过滤+大模型增强"结果,统计点击率或满意度评分。这个对比实验做出来,论文的含金量直接上一个台阶。
6.3 PPT和答辩演示的节奏设计
答辩PPT不要超过20页,逻辑线建议这样走:选题背景与意义 -> 系统架构 -> 核心技术是怎么实现的 -> 数据分析结果展示 -> 系统演示截图 -> 总结与展望。重心放在第三和第四部分,前面两三页快速过完。
演示环节我的建议:提前准备一份带干净数据的演示账号,演示操作脚本要在答辩前完整走3遍以上。准备好几个关键演示点——大模型生成的推荐解释、数据看板的交互图表、推荐效果对比实验的结果页面。另外一定要提前检查大模型API能不能用,万一答辩当天服务抽风,要能用本地兜底方案完成演示。这条踩坑经验是真的带过血的教训,有个学生答辩当天遇到模型服务限流,推荐理由一片空白,磕磕绊绊讲完分数惨淡。
7. 六个月踩坑清单:排期规划与常见问题应对
7.1 时间排期建议
按4-5个月的常规毕设周期,我是这样给学生规划的:
- 第1个月:选题确认、技术预研、数据收集与清洗。这个月最关键,数据量不达标后面一切白搭。
- 第2个月:Django基础搭好,用户、菜谱、评分、收藏这几个核心模块做完。
- 第3个月:推荐系统核心实现,协同过滤跑通,能把推荐列表展示出来。
- 第4个月:大模型接入,推荐解释生成、菜谱问答、语义排序完成。
- 第5个月:数据分析模块、可视化看板、系统测试、文档撰写。最后留一周做PPT和答辩预演。
很多人时间规划出问题的根源是把数据清洗和预研拖到了第二个月。这个必须前置,不然第4月你会发现推荐模块是在垃圾数据上做出来的,返工成本极高。
7.2 高频踩坑点
每周答疑都能遇见的坑,我挑几个有代表性的列出来,建议收藏备用:
- Djang ORM的N+1查询。推荐列表一次查几百个菜谱,没用
select_related和prefetch_related的话,内存和耗时直接爆炸。查菜谱时必须连食材表、标签表一起预取。 - 大模型输出解析失败。前面说的"只输出JSON",实操中模型还是可能多输出一段废话。解析时不要
json.loads一把梭,做一个容错函数:尝试提取第一个{到最后一个}之间的子串再解析,还能顺带处理Markdown代码块包裹的情况。 - 菜谱图片。很多学生忽略图片字段,觉得用占位图就行,结果展示的时候整个页面灰蒙蒙的,答辩观感非常差。尽量找带真实菜品图片的数据源,没有图片就搜索可免费使用的图片资源补充。
- 排行榜和"猜你喜欢"的数据同步。用户收藏、评分后需要刷新推荐,建议做成信号机制:Model保存后自动更新用户的候选池缓存,而不是每次请求都重算。
- Python版本兼容性。安装Django、pandas、sentence-transformers这些库时最怕Python版本过新或过旧。建议统一用Python 3.10-3.11,能避免90%的依赖噩梦。
踩过这些坑之后,我自己做这种Django大模型项目的时候反而是最放心的,因为问题都是可预见的,方案也都是成熟的。如果非要说还有什么变量,那就是大模型服务本身的质量波动——所以兜底策略,我从第一版就开始做,做到答辩前一晚还在优化。这个项目的上限不低,下限其实也硬,关键就看你愿不愿意把每一个模块都按"能拿出来讲"的标准去打磨。