07-LlamaIndex实现RAG:专为RAG而生的框架实战
第 7 篇:LlamaIndex 实现 RAG——专为 RAG 而生的框架实战
本文为「从零到落地:RAG 检索增强生成实战系列」第 7 篇,完整系列持续更新中。
前言
本篇聚焦 LlamaIndex 完整实战,从核心概念到基础 RAG、进阶配置(混合检索 + Rerank)、多轮对话、Agent 工具调用,全部代码逐行讲解。末尾与 LangGraph 做框架选型对比,帮你决定下一个项目该用谁。
在第 6 篇里,你用 LangGraph 的状态机搭建了一个可深度定制的 RAG 流程——条件路由、Query 改写、Agent 融合,灵活度拉满。但你可能也感受到了:写一个基础 RAG 就要定义 State、写节点函数、配置边,代码量不少。 如果你只是想快速搭一个”文档问答”应用,LangGraph 的流程编排有点”杀鸡用牛刀”。
LlamaIndex 就是为这种场景而生的。
LlamaIndex 是一个专门为 RAG 设计的主流框架,API 极其简洁——4 行代码就能跑通一个完整的 RAG 系统。它把文档加载、节点切分、索引构建、查询引擎全部封装好了,同时保留了充分的自定义空间:自定义分块策略、混合检索、Reranker、多轮对话、Agent 工具调用,想深入随时可以深入。
本篇学完你将掌握:
- LlamaIndex 的核心概念:Documents、Nodes、Index、QueryEngine、ChatEngine
- 4 行代码搭建基础 RAG,然后逐层拆解理解原理
- 自定义分块策略:SentenceSplitter、按语义分块
- 混合检索(向量 + BM25)+ Reranker 提升检索精度
- ChatEngine 多轮对话 RAG
- Agent 工具调用 + 结构化数据查询(CSV/SQL)
- LlamaIndex vs LangGraph 框架选型对比
一、LlamaIndex 是什么
1.1 核心定位
LlamaIndex(原名 GPT Index)是一个专注于数据连接和 RAG 的开源框架。它的核心目标是:让你用自己的数据和大模型对话,而不需要关心底层的数据管道细节。
和前面几篇工具的对比:
| 工具 | 定位 | 一句话概括 |
|---|---|---|
| 原生 Python(第 4 篇) | 教学向,理解底层 | 每一步手写,知道框架在封装什么 |
| Dify(第 5 篇) | 低代码平台,快速上线 | 点鼠标搞定,但深度定制受限 |
| LangGraph(第 6 篇) | 状态机编排,深度定制 | 流程自由度最高,但代码量也最多 |
| LlamaIndex(本篇) | RAG 专用框架,开箱即用 | API 最简洁,RAG 场景效率最高 |
1.2 五个核心概念
LlamaIndex 的 RAG 管道由五个核心概念构成:
| 概念 | 说明 | 类比 |
|---|---|---|
| Documents | 原始文档对象,包含文本和元数据 | 一本书 |
| Nodes | 文档切分后的最小单元,是索引和检索的基本单位 | 书里的每一段 |
| Index | 数据索引结构,存储 Nodes 的向量和组织方式 | 书的目录和索引 |
| QueryEngine | 查询引擎,处理”提问 → 检索 → 生成回答”的完整流程 | 帮你翻书找答案的助手 |
| ChatEngine | 在 QueryEngine 基础上加入对话记忆,支持多轮对话 | 能记住上下文的助手 |
1 | Documents(原始文档) |
💡 提示:和 LangGraph 的”状态-节点-边”范式不同,LlamaIndex 是管道式的——数据从文档流入,经过切分、索引、检索,最终输出回答。你只需要配置每个环节的参数,不需要手写流程编排代码。
二、环境准备
2.1 技术栈
| 组件 | 选择 | 理由 |
|---|---|---|
| Python | 3.11 | 系列统一版本 |
| RAG 框架 | LlamaIndex | RAG 专用,API 最简洁 |
| LLM | DeepSeek API | 性价比最高,兼容 OpenAI SDK |
| Embedding 模型 | bge-large-zh-v1.5(本地) | 中文效果最好的开源模型 |
| 向量数据库 | Chroma | 零配置启动,与 LlamaIndex 深度集成 |
2.2 安装依赖
1 | # 创建虚拟环境 |
💡 提示:LlamaIndex 采用模块化设计,核心包
llama-index包含基础功能,LLM 接入、Embedding 模型、向量库等通过独立的集成包安装。这样做的好处是不会安装你用不到的依赖。
2.3 准备测试文档
复用系列统一的测试文档 docs/company_faq.md(内容与第 4 篇相同)。
三、4 行代码搭建基础 RAG
LlamaIndex 最让人惊艳的地方就是:一个完整的 RAG 系统,4 行代码就能跑通。
1 | from llama_index.core import SimpleDirectoryReader, VectorStoreIndex |
运行结果:
1 | 根据公司年假制度: |
4 行核心代码就完成了加载文档 → 切分 → 向量化 → 构建索引 → 检索 → 生成回答的全流程。这就是 LlamaIndex 的效率——它把所有 RAG 管道的环节都封装好了,你只需要关注”问什么”和”怎么答”。
核心价值:这 4 行代码背后,LlamaIndex 自动完成了:①用 SimpleDirectoryReader 读取目录下所有文档;②用默认的 SentenceSplitter 按句子边界切分文本;③用 bge-large-zh-v1.5 生成向量;④构建 VectorStoreIndex(内存模式);⑤用 Top-K 向量检索找到最相关的文本块;⑥拼接 Prompt 调用 DeepSeek 生成回答。
四、核心概念深入理解
4 行代码跑通了,但要调优效果,你需要理解每个环节在做什么。下面逐层拆解。
4.1 Documents:原始文档对象
1 | from llama_index.core import SimpleDirectoryReader |
SimpleDirectoryReader 自动识别文件格式(.txt、.md、.pdf、.docx 等),每个文件生成一个 Document 对象,包含文本内容和元数据(文件名、路径等)。
4.2 Nodes:切分后的最小单元
1 | from llama_index.core.node_parser import SentenceSplitter |
Node 是 LlamaIndex 的核心概念——索引和检索的最小单元。每个 Node 包含:
| 属性 | 说明 |
|---|---|
text |
文本内容 |
embedding |
向量(构建索引时自动生成) |
metadata |
元数据(来源文件、页码等) |
relationships |
与其他 Node 的关系(如父子关系) |
4.3 Index:向量索引
1 | from llama_index.core import VectorStoreIndex, Settings |
VectorStoreIndex 是最常用的索引类型。它把每个 Node 的文本转为向量,存储在内存中(也可持久化到 Chroma 等向量库)。Settings 是 LlamaIndex 的全局配置对象,设置一次后所有组件都会使用默认值。
4.4 QueryEngine:查询引擎
1 | # 创建查询引擎 |
QueryEngine 封装了完整的”检索 → 生成”流程:
1 | 用户问题 → Retriever(检索 Top-K 节点)→ ResponseSynthesizer(拼接 Prompt + 调 LLM)→ 回答 |
| response_mode | 说明 |
|---|---|
compact(默认) |
把检索结果尽量压缩到一个 Prompt 中,效率高 |
tree_summarize |
对多个检索结果逐层总结,适合长文档 |
no_text |
只返回检索结果,不调用 LLM(用于调试检索质量) |
五、进阶配置
基础 RAG 跑通后,通过调整分块策略、检索方式和重排序,可以显著提升效果。
5.1 自定义分块策略
分块质量直接影响检索精度。LlamaIndex 提供多种内置分割器:
| 分割器 | 说明 | 适用场景 |
|---|---|---|
| SentenceSplitter | 按句子边界切分,保持语义完整 | 大多数场景(推荐默认) |
| TokenTextSplitter | 按 Token 数切分,精确控制块大小 | 需要严格控制 Token 数时 |
| SemanticSplitterNodeParser | 按语义相似度切分,自动识别段落边界 | 长文档、主题多变的文档 |
| MarkdownNodeParser | 按 Markdown 标题层级切分 | Markdown 文档 |
| HierarchicalNodeParser | 层级切分,生成父子节点 | 需要父子分段检索时 |
SentenceSplitter(推荐):
1 | from llama_index.core.node_parser import SentenceSplitter |
💡 建议:
chunk_size中文文档建议 300-500 Token。太小(如 100)语义不完整,太大(如 1000)噪声多。从 400 开始试,根据效果调整。
SemanticSplitter(语义分块):
1 | from llama_index.experimental.node_parser import SemanticSplitterNodeParser |
语义分块的优势是能自动识别主题切换的位置,避免把两个不同话题的内容切到同一个块里。
5.2 混合检索(向量 + BM25)
纯向量检索在专有名词、产品型号等精确匹配场景下表现不如关键词检索。LlamaIndex 支持向量 + BM25 的混合检索:
1 | from llama_index.core import VectorStoreIndex |
💡 提示:混合检索是生产环境的标配。向量检索擅长语义理解(”数据库”和”PostgreSQL”能匹配),BM25 擅长精确匹配(”PostgreSQL”只匹配包含这个词的文档),两者互补效果最好。
5.3 Reranker 重排序
Reranker 对初次检索返回的结果做二次精排,用专门的模型重新计算相关性分数,把最相关的排到前面。
1 | # 使用 BGE Reranker(需要先安装) |
Reranker 的工作原理:
1 | 初次检索 Top-10 → Reranker 重新打分 → 保留 Top-3 → 送给 LLM 生成回答 |
核心价值:没有 Reranker 时,向量检索的 Top-1 不一定是最相关的(向量距离只是近似语义匹配)。Reranker 用交叉注意力机制对”问题-文档”对做更精细的相关性判断,显著提升检索精度。实测中,加 Reranker 后回答准确度通常能提升 10-20%。
5.4 持久化索引到 Chroma
默认的 VectorStoreIndex 存在内存里,重启就丢失。接入 Chroma 可以持久化:
1 | import chromadb |
下次启动时,可以直接从 Chroma 加载已有索引,不需要重新处理文档:
1 | # 从已有 Chroma 索引加载 |
六、多轮对话:ChatEngine
QueryEngine 每次提问都是独立的。LlamaIndex 的 ChatEngine 在 QueryEngine 基础上加入了对话记忆,支持连续追问。
6.1 基础多轮对话
1 | # 创建 ChatEngine |
6.2 ChatEngine 的 chat_mode
| chat_mode | 原理 | 适用场景 |
|---|---|---|
| condense_question(推荐) | 把追问 + 历史对话改写为一个独立问题,再去检索 | 大多数 RAG 对话场景 |
| context | 每轮都检索,把结果和历史对话一起送给 LLM | 每轮问题都需要新知识时 |
| condense_plus_context | 改写问题 + 检索 + 完整上下文 | 需要最高回答质量时 |
| simple | 不做检索,纯 LLM 对话(不用知识库) | 闲聊场景 |
condense_question 的工作流程:
1 | 用户追问:"那怎么申请?" |
💡 提示:
condense_question是多轮 RAG 对话的最佳选择——它先用 LLM 把追问改写为独立的完整问题,再去检索,避免了”那””这个”这类代词导致检索不到的问题。
6.3 重置对话
1 | # 清空对话历史,开始新话题 |
七、高阶能力
7.1 Agent + 工具调用
LlamaIndex 支持把 RAG 查询引擎封装为 Agent 工具,让 LLM 自主决定何时查知识库、何时用其他工具。
1 | from llama_index.core.tools import QueryEngineTool, ToolMetadata |
Agent 的推理过程(verbose=True 时可见):
1 | > Thought: 用户问的是公司年假制度,我应该使用 company_knowledge_base 工具来查询 |
7.2 结构化数据查询:CSV
LlamaIndex 不仅能处理文本文档,还能直接查询 CSV 表格数据:
1 | from llama_index.experimental.query_engine import PandasQueryEngine |
💡 提示:PandasQueryEngine 会把自然语言问题转换为 Pandas 代码执行。这对结构化数据分析场景非常有用——比如让 AI 直接回答”上个季度销售额最高的产品是什么”这类问题。
踩坑记录:LlamaIndex 模块导入错误
现象:
1 | from llama_index import VectorStoreIndex |
原因:
LlamaIndex 从 v0.10.0 开始进行了大规模模块化重构,原来的 llama_index 包被拆分为 llama-index-core 和多个集成包。旧的导入路径全部失效。
解决方案:
1 | # 旧写法(v0.10 之前,已失效) |
避坑建议:
安装时注意版本号,确认你看的文档和教程是基于 v0.10+ 的。如果从网上复制代码,先检查导入路径是否是旧版格式。推荐锁定版本:
1 | pip install llama-index>=0.11.0 |
八、LlamaIndex vs LangGraph:怎么选
| 对比维度 | LlamaIndex | LangGraph |
|---|---|---|
| 核心定位 | RAG 专用框架,管道式数据流 | 通用图编排框架,状态机范式 |
| API 风格 | 高度封装,4 行代码跑通 RAG | 需要定义 State/Node/Edge,代码量较多 |
| 上手难度 | ⭐⭐ 较低(管道式,直觉性强) | ⭐⭐⭐ 中等(需理解状态机概念) |
| 基础 RAG 效率 | ⭐⭐⭐⭐⭐ 极高(开箱即用) | ⭐⭐⭐ 中等(需要手写节点函数) |
| 分块策略 | 丰富(5+ 内置分割器,含语义分块) | 需要自己实现或借助 LangChain |
| 混合检索 | 内置支持(向量 + BM25) | 需要自己实现 |
| Reranker | 内置 node_postprocessors | 需要自己集成 |
| 多轮对话 | ChatEngine 开箱即用(多种模式) | MemorySaver + Checkpointer(需配置) |
| 条件路由 | 有限(需借助 Agent 实现) | ⭐⭐⭐⭐⭐ 原生支持,任意复杂 |
| Agent 融合 | 有(ReActAgent),但不如 LangGraph 灵活 | ⭐⭐⭐⭐⭐ 原生支持,深度定制 |
| 流程可视化 | 较弱 | 可打印拓扑图,LangSmith 可视化 |
| 适用人群 | 快速搭建 RAG 应用、不想写太多代码 | 需要精确控制每一步流程的开发者 |
选型建议:
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 快速搭建文档问答系统 | LlamaIndex | 4 行代码跑通,分块/检索/Rerank 开箱即用 |
| 需要自定义分块和检索策略 | LlamaIndex | 内置 5+ 分割器和混合检索 |
| 复杂流程编排(条件路由、循环、自我修正) | LangGraph | 状态机 + 条件边,灵活度无可比拟 |
| RAG + Agent 深度融合 | LangGraph | 原生工具调用和图编排 |
| 多轮对话 RAG | 都行 | LlamaIndex 的 ChatEngine 更简洁,LangGraph 更可控 |
| 快速原型 → 生产级 | LlamaIndex → LangGraph | 先用 LlamaIndex 验证效果,再用 LangGraph 深度定制 |
核心价值:如果你的需求是”用文档做一个问答机器人”,LlamaIndex 是最高效的选择——它把 RAG 的所有环节都封装好了,你只需要调参数。如果你需要”让 RAG 流程具备自我修正、多路并行检索、Agent 工具调用”等高级能力,LangGraph 更合适。两者也可以组合使用——用 LlamaIndex 做文档处理和检索(利用其丰富的分块和检索策略),用 LangGraph 做上层流程编排。
常见问题踩坑汇总
Q:LlamaIndex 默认使用什么 LLM?不配置会怎样?
A:LlamaIndex 默认使用 OpenAI 的 GPT 系列模型。如果你没有配置 LLM 和 Embedding,它会尝试调用 OpenAI API。国内用户必须在 Settings 或创建引擎时显式指定 LLM 和 Embedding 模型,否则会报 API 错误。
Q:检索结果不相关,怎么调优?
A:按优先级排查:①检查分块质量(打印 nodes 查看切分是否合理);②切换混合检索(向量 + BM25);③加 Reranker 重排;④调大similarity_top_k;⑤换更适合你文档语言的 Embedding 模型(中文用 BGE 系列)。
Q:ChatEngine 的
condense_question模式追问效果不好?
A:condense_question依赖 LLM 把追问改写为独立问题。如果改写质量差(比如 LLM 能力不够),可以切换到condense_plus_context模式——它同时做改写和检索,把改写结果和检索上下文一起送给 LLM,回答质量更高但 Token 消耗也更多。
Q:索引构建很慢,有没有优化方法?
A:①使用持久化存储(Chroma),避免每次重启都重建索引;②对大文档集使用batch_size参数控制批量向量化速度;③如果只需要关键词检索,可以用SummaryIndex(不做向量化,速度快但精度低)。
Q:LlamaIndex 能和 LangChain 一起用吗?
A:可以。LlamaIndex 支持把 LangChain 的 LLM、Embedding、工具等组件通过适配器接入。但通常不需要——LlamaIndex 自己的集成包已经覆盖了主流模型和工具。
总结与回顾
| 知识点 | 关键要点 |
|---|---|
| LlamaIndex 定位 | RAG 专用框架,API 最简洁,开箱即用 |
| 核心概念 | Documents → Nodes → Index → QueryEngine / ChatEngine |
| 基础 RAG | 4 行代码跑通:加载文档 → 构建索引 → 创建引擎 → 查询 |
| 分块策略 | 5+ 内置分割器,SentenceSplitter 是默认推荐,SemanticSplitter 按语义切分 |
| 混合检索 | 向量 + BM25 互补,生产环境标配 |
| Reranker | 对检索结果二次精排,实测提升 10-20% 准确度 |
| 多轮对话 | ChatEngine + condense_question 模式,自动改写追问为独立问题 |
| Agent 工具 | ReActAgent 绑定知识库和外部工具,LLM 自主决策调用 |
| 结构化查询 | PandasQueryEngine 用自然语言查询 CSV 表格 |
| 与 LangGraph 对比 | LlamaIndex 高效简洁,LangGraph 深度定制,按需选择 |
下篇预告
第 8 篇:RAGFlow 私有化套件实战 —— 前 4 篇实战分别用了原生 Python、Dify、LangGraph、LlamaIndex 搭建 RAG,它们各有侧重。但如果你需要”一体化私有部署 + 深度文档解析(PDF 布局分析、表格 OCR)”,RAGFlow 是更好的选择。下一篇完整实战 RAGFlow 的 Docker 部署、模型接入、深度文档解析、RAPTOR 索引、Agent 工作流,末尾与 Dify 做平台选型对比。
参考资料
| 资源 | 链接 |
|---|---|
| LlamaIndex 官方文档 | docs.llamaindex.ai |
| LlamaIndex GitHub | run-llama/llama_index |
| DeepSeek 开放平台 | platform.deepseek.com |
| bge-large-zh-v1.5 | HuggingFace 模型页 |
| bge-reranker-v2-m3 | HuggingFace 模型页 |
| Chroma 向量数据库 | trychroma.com |
本文为「从零到落地:RAG 检索增强生成实战系列」第 7 篇,完整系列持续更新中。