使用LlamaIndex中的Reli 进行实体链接和关系提取

2024年08月15日 由 alex 发表 135 0

从文本中构建知识图谱一直是一个引人入胜的研究领域。随着大型语言模型(LLM)的出现,这一领域获得了更多主流关注。然而,大型语言模型的成本可能相当高昂。另一种方法是对较小的模型进行微调,这种方法得到了学术研究的支持,并产生了更有效的解决方案。今天,我们将探讨罗马萨皮恩扎大学(Sapienza University of Rome)的 NLP 小组开发的 Relik,一个用于运行快速、轻量级信息提取模型的框架。


没有 LLM 的典型信息提取管道如下:


8


图片说明了信息提取流水线,从输入数据开始,输入数据包括提及 “托马兹喜欢写博客文章 ”的文本。他对画图特别感兴趣"。提取过程从核心参照解析开始,将 “Tomaz ”和 “He ”识别为同一个实体。然后,命名实体识别 (NER) 识别出 “Tomaz”、“Blog ”和 “Diagram ”等实体。


实体链接是 NER 之后的一个过程,将识别出的实体映射到数据库或知识库中的相应条目。例如,“Tomaz ”链接到 “Tomaz Bratanic (Q12345)”,“Blog ”链接到 “Blog (Q321)”,但 “Diagram ”在知识库中没有匹配项。


关系提取是系统识别和提取已识别实体之间有意义关系的后续步骤。本例中,系统识别出 “Tomaz ”与 “Blog ”之间存在以 “WRITES ”为特征的关系,表明 Tomaz 写博客。此外,系统还识别出 “Tomaz ”与 “Diagram ”之间的关系,关系的特征是 “INTERESTED_IN”,表明 Tomaz 对图表感兴趣。


最后,这些结构化信息,包括实体及其关系,都存储在知识图谱中,从而使数据有条理,便于进一步分析或检索。


传统上,如果没有 LLM 的强大功能,整个过程都要依赖一套专门的模型,每个模型都要处理从核心参照解析到关系提取的特定任务。虽然整合这些模型需要更多的努力和协调,但却能带来显著的优势:降低成本。通过微调针对特定任务的小型模型,可以控制构建和维护系统的总体费用。


环境设置

我建议你使用一个独立的 Python 环境,比如 Google Colab,因为我们需要对依赖关系进行一些处理。模型在 GPU 上运行速度更快,因此如果你有专业版,可以使用 GPU 驱动的运行时。


此外,我们还需要设置原生图数据库 Neo4j 来存储提取的信息。有很多方法可以设置数据库实例。不过,我推荐使用 Neo4j Aura,它提供了一个免费的云实例,可以通过 Google Colab 笔记本轻松访问。


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


from llama_index.graph_stores.neo4j import 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
NUMBER_OF_ARTICLES = 100
news = pd.read_csv(
    "https://raw.githubusercontent.com/tomasonjo/blog-datasets/main/news_articles.csv"
)
news = news.head(NUMBER_OF_ARTICLES)


核心参照解析

管道的第一步是核心参照解析模型。核心参照解析是识别文本中所有表达式是否指向同一实体的任务。


据我所知,可用于核心参照解析的开源模型并不多。我尝试过 maverick-coref,但在我的测试中,spaCy 的 Coreferee 效果更好,因此我们将使用它。使用 Coreferee 的唯一缺点是我们必须处理依赖性地狱问题,这个问题可以在笔记本中解决,但我们在此就不赘述了。


你可以用下面的代码在 spaCy 中加载 coreference 模型:


import spacy, coreferee
coref_nlp = spacy.load('en_core_web_lg')
coref_nlp.add_pipe('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


让我们测试一下该函数,以确保模型和依赖关系设置正确:


print(
    coref_text("Tomaz is so cool. He can solve various Python dependencies and not cry")
)
#  Tomaz is so cool . Tomaz can solve various Python dependencies and not cry


在本例中,模型识别出 “Tomaz ”和 “He ”指的是同一个实体。我们使用 coref_text 函数将 “He ”替换为 “Tomaz”。


请注意,由于对群组内的实体使用了简单的替换逻辑,重写并不总是能返回语法正确的句子。不过,对于大多数情况来说,这已经足够好了。


现在,我们将核心参照解析应用于新闻数据集,并将结果封装为 LlamaIndex 文档:


from llama_index.core import Document
news["coref_text"] = news["text"].apply(coref_text)
documents = [
    Document(text=f"{row['title']}: {row['coref_text']}") for i, row in news.iterrows()
]


实体链接和关系提取

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


9


另一方面,关系提取涉及识别文本中实体之间的关系并对其进行分类,从而能够从非结构化数据中提取结构化信息。


10


如果你使用的是免费 Colab 版本,请使用 relik-ie/relik-relation-extraction-small 模型,该模型只执行关系提取。如果你使用的是专业版,或将在更强大的本地计算机上使用,则可以测试 relik-ie/relik-cie-small 模型,该模型可执行实体链接和关系提取。


from llama_index.extractors.relik.base import RelikPathExtractor
relik = RelikPathExtractor(
    model="relik-ie/relik-relation-extraction-small"
)
# Use on Pro Collab with GPU
# relik = RelikPathExtractor(
#    model="relik-ie/relik-cie-small", model_config={"skip_metadata": True, "device":"cuda"}
# )


此外,我们还必须定义用于嵌入实体的嵌入模型和用于问题解答流程的 LLM:


import os
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI
os.environ["OPENAI_API_KEY"] = "sk-"
llm = OpenAI(model="gpt-4o", temperature=0.0)
embed_model = OpenAIEmbedding(model_name="text-embedding-3-small")


请注意,在构建图时不会使用 LLM。


现在一切就绪,我们可以实例化 PropertyGraphIndex 并将新闻文档作为知识图谱的输入数据。


此外,我们还需要传递 relik 模型作为 kg_extractors 值,以提取关系:


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


构建图形后,可以打开 Neo4j 浏览器验证导入的图形。运行下面的 Cypher 语句也能获得类似的可视化效果:


MATCH p=(:__Entity__)--(:__Entity__)
RETURN p LIMIT 250


结果


11


问题解答

现在,使用 LlamaIndex 可以轻松地进行问题解答。要使用默认的图形检索器,你可以提出以下简单明了的问题:


query_engine = index.as_query_engine(include_text=True)
response = query_engine.query("What happened at Ryanair?")
print(str(response))


这就是定义的 LLM 和嵌入模型发挥作用的地方。当然,你也可以使用自定义检索器来提高准确性。


总结

不依赖 LLM 构建知识图谱不仅可行,而且经济高效。通过微调较小的、针对特定任务的模型(如 Relik 框架中的模型),你可以为你的检索增强生成 (RAG) 应用程序实现高性能的信息提取。


实体链接是这一过程中的关键步骤,可确保识别的实体准确映射到知识库中的相应条目,从而保持知识图谱的完整性和实用性。


通过使用 Relik 等框架和 Neo4j 等平台,可以构建先进的知识图谱,从而为复杂的数据分析和检索任务提供便利,而这一切通常都与部署 LLM 的高成本无关。这种方法不仅使强大的数据处理工具更容易获得,还促进了信息提取工作流程的创新和效率。

文章来源:https://medium.com/neo4j/entity-linking-and-relationship-extraction-with-relik-in-llamaindex-ca18892c169f
欢迎关注ATYUN官方公众号
商务合作及内容投稿请联系邮箱:bd@atyun.com
评论 登录
热门职位
Maluuba
20000~40000/月
Cisco
25000~30000/月 深圳市
PilotAILabs
30000~60000/年 深圳市
写评论取消
回复取消