一、三元组抽取

1、课程目标

  • 理解知识图谱中的“三元组”概念
  • 掌握三元组与 Neo4j 图数据库之间的对应关系
  • 了解三元组抽取的基本流程
  • 能够从文本中识别实体、关系和属性
  • 能够将抽取结果转换为 Neo4j 可存储的数据结构
  • 能够使用 Cypher 语句创建和查询三元组数据

2、知识图谱与三元组概述

2.1 什么是知识图谱

  • 知识图谱是一种用图结构组织和表达知识的技术。它通过“实体”和“关系”描述现实世界中的对象及其联系

  • 例如:

鲁迅创作了《呐喊》。

  • 可以表示为:
鲁迅 —— 创作 —— 《呐喊》
  • 其中:

    • “鲁迅”是实体

    • “《呐喊》”是实体

    • “创作”是二者之间的关系

2.2 什么是三元组

  • 三元组是知识图谱中最基本的知识表示单元,通常表示为:
(主语, 谓语, 宾语)
  • 也可以称为:
(头实体, 关系, 尾实体)
  • 例如:
(鲁迅, 创作, 呐喊)
(北京, 是首都, 中国)
(姚明, 出生于, 上海)
  • 三元组表达的是一个事实或语义关系

3、三元组与 Neo4j 图模型的对应关系

  • Neo4j 是一种图数据库,数据由节点、关系和属性组成

3.1 Neo4j 的基本结构

Neo4j 概念 含义 示例
节点 Node 表示实体 鲁迅、呐喊、中国
关系 Relationship 表示实体之间的联系 创作、出生于、位于
属性 Property 节点或关系的附加信息 年龄、时间、类型
标签 Label 节点类别 Person、Book、City

3.2 三元组到 Neo4j 的映射

  • 三元组:
(鲁迅, 创作, 呐喊)
  • 在 Neo4j 中可以表示为:
(:Person {name: '鲁迅'})-[:CREATED]->(:Book {name: '呐喊'})
  • 对应关系如下:
三元组部分 Neo4j 结构 示例
主语 起始节点 鲁迅
谓语 关系 创作
宾语 结束节点 呐喊

4、三元组抽取的基本任务

  • 三元组抽取是从非结构化文本中识别实体和实体之间关系的过程

4.1 输入与输出

  • 输入文本:
鲁迅出生于浙江绍兴,创作了小说集《呐喊》。
  • 输出三元组:
(鲁迅, 出生于, 浙江绍兴)
(鲁迅, 创作, 呐喊)
(呐喊, 类型, 小说集)

4.2 三元组抽取的三个核心步骤

  1. 实体识别
  2. 关系识别
  3. 三元组构建

5、实体识别

5.1 实体的定义

  • 实体是文本中具有独立意义的对象,例如:

    • 人名:鲁迅、姚明、爱因斯坦

    • 地名:北京、上海、浙江绍兴

    • 机构名:清华大学、联合国

    • 作品名:呐喊、红楼梦

    • 时间:1881 年、2024 年

5.2 示例

  • 文本:
乔布斯创立了苹果公司。
  • 识别出的实体:
乔布斯
苹果公司
  • 实体类型:
实体 类型
乔布斯 Person
苹果公司 Organization

6、关系识别

6.1 关系的定义

  • 关系描述实体之间的语义联系

  • 常见关系包括:

关系类型 示例
出生于 鲁迅出生于绍兴
创作 鲁迅创作《呐喊》
位于 北京位于中国
任职于 张三任职于某公司
毕业于 李四毕业于清华大学
属于 杭州属于浙江省

6.2 示例

  • 文本:
爱因斯坦出生于德国。
  • 实体:
爱因斯坦
德国
  • 关系:
出生于
  • 三元组:
(爱因斯坦, 出生于, 德国)

7、三元组构建

7.1 构建格式

  • 标准格式:
(主语, 谓语, 宾语)
  • 图数据库格式:
(头实体)-[关系]->(尾实体)

7.2 示例

  • 文本:
清华大学位于北京。
  • 抽取结果:
(清华大学, 位于, 北京)
  • Neo4j 图结构:
(:University {name: '清华大学'})-[:LOCATED_IN]->(:City {name: '北京'})

8、三元组抽取方法

  • 三元组抽取方法大致可以分为以下几类:

    1. 基于规则的方法
    2. 基于机器学习的方法
    3. 基于深度学习的方法
    4. 基于大语言模型的方法

8.1 基于规则的方法

  • 基于规则的方法通过人工设计模板或正则表达式抽取三元组

  • 示例规则:

X 出生于 Y → (X, 出生于, Y)
X 创作了 Y → (X, 创作, Y)
X 位于 Y → (X, 位于, Y)
  • 示例文本:
鲁迅出生于浙江绍兴。
  • 抽取结果:
(鲁迅, 出生于, 浙江绍兴)
  • 优点:

    • 实现简单

    • 可解释性强

    • 适合规则明显的场景

  • 缺点:

    • 泛化能力弱

    • 维护成本高

    • 难以处理复杂句式

8.2 基于机器学习的方法

  • 机器学习方法通常将三元组抽取拆解为分类、序列标注等任务

  • 典型流程:

    1. 标注训练数据
    2. 提取文本特征
    3. 训练实体识别模型
    4. 训练关系分类模型
    5. 输出三元组
  • 优点:

    • 比规则方法更灵活

    • 能处理更多语言变化

  • 缺点:

    • 需要人工标注数据

    • 特征设计成本较高

8.3 基于深度学习的方法

  • 深度学习方法使用神经网络自动学习文本特征

  • 常见模型:

    • BiLSTM-CRF

    • CNN

    • Transformer

    • BERT

    • RoBERTa

  • 常见任务:

    • 命名实体识别 NER

    • 关系分类 Relation Classification

    • 联合抽取 Joint Extraction

  • 优点:

    • 特征自动学习能力强

    • 抽取效果较好

    • 能处理复杂语义

  • 缺点:

    • 需要较多训练数据

    • 模型训练成本高

    • 可解释性较弱

8.4 基于大语言模型的方法

  • 大语言模型可以通过提示词从文本中直接抽取结构化三元组

  • 示例提示词:

请从以下文本中抽取三元组,格式为:
(主语, 谓语, 宾语)

文本:鲁迅出生于浙江绍兴,创作了《呐喊》。
  • 可能输出:
(鲁迅, 出生于, 浙江绍兴)
(鲁迅, 创作, 呐喊)
  • 优点:

    • 使用门槛低

    • 适合快速原型开发

    • 能处理复杂自然语言

  • 缺点:

    • 输出可能不稳定

    • 需要校验抽取结果

    • 对专业领域知识可能存在误差

9、从文本到 Neo4j 的完整流程

9.1 流程图

原始文本
   ↓
文本预处理
   ↓
实体识别
   ↓
关系识别
   ↓
三元组构建
   ↓
实体规范化
   ↓
生成 Cypher 语句
   ↓
写入 Neo4j 图数据库

9.2 示例文本

鲁迅出生于浙江绍兴,创作了小说集《呐喊》。

9.3 抽取结果

(鲁迅, 出生于, 浙江绍兴)
(鲁迅, 创作, 呐喊)
(呐喊, 类型, 小说集)

9.4 Neo4j 建模

  • 节点:
Person: 鲁迅
Place: 浙江绍兴
Book: 呐喊
Category: 小说集
  • 关系:
鲁迅 - 出生于 -> 浙江绍兴
鲁迅 - 创作 -> 呐喊
呐喊 - 类型 -> 小说集

10. 使用 Cypher 创建三元组

10.1 创建节点和关系

MERGE (p:Person {name: '鲁迅'})
MERGE (place:Place {name: '浙江绍兴'})
MERGE (book:Book {name: '呐喊'})
MERGE (category:Category {name: '小说集'})
MERGE (p)-[:BORN_IN]->(place)
MERGE (p)-[:CREATED]->(book)
MERGE (book)-[:HAS_TYPE]->(category);
  • 说明:

    • MERGE 表示如果节点或关系不存在则创建,存在则复用

    • PersonPlaceBookCategory 是节点标签

    • BORN_INCREATEDHAS_TYPE 是关系类型

10.2 查询所有三元组

MATCH (s)-[r]->(o)
RETURN s.name AS 主语, type(r) AS 谓语, o.name AS 宾语;
  • 查询结果示例:
主语 谓语 宾语
鲁迅 BORN_IN 浙江绍兴
鲁迅 CREATED 呐喊
呐喊 HAS_TYPE 小说集

10.3 查询某个实体的关系

MATCH (s {name: '鲁迅'})-[r]->(o)
RETURN s.name AS 主语, type(r) AS 谓语, o.name AS 宾语;

10.4 查询与某个实体相关的所有节点

MATCH (s {name: '鲁迅'})-[r]-(o)
RETURN s, r, o;

11、三元组抽取实践案例

11.1 案例文本

阿里巴巴集团由马云等人于 1999 年在杭州创立。阿里巴巴总部位于杭州。

11.2 实体识别

实体 类型
阿里巴巴集团 Organization
马云 Person
1999 年 Time
杭州 City

11.3 关系识别

主语 关系 宾语
马云 创立 阿里巴巴集团
阿里巴巴集团 创立时间 1999 年
阿里巴巴集团 创立地点 杭州
阿里巴巴集团 总部位于 杭州

11.4 三元组结果

(马云, 创立, 阿里巴巴集团)
(阿里巴巴集团, 创立时间, 1999 年)
(阿里巴巴集团, 创立地点, 杭州)
(阿里巴巴集团, 总部位于, 杭州)

11.5 Neo4j 写入语句

MERGE (jack:Person {name: '马云'})
MERGE (ali:Organization {name: '阿里巴巴集团'})
MERGE (year:Time {name: '1999 年'})
MERGE (hangzhou:City {name: '杭州'})
MERGE (jack)-[:FOUNDED]->(ali)
MERGE (ali)-[:FOUNDED_IN_YEAR]->(year)
MERGE (ali)-[:FOUNDED_IN_PLACE]->(hangzhou)
MERGE (ali)-[:HEADQUARTERED_IN]->(hangzhou);

12、数据清洗与实体规范化

12.1 为什么需要实体规范化

  • 在实际文本中,同一个实体可能有多种写法

  • 例如:

北京
北京市
中国北京
  • 它们可能指向同一个实体。如果不进行规范化,图数据库中会产生重复节点

12.2 常见规范化方法

问题 示例 处理方式
简称与全称 北大 / 北京大学 建立别名表
中英文名称 China / 中国 建立映射表
时间格式不同 1999年 / 1999 年 统一格式
标点差异 《呐喊》 / 呐喊 去除装饰符号
同名实体 苹果公司 / 苹果水果 根据上下文消歧

13、Neo4j 中的建模建议

13.1 标签设计

  • 建议为不同类型实体设置不同标签:
Person
Organization
Place
Book
Event
Time
Concept
  • 这样可以提高查询效率和数据可读性

13.2 关系类型设计

  • Neo4j 的关系类型通常使用英文大写形式:
BORN_IN
CREATED
LOCATED_IN
WORKS_FOR
FOUNDED
HAS_TYPE
  • 不建议频繁使用过长或含义模糊的关系名称

13.3 属性设计

  • 节点属性示例:
(:Person {name: '鲁迅', birthYear: 1881})
  • 关系属性示例:
(:Person {name: '马云'})-[:FOUNDED {year: 1999}]->(:Organization {name: '阿里巴巴集团'})

当某个信息是关系发生的上下文时,可以放在关系属性中。

14、通用信息抽取大模型 PP-UIE

pip install --upgrade paddlenlp==3.0.0b4
pip install paddlepaddle-gpu==3.3.1 -i https://www.paddlepaddle.org.cn/packages/stable/cu126/
# 遇到报错ImportError: cannot import name 'download' from 'aistudio_sdk.hub'安装
pip install aistudio-sdk==0.2.6

14.1 模型简介

  • 通用信息抽取大模型(PP-UIE)是 PaddleNLP 团队基于开源模型和高质量数据集构建的通用信息抽取大模型, PaddleNLP 基于百度 UIE 的建模思路,通过大模型的能力来训练并开源了一款面向中、英文通用信息抽取的大模型。 支持统一训练信息抽取任务包括命名实体识别(NER),关系抽取(RE)和事件抽取(EE)。模型共包含0.5B、1.5B、7B 和14B 共4个版本,以适配不同场景下信息抽取任务使用。在多个数据集(包含 Boson、CLUENER、CCIR2021等常见数据)相比其他通用信息抽取大模型在 ACC 和 F1 指标上有大幅度提升

14.2 开箱即用

  • paddlenlp.Taskflow提供通用信息抽取等能力,可抽取多种类型的信息,包括但不限于命名实体识别(如人名、地名、机构名等)、关系(如电影的导演、歌曲的发行时间等)、事件(如某路口发生车祸、某地发生地震等)等信息。用户可以使用自然语言自定义抽取目标,无需训练即可统一抽取输入文本中的对应信息。实现开箱即用,并满足各类信息抽取需求

14.3 实体抽取

  • 命名实体识别(Named Entity Recognition,简称 NER),是指识别文本中具有特定意义的实体。在开放域信息抽取中,抽取的类别没有限制,用户可以自己定义

  • 例如抽取的目标实体类型是"时间"、"选手"和"赛事名称", schema 构造如下:

['时间', '选手', '赛事名称']
  • 调用示例:
from pprint import pprint
from paddlenlp import Taskflow

# https://github.com/PaddlePaddle/PaddleNLP/tree/develop/llm/application/information_extraction


schema = ['时间', '选手', '赛事名称']
ie = Taskflow('information_extraction',
              schema=['时间', '选手', '赛事名称'],
              schema_lang="zh",
              batch_size=1,
              task_path=r"F:\workspace\AI\PaddleNLP-develop\mytest\taskflow\information_extraction\paddlenlp\PP-UIE-0.5B",
              precision='float16')
pprint(ie("2月8日上午北京冬奥会自由式滑雪女子大跳台决赛中中国选手谷爱凌以188.25分获得金牌!"))
  • 运行结果:
[{'时间': [{'end': 6,
          'probability': np.float64(0.9857490404254179),
          'start': 0,
          'text': '2月8日上午'}],
  '赛事名称': [{'end': 23,
            'probability': np.float64(0.8501996999146968),
            'start': 6,
            'text': '北京冬奥会自由式滑雪女子大跳台决赛'}],
  '选手': [{'end': 31,
          'probability': np.float64(0.8981527213523854),
          'start': 28,
          'text': '谷爱凌'}]}]

14.4 关系抽取

  • 关系抽取(Relation Extraction,简称 RE),是指从文本中识别实体并抽取实体之间的语义关系,进而获取三元组信息,即<主体,谓语,客体>

  • 例如以"竞赛名称"作为抽取主体,抽取关系类型为"主办方"、"承办方"和"时间", schema 构造如下:

{
  '竞赛名称': [
    '主办方',
    '承办方',
    '时间'
  ]
}
  • 调用示例:
from pprint import pprint
from paddlenlp import Taskflow

# https://github.com/PaddlePaddle/PaddleNLP/tree/develop/llm/application/information_extraction


ie = Taskflow('information_extraction',
              schema=['时间', '选手', '赛事名称'],
              schema_lang="zh",
              batch_size=1,
              task_path=r"F:\workspace\AI\PaddleNLP-develop\mytest\taskflow\information_extraction\paddlenlp\PP-UIE-0.5B",
              precision='float16')
schema = {'竞赛名称': ['主办方', '承办方', '时间']}  # Define the schema for relation extraction
ie.set_schema(schema)  # Reset schema
pprint(
    ie('2022年语言与智能技术竞赛由中国中文信息学会和中国计算机学会联合主办,百度公司、中国中文信息学会评测工作委员会和中国计算机学会自然语言处理专委会承办,已连续举办4届,成为全球最热门的中文NLP赛事之一。'))
  • 运行结果:
[{'竞赛名称': [{'end': 14,
            'probability': np.float64(0.7929611124806826),
            'relations': {'主办方': [{'end': 23,
                                   'probability': np.float64(0.8373886002106978),
                                   'start': 15,
                                   'text': '中国中文信息学会'},
                                  {'end': 31,
                                   'probability': np.float64(0.7489374664714887),
                                   'start': 24,
                                   'text': '中国计算机学会'}],
                          '承办方': [{'end': 73,
                                   'probability': np.float64(0.6136097663045561),
                                   'start': 57,
                                   'text': '中国计算机学会自然语言处理专委会'},
                                  {'end': 40,
                                   'probability': np.float64(0.8367675075299132),
                                   'start': 36,
                                   'text': '百度公司'},
                                  {'end': 56,
                                   'probability': np.float64(0.6986279377475739),
                                   'start': 41,
                                   'text': '中国中文信息学会评测工作委员会'}]},
            'start': 0,
            'text': '2022年语言与智能技术竞赛'}]}]

14.5 模型选择

  • 多模型选择,满足精度、速度要求
模型 结构 语言
paddlenlp/PP-UIE-0.5B 24-layers, 896-hidden, 14-heads 中、英文
paddlenlp/PP-UIE-1.5B 28-layers, 1536-hidden, 12-heads 中、英文
paddlenlp/PP-UIE-7B 28-layers, 3584-hidden, 28-heads 中、英文
paddlenlp/PP-UIE-14B 48-layers, 5120-hidden, 40-heads 中、英文

14.6 更多配置

from paddlenlp import Taskflow

ie = Taskflow('information_extraction',
                  schema = {'竞赛名称': ['主办方', '承办方', '时间']},
                  schema_lang="zh",
                  batch_size=1,
                  model='paddlenlp/PP-UIE-0.5B',
                  precision='float16')
  • schema:定义任务抽取目标,可参考开箱即用中不同任务的调用示例进行配置。
  • schema_lang:设置 schema 的语言,默认为zh, 可选有zhen。因为中英 schema 的构造有所不同,因此需要指定 schema 的语言
  • batch_size:批处理大小,请结合机器情况进行调整,默认为1
  • model:选择任务使用的模型,可选有paddlenlp/PP-UIE-0.5B, paddlenlp/PP-UIE-1.5B, paddlenlp/PP-UIE-7B, paddlenlp/PP-UIE-14B
  • precision:选择模型精度,默认为float16,可选有float16bfloat16float32和。如果选择float16,在 GPU 硬件环境下,请先确保机器正确安装 NVIDIA 相关驱动和基础软件,确保 CUDA>=11.2,cuDNN>=8.1.1,初次使用需按照提示安装相关依赖。其次,需要确保 GPU 设备的 CUDA 计算能力(CUDA Compute Capability)大于7.0,典型的设备包括 V100、T4、A10、A100、GTX 20系列和30系列显卡等。如果选择bfloat16,能有效加速处理大模型和批量数据,尤其与混合精度结合使用时性能表现更优。但需确保硬件和软件环境支持该精度。支持 bfloat16的硬件包括 NVIDIA A100 和 H800 GPU,同时需要确保使用 CUDA>=11.2、cuDNN>=8.1.1 等软件环境。更多关于 CUDA Compute Capability 和精度支持情况请参考 NVIDIA 文档:GPU 硬件与支持精度对照表

15、常见问题

15.1 主语和宾语如何确定

  • 一般来说:

    • 动作发出者作为主语

    • 动作承受者作为宾语

    • 所属关系中,被描述对象通常作为主语

  • 例如:

鲁迅创作《呐喊》
  • 三元组:
(鲁迅, 创作, 呐喊)

15.2 属性应该作为节点还是属性

  • 这取决于查询需求

  • 如果该信息需要与其他实体建立关系,可以建成节点

(鲁迅, 出生地, 绍兴)
  • 如果该信息只是实体的简单描述,可以作为属性:
(:Person {name: '鲁迅', birthPlace: '绍兴'})

15.3 是否所有文本都能抽取出三元组

  • 不是。以下情况可能难以直接抽取:

    • 语义模糊

    • 指代不清

    • 省略主语

    • 句子过长

    • 包含隐含关系

  • 例如:

他后来去了那里。
  • 如果没有上下文,就无法确定“他”和“那里”分别指谁

16、课堂练习

16.1 练习一:基础抽取

  • 请从下面文本中抽取三元组:
姚明出生于上海,曾效力于休斯顿火箭队。
  • 参考答案:
(姚明, 出生于, 上海)
(姚明, 效力于, 休斯顿火箭队)

16.2 练习 2:转换为 Cypher

  • 请将以下三元组转换为 Cypher:
(北京, 是首都, 中国)
  • 参考答案:
MERGE (beijing:City {name: '北京'})
MERGE (china:Country {name: '中国'})
MERGE (beijing)-[:IS_CAPITAL_OF]->(china);

16.3 练习 3:复杂文本抽取

  • 文本:
华为技术有限公司成立于 1987 年,总部位于深圳,创始人为任正非。
  • 参考答案:
(华为技术有限公司, 成立时间, 1987 年)
(华为技术有限公司, 总部位于, 深圳)
(任正非, 创立, 华为技术有限公司)

17、小结

  • 三元组是知识图谱的基本表达形式
  • 三元组格式为 (主语, 谓语, 宾语)
  • Neo4j 使用节点和关系存储三元组
  • 三元组抽取包括实体识别、关系识别和三元组构建
  • 抽取结果可以通过 Cypher 写入 Neo4j
  • 实体规范化和关系设计会直接影响图数据库质量