使用 LLM Graph Transformer 构建知识图谱

向量数据库大模型关系型数据库

前言

近期在做基于大模型搭建知识图谱相关的调研,收录了很多优质的技术文章,本文也是其中较为透彻的一遍之一。整理后供大家交流学习使用。

Autoflow——一种基于Tidb和LlamaIndex的Knowledge Graph流程构建引擎

基于知识图谱的RAG——如何用固定的实体架构在Knowledge Graph上进行RAG检索

用LLM Graph Builder构建知识图谱实战篇

llm-graph-builder——从非结构化数据创建知识图谱

GraphRAG会成为AI原生应用中RAG的终局吗?

将文本输入或网址转换为知识图谱的AI应用—instagraph

如何将任何文本转换为图谱

如何用知识图谱和Llama-Index来实现RAG?

在本文中,我们探讨了 LangChain 的 LLM Graph Transformer 及其用于从文本构建知识图谱的双重模式。基于工具的模式是我们的主要方法,利用结构化输出和函数调用,减少了提示工程,并允许属性抽取。另一方面,当工具不可用时,基于提示的模式非常有用,依靠少量示例来指导 LLM。然而,基于提示的抽取不支持属性抽取,也不会产生孤立的节点。

深入解析 LangChain 在 LLM 图构建中的实现

从文本中创建图形非常令人兴奋,但也确实具有挑战性。基本上,这是关于将非结构化文本转换为结构化数据。虽然这种方法已经存在了一段时间,但随着大型语言模型(LLM)的出现,它获得了显著的发展,进入了主流应用。

picture.image

从文本中提取实体和关系以构建知识图谱。图片由作者提供。

在上图中,您可以看到信息抽取如何将原始文本转化为知识图谱。左侧,多份文档展示了关于个人及其与公司的关系的非结构化句子。右侧,相同的信息被表示为实体及其连接的图形,显示了谁在各种组织中工作或创建了这些组织。

但是,为什么您要从文本中提取结构化信息并将其表示为图形呢?一个关键原因是为检索增强生成(RAG) 应用程序提供支持。虽然在非结构化文本上使用文本嵌入模型是一种有用的方法,但在回答需要理解多个实体之间连接的复杂、多跳问题[1],或需要结构化操作如过滤、排序和聚合[2]的问题时,它可能会不足。通过从文本中提取结构化信息并构建知识图谱,您不仅可以更有效地组织数据,还可以创建一个强大的框架来理解实体之间的复杂关系。这种结构化的方法使得检索和利用特定信息更加容易,扩展了您可以回答的问题类型,同时提供了更高的准确性。

大约一年前,我开始尝试使用 LLM 构建图形[3],由于日益增长的兴趣,我们决定将此功能集成到 LangChain 中,作为 LLM Graph Transformer[4]。在过去的一年中,我们获得了宝贵的见解并引入了新功能,我们将在这篇博文中展示这些内容。

代码可在 GitHub[5] 上获取。

设置 Neo4j 环境

我们将使用 Neo4j 作为底层图形存储,它自带开箱即用的图形可视化。最简单的入门方式是使用免费的 Neo4j Aura[6] 实例,它提供了 Neo4j 数据库的云实例。或者,您可以通过下载 Neo4j Desktop[7] 应用程序并创建本地数据库实例来设置本地的 Neo4j 数据库。


            
from langchain_community.graphs import Neo4jGraph
            

            
graph = Neo4jGraph(
            
    url="bolt://54.87.130.140:7687",
            
    username="neo4j",
            
    password="cables-anchors-directories",
            
    refresh_schema=False
            
)
        
LLM Graph Transformer

LLM Graph Transformer 旨在提供一个使用任何 LLM 构建图形的灵活框架。由于有如此多的不同提供商和模型可用,这项任务绝非简单。幸运的是,LangChain 介入,处理了大部分标准化过程。至于 LLM Graph Transformer 本身,就像两只猫叠在风衣里——具有以两种完全独立模式运行的能力。

picture.image

LLM Graph Transformer 由从文本中提取图形的两种独立模式组成。图片由用户提供。

LLM Graph Transformer 在两种不同的模式下运行,每种模式都旨在在不同的场景中使用 LLM 从文档中生成图形。

1.基于工具的模式(默认): 当 LLM 支持结构化输出或函数调用时,此模式利用 LLM 的内置 with_structured_output 来使用工具。工具规范定义了输出格式,确保以结构化、预定义的方式提取实体和关系。这在图的左侧有所展示,显示了 NodeRelationship 类的代码。 2.基于提示的模式(后备): 在 LLM 不支持工具或函数调用的情况下,LLM Graph Transformer 会退回到纯粹基于提示的方法。此模式使用少量示例提示来定义输出格式,引导 LLM 以基于文本的方式提取实体和关系。然后通过自定义函数解析结果,将 LLM 的输出转换为 JSON 格式。这个 JSON 用于填充节点和关系,就像在基于工具的模式中一样,但这里 LLM 完全由提示引导而非结构化工具。这在图的右侧有所展示,提供了示例提示和结果 JSON 输出。

请注意,即使在支持工具/函数的模型中,您也可以通过设置属性 ignore_tools_usage=True 来使用基于提示的抽取。

基于工具的抽取

我们最初选择了基于工具的抽取方法,因为它最大限度地减少了对广泛的提示工程和自定义解析函数的需求。在 LangChain 中,with_structured_output 方法允许您使用工具或函数来提取信息,输出可以通过 JSON 结构或 Pydantic 对象来定义。就个人而言,我发现 Pydantic 对象更清晰,所以我们选择了它。

我们首先定义一个 Node 类。


          
class Node(BaseNode):
          
    id: str = Field(..., description="Name or human-readable unique identifier")
          
    label: str = Field(..., description=f"Available options are {enum_values}")
          
    properties: Optional[List[Property]]
      

每个节点都有一个 id、一个 label,以及可选的 properties。为了简洁,我没有在这里包含完整的描述。将 id 描述为人类可读的唯一标识符很重要,因为一些 LLM 倾向于以更传统的方式理解 ID 属性,例如随机字符串或递增整数。相反,我们希望使用实体的名称作为 id 属性。我们还通过简单地在 label 描述中列出它们来限制可用的标签类型。此外,像 OpenAI 这样的 LLM 支持 enum 参数,我们也使用了它。

接下来,我们看看 Relationship


          
class Relationship(BaseRelationship):
          
    source_node_id: str
          
    source_node_label: str = Field(..., description=f"Available options are {enum_values}")
          
    target_node_id: str
          
    target_node_label: str = Field(..., description=f"Available options are {enum_values}")
          
    type: str = Field(..., description=f"Available options are {enum_values}")
          
    properties: Optional[List[Property]]
      

这是 Relationship 类的第二次迭代。最初,我们为源节点和目标节点使用了嵌套的 Node 对象,但我们很快发现嵌套对象降低了抽取过程的准确性和质量。因此,我们决定将源节点和目标节点展平成单独的字段——例如,source_node_idsource_node_label,以及 target_node_idtarget_node_label。此外,我们在节点标签和关系类型的描述中定义了允许的值,以确保 LLM 遵守指定的图形模式。

基于工具的抽取方法使我们能够为节点和关系定义属性。下面是我们用来定义它们的类。


          
class Property(BaseModel):
          
    """A single property consisting of key and value"""
          
    key: str = Field(..., description=f"Available options are {enum_values}")
          
    value: str
      

每个 Property 被定义为一个键值对。虽然这种方法很灵活,但也有其局限性。例如,我们无法为每个属性提供唯一的描述,也无法指定某些属性是必需的而其他是可选的,因此所有属性都被定义为可选的。此外,属性不是为每个节点或关系类型单独定义的,而是在所有节点和关系中共享的。

我们还实现了一个详细的系统提示[8]来帮助引导抽取。然而,根据我的经验,函数和参数描述往往比系统消息具有更大的影响。

不幸的是,目前在 LLM Graph Transformer 中没有简单的方法来自定义函数或参数描述。

基于提示的抽取

由于只有少数商业 LLM 和 LLaMA 3 支持原生工具,我们为不支持工具的模型实现了后备方法。即使在使用支持工具的模型时,您也可以设置 ignore_tool_usage=True 来切换到基于提示的方法。

大部分基于提示的方法的提示工程和示例都是由 Geraldus Wilsen[9] 贡献的。

在基于提示的方法中,我们必须在提示中直接定义输出结构。您可以在此处[10]找到完整的提示。在这篇博文中,我们只做一个高级概述。我们首先定义系统提示。


          
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.
          

          
Extract as many entities and relationships as possible.
          

          
**Entity Consistency**: 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.
          

          
**Important Notes**:
          

          
- Do not add any extra explanations or text.
      

您是一个顶级算法,旨在以结构化格式提取信息以构建知识图谱。您的任务是从给定的文本中识别用户提示中指定的实体和关系,并以 JSON 格式生成输出。此输出应为 JSON 对象的列表,每个对象包含以下键:

"head" :提取的实体的文本,必须匹配用户提示中指定的类型之一。 •"head_type" :提取的头实体的类型,从指定的类型列表中选择。 •"relation" :"head" 和 "tail" 之间的关系类型,从允许的关系列表中选择。 •"tail" :表示关系尾部的实体的文本。 •"tail_type" :尾实体的类型,也从提供的类型列表中选择。

尽可能多地提取实体和关系。

实体一致性 :确保实体表示的一致性。如果一个实体,如 "John Doe",在文本中多次以不同的名称或代词出现(例如 "Joe","he"),请始终使用最完整的标识符。这种一致性对于创建连贯且易于理解的知识图谱至关重要。

重要注意事项

•不要添加任何额外的解释或文本。

在基于提示的方法中,一个关键的区别是我们要求 LLM 只提取关系,而不是单独的节点。这意味着我们不会有任何孤立的节点,与基于工具的方法不同。此外,因为缺乏原生工具支持的模型通常表现较差,我们不允许提取任何属性——无论是节点还是关系,以保持提取输出的简单性。

接下来,我们向模型添加了几个少样本示例。


          
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",
          
    },
          
    ...
          
]
      

在这种方法中,目前不支持添加自定义的少样本示例或额外指令。唯一的自定义方法是通过 prompt 属性修改整个提示。我们正在积极考虑扩展自定义选项。

接下来,我们将看看如何定义图形模式。

定义图形模式

当使用 LLM Graph Transformer 进行信息抽取时,定义一个图形模式对于引导模型构建有意义且结构化的知识表示至关重要。一个良好定义的图形模式指定了要提取的节点和关系类型,以及与每个节点和关系相关的任何属性。该模式作为一个蓝图,确保 LLM 以符合所需知识图谱结构的方式一致地提取相关信息。

在这篇博文中,我们将使用 玛丽·居里维基百科页面[11] 的开头段落进行测试,并在末尾添加一条关于罗宾·威廉姆斯的句子。


          
from langchain_core.documents import Document
          

          
text = """
          
Marie Curie, 7 November 1867 – 4 July 1934, was a Polish and naturalised-French physicist and chemist who conducted pioneering research on radioactivity.
          
She 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.
          
Her 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.
          
She was, in 1906, the first woman to become a professor at the University of Paris.
          
Also, Robin Williams.
          
"""
          
documents = [Document(page_content=text)]
      

我们在所有示例中还将使用 GPT-4o。


          
from langchain_openai import ChatOpenAI
          
import getpass
          
import os
          

          
os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI api key")
          

          
llm = ChatOpenAI(model='gpt-4o')
      

首先,让我们看看在未定义任何图形模式的情况下,抽取过程如何工作。


          
from langchain_experimental.graph_transformers import LLMGraphTransformer
          

          
no_schema = LLMGraphTransformer(llm=llm)
      

现在,我们可以使用异步的 aconvert_to_graph_documents 函数来处理文档。建议在 LLM 抽取中使用异步,因为它允许并行处理多个文档。这种方法可以显著减少等待时间并提高吞吐量,特别是在处理多个文档时。


        
            

          data = await no\_schema.aconvert\_to\_graph\_documents(documents)
        
      

LLM Graph Transformer 的响应将是一个图形文档,具有以下结构:


          
[
          
    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",
          
        ),
          
    )
          
]
      

该图形文档描述了提取的 nodesrelationships。此外,抽取的源文档被添加到 source 键下。

我们可以使用 Neo4j 浏览器来可视化输出,从而更清晰、直观地理解数据。

picture.image

在未定义图形模式的情况下,对相同数据集进行两次抽取的可视化。图片由作者提供。

上图显示了对关于玛丽·居里的同一段落的两次抽取。在这种情况下,我们使用了 GPT-4 和基于工具的抽取,它也允许孤立的节点,如图所示。由于未定义任何图形模式,LLM 在运行时决定要抽取哪些信息,这可能导致输出的变化,即使来自同一段落。因此,一些抽取比其他抽取更详细,甚至对相同的信息结构也可能不同。例如,在左侧,玛丽被表示为诺贝尔奖的 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 浏览器中可视化两次单独的执行。

picture.image

使用基于提示的方法,在未定义图形模式的情况下对相同数据集进行两次抽取的可视化。图片由作者提供。

使用基于提示的方法,我们不会看到任何孤立的节点。然而,与之前的抽取一样,模式可能在运行之间变化,导致对相同输入的不同输出。

接下来,让我们了解如何通过定义图形模式来帮助产生更一致的输出。

定义允许的节点

约束提取的图形结构非常有益,因为它引导模型专注于特定的、相关的实体和关系。通过定义清晰的模式,您可以提高抽取的一致性,使输出更可预测,并与您实际需要的信息保持一致。这减少了运行之间的变化,确保提取的数据遵循标准化的结构,捕获预期的信息。使用良好定义的模式,模型不太可能忽略关键细节或引入意外元素,从而产生更干净、更可用的图形。

我们将从使用 allowed_nodes 参数定义要提取的预期节点类型开始。


          
allowed_nodes = ["Person", "Organization", "Location", "Award", "ResearchField"]
          
nodes_defined = LLMGraphTransformer(llm=llm, allowed_nodes=allowed_nodes)
          
data = await allowed_nodes.aconvert_to_graph_documents(documents)
      

在这里,我们定义了 LLM 应该提取五种类型的节点,例如Person、Organization、Location等。我们在 Neo4j 浏览器中可视化两次单独的执行以进行比较。

picture.image

使用预定义节点类型进行两次抽取的可视化。图片由作者提供。

通过指定预期的节点类型,我们实现了更一致的节点抽取。然而,仍然可能发生一些变化。例如,在第一次运行中,“radioactivity” 被提取为研究领域,而在第二次中则没有。

由于我们尚未定义关系,它们的类型也可能在运行之间变化。此外,一些抽取可能比其他抽取捕获更多的信息。例如,玛丽和皮埃尔之间的 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)
      

让我们再次检查两次单独的抽取。

picture.image

使用预定义的节点和关系类型进行两次抽取的可视化。图片由作者提供。

在定义了节点和关系后,我们的输出变得显著更一致。例如,玛丽始终被显示为获得了奖项,是皮埃尔的配偶,并在巴黎大学工作。然而,由于关系被指定为通用列表,且未限制它们可以连接的节点,仍然会发生一些变化。例如,FIELD_OF_RESEARCH 关系可能出现在 PersonResearchField 之间,但有时它会连接 AwardResearchField。此外,由于未定义关系方向,方向一致性可能存在差异。

为了解决无法指定关系可以连接哪些节点以及强制关系方向的问题,我们最近引入了用于定义关系的新选项,如下所示。


          
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)
      

我们不再将关系定义为简单的字符串列表,而是使用三个元素的元组格式,元素分别代表源节点、关系类型和目标节点。

让我们再次可视化结果。

picture.image

使用预定义的节点和高级关系类型进行两次抽取的可视化。图片由作者提供。

使用三元组方法为多个执行提供了更一致的抽取图形模式。然而,鉴于 LLM 的性质,抽取的细节级别可能仍然存在一些变化。例如,在右侧,皮埃尔被显示为获得了诺贝尔奖,而在左侧,这一信息缺失。

定义属性

我们可以对图形模式进行的最终增强是为节点和关系定义属性。在这里,我们有两个选项。第一个是将 node_propertiesrelationship_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)
      

让我们检查结果。

picture.image

提取的节点和关系属性。图片由作者提供。

我们已启用 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=["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)
      

属性被简单地定义为两个列表。让我们看看 LLM 提取了什么。

picture.image

提取的预定义节点和关系属性。图片由作者提供。

出生和死亡日期与先前的抽取保持一致。然而,这次,LLM 还提取了玛丽在巴黎大学担任教授职位的开始日期。

属性确实为提取的信息增加了有价值的深度,尽管当前的实现存在一些限制:

•属性只能使用基于工具的方法提取。 •所有属性都被提取为字符串。 •属性只能全局定义,不能针对特定的节点标签或关系类型。 •没有选项可以自定义属性描述,以指导 LLM 进行更精确的抽取。

严格模式

如果您认为我们已经完善了一种让 LLM 完美遵循定义的模式的方法,我必须澄清事实。虽然我们在提示工程上投入了大量精力,但让 LLM(特别是性能较差的模型)完全准确地遵循指令是具有挑战性的。为了解决这个问题,我们引入了一个后处理步骤,称为 strict_mode,它会删除任何不符合定义的图形模式的信息,确保结果更干净、更一致。

默认情况下,strict_mode 设置为 True,但您可以使用以下代码禁用它:


          
LLMGraphTransformer(
          
    llm=llm,
          
    allowed_nodes=allowed_nodes,
          
    allowed_relationships=allowed_relationships,
          
    strict_mode=False
          
)
      

关闭严格模式后,您可能会获得超出定义的图形模式的节点或关系类型,因为 LLM 有时可能会在输出结构上发挥创造性。

将图形文档导入图数据库

从 LLM Graph Transformer 提取的图形文档可以使用 add_graph_documents 方法导入到 Neo4j 等图数据库中,以便进行进一步的分析和应用。我们将探讨不同的导入选项,以适应不同的用例。

默认导入

您可以使用以下代码将节点和关系导入 Neo4j。


        
            

          graph.add\_graph\_documents(graph\_documents)
        
      

此方法直接从提供的图形文档中导入所有节点和关系。我们在整个博文中都使用了这种方法来查看不同 LLM 和模式配置的结果。

picture.image

默认导入设置。图片由作者提供。

基础实体标签

大多数图数据库都支持索引以优化数据导入和检索。在 Neo4j 中,索引只能为特定的节点标签设置。由于我们可能无法提前知道所有的节点标签,我们可以通过使用 baseEntityLabel 参数为每个节点添加一个次要的基础标签来处理此问题。这样,我们仍然可以利用索引进行高效的导入和检索,而无需为图中的每个可能节点标签设置索引。


        
            

          graph.add\_graph\_documents(graph\_documents, baseEntityLabel=True)
        
      

如前所述,使用 baseEntityLabel 参数将导致每个节点具有一个额外的 __Entity__ 标签。

picture.image

每个节点都通过 baseEntityLabel 参数获得一个次要标签。图片由作者提供。

包含源文档

最后一个选项是还导入提取节点和关系的源文档。此方法使我们能够跟踪每个实体出现在哪些文档中。您可以使用 include_source 参数导入源文档。


        
            

          graph.add\_graph\_documents(graph\_documents, include\_source=True)
        
      

在检查导入的图形时,我们应该看到类似以下的结果。

picture.image

导入的源文档。图片由作者提供。

在此可视化中,源文档以蓝色突出显示,所有从中提取的实体通过 MENTIONS 关系连接。此模式使您能够构建利用结构化和非结构化搜索方法的检索器[12]。

总结

在本文中,我们探讨了 LangChain 的 LLM Graph Transformer 及其用于从文本构建知识图谱的双重模式。基于工具的模式是我们的主要方法,利用结构化输出和函数调用,减少了提示工程,并允许属性抽取。另一方面,当工具不可用时,基于提示的模式非常有用,依靠少量示例来指导 LLM。然而,基于提示的抽取不支持属性抽取,也不会产生孤立的节点。

我们观察到,定义清晰的图形模式,包括允许的节点和关系类型,可以提高抽取的一致性和性能。受约束的模式有助于确保输出符合我们所需的结构,使其更可预测、可靠和适用。无论使用工具还是提示,LLM Graph Transformer 都能够将非结构化数据转化为更有组织、结构化的表示,支持更好的 RAG 应用程序和多跳查询处理。

代码可在 GitHub[13] 上获取。您还可以使用 Neo4j 托管的 LLM Graph Builder 应用程序,在无代码环境中试用 LLM Graph Transformer。

Neo4j graph builder[14]

常见问题

嗨,Tomaz,感谢您分享关于从非结构化文本中使用 Neo4j 构建知识图谱的见解!

我的问题是,我想从德语法律领域语料库中创建一个知识库,但我无法定义所有可能的节点或关系……

解决方法是 :整理语料对大模型进行微调,详见:https://medium.com/@rakesh.sheshadri44/building-a-large-language-model-with-1-billion-parameters-part-1-778e7652b553

参考文献

• Constructing knowledge graphs from text using OpenAI functions[15]

• Knowledge Graphs + LLMs = Multi-hop Question Answering[16]

• Limitations of Text Embeddings in RAG Applications[17]

• Enhancing the Accuracy of RAG Applications with Knowledge Graphs[18]

声明

本文由山行翻译整理自:https://towardsdatascience.com/building-knowledge-graphs-with-llm-graph-transformer-a91045c49b59https://medium.com/@rakesh.sheshadri44/building-a-large-language-model-with-1-billion-parameters-part-1-778e7652b553,如果对您有帮助,请帮忙点赞、关注、收藏,谢谢~

References

[1] 复杂、多跳问题: https://medium.com/neo4j/knowledge-graphs-llms-multi-hop-question-answering-322113f53f51
[2] 结构化操作如过滤、排序和聚合: https://medium.com/neo4j/limitations-of-text-embeddings-in-rag-applications-b060020b543b
[3] 尝试使用 LLM 构建图形: https://medium.com/@bratanic-tomaz/constructing-knowledge-graphs-from-text-using-openai-functions-096a6d010c17
[4] LLM Graph Transformer: https://python.langchain.com/docs/how\_to/graph\_constructing/
[5] GitHub: https://github.com/tomasonjo/blogs/blob/master/llm/llm\_graph\_transformer\_in\_depth.ipynb
[6] Neo4j Aura: https://neo4j.com/cloud/platform/aura-graph-database/
[7] Neo4j Desktop: https://neo4j.com/download/
[8] 详细的系统提示: https://github.com/langchain-ai/langchain-experimental/blob/main/libs/experimental/langchain\_experimental/graph\_transformers/llm.py#L72
[9] Geraldus Wilsen: https://www.linkedin.com/in/geraldus-wilsen/
[10] 此处: https://github.com/langchain-ai/langchain-experimental/blob/main/libs/experimental/langchain\_experimental/graph\_transformers/llm.py#L206
[11] 玛丽·居里维基百科页面: https://en.wikipedia.org/wiki/Marie\_Curie
[12] 利用结构化和非结构化搜索方法的检索器: https://medium.com/neo4j/enhancing-the-accuracy-of-rag-applications-with-knowledge-graphs-ad5e2ffab663
[13] GitHub: https://github.com/tomasonjo/blogs/blob/master/llm/llm\_graph\_transformer\_in\_depth.ipynb
[14] Neo4j graph builder: https://llm-graph-builder.neo4jlabs.com/?source=post\_page-----a91045c49b59--------------------------------
[15] Constructing knowledge graphs from text using OpenAI functions: https://medium.com/@bratanic-tomaz/constructing-knowledge-graphs-from-text-using-openai-functions-096a6d010c17
[16] Knowledge Graphs + LLMs = Multi-hop Question Answering: https://medium.com/neo4j/knowledge-graphs-llms-multi-hop-question-answering-322113f53f51
[17] Limitations of Text Embeddings in RAG Applications: https://medium.com/neo4j/limitations-of-text-embeddings-in-rag-applications-b060020b543b
[18] Enhancing the Accuracy of RAG Applications with Knowledge Graphs: https://medium.com/neo4j/enhancing-the-accuracy-of-rag-applications-with-knowledge-graphs-ad5e2ffab663

0
0
0
0
关于作者
相关资源
字节跳动 XR 技术的探索与实践
火山引擎开发者社区技术大讲堂第二期邀请到了火山引擎 XR 技术负责人和火山引擎创作 CV 技术负责人,为大家分享字节跳动积累的前沿视觉技术及内外部的应用实践,揭秘现代炫酷的视觉效果背后的技术实现。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论