AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


知识库内容如何转知识图谱?
发布日期:2024-06-16 17:45:19 浏览次数: 1986 来源:三人行AI


一个开源库,用于使用开源LLMs(如Llama 3和Mixtral)从文本语料库构建知识图谱

简介

在本文中,我将分享一个Python库——Graph Maker,它可以根据给定的本体从一组文本中创建一个知识图谱。Graph Maker使用开源LLMs,如Llama3、Mistral、Mixtral或Gemma来提取知识图谱(KG)。

我们将介绍Graph Maker的“为什么”和“是什么”的基本概念,简要回顾之前的文章,并讨论当前方法如何解决一些挑战。本文结尾会分享GitHub仓库链接。

使用生成性知识提取、基于图谱的表示加速科学发现

利用生成性人工智能(AI),我们转化了包含1000篇科学论文的数据集...

arxiv.org[1]

这是一篇引人入胜的论文,展示了知识图谱在AI时代的巨大潜力。它展示了知识图谱不仅可以用于知识检索,还可以用于发现新知识。以下是我最喜欢的论文摘录之一:

“例如,我们将展示这种方法如何将看似不相关的概念,如贝多芬的第九交响曲,与仿生材料科学联系起来。”

这些进展极大地肯定了我在之前文章中提出的想法,并鼓励我进一步发展这些想法。

我还收到了许多技术同仁的反馈,他们在使用该仓库时遇到了挑战,并提出了改进建议。我将一些这些建议整合到一个新的Python包中,这里分享给大家。

在讨论这个包的工作原理之前——Graph Maker——让我们先讨论它的“为什么”和“是什么”。

简要回顾

我们可能应该从“为什么是图谱”开始。

下面是一张简明扼要的知识图谱概念图。

来源[2]

要创建一个知识图谱,我们需要两部分信息:

1.知识库:这可以是文本语料库、代码库、文章集合等。2.本体:我们关心的实体类别及其关系类型。我可能在这里过于简化了本体的定义,但这对于我们的目的来说是有效的。

这里有一个简单的本体:

实体:人、地点关系人→相关于→人人→居住在→地点人→访问→地点

有了这两部分信息,我们可以从提到人和地点的文本中构建一个知识图谱。然而,假设我们的知识库是关于处方药及其相互作用的临床研究。我们可能会使用一个不同的本体,其中化合物、用法、效果、反应等可能构成我们的本体。

尽管这种方法缺乏生成知识图谱的传统方法的严谨性,但它有其优点。与传统方法相比,它能更容易地使用非结构化数据生成知识图谱。它生成的知识图谱在某种意义上也是非结构化的,但它们更容易构建且信息更丰富。它们非常适合于GRAG(图谱检索增强生成)等应用。

为什么选择Graph Maker?

让我列出在我上一篇文章中收到的一些反馈意见中的挑战和观察。这将有助于我们理解使用LLMs创建知识图谱的挑战。让我们以《指环王》书籍的维基百科摘要为例。毕竟,没有人会不爱《指环王》!

有意义的实体

在自由运行的情况下,LLM提取的实体类别可能过于多样化。它错误地将抽象概念标记为实体。例如,在“比尔博·巴金斯庆祝他的生日并将戒指留给弗罗多”这段文本中,LLM可能会提取“比尔博·巴金斯庆祝他的生日”或“庆祝他的生日”作为“动作”。但如果它提取“生日”作为“事件”,可能更有用。

一致的实体

它也可能在不同的上下文中错误地标记相同的实体。例如:

‘Sauron’、‘the Dark Lord Sauron’和‘the Dark Lord不应该被提取为不同的实体。或者如果它们被提取为不同的实体,它们应该通过等价关系连接。

解析的弹性

LLM的输出本质上是不可预测的。要从大文档中提取知识图谱,我们必须将语料库拆分成较小的文本块,然后为每个块生成子图。要构建一致的图谱,LLM必须根据给定的模式一致地输出JSON对象,即使丢失一个也可能会对整个图谱的连接性产生不利影响。

尽管LLMs在生成格式良好的JSON对象方面变得越来越好,但仍然远非完美。具有有限上下文窗口的LLMs也可能生成不完整的响应。

实体的分类

LLMs在识别实体时可能会大量出错。当上下文是特定领域时,或者当实体未用标准英语命名时,这个问题更为严重。NER模型在这方面可能表现更好,但它们也仅限于它们接受训练的数据。此外,它们不能理解实体之间的关系。

迫使LLM在类别上保持一致是一种提示工程的艺术。

隐含关系

关系可以是明确提到的,也可以是由上下文暗示的。例如:

“比尔博·巴金斯庆祝他的生日并将戒指留给弗罗多”暗示了以下关系:比尔博·巴金斯 → 拥有者 → 戒指 比尔博·巴金斯 → 继承人 → 弗罗多 弗罗多 → 拥有者 → 戒指

我认为,LLMs在某些时候将比任何传统方法更好地提取关系。但目前,这仍是一个需要巧妙提示工程的挑战。

Graph Maker

我在这里分享的Graph Maker库,通过在严格性和易用性之间,以及在结构化和非结构化之间找到平衡,改进了之前的方法。在应对上述大多数挑战方面,它比我之前讨论的方法表现得更好。

与之前的方法不同,在之前的方法中,LLM可以自行发现本体,而Graph Maker试图强制LLM使用用户定义的本体。

我们可以通过一个简单的pip命令安装知识图谱生成器库:

pip install knowledge-graph-maker

使用给定的本体从任意文本中创建知识图谱

以下是它的工作方式,分为五个简单步骤。

这些步骤已经编码在一个笔记本中,我将在本文末尾分享。

1. 定义图谱的本体

该库理解以下本体的模式。在幕后,本体是一个pydantic模型。

ontology = Ontology(labels=[{"Person": "没有任何形容词的人的名字,记住一个人可能会用名字或代词引用"},{"Object": "在对象名称中不要添加定冠词'the'"},{"Event": "涉及多个人的事件。不要包括限定词或动词,如给予、留下、工作等。"},"Place","Document","Organisation","Action",{"Miscellaneous": "任何无法分类为其他给定标签的重要概念"},],relationships=["实体对之间的关系",],)

我已经调整了提示,使其生成与给定本体一致的结果。我认为它在这方面做得相当不错。然而,它仍然不是100%准确。准确性取决于我们选择的生成图谱的模型、应用、本体和数据质量。

2.将文本拆分成块

我们可以使用尽可能大的文本语料库来创建大型知识图谱。然而,LLMs目前有一个有限的上下文窗口。所以我们需要适当地将文本分块,并一次创建一个块的图谱。我们应该使用的块大小取决于模型的上下文窗口。这个项目中使用的提示大约占用500个token。其余的上下文可以分为输入文本和输出图谱。根据我的经验,较小的200到500个token的块会生成更详细的图谱。

3.将这些块转换成文档

文档是一个pydantic模型,具有以下模式:

 ## Pydantic文档模型class Document(BaseModel):text: strmetadata: dict

我们在这里添加到文档的元数据将标记到从文档中提取的每个关系中。

我们可以将关系的上下文,例如页码、章节、文章名称等添加到元数据中。通常,每对节点在多个文档中有多个关系。元数据有助于将这些关系情境化。

4.运行Graph Maker

Graph Maker直接接受文档列表,并遍历每个文档,为每个文档创建一个子图。最终输出是所有文档的完整图谱。

以下是实现此目标的简单示例。

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("边的总数", len(graph))## 1503

Graph Maker通过LLM运行每个文档,并解析响应以创建完整的图谱。最终的图谱是边的列表,其中每个边都是一个pydantic模型,如下所示。

class Node(BaseModel):label: strname: str class Edge(BaseModel):node_1: Nodenode_2: Noderelationship: strmetadata: dict = {}order: Union[int, None] = None

我已经调整了提示,使其现在生成相当一致的JSON。如果JSON响应解析失败,图谱生成器还会尝试手动将JSON字符串拆分成多个边字符串,然后尽可能地恢复。

5.保存到Neo4j

我们可以将模型保存到Neo4j,以创建RAG应用程序、运行网络算法,或者只是使用Bloom[3]可视化图谱。

from knowledge_graph_maker import Neo4jGraphModelcreate_indices = Falseneo4j_graph = Neo4jGraphModel(edges=graph, create_indices=create_indices)neo4j_graph.save()

图谱的每条边都作为一个事务保存到数据库中。如果您是第一次运行此代码,请将create_indices设置为true。这将通过在节点上设置唯一性约束来准备数据库。

5.1 可视化,只是为了好玩

在上一篇文章中,我们使用networkx和pyvis库对图谱进行了可视化。在这里,由于我们已经将图谱保存到Neo4J,我们可以直接利用Bloom进行可视化。

为了避免重复,让我们生成一个与上一篇文章不同的可视化。

假设我们想看看书中角色之间的关系是如何演变的。

我们可以通过跟踪图谱生成器遍历书籍时如何逐渐添加边来实现这一点。为了实现这一点,Edge模型有一个名为“order”的属性。这个属性可以用于为图谱添加时间或时间顺序维度。

在我们的示例中,图谱生成器自动将特定文本块在文档列表中出现的顺序号添加到它从该块提取的每条边中。因此,要查看角色之间的关系如何演变,我们只需按边的顺序截取图谱。

这里有一个这些截面的动画。

图谱与RAG

这种知识图谱的最佳应用可能是在RAG(图谱检索增强生成)中。有很多文章讨论了如何用图谱增强RAG应用程序。

本质上,图谱提供了多种不同的知识检索方式。根据我们设计图谱和应用程序的方式,其中一些技术可能比简单的语义搜索更强大。

最基本的是,我们可以将嵌入向量添加到节点和关系中,并对向量索引运行语义搜索进行检索。然而,我觉得图谱在RAG应用程序中的真正力量在于将Cypher查询和网络算法与语义搜索混合使用。

我自己也在探索其中的一些技术。我希望在我的下一篇文章中写到这些内容。

代码

这里是GitHub仓库。请随意试用。我还在仓库中包含了一个示例Python笔记本,可以帮助你快速入门。

请注意,在开始之前,你需要在.env文件中添加你的GROQ凭证。

GitHub - rahulnyk/graph_maker[4]

另外,如果你觉得可以为这个开源项目做出贡献,请这样做并使其成为你自己的项目。

我希望你觉得图谱生成器有用。感谢阅读。



53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询