
在前面的文章我们对langchain和RAG都做过深入的探讨,检索增强生成(RAG)是解决模型核心痛点的关键技术,它能让大模型基于本地私有数据生成精准回答,彻底规避 幻觉问题,同时满足数据本地化、合规性要求。
而LlamaIndex是专为 RAG 场景设计的轻量级 Python 框架,定位为大模型的外部数据中间件,核心能力是高效连接本地数据与大模型。相较于 LangChain 等全场景框架,LlamaIndex 更聚焦 RAG 流程的轻量化实现,无需复杂配置即可完成 “文档加载→向量索引→智能问答” 的全闭环,且深度兼容 Qwen、Llama、Baichuan 等开源大模型,支持纯 CPU 本地化部署,是个人开发者和中小企业落地 RAG 应用的首选工具。
今天我们将从核心概念、技术架构、实战落地三个维度,由浅入深拆解 LlamaIndex 的使用方法,配套可直接运行的代码示例,基于本地的 paraphrase-MiniLM-L6-v2 嵌入模型和 Qwen1.5-1.8B-Chat 大模型,并补充关键技术细节与可视化流程图,覆盖从原理到实践的全维度知识。
LlamaIndex 的核心价值在于将非结构化本地数据与大语言模型高效连接,其底层逻辑围绕一组核心概念构建,这些概念构成了 RAG(检索增强生成)流程的完整闭环。以下对每个核心概念进行逐维度、精细化的解析:
Document 是 LlamaIndex 对原始数据源的标准化封装,是整个 RAG 流程的数据入口。它并非仅指传统的文本文档,而是涵盖所有可被加载的结构化 / 非结构化数据的抽象载体,无论是本地 TXT/PDF/Markdown 文件、数据库中的单行数据、网页爬取的文本,还是 API 返回的结构化信息,加载后都会被统一封装为 Document 对象。
每个 Document 对象包含以下关键属性(决定了数据的可用性与溯源性):
from llama_index.core import SimpleDirectoryReader
# 加载目录下所有文件,生成Document列表
documents = SimpleDirectoryReader("./docs", encoding="utf-8").load_data()
# 查看第一个Document的属性
print(f"文档名称:{documents[0].metadata['file_name']}")
print(f"文档内容长度:{len(documents[0].text)}字符")Node 是 LlamaIndex 对 Document 的最小可检索单元,也被称为文本块。它是将原始长文档切分后生成的子文本片段,是 RAG 流程中向量化和检索的核心对象,长文档直接向量化会丢失局部语义(如一个 10000 字符的文档,其向量无法精准表征某一段落的含义),而将文档切分为小尺寸的 Node 后,每个 Node 的向量能精准对应局部语义,大幅提升检索精度。
LlamaIndex 提供 SentenceSplitter(默认)、TokenTextSplitter 等 Node 切分器,核心参数决定切分效果:
2.4.1 chunk_size
2.3.2 chunk_overlap
2.3.3 separator
from llama_index.core.node_parser import SentenceSplitter
from llama_index.core import SimpleDirectoryReader
# 1. 加载原始Document
documents = SimpleDirectoryReader("./docs", encoding="utf-8").load_data()
# 2. 自定义切分器(适配中文Markdown文档)
splitter = SentenceSplitter(
chunk_size=512, # 单个Node 512字符
chunk_overlap=50, # 重叠50字符
separator="\n## " # 按Markdown二级标题切分
)
# 3. 切分Document为Node列表
nodes = splitter.get_nodes_from_documents(documents)
# 查看Node属性
print(f"原始Document数量:{len(documents)}")
print(f"切分后Node数量:{len(nodes)}")
print(f"第一个Node的文本:{nodes[0].text[:100]}...")
print(f"第一个Node的来源文档:{nodes[0].metadata['file_name']}")
print(f"Node在原文档中的位置:{nodes[0].metadata['start_char_idx']}-{nodes[0].metadata['end_char_idx']}")Index 是 LlamaIndex 对Node 向量的结构化存储与检索引擎,是连接 “文本数据” 与 “相似度检索” 的核心桥梁。其本质是:将所有 Node 的文本内容通过嵌入模型转为高维向量,再将 “向量→Node” 的映射关系存储在特定的数据结构中,当用户提问时,能快速检索出与问题向量最相似的 Node 集合。
LlamaIndex 提供多种索引类型,适配不同场景,其中 VectorStoreIndex 是最基础、最常用的类型:
3.3.1 VectorStoreIndex
3.3.2 KeywordIndex
3.3.3 TreeIndex
3.3.4 ListIndex
3.3.5 KnowledgeGraphIndex
3.4.1 核心原理
3.4.2 构建与使用
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core.node_parser import SentenceSplitter
# 1. 加载Document并切分为Node
documents = SimpleDirectoryReader("./docs", encoding="utf-8").load_data()
splitter = SentenceSplitter(chunk_size=512, chunk_overlap=50)
nodes = splitter.get_nodes_from_documents(documents)
# 2. 构建VectorStoreIndex(基于Node向量)
index = VectorStoreIndex(nodes)
# 3. 索引持久化(保存到磁盘,避免重复构建)
index.storage_context.persist(persist_dir="./index_cache")
# 4. 加载缓存索引(后续运行直接加载)
from llama_index.core import StorageContext, load_index_from_storage
storage_context = StorageContext.from_defaults(persist_dir="./index_cache")
index = load_index_from_storage(storage_context)3.4.3 核心参数调优
Query Engine 是 LlamaIndex 封装的端到端问答引擎,是连接Index(索引)与 大模型 的核心桥梁。它将 “问题检索→提示词拼接→大模型生成→回答格式化” 的全流程封装为统一接口,用户只需调用 query() 方法即可完成从 “输入问题” 到 “获取回答” 的闭环,无需手动处理中间环节。
Query Engine 的内部运行逻辑是 RAG 流程的核心,可拆解为 6 个步骤:

提示词拼接参考示例:
基于以下信息回答问题: 1. 智能客服系统基于LlamaIndex框架开发,支持纯CPU运行,内存占用≤6GB; 2. 系统采用的嵌入模型为paraphrase-MiniLM-L6-v2,大小80MB; 问题:智能客服系统的内存占用要求是多少?
4.4.1 similarity_top_k
4.4.2 response_mode
4.4.3 llm
4.4.4 verbose
4.4.5 streaming
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
# 1. 构建索引
documents = SimpleDirectoryReader("./docs", encoding="utf-8").load_data()
index = VectorStoreIndex.from_documents(documents)
# 2. 创建查询引擎(自定义参数)
query_engine = index.as_query_engine(
similarity_top_k=3, # 检索Top-3 Node
response_mode="compact", # 紧凑回答模式
verbose=True, # 显示检索过程
streaming=False # 非流式返回
)
# 3. 执行问答
response = query_engine.query("智能客服系统的核心功能有哪些?")
# 4. 查看结果
print(f"最终回答:{response}")
# 查看回答溯源(对应的Node)
print("\n回答来源:")
for node in response.source_nodes:
print(f" 相似度:{node.score:.2f} | 文本片段:{node.node.text[:100]}...")Retriever 是 LlamaIndex 中从 Index 中检索相关 Node的核心组件,是 Query Engine 的 “检索子模块”。它的唯一职责是:接收用户问题的向量表示,从 Index 中筛选出与问题语义最相似的 Node 集合,为后续的提示词拼接提供素材。
Retriever 与 Index是配套使用的关系,不同类型的 Index 对应不同的 Retriever,如 VectorStoreIndex 对应 VectorIndexRetriever,确保检索逻辑与索引存储结构匹配。
检索器类型 | 适配索引类型 | 检索原理 | 适用场景 |
|---|---|---|---|
VectorIndexRetriever | VectorStoreIndex | 余弦相似度匹配向量 | 通用语义检索场景(90%+ 的 RAG 场景) |
KeywordTableRetriever | KeywordIndex | 关键词匹配(倒排索引) | 精准关键词检索(如产品编号、文档名称) |
TreeRetriever | TreeIndex | 树形结构逐层检索 | 长文档摘要、结构化回答场景 |
ListRetriever | ListIndex | 线性遍历 Node 匹配 | 小批量 Node(<100)、简单检索场景 |
BM25Retriever | 任意 Index | BM25 算法(传统信息检索) | 补充向量检索,提升关键词匹配精度 |
5.4.1 默认 Retriever 使用(通过 Query Engine 间接调用)
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
# 1. 构建索引
documents = SimpleDirectoryReader("./docs", encoding="utf-8").load_data()
index = VectorStoreIndex.from_documents(documents)
# 2. 创建Query Engine时,默认使用VectorIndexRetriever
query_engine = index.as_query_engine(similarity_top_k=3) # Retriever的top_k参数5.4.2 自定义 Retriever(灵活适配场景)
from llama_index.core.retrievers import VectorIndexRetriever
from llama_index.core.query_engine import RetrieverQueryEngine
# 1. 构建索引
documents = SimpleDirectoryReader("./docs", encoding="utf-8").load_data()
index = VectorStoreIndex.from_documents(documents)
# 2. 自定义Retriever(指定top_k和索引)
retriever = VectorIndexRetriever(
index=index,
similarity_top_k=3, # 检索Top-3 Node
vector_store_query_mode="cosine" # 检索模式:余弦相似度
)
# 3. 基于自定义Retriever创建Query Engine
query_engine = RetrieverQueryEngine.from_args(
retriever=retriever,
response_mode="compact"
)
# 4. 执行检索(手动调用Retriever,无需Query Engine)
nodes = retriever.retrieve("智能客服系统的内存占用要求是多少?")
print(f"检索到的Node数量:{len(nodes)}")
for node in nodes:
print(f"相似度:{node.score:.2f} | 文本:{node.text[:100]}...")Response Synthesis(回答合成)是 LlamaIndex 中将检索到的 Node 文本与用户问题结合,生成最终回答的核心环节,是 Query Engine 的 “生成子模块”。它的核心职责是:将检索到的相关 Node 文本合理组织为提示词,传入大模型并格式化输出结果,确保回答既基于检索到的真实数据,又符合用户的提问意图。
LlamaIndex 提供多种合成模式,适配不同的检索结果和提问场景,核心模式的对比与适用场景如下:
6.2.1 compact(默认)
6.2.2 tree_summarize
6.2.3 refine
6.2.4 simple_summarize
6.2.5 generation
6.2.6 accumulate
6.3.1 提示词构建:
核心逻辑是 “问题 + 检索到的 Node 文本 + 指令”,示例提示词模板:
请严格基于以下提供的信息回答问题,不要使用外部知识。如果信息不足,请回答“未检索到相关信息”。 提供的信息: {context} # 检索到的Node文本,多个Node用换行分隔 问题:{query} 回答:
其中,{context} 为检索到的 Top-K Node 文本拼接结果,{query} 为用户问题。
6.3.2 大模型调用:
将构建好的提示词传入大模型(如 Qwen1.5-1.8B-Chat),生成原始回答,示例:
原始回答: 请严格基于以下提供的信息回答问题,不要使用外部知识。如果信息不足,请回答“未检索到相关信息”。 提供的信息: 1. 智能客服系统基于LlamaIndex框架开发,支持纯CPU运行,内存占用≤6GB; 2. 系统采用的嵌入模型为paraphrase-MiniLM-L6-v2,大小80MB; 问题:智能客服系统的内存占用要求是多少? 回答:智能客服系统的内存占用≤6GB。
6.3.3 回答格式化:
剔除提示词中的冗余内容(如 “提供的信息”“请严格基于以下信息” 等),仅保留核心回答(“智能客服系统的内存占用≤6GB。”)。
6.3.4 结果封装:
将格式化后的回答封装为 Response 对象,包含以下核心属性:
对于个性化的合成需求(如自定义提示词模板、多轮优化回答),可通过继承 BaseSynthesizer 实现自定义合成器:
from llama_index.core.response_synthesizers import BaseSynthesizer, ResponseTuple
from llama_index.core.llms import LLM
from typing import List
from llama_index.core.schema import NodeWithScore
class CustomSynthesizer(BaseSynthesizer):
def __init__(self, llm: LLM):
self.llm = llm
def get_response(self, query: str, nodes: List[NodeWithScore]) -> ResponseTuple:
# 1. 自定义提示词模板
context = "\n".join([f"{i+1}. {node.text}" for i, node in enumerate(nodes)])
prompt = f"""
请以“专业、简洁”的风格回答以下问题,回答必须基于以下信息:
信息:
{context}
问题:{query}
专业回答:
"""
# 2. 调用大模型生成回答
response = self.llm.complete(prompt)
# 3. 封装结果
return ResponseTuple(response.text, nodes)
# 使用自定义合成器创建Query Engine
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core.retrievers import VectorIndexRetriever
# 1. 构建索引和Retriever
documents = SimpleDirectoryReader("./docs", encoding="utf-8").load_data()
index = VectorStoreIndex.from_documents(documents)
retriever = VectorIndexRetriever(index=index, similarity_top_k=3)
# 2. 加载自定义LLM
from custom_llm import LocalQwenLLM # 自定义Qwen LLM类
llm = LocalQwenLLM("D:\\modelscope\\hub\\qwen\\Qwen1___5-1___8B-Chat")
# 3. 创建自定义合成器
custom_synthesizer = CustomSynthesizer(llm=llm)
# 4. 构建Query Engine
query_engine = RetrieverQueryEngine(
retriever=retriever,
response_synthesizer=custom_synthesizer
)
# 5. 执行问答
response = query_engine.query("智能客服系统的核心功能有哪些?")
print(f"自定义合成回答:{response}")LlamaIndex支持自定义嵌入模型和LLM,我们可以通过相应的类来集成本地模型。这里我们使用sentence-transformers的模型作为嵌入模型,使用Qwen1.5-1.8B-Chat作为大模型。
执行步骤:
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.huggingface import HuggingFaceLLM
from llama_index.core.prompts import PromptTemplate
from modelscope import snapshot_download
import torch
# 1. 下载或加载本地模型
model_id = "qwen/Qwen1.5-1.8B-Chat"
cache_dir = "D:\\modelscope\\hub"
local_model_path = snapshot_download(model_id, cache_dir=cache_dir)
# 2. 配置本地嵌入模型
embed_model_path = "D:/modelscope/hub/models/sentence-transformers/paraphrase-MiniLM-L6-v2"
Settings.embed_model = HuggingFaceEmbedding(
model_name=embed_model_path,
device="cuda" if torch.cuda.is_available() else "cpu"
)
# 3. 配置本地大模型 - 修正版本
system_prompt = """你是一个有帮助的AI助手。请根据提供的上下文信息回答问题。如果无法从上下文中找到答案,请诚实地说明。"""
query_wrapper_prompt = PromptTemplate(
"下面是一个问题。\n"
"---------------------\n"
"{query_str}\n"
"---------------------\n"
"请根据你的知识回答这个问题:"
)
# 方法1: 使用正确的参数配置
Settings.llm = HuggingFaceLLM(
model_name=local_model_path,
tokenizer_name=local_model_path,
# 将 device_map 移到 model_kwargs 外面
device_map="auto",
model_kwargs={
"torch_dtype": torch.float16 if torch.cuda.is_available() else torch.float32,
"cache_dir": cache_dir,
},
generate_kwargs={
"temperature": 0.1,
"top_p": 0.95,
"do_sample": True,
},
system_prompt=system_prompt,
query_wrapper_prompt=query_wrapper_prompt,
)
# 4. 加载文档
try:
documents = SimpleDirectoryReader("./data").load_data()
print(f"成功加载 {len(documents)} 个文档")
except Exception as e:
print(f"文档加载失败: {e}")
print("请确保 ./data 目录存在且包含文档文件")
print("正在创建示例文档...")
# 创建一个示例文本文件
import os
os.makedirs("./data", exist_ok=True)
with open("./data/example.txt", "w", encoding="utf-8") as f:
f.write("""LlamaIndex 是一个用于构建检索增强生成(RAG)应用的数据框架。
它允许你连接自定义数据源到大语言模型。
主要功能包括:
1. 数据加载和索引
2. 向量搜索
3. 查询引擎
4. 对话系统""")
documents = SimpleDirectoryReader("./data").load_data()
print("已创建并加载示例文档")
# 5. 创建向量索引
print("正在创建向量索引...")
index = VectorStoreIndex.from_documents(
documents,
embed_model=Settings.embed_model
)
# 6. 创建查询引擎
query_engine = index.as_query_engine(
llm=Settings.llm,
similarity_top_k=3
)
# 7. 测试查询
print("\n" + "="*50)
print("LlamaIndex 本地模型示例 - 测试查询")
print("="*50)
# 简单的测试查询
try:
response = query_engine.query("LlamaIndex 是什么?")
print(f"问题: LlamaIndex 是什么?")
print(f"回答: {response}")
except Exception as e:
print(f"查询失败: {e}")
# 8. 交互式查询
print("\n" + "="*50)
print("进入交互式查询模式 (输入 'quit' 或 'exit' 退出)")
print("="*50)
while True:
try:
user_query = input("\n请输入问题: ").strip()
if user_query.lower() in ['quit', 'exit', 'q']:
print("再见!")
break
if not user_query:
continue
response = query_engine.query(user_query)
print(f"\n回答: {response}")
except KeyboardInterrupt:
print("\n\n程序被中断")
break
except Exception as e:
print(f"查询出错: {e}")输出参考:
成功加载 1 个文档 正在创建向量索引... ================================================== LlamaIndex 本地模型示例 - 测试查询 ================================================== 问题: LlamaIndex 是什么? 回答: LlamaIndex 是一个用于构建检索增强生成(RAG)应用的数据框架,它允许用户连接自定义数据源到大语言模型,并提供以下 主要功能: 1. 数据加载和索引 2. 向量搜索 3. 查询引擎 4. 对话系统 其中,LlamaIndex 的具体功能包括: 1. 数据加载和索引:用户可以将来自各种来源(如数据库、API、文件系统等)的数据导入到LlamaIndex 中进行存储和索引。这 使得模型能够快速地从这些数据中提取有用的信息,从而提高检索性能和查询效率。 2. 向量搜索:LlamaIndex 提供了一种高效的方法来搜索和查找向量数据。通过使用词袋模型或TF-IDF 等方法,模型能够识别出 与特定关键词相关的向量,并在搜索过程中优先匹配这些向量。这种搜索方式不仅适用于文本数据,也适用于图像、音频、视频等 多种类型的数据。 3. 查询引擎:LlamaIndex 为用户提供了一个强大的查询引擎,使他们能够基于预定义的查询条件(如关键词、实体、关系等)对 模型中的向量进行查询。这个引擎还支持模糊查询、 ================================================== 进入交互式查询模式 (输入 'quit' 或 'exit' 退出) ================================================== 请输入问题: 公司的年假政策是怎样的? 回答: 公司规定员工每年享受多少天年假?具体为: 1-3年员工享有5天年假,3-5年员工享有10天年假。所有员工都需要遵守保密协议,不得泄露公司商业秘密和技术信息。 请输入问题: 智能客服系统有哪些功能 回答: 智能客服系统的主要功能包括:... 请输入问题: 2024年AI发展趋势是什么 回答: 2024年,生成式AI技术将继续快速发展,多模态能力成为重点。企业应用AI的主要方向包括智能客服、内容生成、数据分析 等。深度学习和神经网络技术不断突破,大模型参数规模持续增长。具体来说,以下几点是2024年AI发展趋势:...
基于LlamaIndex框架构建的本地RAG系统实现了从用户提问到智能回答的完整工作流。系统首先将用户输入的自然语言问题通过Sentence-Transformers嵌入模型向量化,随后调用Retriever组件从预先构建的向量索引中检索最相关的Top-K个文档节点。检索到的节点文本与原始问题经过精心设计的提示词模板进行智能拼接,形成完整的上下文输入。
本地部署的Qwen1.5大模型基于该上下文生成初步回答,最后经过后处理模块剔除冗余信息、格式化输出,向用户返回精准、可溯源的最终答案。整个流程充分体现了检索增强生成技术的核心优势,在保证数据隐私的前提下,有效扩展了大语言模型的知识边界,为构建企业级智能问答系统提供了可靠的技术路径。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。