从非结构化数据(如文本)中提取结构化信息,这项技术已经存在有一段时间了,并不是什么新鲜事。然而,大型语言模型(LLMs)为信息提取领域带来了重大变革。
如果说以前你需要一个机器学习专家团队来整理数据集和训练自定义模型,如今只需要接入一个大型语言模型即可。进入门槛大幅降低,使得原本仅限于领域专家的操作,现在连非技术人员也能轻松上手。
信息提取管道的目标是从非结构化文本中提取结构化信息。图示描述了非结构化文本如何被转化为结构化信息的过程。该过程被称为“信息提取管道”,最终结果是一种图结构形式的信息。图中的节点表示关键实体,连线则代表实体之间的关系。
知识图谱(Knowledge Graph)在以下场景中非常有用:
•多跳问答(Multi-hop Question Answering)•实时分析(Real-time Analytics)•在单一数据库中结合结构化与非结构化数据
虽然借助 LLM 元宝 混元 Hunyuan 教程提取结构化信息变得更容易,但这绝不是一个已经完全解决的问题。
在本篇文章中,我们将结合 OpenAI 的函数功能与 LangChain,从一个示例 Wikipedia 页面构建一个知识图谱。在这个过程中,我们将探讨一些最佳实践,并讨论当前 LLM 的一些局限性。
你需要配置一个 Neo4j 实例以便运行本文中的示例。
方式一:使用 Neo4j Aura 启动云端数据库实例
Neo4j Aura 提供免费的云实例,是最便捷的方式。
方式二:本地安装 Neo4j
1.下载并安装 Neo4j Desktop 应用2.创建本地数据库实例
以下是一个用于连接 Neo4j 数据库的 LangChain 包装器代码示例:
一个典型的信息提取流程通常包含以下几个步骤:
多步信息提取流程示意图
1. 指代消解(Coreference Resolution)
在第一步中,我们将输入文本输入到一个指代消解模型中。指代消解任务的目标是找出所有指向同一实体的表达方式。简单来说,就是将所有代词链接到其所指代的具体实体上。
2. 命名实体识别(Named Entity Recognition)
在信息提取流程的实体识别部分,我们尝试从文本中提取出所有被提及的实体。
示例中提到的实体包括:
•Tomaz•Blog•Diagram
3. 实体消歧(Entity Disambiguation)
下一步是实体消歧(Entity Disambiguation),这是信息提取流程中一个非常关键但常常被忽视的环节。
实体消歧的任务是准确识别并区分名称相似或引用模糊的实体,以确保在特定上下文中识别出正确的对象。
4. 实体关系识别(Relation Extraction)
在最后一步中,模型会尝试识别实体之间的各种关系。
例如,它可能识别出 Tomaz 与 Blog 之间存在 (喜欢)关系。
OpenAI Functions 是从自然语言中提取结构化信息的极佳工具。其核心理念是:由 LLM 生成一个预定义的 JSON 对象,并填充相应的值。这个预定义的 JSON 对象可以作为输入传递给其他函数(如 RAG 应用中的函数),也可以用于从文本中提取特定的结构化信息。
在 LangChain 框架中,你可以使用 Pydantic 类 来定义所需的 JSON 数据结构,并作为 OpenAI Functions 的描述输入。因此,我们的第一步是定义我们希望从文本中提取的结构信息结构。幸运的是,LangChain 已经定义好了用于表示实体节点(Nodes)和实体关系(Relationships)的 Pydantic 类,我们可以直接复用这些类。接下来可以进入代码部分,演示如何构建这些类并实现信息提取功能。
遗憾的是,目前 OpenAI Functions 并不支持将字典对象作为值(value)。因此,我们需要重写属性(properties)的定义,以符合 Functions 接口的限制条件。也就是说,在定义结构化信息的 JSON 输出格式时,不能直接使用嵌套的字典结构,而需要使用 OpenAI Functions 支持的扁平化数据结构格式。
在这里,我们将 的值从字典改写为 类的列表,以克服 OpenAI Functions 接口的限制。由于该 API 只允许传递一个对象,我们将所有的节点(nodes)和关系(relationships)组合进一个名为 的单一类中。通过这种方式,我们可以在不违反 API 要求的前提下,同时传递完整的结构化信息。
最后只剩下一件事要做,那就是进行一些提示词工程(Prompt Engineering),然后我们就可以开始运行了。
1.用自然语言反复优化提示词以改善输出结果2.如果某些表达没有达到预期效果,就请 ChatGPT 帮忙重新表述任务,使其对 LLM 更加清晰可理解3.当提示词包含了所有必要的指令后,再请 ChatGPT 将这些指令总结为 Markdown 格式,这样可以节省 token,并有可能使指令更加清晰。
我之所以特别选择使用 Markdown 格式,是因为我在某处看到过:OpenAI 的模型对提示词中的 Markdown 语法响应更好。从我的实际经验来看,这一点是有道理的,至少是合理的猜测。
在反复迭代提示词工程后,我设计出了以下这个用于信息提取流程的系统提示词(System Prompt):
我们在这里使用的是 GPT-3.5 的 16k 版本,主要原因在于 OpenAI Functions 的输出是结构化的 JSON 对象,而 JSON 的语法结构会显著增加 token 消耗。换句话说,为了获得结构化输出的便利性,我们需要付出更多的 token 空间作为代价。
除了常规指令外,我还添加了一个可选项,可以限制从文本中提取哪些类型的实体或关系。 在后续的示例中你会看到,这一功能在很多场景下都非常实用。
此时,我们已经完成了 Neo4j 连接配置 和 LLM 提示词设置,接下来可以将整个信息提取流程封装为一个单一函数进行调用。
这个函数接收一个 LangChain 的 Document 文档对象,以及两个可选参数: 和 ,用于限制我们希望 LLM 识别和提取的对象类型。
大约在一个月前,我们在 Neo4j 的图对象中新增了一个方法:, 这个方法可以在这里派上用场,用于无缝导入知识图谱数据,大大简化了处理流程。
我们将从 沃尔特·迪士尼(Walt Disney) 的 Wikipedia 页面中提取信息,并构建一个知识图谱,以测试信息提取流程的效果。
在这个过程中,我们将使用 LangChain 提供的 Wikipedia 加载器 和 文本分块模块 来处理数据。
你可能注意到了,我们设置了一个相对较大的 值,这是因为我们希望在每个文本块中提供尽可能多的上下文信息,以确保指代消解(coreference resolution) 部分的效果尽可能好。
请记住:指代消解只有在实体及其代词引用出现在同一个文本块中时才会生效,否则 LLM 无法获取足够的信息来建立它们之间的联系。
整个处理过程大约需要 5 分钟左右,相对来说是比较慢的。因此,在生产环境中,你可能会希望采用并行调用 API 的方式来解决这个问题,以实现一定程度的可扩展性(scalability)。
接下来,让我们先看看 LLM 所识别出的 节点(Nodes) 和 关系(Relationships) 类型。
由于我们没有预先提供图谱的结构定义(schema),LLM 会在运行时动态决定使用哪些节点标签(node labels)和关系类型(relationship types)。例如,我们可以观察到生成的图谱中同时存在 和 两种节点标签。这两者在语义上可能是相似或等同的,因此在实际项目中,我们通常更希望用一个统一的节点标签来表示这两种实体。
对于任何更为严肃或正式的项目,建议你预先定义好节点标签和关系类型,并明确指定 LLM 应该提取哪些类型的信息。幸运的是,我们已经为提示词增加了一个功能:你可以通过传入额外参数来限制 LLM 提取的节点和关系类型,从而避免上述类型不一致的问题。
在这个示例中,我只限制了节点标签(node labels),但你也可以通过向 函数传入另一个参数,轻松限制关系类型(relationship types) 的提取范围。
提取出的子图在可视化后具有如下结构:
最终生成的图谱比预期效果更好(经过了 5 次迭代 😄)。尽管在可视化中我没能完整展示整张图谱,但你可以在 Neo4j Browser 或其他图数据库工具中自行进行交互式探索。
有一点需要特别说明:在本次流程中,我们部分跳过了实体消歧步骤。尽管我们使用了较大的文本块(chunk size),并在系统提示词中添加了专门针对指代消解与实体消歧的指令,但由于每个文本块是独立处理的,导致我们无法保证不同块之间实体的一致性。举个例子,你可能会看到图谱中出现了两个代表同一个人物的节点,这正是由于不同文本块未能统一实体识别所造成的。
在本示例中,“Walt Disney” 和 “Walter Elias Disney” 实际上指的是同一个现实中的人物。 这正是实体消歧(Entity Disambiguation)问题的典型案例。
这个问题并不新颖,已经有多种方法被提出用于解决它,例如:
•✅ 使用实体链接(Entity Linking)或实体消歧的自然语言处理模型•✅ 对文本进行第二轮处理,通过 LLM 执行全局实体消歧任务•✅ 使用图结构方法(Graph-based Approaches)进行实体对齐和合并
你应该根据具体的应用场景和领域需求来决定使用哪种方案。不过请务必牢记:实体消歧不应被忽视,它对于提升 RAG 应用的准确性与效果具有至关重要的作用。
最后一部分,我们将展示如何通过构造 Cypher 查询语句 来浏览知识图谱中的信息。Cypher 是一种用于图数据库的结构化查询语言,其作用类似于 SQL 在关系型数据库中的作用。通过 Cypher,你可以对图中的节点、关系进行灵活的查询与分析。
LangChain 提供了一个名为 的组件, 它可以:
•自动读取图谱的结构(schema)•根据用户输入智能构造相应的 Cypher 查询语句•实现图谱问答(Graph-based QA)功能
通过这一组件,用户无需掌握 Cypher 的语法细节,也能实现对图谱的自然语言问答交互。
查询结果展示:
当你的 RAG 应用需要同时处理结构化数据与非结构化数据时,知识图谱(Knowledge Graphs)是非常理想的选择。在本篇文章中,你学习了如何使用 OpenAI Functions,从任意文本中提取信息并在 Neo4j 中构建知识图谱。OpenAI Functions 提供了结构清晰的输出形式, 因此在执行结构化信息提取任务时非常高效、便捷。
提升构建体验的建议:
•✅ 在开始构建前,尽可能详细地定义图谱的 Schema(结构)•✅ 在信息提取完成后,加入实体消歧步骤,以确保图谱节点的准确性与一致性
通过这些优化措施,你可以获得更高质量、更可控的图谱构建体验。
本文由笔者翻译整理自:https://bratanic-tomaz.medium.com/constructing-knowledge-graphs-from-text-using-openai-functions-096a6d010c17,如对您有帮助,请帮忙点赞、转发,谢谢!
发布者:Ai探索者,转载请注明出处:https://javaforall.net/278524.html原文链接:https://javaforall.net
