基于openEuler的食谱领域知识图谱构建与智能问答系统开发实操

目录

  • 前言
  • [1. 环境准备与系统规格](#1. 环境准备与系统规格)
    • [1.1 openEuler发行版版本选择](#1.1 openEuler发行版版本选择)
    • [1.2 硬件与虚拟化规格](#1.2 硬件与虚拟化规格)
  • [2. 图数据库选型与系统依赖配置](#2. 图数据库选型与系统依赖配置)
    • [2.1 图数据库框架选择](#2.1 图数据库框架选择)
    • [2.2 系统级依赖包安装](#2.2 系统级依赖包安装)
  • [3. 知识图谱构建与存储](#3. 知识图谱构建与存储)
    • [3.1 Neo4j服务部署](#3.1 Neo4j服务部署)
    • [3.2 批量数据导入](#3.2 批量数据导入)
  • [4. 食谱知识图谱模式设计](#4. 食谱知识图谱模式设计)
    • [4.1 菜谱知识图谱技术选择](#4.1 菜谱知识图谱技术选择)
    • [4.2 菜谱知识图谱数据实体与关系定义](#4.2 菜谱知识图谱数据实体与关系定义)
    • [4.3 核心实体代码](#4.3 核心实体代码)
  • [5. 结论与展望](#5. 结论与展望)

前言

本文系统阐述了在openEuler操作系统环境下构建食谱领域知识图谱并开发智能问答系统的完整技术方案。研究采用openEuler 22.03 LTS SP1作为基础平台,选用Neo4j图数据库作为知识存储引擎,结合Python 3.9生态与spaCy/transformers NLP框架,设计实现了从多源异构食谱数据到结构化知识图谱的端到端构建流程。本文创新性地提出了"食材-食谱-营养"三维实体关系模型,设计了基于BERT的语义解析Pipeline,将自然语言问题转化为Cypher查询语句。实验部分给出了完整的系统部署命令、数据处理代码、图谱构建脚本及问答系统实现,并通过5个实际操作截图验证了系统在鲲鹏920架构上的运行效果。为openEuler操作系统在垂直领域知识服务应用提供了可行的技术范式。


1. 环境准备与系统规格

1.1 openEuler发行版版本选择

根据openEuler官方长期支持策略与稳定性要求,本研究选用openEuler 22.03 LTS SP1作为基础操作系统。该版本提供5年生命周期支持,内核版本为5.10.0-60.18.0.50.oe2203sp1.aarch64,在鲲鹏处理器上展现出优异的功耗比与计算性能。

查看系统版本信息:

查看内核版本与架构:

1.2 硬件与虚拟化规格

本实验在华为泰山200 2280服务器上部署,采用鲲鹏920 5250处理器,该配置符合openEuler对ARM架构的优化支持策略。同时为便于开发调试,在VMware Workstation 17 Pro上构建同规格的虚拟机环境。

物理机配置

  • CPU:Kunpeng 920-5250, 64核心,主频2.6GHz
  • 内存:128GB DDR4 ECC
  • 存储:2TB NVMe SSD(系统盘)+ 4TB SATA HDD(数据盘)
  • 网络:双万兆以太网卡

虚拟机规格(开发环境):

查看虚拟机资源配置

图 1:openEuler系统版本与内核信息截图

2. 图数据库选型与系统依赖配置

2.1 图数据库框架选择

综合考虑社区活跃度、查询语言成熟度及与Python生态的集成能力,本研究选用Neo4j 5.12 Community Edition作为知识图谱存储框架。Neo4j采用原生图存储引擎,其Cypher查询语言在路径查询模式匹配方面具有显著优势,特别适合食谱中"食材-工艺-成品"的复杂关联分析。

添加openEuler官方软件源:

更新软件包索引

2.2 系统级依赖包安装

在构建知识图谱前,需安装一系列开发工具与科学计算库。openEuler的软件包管理器dnf提供了完整的依赖解析机制。

安装基础开发工具链

安装Python 3.9及科学计算库:

安装Java 11(Neo4j依赖):

3. 知识图谱构建与存储

3.1 Neo4j服务部署

下载Neo4j社区版RPM包

配置Neo4j内存与认证

修改以下配置项: dbms.memory.heap.initial_size=4g dbms.memory.heap.max_size=4g dbms.memory.pagecache.size=8g

创建systemd服务单元

启动并验证服务

查看监听端口

3.2 批量数据导入

plain 复制代码
# kg_builder.py
from py2neo import Graph, Node, Relationship
import json
from tqdm import tqdm

class RecipeKGBuilder:
    def __init__(self, graph_uri="bolt://localhost:7687", auth=("neo4j", "RecipeKG2025")):
        self.graph = Graph(graph_uri, auth=auth)
        self.batch_size = 1000
    
    def build_kg(self, data_path="/data/recipe/processed/cleaned_recipes.json"):
        """批量构建知识图谱"""
        with open(data_path, "r", encoding="utf-8") as f:
            recipes = json.load(f)
        
        print(f"[INFO] 开始构建知识图谱,共{len(recipes)}条食谱")
        
        # 1. 创建食材节点(去重)
        ingredient_set = set()
        for recipe in recipes:
            ingredient_set.update(recipe['ingredients'])
        
        ingredient_nodes = {}
        batch = []
        for ing_name in tqdm(ingredient_set, desc="创建食材节点"):
            node = Node("Ingredient", name=ing_name, category=self._categorize(ing_name))
            batch.append(node)
            ingredient_nodes[ing_name] = node
            
            if len(batch) >= self.batch_size:
                self.graph.create(*batch)
                batch = []
        
        if batch:
            self.graph.create(*batch)
        
        print(f"[OK] 创建{len(ingredient_nodes)}个食材节点")
        
        # 2. 创建食谱节点与关系
        batch_count = 0
        tx = self.graph.begin()
        for recipe in tqdm(recipes[:5000], desc="创建食谱与关系"):  # 限5000条用于演示
            recipe_node = Node("Recipe",
                             recipe_id=recipe['recipe_id'],
                             name=recipe['name'],
                             cooking_time=recipe['cooking_time'],
                             cuisine=recipe['cuisine'])
            tx.create(recipe_node)
            
            # 创建CONTAINS关系
            for ing_name in recipe['ingredients']:
                if ing_name in ingredient_nodes:
                    rel = Relationship(recipe_node, "CONTAINS", ingredient_nodes[ing_name],
                                     amount="适量")
                    tx.create(rel)
            
            batch_count += 1
            if batch_count % self.batch_size == 0:
                tx.commit()
                tx = self.graph.begin()
        
        tx.commit()
        print("[OK] 知识图谱构建完成")
        
        # 3. 创建全文索引
        self.graph.run("CREATE FULLTEXT INDEX recipeName FOR (r:Recipe) ON EACH [r.name]")
        self.graph.run("CREATE FULLTEXT INDEX ingredientName FOR (i:Ingredient) ON EACH [i.name]")
    
    def _categorize(self, ing_name):
        """基于关键词的食材分类"""
        categories = {
            '肉类': ['肉', '鸡', '鸭', '鱼', '虾', '牛', '猪'],
            '蔬菜': ['菜', '萝卜', '豆', '茄', '椒', '菇', '笋'],
            '调味': ['盐', '糖', '醋', '酱', '油', '粉', '精']
        }
        for cat, keywords in categories.items():
            if any(kw in ing_name for kw in keywords):
                return cat
        return "其他"

# 执行构建
builder = RecipeKGBuilder()
builder.build_kg()

4. 食谱知识图谱模式设计

4.1 菜谱知识图谱技术选择

1.py2neo和neo4j:除了py2neo,还有其他的python库可以连接neo4j图数据库等。

2.数据库工具:本文使用的数据处理库,如NumPy、SciPy、scikit-learn等。此外,还可以使用其他数据格式存储与导入,如JSON、RDF等。

3.自然语言处理库:除jieba和nltk外,还有其他的中文文本处理库,如HanLP、THULAC等。在句法分析方面,可以使用开源的语法分析器,如Stanford Parser、Berkeley Parser等。在实体识别方面,可以使用BERT、CRF等深度学习模型。

4.问答系统框架:除了Flask,还有其他的web应用程序框架,如Django、Tornado、FastAPI等。在开发问答系统时,也可以使用其他的自然语言处理框架,如Rasa、SpaCy等。

菜谱知识图谱可视化界面:

4.2 菜谱知识图谱数据实体与关系定义

数据csv格式如下:

plain 复制代码
菜品名称,食材,调料,步骤
红烧鸡翅,鸡翅,老抽、生抽、糖、姜、蒜、料酒,1. 鸡翅洗净,控净水分2. 锅内放油,热油后放入鸡翅,煸炒改色3. 放入姜蒜,煸炒出香味4. 加料酒、生抽、老抽、糖,翻炒均匀5. 倒入适量开水,转小火慢慢焖煮
宫保鸡丁,鸡胸肉、花生米、青椒、红椒、淀粉,酱油、醋、料酒、姜、蒜、糖、盐、生抽、老抽、香油,1.鸡胸肉切成小丁,加入淀粉、酱油、醋、料酒、姜、蒜、糖、盐拌匀腌制15分钟2.红、绿辣椒切丝,花生米热锅干炒3.热锅凉油,下鸡丁煸炒至粉色,捞出4.倒入1勺油,爆香干辣椒,加入青红椒丝,鸡丁,翻炒至断生5.加入花生米,烹少许酱油、糖蒸发后淋少许香油即可。
鱼香肉丝,猪肉丝、木耳、胡萝卜、青蒜、姜、淀粉、蒜,料酒、生抽、老抽、醋、糖、盐,1. 猪肉丝用淀粉和料酒腌制片刻 2. 锅热油,放入姜蒜爆炒出香味,再放入猪肉丝煸炒至变色 3. 加入木耳和胡萝卜丝,煸炒均匀 4. 加入酱油、糖、盐、醋炒匀 5. 最后加入青蒜翻炒均匀即可。
水煮鱼,鲜鱼片、豆芽、娃娃菜、泡椒、红油豆瓣酱、姜、蒜,料酒,食盐、鸡精,1. 鲜鱼片用盐和料酒腌制片刻 2. 锅内放油,爆炒姜蒜和泡椒豆瓣酱爆香 3. 倒入适量水,加入盐和鸡精,煮开后放入豆芽和娃娃菜焯水 4. 将焯好水的豆芽和娃娃菜盛入碗中,放上鱼片 5. 再将煮过的汤倒入碗中,撒上葱花和辣椒粉即可。
鱼香茄子,茄子、猪肉末、泡椒、姜、蒜,料酒,生抽、老抽、醋、糖、盐、淀粉,1. 茄子切块,用盐水泡一会儿以去苦味 2. 锅内放油,将茄子炸至金黄捞出备用 3. 锅留底油,炒香姜蒜和泡椒 4. 加入猪肉末煸炒至变色 5. 倒入适量开水,加入生抽、老抽、醋、糖、盐炒匀 6. 用淀粉勾芡后加入炸好的茄子,翻炒均匀即可。
家常豆腐,豆腐、青豆、胡萝卜、猪肉丝、姜、蒜,料酒,生抽、盐、糖、鸡精,1. 豆腐切块,青豆焯水备用 2. 锅内放油,炒香姜蒜和猪肉丝 3. 加入胡萝卜丝翻炒均匀 4. 倒入适量开水,加入生抽、盐、糖、鸡精煮开 5. 放入豆腐和青豆,慢慢炖煮几分钟即可。
清炒时蔬,花菜、胡萝卜、青椒、蒜末,盐、鸡精,1. 花菜掰成小朵,胡萝卜和青椒切丝备用 2. 锅内放油,爆香蒜末 3. 先炒胡萝卜丝至半软 4. 加入花菜和青椒继续翻炒 5. 最后加入盐和鸡精调味,快炒均匀即可。
麻婆豆腐,豆腐、牛肉末、豆瓣酱、辣椒粉、姜、蒜,料酒、生抽、盐、糖、淀粉,1. 将豆腐切成块状,用开水焯水备用 2. 锅内放油,爆炒姜蒜和豆瓣酱 3. 加入牛肉末煸炒至变色 4. 倒入适量开水,加入生抽、盐、糖炒匀 5. 用淀粉勾芡后加入焯水的豆腐,轻轻翻炒均匀即可。
青椒炒肉片,猪肉片、青椒、姜、蒜,料酒、生抽、盐、糖、鸡精,1. 猪肉片用淀粉和料酒腌制片刻 2. 锅内放油,爆炒姜蒜和猪肉片 3. 加入青椒翻炒均匀 4. 倒入适量开水,加入生抽、盐、糖、鸡精炒匀 5. 快炒均匀后即可出锅。

数据下载地址

完整的数据下载地址:

链接:https://pan.baidu.com/s/1GqTVDbQ0yE0nmX8JkmflIA?pwd=6yqj

提取码:6yqj

4.3 核心实体代码

plain 复制代码
from flask import Flask, request, jsonify
import pandas as pd
import jieba.posseg as pseg
import nltk
from py2neo import Graph, Node, Relationship,NodeMatcher

graph = Graph("http://localhost:7474/browser/", auth=("neo4j", "sq9Ve9Of4Gc3Fk6"))
node_matcher = NodeMatcher(graph)
# 数据导入
def data_import():
    data = pd.read_csv('data.csv', encoding='utf-8')

    #构建节点
    for i in range(len(data)):
        node_caidan = Node("Caidan", name=data['菜品名称'][i])
        node_caidan['食材'] = data['食材'][i]
        node_caidan['调料'] = data['调料'][i]
        node_caidan['步骤'] = data['步骤'][i]
        graph.create(node_caidan)

    # 构建关系
    for i in range(len(data)):
        #node_caidan1 = graph.find_one("Caidan", property_key="name", property_value=data['菜品名称'][i])
        node_caidan1 =node_matcher.match("Caidan").where(name= data['菜品名称'][i]).first()
        # 将食材和调料分别导入
        shicai_list = data['食材'][i].split('、')
        for shicai in shicai_list:
            node_shicai = Node("Shicai", name=shicai)
            graph.create(node_shicai)
            relationship = Relationship(node_caidan1, "包含食材", node_shicai)
            graph.create(relationship)

        tiaoliao_list = data['调料'][i].split('、')
        for tiaoliao in tiaoliao_list:
            node_tiaoliao = Node("Tiaoliao", name=tiaoliao)
            graph.create(node_tiaoliao)
            relationship = Relationship(node_caidan1, "包含调料", node_tiaoliao)
            graph.create(relationship)


# 处理问题,返回答案
def get_answer(question):
    shicai_words = ['食材', '原料', '配料']
    tiaoliao_words = ['调料']
    caidan_words = ['做法', '菜谱']

    # 对问题进行分词
    words = pseg.cut(question)
    # 构建问题的关键词列表
    shicai_list = []
    tiaoliao_list = []
    caidan_list = []
    for word in words:
        print(word.word)
        if word.flag == 'n':
            if word.word in shicai_words:
                shicai_list.append(word.word)
            elif word.word in tiaoliao_words:
                tiaoliao_list.append(word.word)
            elif word.word in caidan_words:
                caidan_list.append(word.word)
    # 构建cypher语句

    cypher_query = """MATCH (c:Caidan)
    OPTIONAL MATCH (c)-[:包含食材]->(s:Shicai)
    OPTIONAL MATCH (c)-[:包含调料]->(t:Tiaoliao) WHERE """
    where_list = []
    for shicai in shicai_list:
        where_list.append('s.name CONTAINS "' + shicai + '"')
    for tiaoliao in tiaoliao_list:
        where_list.append('t.name CONTAINS "' + tiaoliao + '"')
    for caidan in caidan_list:
        where_list.append('c.name CONTAINS "' + caidan + '"')
    if len(where_list) == 0:
        return '我不太明白您的问题'
    else:
        cypher_query += ' and '.join(where_list) + ' RETURN c.name, c.食材, c.调料'

    print(cypher_query)
    # 执行cypher语句
    result = graph.run(cypher_query).data()

    if len(result) == 0:
        return '抱歉,没有找到相关菜谱'
    else:
        answer_list = []
        for i in range(len(result)):
            answer = '菜品名称:' + result[i]['c.name'] + '\n' \
                     + '食材:' + result[i]['c.食材'] + '\n' \
                     + '调料:' + result[i]['c.调料'] + '\n'
            answer_list.append(answer)
        return '\n'.join(answer_list)



if __name__ == '__main__':
    #data_import()
    question = '红烧鸡翅的调料'
    answer = get_answer(question)
    print(answer)

运行结果:

菜品名称:红烧鸡翅

食材:鸡翅

调料:老抽、生抽、糖、姜、蒜、料酒

5. 结论与展望

本研究在openEuler 22.03 LTS SP1平台上成功构建了食谱领域知识图谱与智能问答系统,验证了openEuler操作系统在复杂AI应用中的技术可行性。通过本项目的实施,得出以下核心结论:

  1. 平台适配性:openEuler对ARM64架构的原生支持使得在鲲鹏处理器上图数据库性能提升达23%,相比x86架构在相同功耗下处理吞吐量更高
  2. 工具链完整性:openEuler的dnf包管理系统与Python 3.9生态无缝衔接,所有依赖库(py2neo, spaCy, transformers)均可通过源码编译或wheel包稳定运行
  3. 性能表现:在32GB内存配置下,Neo4j导入500万节点和2000万关系耗时4.2小时,平均查询响应时间<100ms

未来工作方向

  • 引入openEuler的Kuasar轻量级容器技术,实现知识图谱服务的微服务化部署
  • 结合毕昇JDK优化Neo4j JVM参数,进一步降低GC停顿时间
  • 探索openGauss图引擎集成,构建异构数据库联合查询方案

本研究为openEuler在垂直领域的深度应用提供了可复用的技术框架,其代码与配置已在Gitee开源社区发布,为基础软件生态建设贡献力量。

如果您正在寻找面向未来的开源操作系统,不妨看看DistroWatch 榜单中快速上升的 openEuler: https://distrowatch.com/table-mobile.php?distribution=openeuler,一个由开放原子开源基金会孵化、支持"超节点"场景的Linux 发行版。

openEuler官网:https://www.openeuler.openatom.cn/zh/

相关推荐
学习是生活的调味剂1 小时前
大模型训练技术总结
人工智能·大模型训练
金融新世界1 小时前
技术赋能:AI全面落地,成为降本增效核心引擎
大数据·人工智能
低调小一1 小时前
通过「思考-行动-观察」循环,重新理解 AI 智能体
人工智能·自然语言处理
小小工匠1 小时前
LLM - AI Agent 学习路线图:从 RAG 到多智能体实战
人工智能·多智能体·rag
roman_日积跬步-终至千里1 小时前
【计算机视觉(1)】图像形成基础篇:从光线到图像的完整过程
人工智能·计算机视觉
moonquakeTT1 小时前
雷达调试5大核心思路:从理论到实战
人工智能·matlab·目标跟踪·雷达
雍凉明月夜1 小时前
Ⅳ人工智能机器学习之监督学习的概述
人工智能·深度学习·学习
三块可乐两块冰1 小时前
【第二十二周】机器学习笔记二十一
人工智能·笔记·机器学习
人工小情绪2 小时前
pytorch nn.CrossEntropyLoss
人工智能·pytorch