拓冰建站拓冰建站
首页 / 资讯中心 / 正文

基于知识图谱与本地LLM的可解释食谱推荐系统

简介本资源是一套基于知识图谱与生成式AI技术构建的智能食谱推荐系统毕业设计源码面向计算机及相关专业本科生开展毕业设计、课程设计或项目实战练习。系统融合知识图谱建模食材-营养-功效-菜系等多维关系与生成式AI能力如个性化描述生成、食谱优化建议解决传统推荐中冷启动与可解释性不足问题。压缩包共42个文件含19个React前端组件.tsx、9个样式文件.less、3个TypeScript核心逻辑.ts、2个Python脚本含main.py后端入口、2个Shell部署脚本及配置类文件json/yaml/sh等整体681KB结构清晰、模块解耦便于理解前后端协同逻辑。已有403人学习下载提供完整可运行环境本地编译调试通过评审分98分附带典型目录结构说明与关键模块注释助力快速掌握知识图谱构建、API对接及生成式AI集成实践路径。1. 这不是又一个“猜你喜欢”推荐系统它用知识图谱建模食材化学关系再让生成式AI解释“为什么这道菜适合你”很多同学拿到“智能食谱推荐”毕设题目第一反应是套用协同过滤或矩阵分解——但这类方法在冷启动、可解释性、营养约束上天然乏力。这个98分毕业设计的突破点很实在它不把食谱当黑盒商品而是先用本体建模构建「食材-营养素-功效-禁忌-烹饪方式」五层关系网络再让生成式AI本地部署的轻量LLM基于图谱路径推理生成带医学依据的推荐理由。比如输入“孕妇缺铁忌生冷”系统不会只返回菠菜猪肝汤还会输出“菠菜含非血红素铁需维生素C促进吸收猪肝提供血红素铁二者协同提升铁利用率姜汁替代生冷调料符合中医‘温中散寒’原则”。整个流程完全脱离用户行为日志纯靠结构化知识驱动对食品科学、营养学、中医药等跨学科场景有强适配性。适合计算机专业学生做毕设——代码量可控核心逻辑集中在main.py和src/components/GraphEngine技术栈清晰Python后端React前端Neo4j图数据库且所有模块均通过本地编译验证无需调用外部API。2. 知识图谱构建从食材本体定义到Neo4j三元组批量导入2.1 为什么选Neo4j而非RDF三元组存储项目放弃传统OWL本体工具链直接采用Neo4j作为图数据库原因很务实一是Neo4j的Cypher查询语法对“多跳路径推理”如“食材A→含营养素B→改善症状C→适用人群D”支持更直观二是毕业设计场景下数据规模在万级节点内Neo4j社区版完全够用且免去SPARQL服务部署复杂度。对比RDF存储Neo4j在MATCH (a:Ingredient)-[r:CONTAINS]-(n:Nutrient)-[s:IMPROVES]-(c:Symptom)这类深度关联查询中执行效率高3倍以上实测10万条边数据5跳查询平均耗时80ms。2.2 本体层设计五类核心节点与七种语义关系项目定义了严格受控的本体结构全部在src/common/ontology_schema.py中声明。关键不是堆砌概念而是确保每条关系可被营养学文献支撑节点类型示例值数据来源说明Ingredient菠菜、猪肝、枸杞《中国食物成分表》标准编码Nutrient铁、叶酸、维生素AWHO营养素推荐摄入量RNI标准Symptom缺铁性贫血、妊娠呕吐、夜盲症ICD-11症状编码子集Population孕妇、糖尿病患者、痛风患者《中国居民膳食指南》特殊人群章节CookingMethod清蒸、快炒、炖煮中国烹饪协会《健康烹饪白皮书》提示所有节点ID采用{type}_{standard_code}格式如Ingredient_010101避免中文字符导致的Cypher解析异常。standard_code直接映射国家标准GB/T 32917-2016《食品营养成分标示通则》编码体系。2.3 三元组生成与批量导入脚本详解知识注入不靠手动录入而是通过scripts/build_kg.py自动化完成。该脚本核心逻辑分三步# scripts/build_kg.py 关键片段 def generate_triples_from_csv(csv_path: str) - List[Tuple[str, str, str]]: 从结构化CSV生成(主语, 谓语, 宾语)三元组 triples [] df pd.read_csv(csv_path) for _, row in df.iterrows(): # 根据字段名自动映射关系类型 if row[relation] contains_nutrient: triples.append((fIngredient_{row[ingredient_id]}, CONTAINS, fNutrient_{row[nutrient_id]})) elif row[relation] improves_symptom: triples.append((fNutrient_{row[nutrient_id]}, IMPROVES, fSymptom_{row[symptom_id]})) return triples def import_to_neo4j(triples: List[Tuple[str, str, str]]): 批量导入至Neo4j启用事务确保一致性 with driver.session() as session: # 先创建唯一约束避免重复节点 session.run(CREATE CONSTRAINT ON (i:Ingredient) ASSERT i.id IS UNIQUE) session.run(CREATE CONSTRAINT ON (n:Nutrient) ASSERT n.id IS UNIQUE) # 批量创建节点分批次提交防内存溢出 for batch in chunk_list(triples, 1000): session.run( UNWIND $batch AS t MERGE (a {id: t[0]}) MERGE (b {id: t[2]}) CREATE (a)-[:{t[1]}]-(b) , batchbatch)参数说明与调试要点chunk_list(triples, 1000)将三元组按1000条分批避免单次事务过大导致Neo4j OOM。实测在8GB内存机器上超过2000条/批易触发GC停顿。MERGE而非CREATE确保同一食材节点不重复创建id字段必须全局唯一。关系名大写如CONTAINSCypher要求关系类型为标识符不能含空格或下划线。2.4 验证图谱完整性用Cypher检测常见逻辑漏洞导入后必须运行以下查询否则后续推荐会失效// 检查是否存在孤立营养素节点无任何食材指向它 MATCH (n:Nutrient) WHERE NOT (n)-[:CONTAINS]-(:Ingredient) RETURN count(n) AS orphan_nutrients // 检查孕妇群体是否至少关联3种改善妊娠症状的营养素 MATCH (p:Population {id: Population_pregnant})-[:REQUIRES]-(n:Nutrient)-[:IMPROVES]-(s:Symptom) RETURN count(DISTINCT n) AS nutrient_count注意若orphan_nutrients 0说明营养素数据未与食材正确关联需检查CSV中ingredient_id与nutrient_id映射表是否完整若nutrient_count 3则孕妇本体定义不充分需补充叶酸、铁、DHA等关键营养素路径。3. 生成式AI推理引擎本地化LLM如何基于图谱路径生成可解释推荐3.1 为什么不用ChatGLM或Qwen直接问答项目未调用云端大模型而是采用llama.cpp量化后的Phi-3-mini-4k-instruct仅1.8GB原因明确毕业设计需保证离线可运行、响应延迟可控P951.2s、且能精确控制生成内容结构。实测对比显示当提示词要求“按JSON格式输出推荐理由包含[营养机制][中医原理][烹饪建议]三个字段”时Phi-3的结构化输出成功率JSON解析通过率达92.7%远超同等参数量的ChatGLM-6B73.1%。3.2 图谱路径到Prompt的转换规则生成式AI不直接读取图数据库而是由src/components/GraphEngine/path_to_prompt.py将Cypher查询结果转化为结构化提示词。关键设计是路径压缩避免将整条路径如菠菜→含铁→改善贫血→适用孕妇直译为自然语言而是提取因果链主干def compress_path_to_prompt(path_nodes: List[Dict], user_profile: Dict) - str: 将图谱路径压缩为LLM可理解的提示词 # 提取关键实体去除非核心节点如CookingMethod core_entities [n for n in path_nodes if n[label] in [Ingredient, Nutrient, Symptom, Population]] # 构建因果链描述非逐字翻译 if len(core_entities) 3: # 示例[菠菜, 铁, 贫血, 孕妇] → 菠菜富含铁元素可改善孕妇常见的缺铁性贫血 subject core_entities[0][name] nutrient core_entities[1][name] symptom core_entities[2][name] population user_profile.get(population, 普通人群) return f{subject}富含{nutrient}可改善{population}常见的{symptom} # fallback返回原始路径文本极少触发 return - .join([n[name] for n in path_nodes])3.3 Prompt工程细节强制JSON输出与领域术语校验main.py中调用LLM的generate_explanation()函数其提示词模板经过三次迭代优化PROMPT_TEMPLATE 你是一名资深营养师兼中医食疗顾问。请根据以下信息用中文生成一段专业、简洁、可验证的食谱推荐理由。要求 1. 严格按JSON格式输出包含三个字段nutrition_mechanism营养学机制、tcm_principle中医原理、cooking_advice烹饪建议 2. 所有内容必须基于已知科学事实禁止虚构。若信息不足字段值填暂无可靠依据 3. 禁止使用可能大概等模糊表述必须给出确定性结论 用户画像{user_profile} 图谱路径摘要{path_summary} 输出示例 {{ nutrition_mechanism: 菠菜含非血红素铁需维生素C促进吸收, tcm_principle: 菠菜性凉孕妇宜配姜汁中和寒性, cooking_advice: 建议焯水后与猪肝同炒加少量鲜榨橙汁 }} 关键参数说明temperature0.3降低随机性确保相同输入产生稳定输出毕业设计答辩需结果可复现。max_tokens256限制长度防止LLM自由发挥偏离主题。stop[\n\n]设置停止符避免LLM续写无关内容。3.4 本地LLM服务封装Flask API与错误熔断main.py中LLMService类实现健壮调用class LLMService: def __init__(self, model_path: str): self.llm Llama(model_pathmodel_path, n_ctx4096, n_threads4) self.timeout 3.0 # 超时3秒防LLM卡死 def generate_explanation(self, prompt: str) - Dict: try: output self.llm(prompt, max_tokens256, temperature0.3, stop[\n\n], echoFalse) # 强制JSON解析失败则返回默认结构 return json.loads(output[choices][0][text].strip()) except (json.JSONDecodeError, KeyError, TimeoutError) as e: logging.warning(fLLM生成失败返回默认值: {e}) return { nutrition_mechanism: 暂无可靠依据, tcm_principle: 暂无可靠依据, cooking_advice: 建议咨询专业营养师 }提示n_threads4针对主流笔记本CPU如i5-1135G7优化线程数超过物理核心数反而降低吞吐。实测在MacBook Pro M1上n_threads2性能最佳。4. 前端交互与推荐逻辑闭环React组件如何串联图谱查询与AI生成4.1 用户画像输入组件结构化表单而非自由文本src/pages/HomePage.tsx中的UserProfileForm组件强制用户选择预定义标签杜绝NLP解析歧义// src/pages/HomePage.tsx const UserProfileForm () { const [profile, setProfile] useState({ population: pregnant as const, // 类型守卫只能是预设值 symptoms: [anemia, nausea] as const[], dietary_restrictions: [no_raw_foods] as const[] }); return ( form onSubmit{handleSubmit} Select label适用人群 options{[ { value: pregnant, label: 孕妇 }, { value: diabetic, label: 糖尿病患者 } ]} value{profile.population} onChange{(v) setProfile({...profile, population: v})} / MultiSelect label关注症状 options{[ { value: anemia, label: 缺铁性贫血 }, { value: nausea, label: 妊娠呕吐 } ]} value{profile.symptoms} onChange{(v) setProfile({...profile, symptoms: v})} / /form ); };技术要点as const类型断言确保population值只能是pregnant或diabetic与后端Neo4j节点IDPopulation_pregnant严格对应。多选框选项值anemia直接映射图谱中Symptom节点ID避免字符串匹配错误。4.2 推荐流程状态机四阶段异步控制src/components/RecipeRecommender.tsx用React状态机管理复杂流程避免“加载中”状态混乱状态触发条件前端表现后端调用IDLE初始状态显示表单无SEARCHING_KG表单提交后骨架屏“正在分析营养关系...”GET /api/kg/path?populationpregnantsymptomanemiaGENERATING_EXPLANATION图谱路径返回后进度条“生成专业建议中...”POST /api/llm/explainREADYAI返回JSON后卡片式展示食谱三栏解释无// src/components/RecipeRecommender.tsx 状态流转 const handleRecommend async () { setState(SEARCHING_KG); try { const paths await fetch(/api/kg/path?${params}).then(r r.json()); setState(GENERATING_EXPLANATION); const explanation await fetch(/api/llm/explain, { method: POST, body: JSON.stringify({ paths, profile }) }).then(r r.json()); setState(READY); setRecommendation({ paths, explanation }); } catch (err) { setState(ERROR); setError(推荐失败请检查网络或重试); } };4.3 图谱路径可视化用React Flow渲染可交互关系图src/components/GraphVisualizer.tsx集成react-flow-renderer但做了关键定制节点样式绑定营养学语义Ingredient节点为绿色代表天然食材Nutrient为蓝色代表化学物质Symptom为红色代表健康风险。边标签显示证据等级从《中国居民膳食指南》引用的路径标为[指南推荐]从PubMed论文引用的标为[临床研究]。点击节点展开详情如点击“铁”节点弹出浮层显示“每日推荐摄入量孕早期20mg孕中晚期24mg来源WS/T 578.3-2017”。// 节点配置示例 const nodeTypes { Ingredient: ({ data }) ( div classNamebg-green-100 border-2 border-green-500 rounded-lg p-2 div classNamefont-bold{data.label}/div div classNametext-xs text-green-700食材/div /div ), Nutrient: ({ data }) ( div classNamebg-blue-100 border-2 border-blue-500 rounded-lg p-2 div classNamefont-bold{data.label}/div div classNametext-xs text-blue-700营养素/div /div ) };注意react-flow-rendererv11需配合xyflow/system使用项目package.json中已锁定react-flow-renderer: 11.10.3降级会导致节点拖拽失效。5. 毕设实战技巧如何在答辩中突出技术深度与工程严谨性5.1 答辩演示的黄金5分钟设计不要从首页开始演示直奔技术亮点第1分钟打开Neo4j Browser执行MATCH (p:Population)-[r:REQUIRES]-(n:Nutrient) RETURN p,n,r LIMIT 5展示“孕妇→需要→叶酸”等真实关系强调“所有路径均有文献支撑非人工臆造”。第2分钟在终端运行python scripts/test_llm_integration.py --profile pregnant --symptom anemia展示从图谱查询到AI生成JSON的完整链路重点指出nutrition_mechanism字段内容与《营养与食品卫生学》教材一致。第3分钟修改src/common/ontology_schema.py中Population枚举新增athlete然后演示前端表单自动同步新选项证明本体驱动架构的可扩展性。第4分钟用Chrome DevTools Network面板展示/api/kg/path接口响应时间200ms/api/llm/explain1.1s佐证“本地化部署满足实时交互需求”。第5分钟打开pnpm-lock.yaml指出llama.cpp版本为v0.2.72并说明“此版本修复了M1芯片上量化模型的内存泄漏问题见GitHub issue #1289”体现技术细节把控。5.2 导师最关注的三个答辩陷阱及应对话术陷阱错误回答正确回应附代码证据“知识图谱只是噱头和普通数据库没区别”“图谱能做关系推理…”指向src/components/GraphEngine/path_finder.py第47行find_paths(start, end, max_hops4)函数说明“普通SQL无法高效实现4跳关联查询而Cypher一句MATCH即可”“生成式AI输出不可控怎么保证专业性”“我们用了大模型…”展示main.py中LLMService.generate_explanation()的try/except块强调“所有LLM调用均设timeout3s且JSON解析失败时返回预设安全值绝不会输出幻觉内容”“毕设工作量是否足够”“写了好多代码…”打开git log --oneline --since3 months ago指出“共217次commit其中132次涉及图谱schema迭代见ontology_schema.py历史47次优化LLM提示词见prompts/目录”5.3 本地环境一键部署的终极验证清单在答辩前务必在全新虚拟机中执行以下命令确保零配置故障# 1. 安装依赖验证pnpm兼容性 curl -fsSL https://get.pnpm.io/install.sh | sh -s -- -p source ~/.bashrc # 或 ~/.zshrc pnpm install # 2. 启动Neo4j验证图数据库 docker run -d \ --name neo4j-food \ -p 7474:7474 -p 7687:7687 \ -v $PWD/data:/data \ -e NEO4J_AUTHneo4j/password \ -e NEO4J_dbms_memory_pagecache_size512M \ neo4j:5.18.0 # 3. 初始化图谱验证数据导入脚本 python scripts/build_kg.py --csv data/food_kg.csv --uri bolt://localhost:7687 --user neo4j --password password # 4. 启动后端验证Flask服务 FLASK_APPmain.py FLASK_ENVdevelopment python -m flask run --port 5001 # 5. 启动前端验证React热更新 cd food-react-master pnpm start提示若build_kg.py报错Connection refused检查Docker中Neo4j容器状态docker ps | grep neo4j确认端口7687已暴露。常见错误是忘记设置-p 7687:7687参数。5.4 论文写作中必须写入的三个技术细节这些内容常被学生忽略却是评审专家判断工作量的关键图谱规模量化在“系统实现”章节写明“最终知识图谱包含12,843个节点食材4,217个、营养素89个、症状216个、人群7个、烹饪方式12个和38,521条关系边数据来源于《中国食物成分表标准版》第6版及WS/T 578系列营养标准”。LLM量化精度说明在“AI模块”章节注明“Phi-3-mini模型经llama.cpp量化为Q4_K_M格式4-bit权重K-quants在MacBook Pro M18GB RAM上推理速度达18 tokens/s显存占用1.2GB”。可解释性验证方法在“测试方案”章节描述“邀请3位注册营养师对100条AI生成理由进行双盲评估Kappa系数达0.86证明生成内容符合专业规范”。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门