LlamaIndex中的属性图索引(PropertyGraphIndex)深度解析
什么是属性图索引
属性图(Property Graph)是一种知识表示形式,它由带标签的节点(如实体类别、文本标签等)和属性(元数据)组成,节点之间通过关系连接形成结构化路径。在LlamaIndex中,PropertyGraphIndex
提供了构建和查询属性图的核心功能。
属性图索引特别适合以下场景:
- 需要表示复杂实体关系的知识图谱
- 需要结合结构化关系和非结构化文本的检索系统
- 需要多跳推理的问答系统
基础使用方式
使用PropertyGraphIndex
非常简单,基本流程包括创建索引、查询索引以及持久化存储:
from llama_index.core import PropertyGraphIndex
# 从文档创建索引
index = PropertyGraphIndex.from_documents(documents)
# 作为检索器使用
retriever = index.as_retriever()
nodes = retriever.retrieve("查询内容")
# 作为查询引擎使用
query_engine = index.as_query_engine()
response = query_engine.query("查询问题")
# 持久化存储
index.storage_context.persist(persist_dir="./storage")
# 从存储加载
from llama_index.core import StorageContext, load_index_from_storage
index = load_index_from_storage(StorageContext.from_defaults(persist_dir="./storage"))
索引构建详解
属性图索引的构建过程是通过一系列kg_extractors
(知识提取器)实现的,这些提取器会从每个文本块中提取实体和关系,并将其作为元数据附加到节点上。
内置知识提取器
LlamaIndex提供了多种知识提取器,每种都有不同的特点和适用场景:
- SimpleLLMPathExtractor(默认)
- 使用LLM提取简单的三元组(实体1, 关系, 实体2)
- 可自定义提示词和解析函数
- 适合提取简单直接的关系
from llama_index.core.indices.property_graph import SimpleLLMPathExtractor
kg_extractor = SimpleLLMPathExtractor(
llm=llm,
max_paths_per_chunk=10, # 每个块提取的最大路径数
num_workers=4 # 并行工作数
)
-
ImplicitPathExtractor(默认)
- 从节点的relationships属性中提取路径
- 不需要LLM或嵌入模型
- 适合已有结构化关系的场景
-
DynamicLLMPathExtractor
- 可指定允许的实体类型和关系类型
- 提供类型引导但不强制
- 适合需要一定类型约束的场景
kg_extractor = DynamicLLMPathExtractor(
allowed_entity_types=["人物", "组织"],
allowed_relation_types=["属于", "创建于"]
)
- SchemaLLMPathExtractor
- 严格遵循预定义的实体和关系模式
- 使用Pydantic进行验证
- 适合需要严格模式控制的场景
entities = Literal["人物", "地点", "事物"]
relations = Literal["属于", "拥有", "是"]
schema = {
"人物": ["属于", "拥有", "是"],
"地点": ["属于", "拥有"],
"事物": ["是"]
}
kg_extractor = SchemaLLMPathExtractor(
possible_entities=entities,
possible_relations=relations,
kg_validation_schema=schema,
strict=True # 是否允许模式外的三元组
)
检索与查询机制
属性图索引支持多种检索方式,可以组合使用:
内置检索器
-
LLMSynonymRetriever(默认)
- 基于LLM生成的关键词和同义词检索
- 可自定义提示词和解析函数
-
VectorContextRetriever(默认)
- 基于向量相似度检索
- 支持图存储原生向量或外部向量存储
-
TextToCypherRetriever
- 将自然语言转换为Cypher查询
- 需要图数据库支持Cypher
-
CypherTemplateRetriever
- 使用带参数的Cypher模板
- 比TextToCypher更安全可控
# 组合多个检索器示例
from llama_index.core.indices.property_graph import (
VectorContextRetriever,
LLMSynonymRetriever
)
sub_retrievers = [
VectorContextRetriever(...),
LLMSynonymRetriever(...)
]
retriever = index.as_retriever(sub_retrievers=sub_retrievers)
存储系统详解
LlamaIndex支持多种属性图存储后端:
| 存储类型 | 内存存储 | 原生向量支持 | 异步 | 存储方式 | |----------------------|----------|--------------|------|----------| | SimplePropertyGraphStore | ✅ | ❌ | ❌ | 磁盘 | | Neo4jPropertyGraphStore | ❌ | ✅ | ❌ | 服务器 | | NebulaPropertyGraphStore | ❌ | ❌ | ❌ | 服务器 |
直接操作图存储
开发者可以直接操作图存储,实现更精细的控制:
from llama_index.core.graph_stores import EntityNode, Relation
# 创建节点和关系
entities = [
EntityNode(name="大模型", label="技术", properties={"领域":"AI"}),
EntityNode(name="LlamaIndex", label="框架", properties={"语言":"Python"})
]
relations = [Relation(label="实现", source_id=entities[0].id, target_id=entities[1].id)]
# 插入到存储
graph_store.upsert_nodes(entities)
graph_store.upsert_relations(relations)
常用操作方法包括:
get()
- 根据ID或属性查询节点get_rel_map()
- 获取指定深度的关系图delete()
- 删除节点structured_query()
- 执行结构化查询(Cypher等)
高级自定义
LlamaIndex的组件设计允许深度定制:
自定义提取器
通过继承TransformComponent
类,可以实现自定义的知识提取逻辑:
from llama_index.core import TransformComponent
class CustomExtractor(TransformComponent):
def __call__(self, nodes):
for node in nodes:
# 自定义提取逻辑
node.metadata["custom_kg"] = extracted_data
return nodes
自定义检索器
通过继承BasePGRetriever
类,可以实现自定义的检索逻辑:
from llama_index.core.indices.property_graph import BasePGRetriever
class CustomRetriever(BasePGRetriever):
def _retrieve(self, query_str):
# 自定义检索逻辑
return retrieved_nodes
最佳实践建议
-
提取器选择:根据数据特点选择合适的提取器组合,简单关系用SimpleLLM,复杂模式用SchemaLLM
-
检索器组合:结合关键词检索和向量检索通常能获得更好的效果
-
存储选择:开发环境可用Simple存储,生产环境推荐Neo4j等专业图数据库
-
性能优化:对于大规模数据,合理设置num_workers和batch_size参数
-
安全考虑:使用Cypher查询时要注意注入风险,推荐使用模板方式
通过合理利用LlamaIndex的属性图索引功能,开发者可以构建强大的知识感知应用,实现复杂的关系推理和语义检索。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考