ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

LlamaIndex 属性图索引 API 深度解析:PropertyGraphIndex、PGRetriever 与五类子检索器的实现机制

LlamaIndex 属性图索引 API 深度解析:PropertyGraphIndex、PGRetriever 与五类子检索器的实现机制 LlamaIndex 属性图索引 API 深度解析PropertyGraphIndex、PGRetriever 与五类子检索器的实现机制【免费下载链接】llama_indexLlamaIndex is the leading document agent and OCR platform项目地址: https://gitcode.com/GitHub_Trending/ll/llama_index本文围绕 LlamaIndex API 参考页 property_graph 索引文档 所列的模块成员PropertyGraphIndex、PGRetriever、BasePGRetriever、CustomPGRetriever、CypherTemplateRetriever、LLMSynonymRetriever、TextToCypherRetriever、VectorContextRetriever、ImplicitPathExtractor、SchemaLLMPathExtractor、SimpleLLMPathExtractor展开逐一剖析这些 API 在 llama-index-core 源码 中的真实行为、默认参数与调用链帮助读者理解属性图Property Graph索引从三元组抽取、图存储写入到多路混合检索的完整数据流并能据此正确配置自己的 GraphRAG 管道。1. 模块总览API 页面对应的代码骨架该 API 参考页由 mkdocs 的::: llama_index.core.indices指令生成其 members 列表精确对应 模块导出文件 中的__all__。从源码结构看整个模块组织为三层层级文件职责索引base.pyPropertyGraphIndex构建、写入、生成检索器检索retriever.py 与 sub_retrievers/PGRetriever编排器 5 个内置/可自定义的子检索器抽取transformations/三类源码中实际还有第四类路径/三元组抽取器需要说明的是API 页面仅列出三个 PathExtractorImplicit、SchemaLLM、SimpleLLM而从源码结构看模块的__init__.py还额外导出了DynamicLLMPathExtractor见 dynamic_llm.py 的导入它同样可用作kg_extractors参数。2. PropertyGraphIndex构建参数与写入流程2.1 构造参数PropertyGraphIndex继承自BaseIndex[IndexLPG]其构造函数定义在 base.py#L80-L143完整参数及默认值如下参数类型默认值说明nodesOptional[Sequence[BaseNode]]None初始写入的节点列表llmOptional[LLM]Settings.llm用于三元组抽取的模型kg_extractorsOptional[List[TransformComponent]][SimpleLLMPathExtractor, ImplicitPathExtractor]三元组抽取器列表见第 6 节property_graph_storeOptional[PropertyGraphStore]SimplePropertyGraphStore属性图存储不提供时懒加载一个内存实现base.py#L104-L107vector_storeOptional[BasePydanticVectorStore]None图存储不支持向量查询时的外挂向量库use_asyncboolTrue抽取/嵌入是否走异步路径embed_modelOptional[EmbedType]Settings.embed_modelKG 节点嵌入模型embed_kg_nodesboolTrue是否对 KG 节点做向量嵌入transformationsOptional[List[TransformComponent]]None在kg_extractors之前执行的通用转换storage_contextOptional[StorageContext]自动创建统一存储上下文show_progressboolFalse进度条开关其中有两个关键推断点源码给出了明确答案向量库的选择逻辑当vector_store被显式提供或图存储supports_vector_queries为False时_override_vector_store置真base.py#L131-L134此时 KG 节点会同时写入独立向量库反之则依赖图存储自身的vector_query能力。默认抽取器组合不传kg_extractors时默认为[SimpleLLMPathExtractor(llm...), ImplicitPathExtractor()]base.py#L124-L127即LLM 自由抽取 结构化隐式关系双管齐下。2.2 写入流程_insert_nodes内部机制_insert_nodesbase.py#L195-L308是理解整个索引的核心其执行顺序为跑抽取管线按use_async选择arun_transformations/run_transformations依次执行kg_extractors随后断言每个节点的 metadata 中必须存在KG_NODES_KEY或KG_RELATIONS_KEY否则写入失败——这是强制约束抽取器必须产出结构化结果。回溯源节点从 metadata 中pop出LabelledNode/Relation列表并给每个 KG 节点与关系的properties写入TRIPLET_SOURCE_KEY node.id_从而建立图数据 → 原文 chunk的反向索引。两级去重KG 节点按id与图存储中已有节点比对upsert 语义只插入新节点LlamaIndex 原文节点按hash去重。双向嵌入embed_kg_nodesTrue时同时嵌入原文节点MetadataMode.EMBED模式文本与 KG 节点str(kg_node)二者批量调用aget_text_embedding_batch。向量旁路写入若_override_vector_store为真KG 节点被转换为TextNodemetadata 带VECTOR_SOURCE_KEY与原始 properties写入向量库base.py#L310-L330。upsert 顺序有讲究先upsert_llama_nodes→ 再upsert_nodes→最后upsert_relations源码注释important: upsert relations after nodes保证关系引用的两端节点已存在若图存储支持结构化查询则调用get_schema(refreshTrue)刷新模式缓存。此外两个 API 行为值得注意from_existing(property_graph_store, ...)类方法base.py#L145-L179用于挂载已有图库如 Neo4j、FalkorDB 等集成包中的PropertyGraphStore实现而零写入。ref_doc_info直接抛出NotImplementedError源码注释解释为 All inserts are already upsertsbase.py#L404-L410即属性图索引不提供文档级删除追踪。2.3 生成检索器as_retriever的默认组合as_retrieverbase.py#L341-L394在未显式指定sub_retrievers时自动组装始终包含LLMSynonymRetriever仅当存在嵌入模型且图存储支持向量查询或提供了外挂vector_store时追加VectorContextRetriever最终封装为PGRetriever(sub_retrievers, use_async...)。3. PGRetriever多子检索器编排与去重PGRetriever 本身不访问图它是一个检索器聚合器参数sub_retrieversList[BasePGRetriever]、num_workers4、use_asyncTrue、show_progressFalse异步路径通过run_jobs并发执行各子检索器的aretrieveworker 数由num_workers控制同步路径则顺序执行汇合后调用_deduplicate按node.text精确去重retriever.py#L41-L49。由于子检索器产出的节点文本通常是三元组字符串或来源 chunk这意味着不同检索路径召回同一事实时只会保留一份这是设计上的合理取舍——跨路径的相似度级去重并不在此层发生。4. BasePGRetriever所有子检索器的公共基座BasePGRetriever 定义了两个抽象方法retrieve_from_graph/aretrieve_from_graph并统一处理三元组 → 可喂给 LLM 的节点的转换构造参数graph_store、include_textTrue、include_text_preamble默认DEFAULT_PREAMBLE Here are some facts extracted from the provided text:\n\nbase.py#L19、include_propertiesFalse_get_nodes_with_score把每个Triplet渲染为TextNode文本为{主语} - {关系} - {宾语}include_propertiesTrue时改用str(node)以携带属性并挂上指向原文 chunk 的NodeRelationship.SOURCE关系默认score1.0add_source_text当include_textTrue时用ref_doc_id反查图存储中的原始 Llama 节点把检索到的三元组 前缀 原文 chunk 内容拼接成新节点内容base.py#L80-L121。这一机制正是写入阶段TRIPLET_SOURCE_KEY的对称消费方实现了图检索与原文上下文的结合是 GraphRAG 回答可溯因的关键。5. 五个内置/可定制子检索器逐一解析5.1 LLMSynonymRetrieverLLM 同义词扩展召回LLMSynonymRetriever 用 LLM 把查询扩展为同义词再按节点名做 ID 精确匹配关键参数max_keywords10、path_depth1、limit30、output_parsing_fn可选自定义解析、synonym_prompt默认DEFAULT_SYNONYM_EXPAND_TEMPLATE要求 LLM 用^分隔单行输出llm_synonym.py#L18-L27解析时每个关键词会strip().capitalize()源码注释说明这是为了与写入阶段的命名归一化对齐命中节点后通过graph_store.get_rel_map(kg_nodes, depthpath_depth, limit..., ignore_rels[KG_SOURCE_REL])展开成三元组KG_SOURCE_REL关系被排除以免把来源边混入事实。5.2 VectorContextRetriever向量相似度驱动的路径召回VectorContextRetriever 是另一路默认检索器参数与取值参数默认作用embed_modelSettings.embed_model查询向量化vector_storeNone图存储不支持向量查询时必填的外挂向量库similarity_top_k4向量召回的 top-k KG 节点数path_depth1每个命中节点向外展开的路径深度1 即一条三元组limit30get_rel_map展开的三元组上限similarity_scoreNone三元组的最低相似度阈值设值后先过滤再排序filtersNoneMetadataFilters透传给向量查询检索流程vector.py#L131-L201查询嵌入 → 优先走graph_store.vector_query否则走外挂vector_store.query→ 按VECTOR_SOURCE_KEY/id 取回LabelledNode→get_rel_map展开三元组 →三元组得分为其两端节点相似度的最大值→ 按分降序返回。源码还通过_filter_vector_store_query_kwargs把额外 kwargs 过滤到VectorStoreQuery的合法字段vector.py#L22、L82-L91避免非法参数透传报错。5.3 TextToCypherRetriever自然语言生成 CypherTextToCypherRetriever 是表达能力最强的结构化检索路径构造函数会先检查graph_store.supports_structured_queries不满足直接抛ValueErrortext_to_cypher.py#L80-L83因此它只适用于 Neo4j 等支持 Cypher 的图存储。参数与默认值text_to_cypher_template缺省时使用graph_store.text_to_cypher_template、response_template默认Generated Cypher query:\n{query}\n\nCypher Response:\n{response}、cypher_validator可调用校验/改写函数、allowed_output_fields结果字典字段白名单经_clean_query_output递归过滤、include_raw_response_as_metadataFalse为真时把{query: ..., response: ...}写入节点 metadata 便于审计、summarize_responseFalse为真时用DEFAULT_SUMMARY_TEMPLATE让 LLM 把原始查询结果改写为自然语言回答text_to_cypher.py#L14-L34。执行链get_schema_str()取模式 → LLM 生成 Cypher →cypher_validator后处理 →structured_query执行 → 字段清洗 → 可选摘要产出单个score1.0的NodeWithScore。源码 docstring 明确警示执行任意生成的 Cypher 存在风险生产环境应采取只读角色、沙箱等防护措施。5.4 CypherTemplateRetriever结构化参数填充 Cypher 模板CypherTemplateRetriever 与上一个形成互补Cypher 语句由开发者预先固定LLM 只负责通过llm.structured_predict(output_cls, ...)把问题映射为一个BaseModeloutput_cls再model_dump()成param_map交给structured_query执行。同样是supports_structured_queries前置检查。相比 TextToCypherRetriever它的查询语句完全可控安全性与结果稳定性更高适合固定问答形态如某实体的邻居某关系的数量统计。5.5 CustomPGRetriever面向扩展的骨架CustomPGRetriever 为自定义检索逻辑提供模板子类只需实现init(**kwargs)与custom_retrieve(query_str)可覆写acustom_retrieve实现原生异步并可直接通过self.graph_store访问底层图库。custom_retrieve的返回值类型被约束在CUSTOM_RETRIEVE_TYPE联合类型内str、List[str]、TextNode、List[TextNode]、NodeWithScore、List[NodeWithScore]custom.py#L8-L10基类负责统一包装成score1.0的节点列表并走标准的include_text来源文本拼接逻辑。6. 三元组抽取器kg_extractors 的三个加一个实现抽取器是PropertyGraphIndex写入阶段的核心它们都是TransformComponent把原文 chunk 转化为挂在KG_NODES_KEY/KG_RELATIONS_KEYmetadata 下的EntityNode/Relation列表。6.1 SimpleLLMPathExtractor无 Schema 的自由抽取SimpleLLMPathExtractor 用默认提示词DEFAULT_KG_TRIPLET_EXTRACT_PROMPT让 LLM 输出形如(主语, 关系, 宾语)的三元组行参数parse_fn默认default_parse_triplets_fn、max_paths_per_chunk10、num_workers4run_jobs并发度、raise_on_errorFalse抽取失败仅记日志、产出空三元组保证管道不断流解析函数 default_parse_triplets_fn 的行为细节值得注意仅接受括号内恰好 3 个逗号分隔 token 的行按 UTF-8字节长度上限 128过滤过长 token去双引号并capitalize()归一化——这与LLMSynonymRetriever检索端的capitalize()正好构成写入/查询两端的命名一致性契约。6.2 ImplicitPathExtractor零成本的结构化关系ImplicitPathExtractor 不调用 LLM它直接读取node.relationships把source、parent、previous、next、child五类节点关系逐一转成Relation边implicit.py#L36-L85。这意味着 chunk 的层级、前后顺序、原文归属天然进入图结构是图导航类问题这一事实出自哪个父文档的数据基础。6.3 SchemaLLMPathExtractor受 Schema 约束的类型化抽取SchemaLLMPathExtractor 把抽取约束到预定义本体上内置默认本体DEFAULT_ENTITIESPRODUCT、MARKET、TECHNOLOGY、EVENT、CONCEPT、ORGANIZATION、PERSON、LOCATION、TIME、MISCELLANEOUS与DEFAULT_RELATIONSUSED_BY、USED_FOR、LOCATED_IN、PART_OF、WORKED_ON、HAS、IS_A、BORN_IN、DIED_IN、HAS_ALIAS以及 27 条合法的(主体类型, 关系, 客体类型)校验元组DEFAULT_VALIDATION_SCHEMAschema_llm.py#L25-L81可定制项possible_entities/possible_relationsLiteral 类型、possible_entity_props/possible_relation_props支持(name, description)元组携带属性说明、strictTrue严格模式下剔除 schema 外属性并校验三元组合法性、kg_validation_schema、max_triplets_per_chunk10、num_workers4、allow_additional_propertiesTrue面向要求严格 JSON Schema 的 LLM 提供方可设为False、raise_on_errorFalse实现机制运行时用 pydanticcreate_model动态生成实体/关系/Triplet 模型LLM 输出经field_validator归一化类型空格替换为下划线并转大写后逐条校验_prune_invalid_triplets还会剔除主体与客体同名忽略大小写的自引用三元组schema_llm.py#L346-L348。与 SimpleLLMPathExtractor 相比它产出的是带label实体类型的EntityNode使图查询与模式推理成为可能代价是抽取范围被本体边界框死。6.4 补充DynamicLLMPathExtractor从 模块导出 可见transformations/目录下还存在DynamicLLMPathExtractordynamic_llm.py虽然不在当前 API 页面的 members 列表中但它遵循同样的TransformComponent契约可直接替换进kg_extractors。7. 实践要点与组合建议结合上述源码事实可以给出几条有据可依的工程指引默认组合的适用边界as_retriever()的默认双路同义词 向量在SimplePropertyGraphStore下同样可用因为后者也实现了vector_query若图存储既不支持向量也不支持结构化查询supports_vector_queriesFalse必须为PropertyGraphIndex或VectorContextRetriever显式传入vector_store。需要 Cypher 能力时TextToCypherRetriever与CypherTemplateRetriever都要求supports_structured_queriesTrue可搭配llama-index-integrations/graph_stores/下的 Neo4j、FalkorDB、Neptune 等集成包使用对固定查询形态优先选CypherTemplateRetriever把 LLM 局限在参数抽取环节。安全性TextToCypher 路径务必叠加cypher_validator与allowed_output_fields做双重收敛并遵循源码 docstring 的只读/沙箱建议。命名一致性写入侧default_parse_triplets_fn与检索侧LLMSynonymRetriever都依赖capitalize()归一化实体名自定义parse_fn或output_parsing_fn时应保持这一约定否则精确 ID 匹配会静默失效。可验证性核心行为的测试位于 test_property_graph.py官方示例 Notebooks 位于 docs/examples/graph_rag/ 目录图存储抽象PropertyGraphStore、LabelledNode、Relation、TRIPLET_SOURCE_KEY等类型定义在 graph_stores/types.py阅读该文件可以进一步理解vector_query、get_rel_map、structured_query等接口契约。8. 小结这篇 API 参考页背后的模块实质上定义了一条完整的属性图 RAG 管道PropertyGraphIndex通过可插拔的kg_extractorsLLM 自由抽取 / 隐式关系 / Schema 约束抽取把文本变成带溯源键的三元组并 upsert 入图PGRetriever则把同义词扩展、向量近邻、Cypher 生成/模板填充、自定义逻辑等多路检索并发聚合并按文本去重最终借include_text机制把图事实与原文 chunk 缝合在一起交给 LLM 作答。理解上述每一层的默认值与前置条件尤其是supports_vector_queries/supports_structured_queries两个能力开关是正确使用 LlamaIndex 属性图索引的前提。【免费下载链接】llama_indexLlamaIndex is the leading document agent and OCR platform项目地址: https://gitcode.com/GitHub_Trending/ll/llama_index创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进