| 编辑推荐: |
本文介绍了怎么使用
LLM Graph Transformer 构建知识图谱相关内容。希望对你的学习有帮助。
本文来自于微信公众号三人行AI ,由火龙果软件Alice编辑,推荐。 |
|
引言
从文本构建图谱是一件既令人兴奋又充满挑战的事。
本质上,这个过程就是将非结构化文本转换为结构化数据。 这种方法早已存在,但在大语言模型(LLM)出现之后,它的应用和关注度才迅速进入主流视野。
从文本中提取实体与关系
上图展示了如何通过信息抽取,将原始文本转化为知识图谱:
•左侧:多份文档中包含关于个人及其与企业关系的非结构化句子。
•右侧:相同信息被转化为一个知识图谱,展示了实体及它们之间的连接,例如谁曾在某家公司工作或创办了某个组织。
这种结构化表达使数据更清晰、关系更直观。
为什么要将文本信息转成图谱?
核心原因之一,是为了驱动 检索增强生成(RAG) 应用。
•传统做法:在非结构化文本上使用文本嵌入模型,效果不错,但在处理复杂的多跳推理问题[1]时会遇到瓶颈,尤其是那些需要跨多个实体理解连接,或执行结构化操作[2](如过滤、排序、聚合)的问题。
•图谱方法:
•将非结构化文本转化为结构化信息(知识图谱),不仅能更高效地组织数据,还能形成强大的框架去理解实体之间的复杂关系。
•能更方便地检索、过滤和利用特定信息。
•扩展可回答问题的类型,并提升准确性。
LLM Graph Transformer 的诞生
大约一年前,我开始尝试使用 LLM 来构建知识图谱。
由于社区对此需求不断增长,我们决定在 LangChain 中引入这项能力,并将其命名为 LLM Graph
Transformer[3]。
经过一年的迭代,我们收获了许多宝贵经验,并在功能上做了多项改进。
本篇文章将详细介绍这些特性,并通过实例进行演示。
搭建 Neo4j 环境
在本教程中,我们将使用 Neo4j 作为底层图数据库存储,它自带可视化功能,方便直观地查看和分析图数据。
1. 使用 Neo4j Aura(云端)
最快的上手方式是使用 Neo4j Aura[5] 的免费实例(云端版本的 Neo4j 数据库),无需本地安装,注册即可使用。
2. 本地部署 Neo4j
如果需要离线或本地开发,也可以下载 Neo4j Desktop[6] 应用,创建本地数据库实例进行使用。
3. 在 LangChain 中连接 Neo4j
LangChain 提供了 Neo4jGraph 类来管理与 Neo4j 的连接及数据交互。
from
langchain_community.graphs importNeo4jGraph
# 创建 Neo4j 连接
graph =Neo4jGraph(
url="bolt://54.87.130.140:7687",#
Neo4j Bolt 协议连接地址
username="neo4j",# 用户名
password="cables-anchors-directories",#
密码
refresh_schema=False# 是否刷新数据库模式信息
)
|
LLM Graph Transformer
LLM Graph Transformer 的设计目标是提供一个灵活的框架,能用任意大语言模型(LLM)来构建知识图谱。
由于 LLM 提供商与模型种类繁多,这个任务并不简单。
好在 LangChain 接管了大部分标准化处理工作,让流程变得可控。
作者打了个有趣的比喻:
它就像两只猫叠在一件风衣里
—— 可以以两种完全独立的模式运行。 |
两种工作模式
LLM Graph Transformer 有两种从文本提取图谱的模式,每种模式针对不同场景生成图数据。
1.工具模式(Tool-Based Mode,默认)
•适用场景:LLM 支持结构化输出或函数调用(Function Calling)。
•工作原理:
•使用 LLM 内置的 with_structured_output 方法[7],结合工具(Tool)规范,定义输出格式。
•确保提取到的 实体(Entity) 和 关系(Relationship) 以预定义的结构化形式返回。
•示意图:左侧展示了 Node 和 Relationship 类的代码。
2.提示模式(Prompt-Based Mode,回退方案)
•适用场景:LLM 不支持工具或函数调用。
•工作原理:
•使用 Few-Shot Prompting 定义输出格式,完全依靠提示词引导 LLM 在纯文本中抽取实体与关系。
•输出结果再通过自定义解析函数转换为 JSON,再用 JSON 填充节点与关系。
•示意图:右侧展示了一个提示示例及对应的 JSON 输出。
这两种模式让
LLM Graph Transformer 能适配不同类型的 LLM:
•有工具能力 → 直接调用工具生成图谱。
•无工具能力 → 通过 Prompt 抽取,再解析生成图谱。 |
这两种模式让 LLM Graph Transformer 能适配不同类型的 LLM:
•有工具能力 → 直接调用工具生成图谱。
•无工具能力 → 通过 Prompt 抽取,再解析生成图谱。
即使模型支持工具/函数调用,你也可以强制使用 Prompt 模式,方法是将
ignore_tools_usage=True。
为什么优先选择工具模式?
我们最初选择工具模式,因为它:
•减少了对复杂 Prompt 工程的依赖;
•免去了额外的自定义解析函数需求。
在 LangChain 中,with_structured_output 方法可以使用工具或函数来提取信息:
•输出结构可以用 JSON 描述;
•或使用 Pydantic 对象 定义。
作者更喜欢 Pydantic 对象,因为结构更清晰,所以在实现中也选用了它。
定义 Node 类
以下是一个基于 Pydantic 的 Node 类定义:
classNode(BaseNode):
id: str =Field(..., description="名称或可读的唯一标识符")
label: str =Field(..., description=f"可选标签包括
{enum_values}")
properties:Optional[List[Property]] |
每个 节点(Node) 都包含:
•id:唯一标识符(必须可读且具备语义)
•重要原因:部分 LLM(例如一些通用大模型)在理解 id 时,容易倾向于使用随机字符串或自增数字。
•我们的目标是使用实体名称作为 id,使其更直观且便于人工理解。
•label:节点标签(类别)
•为了减少歧义,我们在 label 的 description 中直接列出可选标签列表。
•对于支持 enum 参数的模型(如 OpenAI 系列),可以直接使用 enum 限制取值范围。
•properties(可选):节点的属性列表。
Relationship 类定义
关系(Relationship) 表示两个节点之间的连接,并附带类型和可选属性。
classRelationship(BaseRelationship):
source_node_id: str
source_node_label: str =Field(
...,
description=f"可选标签包括 {enum_values}"
)
target_node_id: str
target_node_label: str =Field(
...,
description=f"可选标签包括 {enum_values}"
)
type: str =Field(
...,
description=f"可选关系类型包括 {enum_values}"
)
properties:Optional[List[Property]] |
在这一版 Relationship 类中,我们对结构做了重要调整。最初,source 与 target
使用嵌套的 Node 对象表示;但实践表明,嵌套对象会降低信息抽取的准确性和质量。因此,我们将其改为扁平化字段,分别为:
•source_node_id、source_node_label
•target_node_id、target_node_label
同时,我们在节点标签与关系类型的字段说明(description)中显式限定可用取值,以确保 LLM
在抽取时严格遵循既定图谱模式(schema)。
在工具模式(tool-based extraction)下,我们还能为节点与关系定义属性(properties)。下方给出的类用于描述该属性结构(键值对):
•key:属性名(通过枚举/描述限定取值)
•value:属性值
classProperty(BaseModel):
"""A single property consisting
of key and value"""
key: str =Field(..., description=f"Available
options are {enum_values}")
value: str |
在 LLM Graph Transformer 中,每个 Property 都是一个键值对(key-value
pair)。 这种设计足够灵活,但也存在以下限制:
1.无法为每个属性单独编写描述
所有属性共用同一个 description,缺乏针对性说明。
2.无法设置必填 / 可选属性
目前所有属性都被定义为可选(optional)。
3.属性定义不区分节点或关系类型
节点和关系共用同一组属性定义,不能针对特定类型单独设定。
我们为 LLM Graph Transformer 实现了一个详细的系统提示[8](system
prompt)来引导抽取。
但在实际使用中,函数与参数的描述往往比系统消息对结果影响更大。
目前还没有简单的方法去定制函数或参数的描述。
提示模式(Prompt-Based Extraction)
由于目前仅有少数商业 LLM(如部分 OpenAI 模型)和 LLaMA 3 支持原生工具调用,我们实现了回退方案来兼容不支持工具的模型。
你也可以在支持工具的模型中,通过设置 ignore_tool_usage=True 来强制启用提示模式。
提示模式的大部分提示工程与示例由 Geraldus Wilsen[9] 贡献。
在提示模式中,我们必须在提示词中直接定义输出结构[10]。 以下是系统提示(System Prompt)的高层概述:
You
are a top-tier algorithm designed for extracting
information in structured formats to build a
knowledge graph.Your task is to identify the
entities and relations specified in the user
prompt from a given text and produce the output
in JSON format.This output should be a list
of JSON objects,with each object containing
the following keys:
-**"head"**:The text of the extracted
entity, which must match one of the types
specified in the user prompt.
-**"head_type"**:The type of the
extracted head entity, selected from the specified
list of types.
-**"relation"**:The type of relation
between the "head"and the "tail,"
chosen from the list of allowed relations.
-**"tail"**:The text of the entity
representing the tail of the relation.
-**"tail_type"**:The type of the
tail entity, also selected from the provided
list of types.
Extractas many entities and relationships
as possible.
**EntityConsistency**:Ensure consistency
in entity representation.If an entity, like
"John Doe," appears multiple times
in the text under different names or pronouns
(e.g.,"Joe,""he"),use
the most complete identifier consistently.This
consistency is essential for creating a coherent
and easily understandable knowledge graph.
**ImportantNotes**:
-Donot add any extra explanations or text.
|
在 提示模式(Prompt-Based Approach) 中,我们对抽取目标做了重要调整:
1.只抽取关系(Relationships)
•不单独抽取孤立节点(Isolated Nodes)。
•与工具模式不同,提示模式不会生成没有连接关系的节点数据。
2.不提取属性(Properties)
•无论是节点属性还是关系属性,都不在提示模式中抽取。
•原因是缺少原生工具支持的模型通常在信息抽取准确性上较弱,为了简化输出、降低错误率,我们仅保留关系级别的结构。
为了让模型更好地理解任务,我们在提示中添加了少量示例(Few-Shot Examples)。 每个示例包含:
•text:原始文本。
•head / tail:关系的起点与终点实体。
•head_type / tail_type:实体类型。
•relation:两实体间的关系类型。
示例代码:
examples
=[
{
"text":(
"Adam is a software engineer in Microsoft
since 2009, "
"and last year he got an award as the Best
Talent"
),
"head":"Adam",
"head_type":"Person",
"relation":"WORKS_FOR",
"tail":"Microsoft",
"tail_type":"Company",
},
{
"text":(
"Adam is a software engineer in Microsoft
since 2009, "
"and last year he got an award as the Best
Talent"
),
"head":"Adam",
"head_type":"Person",
"relation":"HAS_AWARD",
"tail":"Best Talent",
"tail_type":"Award",
},
...
] |
在当前版本的提示模式中:
•不支持直接添加自定义的 Few-Shot 示例或额外指令;
•想要自定义提示,只能通过修改 prompt 属性整体替换系统提示。
扩展自定义功能(如动态增加示例、添加额外指令)是未来的改进方向。
|
定义图谱模式(Graph Schema)
在使用 LLM Graph Transformer 进行信息抽取时,定义图谱模式(schema)是关键步骤。
它的作用是:
•明确指定要抽取的节点类型与关系类型;
•定义各节点与关系可具备的属性;
•作为知识图谱的蓝图,指导 LLM 按预期结构抽取信息。
一个良好定义的 schema 可以确保模型:
•一致性(Consistent)
•相关性(Relevant)
•结构化(Structured)
测试案例:Marie Curie + Robin Williams
在本例中,我们选取了玛丽·居里(Marie Curie)[11]的维基百科开头段落,并在结尾加上了一句关于
Robin Williams 的描述。
from
langchain_core.documents importDocument
text ="""
MarieCurie,7November1867–4July1934, was a
Polishand naturalised-French physicist and
chemist who conducted pioneering research
on radioactivity.
She was the first woman to win a NobelPrize,
the first person to win a NobelPrize twice,and
the only person to win a NobelPrizein two
scientific fields.
Her husband,PierreCurie, was a co-winner of
her first NobelPrize, making them the first-ever
married couple to win the NobelPrizeand launching
the Curie family legacy of five NobelPrizes.
She was,in1906, the first woman to become
a professor at the University of Paris.
Also,RobinWilliams.
"""
documents =[Document(page_content=text)]
|
使用 GPT-4o 作为 LLM
from
langchain_openai importChatOpenAI
import getpass
import os
os.environ["OPENAI_API_KEY"]= getpass.getpass("OpenAI
api key")
llm =ChatOpenAI(model='gpt-4o')
|
不定义 Schema 的抽取方式
在未提供任何 graph schema 的情况下,我们先直接运行 LLM Graph Transformer,看看抽取效果。
from
langchain_experimental.graph_transformers importLLMGraphTransformer
no_schema =LLMGraphTransformer(llm=llm)
|
异步处理:将文档转换为图谱文档
在提示模式下,推荐使用 异步 的方式进行抽取,这样可以并行处理多份文档,显著降低等待时间、提高吞吐量。
data
= await no_schema.aconvert_to_graph_documents(documents)
|
上面的 aconvert_to_graph_documents 是异步方法。对于包含多文档的数据集,异步并发能有效提升整体处理效率。
返回结果:GraphDocument 结构
LLM Graph Transformer 的响应为一个 图谱文档(GraphDocument) 列表。其基本结构如下(节选自示例输出):
[
GraphDocument(
nodes=[
Node(id="Marie Curie", type="Person",
properties={}),
Node(id="Pierre Curie", type="Person",
properties={}),
Node(id="Nobel Prize", type="Award",
properties={}),
Node(id="University Of Paris", type="Organization",
properties={}),
Node(id="Robin Williams", type="Person",
properties={}),
],
relationships=[
Relationship(
source=Node(id="Marie Curie", type="Person",
properties={}),
target=Node(id="Nobel Prize", type="Award",
properties={}),
type="WON",
properties={},
),
Relationship(
source=Node(id="Marie Curie", type="Person",
properties={}),
target=Node(id="Nobel Prize", type="Award",
properties={}),
type="WON",
properties={},
),
Relationship(
source=Node(id="Marie Curie", type="Person",
properties={}),
target=Node(
id="University Of Paris", type="Organization",
properties={}
),
type="PROFESSOR",
properties={},
),
Relationship(
source=Node(id="Pierre Curie", type="Person",
properties={}),
target=Node(id="Nobel Prize", type="Award",
properties={}),
type="WON",
properties={},
),
],
source=Document(
metadata={"id":"de3c93515e135ac0e47ca82a4f9b82d8"},
page_content="\nMarie Curie, 7 November
1867 – 4 July 1934, was a Polish and naturalised-French
physicist and chemist who conducted pioneering
research on radioactivity.\nShe was the first
woman to win a Nobel Prize, the first person
to win a Nobel Prize twice, and the only person
to win a Nobel Prize in two scientific fields.\nHer
husband, Pierre Curie, was a co-winner of her
first Nobel Prize, making them the first-ever
married couple to win the Nobel Prize and launching
the Curie family legacy of five Nobel Prizes.\nShe
was, in 1906, the first woman to become a professor
at the University of Paris.\nAlso, Robin Williams!\n",
),
)
] |
图谱文档与可视化
上面的图谱文档(graph document)描述了抽取到的节点(nodes)与关系(relationships);此外,还在
source 字段下附带了用于抽取的原始文档。
我们可以使用 Neo4j Browser 对抽取结果进行可视化,从而更直观地理解数据。
(配图)在未定义图谱模式(schema)的情况下,对同一数据集进行了两次抽取并可视化。
如上图所示,我们对关于 Marie Curie 的同一段文字进行了两次抽取。本例使用 GPT-4
的工具模式进行抽取,该模式也会产生孤立节点(isolated nodes),图中已有体现。由于没有定义图谱
schema,LLM 会在运行时自行决定要抽取哪些信息,因此即便是同一段文字,输出也可能存在差异:
•有的抽取结果更详细,
•有的在结构上会有所不同。
例如:左图把 Marie 表示为诺奖的 WINNER(获奖者),而右图则表示她 WON(赢得了)诺贝尔奖。
现在,我们用提示模式做同样的抽取。对于支持工具的模型,也可以通过设置 ignore_tool_usage
参数开启提示模式:
no_schema_prompt
=LLMGraphTransformer(llm=llm, ignore_tool_usage=True)
data = await no_schema.aconvert_to_graph_documents(documents)
|
同样,你可以在 Neo4j Browser 中对两次独立执行的结果进行可视化对比。
同一数据集在未定义图谱模式(schema)且采用提示模式(prompt-based)下执行两次的可视化对比(示意图)。
在 提示模式 下,不会出现孤立节点(isolated nodes)。不过,与之前的抽取相同,由于未约束
schema,不同轮次之间的输出仍可能存在差异,即:同一输入的结构和细节在不同次运行中会有所不同。
限定可抽取的节点类型(Defining allowed nodes)
对抽取到的图结构进行约束非常关键:
•引导模型聚焦于特定、相关的实体与关系;
•提升不同轮次之间的一致性,让输出更可预测、更贴合业务需求;
•降低随机性与噪声,减少遗漏或“意外元素”,使结果更干净可用。
我们先用 allowed_nodes 参数限定允许抽取的节点类型:
allowed_nodes
=["Person","Organization","Location","Award","ResearchField"]
nodes_defined =LLMGraphTransformer(llm=llm,
allowed_nodes=allowed_nodes)
data = await nodes_defined.aconvert_to_graph_documents(documents)
|
上例中,我们要求 LLM 仅抽取 Person / Organization / Location
/ Award / ResearchField 五类节点。 随后可在 Neo4j Browser 中对两次独立执行的结果进行可视化对比,以观察一致性提升。
(配图)在预定义了节点类型的前提下,对同一数据集进行了两次抽取的可视化对比。
通过指定预期的节点类型,节点抽取的一致性显著提升。但仍可能存在一定差异。例如:第一轮中将 “radioactivity(放射性)”
抽取为一个 研究领域(ResearchField),而第二轮中则未被抽取。
由于我们尚未限定关系类型,不同轮次中关系的类型也可能有所不同;同时,不同抽取结果对信息的覆盖程度也会有差异。比如,Marie
与 Pierre 之间的 MARRIED_TO(婚姻关系)并非在两次抽取中都出现。
限定关系类型
仅限定节点类型,仍会使关系抽取存在波动。为进一步提升一致性,可以同时限定允许的关系类型。第一种做法是提供一个可用关系类型列表:
allowed_nodes
=["Person","Organization","Location","Award","ResearchField"]
allowed_relationships =["SPOUSE","AWARD","FIELD_OF_RESEARCH","WORKS_AT","IN_LOCATION"]
rels_defined =LLMGraphTransformer(
llm=llm,
allowed_nodes=allowed_nodes,
allowed_relationships=allowed_relationships
)
data = await rels_defined.aconvert_to_graph_documents(documents)
|
接下来,同样可以对两次独立执行的结果进行可视化对比,以观察在节点类型 + 关系类型双重约束下,一致性的进一步提升。
(配图)在预定义节点类型与关系类型的前提下,对同一数据集进行了两次抽取的可视化对比。
当节点与关系都被定义后,输出的一致性显著提升。
例如:关于 Marie 的信息会稳定地体现出她获得过奖项、是 Pierre 的配偶、并且就职于巴黎大学。
不过,由于关系目前仅以通用列表的形式提供,没有约束可连接的节点类型,仍会出现一些差异:
•例如 FIELD_OF_RESEARCH 关系有时连接的是 Person → ResearchField,但有时又会出现
Award → ResearchField。
•另外,由于未定义关系方向,不同轮次之间的方向一致性也会有所不同。
为了解决无法限定关系连接的节点类型以及缺乏方向约束的问题,我们最近引入了新的关系定义方式(见下方示例)。
allowed_nodes
=["Person","Organization","Location","Award","ResearchField"]
allowed_relationships =[
("Person","SPOUSE","Person"),
("Person","AWARD","Award"),
("Person","WORKS_AT","Organization"),
("Organization","IN_LOCATION","Location"),
("Person","FIELD_OF_RESEARCH","ResearchField")
]
rels_defined =LLMGraphTransformer(
llm=llm,
allowed_nodes=allowed_nodes,
allowed_relationships=allowed_relationships
)
data = await rels_defined.aconvert_to_graph_documents(documents)
|
与之前字符串列表式的关系定义不同,现在采用三元组(tuple)格式: (源节点类型, 关系类型, 目标节点类型)
这使我们能够同时限定可连接的端点类型并固定关系方向。
接下来,可以再次在 Neo4j Browser 中进行可视化对比,观察在节点类型 + 关系端点与方向约束齐备情况下的一致性提升。
(配图)在预定义节点类型与三元组关系约束(高级关系类型)的前提下,对同一数据集进行了两次抽取的可视化对比。
采用 三元组 形式定义关系后,跨多次执行的图谱 schema 一致性 明显提升。
不过,鉴于 LLM 的生成特性,细节层面的差异仍可能存在:例如右图中 Pierre 被抽取为获得过诺贝尔奖,而左图中该信息缺失。
定义属性(Defining properties)
改进图谱 schema 的最后一步,是为节点与关系定义属性。这里有两种思路:
1.自动属性抽取(更灵活但不完全可控)
将 node_properties 或 relationship_properties 设为 True,让
LLM 自主决定要抽取哪些属性。
示例代码:
allowed_nodes
=["Person","Organization","Location","Award","ResearchField"]
allowed_relationships =[
("Person","SPOUSE","Person"),
("Person","AWARD","Award"),
("Person","WORKS_AT","Organization"),
("Organization","IN_LOCATION","Location"),
("Person","FIELD_OF_RESEARCH","ResearchField")
]
node_properties =True
relationship_properties =True
props_defined =LLMGraphTransformer(
llm=llm,
allowed_nodes=allowed_nodes,
allowed_relationships=allowed_relationships,
node_properties=node_properties,
relationship_properties=relationship_properties
)
data = await props_defined.aconvert_to_graph_documents(documents)
graph.add_graph_documents(data)
|
说明:开启自动属性后,模型会尝试为节点与关系补充其认为重要的属性;优点是覆盖更丰富,缺点是一致性与可控性较弱。
|
(配图)已抽取出的节点与关系属性
当我们允许 LLM 自主添加节点或关系属性后,模型会补充其认为“相关”的信息。
在示例中,它加入了如下属性:
•玛丽·居里(Marie Curie)的出生/去世日期;
•她在巴黎大学担任教授的身份;
•两次获得诺贝尔奖的事实。
这些额外属性显著丰富了知识图谱的信息密度。
第二种做法是显式指定希望抽取的节点属性与关系属性。如下:
allowed_nodes
=["Person","Organization","Location","Award","ResearchField"]
allowed_relationships =[
("Person","SPOUSE","Person"),
("Person","AWARD","Award"),
("Person","WORKS_AT","Organization"),
("Organization","IN_LOCATION","Location"),
("Person","FIELD_OF_RESEARCH","ResearchField")
]
# 精确指定要抽取的属性
node_properties =["birth_date","death_date"]
relationship_properties =["start_date"]
props_defined =LLMGraphTransformer(
llm=llm,
allowed_nodes=allowed_nodes,
allowed_relationships=allowed_relationships,
node_properties=node_properties,
relationship_properties=relationship_properties
)
data = await props_defined.aconvert_to_graph_documents(documents)
graph.add_graph_documents(data)
|
这里,属性以两个列表的形式定义:
•node_properties:要抽取的节点属性列表(如 birth_date、death_date);
-relationship_properties:要抽取的关系属性列表(如 start_date)。
这种方式有助于在生产环境中提升一致性与可控性:
•自动模式:信息更丰富,但可能“不稳定”。
•显式指定:信息更可控、结构更稳定,便于后续下游查询与分析。 |
接下来,我们可以查看 LLM 在该约束下抽取到的属性结果。
(配图)已抽取出的预定义节点与关系属性
在使用预定义属性模式下:
•出生日期与去世日期与上一次的结果保持一致;
•同时,LLM 还额外抽取了 Marie 在 巴黎大学担任教授的起始日期。
这些属性显著增加了知识图谱的信息深度。 不过,当前实现仍存在以下局限:
1.仅限工具模式(tool-based approach)可抽取属性;
2.所有属性类型均为字符串(不支持日期、数值等强类型);
3.属性只能全局定义,无法针对单一节点类型或关系类型单独定义;
4.无法为属性提供自定义描述,因此难以精确引导 LLM 抽取。
严格模式(Strict mode)
如果你以为到这里 LLM 就能完美遵循 schema,那我得澄清一下:
即使经过大量提示工程优化,仍很难让 LLM —— 尤其是性能较弱的模型 —— 100% 严格执行规则。
为此,我们引入了一个后处理步骤:strict_mode
•作用:移除任何不符合定义的图谱 schema 的信息,保证输出结果更干净、更一致。
默认情况下,strict_mode 为 True。 如果需要,可以关闭它:
LLMGraphTransformer(
llm=llm,
allowed_nodes=allowed_nodes,
allowed_relationships=allowed_relationships,
strict_mode=False
)
|
当关闭 strict_mode 时,LLM 可能会生成超出已定义 graph schema 的节点或关系类型。
这是因为 LLM 有时会“发挥创意”,在输出结构上添加不在 schema 中的元素。
将图谱文档导入图数据库
通过 LLM Graph Transformer 抽取到的图谱文档(GraphDocument)可以导入到图数据库(如
Neo4j)进行进一步分析与应用。
导入可通过 .add_graph_documents() 方法完成,我们可以根据不同需求选择不同的导入方式。
默认导入(Default import)
最简单的方式,是将节点与关系直接导入到 Neo4j:
graph.add_graph_documents(graph_documents)
|
该方法会:
•从 graph_documents 中直接导入所有节点与关系;
•无额外数据清洗或筛选;
•在本篇文章中,我们一直使用这种方式来检查不同 LLM 与 schema 配置下的抽取结果。
基础实体标签(Base entity label)
大多数图数据库都支持索引(index)来优化数据的导入与查询性能。
以 Neo4j 为例:
•索引必须针对特定节点标签创建;
•但在实际应用中,我们可能事先并不知道所有可能的节点标签。
为了解决这个问题,可以通过 baseEntityLabel 参数,为每个节点添加一个统一的基础标签。
这样:
•只需为这个基础标签建立索引,即可优化导入与查询性能;
•无需为图谱中可能出现的每个节点标签单独建立索引。
示例代码:
graph.add_graph_documents(graph_documents,
baseEntityLabel=True) |
执行后,每个节点都会额外带有一个 __Entity__ 标签,例如:
(:Person:__Entity__)
(:Organization:__Entity__) |
这样,我们就能对__Entity__ 建立统一索引,从而提升批量导入和查询的效率,而无需维护大量标签的索引配置。
导入源文档(Include source documents)
在导入图谱数据时,我们还可以选择同时导入源文档信息,以便追踪每个实体或关系最初出现在哪些文档中。
这对溯源、数据验证及后续分析非常有用。
示例代码:
graph.add_graph_documents(graph_documents, include_source=True)
|
在导入完成后,检查图数据库即可看到类似如下的结构:
在可视化中,源文档节点会以蓝色高亮显示,所有从该文档中抽取到的实体都会通过 MENTIONS 关系与其相连。
这种模式的优势在于,可以构建同时利用[结构化与非结构化检索](https://medium.com/neo4j/enhancing-the-accuracy-of-rag-applications-with-knowledge-graphs-ad5e2ffab663)的混合型检索器(Retriever),从而在
RAG 场景中提升召回的多样性与准确度。
总结
本文深入探讨了 LangChain LLM Graph Transformer,以及它在从文本构建知识图谱时的两种运行模式:
1.工具模式(Tool-based mode)
•主要使用方式
•基于结构化输出与函数调用(Function Calling)
•减少了提示词工程的复杂度
•支持属性抽取(节点与关系)
2.提示模式(Prompt-based mode)
•用于不支持工具调用的模型
•依赖少量示例(Few-shot examples)引导 LLM
•不支持属性抽取
•不会生成孤立节点
关于 Schema 的重要性
实验表明:
•明确定义节点类型与关系类型(graph schema)能显著提升抽取结果的一致性与稳定性;
•受限的 schema 可以确保输出结构与预期匹配,使结果更可预测、更可靠、更便于应用;
•无论使用工具模式还是提示模式,LLM Graph Transformer 都能将非结构化数据组织成更规范的结构化表示,进而:
•改进 RAG(检索增强生成)应用效果
•增强多跳(multi-hop)查询能力
代码与体验
•源代码已发布在 GitHub[12];
•你也可以在 Neo4j 提供的托管应用 LLM Graph Builder 中零代码体验 LLM
Graph Transformer。
https://medium.com/data-science/building-knowledge-graphs-with-llm-graph-transformer-a91045c49b59 |
|