第 32 课 | LlamaIndex 入门:用 50 行代码构建企业级知识库
从零到一:用 LlamaIndex 将行业报告、研究文档构建为可语义检索的知识库,让 Agent 的回答有据可依。
一、业务痛点:Agent 的「知识幻觉」问题
在场景二中,我们让 Agent 查询数据库、生成图表、回答问题。但有一个根本问题没解决:Agent 的知识从哪里来?
LLM 的训练数据有截止日期,而且不可能包含你公司内部的行业报告、竞品分析、市场研究。如果直接问 Agent「智能手表市场有多大」,它可能回答一个过时的数字,或者干脆编造一个。
这就是「知识幻觉」——Agent 不知道就说不知道,但 LLM 不知道也会硬编。
业务场景中,这可能是致命的。老板问「华为手表在血压监测方面有什么优势」,如果你的 Agent 给出一个似是而非的答案,老板据此做了错误决策,后果不堪设想。
解决方案:RAG(Retrieval-Augmented Generation)——检索增强生成。在 Agent 回答问题之前,先从知识库中检索相关文档,将检索结果作为上下文注入 Prompt,让 LLM 基于真实数据回答。
在 9-12 课我们已经学过 RAG 的基础组件(BGE 嵌入、ChromaDB、Reranker)。现在我们要用LlamaIndex这个框架,把这些组件优雅地组装起来,构建一个生产级的知识库系统。
二、为什么选择 LlamaIndex?
在 RAG 领域,LlamaIndex 和 LangChain 是最主流的两大框架。它们的定位不同:
| 维度 | LlamaIndex | LangChain |
|---|---|---|
| 核心定位 | 数据索引和检索 | 通用 Agent 编排 |
| 擅长领域 | RAG、知识库、文档问答 | 工具调用、工作流、Agent |
| 数据连接器 | 160+ 内置连接器 | 需要自己写 |
| 索引结构 | 多种索引类型 | 主要用于 Chain |
| 学习曲线 | 低(专注一件事) | 中(概念多) |
| 最佳场景 | 构建知识库、文档问答 | 多步骤 Agent 编排 |
简单来说:LlamaIndex 做检索,LangChain 做编排。两者可以配合使用——用 LlamaIndex 构建知识库,用 LangChain/LangGraph 编排 Agent 工作流。
LlamaIndex 的核心工作流:
三、核心概念拆解
3.1 Document(文档)
LlamaIndex 中的最小数据单元。一份 PDF、一页网页、一段文本,都可以是一个 Document。
fromllama_index.coreimportDocument doc=Document(text="智能手表市场2025年规模预计达到850亿美元...",metadata={"source":"行业报告","date":"2025-01","author":"市场部"})3.2 Node(节点)
Document 通常太长,需要切分为更小的检索单元,称为 Node。每个 Node 包含一段文本 + 元数据 + 与其他 Node 的关系。
fromllama_index.core.node_parserimportSentenceSplitter parser=SentenceSplitter(chunk_size=512,chunk_overlap=50)nodes=parser.get_nodes_from_documents(documents)chunk_size和chunk_overlap是关键参数:
- chunk_size=512:每个节点约 512 个字符,适合中文检索
- chunk_overlap=50:相邻节点重叠 50 字符,避免关键信息被切分到两个节点
3.3 Index(索引)
将 Node 向量化后存储的结构。最常用的是VectorStoreIndex:
fromllama_index.coreimportVectorStoreIndex index=VectorStoreIndex(nodes,embed_model=embed_model)LlamaIndex 还支持其他索引类型:
- SummaryIndex:对文档做摘要,适合「这份文档讲了什么」
- KeywordTableIndex:基于关键词的索引,适合精确匹配
- TreeIndex:树形索引,适合「总结文档的某个章节」
3.4 Query Engine(查询引擎)
将「检索 + 生成」封装为一步操作:
query_engine=index.as_query_engine(similarity_top_k=3)response=query_engine.query("智能手表市场规模?")similarity_top_k=3表示返回最相关的 3 个文档片段。
四、代码实战:构建行业报告知识库
完整代码结构
code/lesson-32-llamaindex/ ├── pyproject.toml # UV 依赖配置 ├── llamaindex_kb.py # 主程序 ├── data/ # 原始文档(自动生成) │ ├── 智能手表市场分析2025.txt │ ├── 华为智能手表产品分析.txt │ ├── 供应链与成本分析.txt │ └── 风险评估框架.txt └── index_storage/ # 索引持久化(自动生成)核心代码分步讲解
步骤 1:准备数据
defcreate_sample_reports():"""创建示例行业报告,模拟真实的企业知识库文档"""DATA_DIR.mkdir(parents=True,exist_ok=True)# 创建 4 份模拟行业报告...实际项目中,你的文档来源可能是:
- 公司内部的研究报告(PDF、Word)
- 竞品分析文档(Markdown)
- 行业数据(Excel)
- 会议纪要(飞书文档)
LlamaIndex 提供了 160+ 数据连接器,支持从几乎所有数据源加载。
步骤 2:构建索引
# 配置全局设置Settings.embed_model=HuggingFaceEmbedding(model_name="BAAI/bge-small-zh-v1.5")Settings.node_parser=SentenceSplitter(chunk_size=512,chunk_overlap=50)# 加载文档documents=SimpleDirectoryReader(DATA_DIR).load_data()# 构建索引index=VectorStoreIndex.from_documents(documents)# 持久化index.storage_context.persist(persist_dir=str(INDEX_DIR))步骤 3:查询知识库
query_engine=index.as_query_engine(similarity_top_k=3)response=query_engine.query("智能手表市场规模有多大?")关键设计决策:
| 决策点 | 选择 | 理由 |
|---|---|---|
| 嵌入模型 | bge-small-zh-v1.5 | 轻量(384维),CPU 友好,中文效果好 |
| 切分策略 | 512 字符 + 50 重叠 | 中文语义完整,避免切断关键信息 |
| 索引类型 | VectorStoreIndex | 语义检索,适合自然语言查询 |
| 持久化 | 本地文件系统 | 简单、零依赖,适合小规模场景 |
五、运行效果
# 安装依赖cdcode/lesson-32-llamaindex uvsync# 运行uv run llamaindex_kb.py输出示例:
[步骤 1] 准备示例行业报告... [创建] .../智能手表市场分析2025.txt [创建] .../华为智能手表产品分析.txt [创建] .../供应链与成本分析.txt [创建] .../风险评估框架.txt 共创建 4 份示例报告 [步骤 2] 构建 LlamaIndex 知识库索引... 正在加载文档... 加载了 4 份文档 - 智能手表市场分析2025.txt: 885 字符 - 华为智能手表产品分析.txt: 832 字符 - 供应链与成本分析.txt: 843 字符 - 风险评估框架.txt: 833 字符 正在解析文档为节点... 生成了 12 个节点(chunk) [步骤 3] 查询知识库... 🔍 查询: 智能手表市场规模有多大? [1] 相关度: 0.8523 | 来源: 智能手表市场分析2025.txt 内容: 2025年全球智能手表市场规模预计达到 850 亿美元... 🔍 查询: 华为智能手表有哪些产品线? [1] 相关度: 0.8934 | 来源: 华为智能手表产品分析.txt 内容: 1. 华为 Watch GT 系列(1500-2500 元)...六、效果对比:有无知识库的区别
| 维度 | 无知识库(纯 LLM) | 有知识库(LlamaIndex RAG) |
|---|---|---|
| 数据准确性 | 依赖训练数据,可能过时 | 基于最新文档,真实可靠 |
| 可追溯性 | 无法追溯信息来源 | 每个回答可追溯到具体文档 |
| 领域专业性 | 通用知识,不够深入 | 公司内部数据,专业对口 |
| 更新成本 | 需要重新训练模型 | 更新文档即可,实时生效 |
| 幻觉风险 | 高 | 低(有检索结果约束) |
业务价值量化:
场景:市场部需要调研「智能手表」行业,撰写市场分析报告 人工方式: - 搜索行业报告 → 2 小时 - 阅读 10+ 份报告 → 4 小时 - 提取关键数据 → 1 小时 - 整理成摘要 → 1 小时 总计:8 小时 × 150 元/时 = 1,200 元 知识库 RAG 方式: - 上传报告到知识库 → 5 分钟 - 自然语言提问 → 30 秒/问题 - 自动生成摘要 → 1 分钟 总计:约 10 分钟 × 0.5 元 = 0.5 元 效率提升:480 倍 成本节省:99.96%七、常见问题与优化
7.1 索引太大怎么办?
小规模(<1000 文档):本地文件存储,本课方案够用
中规模(1000-100000 文档):使用 ChromaDB 作为向量存储后端
大规模(>100000 文档):使用 Milvus 或 Pinecone 等生产级向量数据库
7.2 检索结果不准确怎么办?
- 增大
chunk_overlap(如 50 → 100),减少信息截断 - 调整
chunk_size(如 512 → 256),提高检索精度 - 加入 Reranker 重排序(第 33 课将详细讲解)
- 使用混合检索(向量 + 关键词)
7.3 文档更新了怎么办?
# 重新构建索引index=VectorStoreIndex.from_documents(new_documents)index.storage_context.persist(persist_dir=INDEX_DIR)或者使用 LlamaIndex 的增量索引功能,只更新变化的文档。
八、本课小结
这一课我们完成了 LlamaIndex 的入门:
- 理解 LlamaIndex 的定位:专注于 RAG 和知识库构建的框架
- 掌握四大核心概念:Document → Node → Index → Query Engine
- 构建了第一个知识库:4 份行业报告,12 个检索节点
- 跑通了完整流程:数据准备 → 索引构建 → 语义检索 → 效果对比
下一课,我们将进一步升级——实现混合检索、Rerank 重排序、查询改写,把检索精度提升到 90%+。
配套代码:code/lesson-32-llamaindex/llamaindex_kb.py(200+ 行,可直接运行)