5.5.md 3.8 KB

5.5 从企业文档构建知识图谱

现在我们拿到的是一张配方,上面写着“招牌蛋糕需要草莓酱作为夹层。” 人可以圈出蛋糕、果酱和“需要”;程序也要完成这一步,并保留原句供核对。

{{figure:05-build|图 5-8 从配方原句提取已知对象之间的关系,先校验、再审核。}}

一、先分开“对象目录”和“从原文提关系”

小店先维护好有哪些东西:新鲜草莓、草莓酱、招牌蛋糕、套餐、店员。它们放在 entities.json。这一版抽取器在这些已知对象之间找明确关系,不负责自动发现任意新对象。

人工逐条核对的配方事实是问答实验基线。大模型抽取是练习另一种建图输入:它提出候选,校验格式和来源后仍要审核。这样学生能分清“配方理解错了”和“配方正确但检索没找到”,不把两种误差混在一起。

二、一条关系记录,哪些字段不能少

下面把配套的一条套餐关系记录,映射为便于阅读的中文字段。它与实际文件是同一条事实:

{{fixture:tea-fact}}

先读中文记录:双人下午茶“包含”招牌蛋糕,并注明依据来自哪句原文。写入 Neo4j 后,箭头类型就叫 包含,不能因为都在影响链上就把每条边都写成 需要。

配套 JSON 文件是程序交换数据的接口,仍保留固定字段名:subject 对应左边节点编号,object 对应右边节点编号,relation 对应关系,chunk_id 对应原文编号,evidence_quote 对应引用原句。导入模块负责把这些接口字段转换成图中的中文命名;上面展示的是同一记录的中文读法,不是要求复制覆盖 JSON 文件。

三、合法 JSON 不等于读懂配方

设想抽取器把“巧克力饼干不使用草莓”读成“饼干需要草莓”,格式仍可以完全正确,业务含义却相反。先看代码做了哪些有限检查:

{{snippet:validate-extraction}}

它检查对象是否在当前目录、关系是否被允许、引用是否是原文中的连续内容。原句存在,只能证明能够定位来源,不能自动证明关系方向和含义正确。 因此还要拿原句和候选关系逐项比较。

四、把模型约束在这套资料内

{{snippet:llm-extract}}

提示给出已知对象和允许的关系,要求只提取明确表达的事实,不能把否定句变成肯定关系。模型输出后先解析、校验,并保存为待审核文件,不自动写入图。

python -m graph_qa extract \
  --chunk-id recipe-cake:v1:c01 \
  --output ../../验证结果/extracted-cake.json

review_required 表示需要审核。学生应核对主语是招牌蛋糕,关系是需要,宾语是草莓酱,原句来自蛋糕配方。审核通过后再并入事实数据,经正常导入链路写入。

本次真实生成服务已返回如下候选,这里按中文名称展示(经结构与原文校验,仍保留待审核标记):

招牌蛋糕  — 需要 →  草莓酱
原句:制作招牌蛋糕需要草莓酱

它只抽取原句明确表达的一步,不把“蛋糕间接需要草莓”的多跳结论另写成一条直接关系。完整输出保存在配套验证结果 extracted-cake.json。

五、用三个日常句子检查是否真的理解

原句表达的意思 应画出的关系
招牌蛋糕需要草莓酱作为夹层 蛋糕 → 需要 → 果酱
双人下午茶包含招牌蛋糕 套餐 → 包含 → 蛋糕
巧克力饼干不使用草莓 不能画成饼干 → 需要 → 草莓

这三种表达都很容易懂,技术难点却不同:关系类型、方向与否定。完成本节后,学生应能为每一条边说出“原文为什么支持它”。下一节处理顾客和配方对同一东西使用不同叫法的情况。