人工智能学习

??LlamaIndex中的实体链接与关系抽取:使用Relik构建知识图谱

本文主要是介绍??LlamaIndex中的实体链接与关系抽取:使用Relik构建知识图谱,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
结合指代消解、实体链接和关系抽取来构建知识图谱,以支持您的RAG应用,而不需要大语言模型

从文本构建知识图谱一直是研究者们感兴趣的一个领域。随着大型语言模型(LLMs)的兴起,这一领域得到了更多的公众关注。然而,使用LLMs的成本较高。另一种方法是微调较小的模型,这种方法得到了学术界的认可,从而产生了更高效的解决方案。今天我们来聊聊由罗马萨皮恩扎大学自然语言处理小组开发的Relik,这是一个快速且轻量级的信息提取模型运行框架。

如下是一个典型的不使用大型语言模型的信息抽取流程:

信息抽取流程 — 作者提供图片

该图展示了信息提取管道,从包含文本“Tomaz喜欢写博客文章。他特别感兴趣于绘制图表。”的输入数据开始。流程首先通过共指消解来识别“Tomaz”和“他”是同一个实体。接着,命名实体识别(NER)识别了“Tomaz”、“博客”和“图表”等实体。

实体链接是在命名实体识别(NER)之后的一个步骤,其中识别出的实体会被映射到数据库或知识库中的相应条目上。例如,“Tomaz”链接到“Tomaz Bratanic (Q12345)”,“Blog”链接到“Blog (Q321)”,但“Diagram”在知识库中找不到匹配项。

例如,系统识别出Tomaz和Blog之间存在由“WRITES”描述的关系,表明Tomaz写博客。另外,系统还识别出Tomaz和Diagram之间存在由“INTERESTED_IN”描述的关系,表明Tomaz对图表感兴趣。

最后,这些结构化的信息,包括实体及其关系,会被存入一个知识图中,从而使数据易于组织和访问,以便进一步分析或检索信息。

在过去,没有大型语言模型(LLM)的能力时,整个过程依赖于一系列专门的模型,每个模型负责从共指解析到关系抽取等特定任务上。虽然整合这些模型需要更多的努力和协调,但是可以带来显著的优势:更低的成本。通过微调较小的、特定任务的模型,可以把整个系统的构建和维护成本控制在较低水平。

代码可以在 GitHub 上找到:GitHub。

环境搭建

我建议你使用一个单独的Python环境,比如 Google Colab,因为我们可能需要调整一些依赖项。模型在GPU上运行更快,所以如果你有Pro版本,你可以使用一个带有GPU的运行时环境。

此外,我们需要部署Neo4j,一个原生图数据库,来存储提取的信息。有多种方式可以部署数据库实例。然而,推荐使用Neo4j Aura,它提供了一个免费的云实例,可以从Google Colab笔记本中轻松访问。

Neo4j Aura - 全面托管的云图数据库解决方案使用 AuraDB(我们的图数据库服务)构建应用程序,处理高度关联的数据,实现闪电般的查询性能…neo4j.com

创建数据库后,我们可以使用 LlamaIndex 来定义连接:

从 llama_index.graph_stores.neo4j 中导入 Neo4jPGStore  

username="neo4j"  
password="rubber-cuffs-radiator"  
url="bolt://54.89.19.156:7687"  

graph_store = Neo4jPGStore(  
    username=username,  
    password=password,  
    url=url,  
    refresh_schema=False  
)
数据集(也就是数据集合的意思)

数据集就是...

我们将使用一个新闻数据集,这个数据集是我之前从Diffbot API获得的。该数据集已经在GitHub上提供了方便的重复利用:

import pandas as pd  

# 文章数量设置为100
文章数量 = 100  
news = pd.read_csv(  
    "https://raw.githubusercontent.com/tomasonjo/blog-datasets/main/news_articles.csv"  
)  
# 获取前100条新闻数据
news = news.head(文章数量)
核心指代消解

管道的第一步是核心指代消解模型。指代消解的任务是识别文本中指代同一实体的所有表达。

据我了解,可供使用的开源核心指代消解模型并不多。我尝试了maverick-coref,但在我的测试中,来自spaCy的Coreferee表现更好,所以我们会选择使用它。使用Coreferee的唯一缺点是会遇到依赖冲突的问题,这个问题在笔记本里解决了,但这里我们就不细说了。

下面的代码可以用来加载spaCy的共指消解模型:

# 加载代码在这里
导入spacy和coreferee

coref_nlp = spacy.load('en_core_web_lg')  # 'en_core_web_lg' 是一个预训练的英文模型
coref_nlp.add_pipe('coreferee')  # 将 'coreferee' 添加到处理管道中,用于处理共指消解

Coreferee模型能够检测指同一个实体或一组实体的表达群。要根据这些群来重写文本,我们需要实现我们自己的重写函数。

    def coref_text(text):  
        coref_doc = coref_nlp(text)  
        resolved_text = ""  

        for token in coref_doc:  
            repres = coref_doc._.coref_chains.resolve(token)  
            if repres:  
                resolved_text += " " + " and ".join(  
                    [  
                        t.text  
                        if t.ent_type_ == ""  
                        else [e.text for e in coref_doc.ents if t in e][0]  
                        for t in repres  
                    ]  
                )  
            else:  
                resolved_text += " " + token.text  

        return resolved_text

咱们试试这个功能,确保一下模型和相关依赖正确设置,看看有没有问题。

    打印(  
        coref_text("Tomaz 很酷。他可以解决各种 Python 依赖问题而不会哭")  
    )  
    # Tomaz 很酷。他可以解决各种 Python 依赖问题而不会哭

在这个例子中,模型识别到了“Tomaz”和“他”指的是同一个实体。通过使用coref_text函数,用“Tomaz”替换了“他”。

注意,重写不一定总是能得到语法正确的句子,因为实体集内的实体使用了简单的替换方法。不过,对于大多数情况来说,这样的重写结果应该已经足够用了。

现在我们将核心指代消解应用到我们的新闻数据集,并将结果封装为LlamaIndex文档,

从 llama_index.core 导入 Document

news["coref_text"] = news["text"].apply(coref_text) 
documents = [Document(text=f"{row['title']}: {row['coref_text']}") for row in news.iterrows()]
实体识别与链接和关系抽取

Relik 是一个包含实体链接(EL)和关系抽取(RE)功能的库,并且它还支持结合这两种功能的模型。在实体链接中,维基百科被用作目标知识库,将文本中的实体映射到维基百科中的相应条目。

将实体链接到维基百科 - 图片作者

另一方面,关系提取涉及识别并分类文本中实体间的关系,从而从非结构化数据中提取出结构化的信息,从而使人们能够更好地理解和利用这些信息。

关系抽取 - 图片作者:

如果你使用的是免费的Colab版本的话,请使用relik-ie/relik-relation-extraction-small模型,该模型仅执行关系抽取。如果你使用的是Pro版本,或者你打算在一台性能更强的本地机器上使用它,你也可以试试relik-ie/relik-cie-small模型,该模型不仅可以进行实体识别,还可以进行关系抽取。

from llama_index.extractors.relik.base 导入 RelikPathExtractor  

relik = RelikPathExtractor(  
    model="relik-ie/relik-relation-extraction-small"  
)  

# 注释:在 Pro Collab 上使用带 GPU 的 RelikPathExtractor  
# relik = RelikPathExtractor(  
#    model="relik-ie/relik-cie-small", model_config={"skip_metadata": True, "device": "cuda"}  
# )

此外,我们还需要定义实体嵌入模型以及用于问答的语言模型。

import os  

# 引入OpenAI嵌入模型
from llama_index.embeddings.openai import OpenAIEmbedding  
# 引入OpenAI大模型
from llama_index.llms.openai import OpenAI  

# 设置环境变量OPENAI_API_KEY
os.environ["OPENAI_API_KEY"] = "sk-"  

# 初始化大模型对象,使用"gpt-4o"模型版本,温度设置为0.0
llm = OpenAI(model="gpt-4o", temperature=0.0)  # 大模型对象
# 创建一个使用"text-embedding-3-small"模型的嵌入模型对象
embed_model = OpenAIEmbedding(model_name="text-embedding-3-small")  # 嵌入模型对象

注意,在构建图时不会使用LLM(LLM: Large Language Model)。

现在我们准备好了,可以创建一个 PropertyGraphIndex,并将新闻文档作为知识图的输入数据。

另外,我们需要将 relik 模型设置为 kg_extractors 参数,这样就能用来提取关系了。

    导入 llama_index.core 中的 PropertyGraphIndex  

    index = PropertyGraphIndex.from_documents(  
        documents,  
        kg_extractors=[relik],  
        llm=llm,  
        embed_model=embed_model,  
        property_graph_store=graph_store,  
        show_progress=True,  
    )

构建图完成后,你可以打开 Neo4j Browser 来验证你导入的图。运行以下 Cypher 语句:你应该能看到类似的结果。

MATCH p=(:__Entity__)--(:__Entity__)  
    // 返回路径p,限制结果为250条
    RETURN p LIMIT 250

结果

图可视化 - 图片由作者制作

问答环节

现在使用LlamaIndex进行问答变得非常简单。若要使用默认的图检索器,你可以这样提问:

    query_engine = index.as_query_engine(include_text=True)  

    response = query_engine.query("瑞安航空到底发生了什么事?")  

    print(str(response)) # 打印响应

这里就是我们之前定义的LLM和嵌入式模型的用武之地。当然,你也可以自定义自定义检索器以提高准确性。

摘要

不依赖大型语言模型(LLM)创建知识图谱不仅完全可行,而且成本低且高效。通过微调较小的任务特定模型,比如使用Relik框架的模型,你可以利用这些模型为RAG应用(即检索增强生成应用)实现高效的信息提取。

实体链接过程是这一过程中的关键步骤,确保识别的实体准确对应知识库中的条目,从而保证知识图谱的完整性和实用性更佳。

通过使用像 Relik 这样的框架和像 Neo4j 这样的平台,可以构建高级知识图,从而促进复杂的数据分析和检索工作,而无需支付部署大型语言模型的高昂费用。这种方法不仅使强大的数据处理工具更易于获得,还促进了信息提取工作流程的创新和效率提升。

别忘了给 Relik库 点个赞哦!代码可以在 GitHub 上找到。

这篇关于??LlamaIndex中的实体链接与关系抽取:使用Relik构建知识图谱的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!