知识图谱自动构建:NER、关系抽取、实体链接
原创
灵阙教研团队
S 精选 进阶 |
约 10 分钟阅读
更新于 2026-02-28 AI 导读
知识图谱自动构建:NER、关系抽取、实体链接 知识图谱的构建从手工编辑走向自动化是降低成本、扩大规模的关键。本文系统介绍知识图谱自动构建的三大核心任务——命名实体识别(NER)、关系抽取(RE)、实体链接(EL)——的技术方法、LLM增强方案与工程实践。 一、知识图谱构建流水线 1.1 全流程概览 非结构化文本 → 知识图谱的自动构建流水线: 原始文本 │ ▼ ┌──────────────┐...
知识图谱自动构建:NER、关系抽取、实体链接
知识图谱的构建从手工编辑走向自动化是降低成本、扩大规模的关键。本文系统介绍知识图谱自动构建的三大核心任务——命名实体识别(NER)、关系抽取(RE)、实体链接(EL)——的技术方法、LLM增强方案与工程实践。
一、知识图谱构建流水线
1.1 全流程概览
非结构化文本 → 知识图谱的自动构建流水线:
原始文本
│
▼
┌──────────────┐
│ 1. 文本预处理 │ 分句、分词、清洗
└──────────────┘
│
▼
┌──────────────┐
│ 2. 命名实体识别│ 识别人名、地名、机构名等
│ (NER) │ 输出: [(实体, 类型, 位置)]
└──────────────┘
│
▼
┌──────────────┐
│ 3. 关系抽取 │ 识别实体间的语义关系
│ (RE) │ 输出: [(实体1, 关系, 实体2)]
└──────────────┘
│
▼
┌──────────────┐
│ 4. 实体链接 │ 将提及映射到知识库实体
│ (EL) │ 输出: [提及 → KB实体ID]
└──────────────┘
│
▼
┌──────────────┐
│ 5. 知识融合 │ 去重、冲突消解、置信度
└──────────────┘
│
▼
知识图谱 (Neo4j / RDF Store)
1.2 数据源类型
| 数据源 | 结构化程度 | 抽取难度 | 典型示例 |
|---|---|---|---|
| 结构化数据 | 高 | 低 | 数据库、CSV、表格 |
| 半结构化数据 | 中 | 中 | JSON、XML、HTML |
| 非结构化文本 | 低 | 高 | 新闻、报告、论文 |
| 多模态数据 | 低 | 极高 | 图片、视频、音频 |
二、命名实体识别(NER)
2.1 方法演进
NER技术发展:
规则方法 (1990s-2000s)
├── 正则表达式 + 字典匹配
├── 手工规则 + 上下文模板
└── 优势:可控性强;劣势:扩展性差
统计方法 (2000s-2010s)
├── HMM(隐马尔可夫模型)
├── CRF(条件随机场)
├── 最大熵模型
└── 优势:数据驱动;劣势:特征工程繁重
深度学习 (2015-2020)
├── BiLSTM-CRF
├── CNN-CRF
├── BERT + Token Classification
└── 优势:端到端学习;劣势:需要标注数据
LLM时代 (2023+)
├── In-context Learning (Few-shot NER)
├── 指令微调 NER
├── LLM + 传统NER混合
└── 优势:零/少样本;劣势:速度与成本
2.2 BERT-based NER实现
from transformers import AutoTokenizer, AutoModelForTokenClassification
from transformers import pipeline
import torch
# 加载预训练NER模型
model_name = "dslim/bert-base-NER"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForTokenClassification.from_pretrained(model_name)
# 使用Pipeline简化调用
ner_pipeline = pipeline(
"ner",
model=model,
tokenizer=tokenizer,
aggregation_strategy="simple" # 合并子词token
)
# 执行NER
text = "Apple CEO Tim Cook announced the new iPhone at the Steve Jobs Theater in Cupertino."
results = ner_pipeline(text)
for entity in results:
print(f" {entity['word']:20s} | {entity['entity_group']:5s} | "
f"score={entity['score']:.3f} | "
f"pos=[{entity['start']}, {entity['end']}]")
# 输出:
# Apple | ORG | score=0.998 | pos=[0, 5]
# Tim Cook | PER | score=0.999 | pos=[10, 18]
# iPhone | MISC | score=0.987 | pos=[37, 43]
# Steve Jobs Theater | LOC | score=0.965 | pos=[51, 70]
# Cupertino | LOC | score=0.998 | pos=[74, 83]
2.3 LLM-based NER
# 使用LLM进行零样本NER
def llm_ner(text, entity_types, llm_client):
prompt = f"""从以下文本中提取命名实体。
实体类型: {', '.join(entity_types)}
文本: {text}
请以JSON格式输出,格式为:
[{{"entity": "实体文本", "type": "实体类型", "start": 起始位置, "end": 结束位置}}]
只输出JSON,不要其他内容。"""
response = llm_client.generate(prompt)
return json.loads(response)
# 调用
entities = llm_ner(
text="华为创始人任正非在深圳总部发布了新款Mate系列手机",
entity_types=["人物", "组织", "地点", "产品"],
llm_client=client
)
# 预期输出:
# [
# {"entity": "华为", "type": "组织", "start": 0, "end": 2},
# {"entity": "任正非", "type": "人物", "start": 5, "end": 8},
# {"entity": "深圳", "type": "地点", "start": 9, "end": 11},
# {"entity": "Mate系列手机", "type": "产品", "start": 16, "end": 23}
# ]
2.4 NER评估指标
| 指标 | 计算方式 | 说明 |
|---|---|---|
| Precision | TP / (TP + FP) | 识别结果中正确的比例 |
| Recall | TP / (TP + FN) | 应识别实体中被正确找到的比例 |
| F1 | 2 * P * R / (P + R) | 精确率与召回率的调和平均 |
| Exact Match | 边界和类型都正确 | 严格评估 |
| Partial Match | 部分重叠即可 | 宽松评估 |
三、关系抽取(RE)
3.1 任务定义
输入: 文本 + 实体对
输出: 实体间的关系类型
示例:
文本: "任正非创立了华为公司,总部位于深圳。"
实体对: (任正非, 华为公司)
输出: 创始人(founder)
实体对: (华为公司, 深圳)
输出: 总部所在地(headquartered_in)
3.2 方法分类
关系抽取方法:
1. 管道式(Pipeline)
先NER → 再RE
优势: 模块化,各环节可独立优化
劣势: 错误传播
2. 联合抽取(Joint Extraction)
同时识别实体和关系
优势: 避免错误传播,共享信息
劣势: 模型更复杂
3. 远程监督(Distant Supervision)
利用已有知识库自动标注训练数据
优势: 无需人工标注
劣势: 噪声标签
4. LLM提示式
直接用LLM抽取三元组
优势: 零样本、灵活
劣势: 速度慢、成本高
3.3 LLM驱动的关系抽取
def extract_relations(text, llm_client, relation_types=None):
"""使用LLM从文本中抽取关系三元组"""
relation_hint = ""
if relation_types:
relation_hint = f"\n可能的关系类型: {', '.join(relation_types)}"
prompt = f"""从以下文本中抽取所有实体关系三元组。
{relation_hint}
文本: {text}
输出格式(JSON数组):
[
{{"subject": "主语实体", "relation": "关系", "object": "宾语实体", "confidence": 0.95}},
...
]
规则:
1. 只抽取文本中明确表达的关系
2. confidence表示你对这个三元组的确信程度(0-1)
3. 关系用简洁的中文动词短语表达"""
response = llm_client.generate(prompt)
triples = json.loads(response)
return triples
# 示例
text = """
腾讯公司由马化腾于1998年在深圳创立。目前腾讯是中国市值最高的互联网公司之一,
旗下产品包括微信、QQ、腾讯云等。2024年,腾讯宣布与华为合作开发AI大模型。
"""
triples = extract_relations(text, client)
# 预期输出:
# [
# {"subject": "马化腾", "relation": "创立", "object": "腾讯公司", "confidence": 0.98},
# {"subject": "腾讯公司", "relation": "创立时间", "object": "1998年", "confidence": 0.97},
# {"subject": "腾讯公司", "relation": "总部位于", "object": "深圳", "confidence": 0.96},
# {"subject": "微信", "relation": "属于", "object": "腾讯公司", "confidence": 0.95},
# {"subject": "QQ", "relation": "属于", "object": "腾讯公司", "confidence": 0.95},
# {"subject": "腾讯云", "relation": "属于", "object": "腾讯公司", "confidence": 0.94},
# {"subject": "腾讯", "relation": "合作", "object": "华为", "confidence": 0.93}
# ]
四、实体链接(EL)
4.1 任务定义
实体链接(Entity Linking):
将文本中的实体提及(mention)映射到知识库中的标准实体(entity)
示例:
提及: "苹果"
候选知识库实体:
- Q312 (Apple Inc., 科技公司)
- Q89 (苹果, 水果)
- Q7860 (Apple Records, 唱片公司)
上下文: "苹果公司CEO库克宣布了新产品"
链接结果: Q312 (Apple Inc.)
核心挑战: 歧义消解(同一名称对应多个实体)
4.2 实体链接流水线
实体链接三步骤:
Step 1: 候选生成(Candidate Generation)
├── 方法:
│ ├── 精确匹配:名称/别名完全匹配
│ ├── 模糊匹配:编辑距离、拼音匹配
│ ├── 别名表:维护实体的各种称呼
│ └── 锚文本:Wikipedia超链接文本
├── 目标:高召回率(不遗漏正确候选)
└── 典型候选数:5-20个
Step 2: 候选排序(Candidate Ranking)
├── 特征:
│ ├── 上下文相似度(实体描述 vs 提及上下文)
│ ├── 实体先验概率(热门度)
│ ├── 类型一致性(期望类型 vs 候选类型)
│ └── 共现信息(同文档中其他实体的关联)
├── 方法:
│ ├── 传统:SVM/LR + 手工特征
│ ├── 深度学习:双塔模型 + Cross-encoder
│ └── LLM:上下文理解 + 知识推理
└── 目标:高精确率(排第一的是正确答案)
Step 3: NIL检测
├── 判断提及是否不在知识库中
├── NIL实体可触发知识库扩展
└── 避免错误链接(宁可不链,不可错链)
4.3 基于嵌入的实体链接
from sentence_transformers import SentenceTransformer
import numpy as np
class EmbeddingEntityLinker:
def __init__(self, knowledge_base):
self.model = SentenceTransformer('all-MiniLM-L6-v2')
self.kb = knowledge_base
self._build_index()
def _build_index(self):
"""构建知识库实体的嵌入索引"""
descriptions = [
f"{entity['name']}: {entity['description']}"
for entity in self.kb
]
self.entity_embeddings = self.model.encode(descriptions)
def link(self, mention, context, top_k=5):
"""将提及链接到知识库实体"""
# 编码提及+上下文
query = f"{mention}: {context}"
query_embedding = self.model.encode([query])
# 计算相似度
similarities = np.dot(
self.entity_embeddings, query_embedding.T
).flatten()
# 排序取Top-K
top_indices = np.argsort(similarities)[::-1][:top_k]
results = []
for idx in top_indices:
results.append({
"entity_id": self.kb[idx]["id"],
"entity_name": self.kb[idx]["name"],
"score": float(similarities[idx])
})
return results
五、端到端知识图谱构建
5.1 LLM驱动的一体化构建
def build_kg_from_text(text, llm_client, schema=None):
"""使用LLM从文本一步构建知识图谱"""
schema_hint = ""
if schema:
schema_hint = f"""
图谱Schema:
- 节点类型: {', '.join(schema['node_types'])}
- 关系类型: {', '.join(schema['relation_types'])}
"""
prompt = f"""从以下文本中构建知识图谱。
{schema_hint}
文本:
{text}
请输出JSON格式的图谱数据:
{{
"nodes": [
{{"id": "唯一标识", "label": "节点类型", "properties": {{"name": "...", ...}}}}
],
"edges": [
{{"source": "源节点id", "target": "目标节点id", "type": "关系类型", "properties": {{}}}}
]
}}
要求:
1. 实体去重(相同实体只出现一次)
2. 关系必须有方向性
3. 属性尽可能丰富"""
response = llm_client.generate(prompt)
graph_data = json.loads(response)
return graph_data
def import_to_neo4j(graph_data, driver):
"""将图谱数据导入Neo4j"""
with driver.session() as session:
# 导入节点
for node in graph_data["nodes"]:
session.run(
f"MERGE (n:{node['label']} {{id: $id}}) "
f"SET n += $props",
id=node["id"],
props=node["properties"]
)
# 导入边
for edge in graph_data["edges"]:
session.run(
f"MATCH (a {{id: $src}}), (b {{id: $tgt}}) "
f"MERGE (a)-[r:{edge['type']}]->(b) "
f"SET r += $props",
src=edge["source"],
tgt=edge["target"],
props=edge.get("properties", {})
)
5.2 质量保障
| 环节 | 质量指标 | 保障方法 |
|---|---|---|
| NER | F1 > 0.85 | 多模型投票 + 人工校验 |
| RE | F1 > 0.75 | 置信度过滤 + 规则校验 |
| EL | Accuracy > 0.90 | Top-K候选 + 上下文消歧 |
| 融合 | 一致性 > 0.95 | 冲突检测 + 多源验证 |
六、工程实践建议
6.1 方法选择决策树
选择NER/RE/EL方法:
数据量 > 10K标注样本?
├── 是 → BERT/微调方案(性价比最高)
└── 否 → 标注样本 > 100?
├── 是 → Few-shot LLM + 主动学习
└── 否 → Zero-shot LLM + 规则补充
实时性要求?
├── <100ms → BERT/小模型部署
├── <1s → 中等模型 + 缓存
└── 无要求 → LLM(最灵活)
领域特异性?
├── 高(医学/法律) → 领域微调 + 领域词典
├── 中 → 通用模型 + 少量领域样本
└── 低 → 通用预训练模型即可
知识图谱的自动构建正在从传统NLP流水线向LLM驱动的端到端方案演进。两者并非替代关系,而是互补:传统方法提供速度和可控性,LLM提供灵活性和零样本能力。在实际工程中,混合方案往往是最优选择。
Maurice | maurice_wen@proton.me