84.图RAG-llamaindex图谱关系提取器-动态提取器
内容参考于图灵AI大模型全栈图谱关系提取器的选择提取器类型用途实现逻辑是否调用LLM推荐指数SimpleLLMPathExtractor三元组抽取快速构建知识图谱Prompt → LLM → 抽取 Entity-Relation-Entity✅⭐⭐DynamicLLMPathExtractor动态图谱抽取自动发现实体类型和关系类型Prompt → LLM → 实体分类 → 关系推断✅⭐⭐⭐SchemaLLMPathExtractorSchema约束抽取企业级GraphRAGPrompt Schema → LLM → 验证 → 输出✅⭐⭐⭐⭐⭐ImplicitPathExtractor隐式关系抽取保留文档结构关系根据Node Relationship自动生成边❌⭐⭐⭐⭐通过默认的提取器生成的知识图谱内容很怪如下图红框它的分类看起来就很怪如果看不出来继续往下看对比一下就看出来了DynamicLLMPathExtractor动态提取器逻辑首先还是获取文档然后对文档进行分割分割完的数据跟大模型提示词组合提示词的组合逻辑如下图4中请从以下文本中抽取实体及实体之间的关系按照给定的格式返回文本xxx返回结果然后提取所有的实体然后提取关系然后过滤然后写到数据库中它的逻辑和默认提取器差不多但是它多了可配置参数可以限制 entity_tupes实体类型relation_types关系类型等就是可以选择这个节点实体它必须是人物或其它什么东西我们可以对它进行限制默认提取器的提示词源码查看步骤按着CTRL鼠标左键单击下图红框然后再按着CTRL鼠标左键单击下图红框然后再按着CTRL鼠标左键单击下图红框然后就可以看到默认提取器使用的提示词来如下图红框翻译的中文如下图DynamicLLMPathExtractor生成的分类它生成的就很好它和默认提取器的区别就是提示词不一样但是它是英文的默认提示词就会是英文的还有一个提取器会使用它进行完整的图生成DynamicLLMPathExtractor的提示词按着CTRL鼠标左键单击下图红框如下图红框它有两种提示词如下图红框如果有指定实体类型也就是设置了 allowed_entity_props它的值或者设置了关系类型也就是设置了allowed_relation_props它的值就会使用DEFAULT_DYNAMIC_EXTRACT_PROMPT这个提示词大模型就会尽力根据我们指定的类型进行提取比如让大模型必须提取出人物、地点这些数据如果实在不匹配它就按着自己的逻辑进行提取也就是说按着我们指定的逻辑提出不出来内容就按着大模型自己的逻辑进行提取这就是动态提取这种的虽然我们可以干预结果但是还是差点事下一节还有提取器更好用什么参数都不传递它会使用下图红框的提示词按着CTRL鼠标左键单击下图红框然后再按着CTRL鼠标左键单击下图红框下图红框就是它的提示词中文翻译“从给定文本中提取最多{max_knowledge_triplets}个知识三元组。” 每个三元组应该以head、relation、tail的形式存在并具有各自的类型和属性。\n “----------------------\n” “初始本体\n” “实体类型{allowed_Entity_Types}\n” “实体属性{allowed_Entity_Properties}\n” “关系类型{allowed_Relation_Types}\n” “关系属性{allowed_Relation_Properties}\n” “\n” 使用这些类型作为起点但如果需要请根据上下文引入新类型。\n “\n” “指南\n” “-JSON格式的输出[{{headhead_typehead_props{{…}}关系关系_props:{{¡}}、tail、tail_type:tail_props]\n” -对实体使用最完整的形式例如“美利坚合众国”而不是“美国”\n “-保持实体简洁最多3-5个字\n” “-将复杂短语分解为多个三元组\n” “-确保知识图连贯且易于理解\n” “----------------------\n” “示例\n” 文本苹果公司AppleInc.首席执行官蒂姆·库克TimCook宣布推出新的苹果手表用于监测心脏健康 “加州大学伯克利分校的研究人员研究了苹果的好处。\n” “输出\n” “[{{headTim Cookhead_typePERSONhead_props{{prop1val…}}关系CEO_OF关系_props:{{rop1val…}tail苹果公司尾类型公司tail_props:{{prop1val…{}}}}、\n” “{{headApple Inc.head_typeCOMPANYhead_props{{prop1val…}}relation产品关系_props{{prop1val…}尾巴苹果手表尾巴类型PRODUCTtail_props:{{rop1val…{}}}。\n” “{{head苹果手表head_type产品head_props{{prop1val…}}关系监视器relation_props:{{rop1val…}tail心脏健康尾巴类型健康H_METRICtail_props:{prop2val…{}}}}、\n” “{{headUC Berkeleyhead_type大学head_props{{prop1val…}}关系研究relation_props:{{rop1val…}tail苹果的好处tail_type:RESEARCH_TOPICtail_props:{prop1val…{}}}]\n” “----------------------\n” “文本{Text}\n” “输出\n”然后另一个提示词按着CTRL鼠标左键单击下图红框然后再按着CTRL鼠标左键单击下图红框如下图红框它的提示词中文翻译“从给定文本中提取最多{max_knowledge_triplets}个知识三元组。” 每个三元组应该以头、关系、尾的形式存在并具有各自的类型。\n “----------------------\n” “初始本体\n” “实体类型{allowed_Entity_Types}\n” “关系类型{allowed_Relation_Types}\n” “\n” 使用这些类型作为起点但如果需要请根据上下文引入新类型。\n “\n” “指南\n” “-JSON格式的输出[{{headhead_type、关系tail尾类型}]\n” -对实体使用最完整的形式例如“美利坚合众国”而不是“美国”\n “-保持实体简洁最多3-5个字\n” “-将复杂短语分解为多个三元组\n” “-确保知识图连贯且易于理解\n” “----------------------\n” “示例\n” 文本苹果公司AppleInc.首席执行官蒂姆·库克TimCook宣布推出新的苹果手表用于监测心脏健康 “加州大学伯克利分校的研究人员研究了苹果的好处。\n” “输出\n” “[{{headTim Cookhead_typePERSON关系CEO_OFtailApple Inc.尾类型COMPANY}\n” “{{head苹果公司head_type公司关系产品尾巴Apple Watch尾类型商品}}\n” “{{head苹果手表head_type产品关系监视器尾巴心脏健康尾类型健康H_METRIC}\n” “{{头部加州大学伯克利分校头部类型大学关系研究尾巴苹果的好处尾部类型RESEARCH_TOPIC}]\n” “----------------------\n” “文本{Text}\n” “输出\n”代码运行效果图可以看到大模型给我们的CQL语法的查询逻辑它就会根据查询出来的内容进行拼接然后给大模型进行回答问题代码import asyncio from pathlib import Path from llama_index.core import SimpleDirectoryReader, Settings from llama_index.core.node_parser import SentenceSplitter from llama_index.core.indices.property_graph import PropertyGraphIndex, DynamicLLMPathExtractor from llama_index.core.ingestion import IngestionPipeline, IngestionCache from llama_index.core.storage.kvstore import SimpleKVStore from llama_index.graph_stores.neo4j import Neo4jPropertyGraphStore from base_llm import llm, embed_model # 设置全局大模型 Settings.llm llm # 创建Neo4j数据库连接 graph_store Neo4jPropertyGraphStore( usernameneo4j, password11111111, urlbolt://localhost:7687, ) # 读取文档 documents SimpleDirectoryReader( input_files[./data_file/小说.txt] ).load_data() # 缓存地址 path ./cache/cache.json # 获取文件对象 file_path Path(path) # 判断文件是否存在也就是判断缓存是否存在 if file_path.is_file(): print(缓存文件存在) # 创建缓存模式kv缓存 kvstore SimpleKVStore.from_persist_path(path) # 创建缓存 cache IngestionCache( cachekvstore ) else: print(缓存文件不存在) # 创建缓存模式kv缓存 kvstore SimpleKVStore() # 创建缓存 cache IngestionCache( cachekvstore ) # 创建摄取管道 pipeline IngestionPipeline( # 设置文档处理器 transformations[ # 文本分割器 SentenceSplitter(chunk_size512, chunk_overlap50), # 动态提取 DynamicLLMPathExtractor(llmllm) ], # 设置缓存 cachecache # 本地缓存避免重复调用 LLM ) # 使用摄取器生成节点自动处理缓存/增量 nodes pipeline.run(documentsdocuments, show_progressTrue) print(nodes) # 构建 PropertyGraphIndex 并写入 Neo4j也就是创建图索引 index PropertyGraphIndex( nodesnodes, # 设置数据库连接 property_graph_storegraph_store, # 设置大模型 llmllm, # 设置向量模型 embed_modelembed_model ) kvstore.persist(path) print(图谱处理完成含缓存增量机制) # 创建查询引擎 query_engine index.as_query_engine(llmllm) res query_engine.query(萧炎的父亲是谁?) print(回答:, res) # 使用检索器查看上下文节点 retriever index.as_retriever() nodes retriever.retrieve(萧炎的父亲是谁?) for node in nodes: print(*50) print(node.text) print() # 关闭 Neo4j连接 graph_store.close() asyncio.run(graph_store._async_driver.close())