68.高级RAG-父子索引优化

发布时间:2026/7/29 4:21:44
68.高级RAG-父子索引优化 内容参考于图灵AI大模型全栈索引优化在高级RAG中很重要它是在数据摄取阶段和索引构建阶段提升索引数据的结构、检索效率、质量让检索到的结果更加准确、更加相关索引优化核心目标是提高检索的准确性和召回率减少无关数据降低幻觉可以更加好的处理长文档、复杂结构文档文档地址:https://developers.llamaindex.ai/python/framework-api-reference/indices/父子索引在LLamaindex中是一种层级化Hierarchical的索引策略用来解决大文档检索时丢失上下文的问题思路是子节点Child它的文本会很小块一般256到512个tokens用来相似度高的内容如果文档过长会丢失语义父节点Parent它的文本会更大一般1024到2048个tokens或整个文档用来提供完整详细的上下文在检索时它会先通过子节点检索找到子节点后关联出它的父节点来实现高相似度并不会缺失上下文安装指令pip install llama-index-vector-stores-chroma效果图文档信息存储的结构如下图ref_doc_info是当前数据来源于什么文档如下图data里就是父子文档的数据如下图元数据注意元数据的内容在data中如下图红框下图红框的1表示来自于哪一个文档2表示上一个节点3是下一个节点5是子节点的数据5里面的内容它还有个44表示父节点它的结构图代码运行效果Merging 3 nodes into parent node.意思是合并了3个节点Parent node id: aaa5e141-8397-40a7-87ac-17254eb6ec5c.意思是父节点id是aaa5e141-8397-40a7-87ac-17254eb6ec5cParent node text:是父节点的文本代码# 引入LlamaIndex核心组件 # VectorStoreIndex向量索引核心类用于构建、查询向量知识库 # SimpleDirectoryReader目录读取器自动加载文件夹内各类文档(txt/pdf/md等) # StorageContext存储上下文统一管理向量库、文档存储、元数据存储 # load_index_from_storage从本地磁盘加载已持久化保存的索引避免重复向量化 from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, StorageContext, load_index_from_storage # 数据摄入流水线摄取管道封装文档加载→切分→向量化全流程便于复用配置 from llama_index.core.ingestion import IngestionPipeline # 分层节点解析器AutoMerging Retrieval 核心 # HierarchicalNodeParser分层切割文档生成粗粒度父节点 细粒度子叶子节点 # get_leaf_nodes筛选出所有底层细粒度子节点仅将叶子节点存入向量库 from llama_index.core.node_parser import HierarchicalNodeParser, get_leaf_nodes # SimpleDocumentStore本地文档存储用来保存完整分层节点父子节点全部留存 from llama_index.core.storage.docstore import SimpleDocumentStore # AutoMergingRetriever自动合并检索器 # 检索到细碎子节点后自动向上合并父节点上下文解决切片丢失上下文问题 from llama_index.core.retrievers import AutoMergingRetriever # RetrieverQueryEngine检索增强查询引擎把检索器接入大模型实现问答 from llama_index.core.query_engine import RetrieverQueryEngine # Chroma向量存储实现负责存放embedding向量 from llama_index.vector_stores.chroma import ChromaVectorStore # chromadbChroma数据库原生客户端用于创建/获取持久化集合 import chromadb # os模块操作系统接口用来判断文件夹是否存在、路径管理 import os from base_llm import embed_model, llm # 创建Chroma 向量数据库 chroma_client chromadb.PersistentClient( path./chroma_db ) # 数据的名字叫 parent_child_demo chroma_collection chroma_client.get_or_create_collection( parent_child_demo ) # 创建向量数据库存储对象用来操作数据库的 vector_store ChromaVectorStore( chroma_collectionchroma_collection ) # 判断索引是否存在 if os.path.exists(./storage): print(开始加载索引...) # 注意 # 不要自己重新 docstore # 要从 persist_dir 自动恢复 storage_context StorageContext.from_defaults( persist_dir./storage, vector_storevector_store, ) # 加载索引 index load_index_from_storage( storage_contextstorage_context, embed_modelembed_model, ) print(索引加载成功) else: print(开始构建索引...) # 加载文档 documents SimpleDirectoryReader( input_files[./data_file/小说.txt] ).load_data() # 层级切分2048位置标识父节点的大小512的位置表示子节点的大小2048是512的父节点128表示子节点的大小512是128的父节点 node_parser HierarchicalNodeParser.from_defaults( chunk_sizes[2048, 512, 128] ) # 初始化摄取管道 # 这里只做切分 # 不提前做 embedding pipeline IngestionPipeline( transformations[ node_parser, ] ) # 生成所有 nodes nodes pipeline.run( documentsdocuments ) # 获取最子节点 # 只有 leaf nodes 参与向量化 leaf_nodes get_leaf_nodes(nodes) # 创建 docstore # 保存所有层级节点 docstore SimpleDocumentStore() # 父子节点添加到文档存储中 docstore.add_documents(nodes) # 存储管理器用来操作存储的 storage_context StorageContext.from_defaults( vector_storevector_store, docstoredocstore, ) # 创建索引 # 这里只会给 leaf_nodes 生成 embedding index VectorStoreIndex( leaf_nodes, storage_contextstorage_context, embed_modelembed_model, ) # 持久化 # 会保存 # - docstore所有父子节点 # - index_store索引 # - vector_store向量 index.storage_context.persist( persist_dir./storage ) print(索引构建完成) # 基础检索器 # 先召回子节点 base_retriever index.as_retriever( similarity_top_k5 ) # AutoMergingRetriever合并器 # 自动向上合并通过子节点找父节点 # 如果检索出来的子节点超过0.5百分之50来自于同一个父节点那就返回父节点 # 如果小于百分之50就不返回父节点还是使用子节点 retriever AutoMergingRetriever( # 基础检索器 vector_retrieverbase_retriever, # 完整的内容带父节点的内容 storage_contextindex.storage_context, # 是否展示细节 verboseTrue, # 设置阈值也就是百分之50 simple_ratio_thresh0.5 ) # QueryEngine查询引擎 query_engine RetrieverQueryEngine.from_args( # 查询的数据源 retrieverretriever, # 大语言模型 llmllm, ) # 问题 query 萧炎父亲是谁 # 回答问题 response query_engine.query(query) print(\n 回答 \n) print(response) # 查看检索文档这里是返回合并之后的文档就是说会包含父文档 nodes retriever.retrieve(query) print(\n 检索出的文档注意这里是合并之后的文档 \n) for node in nodes: print(node.model_dump_json(indent2)) print()

相关新闻