点击上方↗️「活水智能」,关注 + 星标🌟
作者:Lina Faik
编译:活水智能
大型语言模型(LLMs)的兴起彻底改变了我们从文本中提取信息和与之交互的方式。然而,尽管它们的能力令人印象深刻,LLMs在推理、一致性以及信息的上下文准确性等方面仍然面临一些固有的挑战。这些问题源于LLMs的概率性本质,可能导致幻觉(hallucinations)、缺乏透明性以及处理结构化数据的困难。
这正是知识图谱(Knowledge Graphs, KGs)发挥作用的地方。通过将LLMs与知识图谱相结合,可以显著增强AI生成的知识。为什么呢?知识图谱提供了信息的结构化和互联表示,反映了现实世界中实体及其关系。与传统数据库不同,知识图谱能够捕获并推理人类知识的复杂性,确保LLMs的输出来自结构化、可验证的知识库。这种整合可以带来更准确、一致且上下文相关的结果。
像医疗、金融和法律服务等行业由于对精确和可解释性信息的需求,可以从知识图谱中获得巨大益处。
本文探讨了如何利用LLMs构建和利用知识图谱的创新方法。
阅读本文后,您将了解:
1. 如何使用LLMs构建知识图谱
2. LLMs如何利用知识图谱提升其能力
3. 在将LLMs与知识图谱结合时的局限性和关键考虑因素
无需任何先验知识即可理解本文。文中描述的实验仅使用了 llama-index 库(https://www.llamaindex.ai/)。
您可以在GitHub上找到代码:https://github.com/linafaik08/knowledge_graphs_llm。
本节全面介绍了使用LLMs构建和利用知识图谱的过程。在深入探讨具体方法之前,首先介绍了关键概念、术语以及各种方法。
图1展示了整体工作流程,包括两个关键步骤:
1. 知识图谱的提取及其可能的技术(详见第2节)。此步骤生成知识图谱。
2. 使用第3节中详细讨论的技术进行检索。这些技术可用于回答查询。
在网络术语中,三元组(triplet)是知识图谱的基本单元。它由三个元素组成:主语(一个实体)、关系(实体之间的连接)和宾语(另一个实体)。
节点(nodes)代表网络中的实体(例如,人、公司),而边(edges)或链接表示这些节点之间的关系或交互。
节点和边共同构成图结构,其中三元组定义了网络中的特定连接。
实验数据来自维基百科关于“巴拿马文件丑闻”的页面。
llama-index 库提出了4种主要方法,从文档语料中使用LLMs提取知识图谱:
1. 基于模式的提取
2. 自由形式的提取
3. 动态提取
4. 隐式提取
让我们深入了解这些方法。
这种方法的核心思想是基于预定义的网络模型构建图谱。通过指定所需的实体类型及其可能的关系,基于LLMs的方法从文本中生成一个按照指定模型结构化的网络。
💡 示例: 在“巴拿马文件丑闻”中,我们可以建立一个预定义的结构,其中实体包括公司、银行或丑闻,关系定义为“涉及”或“拥有”。基于模式提取的图谱将揭示诸如“某人拥有某公司”或“某银行涉及某丑闻”之类的连接。
如何在实践中实现基于模式的提取?
以下是实现基于模式提取的代码框架:
from typing import Literal
from llama_index.core.indices.property_graph import SchemaLLMPathExtractor
from llama_index.core import PropertyGraphIndex
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI
# 定义知识图谱的可能实体类型
entities = Literal["PERSON", "COMPANY", "COUNTRY", "BANK", "SCANDAL"]
# 定义知识图谱中实体之间可能的关系
relations = Literal["OWNS", "LOCATED_IN", "INVOLVED_IN"]
# 定义概述哪些实体可以具有哪些关系的模式
schema = {
"PERSON": ["OWNS", "LOCATED_IN", "INVOLVED_IN"],
"COMPANY": ["OWNS", "LOCATED_IN", "INVOLVED_IN"],
"COUNTRY": ["LOCATED_IN"],
"BANK": ["LOCATED_IN", "INVOLVED_IN"],
"SCANDAL": ["INVOLVED_IN"],
}
# 创建 SchemaLLMPathExtractor 实例以基于定义的模式提取路径
kg_extractor = SchemaLLMPathExtractor(
llm=OpenAI(model=LLM_MODEL, temperature=TEMPERATURE), # 使用指定参数的OpenAI语言模型
possible_entities=entities, # 定义要提取的实体类型
possible_relations=relations, # 定义要提取的关系类型
kg_validation_schema=schema, # 使用预定义的模式进行验证
strict=True, # 强制严格验证;仅允许模式中定义的实体和关系
)
# 使用指定的嵌入模型从提供的文档中创建 PropertyGraphIndex
index = PropertyGraphIndex.from_documents(
documents, # 待处理和索引的输入文档
embed_model=OpenAIEmbedding(model_name=EMBEDDING_MODEL), # 使用OpenAI的嵌入模型进行文档表示
show_progress=True, # 在索引过程中显示进度
kg_extractors=[kg_extractor], # 使用之前定义的 SchemaLLMPathExtractor 提取知识图谱路径
)
# 定义关键字提取器的存储路径
path_output_storage_kg_extractor = f"{path_output_storage}/{kw_extractor_name}/"
# 如果存储目录不存在,则创建它
if not os.path.exists(path_output_storage_kg_extractor):
os.makedirs(path_output_storage_kg_extractor)
# 将索引的存储上下文持久化到指定目录
index.storage_context.persist(persist_dir=path_output_storage_kg_extractor)
# 将知识图谱保存为 HTML 文件
index.property_graph_store.save_networkx_graph(name=f"{path_output}/kwnoledge_graphs_{kw_extractor_name}.html")
⚠️ 注意:在
PropertyGraphIndex
的kg_extractors
参数中,可以添加多个知识提取器实例,从而在单个网络中结合多种提取方法。
图2展示了代码生成的基于模式提取的图谱的一部分。节点代表人、公司、国家、银行或丑闻,而关系仅限于代码中预定义的“拥有”和“涉及”。
基于模式提取的方法是什么?
✓ 文本分析: 提取器首先使用LLM分析每个文本块的内容。模型根据提供的模式解释文本,识别潜在的实体(如人、组织或地点)和关系(如所有权、位置或关联)。
✓ 路径提取:
• 工具使用模式作为指南,提取已识别实体之间的特定关系,形成三元组。
• 三元组由三个部分组成:主语实体、关系和宾语实体(例如,“某人拥有某公司”)。
• max_triplets_per_chunk
参数限制每次处理的三元组数量,确保在处理大数据集时的效率。
✓ 验证: 提取的三元组随后根据模式进行验证,以确保它们符合预定义的实体和关系类型。如果模式设置为严格模式,则仅保留完全符合模式的三元组。
✓ 图谱构建: 验证后的三元组用于构建或扩展知识图谱。每个三元组为图谱添加节点(实体)和边(关系),逐步构建反映从文本中提取的信息的网络。
✓ 元数据整合: 工具还可以整合元数据,包括与实体和关系相关的附加上下文或属性(如时间戳、来源文档)。这有助于用更详细和相关的信息丰富图谱。
自由形式提取是一种灵活的关系(三元组)提取方法,与基于模式的提取方法不同,它不依赖于预定义的模式或结构,而是利用语言模型(LLM)的能力自主识别实体之间的有意义连接。
💡 示例: 在“巴拿马文件丑闻”中,自由形式提取可以分析泄露的文件,揭示个人、公司和离岸实体之间的隐藏关系。例如,模型可能提取出“三元组”如“公司B注册于离岸司法管辖区C”或“律师事务所D管理公司B”。这些从上下文中推断出的连接有助于构建一个映射丑闻中涉及实体复杂网络的知识图谱。
如何在实践中实现自由形式的提取?
from llama_index.core.indices.property_graph import SimpleLLMPathExtractor
# 创建 SimpleLLMPathExtractor 实例
kg_extractor = SimpleLLMPathExtractor(
llm=OpenAI(model=LLM_MODEL, temperature=TEMPERATURE)
)
图3展示了自由形式提取图谱的一部分。在这里,节点之间的关系更加灵活,允许更大的探索空间。然而,这种灵活性涉及在探索欲望与对简洁、重点表示的需求之间的权衡。
来源:“卡塔尔前埃米尔哈马德·本·哈利法·阿勒萨尼拥有Afrodille S.A.,该公司在卢森堡有一个银行账户,并持有两家南非公司的股份。阿勒萨尼还持有Rienne S.A.和Yalis S.A.的大部分股份,并在卢森堡中国银行持有定期存款。” [3]
自由形式提取如何实现其结果?
✓ 输入文本分析: 该过程从分析文本块的输入文本开始。内容通过语言模型处理,使用特定提示词引导提取过程,生成潜在的三元组。提取由 max_paths_per_chunk
参数控制,该参数限制每个块生成的三元组数量。这确保了在处理大量文本时的效率和可管理性。
✓ 解析: 语言模型的输出随后由函数解析,从原始文本响应中提取这些三元组。
✓ 构建图谱: 提取的三元组用于创建或更新知识图谱。这些节点和边被元数据丰富化,例如数据来源或时间戳等附加信息。
动态提取与自由形式提取在灵活性上类似,但它引入了一个初始结构,并且随着模型处理更多数据可以不断演化。
与自由形式提取允许模型在没有任何预定义结构的情况下解释和提取关系不同,动态提取从一个基本本体(例如一组初始实体类型和关系)开始,引导提取过程。
这种方法不仅提取关系,还鼓励发现新的实体类型和连接,并在需要时扩展本体。
💡 示例: 在“巴拿马文件丑闻”中,动态提取可能从包含“人物”、“公司”和“离岸账户”等实体和“拥有”或“控制”等关系的初始本体开始。当LLM处理泄露的文档时,它可能发现新的关系(例如“由…促成”,将某人与律师事务所连接起来)或识别新的实体类型(例如“空壳公司”)。这些发现将扩展原始本体,使知识图谱能够捕获丑闻中实体及其连接的更广泛和更细致的图景。
如何在实践中实现动态提取?
from llama_index.core.indices.property_graph import DynamicLLMPathExtractor
from llama_index.core import PropertyGraphIndex
from llama_index.llms.openai import OpenAI
# 定义知识图谱的可能实体类型
entities = ["PERSON", "COMPANY", "COUNTRY", "BANK", "SCANDAL"]
# 定义知识图谱中实体之间可能的关系
relations = ["OWNS", "LOCATED_IN", "INVOLVED_IN"]
# 创建 DynamicLLMPathExtractor 实例
kg_extractor = DynamicLLMPathExtractor(
llm=OpenAI(model=LLM_MODEL, temperature=TEMPERATURE),
allowed_entity_types=entities,
allowed_relation_types=relations,
)
图4展示了动态提取的图谱片段。它表明该方法成功识别了新的相关实体和关系,并在提供的初始结构基础上进行了扩展。这种技术在探索与结构之间实现了理想的平衡。
图4 — 动态提取图谱的一部分
动态提取方法如何运作?
✓ 从初始本体开始: 与自由形式提取不同,动态提取从一个初始本体开始,包括基本的实体类型(如“人物”、“公司”)和关系(如“拥有”、“位于”)。它作为方法可以扩展的起点。
✓ LLM引导提取: 与自由形式提取类似,动态提取使用提示词指导语言模型(LLM)提取内容。然而,动态提取的提示词不仅引导已知实体和关系的提取,还鼓励LLM识别并提出新的实体和关系。
✓ 解析与图谱扩展: 模型的输出被解析为三元组(主语-关系-宾语),与自由形式提取类似。然而,在动态提取中,此过程包括识别和整合新的实体类型或关系。
✓ 本体演化: 随着模型处理更多文本,它会不断优化和扩展本体。
这种方法的关键思想是利用数据中的内在连接来识别实体之间的关系,即使这些关系没有被明确提及。它根据数据的结构或上下文推断关系,在关系可以被逻辑推导而非直接陈述的情况下特别有用。
💡 示例: 隐式提取最适合分析具有内在关系的结构化文档,例如法律合同或具有明确章节、子章节和引用层次的研究论文。在这种情况下,章节之间的关系(例如“第1章之后是第2章”)或引用之间的关系(例如“第A节引用了参考文献B”)并未明确标注为关系,但可以从文档的结构中推断出来。隐式提取会自动推断诸如“第1.1条是第1节的子节”或“第1.1条引用了附录A”之类的关系。
如何在实践中实现隐式提取?
以下是实现隐式提取的代码框架:
from llama_index.core.indices.property_graph import ImplicitPathExtractor
# 创建 ImplicitPathExtractor 实例
kg_extractor = ImplicitPathExtractor()
隐式提取如何进行?
✓ 节点关系: 图中的每个节点可能与其他节点存在多种类型的关系,例如是另一个节点的父节点、在顺序上位于另一个节点之前或之后,或将另一个节点作为引用来源。这些关系通常存储在节点的结构中。
✓ 边的提取: 提取器扫描节点列表并检查这些内在关系。对于每个节点,它识别与其他节点的连接,并在它们之间创建相应的边(关系)。这些边会根据关系的类型被适当地标注(例如“父节点”、“子节点”、“下一个”、“上一个”)。
✓ 元数据整合: 在此过程中,提取器还可以整合与节点相关的任何元数据,例如时间戳或来源信息。这些信息丰富了图谱,使隐式连接更加具有信息性。
一旦图谱构建完成,接下来的挑战是如何有效地利用它来处理LLM查询。Llama-Index库目前提供了四种方法,其中两种基于Cypher查询语言。
1. 向量上下文检索器
2. LLM同义词检索器
3. 文本到Cypher转换
4. Cypher模板检索器
Cypher是一种强大的查询语言,用于与图数据库交互,通过模式匹配和其他高级查询技术实现精确的数据检索和操作。
这种方法基于查询与节点的语义相似性检索节点,从而实现更精确和上下文相关的搜索结果。
💡 示例: 想象一下在从巴拿马文件数据构建的属性图谱中搜索与“离岸账户”相关的信息。向量上下文检索器会将查询转换为向量,并找到图谱中语义上相似的节点,例如表示特定公司、个人或与离岸账户相关的交易的节点。然后,它会检索这些节点以及任何直接相关的实体(例如所有者或关联银行),并按相关性排序返回它们。
如何在实践中应用向量上下文检索器?
# 从 llama_index 库导入必要模块
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI
from llama_index.core.indices.property_graph import VectorContextRetriever
# 使用 VectorContextRetriever 创建子检索器
sub_retriever = VectorContextRetriever(
index.property_graph_store,
vector_store=index.vector_store,
embed_model=OpenAIEmbedding(model_name=EMBEDDING_MODEL),
)
# 使用之前定义的子检索器从索引中创建检索器
retriever = index.as_retriever(sub_retrievers=[sub_retriever])
# 初始化查询引擎
query_engine = index.as_query_engine(sub_retrievers=[retriever])
# 查询引擎示例查询
print(query_engine.query(
"国际调查记者联盟(ICIJ)如何参与巴拿马文件丑闻?"
).response)
输出:
国际调查记者联盟(ICIJ)在南德意志报意识到验证泄露数据真实性所需工作量后,帮助组织了研究和文档审查。ICIJ招募了来自各媒体的记者和资源,调查与莫萨克·冯赛卡相关的个人和组织。此外,ICIJ在验证来源和内容后,在其网站上发布了巴拿马文件丑闻的泄露文档。
图4 — 支持回答查询的知识图谱部分
向量上下文检索器如何工作?
✓ 查询嵌入: 提交查询时,向量上下文检索器首先使用嵌入模型将查询转换为向量表示。此向量捕获查询的语义含义,使检索器能够在图中找到类似的内容。
✓ 向量存储查询: 检索器使用相似性度量(如余弦相似度)识别与查询向量最相似的节点。检索的节点数量由 similarity_top_k
参数控制。
✓ 节点检索与路径扩展: 一旦识别出最相似的节点,检索器还可以根据指定的 path_depth
参数探索与这些节点相关的关系。
✓ 相似性评分: 每个检索到的节点都会被分配一个相似性评分,反映其与查询的匹配程度。
✓ 最终输出: 检索器按相似性评分对检索到的节点进行排序,可选地基于 similarity_score
阈值过滤它们,然后返回最相关的节点及其相关关系。
LLM同义词检索器通过使用LLM扩展用户查询的同义词来增强知识图谱的信息检索能力。
这种扩展允许检索器从图谱中捕获并返回更多相关节点,从而提高搜索结果的准确性。
💡 示例: 一位调查员在巴拿马文件图谱中搜索“离岸公司”,可以使用LLM同义词检索器将查询扩展为“空壳公司”或“避税天堂实体”等术语。这种更广泛的搜索会发现更多相关节点,例如参与逃税的公司,这些节点可能会被原始查询忽略,从而进行更彻底的调查。
如何在实践中使用LLM同义词检索器?
from llama_index.core.indices.property_graph import LLMSynonymRetriever
sub_retriever = LLMSynonymRetriever(
index.property_graph_store,
llm=OpenAI(model=LLM_MODEL, temperature=TEMPERATURE),
include_text=True,
max_keywords=100,
path_depth=5,
)
LLM同义词检索器的工作原理是什么?
✓ 查询同义词扩展: 提交查询时,LLM同义词检索器首先使用语言模型为查询中的关键词生成同义词。这通过预定义的提示词完成,提示LLM建议与原查询词类似的替代词或短语。
✓ 同义词整合: LLM生成的同义词被整合到查询中,从而使LLM能够在图谱中进行更广泛的搜索。
✓ 图谱检索:
• 扩展后的查询用于从图谱中检索节点。检索器搜索与扩展查询中的任何术语匹配的节点和关系。
• 检索的深度(即搜索关系链的程度,例如直接连接或更深层次的关系)可以通过 path_depth
参数调整。
✓ 解析与匹配: LLM的输出被解析为可用于识别图谱中相关节点的格式。
✓ 节点评分与检索: 匹配的节点根据它们与原始查询的相关性及其在图谱中的关系进行评分。然后,检索器返回节点列表及其相关评分,代表查询的最相关实体和连接。
Llama-Index 提供了两种基于Cypher的检索器以利用图数据库的功能。
简要概述如下:
• TextToCypherRetriever:通过利用图存储模式、输入查询和文本到Cypher转换的提示模板生成并执行Cypher查询。
• CypherTemplateRetriever:相比TextToCypherRetriever,提供了一种更受控的方法。它使用预定义的Cypher模板,其中LLM填充具体细节。
✓ 知识图谱不仅提高了AI生成知识的准确性和上下文相关性,还为医疗、金融和法律服务等需要精确和可解释性信息的行业提供了强大的工具。
✓ 在选择使用LLMs构建知识图谱的方法时,需权衡探索性与结构化之间的取舍。动态提取为需要灵活性和结构的用户提供了一个绝佳的平衡。
✓ 在利用知识图谱时,可以使用多种技术,其中基于向量的方法提供了高效的检索能力。
✓ 然而,需要承认的是,当前版本的Llama-Index在网络分析和处理复杂图结构方面存在局限性。随着知识图谱与LLMs的协同作用成为热门话题,这些能力必然会进一步提升!
[1] Llama-Index文档 (https://docs.llamaindex.ai/en/latest/module_guides/indexing/lpg_index_guide/#default-llmsynonymretriever) [2] 介绍属性图索引:一种利用LLMs构建知识图谱的强大新方法 (https://www.llamaindex.ai/blog/introducing-the-property-graph-index-a-powerful-new-way-to-build-knowledge-graphs-with-llms)
若要了解更多知识图谱或neo4j图数据库相关教学,你可以查看公众号的其他文章:
活水智能成立于北京,致力于通过AI教育、AI软件和社群提高知识工作者生产力。中国AIGC产业联盟理事。
活水现有AI线下工作坊等10+门课程,15+AI软件上线,多款产品在研。知识星球中拥有2600+成员,涵盖大厂程序员、公司高管、律师等各类知识工作者。在北、上、广、深、杭、重庆等地均有线下组织。
欢迎加入我们的福利群,每周都有一手信息、优惠券发放、优秀同学心得分享,还有赠书活动~
👇🏻👇🏻👇🏻