从文本到知识图谱

从文本中构建知识图谱,是一件既令人兴奋又充满挑战的技术实践 —— 其核心在于将非结构化文本精准转化为结构化数据,为后续的知识检索、分析与应用打下基础。​

事实上,“文本转结构化数据” 的方法早有探索,但直到大语言模型(LLMs) 兴起后,这一过程的效率与准确性大幅提升,不仅突破了传统方法的局限,更让文本构建知识图谱的技术迅速进入主流视野,在企业知识库、智能问答等场景中得到广泛应用。

在下图中:

左侧 展示了若干包含人物与公司关系的非结构化句子。•右侧 则将这些信息抽取为知识图谱,展示了谁在哪些公司工作或创建了哪些组织。

为什么要构建知识图谱?

一个关键原因是为了支持 检索增强生成(RAG, Retrieval-Augmented Generation) 应用。

•仅仅依靠文本嵌入模型处理非结构化文本,虽然有用,但在以下情况下会受限:•复杂的 多跳推理问题[1](需要跨多个实体进行推理)。•需要 结构化操作(如过滤、排序、聚合)[2]的任务。•通过从文本中抽取结构化信息并构建知识图谱:•可以更有效地组织数据;•可以建立强大的框架来理解复杂关系。

这种 结构化方法 不仅让检索和利用特定信息更加容易,还能显著提升准确性,并扩展可回答的问题范围。

LLM 图转换器的出现

大约一年前,我开始尝试用 LLM 构建图谱。随着兴趣日益增长,我们决定将这一功能集成到 LangChain 中,推出了 LLM Graph Transformer

过去一年,我们积累了宝贵经验,并新增了多项功能。本文将逐步展示这些成果。

相关代码已在 GitHub[3] 开源。

搭建 Neo4j 环境

我们选择 Neo4j 作为底层图数据库,它内置图形可视化能力。

快速入门方式有两种:

1.使用 Neo4j Aura 免费云实例[4](官方提供,开箱即用)。2.下载 Neo4j Desktop 应用[5],在本地创建数据库实例。

示例代码:

from langchain_community.graphs importNeo4jGraph

LLM 图转换器

LLM Graph Transformer 的设计目标,是提供一个灵活的框架,让我们可以利用任意大语言模型(LLM)来构建知识图谱。 由于当下有众多不同的模型和服务提供商,这项任务远非简单。

幸运的是,LangChain在标准化处理方面承担了大量工作。 至于 LLM 图转换器 本身,它就像是“两只猫套在风衣里” —— 具备两种完全独立的工作模式。

两种工作模式

LLM 图转换器 提供了两种模式,用于在不同场景下从文档中生成知识图谱:

1. 工具驱动模式(默认模式)

•适用于 LLM 支持 结构化输出函数调用 的情况。•此模式依赖 LLM 内置的 with_structured_output 方法[6],结合工具规范来定义输出格式。•这样,实体与关系就能以 结构化、预定义的形式 被准确提取。•在原文插图的左侧,可以看到 NodeRelationship 类的代码示例。

2. 提示驱动模式(回退模式)

•当 LLM 不支持工具或函数调用时,系统会退回到纯 Prompt 驱动 的方式。•使用 少样本提示(few-shot prompting) 来定义输出格式,引导 LLM 以文本形式抽取实体和关系。•随后,结果会经过一个自定义函数解析,转化为 JSON 格式,用于填充节点和关系。•本质上,与工具模式生成的结构一致,只是这里完全依赖 Prompt 进行引导。•在原文插图的右侧,可以看到提示示例及其对应的 JSON 输出。

灵活性与兼容性

•这两种模式保证了 LLM 图转换器 能够适配不同的 LLM:•可以直接使用工具提取;•也可以通过解析 Prompt 输出的文本来构建图谱。•即使模型本身支持工具/函数调用,你也可以通过设置 ignore_tools_usage=True 来强制启用 Prompt 模式。

为什么选择工具驱动提取?

我们最初选择 工具驱动模式 作为默认方案,原因在于它可以:

减少复杂的 Prompt 设计工作;•避免编写过多自定义解析函数

LangChain 中,with_structured_output 方法允许通过 工具函数 来提取信息:

•输出可以定义为 JSON 结构;•或者定义为 Pydantic 对象

就个人而言,我认为 Pydantic 对象 更加直观清晰,因此我们选择了这种方式。

以下是一个 Node 类的示例,用于描述知识图谱中的节点:

classNode(BaseNode):
Node 类说明

每个 节点(Node) 都包含以下部分:

id:节点唯一标识符(要求是 人类可读的唯一名称)。•说明:有些 LLM 会将 ID 理解为随机字符串或自增整数,但我们更希望 ID 能直接表示实体的名称。•label:节点标签(通过描述中列出可选项来限制标签类型)。•properties:可选的属性(用于存放节点的额外信息)。

此外,像 OpenAI 这样的模型支持 enum 参数,我们也利用这一特性来限制可用的标签范围。

Relationship 类定义

接下来是 关系(Relationship) 的定义:

classRelationship(BaseRelationship):
Relationship 类的改进(第二版)

这是 Relationship 类 的第二个迭代版本。

在最初的实现中,我们为关系的 起始节点(source)目标节点(target) 使用了嵌套的 Node 对象。
但实验发现:嵌套对象会降低提取的准确性和质量

因此,我们将其 扁平化,改为独立字段:

source_node_idsource_node_labeltarget_node_idtarget_node_label

另外,我们在 节点标签(label)关系类型(type) 的描述中,明确限定了可选值,确保 LLM 严格遵守既定的图谱模式(schema)。

定义属性类(Property)

工具驱动提取 模式下,我们可以为节点和关系都定义属性。
以下是用于定义属性的 Property 类:

classProperty(BaseModel):
属性(Property)的局限性

每个 Property 都是以 键值对(key-value pair) 的形式定义。
这种方式虽然灵活,但也存在一些局限:

•无法为每个属性单独提供唯一的描述。•无法区分哪些属性是 必填,哪些是 可选 —— 因此所有属性都被统一定义为可选。•属性并不是针对每种节点或关系类型分别定义的,而是 在所有节点和关系之间共享

系统提示(System Prompt)的作用

为了引导信息抽取,我们实现了一个详细的 系统提示[7]。 不过根据经验,函数及参数的描述 往往比系统提示对结果的影响更大。

遗憾的是,目前在 LLM Graph Transformer 中,还没有简便的方法去定制函数或参数的描述。

提示驱动模式(Prompt-based Extraction)

由于只有少数商用 LLM 和 LLaMA 3 支持原生工具,我们实现了一个 回退方案 —— 在模型不支持工具时,采用 Prompt 驱动模式

即便使用支持工具的模型,也可以通过设置 ignore_tool_usage=True 来强制使用 Prompt 模式。

提示驱动模式的大部分 Prompt 工程 和示例由 Geraldus Wilsen[8] 提供。

在这种模式下,输出结构必须直接在 Prompt 中定义。完整的 Prompt[9] 可以在原始代码中找到,这里只展示概要。

系统 Prompt 示例
You are a top-tier algorithm designed for extracting information in structured formats to build a knowledge graph.
提示驱动模式的关键差异

提示驱动模式(Prompt-based approach) 中,有一个重要区别:

•我们只要求 LLM 抽取关系(relationships),而不是单独抽取节点(nodes)。•这意味着输出中不会存在“孤立节点”,与 工具驱动模式 不同。•另外,由于缺乏原生工具支持的模型性能往往较差,我们在该模式下 不允许抽取任何属性(无论是节点属性还是关系属性),以保持结果输出的简洁性。

少样本示例(Few-shot Examples)

在 Prompt 中,我们会加入若干 少样本示例,用来引导 LLM 学习所需的抽取格式。
下面是部分示例代码:

examples =[
自定义 Few-shot 示例的限制

提示驱动模式 下,目前还 不支持添加自定义的 few-shot 示例 或额外的说明指令。
唯一的定制方式是通过 prompt 属性,直接修改整个 Prompt。

扩展自定义选项是我们正在积极考虑的方向。

定义图谱模式(Graph Schema)

在使用 LLM Graph Transformer 进行信息抽取时,定义图谱模式(schema) 至关重要。
它可以:

•指定需要抽取的 节点类型关系类型;•明确每个节点或关系所关联的属性;•为模型提供一个蓝图(blueprint),确保 LLM 输出的内容始终与目标知识图谱的结构保持一致。

一个良好的图谱模式,能帮助模型稳定地抽取有意义的结构化信息,从而构建出清晰、可用的知识图谱。

示例:Marie Curie + Robin Williams

在本篇博客的示例中,我们选取了 玛丽·居里(Marie Curie)[10] 的维基百科开头段落,并在结尾加了一句关于 罗宾·威廉姆斯(Robin Williams) 的描述。

from langchain_core.documents importDocument

使用 GPT-4o 作为 LLM

在所有示例中,我们都使用 GPT-4o 作为底层 LLM:

from langchain_openai importChatOpenAI

下面先看看在未定义任何图谱 schema 的情况下,抽取流程是如何工作的。

from langchain_experimental.graph_transformers importLLMGraphTransformer

接下来使用异步的 aconvert_to_graph_documents 来处理文档。 推荐在 LLM 抽取中使用 async:它可以并行处理多个文档,显著缩短等待时间、提升吞吐量,尤其适合批量场景。

data = await no_schema.aconvert_to_graph_documents(documents)

LLM Graph Transformer 的返回结果是一个图文档(graph document),其结构大致如下:

[
图文档与可视化

图文档(graph document)中不仅描述了抽取出的 节点(nodes)关系(relationships), 还会在 source 字段下附上 抽取所依据的源文档,便于溯源与校验。

我们可以使用 Neo4j Browser 对结果进行可视化,从而获得更清晰、直观的理解。

下图(原文示意)展示了**在未定义图谱模式(schema)**的情况下,对同一段玛丽·居里(Marie Curie)文本进行两次抽取的可视化对比。
本例使用 GPT-4 的工具驱动抽取,因此可能出现“孤立节点”。

由于没有预先定义 schema,LLM 会在运行时自行决定抽取哪些信息:

•即便是同一段文本,不同次的输出也可能存在差异;•有的结果更详细,有的在结构上也会有所不同。
例如:左图把 Marie 表达为 Nobel Prize 的 WINNER,右图则表达为 Marie WON 了 Nobel Prize —— 语义相近,但关系类型与表述结构不同。

使用提示驱动模式(Prompt-based)进行同样的抽取

对于 支持工具 的模型,也可以通过设置 ignore_tool_usage 参数来启用 提示驱动模式

no_schema_prompt =LLMGraphTransformer(llm=llm, ignore_tool_usage=True)
使用提示驱动模式的效果与局限

提示驱动模式(prompt-based approach) 下,不会出现“孤立节点”。
不过,与之前的抽取一样,由于未定义 schema,同一输入在不同运行之间的结构仍可能变化,从而得到不同的输出。

通过定义图谱模式获得更一致的结果

接下来看看:定义图谱 schema 如何帮助产出更一致的结果。

限定允许的节点类型(Defining allowed nodes)

对抽取到的图结构进行约束非常有帮助,它能引导模型聚焦于特定且相关的实体与关系。 通过定义清晰的 schema,你可以显著提升多次抽取之间的一致性,让结果更可预测、更符合实际需求。
这将降低不同运行之间的波动,确保抽取数据遵循标准化结构,并捕获预期中的信息。
在一个良好定义的 schema 下,模型更不容易遗漏关键细节,也更不容易引入意外元素,最终得到更干净、可用性更强的图。

我们先用 allowed_nodes 参数定义期望抽取的节点类型:

allowed_nodes =["Person","Organization","Location","Award","ResearchField"]

在这里,我们规定 LLM 只能抽取五类节点,如 PersonOrganizationLocation 等。 随后,可以在 Neo4j Browser 中对两次独立执行的结果进行可视化对比。

通过明确期望的节点类型,节点抽取的确会更一致;但仍可能出现差异。
例如:第一次运行中将 “radioactivity(放射性)” 抽取为 ResearchField,而第二次运行则未抽取到。

由于我们尚未限定关系类型,不同运行间的关系抽取也会不一致;且有的结果信息更丰富。
比如:MARRIED_TO(已婚/配偶)这一关系(Marie 与 Pierre 之间)并非在两次抽取中都出现。

仅限定节点类型,关系抽取仍会波动。接下来我们同时限定关系类型,以进一步提升一致性。

定义允许的关系类型(Defining allowed relationships)

第一种做法是以枚举列表的方式,指定允许的关系类型:

allowed_nodes =["Person","Organization","Location","Award","ResearchField"]

随后,可以再次对两次独立抽取进行对比可视化,观察在限定了节点与关系之后,输出在结构与语义上的一致性是否显著提升。

同时限定节点与关系后的效果

节点类型关系类型都被限定后,输出的一致性显著提升。
例如:关于 Marie 的信息会稳定地包含:

获得奖项(如诺贝尔奖);•与 Pierre 为配偶关系;•就职/任教于巴黎大学

不过,由于关系仅以通用列表的方式定义,且未限制可连接的节点类型,仍会出现一些差异:

FIELD_OF_RESEARCH(研究领域)有时会在 Person ↔ ResearchField 之间建立,
但也可能错误地出现在 Award ↔ ResearchField 之间。•此外,我们没有定义关系方向,因此方向一致性也可能不稳定。

新增:关系的三元组约束(限定端点与方向)

为了解决无法指定关系可连接的节点类型以及无法强制方向的问题,我们引入了新的关系定义方式,如下所示:

allowed_nodes =["Person","Organization","Location","Award","ResearchField"]
使用三元组格式定义关系

与之前用 字符串列表 定义关系不同,现在我们采用 三元组(tuple) 的格式来描述关系:

第 1 个元素:源节点类型(Source Node)•第 2 个元素:关系类型(Relationship Type)•第 3 个元素:目标节点类型(Target Node)

这种方式的优势在于:

•明确规定了 关系必须连接的节点类型;•保证了 关系的方向性;•大幅提升了抽取结果的 一致性与准确性

可视化结果

通过在 Neo4j Browser 中再次进行可视化,可以直观对比:

•使用 字符串列表 定义关系时的不确定性;•采用 三元组格式 后,关系结构更加稳定、语义更加清晰的效果。

三元组关系的稳定性与剩余差异

采用 三元组(source, relation, target) 的关系定义后,多次执行间的 schema 一致性 显著提升。
不过,由于 LLM 的固有特性,细节层面的差异 仍可能存在:

•例如右侧结果中显示 Pierre 获得了诺贝尔奖,而左侧结果则缺少这一信息。

定义属性(Properties)

改进图谱 schema 的最后一步,是为 节点关系 定义属性。这里有两种思路:

方案一:让模型自主决定提取哪些属性

node_propertiesrelationship_properties 设为 True,允许 LLM 自主判定要抽取的属性键值对。
优点是简便、能快速捕获更多细节;缺点是不够可控、不同运行间可能存在差异。

示例代码:

allowed_nodes =["Person","Organization","Location","Award","ResearchField"]

接下来即可查看结果,评估在属性启用后,节点与关系是否携带了更丰富的上下文信息(如时间、职位、地点、获奖年份等)。

注:方案二通常是显式列举允许的属性键并限制类型与必选/可选,但本文段落暂仅介绍“让模型自主决定”的做法。

在该方案中,我们允许 LLM 自主决定为节点或关系添加它认为相关的属性。
例如,模型会补充:

玛丽·居里(Marie Curie)出生/逝世日期;•她在 巴黎大学任教(Professor at the University of Paris) 的角色信息;•她 两次获得诺贝尔奖 的事实。

这些附加属性显著丰富了抽取的信息密度,让图谱更具语义价值。

第二种做法是明确列出我们希望抽取的节点属性关系属性,从而让输出更可控、更一致

allowed_nodes =["Person","Organization","Location","Award","ResearchField"]

接下来即可查看 LLM 的抽取结果,验证是否正确填充了:

与前一次抽取相比,出生日期逝世日期保持一致。
此外,这一次模型还抽取出了 玛丽在巴黎大学任教的起始日期(教授任期的开始时间)。

引入 属性(Properties) 的确能显著提升信息的深度与可用性,但当前实现仍存在一些限制:

1.只能在工具驱动模式下 抽取属性(prompt 驱动模式不支持)。2.所有属性都以字符串(string)形式 返回(缺少类型化,如日期/数字/布尔等)。3.属性只能 全局定义,而不能按节点标签或关系类型分别指定。4.无法自定义属性的描述 来进一步约束或引导 LLM 提取得更精确。

严格模式(Strict Mode)

如果你以为我们已经找到了让 LLM 完美遵循 schema 的方法,那我需要澄清一下:
即便投入了大量的 Prompt 设计工作,要让 LLM(尤其是性能较弱的模型)百分之百 严格遵循指令仍然很难。

为此,我们引入了一个后处理步骤——strict_mode

•它会 移除 所有 不符合已定义图谱 schema 的信息,•以获得更干净、更一致的输出。

默认情况下,strict_mode=True。你也可以手动关闭:

LLMGraphTransformer(

关闭严格模式后,LLM 可能会输出 超出 schema 定义的节点或关系类型, 因为模型有时会“发挥创意”,产生不在约束内的结构。

将图文档导入图数据库

LLM Graph Transformer 抽取出的图文档,可以导入到图数据库(如 Neo4j)中,
以便进行后续的分析与应用。
导入时可使用 add_graph_documents 方法,根据不同场景选择不同的导入策略。

默认导入(Default Import)

最简单的方式是直接将节点与关系导入 Neo4j,示例代码如下:

graph.add_graph_documents(graph_documents)

此方法会直接导入传入的图文档中的所有节点与关系。 在本文的实验与演示中,我们一直采用这种方式来验证不同 LLM 与 schema 配置下的结果。

基础实体标签(Base Entity Label)

大多数图数据库都支持 索引(indexes) 来优化数据的导入与检索。
Neo4j 中,索引只能设置在特定的 节点标签(node labels) 上。

然而,我们可能事先并不知道所有的节点标签。
为了解决这个问题,可以通过 baseEntityLabel 参数,
为每个节点添加一个 次级的基础标签,以便统一建立索引。

示例代码:

graph.add_graph_documents(graph_documents, baseEntityLabel=True)

启用 baseEntityLabel 后,每个节点都会额外拥有一个__Entity__标签。 这样我们就能基于 __Entity__ 建立索引,从而提升 导入效率 和 查询性能, 而无需为图中每个可能出现的节点标签单独设置索引。

导入源文档(Include Source Documents)

最后一个可选项是 同时导入源文档,以记录节点与关系的出处。
这种方式可以帮助我们追踪:某个实体或关系来源于哪些文档, 便于后续的溯源与分析。

启用方法:在导入时设置 include_source=True

graph.add_graph_documents(graph_documents, include_source=True)

在可视化结果中,源文档(source document) 会以蓝色高亮显示,
并通过 MENTIONS 关系与从该文档中抽取出的所有实体相连。

这种模式不仅能展示信息来源,还可以构建同时利用
结构化搜索非结构化搜索 的检索器(retrievers)[11], 从而提升检索增强生成(RAG)的能力。

总结

在这篇文章中,我们探索了 LangChain 的 LLM Graph Transformer
以及它的两种构建知识图谱的模式:

工具驱动模式(Tool-based mode)•我们的主要方法。•借助结构化输出与函数调用,减少了 Prompt 设计的复杂性。•支持属性(Properties)的抽取。•提示驱动模式(Prompt-based mode)•当工具不可用时的替代方案。•依赖少样本示例(few-shot examples)来引导 LLM 输出。•不支持属性抽取,且不会生成孤立节点。

图谱 Schema 的重要性

实验表明,清晰的图谱 Schema 定义(包括允许的节点类型与关系类型):

•能显著提升抽取结果的一致性与性能;•确保输出严格遵循目标结构;•让结果更可预测、更可靠,并便于应用在下游任务中。

应用价值

无论是工具驱动还是提示驱动,
LLM Graph Transformer 都能将非结构化文本转化为更有组织、更结构化的表示。
这对于:

RAG 应用多跳推理查询(multi-hop queries)

都具有重要价值。

获取与尝试

•代码已在 GitHub[12] 开源。•你也可以在 Neo4j 提供的托管 LLM Graph Builder 应用 中,
通过 零代码环境(no-code environment) 来尝试 LLM Graph Transformer。

https://medium.com/data-science/building-knowledge-graphs-with-llm-graph-transformer-a91045c49b59

读者福利大放送:如果你对大模型感兴趣,想更加深入的学习大模型**,那么这份精心整理的大模型学习资料,绝对能帮你少走弯路、快速入门**

如果你是零基础小白,别担心——大模型入门真的没那么难,你完全可以学得会

👉 不用你懂任何算法和数学知识,公式推导、复杂原理这些都不用操心;
👉 也不挑电脑配置,普通家用电脑完全能 hold 住,不用额外花钱升级设备;
👉 更不用你提前学 Python 之类的编程语言,零基础照样能上手。

你要做的特别简单:跟着我的讲解走,照着教程里的步骤一步步操作就行。

包括:大模型学习线路汇总、学习阶段,大模型实战案例,大模型学习视频,人工智能、机器学习、大模型书籍PDF。带你从零基础系统性的学好大模型!

现在这份资料免费分享给大家,有需要的小伙伴,直接VX扫描下方二维码就能领取啦😝↓↓↓
在这里插入图片描述

为什么要学习大模型?

数据显示,2023 年我国大模型相关人才缺口已突破百万,这一数字直接暴露了人才培养体系的严重滞后与供给不足。而随着人工智能技术的飞速迭代,产业对专业人才的需求将呈爆发式增长,据预测,到 2025 年这一缺口将急剧扩大至 400 万!!
在这里插入图片描述

大模型学习路线汇总

整体的学习路线分成L1到L4四个阶段,一步步带你从入门到进阶,从理论到实战,跟着学习路线一步步打卡,小白也能轻松学会!
在这里插入图片描述

大模型实战项目&配套源码

光学理论可不够,这套学习资料还包含了丰富的实战案例,让你在实战中检验成果巩固所学知识
在这里插入图片描述

大模型学习必看书籍PDF

我精选了一系列大模型技术的书籍和学习文档(电子版),它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础。
在这里插入图片描述

大模型超全面试题汇总

在面试过程中可能遇到的问题,我都给大家汇总好了,能让你们在面试中游刃有余
在这里插入图片描述

这些资料真的有用吗?

这份资料由我和鲁为民博士(北京清华大学学士和美国加州理工学院博士)共同整理,现任上海殷泊信息科技CEO,其创立的MoPaaS云平台获Forrester全球’强劲表现者’认证,服务航天科工、国家电网等1000+企业,以第一作者在IEEE Transactions发表论文50+篇,获NASA JPL火星探测系统强化学习专利等35项中美专利。本套AI大模型课程由清华大学-加州理工双料博士、吴文俊人工智能奖得主鲁为民教授领衔研发。

资料内容涵盖了从入门到进阶的各类视频教程和实战项目,无论你是小白还是有些技术基础的技术人员,这份资料都绝对能帮助你提升薪资待遇,转行大模型岗位。
在这里插入图片描述
👉获取方式

😝有需要的小伙伴,可以保存图片到VX扫描下方二维码免费领取【保证100%免费】
在这里插入图片描述
相信我,这套大模型系统教程将会是全网最齐全 最适合零基础的!!

Logo

为武汉地区的开发者提供学习、交流和合作的平台。社区聚集了众多技术爱好者和专业人士,涵盖了多个领域,包括人工智能、大数据、云计算、区块链等。社区定期举办技术分享、培训和活动,为开发者提供更多的学习和交流机会。

更多推荐