大数跨境
0
0

用 iText2KG 增量构建《西游记》知识图谱

用 iText2KG 增量构建《西游记》知识图谱 数翼
2024-09-29
0
本文介绍了实体和关系的增量提取 工具 iText2KG。并已《西游记》白话文为例, 演示如何使用该工具基于文本进行知识图谱的构建和展示。

iText2KG 是一个 Python 包,旨在通过利用大型语言模型从文本文档中提取实体和关系, 逐步构建具有已解析实体和关系的一致知识图谱。它具有零样本能力,无需专门的训练即可跨各个领域提取知识。 该包包括用于文档提炼、实体提取和关系提取的模块,确保已解析且唯一的实体和关系。 它不断用新文档更新知识图谱,并将其集成到 Neo4j 等框架中进行可视化表示。

总体架构

iText2KG软件包由四个主要模块组成,它们协同工作,从非结构化文本构建和可视化知识图谱。整体架构概述:

  1. 1. 文档提取器:该模块处理原始文档,并根据用户定义的模式将其重新组织成语义块。它通过关注相关信息并以预定义的格式对其进行结构化来提高信噪比。

  2. 2. 增量实体提取器:此模块从语义块中提取唯一实体并解决歧义以确保每个实体都有明确定义。它使用余弦相似度度量将局部实体与全局实体进行匹配。

  3. 3. 增量关系提取器:此模块识别提取的实体之间的关系。它可以以两种模式运行:使用全局实体丰富图形中的潜在信息,或使用局部实体建立更精确的关系。

  4. 4. 图形集成器和可视化:此模块将提取的实体和关系集成到 Neo4j 数据库中,提供知识图谱的可视化表示。它允许对结构化数据进行交互式探索和分析。

iText2KG 总体架构四个模块

LLM 被提示提取代表一个唯一概念的实体,以避免语义混合的实体。 下图显示了使用 Langchain JSON 解析器的实体和关系提取提示。 它们分类如下:

  • • 蓝色 - 由 Langchain 自动格式化的提示;

  • • 常规 - 我们设计的提示;

  • • 斜体 - 专门为实体和关系提取设计的提示。

    • • (a)关系提取提示和

    • • (b)实体提取提示。

安装

要安装 iText2KG,请确保已安装 Python,然后使用 pip 安装

pip install itext2kg

或者使用 poetry 安装:

poetry add itext2kg

准备文档

我这里使用《西游记》的白话文版本来进行演示。

准备好文本(百度搜索有很多),放到 datasets 目录:

加载大模型

iText2KG 进行知识图谱的抽取使用到了聊天和嵌入两个模型,可以使用本地 Ollama 的模型:

from langchain_ollama import ChatOllama, OllamaEmbeddings

llm = ChatOllama(
    model="glm4",
    temperature=0,
)
embeddings = OllamaEmbeddings(
    model="glm4",
)

记得安装依赖:

pip install langchain-community langchain-ollama

定义指令

iText2KG 可以很方便的定义指令,比如我下面的:

IE_query = '''
指令:
- 像经验丰富的信息提取者一样行动。
- 提取的信息包含人物、地点、事件、物品、任务以及技能。
- 您有大量的故事阅读。
- 如果找不到正确的信息,请将其保留为空白。
'''

你可以根据你要抽取的数据类型进行简单定制。

文件处理

类似 RAG 一样,我们也需要对文件进行预处理,我直接给出函数代码,大家需要的话可以直接拿来用:

def build_sections(file_path):
    loader = PythonLoader(file_path)
    pages = loader.load_and_split()

    # we have replaced the curly braces with square brackets to avoid the error in the query
    distilled_cv = document_distiller.distill(
        documents=[page.page_content.replace("{"'[').replace("}""]"for page in pages],
        IE_query=IE_query,
        output_data_structure=CV
    )

    sections = [f"{key} - {value}".replace("{""[").replace("}""]"for key, value in distilled_cv.items()
                if value != [] and value != "" and value != None]
    return sections

如果要处理 xiyou01.txt 文件,那么可以如下写:

sections = build_sections('./datasets/xiyou01.txt')

sections 的内容大概是这样:

构建图谱

加下来就是构建图谱了,我也把写好的函数贴到下面,需要的大家可以直接用:

def build_graph(sections, existing_global_entities=None, existing_global_relationships=None,ent_threshold=0.6, rel_threshold=0.6):
    global_ent, global_rel = itext2kg.build_graph(
        sections=sections, ent_threshold=ent_threshold, rel_threshold=rel_threshold,
        existing_global_relationships=existing_global_relationships,
        existing_global_entities=existing_global_entities
    )
    print(global_rel)
    print(global_ent)
    return global_ent, global_rel
ent_thresholdrel_threshold 两个阈值用来确定节点根据向量信息是否合并。值越大,节点越多。两个值建议去相同值。

传入刚才的 sections 就可以得到节点和关系数据:

global_ent, global_rel = build_graph(sections)

我们可以看到节点数据大约如下:

关系数据大约如下:

从控制台的调试信息我们可以看出,iText2KG 会进行关系梳理、节点去重等动作:

由于大模型的不确定性,不同的大模型的计算的结果会不一样,及时同一个模型出来的结果也可能不一样。

显示

我们使用 pyvis 这个工具来显示图谱。

首先是安装:

pip install pyvis

程序比较简单:

from pyvis.network import Network

net = Network(height="100vh", width="100%")
for x in global_ent:
    net.add_node(x['name'])
for x in global_rel:
    net.add_edge(x['startNode'], x['endNode'], weight=1)
net.show('mygraph.html', notebook=False)

然后点击生成的 mygraph.html 文件,就可以看到关系数据如下:

调整下参数,你可能得到更多的节点和关系:

增量构建

iText2KG 在构建图谱的一个亮点功能就是增量构建

比如刚才了构建了《西游记》的第一章的图谱,我们可以在第一章的基础之上进行构建, 而不是第一章和第二章一起构建。

sections2 = build_sections(text02)
global_ent2, global_rel2 = build_graph(sections2, existing_global_entities=global_ent1, existing_global_relationships=global_rel1)

再次画图看一下结构吧:

这次效果不是很好,产生了一些孤立节点。

增量构建 我们看到了,增量构建依赖于前面的构建结果,如果每次都把前面结果执行一遍算出来,其实增量构建的效果就没有了。 一般情况我们会做如下处理:
  1. 1. 每次构建的结果都记录到数据库(比如 Neo4j)中,也可以是本地文件(SCV/JSON)

  2. 2. 每次构建的记录都和文本进行关联(比如西游记第一章,第二章)

  3. 3. 多次构建并进行参数调整达到比较满意的效果

  4. 4. 提取结果人工调整

  5. 5. 增量构建的时候使用历史数据(数据库或本地文件),避免重复计算

  6. 6. 重复 1234 步

指定结构

iText2KG 还有一个很棒的特性就是你可以指定节点的属性结构。

先声明一个节点类,比如官方示例中的简历:


class JobOffer(BaseModel):
    job_offer_title: str = Field(..., description="The job title")
    company: str = Field(..., description="The name of the company offering the job")
    location: str = Field(..., description="The job location (can specify if remote/hybrid)")
    job_type: str = Field(..., description="Type of job (e.g., full-time, part-time, contract)")
    responsibilities: List[JobResponsibility] = Field(..., description="List of key responsibilities")
    qualifications: List[JobQualification] = Field(..., description="List of required or preferred qualifications")
    certifications: Optional[List[JobCertification]] = Field(None, description="Required or preferred certifications")
    benefits: Optional[List[str]] = Field(None, description="List of job benefits")
    experience_required: str = Field(..., description="Required years of experience")
    salary_range: Optional[str] = Field(None, description="Salary range for the position")
    apply_url: Optional[str] = Field(None, description="URL to apply for the job")

然后我们再蒸馏的时候就可以指定 output_data_structure 参数:

distilled_Job_Offer = document_distiller.distill(
    documents=[job_offer], IE_query=IE_query,
    output_data_structure=JobOffer
)

写在最后

AI应用 特别是 LLM 应用的性能,很大程度依赖大模型本身。

iText2KG 也不例外,小参数的大模型很可能解析不出期望的结果。

个人感觉,这个框架虽然能用,但是速度、准确度都比较慢,成本(TOKEN)也比较高。 但是好在,项目本身是在积极开发中。

项目代码:https://github.com/AuvaLab/itext2kg[1]


Links:

  • • Obsidian iText2KG[2]

引用链接

[1]https://github.com/AuvaLab/itext2kg
[2] Obsidian iText2KG: obsidian://open?vault=ObsidianKG&file=AI%2FKG%2FExtraction%2FiText2KG


【声明】内容源于网络
0
0
数翼
专注 AIGC 人工智能知识传播和实践
内容 228
粉丝 0
数翼 专注 AIGC 人工智能知识传播和实践
总阅读154
粉丝0
内容228