跳到主要内容

从零到一Llama-Index上手指南

课程说明:

  体验课时间有限,若想深度学习大模型技术,欢迎大家报名由我主讲的《2025大模型Agent智能体开发实战》(12月班)

ac4f2a592e0453c3089da3643ee3404a

《2025大模型Agent智能体开发实战》(12月班) 为【100+小时】体系大课,总共20大模块精讲精析,零基础直达大模型企业级应用!

课程完整介绍

a92973f60f055b9109d991503fb7f000 6ee2fbee6b72608bee2888620fac1932

部分课程成果演示

from IPython.display import Video
  • Dify+DeepSeek搭建智能微信语音客服
Video("https://ml2022.oss-cn-hangzhou.aliyuncs.com/2f1b47f42c65fd59e8d3a83e6cb9f13b_raw.mp4", width=800, height=400)
  • Coze自动图文视频创作流程
Video("https://ml2022.oss-cn-hangzhou.aliyuncs.com/Coze%E5%8A%A8%E6%80%81%E8%A7%86%E9%A2%91%E7%94%9F%E6%88%90%E5%AE%9E%E4%BE%8B.mp4", width=800, height=400)
  • 可视化数据分析Multi-Agent
Video("https://ml2022.oss-cn-hangzhou.aliyuncs.com/%E5%8F%AF%E8%A7%86%E5%8C%96%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90Multi-Agent%E6%95%88%E6%9E%9C%E6%BC%94%E7%A4%BA%E6%95%88%E6%9E%9C.mp4", width=800, height=400)
  • 高效微调全自动数据集创建
Video("https://ml2022.oss-cn-hangzhou.aliyuncs.com/easy_daset_yanshi.mp4", width=800, height=400)
  • MateGen Pro 项目功能演示
Video("https://ml2022.oss-cn-hangzhou.aliyuncs.com/MG%E6%BC%94%E7%A4%BA%E8%A7%86%E9%A2%91.mp4", width=800, height=400)
  • 智能客服项目展示
Video("https://ml2022.oss-cn-hangzhou.aliyuncs.com/%E6%99%BA%E8%83%BD%E5%AE%A2%E6%9C%8D%E6%A1%88%E4%BE%8B%E8%A7%86%E9%A2%91.mp4", width=800, height=400)
  • GraphRAG+多模态文档检索
Video("https://ml2022.oss-cn-hangzhou.aliyuncs.com/7%E6%9C%8817%E6%97%A5%281%29%20%E8%BF%9B%E5%BA%A6%E6%9D%A1.mp4", width=800, height=400)

此外,若是对大模型底层原理感兴趣,也欢迎报名由我和菜菜老师共同主讲的《2025大模型原理与实战课程》(秋季班)

a9c8776df826a9ee8e9fb8e31c72b180 3 282126fbd48fc7124eaaa5ce9761443e

详细信息扫码添加助教,回复“大模型”,即可领取课程大纲&查看课程详情👇

f4cbd61f066c028e479cdbe8410aab1b
1b29bf01197a27bbb67de0c7003311e2

最强RAG框架:Llama-Index快速入门实战

Part 1.从零到一Llama-Index上手指南

一、RAG(Retrieval-Augmented Generation,检索增强生成)技术综述

  RAG,Retrieval-Augmented Generation,也被称作检索增强生成技术,最早在 Facebook AI(Meta AI)在 2020 年发表的论文《Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks》( https://arxiv.org/abs/2005.11401 )中正式提出,这种方法的核心思想是借助一些文本检索策略,让大模型每次问答前都带入相关文本,以此来改善大模型回答时的准确性。这项技术刚发布时并未引发太大关注,而伴随2022年大模型技术大爆发,RAG技术才逐渐进入人们视野,并且由于早期大模型技术应用均已“知识库问答”为主,而RAG技术是最易上手、并且上限极高的技术,因此很快就成为了大模型技术人必备的技术之一。

1. RAG技术极简实现流程

  时至今日,RAG技术已经是非常庞大的技术体系了,从简答的文档切分、存储、匹配,再到复杂的入GraphRAG(基于知识图谱的检索增强),以及复杂文档解析+多模态识别技术等等等等。

image-20250708010422027

而对于初学者来说,为了更好的上手学习RAG技术,我们首先需要对RAG技术最简单的实现形式有个基础的了解。一个最简单的RAG技术实现流程如下所示:

image-20231218182814731

我们需要围绕给定的文档(往往是非常长的文档)先进行切分,然后将切分的文档转化为计算机能识别的形式,也就是将其转化为一个数值型向量(也被称为词向量),然后当用户询问问题的时候,我们再将用户的问题转化为词向量,并和段落文档的词向量进行相似度匹配,借此找出和当前用户问题最相关的原始文档片段,然后将用户的问题和匹配的到的原文片段都带入大模型,进行最终的问答。由此便可实现一次完整的文档检索增强执行流程。a

  具体执行过程如下所示:

image-20250708015352331

3. RAG技术核心应用场景:拓展模型知识边界与减少问答幻觉

  那这样的一个检索增强流程到底有什么用呢?这就不得不从当代大模型本身的三项技术缺陷开始说起了。

  • 缺陷一:大模型幻觉

  相信大家在使用大模型的时候,都会遇到大模型无中生有胡编乱造答案的情况,例如胡乱生成一些概念、一些论文甚至是一些实时等,这就是所谓的大模型幻觉。

image-20250707233838007

而其中,第一代DeepSeek R1模型的幻觉是非常严重的,平均七次回答中就会有一次的回答存在幻觉,这可以说是第一版R1模型最大的短板。

  大型语言模型之所以会产生幻觉,主要是因为它们的训练方式和内在机制决定了它们并不具备真正理解和验证事实的能力。模型在训练过程中,通过分析大规模文本数据来学习不同词语和句子之间的概率关系,也就是在某种程度上掌握“在什么上下文中,什么样的回答听起来更合理”。然而,模型并没有接入实时的知识库或事实核查工具,当它遇到陌生的问题、模糊的描述或者上下文不完整的输入时,就会基于概率和语料库中似是而非的关联去“编造”一个看似正确的答案。由于这些输出往往语法流畅、逻辑连贯,人类读者很容易误以为它是真实可信的内容,这就是我们通常说的“模型幻觉”。

  • 缺陷二:有限的最大上下文

  而除此之外,大模型在实际应用中还会另一个“障碍”,那就是最大上下文限制。由于大模型的本质其实是一个算法,不管是让大模型“知道”有哪些外部工具,还是要给大模型进行“背景设置”,或者是要给模型添加历史对话消息,以及本次对话的输出,都需要占用这个上下文窗口。这就使得我们在一次对话中能够给大模型灌输的知识(文本)其实是有限的。

  大型语言模型还存在最大上下文限制,这是由它们的架构和计算方式决定的。每次生成回答时,模型需要把输入文本转换成固定长度的数字序列(称为token),并在内部一次性加载到模型的“上下文窗口”中进行处理。这个窗口的大小是有限的,不同模型一般在几千到几万token之间。如果输入内容超出这个长度,模型要么截断最前面的部分,要么丢弃部分信息,这就会造成对话历史、长文档或先前提到的重要细节的遗失。因为它无法跨越上下文窗口无限地保留信息,所以在面对长对话或者大量背景知识时,模型常常出现上下文断裂、回答不连贯或者忽略先前条件的情况。

  早些时候的大模型普遍是8k最大上下文,相当于是8-10页中文PDF,伴随着大模型预训练技术的不断发展,顶尖的大模型,如Gemini 2.5 Pro和GPT-4.1等模型,已经达到了1M的最大上下文长度,相当于是一千页的PDF,相当于1.5本《红楼梦》,而普通的模型,也基本达到64K或128K最大上下文,相当于60-100也左右的PDF。

image-20250707234800964

但是,模型上下文的增长也是有限度的,对于开发者来说,能够一次性输入的信息都会有限制。

  • 缺陷三:模型专业知识与时效性知识不足

  大型语言模型虽然在通用领域展现出令人瞩目的语言理解和生成能力,但其在特定领域的专业知识掌握往往存在明显局限。其根本原因在于,模型的训练依赖于预先收集的大规模语料,这些语料覆盖面虽广,却很难保证在所有专业领域中具有足够的深度和准确性。某些领域,如医学、法律或前沿科技,知识更新速度快且门槛较高,公开可获取的高质量数据本身就有限,模型难以在此基础上形成系统性和权威性的认知。此外,模型训练通常在固定的时间点结束,因此其所掌握的知识具有天然的时效性,无法实时反映新近出现的研究成果、政策变化或行业动态。这种静态的知识存储模式,决定了大模型在面对最新或高度专业化的问题时,往往难以提供全面、精确的解答。

image-20250708022912484

  基于此,我们再回顾RAG的技术实现流程,就不难发现其背后的技术价值了:如果我们能在每次对话的时候,为当前模型输入最精准的问题相关的文档,那就能拓展模型的知识边界,无论是提升模型专业知识的准确性、给模型灌输一些时效性的知识、或者消除模型幻觉,都将大有助益,而在其他一些对话场景中,无论是需要围绕海量的文本搭建本地问答知识库、还是在构建无限上下文的聊天机器人,RAG技术都是最佳解决方案。

4. 问答机器人标配:RAG系统

  正因为知识库检索的广泛的使用需求,RAG技术几乎成了现在各项聊天机器人的标配,无论是面向普通用户的聊天问答应用Cherry Studio:

image-20250708141040865

还是面向企业应用场景的通用开源前端Open-WebUI:

image-20250708142841404

都毫无例外都配置了RAG功能,而对于OpenAI-WebUI这种企业级前端,还为用户展示了RAG检索过程诸多技术细节:

image-20250708143007552

尽管这些项目能让用户更加快速的使用RAG系统,但这种传统的RAG流程(也被称作Native RAG),在长期的应用过程中也逐渐展露出很多问题,例如对于非结构化的文本(例如包含图片、公式的文本)无法进行检索,而对于超大规模文本的检索又会存在精度不足、或者无法提炼总结跨文本概念等问题。为此,近两年的时间里,在无数技术人的共同努力下,RAG技术有了长足的成长和突破。

  我们团队自研的开源Jupyter智能体助教MateGen Air,也提供了完整的公开课(部分)知识库问答功能:

image-20250708155628356 image-20250708155442209

5. RAG全栈技术体系介绍

  但是,就像前文介绍的那样,RAG技术是一项应用面广、门槛很低、但同时上限也很高的一项技术。历经数年的技术发展,RAG技术的体系已经非常庞大,以下是RAG技术全栈技术框架概览:

88bac0891ac369368fd9199d1542862
  • GraphRAG

GraphRAG(Graph-enhanced Retrieval-Augmented Generation) 是一种在经典 RAG 基础上引入知识图谱/图结构的新型检索生成方法 。其核心思想是通过将文档或数据转换成图的形式,从而捕捉实体与实体之间的语义关系,并在检索阶段利用图遍历、关系推理等机制来辅助上下文构建,这种结构化信息能够提升语义理解和多跳推理能力。

具体来说,GraphRAG 的流程包括:

  1. 图谱构建:将文本拆分为多个单元(TextUnit),提取实体与关系,构造知识图,并进行图社区检测与摘要;
  2. 混合检索:用户提问既可以进行向量检索定位实体,也可以通过图查询(如 Cypher/SPARQL)沿关系边扩展信息 ;
  3. 图增强生成:将检索到的节点、路径、社区摘要等信息拼接进 Prompt,引导 LLM 生成更准确、结构清晰、并基于事实推理的回答。
对比维度传统 RAGGraphRAG
检索方式基于向量语义相似度向量+知识图遍历/查询
关系理解能力弱:只能匹配语义相近片段强:能理解实体之间的多跳关系与结构
多跳推理支持弱:难以综合跨文档信息强:图结构天然支持推理路径遍历
语义上下文覆盖依赖检索片段可检索完整实体子图、社区摘要
可解释性中:返回片段但缺关键信息结构高:能显示实体关系路径及社区结构
性能/复杂度低:直接使用向量库高:需要图构建、遍历、摘要等pipeline

传统 RAG 主要是“先检索语义近似片段,再生成回答”,适合简单查询与短对话。但当问题需要“连接多个事实”“推理关系链”和“洞察上下文结构”时,传统 RAG 会显得力不从心,而 GraphRAG 正是为复杂推理场景设计的增强机制。

  • Agentic RAG

   Agentic RAG(Agentic Retrieval-Augmented Generation) 是一种在传统 RAG 基础上进一步扩展的增强范式,它将检索增强生成Agent(智能体)能力有机结合,使大模型不仅能够基于外部知识库进行回答,还能够通过一系列自主决策和工具调用来完成复杂任务。与经典 RAG 的“检索+拼接+生成”线性流程不同,Agentic RAG 将 LLM 视为一个具备推理、规划和操作能力的智能体,它在对话过程中可以根据问题拆解子任务,先后执行多轮检索、知识整合、函数调用甚至外部API请求,再将结果动态组合成最终的答案。

   在这个模式下,大模型可以主动提出接下来的检索需求,或根据中间推理结果迭代获取更多信息,形成“循环式检索与生成”的闭环工作流。例如,当用户提出复杂查询时,Agentic RAG可以先调用检索工具定位候选内容,再使用工具对结果进行归纳或分类,必要时还会触发计算或外部查询操作,最后再汇总所有信息输出一个有依据的、分步骤的解答。

   相比传统RAG,Agentic RAG不仅提升了回答准确性和透明度,也为多轮推理和跨知识库整合提供了更强的灵活性,是近年来大模型产品中非常重要的能力演进方向。

6. RAG技术实际落地应用困局

6.1 “易于上手,难于精通”的技术悖论

  检索增强生成(RAG)技术展现出典型的“低门槛,高天花板”特征。在原型验证(PoC)阶段,通过标准的“切分-向量化-检索-生成”流程,开发者往往能在数小时内构建出一个可运行的 Demo。

  然而,当系统从演示环境走向企业级生产环境时,边际效益会迅速递减。尽管市面上已经涌现出如 MaxKB、RAGFlow 等优秀的开箱即用型 RAG 产品,它们在处理通用知识库时表现出色,但在面对企业高度定制化、非标准化的业务场景时,往往显得力不从心。

  企业级应用的核心挑战在于:业务需求千差万别,不存在“一套通吃(One-size-fits-all)”的 RAG 架构。为了在特定领域达到生产可用的准确率(通常要求 90% 以上),必须深入数据层进行定制化开发与调优。

image-20250708145634936

6.2 当前 RAG 系统的核心技术瓶颈

在实际工程实践中,通用的 RAG 架构主要面临以下三大难以逾越的障碍:

  • 痛点一:系统效果的黑盒化与评估难题

    • 缺乏量化标准: 与传统软件工程不同,RAG 系统的输出具有概率性。缺乏“标准答案(Ground Truth)”使得开发者难以对检索准确率(Retrieval Accuracy)和生成忠实度(Generation Faithfulness)进行客观量化。
    • 归因困难: 当模型回答错误时,很难快速界定是检索环节漏掉了关键文档(Recall Issue),还是大模型本身的推理能力不足(Reasoning Issue),或是 Prompt 设计不当。这导致优化工作如同“盲人摸象”,缺乏迭代方向。
  • 痛点二:大规模语料下的“迷失”与推理局限

    • 精度与规模的矛盾: 随着文档数量从几百篇增加到数万篇,简单的 Top-K 向量检索容易引入大量噪声,导致“大海捞针(Needle in a Haystack)”效应,关键信息被淹没。
    • 跨文档推理能力的缺失: 传统 RAG 将文档切碎成独立的片段(Chunks),丢失了文档间的逻辑关联。当用户问题需要综合 A 文档的条件和 B 文档的结论进行多跳推理(Multi-hop Reasoning)时,或者需要对整个文集进行综合性主题概括时,基于片段匹配的 RAG 系统往往表现堪忧。
  • 痛点三:高价值数据的结构性丢失(多模态与表格)

    • 表格数据的语义坍塌: 企业财报、技术手册中包含大量表格。传统的文本切分方式会将表格打散成无意义的字符串,导致行列对应关系丢失,LLM 无法进行精准的数据查询与对比。
    • 多模态信息的盲区: 传统的 RAG 流程通常会丢弃 PDF 中的图表、架构图和截屏。然而,在工业制造、医疗诊断等场景中,核心知识往往蕴含在图片而非文字中,这造成了巨大的信息资产浪费。

二、Llama-Index框架入门介绍

1. Llama-Index 项目介绍

image-20251211171356686 image-20251211150319664

  Llama-Index(前身为 GPT Index)由 Jerry Liu 于 2022 年底发起。项目的诞生背景源于大语言模型(LLM)落地初期的一个核心痛点:模型虽然具备强大的通用推理能力,但缺乏特定领域的私有知识(Private Knowledge),且受限于上下文窗口(Context Window)的长度,无法处理大规模文档。

  Llama-Index 最初的初衷非常纯粹:构建一个高效的“接口”,将用户的私有数据(如 PDF、Notion、SQL、API 数据)转化为 LLM 能够理解和利用的格式,从而通过上下文学习(In-context Learning)来增强模型的能力。经过两年的高速迭代,它已从一个简单的索引工具演变为一个完整的**“数据驱动型”大模型应用开发框架**。

  如果把大模型比作“大脑”,Llama-Index 的定位就是“记忆增强系统”。它的官方定义是:“用于构建上下文增强型(Context-augmented)LLM 应用程序的数据框架”**。

  它不仅仅关注于如何向模型提问(Prompt Engineering),更侧重于数据管理(Data Management)的全生命周期,包括数据的摄入(Ingestion)、结构化索引(Indexing)以及高效检索(Retrieval)。其核心目标是打破私有数据孤岛,让 LLM 能够以最低的成本、最高的精度访问海量外部知识。

  目前,Llama-Index 是全球 AI 开源社区中最活跃的项目之一。

  • 技术迭代: 保持着极高的更新频率,已发布 v0.10+ 版本,完成了核心架构的模块化重构,具备了企业级生产环境所需的稳定性。
  • 生态系统: 拥有庞大的 LlamaHub 数据加载器生态,支持数百种数据源(从文件系统到 SaaS 服务)的开箱即用连接;同时支持 Python 和 TypeScript 双语言版本。

  在 LLM 开发领域,通过对比可以更清晰地理解两者的差异:

  • LangChain(通用编排者):
    • 定位: 通用的 LLM 应用开发框架。
    • 强项: 侧重于**“计算逻辑”**的编排。它擅长管理复杂的 Agent 行为链、工具调用(Tool Usage)以及多模态交互的流程控制。它像是一个“胶水”,连接模型与万物。
  • Llama-Index(数据专家):
    • 定位: 专注于数据处理与检索的垂直框架。
    • 强项: 侧重于**“数据结构”**的优化。它在 RAG 领域拥有更深的护城河,特别是在处理非结构化数据切片、层级索引构建、复杂查询路由等方面提供了更精细的控制能力。

  相较于其他框架,Llama-Index 在 RAG(检索增强生成)方面展现出显著的专业性优势:

  1. 更丰富的数据索引结构: 不仅支持简单的向量索引,还原生支持树状索引、关键词表索引、知识图谱索引等多种结构。
  2. 更高级的检索策略: 提供了递归检索(Recursive Retrieval)、混合检索(Hybrid Search)及元数据过滤等开箱即用的高级功能。
  3. 数据与 LLM 的深度对齐: 能够更好地处理长文档摘要、跨文档推理等复杂的数据任务。
Gemini_Generated_Image_rbs8kvrbs8kvrbs8

2. Llama-Index RAG核心优势

2.1 RAG 全生命周期(Full-Lifecycle)的闭环支持

  与许多仅关注“向量检索”单一环节的工具不同,Llama-Index 提供了从数据源头到最终评估的 RAG 全流程解决方案。它将 RAG 系统抽象为五个标准化的流水线环节,开发者可以在同一个框架内完成所有工作,无需拼凑多个零散的工具库。

  • 数据加载 (Loading): 提供统一接口将各类非结构化数据转化为标准的 Document 对象。
  • 索引构建 (Indexing): 将文档切分(Chunking)并向量化(Embedding),构建出不仅包含向量、还包含元数据(Metadata)和节点关系(Relationships)的高级索引结构。
  • 存储 (Storing): 原生适配数十种主流向量数据库(如 Chroma, Weaviate, Milvus)及图数据库,支持索引的持久化与增量更新。
  • 查询 (Querying): 这一环节是 Llama-Index 的核心,它封装了检索、后处理和合成的复杂逻辑,对外提供简洁的查询接口。
  • 评估 (Evaluation): 独有的 "Evaluation-First" 理念,内置了基于 LLM 的评估模块,能够对检索的准确性(Retrieval metrics)和生成的质量(Response metrics)进行自动化评分,解决了 RAG 难以优化的痛点。
Gemini_Generated_Image_ibcj2fibcj2fibcj

2.2 极致的定制化空间与丰富的功能接口

  Llama-Index 最大的架构优势在于其模块化(Modularity)设计。它将 RAG 的每个步骤都解耦为可插拔的组件,特别是在查询引擎(Query Engine)环节,提供了极高的定制自由度:

  • 高级后处理 (Post-Processing): 在检索与生成之间,Llama-Index 允许开发者插入“节点后处理器(Node Postprocessors)”。这使得我们可以轻松实现:
    • 重排序(Re-ranking): 集成 Cohere Rerank 或 BGE Rerank 模型,对检索到的 Top-K 结果进行二次精排,大幅提升相关性。
    • 元数据过滤(Metadata Filtering): 基于时间、作者或文件类型过滤节点。
    • 相似度截断(Similarity Cutoff): 自动丢弃相似度低于阈值的噪声数据。
  • 灵活的响应合成 (Response Synthesis): 针对不同的业务场景,提供了多种内置的合成策略,而非单一的拼接:
    • Refine(精炼模式): 线性遍历检索结果,逐步迭代优化答案,适合生成详尽的回答。
    • Tree Summarize(树状总结): 自底向上构建摘要树,适合处理海量上下文的归纳总结任务。
    • Compact(紧凑模式): 最大化利用 Context Window,平衡速度与成本。
Gemini_Generated_Image_x5ugvjx5ugvjx5ug

2.3 庞大的数据生态:LlamaHub

  Llama-Index 拥有目前 AI 社区中最丰富的数据连接器生态——LlamaHub。它解决了 RAG 开发中“最后一公里”的数据获取难题,让开发者无需自行编写爬虫或解析脚本。

  • 海量数据加载器 (Data Loaders): 社区维护了超过 400 种数据加载器,覆盖了几乎所有主流数据源:
    • 文件类: PDF, Markdown, PowerPoint, Word, Excel, CSV 等。
    • SaaS 类: Notion, Slack, Discord, Jira, Salesforce, Google Docs 等。
    • 网络类: Wikipedia, YouTube Transcripts, Web Page Reader 等。
    • 数据库类: PostgreSQL, MongoDB, SQL Database 等。
  • 多模态原生支持: 除了文本,LlamaHub 还提供了针对图像、音频和视频的加载器,支持构建图文混排的 RAG 系统,能够将多模态信息统一映射到向量空间。
image-20251211155312326

2.4 企业级云服务:LlamaCloud

为了满足企业对高性能和免运维的需求,Llama-Index 团队还推出了配套的商业化云服务,进一步补全了开源框架的拼图:

  • LlamaParse: 这是目前业界最先进的文档解析服务之一。专为解决 RAG 中的“复杂文档处理”难题而生,能够精准识别和解析 PDF 中的复杂表格、图表、数学公式以及多栏排版,将其转化为 LLM 易于理解的 Markdown 格式,从源头上提升了 RAG 的检索质量。
  • Managed Indexing: 提供“检索即服务(Retrieval-as-a-Service)”,开发者无需自行维护向量数据库和索引管道,通过 API 即可直接上传文件并进行高效检索,大幅降低了企业级 RAG 的落地门槛。
image-20251211172759759

3.Llama-Index RAG 黑科技

  在 Llama-Index 的工具箱中,隐藏着几种能够显著提升 RAG 性能的“杀手级”特性。这些技术突破了传统 RAG 的线性流程,引入了逻辑推理、代码执行和多模态能力。

3.1 Small-to-Big Retrieval(小索引,大窗口)

  • 痛点: 传统 RAG 直接对切片进行检索。切片太小,上下文缺失(LLM 看不懂);切片太大,包含过多噪声(检索不准)。
  • 黑科技原理: “索引粒度”与“生成粒度”分离。 系统将文档切分成极小的句子(Sentence)进行精准检索,但在提交给 LLM 时,自动将该句子替换为它周围更大的文本窗口(Window)。既保证了检索的高精度(High Precision),又提供了生成所需的丰富上下文(Rich Context)。
  • 伪代码示例:
    # 1. 使用窗口解析器,记录每句话的“上下文窗口”
    node_parser = SentenceWindowNodeParser.from_defaults(
    window_size=3 # 检索到一句话,同时带出前后各3句话
    )

    # 2. 在查询时,启用元数据替换功能
    query_engine = index.as_query_engine(
    node_postprocessors=[MetadataReplacementPostProcessor(...)]
    )

3.2 Pandas Query Engine(结构化数据RAG)

  • 痛点: 用户问:“计算 Q3 销售额的总和。” 传统 RAG 会检索出一堆包含数字的文本,让 LLM 自己算,极易出现数学幻觉(Math Hallucination)。
  • 黑科技原理: 将“检索任务”转化为“编程任务”。 Llama-Index 不去搜索文本,而是让 LLM 编写一段 Pandas Python 代码,并在本地沙箱中执行。这相当于让 RAG 拥有了类似 ChatGPT Code Interpreter 的能力,实现 100% 准确的数据计算。
  • 伪代码示例:
    import pandas as pd
    from llama_index.experimental import PandasQueryEngine

    df = pd.read_excel("sales_data.xlsx")

    # 引擎会自动生成代码:df[df['quarter']=='Q3']['sales'].sum() 并执行
    query_engine = PandasQueryEngine(df=df, verbose=True)
    response = query_engine.query("Q3 的销售总额是多少?")

3.3 Router Query Engine(智能路由分诊)

  • 痛点: 系统中既有非结构化的 PDF(适合语义检索),又有结构化的 SQL 数据库(适合精确查询)。用户提问时,系统不知道该查哪一个。
  • 黑科技原理: RAG 的“前置大脑”。 Router 是一个轻量级的分类器(Agent),它会先分析用户意图,然后动态决定将问题路由给“向量检索引擎”还是“SQL 查询引擎”,甚至同时查询两者。
  • 伪代码示例:
    from llama_index.core.tools import QueryEngineTool
    from llama_index.core.query_engine import RouterQueryEngine

    # 定义两个工具:一个查文档,一个查摘要
    summary_tool = QueryEngineTool.from_defaults(query_engine=summary_engine, description="查摘要")
    vector_tool = QueryEngineTool.from_defaults(query_engine=vector_engine, description="查细节")

    # 智能路由:根据问题自动选择用哪个工具
    query_engine = RouterQueryEngine(
    selector=LLMSingleSelector.from_defaults(),
    query_engine_tools=[summary_tool, vector_tool]
    )

3.4 Sub-Question Query Engine(多子问题查询)

  • 痛点: 用户问:“对比 A 公司和 B 公司的营收增长率。” 这是一个多跳推理(Multi-hop)问题,单次检索往往只能搜到其中一家的数据,导致回答不全。
  • 黑科技原理: 分而治之(Divide and Conquer)。 引擎会自动将这个复杂问题拆解为三个子问题:(1)查 A 公司营收;(2)查 B 公司营收;(3)对比结果。系统并发执行查询,最后汇总答案。
  • 伪代码示例:
    from llama_index.core.query_engine import SubQuestionQueryEngine

    # 引擎运行时会打印:
    # > Generated sub-question: What is the revenue of Company A?
    # > Generated sub-question: What is the revenue of Company B?
    query_engine = SubQuestionQueryEngine.from_defaults(
    query_engine_tools=tools
    )

3.5 Native Multimodal RAG(原生多模态检索)

  • 痛点: PDF 中的架构图、流程图或产品照片被传统 OCR 忽略,导致关键信息丢失。
  • 黑科技原理: CLIP 跨模态对齐。 利用 CLIP 模型将文本和图像映射到同一个向量空间。无需 OCR 转文字,系统可以直接用“文字”检索到“图片”,并将图片直接喂给 GPT-4o 或 LLaVA 等多模态大模型进行理解。
  • 伪代码示例:
    from llama_index.core.indices import MultiModalVectorStoreIndex

    # 建立包含文本和图片的混合索引
    index = MultiModalVectorStoreIndex.from_documents(documents)

    # 检索结果包含 ImageNode,可直接展示图片或喂给视觉模型
    retriever = index.as_retriever(image_similarity_top_k=2)

三、Llama-Index快速上手指南

1.基本环境搭建与快速运行

  课程开始之前,我们需要构建一个干净、独立的 Python 开发环境。Llama-Index 迭代速度极快,使用虚拟环境可以避免与您本地的其他项目产生依赖冲突。

1.1 创建 Python 虚拟环境

推荐使用 Conda 进行环境管理(也可以使用 Python 自带的 venv)。我们将创建一个名为 llama-index-demo 的环境,并指定 Python 版本为 3.10 或以上(Llama-Index 对新特性支持较好)。

  • 打开终端(Terminal)或 Anaconda Prompt,执行以下命令:

    # 1. 创建虚拟环境
    conda create -n llamaindex python=3.12 -y

    # 2. 激活虚拟环境
    conda activate llamaindex

    # 3.安装jupyter kernel
    conda install jupyterlab
    conda install ipykernel
    python -m ipykernel install --user --name llamaindex --display-name "Python (llamaindex)"

    # 4.启动jupyter
    jupyter lab

1.2 安装 Llama-Index 核心库

  自 v0.10.0 版本起,Llama-Index 采用了模块化架构。对于初学者,我们直接安装主包,它会自动包含核心组件(Core)以及常用的 OpenAI 适配器。

  • 执行安装命令:

    # 安装 Llama-Index 主包
    pip install llama-index -i https://pypi.tuna.tsinghua.edu.cn/simple

    # 安装环境变量管理工具 (用于加载 .env 文件)
    pip install python-dotenv -i https://pypi.tuna.tsinghua.edu.cn/simple

是一个包含以下软件包的入门级捆绑包

  • llama-index-core
  • llama-index-llms-openai
  • llama-index-embeddings-openai
  • llama-index-readers-file

注意: llama-index-core已预先捆绑 NLTK 和 tiktoken 文件,以避免运行时下载和网络调用。

1.3 配置 OpenAI API Key

  Llama-Index 默认使用 OpenAI 的 GPT-3.5-turbo 进行推理以及 text-embedding-ada-002 进行向量化。虽然框架支持更换任意模型,但在快速上手阶段,使用 OpenAI 是最稳定、调试最方便的选择。

为了安全起见,我们严禁将 API Key 直接硬编码在代码中。我们将采用业界标准的 .env 环境变量文件进行配置。

  • 步骤 1: 在项目根目录下,创建一个名为 .env 的新文件(注意文件名前面有个点,且没有后缀名)。

  • 步骤 2: 使用文本编辑器打开该文件,并写入您的 API Key:

    # .env 文件内容示例
    OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    BASE_URL=sk-proj-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
image-20251211173844353 721278dab61b076b06172a89203f9800

1.4 验证安装

import os
from dotenv import load_dotenv
import llama_index.core
# 1. 加载环境变量
load_dotenv()

# 2. 检查 Llama-Index 版本
print(f"Llama-Index Version: {llama_index.core.__version__}")
  • 模型调用测试
from openai import OpenAI
client = OpenAI(
base_url=os.getenv("BASE_URL"),
api_key=os.getenv("OPENAI_API_KEY"),
)
# 查看模型列表
model_list = client.models.list()
model_list.data

2.【选学】LLama-Index创建Agent功能介绍

import asyncio
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.llms.openai import OpenAI
# Define a simple calculator tool
def multiply(a: float, b: float) -> float:
"""Useful for multiplying two numbers."""
return a * b
OpenAI?
base_url=os.getenv("BASE_URL")
api_key=os.getenv("OPENAI_API_KEY")
llm=OpenAI(api_key=api_key,
api_base=base_url,
model="gpt-4o-mini")
# Create an agent workflow with our calculator tool
agent = FunctionAgent(
tools=[multiply],
llm=llm,
system_prompt="You are a helpful assistant that can multiply two numbers.",
)
response = await agent.run("What is 1234 * 4567?")
response
  • Llama-Index Agent历史对话记忆管理
from llama_index.core.workflow import Context

# create context
ctx = Context(agent)

# run agent with context
response = await agent.run("你好,我叫陈明", ctx=ctx)
response
response = await agent.run("你还记得我叫什么名字么?", ctx=ctx)
response

3.Llama-Index RAG功能快速实现方法

  • 数据集准备
import os
file_path = "./data/创新科技股份有限公司员工手册.txt"

with open(file_path, "r", encoding="utf-8") as f:
md_content = f.read()
md_content[:1000]
image-20250922203147677

接下来介绍如何从零构建一个能够回答公司内部政策的 AI 助手。请注意,这几行代码虽然简洁,但它们在后台完成了 RAG 系统中最核心的ETL(抽取、转换、加载)、索引构建以及检索生成的全流程。我们将逐行拆解,重点剖析在默认参数下,Llama-Index 到底在后台做了什么,以及如何查看底层结果。

Gemini_Generated_Image_x5ugvjx5ugvjx5ug
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader

# 1. 数据摄入 (Loading)
documents = SimpleDirectoryReader("data").load_data()

# 2. 索引构建 (Indexing)
index = VectorStoreIndex.from_documents(documents)

# 3. 引擎配置 (Query Engine)
query_engine = index.as_query_engine()

# 4. 执行查询 (Execution)
# 注意:aquery 是异步调用,在 Jupyter 或标准脚本中通常使用同步的 query
response = query_engine.query("请问,我们公司有病假政策么?请用中文进行回复。")
response.response

第一步:数据摄入 (Data Ingestion)

FENCE0

  • 功能逻辑: 这是 RAG 流程的起点。SimpleDirectoryReader 就像一个全能的搬运工,它读取 data 目录下的《员工手册.txt》,将其内容加载到内存中,并封装为 Llama-Index 的标准 Document 对象
  • 默认行为:
    • 读取模式: 默认将一个文件视为一个完整的 Document。如果手册有 1 万字,这里生成的 Document 就包含 1 万字的 text
    • 元数据提取: 自动提取文件名、路径、创建时间等基础信息作为 metadata
documents
len(documents)
  • 如何查看底层结果:
print(f"加载了 {len(documents)} 个文档")
print(f"文档内容预览: {documents[0].text[:100]}...") # 查看前100个字符
print(f"元数据: {documents[0].metadata}")

第二步:索引构建 (Indexing Pipeline) —— 黑盒核心

FENCE0

  • 功能逻辑: 这行代码启动了数据处理流水线。它将粗粒度的 Document 转化为适合检索的细粒度向量索引。
  • 默认参数下的后台动作 (The Default Pipeline):
    1. 切分 (Parsing): 调用 SentenceSplitter,将《员工手册》切分成多个小的 Node (节点)
      • 默认大小: chunk_size=1024 (Token)。
      • 默认重叠: chunk_overlap=20 (Token)。
    2. 嵌入 (Embedding): 调用 OpenAI 的 text-embedding-ada-002 模型,将每个 Node 的文本转化为 1536 维的向量。
    3. 存储 (Storage): 将向量和文本保存在内存中的 SimpleVectorStore(即 Python 字典结构)。
# 查看切分后的 Node 数量
print(f"文档被切分成了 {len(index.docstore.docs)} 个节点")
# 查看第一个节点的实际内容
nodes = list(index.docstore.docs.values())
print(f"节点1内容: {nodes[0].text}")

第三步:引擎配置 (Query Engine Configuration)

FENCE0

  • 功能逻辑: 将静态的索引数据库封装为可交互的问答引擎。这一步定义了 RAG 的检索策略和合成策略。
  • 默认参数行为:
    • 检索策略: similarity_top_k=2。意味着当用户提问时,系统只会在《员工手册》中寻找最相关的 2 个片段
    • 合成策略: response_mode='compact'。系统会将检索到的 2 个片段拼接进 Prompt,一次性发送给 LLM 生成答案。

第四步:执行查询 (Query Execution)

FENCE0

  • 功能逻辑:

    1. Query Embedding: 将用户的自然语言问题转化为向量。
    2. Similarity Search: 计算问题向量与《员工手册》所有 Node 向量的相似度,找出 Top-2。
    3. Synthesis: 将 Top-2 的“病假相关条款”填入 Prompt 模板,发给 GPT-3.5/4。
    4. Response: LLM 返回“根据员工手册,本公司病假政策如下……”
  • 如何查看底层结果(验证 RAG 是否有效): 查看 response 对象不仅能看到答案,还能看到依据(即溯源)。

print("=== AI 回答 ===")
print(response.response)

print("\n=== 参考依据 (Source Nodes) ===")
for node in response.source_nodes:
print(f"引用片段 (相似度 {node.score:.2f}):")
print(node.node.text)
print("----------------")

也就是说,通过这 5 行代码,我们实际上构建了一个完整的非结构化数据处理管道

  • 输入: 本地 txt 文件(非结构化)。
  • 处理: 切分 -> 向量化 -> 存储(结构化索引)。
  • 输出: 基于事实的自然语言回答(知识服务)。

4.【选学】Llama-Index Agentic RAG基础实现流程

async def search_documents(query: str) -> str:
"""Useful for answering natural language questions about an personal essay written by Paul Graham."""
response = await query_engine.aquery(query)
return str(response)
# Create an enhanced workflow with both tools
agent = FunctionAgent(
tools=[multiply, search_documents],
llm=llm,
system_prompt="""你是一名助人为乐的助手,能够快速准确的进行乘法运算,同时也能结合文档内容回答用户问题。""",
)
response = await agent.run("请问,我们公司有病假政策么?")
response
image-20251211182818272

5.Llama-Index RAG系统默认参数与默认RAG流程

  在上一节的“5 行代码”示例中,系统之所以能自动运行,是因为 Llama-Index 在后台加载了一套默认配置(Default Configuration)。但在实际生产环境中,默认参数往往无法满足中文语境或特定业务的需求。本节我们将深入系统的“驾驶舱”,学习如何查看与修改核心参数。自 v0.10.0 版本起,Llama-Index 引入了全局配置对象 Settings,它是控制 RAG 行为的核心枢纽。

5.1 默认切分策略 (Chunking)

  • 默认配置:

    • 切分器: SentenceSplitter(句子切分器,优先保持句子完整)。
    • Chunk Size (块大小): 1024 Token。这意味着每个节点包含约 1024 个 token 的文本。
    • Chunk Overlap (块重叠): 20 Token。用于保持切片间的上下文连贯性。
from llama_index.core import Settings
# 查看默认值
print(f"默认块大小: {Settings.chunk_size}")
print(f"默认重叠块大小: {Settings.chunk_overlap}")
  • 修改后的效果: 减小 Chunk Size 会增加生成的节点(Node)总数,通常能提升检索的精准度(Precision),但可能会切断长距离的语义关联;增加 Overlap 可以减少上下文丢失的风险。

5.2 默认 Embedding 模型

  • 默认配置:

    • 模型厂商: OpenAI
    • 具体模型: text-embedding-ada-002 (1536 维)。
    • 注意: 这意味着哪怕你只是在本地跑索引,每处理一段文本都会向 OpenAI 发起 API 请求并产生费用。
  • 如何修改 (切换为本地开源模型): 对于中文用户,默认的 OpenAI 模型效果虽然不错,但网络延迟和成本是问题。我们通常会切换为 HuggingFace 上的中文模型(如 BGE 或 M3)。

# 1. 获取当前的 Embedding 模型对象
embed_model = Settings.embed_model

# 2. embedding模型名字
print(f"模型名称: {embed_model.model_name}")

5.3 默认存储机制 (Storage)

  • 默认配置:

    • 存储位置: 内存 (In-Memory)
    • 存储类: SimpleVectorStore
    • 风险: 这是一个临时存储。一旦你的 Python 脚本运行结束或程序崩溃,花费大量时间(和金钱)构建好的索引会直接消失
  • 如何修改 (持久化到磁盘): 我们需要显式调用 persist() 方法将内存中的索引“刷”到硬盘上。

# 1. 构建索引时 (默认在内存)
index = VectorStoreIndex.from_documents(documents)

# 2. 保存到磁盘 (会在当前目录生成一个 storage 文件夹)
index.storage_context.persist(persist_dir="./storage")
image-20251211181820357
# 3. 下次启动时加载 (无需重新 Embedding)
# 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)

5.4 默认检索参数 (Retrieval)

  • 默认配置:

    • Top-K: 2。即每次只找最相似的 2 个片段。
    • 后果: 对于简单问题(如“公司地址在哪”)够用了,但对于复杂问题(如“总结公司五大核心价值观”),2 个片段可能无法覆盖全貌,导致回答不完整。
  • 如何查看与修改: 这是在生成查询引擎时配置的,而不是在 Settings 里。

# 修改 Top-K 为 5,获取更多上下文
query_engine = index.as_query_engine(similarity_top_k=5)

5.5 默认提示词模板 (Prompt Template)

  • 默认配置:

    • 语言: 纯英文
    • 内容: Llama-Index 内置了一套通用的问答模板,大意是:“Context information is below... Given the context information... answer the question”。
    • 风险: 这是中文 RAG 开发中最大的隐形坑。如果您的文档是中文,问题是中文,但提示词是英文,模型(尤其是能力较弱的小模型)很容易出现“中英夹杂”的回复,或者回答语气生硬。
  • 如何查看底层结果: 提示词是在 QueryEngine 初始化时绑定的,我们可以通过 get_prompts() 方法把它“提取”出来看看。

prompts_dict = query_engine.get_prompts()

for key, prompt in prompts_dict.items():
print(f"=== 提示词类型: {key} ===")
# 打印模板的具体内容
print(prompt)
print("\n")

翻译如下:

=== 提示词类型: response_synthesizer:text_qa_template ===

metadata={'prompt_type': <PromptType.QUESTION_ANSWER: 'text_qa'>} template_vars=['context_str', 'query_str'] kwargs={} output_parser=None template_var_mappings={} function_mappings={} default_template=PromptTemplate(metadata={'prompt_type': <PromptType.QUESTION_ANSWER: 'text_qa'>}, template_vars=['context_str', 'query_str'], kwargs={}, output_parser=None, template_var_mappings=None, function_mappings=None, template='上下文信息如下。\n---------------------\n{context_str}\n---------------------\n给定上述上下文信息,不要使用先验知识,直接回答该查询。\n问题:{query_str}\n答案:') conditionals=[(<function is_chat_model at 0x00000198FECB36A0>, ChatPromptTemplate(metadata={'prompt_type': <PromptType.CUSTOM: 'custom'>}, template_vars=['context_str', 'query_str'], kwargs={}, output_parser=None, template_var_mappings=None, function_mappings=None, message_templates=[ChatMessage(role=<MessageRole.SYSTEM: 'system'>, additional_kwargs={}, blocks=[TextBlock(block_type='text', text="你是一个享誉全球的专家级问答系统。\n始终使用提供的上下文信息来回答查询,不要使用先验知识。\n需要遵循的一些规则:\n1. 绝不要在你的回答中直接引用给定的上下文(例如不要说‘根据上下文...’)。\n2. 避免使用像‘基于上下文...’或‘上下文信息显示...’或任何类似的表述。")]), ChatMessage(role=<MessageRole.USER: 'user'>, additional_kwargs={}, blocks=[TextBlock(block_type='text', text='上下文信息如下。\n---------------------\n{context_str}\n---------------------\n给定上述上下文信息,不要使用先验知识,直接回答该查询。\n问题:{query_str}\n答案:')])]))]

=== 提示词类型: response_synthesizer:refine_template ===

metadata={'prompt_type': <PromptType.REFINE: 'refine'>} template_vars=['query_str', 'existing_answer', 'context_msg'] kwargs={} output_parser=None template_var_mappings={} function_mappings={} default_template=PromptTemplate(metadata={'prompt_type': <PromptType.REFINE: 'refine'>}, template_vars=['query_str', 'existing_answer', 'context_msg'], kwargs={}, output_parser=None, template_var_mappings=None, function_mappings=None, template="原始问题如下:{query_str}\n我们提供了一个现有的答案:{existing_answer}\n我们有机会利用下方更多的上下文来完善现有答案(仅在需要时)。\n------------\n{context_msg}\n------------\n基于新的上下文,完善原始答案以更好地回答查询。如果上下文没有用,请返回原始答案。\n完善后的答案:") conditionals=[(<function is_chat_model at 0x00000198FECB36A0>, ChatPromptTemplate(metadata={'prompt_type': <PromptType.CUSTOM: 'custom'>}, template_vars=['context_msg', 'query_str', 'existing_answer'], kwargs={}, output_parser=None, template_var_mappings=None, function_mappings=None, message_templates=[ChatMessage(role=<MessageRole.USER: 'user'>, additional_kwargs={}, blocks=[TextBlock(block_type='text', text="你是一个专家级问答系统,在完善现有答案时严格按照两种模式运行:\n1. 重写:利用新上下文重写原始答案。\n2. 重复:如果新上下文没用,则重复原始答案。\n绝不要在你的回答中直接引用原始答案或上下文。\n如有疑问,直接重复原始答案即可。\n新上下文:{context_msg}\n问题:{query_str}\n原始答案:{existing_answer}\n新答案:")])]))]

5.6 默认响应合成策略 (Response Synthesis)

  • 默认配置:

    • 策略名称: compact (紧凑模式)
    • 工作原理: 这是为了节省 Token 和 API 调用次数而设计的默认策略。它会尝试将尽可能多的检索片段(Node)塞进一个 Prompt 窗口中发送给 LLM。如果片段太多塞不下,它才会分批处理。
    • 对比: 早期版本或其他框架可能默认使用 refine(精炼模式,串行处理,慢但细致)或 tree_summarize(树状总结)。compact 是速度与成本的最佳平衡点。
  • 如何查看底层结果: 合成策略封装在引擎的合成器(Synthesizer)内部。我们可以通过访问受保护属性来验证它。

synth = query_engine._response_synthesizer
print(f"当前合成模式: {synth}")
  • Llama-Index基础默认参数
核心组件默认参数 (Default)潜在风险/问题推荐优化方向 (Optimization)
切分 (Chunking)Size: 1024, Overlap: 200粒度较粗,细节丢失中文场景建议 Size: 256-512
向量 (Embedding)OpenAI (ada-002)产生费用,依赖网络切换为 BGE/M3 等本地开源模型
存储 (Storage)内存 (RAM)关机即失,无法持久化必须使用 persist 保存到磁盘
检索 (Retrieval)Top-k: 2上下文覆盖不足根据文档长度调整为 3-5
提示词 (Prompt)纯英文模板回答中英夹杂,指令遵循差必须替换为中文 Prompt 模板
合成 (Synthesis)Compact (紧凑模式)对长文档总结能力一般总结类任务改用 tree_summarize

6.Llama-Index RAG系统核心组建与通用RAG流程

  通过前面的实操,我们已经跑通了一个基础的 RAG Demo。现在,让我们跳出代码细节,站在系统架构的高度,俯瞰 Llama-Index 是如何将一个 RAG 系统拆解为三个标准化的工业阶段:数据装载 (Loading)索引构建 (Indexing)查询执行 (Querying)

  这一架构图景将帮助大家理解 Llama-Index 的核心设计哲学:将非结构化数据转化为结构化知识的流水线。

第一阶段:数据装载 (Loading) —— 连接真实世界

  • 定义:   装载阶段是 RAG 系统的“入口”。它的核心任务是解决**“数据孤岛”**问题,将散落在磁盘文件、云端文档、数据库或 API 中的原始数据,统一提取并转换为 Llama-Index 能够理解的标准格式。

  • 核心对象:Document (文档)   这是该阶段的产物。Document 是一个数据容器,它不仅包含原始文本(Text),还承载了关键的属性信息(Metadata,如文件名、页码、作者)。此时的数据尚未被切分,仍保持原始形态。

  • 核心工具:

    • SimpleDirectoryReader: 内置的最基础加载器,适用于读取本地文件夹中的文件(支持 .txt, .pdf, .docx, .ppt 等)。
    • LlamaHub (生态连接器): 这是 Llama-Index 的核心护城河。它提供了数百种社区维护的加载器,能够连接 Notion、Discord、YouTube、SQL 数据库甚至 Google Drive。这意味着您不仅能读取本地文件,还能直接对接企业的 SaaS 数据资产。
image-20251211184006380

第二阶段:索引构建 (Indexing) —— 知识的原子化与结构化

  • 定义: 这是 RAG 系统的“加工厂”。在此阶段,系统需要将粗粒度的 Document 进行精细化处理,使其适合数学计算和检索。这个过程通常包含切分 (Chunking)向量化 (Embedding)存储 (Storing)

  • 核心对象:Node (节点) 这是 Llama-Index 中的最小数据单元。

    • 概念梳理: 一个 Document 会被切分成多个 NodeNode 不仅是一段文本切片,它还保留了指向原文档的引用(Ref_ID)以及与前后节点的逻辑关系(Prev/Next Node),这是实现高质量上下文检索的基础。
  • 切分策略 (Splitters): Llama-Index 提供了多种针对不同数据类型的切分器,以保证语义的完整性:

    • SentenceSplitter (默认): 按句子边界切分,适合通用文本。
    • CodeSplitter: 专为代码设计,支持 Python/Java 等语法树切分。
    • MarkdownSplitter: 按标题层级(H1, H2)切分,适合技术文档。
  • 存储与扩展性 (Vector Stores): 虽然默认使用内存存储,但 Llama-Index 具有极强的可扩展性。它允许通过统一接口(StorageContext)组装各类主流向量数据库,如 Chroma, Faiss, Pinecone, Milvus, Weaviate 等。这使得系统能够轻松从 Demo 扩展至亿级数据规模的生产环境。

image-20251211184208978

第三阶段:查询执行 (Querying) —— 智能交互与合成

  • 定义: 这是 RAG 系统的“出口”。它的目标是理解用户的自然语言问题,从索引中精准找到答案,并组织语言进行回复。

  • 核心组件:Query Engine (查询引擎) 它是检索器(Retriever)和合成器(Response Synthesizer)的封装体。

  • 关键概念与拓展:

    • 检索 (Retrieval): 除了基础的“Top-K 向量相似度搜索”,Llama-Index 还支持关键词搜索(BM25)、混合搜索(Hybrid Search)以及递归检索(Recursive Retrieval)。
    • 后处理 (Post-Processing): 在检索后、生成前,引入重排序(Rerank)模型或元数据过滤器,剔除不相关内容。
    • 响应合成 (Synthesis): 决定如何利用检索到的信息。除了默认的“拼接(Compact)”,还支持“分步精炼(Refine)”和“树状总结(Tree Summarize)”等高级策略。
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
documents = SimpleDirectoryReader("data").load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
documents
index
  • 持久化存储
# Save the index
index.storage_context.persist("storage")

# Later, load the index
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)
query_engine = index.as_query_engine()
  • RAG管道构建

LLM(生命周期模型)基于海量数据进行训练,但并未基于您的数据进行训练。检索增强生成(RAG)通过将您的数据添加到 LLM 已可访问的数据中来解决这个问题。您将在本文档中频繁看到 RAG 的相关内容。查询引擎、聊天引擎和代理通常使用 RAG 来完成其任务。

在 RAG 中,您的数据会被加载并准备好以供查询,即“建立索引”。用户查询会作用于索引,索引会将数据筛选到最相关的上下文。然后,该上下文和您的查询以及提示信息会发送到 LLM,LLM 会提供响应。

即使你正在构建的是聊天机器人或代理,你也需要了解 RAG 技术,以便将数据导入到你的应用程序中。

RAG流程包含五个关键阶段,而这些阶段又会成为您构建的大多数大型应用程序的组成部分。这五个阶段分别是:

  • 加载:这指的是将数据从其存储位置(无论是文本文件、PDF、其他网站、数据库还是 API)导入到您的工作流程中。LlamaHub提供数百种连接器供您选择。

  • 索引:这意味着创建一种数据结构,以便查询数据。对于LLM(语言学习模型)而言,这几乎总是意味着创建vector embeddings数据含义的数值表示,以及其他多种元数据策略,以便轻松准确地找到与上下文相关的数据。

  • 存储:一旦数据被索引,您几乎总是希望存储索引以及其他元数据,以避免重新索引。

  • 查询:对于任何给定的索引策略,您可以使用 LLM 和 LlamaIndex 数据结构进行查询,包括子查询、多步骤查询和混合策略。

  • 评估:任何流程的关键步骤之一就是检查其相对于其他策略的有效性,或者在进行更改时进行评估。评估提供客观的衡量标准,用于衡量您对查询的响应的准确性、可靠性和速度。

  • 装载阶段

节点和文档(Nodes and Documents):Document是包含任何数据源的容器,例如 PDF 文件、API 输出或从数据库中检索的数据。Node是 LlamaIndex 中的数据最小单元,代表数据源的一个“数据块”Document。节点具有元数据,用于关联它们所在的文档以及其他节点。

连接器(Connectors):数据连接器(通常称为Reader)将来自不同数据源和数据格式的数据导入到Documents和 中Nodes。

  • 索引阶段

索引(Indexes):导入数据后,LlamaIndex 会帮助您将数据建立索引,使其结构易于检索。这通常涉及生成索引vector embeddings,这些索引存储在一个名为“索引库”的专用数据库中vector store。索引还可以存储各种关于数据的元数据。

嵌入(Embeddings):LLM 生成称为嵌入的数值数据表示embeddings。在筛选数据相关性时,LlamaIndex 会将查询转换为嵌入,而您的向量存储将找到与查询的嵌入在数值上相似的数据。

  • 查询阶段

检索器(Retrievers):检索器定义了如何根据查询从索引中高效地检索相关上下文。检索策略是决定检索数据的相关性和效率的关键。

路由器(Routers):路由器决定使用哪个检索器从知识库中检索相关上下文。更具体地说,路由器RouterRetriever 类负责选择一个或多个候选检索器来执行查询。它们使用选择器,根据每个候选检索器的元数据和查询语句来选择最佳选项。

节点后处理器(Node Postprocessors):节点后处理器接收一组检索到的节点,并对其应用转换、过滤或重新排序逻辑。

响应合成器(Response Synthesizers):响应合成器使用用户查询和一组给定的检索文本块,从 LLM 生成响应。

  • 数据加载

在您选择的机器学习模型能够处理数据之前,您首先需要对数据进行处理和加载。这与机器学习领域的数据清洗/特征工程流程,或者传统数据环境中的 ETL 流程类似。

该数据摄取流程通常包含三个主要阶段:

加载数据 转换数据 数据索引和存储

Loaders

在您选择的 LLM 能够处理您的数据之前,您需要先加载数据。LlamaIndex 通过数据连接器(也称为数据对象)来实现这一点Reader。数据连接器从不同的数据源提取数据,并将其格式化为Document数据对象。数据对象Document是数据(目前为文本,未来将支持图像和音频)及其元数据的集合。

使用 SimpleDirectoryReader 加载

我们最易用的阅读器是 SimpleDirectoryReader,它可以将指定目录中的每个文件转换为文档。它内置于 LlamaIndex 中,可以读取多种格式,包括 Markdown、PDF、Word 文档、PowerPoint 演示文稿、图像、音频和视频。

from llama_index.core import SimpleDirectoryReader

documents = SimpleDirectoryReader("./data").load_data()

LlamaHub reader

由于获取数据的方式多种多样,因此并非所有数据都已内置。您需要从我们的数据连接器注册表LlamaHub下载这些数据连接器。

在这个例子中,LlamaIndex 下载并安装了名为DatabaseReader 的连接器,该连接器针对 SQL 数据库运行查询,并将结果的每一行作为Document:

from llama_index.core import download_loader

from llama_index.readers.database import DatabaseReader

reader = DatabaseReader(
scheme=os.getenv("DB_SCHEME"),
host=os.getenv("DB_HOST"),
port=os.getenv("DB_PORT"),
user=os.getenv("DB_USER"),
password=os.getenv("DB_PASS"),
dbname=os.getenv("DB_NAME"),
)

query = "SELECT * FROM users"
documents = reader.load_data(query=query)

直接创建文档

除了使用加载器之外,您还可以直接使用文档。

from llama_index.core import Document

doc = Document(text="text")

Transformations

数据加载完成后,需要对其进行处理和转换,然后才能将其存入存储系统。这些转换包括分块、提取元数据以及嵌入各个数据块。这样做是为了确保LLM能够检索并充分利用数据。

转换的输入/输出是Node对象(aDocument是 a 的子类Node)。转换也可以堆叠和重新排序。

我们有用于转换文档的高级 API 和低级 API。

documents = SimpleDirectoryReader("data").load_data()
len(documents)
documents[2]
index = VectorStoreIndex.from_documents(documents)
VectorStoreIndex?
query_engine = index.as_query_engine()
from llama_index.core import Settings

# 默认的全局切分大小
print(f"默认 Chunk Size: {Settings.chunk_size}")
# 输出: 1024

# 默认的全局重叠大小
print(f"默认 Chunk Overlap: {Settings.chunk_overlap}")
# 输出: 20
print(Settings.node_parser)
print(Settings.embed_model)
# 2. 获取所有节点 (它是一个字典,key是id,value是Node对象)
# 我们把它转成列表方便查看
all_nodes = list(index.docstore.docs.values())

print(f"一共切分出了 {len(all_nodes)} 个节点")
# 3. 抽查第一个节点看看长啥样
first_node = all_nodes[0]

print("=== 节点 ID ===")
print(first_node.node_id)

print("\n=== 节点文本 (切片内容) ===")
print(first_node.text) # <--- 这就是喂给 Embedding 的实际内容

print("\n=== 节点元数据 ===")
print(first_node.metadata) # <--- 继承自 Document 的 metadata

print("\n=== 节点关系 (重点) ===")
# 这里能看到它指向的“上一块”和“下一块”是谁
print(first_node.relationships)
response = query_engine.query("DeepSeek V3.2 的核心特点是什么?")
response.response
index?
documents = SimpleDirectoryReader("data").load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader

documents = SimpleDirectoryReader("data").load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
response = query_engine.query("Some question about the data should go here")
print(response)