根据论文和代码实现,实体关系提取使用了两种方法:
论文描述(paper_revised.tex 第47-59行):
-
使用工具:
- GPT-4(LLM)
- 开源NLP库(如spaCy)
- 依赖解析模型
-
提取过程:
- 分析语法结构(名词短语、介词短语、关系从句等)
- 识别依赖关系(如"belongs to"、"contains"、"is dependent on")
- 定义规则识别层次关系:
- 如果词修饰另一个名词 → 子-父关系
- 如果有连词("and", "or")→ 将概念分组到同一父节点下
-
关系类型:
- 组织关系(organizational)
- 分类关系(categorization)
- 时间关系(temporal)
- 地理关系(geographic)
- 包含关系(inclusion)
- 功能关系(functional)
- 属性关系(attribute)
代码实现(benchmark/build_medqa_dart_index.py 和 benchmark/build_aeslc_index.py):
# 从数据集中查找共现的实体
for item in dataset[:200]:
text = item.get('answer', item.get('expected_answer', '')).lower()
entities_in_text = [e for e in entities_list if e.lower() in text]
# 创建共现实体之间的关系
for i, e1 in enumerate(entities_in_text[:5]):
for e2 in entities_in_text[i+1:i+3]:
if e1 != e2:
relations.add((e1, e2))共现关系方法:
- 从同一文本中提取实体
- 如果两个实体在同一文本中出现,就建立它们之间的关系
- 这是一个简化的实现,用于快速构建实体关系
实体提取(简化方法):
def extract_entities_simple(text: str) -> Set[str]:
"""简单提取实体:使用大写字母开头的单词和常见名词短语"""
entities = set()
# 提取大写字母开头的单词
words = re.findall(r'\b[A-Z][a-z]+\b', text)
entities.update(words[:10])
# 提取常见的名词短语(2-3个单词的组合)
noun_phrases = re.findall(r'\b(?:the|a|an)?\s*[A-Z][a-z]+(?:\s+[A-Z][a-z]+)?\b', text)
entities.update(noun_phrases[:10])
return entities论文中:是的,提到了使用GPT-4进行依赖解析。
代码实现中:没有使用LLM,使用的是简化的共现关系方法。
是的,代码中的实际实现使用的是共现关系:
- 同一文本中出现的实体之间建立关系
- 这是当前代码中的主要方法
是的,是同一个数据集!
在 benchmark/build_medqa_dart_index.py 中:
def build_entities_file_medqa(dataset_path: str, output_path: str, max_samples: int = 500):
"""为MedQA数据集构建实体关系文件"""
with open(dataset_path, 'r', encoding='utf-8') as f:
dataset = json.load(f) # 从同一个数据集文件读取
# 从数据集中提取实体关系
for item in dataset:
text = item.get('answer', item.get('expected_answer', ''))
# ... 提取实体和关系在 benchmark/run_benchmark.py 中:
# 使用同一个数据集
--dataset ./datasets/processed/medqa.json # 用于benchmark
# 和
build_entities_file_medqa(dataset_path, ...) # 从同一个文件提取实体关系数据集文件(如 medqa.json)
↓
├─→ 提取chunks → 构建向量数据库(VecDB)
│
└─→ 提取实体关系 → 构建实体树(Entity Tree)
↓
同一数据集的不同用途
论文第43行:
"For existing hierarchical data, binary pairs representing parent-child relationships are directly extracted. For raw textual data, text cleansing is first performed manually to remove irrelevant information."
这表明:
- 对于已有层次结构的数据:直接提取
- 对于原始文本数据:从同一个数据集中提取实体关系
| 方法 | 论文描述 | 代码实现 | 说明 |
|---|---|---|---|
| 依赖解析 | ✅ 使用GPT-4和NLP库 | ❌ 未实现 | 理想方法,更准确但更复杂 |
| 共现关系 | ❌ 未明确提及 | ✅ 已实现 | 简化方法,快速但可能不够准确 |
- 构建实体关系的数据集 = 跑测评的数据集 = 构建向量数据库的数据集
- 都是同一个数据集文件(如
medqa.json、aeslc.json、dart.json)
-
数据预处理:
- 从数据集提取chunks(用于构建向量数据库)
- 从同一个数据集提取实体关系(用于构建实体树)
-
构建阶段:
- 使用chunks构建向量数据库
- 使用实体关系构建实体树/图
-
运行阶段:
- 使用向量数据库进行相似度检索
- 使用实体树/图进行层次化检索
-
实体关系提取代码:
benchmark/build_medqa_dart_index.py(第117-126行:共现关系)benchmark/build_aeslc_index.py(第98-107行:共现关系)
-
论文描述:
paper_revised.tex(第47-59行:依赖解析方法)
如果要实现论文中描述的依赖解析方法,可以:
- 使用spaCy进行依赖解析:
import spacy
nlp = spacy.load("en_core_web_sm")
doc = nlp(text)
for token in doc:
if token.dep_ in ["nmod", "amod", "pobj"]: # 修饰关系
# 建立子-父关系
relations.add((token.text, token.head.text))- 使用GPT-4进行关系提取:
# 使用LLM提取实体关系
prompt = f"Extract hierarchical relationships from: {text}"
response = openai.ChatCompletion.create(...)
# 解析response得到实体关系- 结合两种方法:
- 使用共现关系作为基础
- 使用依赖解析进行验证和优化