5.4.md 3.6 KB

5.4 图存储模块与工程配置

现在图模型已经确定。本节处理一个很实际的问题:老师演示一次,学生再执行一次,数据库里会不会出现两套相同商品?我们希望重复执行仍能得到同一份有效数据,这叫幂等导入。

一、先看“同一个蛋糕”如何被认出来

{{figure:04-import|图 5-7 稳定标识、约束与幂等写入,共同避免重复导入造成重复节点。}}

配套模块 graph_qa/db.py 集中管理 Neo4j。业务代码不应在每个函数里重新创建连接、随手拼一条查询。本节围绕三个动作读代码:建立连接、创建约束、导入资料。

二、配置从一个入口进来

GraphSettings 读取数据库地址与召回预算,模型运行模块读取模型位置。模型位置指向本机已有的完整模型文件夹,程序不需要把权重复制到第五章代码里。

{{snippet:settings}}

这里关注的是配置的职责:Neo4j 地址负责图存储,Milvus 地址负责向量存储,BGE-M3 与重排序器目录负责本地推理。生成服务沿用已有可用服务,和图数据库是两个独立角色。

!!! note "先检查文件是否完整"

“存在一个模型目录”不等于“存在可加载的模型”。目录中还要有主权重与模型配置。本次验证复用同机已经完整下载的模型,通过增强版运行配置指定位置;个人绝对路径不写进课件或公共代码示例。

三、约束:先确定不允许重复的东西

{{snippet:graph-constraints}}

源码里还会看到公共标签 对象,它让连接模块能统一管理商品、食材等不同分类;学生查蛋糕时仍可直接使用 :商品。这只是项目约定,不是数据库强制规定的节点名称。

唯一约束守住节点标识的边界。MERGE 按稳定标识查找已有节点,没有才创建;SET 更新本次数据的属性。关系也需要稳定事实标识与来源,不能每次执行都无条件 CREATE 一条相同事实。

图中的 知识域 属性是隔离条件。配套主店与实验分店都有同名双人下午茶,查询当前店时不能把实验分店的负责人混进答案。

四、导入事务:先写商品与食材,再写它们的关系

{{snippet:graph-import}}

先写节点,再用它们的标识匹配关系两端。真实 Python 源码中的 id、name、scope 是程序数据字段,入库时分别映射为图里的 编号、名称、知识域;它们不是要求学生重新背一套图名称。参数承载数据,查询结构限定允许的关系。导入过程中核对每篇文档的版本和证据;遇到引用缺失时应停止这次导入,不把一个无法追溯的半成品当成完整知识图。

事务让同一批数据库操作遵循明确的提交边界,但 Neo4j 与 Milvus 之间没有天然的共同事务。5.11 会继续讨论两边更新时怎样核对和恢复。

五、重复执行,观察什么才算通过

python -m graph_qa ingest
python -m graph_qa ingest
python -m graph_qa health

第一次导入后记录节点、关系、文本块数量;第二次比较这些数量,并再次查询“招牌蛋糕”。课程验收要看“是否仍是一份有效数据”,不能仅凭第二次命令没有报错就判断幂等成立。

练习:把招牌蛋糕的显示名改变但保留原来的 编号,再导入。关系应该仍然指向同一对象。再想一想:如果直接把名字当主键,改名会造成什么结果?下一节开始处理关系事实的来源,从人工核对的基线进入文档抽取。