第 2 章 · 图抽取:从文本抽出实体和关系
这章讲什么: 这是整条流水线里"含金量"最高的一步——把一段自然语言变成结构化的"实体 + 关系"。本章讲 LLM 抽取的模板与解析、"gleaning"多轮补抽的技巧、同名实体的描述合并,以及不花 LLM 的 NLP 快速路径。对应 workflow:
extract_graph(standard)与extract_graph_nlp(fast)。
2.1 要解决的小问题
给一段文本(一个 text_unit),要抽出两样东西:
- 实体:文本里提到的"东西"——人、组织、地点…(
entity_name, entity_type, entity_description)。 - 关系:实体两两之间的联系(
source, target, description, strength/weight)。
难点有二:(a) LLM 输出是自由文本,得可靠地解析成结构化记录;(b) LLM 一遍常常抽不全(漏实体、漏关系)。GraphRAG 用"带分隔符的模板" + "gleaning 多轮补抽"分别对付这两点。
2.2 思路:让 LLM 输出"带自定义分隔符"的记录
GraphRAG 不依赖 JSON,而是让 LLM 按一套自定义分隔符吐记录,再自己切。分隔符定义在 graph_extractor.py 顶部:
| 常量 | 值 | 作用 |
|---|---|---|
TUPLE_DELIMITER | `< | >` |
RECORD_DELIMITER | ## | 记录之间的分隔 |
COMPLETION_DELIMITER | `< | COMPLETE |
prompt(packages/graphrag/graphrag/prompts/index/extract_graph.py(GRAPH_EXTRACTION_PROMPT))要求 LLM 把每条实体写成 ("entity"<|>名字<|>类型<|>描述)、每条关系写成 ("relationship"<|>源<|>目标<|>描述<|>强度),用 ## 连成一串,末尾输出 <|COMPLETE|>。prompt 里还内置了几个 few-shot 例子帮助模型对齐格式。
为什么不用 JSON(精华): 抽取常常是长列表、还要多轮追加(见下),用轻量分隔符比反复拼合法 JSON 更省 token、也更抗"半截输出"——切分时按 ## split、按 <|> split 即可,坏记录直接跳过。