用Graph Maker轻松将文本转换为知识图谱
2024/12/20 21:04:13
本文主要是介绍用Graph Maker轻松将文本转换为知识图谱,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
这张图片是由作者用Adobe Photoshop制作的
在这篇文章中,我将分享一个Python库——Graph Maker(图形制作库),它可以根据给定的本体(Ontology)从文本语料库创建知识图谱。Graph Maker使用开源的大语言模型(LLM),如Llama3、Mistral、Mixtral或Gemma(这些模型用于提取知识图谱中的信息)。
我们来谈谈图生成器(Graph Maker)的“为什么”的基本概念,回顾一下上一篇文章的基本内容,以及当前方法是如何解决这些挑战的。最后我会在本文结尾分享GitHub仓库。
这是几个月前我写的一篇文章的后续文章,关于如何将任何文本转换成图形。
这篇文章得到了强烈的反响。文章中提到的GitHub仓库已经获得了超过180次分叉(Forks)和超过900次点赞(Stars)。文章本身在Medium上有超过80K的阅读量。最近,这篇文章还被麻省理工学院的马库斯·J·布赫勒教授在他的论文中引用。
这是一篇非常迷人的论文,展示了知识图谱在AI时代巨大的潜力。它展示了知识图谱不仅能用来检索知识,还能用来发现新知识。这里是我最喜欢的论文片段之一。
“比如,我们将展示这种方法如何将看似不相关的概念联系在一起,比如贝多芬的第九交响曲与仿生材料科学之间的联系。”
这进一步肯定了我在之前文章中提出的想法,让我更有信心继续探索这些想法。
我也收到了许多来自同行的反馈,关于他们在使用仓库时遇到的问题以及对改进的建议。我将其中一些意见融入到了我在这里分享的一个新的Python包中。
在我们讨论“图制作器”的工作原理之前,让我们先讨论为什么要用它以及它是什么。
我们最好还是先从“为什么使用图”开始。不过,我在我的之前的文章中已经简要讨论过这个话题了。回头看看那篇文章复习一下。不过,让我们快速地在这里简要回顾一下与我们当前讨论相关的重要概念。
如果你已经熟悉知识图谱的相关背景,可以直接略读这一部分。
这里有一个简洁地说明知识图谱概念的例子。
请参阅链接:https://arxiv.org/abs/2403.11996。
创建一个知识图谱(KG),我们只需要两条信息。
- 知识库:知识库可以是一系列文本、代码库、文章集合等等。
- 本体论:本体论是指我们关注的实体类型及其关系类型。这里我对本体论的定义做了简化,但这样解释对我们来说足够了。
这是一个简单的本体
实体:人,地方
关系:
人A和人B — 与...有关 → 人
人 — 住在 → 地方
人 — 去 → 地方
有了这两条信息,我们可以从提到人物和地点的文本中构建一个知识图谱(KG)。然而,如果我们的知识库是关于处方药及其相互作用的临床研究,我们可能会使用不同的本体(例如化合物、用法和效果、反应等构成我们的本体,化合物、用法和效果、反应等可能构成我们的本体)。
在前一篇文章中,我们讨论了如何让LLM自动生成知识图,而不提供任何本体定义。我们的想法是让LLM自行发现最适合给定文本数据集的本体结构。
尽管这种方法缺乏生成知识图谱(KG)的传统方法的严谨性,但它也有其优点。它能比传统方法更容易地从非结构化数据中生成知识图谱。它生成的知识图谱在某种程度上也属于非结构化的。然而,它们不仅更易于构建,还包含更多信息。它们非常适合应用于类似GRAG(图谱检索增强生成)这样的场景。
让我列出我在之前的文章中收到的一些反馈中的挑战与观察。这将帮助我们理解在使用大语言模型创建知识图谱时所面临的挑战。我们用维基百科上的《指环王》书籍简介来说明。毕竟,谁会不喜欢《指环王》呢!
如果自由运行,LLM 在自由运行下提取的实体类别可能过于多样。它可能会误将抽象概念当作实体来标记。例如,在“比尔博·巴金斯庆祝他的生日并将戒指留给弗罗多”这句话中,LLM 可能会将“比尔博·巴金斯庆祝他的生日”或“庆祝他的生日”标记为‘动作’(Action)。但更实用的做法是将其提取为‘事件’(Event)。
它也可能在同一实体上,在不同的上下文中错误地标记为不同。例如:
‘ 索伦’ , ‘ 魔君索伦’ 和 ‘ 魔君’ 不应作为不同的实体分离。或者如果它们被提取为不同的实体,它们之间应视为等价。索伦又称“黑暗魔君”。
大型语言模型的输出本质上是不可预测的。为了从一个大的文档中提取知识图谱,我们必须将文本拆分成更小的片段,然后为每个片段生成子图。为了构建完整的知识图谱,语言模型必须按照给定模式一致地输出JSON对象。缺少任何一个都可能严重影响整个图谱的连接性。
虽然LLM在生成格式良好的JSON对象方面越来越熟练,但还是离完美很远。由于上下文窗口有限,这些LLM有时也会给出不完整的回复。
大语言模型在识别实体时可能会犯很多错误,特别是在处理特定领域的内容或实体名称不符合英语标准表达的情况下,这成了一个更大的问题。虽然命名实体识别(NER)模型在这方面表现得更好,但它们也受限于训练时的数据。此外,它们也搞不懂这些实体之间的关系。
使大型语言模型在分类上保持一致体现了提示设计的艺术。
关系可以被直接提到,也可以由上下文隐含。例如,
“比尔博·巴金斯在庆祝生日时把戒指留给弗罗多”意味着以下关系:
比尔博·巴金斯 → 拥有者 → 戒指
比尔博·巴金斯 → 遗产继承人 → 弗罗多
弗罗多 → 拥有者 → 戒指
在这里,我认为LLM在某个时候会比任何传统方法更擅长提取关系。但是现在,这仍然是一项需要巧妙提示设计的挑战。
我在这里分享的图形制作库改进了之前的方案,在严谨性和便捷性之间找到了一个平衡点——在有结构和无结构之间找到了一个平衡点。在大多数上述挑战中,这个图形制作库比之前我讨论的方法做得更好。
与之前的 approach 不同,在之前的 approach 中,LLM 可以自由地自己发现本体,而 graph maker 则试图强迫 LLM 使用用户定义的本体结构。
可以用一条简单的 pip 命令安装知识图谱制作库
pip install knowledge-graph-maker
这里有五个简单的步骤,告诉你它是如何工作的。
这些步骤写在一个笔记本里,我会在本文末尾分享这个笔记本。
该库遵循以下本体模式。实际上,本体是一个 pydantic模型。
ontology = Ontology( # 要提取的实体标签。可以是字符串或如下所示的对象。 labels=[ {"Person": "人名,不带任何形容词。记住,一个人可能通过名字或代词来指代他人"}, {"Object": "对象名称中不要添加定冠词 'the'"}, {"Event": "涉及多人的事件,不要包含像 gives, leaves, works 这样的限定词或动词"}, "Place", "Document", "组织", "Action", {"Miscellaneous": "任何无法归类到其他给定标签的重要概念"}, ], # 对应用程序来说重要的关系。 # 这些更像是给 LLM 的指令,让它专注于特定的关系。 # 没有保证只会提取这些关系,但一些模型能很好地专注于这些关系。 relationships=[ "任意两个实体之间的关系", ], )
我已经调整了提示,以确保结果与给定的本体一致。我认为它在这方面做得相当不错,效果令人满意。但是,准确度仍然无法达到100%。准确性取决于我们选择的生成模型、应用场景、本体及其数据质量。
我们可以使用任意大小的语料库来创建知识图。然而,当前的大语言模型具有有限的上下文窗口。因此,我们需要适当切分文本,并逐步构建知识图。我们应使用的分块大小应根据模型的上下文窗口来确定。该项目中使用的提示大约消耗500个token。剩余的上下文可以分为输入文本和生成的知识图。根据我的经验,使用200到500个token的小块可以生成更详细的知识图。
该文档是一个 Pydantic 模型,具有以下模式
## Pydantic 文档模型示例 class Document(BaseModel): text: str metadata: 元数据
我们在这里为文档添加的元数据都会标记到从文档中提取出的每个关系上。
我们可以加入关系的背景信息,例如页码、章节名、文章名等。大多数情况下,每个节点在多个文档中与其他节点存在多种联系。元数据有助于明确这些关系。
图形生成器直接处理一份文档列表,并对每个文档进行处理,为每个文档生成一个子图。最终输出的是所有文档的完整图形。
这里有个简单的例子说明怎么做。
from knowledge_graph_maker import GraphMaker, Ontology, GroqClient ## -> 选择一个 Groq 支持的模型,例如 model = "mixtral-8x7b-32768" # model = "llama3–8b-8192" # model = "llama3–70b-8192" # model = "gemma-7b-it" ## 这可能是所有模型中最快的,不过稍微有点不准确。 ## -> 初始化 Groq 客户端,准备使用。 llm = GroqClient(model=model, temperature=0.1, top_p=0.5) graph_maker = GraphMaker(ontology=ontology, llm_client=llm, verbose=False) ## -> 根据文档列表创建一个图。 graph = graph_maker.from_documents(docs) ## 结果:一个边的列表。 print(f"总边数:{len(graph)}") ## 1503
图生成程序会将每个文档通过大型语言模型处理,并解析响应,生成完整图。最终结果是一个边的列表,其中每条边都是像下面这样的 Pydantic 模型。
class Node(BaseModel): # 基础模型类 label: str # 标签 name: str # 名称 class Edge(BaseModel): # 基础模型类 node_1: Node # 节点1 node_2: Node # 节点2 relationship: str # 关系 metadata: dict = {} # 元数据 order: Union[int, None] = None # 顺序
我已经调整了提示语,现在生成的JSON更加一致了。如果JSON响应解析失败,图形生成器会尝试手动拆分JSON字符串,尽可能修复。
我们可以将模型保存到Neo4j,以创建一个RAG应用程序,运行网络分析算法,或者只是用Bloom来可视化图。
from knowledge_graph_maker import Neo4jGraphModel # 设置是否创建索引为False create_indices = False # 使用graph作为边缘数据创建Neo4j图模型,是否创建索引为False neo4j_graph = Neo4jGraphModel(edges=graph, create_indices=create_indices) # 保存图模型 neo4j_graph.save()
图中的每条边都作为事务被保存到数据库中。如果你是首次运行此代码,则将「create_indices」设置为 true。这会通过在节点上设置唯一性限制来预先准备数据库。
5.1 纯粹为了好玩,可视化一下
在上一篇文章中,我们使用 networkx 和 pyvis 库可视化了图。所以这里可以直接用 Bloom 来看图。
为了避免重复自己,让我们制作一个不同于前一篇文章的可视化图表。
我们喜欢看看书中人物间的关系是如何演变的
我们可以这样做,通过跟踪在图构建过程中边是如何逐步加入到图中的。为了做到这点,Edge 模型有一个叫做“顺序号”的属性。这个属性可以让图具有时间或顺序维度。
在我们的例子中,图生成器会自动在从每个文本片段中提取的每条边上添加该片段在文档列表中的顺序号。这样一来,我们可以通过按边的顺序切分图来观察角色间关系的发展。
这里有一些横截面图的动画展示。
作者生成的动画
这类知识图谱(KG)最可能的应用可能是RAG技术。Medium上有许多文章介绍如何利用图来增强你的RAG系统。
图数据库提供了多种不同的手段来获取信息。根据我们如何设计图和应用程序,其中一些方法可能会比简单的语义搜索更有效。
最基本的做法是,在节点和关系中添加嵌入向量,并通过向量索引进行语义搜索来检索。然而,我认为图在RAG这类应用中的真正优势在于将Cypher查询、网络算法与语义搜索结合起来的时候。
我自己也在探索这些技术。我打算在我的下一篇专栏里谈谈这些技巧。
这里是我的GitHub仓库。请随意体验一下。我还提供了一个示例Python笔记本在仓库中,这可以帮助你快速开始。
请注意,你需要在 .env 文件里添加你的 GROQ 凭据,才能开始使用。
最初,我是为了几个个人项目开发了这套代码库。我相信它对许多其他应用也会很有帮助。如果你在我的库基础上开发了自己的应用,请和我分享一下。我很想了解你是如何使用的。
如果你愿意为这个开源项目积极贡献,请把它当作你自己的作品来参与。
我希望你觉得这个图表制作器很有用。谢谢。
我是一名学习建筑技术的学员(不是指建筑物……而是指技术方面的)。以前,我从事过半导体模型设计、数字电路设计、电子接口设计以及物联网相关工作。
目前,我在沃尔玛的数据及消费者分析工作上忙得不可开交。
好的,谢谢
这篇关于用Graph Maker轻松将文本转换为知识图谱的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-20自建AI入门:生成模型介绍——GAN和VAE浅析
- 2024-12-20游戏引擎的进化史——从手工编码到超真实画面和人工智能
- 2024-12-20利用大型语言模型构建文本中的知识图谱:从文本到结构化数据的转换指南
- 2024-12-20揭秘百年人工智能:从深度学习到可解释AI
- 2024-12-20复杂RAG(检索增强生成)的入门介绍
- 2024-12-20基于大型语言模型的积木堆叠任务研究
- 2024-12-20从原型到生产:提升大型语言模型准确性的实战经验
- 2024-12-20啥是大模型1
- 2024-12-20英特尔的 Lunar Lake 计划:一场未竟的承诺
- 2024-12-20如何在本地使用Phi-4 GGUF模型:快速入门指南