news 2026/9/12 20:26:46

LlamaIndex 索引(Indexing)模块深入指南:从 Document 到可检索数据结构的完整解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LlamaIndex 索引(Indexing)模块深入指南:从 Document 到可检索数据结构的完整解析

LlamaIndex 索引(Indexing)模块深入指南:从 Document 到可检索数据结构的完整解析

【免费下载链接】llama_indexLlamaIndex is the document processing platform for AI项目地址: https://gitcode.com/GitHub_Trending/ll/llama_index

LlamaIndex 将Index(索引)定义为一种允许我们快速检索用户查询所需上下文的数据结构,它是检索增强生成(RAG)用例的核心基础。本文以官方 Indexing 模块指南为主线,结合llama-index-core源码实现,系统讲解 Index 的概念与架构、各类索引(Vector Store Index、Summary Index、Tree Index、Keyword Table Index、Property Graph Index)的构建与查询原理,以及索引的增删改刷新、持久化加载和 Query/Chat Engine 装配,帮助你根据真实业务场景做出正确的索引选型与工程落地。

Index 是什么:RAG 检索的核心数据结构

根据官方文档的定义,Index是一种允许我们快速检索用户查询所需上下文的数据结构,对于 LlamaIndex 而言,它是检索增强生成(RAG)用例的核心基础

在高层次上,索引由 Documents 构建,并被用来搭建 Query Engines 和 Chat Engines,从而实现对数据内容的问答与聊天。

在底层,Index 将数据存储在Node对象中(Node 代表原始文档切分后的文本块),并对外暴露一个支持额外配置与自动化的 Retriever 接口。从源码结构看,llama_index.core.indices.base中的BaseIndex是所有索引类型的抽象基类,它通过模板方法模式统一了"从文档构建索引""插入/删除/更新/刷新节点""转换为 Retriever/Query Engine/Chat Engine"等全套生命周期操作(base.py)。

关键概念链条:Document → Node → Index → Retriever

这一条数据流是理解整个 Indexing 模块的钥匙:

  1. Document:原始数据载体(如SimpleDirectoryReader加载的文件)。
  2. Node:Document 经解析/切分(chunking)后得到的文本块,携带元数据(metadata)与节点间关系。
  3. Index:对 Nodes 进行组织的数据结构(列表、向量表、树、关键词表、属性图等)。
  4. Retriever:Index 暴露的检索接口,负责在查询时取回最相关的 Node 集合。

构建索引的两种入口:from_documents与构造函数

BaseIndex.from_documents是文档驱动的标准入口。从源码看,它内部会先将每个文档的哈希写入 docstore(用于后续的 refresh 增量更新判断),再调用run_transformations把 Documents 通过变换管线(默认是文本切分)转换为 Nodes,最后调用索引构造函数完成构建(base.py):

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader documents = SimpleDirectoryReader( "../../examples/data/paul_graham" ).load_data() index = VectorStoreIndex.from_documents(documents)

需要特别注意的是,构造函数本身只接受Node 对象列表。源码中有显式校验:如果传入的是Document列表,会直接抛出ValueError,提示"构造函数现在接收 Node 列表,若要传入 Document 请使用from_documents"(base.py)。因此两种入口的适用场景是:

入口输入适用场景
Index.from_documents(documents)原始文档列表快速起步,默认切分逻辑
Index(nodes)手动构造的 Node 列表需要完全控制切分、元数据与节点关系

索引类型全景:内置 10 种索引

llama-index-core中的索引注册表INDEX_STRUCT_TYPE_TO_INDEX_CLASS定义了全部内置索引类型(registry.py):

索引类型索引结构特点
VectorStoreIndex向量存储索引为每个 Node 生成 embedding 并存入向量库,按相似度检索
SummaryIndex(原 List Index)顺序链式列表将 Nodes 存为顺序链
TreeIndex层次化树从 Nodes 构建层级树(叶子节点),自根向下遍历
KeywordTableIndex关键词表提取关键词并建立关键词到 Nodes 的映射
PropertyGraphIndex属性图(LPG)构建带标签节点与关系的知识图谱
KnowledgeGraphIndex知识图谱基于三元组的知识图谱索引
SQLStructStoreIndexSQL 结构化索引面向结构化 SQL 查询
PandasIndexPandas 数据框索引面向表格数据分析
DocumentSummaryIndex文档摘要索引为每个文档建立摘要并检索
MultiModalVectorStoreIndex多模态向量索引同时支持文本与图像节点
EmptyIndex空索引无存储结构的占位索引

其中,VectorStoreIndex是目前使用最广泛的索引,官方文档也明确推荐从 VectorStoreIndex 使用指南 开始学习。更多索引类型的完整清单可参见 modules.md。

VectorStoreIndex 深度实践:最常用的 RAG 索引

向量存储是 RAG 的关键组件,因此你在几乎每个 LlamaIndex 应用中都会直接或间接用到它。向量存储接收一组Node对象并基于它们构建索引。下面按官方指南的脉络,从数据加载、自定义构建到存储与组合检索逐步展开。

方式一:from_documents快速构建

最简单的用法是加载文档集合并通过from_documents构建索引(vector_store_index.mdx):

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader documents = SimpleDirectoryReader( "../../examples/data/paul_graham" ).load_data() index = VectorStoreIndex.from_documents(documents)

使用from_documents时,你的 Documents 会被切分并解析为Node对象——它们是文本字符串上的轻量抽象,同时跟踪元数据与节点间关系。

两个实用提示:

  • 在命令行中构建索引时,可传入show_progress=True显示进度条。
  • 默认情况下,VectorStoreIndex会以2048 个节点为一批批量生成并插入向量。如果内存受限(或内存充裕),可以通过insert_batch_size参数调整批大小,这在向远端托管的向量数据库插入时尤其有用(vector_store/base.py)。

从源码看,批量插入逻辑位于_add_nodes_to_index:先用embed_nodes分批计算 embedding,再调用vector_store.add()写入;若向量库本身不存储文本(stores_text=False),还会将去 embedding 后的 Node 同步进 docstore 与 index_struct,保证后续能按ref_doc_id追溯原始文档(vector_store/base.py)。

方式二:使用 Ingestion Pipeline 精细控制

如果想对文档如何被索引拥有更多控制权,官方推荐使用 ingestion pipeline,它允许自定义切分(chunking)、元数据与 embedding(vector_store_index.mdx):

from llama_index.core import Document from llama_index.embeddings.openai import OpenAIEmbedding from llama_index.core.node_parser import SentenceSplitter from llama_index.core.extractors import TitleExtractor from llama_index.core.ingestion import IngestionPipeline, IngestionCache pipeline = IngestionPipeline( transformations=[ SentenceSplitter(chunk_size=25, chunk_overlap=0), TitleExtractor(), OpenAIEmbedding(), ] ) nodes = pipeline.run(documents=[Document.example()])

这里的SentenceSplitter(chunk_size=25, chunk_overlap=0)定义了文本切分粒度与重叠窗口,TitleExtractor负责抽取标题元数据,OpenAIEmbedding负责向量化——管线产出的nodes可直接喂给索引构造函数。

方式三:手动创建与管理 Node

如果你希望完全掌控索引,可以手动创建TextNode并直接传给索引构造函数(vector_store_index.mdx):

from llama_index.core.schema import TextNode node1 = TextNode(text="<text_chunk>", id_="<node_id>") node2 = TextNode(text="<text_chunk>", id_="<node_id>") nodes = [node1, node2] index = VectorStoreIndex(nodes)

当数据源随时间变化时,Index类还提供插入(insertion)、删除(deletion)、更新(update)、刷新(refresh)四类操作,详见后文"文档管理"章节及 document_management.md、metadata_extraction.md。

存储:从内存到持久化向量库

默认情况下VectorStoreIndex将一切保存在内存中。LlamaIndex 支持数十种向量存储,通过传入StorageContext并指定vector_store参数即可切换到持久化后端(vector_store_index.mdx):

import pinecone from llama_index.core import ( VectorStoreIndex, SimpleDirectoryReader, StorageContext, ) from llama_index.vector_stores.pinecone import PineconeVectorStore pinecone.init(api_key="<api_key>", environment="<environment>") pinecone.create_index( "quickstart", dimension=1536, metric="euclidean", pod_type="p1" ) storage_context = StorageContext.from_defaults( vector_store=PineconeVectorStore(pinecone.Index("quickstart")) ) documents = SimpleDirectoryReader( "../../examples/data/paul_graham" ).load_data() index = VectorStoreIndex.from_documents( documents, storage_context=storage_context )

对应的向量库实现均位于llama-index-integrations/vector_stores/目录下(如llama-index-vector-stores-pinecone),各集成包的用法示例可参考 vector_store_guide.ipynb。

组合式检索(Composable Retrieval)

VectorStoreIndex(以及任何索引/检索器)都具备检索通用对象的能力,包括:

  • 节点引用(references to nodes)
  • 查询引擎(query engines)
  • 检索器(retrievers)
  • 查询管线(query pipelines)

当这些对象被检索到时,它们会自动使用提供的查询语句执行(vector_store_index.mdx):

from llama_index.core.schema import IndexNode query_engine = other_index.as_query_engine obj = IndexNode( text="A query engine describing X, Y, and Z.", obj=query_engine, index_id="my_query_engine", ) index = VectorStoreIndex(nodes=nodes, objects=[obj]) retriever = index.as_retriever(verbose=True)

如果包含该查询引擎的 IndexNode 被检索命中,查询引擎会被自动执行,其结果作为节点返回。源码中BaseIndex通过_object_map维护index_id → 对象的映射,并在序列化前将obj置空以避免序列化问题(base.py)。

各类索引的工作原理与查询流程

index_guide.md系统讲解了各索引类型的构建与查询机制(index_guide.md)。核心术语:Node对应 Document 中的文本块;Response Synthesis负责根据检索到的 Node 合成回答。

Vector Store Index

向量存储索引将每个 Node 及其对应的 embedding 存储在向量存储中,其构建流程如下图所示:

查询时,它会获取最相似的 top-k 个 Node,并将其传入 Response Synthesis 模块合成答案:

Summary Index(原 List Index)

摘要索引将 Nodes 存储为顺序链,这是最简单的索引结构:

查询时,如果未指定其他查询参数,LlamaIndex 会把列表中的所有 Nodes 全部加载进 Response Synthesis 模块。它同时支持多种查询方式:基于 embedding 的查询(取回 top-k 近邻)、叠加关键词过滤器、或基于 LLM 的查询——对应源码中SummaryIndex.as_retriever的三种模式ListRetrieverMode.DEFAULT / EMBEDDING / LLM(list/base.py)。

Tree Index

树索引从一组 Nodes 构建层次树(这些 Nodes 成为树的叶子节点):

查询树索引时,从根节点向下遍历到叶子节点。默认情况下(child_branch_factor=1),查询在给定父节点时只选择一个子节点;若child_branch_factor=2,则每层选择两个子节点。对应的检索器实现位于llama-index-core/llama_index/core/indices/tree/目录(含select_leaf_retriever.pytree_root_retriever.pyall_leaf_retriever.py等)。

Keyword Table Index

关键词表索引从每个 Node 中提取关键词,并建立"关键词 → 对应 Nodes"的映射:

查询时,从查询语句中提取相关关键词,与预提取的 Node 关键词匹配,取回对应 Nodes 后交给 Response Synthesis 模块。其实现位于llama-index-core/llama_index/core/indices/keyword_table/,支持简单关键词提取(simple_base.py)与 RAKE 算法(rake_base.py)两种底层提取策略。

Property Graph Index

属性图索引通过首先构建包含带标签节点与关系的知识图谱来工作,其构建过程高度可定制:从让 LLM 自由抽取,到按严格 schema 抽取,甚至实现你自己的抽取模块。可选项包括:为节点生成 embedding 以便后续向量检索;也可以跳过图构建,直接通过 Neo4j 等集成连接已有知识图谱。

查询属性图索引同样高度灵活:检索通过多个子检索器组合结果实现。默认使用关键词 + 同义词扩展,以及在图谱已嵌入时的向量检索来取回相关三元组;还可以选择在检索结果中包含源文本(对于在 LlamaIndex 之外创建的图谱则不可用)。完整的子检索器与变换器实现参见 llama-index-core/llama_index/core/indices/property_graph/,深入指南见 lpg_index_guide.md。

文档管理:索引的插入、删除、更新与刷新

大多数 LlamaIndex 索引结构都支持insertion、deletion、update、refresh四类操作(document_management.md)。这些操作在BaseIndex中均有同步与异步(a前缀)两套实现(base.py)。

插入(Insertion)

构建索引后,可以随时将新 Document 插入任意索引结构,该文档会被切分为 Nodes 并摄入索引。底层机制取决于索引类型:对 Summary Index,新 Document 作为额外节点追加进列表;对 Vector Store Index,新 Document(及其 embeddings)被插入底层文档/向量存储:

from llama_index.core import SummaryIndex, Document index = SummaryIndex([]) text_chunks = ["text_chunk_1", "text_chunk_2", "text_chunk_3"] doc_chunks = [] for i, text in enumerate(text_chunks): doc = Document(text=text, id_=f"doc_id_{i}") doc_chunks.append(doc) for doc_chunk in doc_chunks: index.insert(doc_chunk)

从源码看,insert(document)会先对文档执行变换管线生成 Nodes,然后调用insert_nodes写入 docstore 与索引结构,并记录文档哈希(base.py)。

删除(Deletion)

通过指定document_id即可从大多数索引结构中删除 Document(注意:Tree Index 当前不支持删除),该文档对应的所有节点都会被删除:

index.delete_ref_doc("doc_id_0", delete_from_docstore=True)

delete_from_docstore默认为False——当你使用同一个 docstore 在多个索引间共享节点时,节点会被从索引的index_struct中移除(index_struct记录了可用于查询的节点),从而在查询时不再使用;True则会进一步清理 docstore。从源码看,delete_ref_doc通过 docstore 中的RefDocInfo找到该文档的所有node_ids,再逐个删除(base.py)。

更新(Update)

如果某个 Document 已存在于索引中,可以通过相同id_更新它(例如文档内容发生变化时):

doc_chunks[0].text = "Brand new document text" index.update_ref_doc(doc_chunks[0])

源码实现update_ref_doc本质上等价于"先删除、再插入":先以delete_from_docstore=True删除旧文档及其节点,再重新插入新文档(base.py)。

刷新(Refresh)

如果加载数据时为每个文档设置了id_,可以自动刷新索引。refresh()只会更新相同id_但文本内容不同的文档;完全不在索引中的文档也会被插入。它返回一个布尔列表,指示输入文档中哪些已被刷新:

doc_chunks[0] = Document(text="Super new document text", id_="doc_id_0") doc_chunks.append( Document( text="This isn't in the index yet, but it will be soon!", id_="doc_id_3", ) ) refreshed_docs = index.refresh_ref_docs(doc_chunks) # refreshed_docs[0] 和 refreshed_docs[-1] 应为 True print(refreshed_docs) # > [True, False, False, True]

这一功能最适合"目录不断更新新信息"的场景。其原理是利用from_documents时写入 docstore 的文档哈希:refresh_ref_docs逐个比较existing_doc_hashdocument.hash——哈希不存在则插入、哈希不一致则更新(base.py)。若使用SimpleDirectoryReader,可设置filename_as_id标志自动为文档设置id_

文档追踪(Document Tracking)

任何使用 docstore 的索引(即除大多数向量存储集成之外的所有索引)都可以查看已摄入的文档:

print(index.ref_doc_info) # > {'doc_id_1': RefDocInfo(node_ids=['071a66a8-3c47-49ad-84fa-7010c6277479'], metadata={}), # 'doc_id_2': RefDocInfo(node_ids=['9563e84b-f934-41c3-acfd-22e88492c869'], metadata={}), # 'doc_id_0': RefDocInfo(node_ids=['b53e6c2f-16f7-4024-af4c-42890e945f36'], metadata={}), # 'doc_id_3': RefDocInfo(node_ids=['6bedb29f-15db-4c7c-9885-7490e10aa33f'], metadata={})}

输出以摄入文档的id_为键,值为其切分后对应的node_ids列表,同时保留每个输入文档的原始metadata字典。

索引的持久化与重新加载

索引构建后可通过StorageContext持久化,并通过load_index_from_storage重新加载。源码实现从 index store 读取IndexStruct,依据其类型从注册表反查出对应索引类并重建实例(loading.py):

from llama_index.core import StorageContext, load_index_from_storage storage_context = StorageContext.from_defaults(persist_dir="./storage") index = load_index_from_storage(storage_context)

若 index store 中存在多个索引,需显式传入index_id,否则会因无法确定加载目标而抛出ValueError

从索引到 Retriever、Query Engine 与 Chat Engine

索引的最终目的是支撑检索与生成。BaseIndex提供三个标准转换入口(base.py):

  • as_retriever(**kwargs):返回BaseRetriever。以VectorStoreIndex为例,它返回VectorIndexRetriever,并注入索引结构中的全部节点 ID 与对象映射(vector_store/base.py)。
  • as_query_engine(llm=None, **kwargs):内部先调用as_retriever获取检索器,再包装为RetrieverQueryEngine,将检索与响应合成串联起来,实现"基于你的数据问答"。
  • as_chat_engine(chat_mode=..., **kwargs):在查询引擎基础上包装多轮对话能力。支持ChatMode.BEST(默认,使用带查询引擎工具的 Agent)、CONTEXT(检索上下文)、CONDENSE_QUESTION(问题压缩)、CONDENSE_PLUS_CONTEXTSIMPLE等模式。

小结:如何选择合适的索引

官方文档给出了明确的选型指引(modules.md):

  • 通用 RAG 场景:首选VectorStoreIndex,语义相似度检索 + 向量数据库持久化,生态支持最完善。
  • 文档级摘要检索SummaryIndex适合需要遍历/汇总全部内容的场景,或DocumentSummaryIndex做文档粒度摘要。
  • 层级化推理TreeIndex适合需要自顶向下逐层筛选的查询。
  • 关键词精确匹配KeywordTableIndex适合关键词驱动、对语义向量不敏感的场景。
  • 实体与关系推理PropertyGraphIndex/KnowledgeGraphIndex适合知识图谱类应用,支持 LLM 抽取、严格 schema 或自定义抽取模块,并能对接 Neo4j 等已有图谱。
  • 结构化数据SQLStructStoreIndexPandasIndex面向数据库与表格分析。

完整的模块索引与示例入口可参考 modules.md,各索引的构建与查询图示汇总于 index_guide.md,而所有索引类型的统一生命周期实现可深入阅读 llama-index-core/llama_index/core/indices/ 下的源码。

【免费下载链接】llama_indexLlamaIndex is the document processing platform for AI项目地址: https://gitcode.com/GitHub_Trending/ll/llama_index

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 20:21:33

嵌入式C++安全编码实践与MISRA标准解析

1. 嵌入式C安全编码的必要性在嵌入式系统开发中&#xff0c;C因其高效性和灵活性而广受欢迎&#xff0c;但同时也带来了诸多安全隐患。我曾参与过一个工业控制项目&#xff0c;团队使用C开发嵌入式控制器时&#xff0c;因为一个简单的缓冲区溢出漏洞导致整个产线停机8小时&…

作者头像 李华
网站建设 2026/9/12 20:21:10

EMI、敏感性、抗扰度:EMC工程师的三把物理标尺

1. 这不是教科书里的概念堆砌&#xff0c;而是产线工程师每天要掰扯清楚的三把尺子“电磁干扰”“敏感性”“抗扰度”——这三个词在EMC标准文档里加粗加黑、反复出现&#xff0c;但如果你刚从实验室转到产品试产现场&#xff0c;第一次听到产线组长拍着测试报告吼&#xff1a;…

作者头像 李华
网站建设 2026/9/12 20:20:57

# 铜价新高,谁在定价?

CSDN版 &#xff5c; 发布日期&#xff1a;2026-09-11 &#xff5c; 母稿直发合规微调 &#xff5c; 标题宽度&#xff1a;10 ≤20 ✅摘要&#xff1a;9月8日&#xff0c;LME铜盘中触及14779美元/吨&#xff0c;连续刷新历史纪录&#xff1b;同一天&#xff0c;中国海关公布前8…

作者头像 李华
网站建设 2026/9/12 20:19:08

遥控器APP自动重连方案:状态机、退避算法与实战排查

晚上十一点半&#xff0c;空调遥控器APP连不上设备&#xff0c;我蹲在床头对着手机屏幕干瞪眼——这种场景你经历过吗&#xff1f;不只是空调&#xff0c;无人机遥控器、智能灯、玩具车、电视盒子&#xff0c;凡是走APP控制的硬件&#xff0c;几乎都绕不开"断连"这道…

作者头像 李华
网站建设 2026/9/12 20:13:27

数据中心冷却液验收:二次侧必测的 5 个关键参数与测试要点

引言GB/T 48023-2026《数据中心冷板式液冷系统技术规范》已于 2026 年 7 月 30 日发布、2027 年 2 月 1 日实施。该标准规定&#xff0c;二次侧冷却液需检测冰点、pH、菌落总数、硫酸根、氯离子、硬度、电导率、浊度及金属离子等指标&#xff0c;并给出对应测试方法。本文从工程…

作者头像 李华
网站建设 2026/9/12 20:13:23

【AI大模型进阶】Faker 库生成模拟数据,测试你的AI鲁棒性

【AI大模型进阶】Faker 库生成模拟数据,测试你的AI鲁棒性 这是【AI大模型进阶】系列第一百二十八课,在前序课程中,我们已经完成大模型API接入、性格人设定制、智能模型路由、企业级工程封装等核心能力搭建,实现了AI服务从Demo演示到商用落地的基础转型。但绝大多数开发者的…

作者头像 李华