LlamaIndex 全面技术详解
构建生产级RAG应用的企业级框架
目录
- 一、LlamaIndex 概述
- 二、核心架构设计
- 三、核心组件详解
- 四、索引策略与选择
- 五、检索与查询引擎
- 六、数据连接器与文档处理
- 七、高级检索技术
- 八、查询处理与后处理
- 九、存储与持久化
- 十、性能优化与调优
- 十一、评估与监控
- 十二、与LangChain对比
- 十三、Java生态支持
- 十四、生产部署最佳实践
- 十五、常见问题与解决方案
一、LlamaIndex 概述
1.1 什么是LlamaIndex
LlamaIndex(前身为GPT Index)是一个专门为LLM应用设计的数据框架,核心解决私有数据接入LLM的问题。
核心定位:
- 数据连接层:连接私有数据(文档、数据库、API)与LLM
- 索引构建层:将非结构化/结构化数据转换为LLM可高效检索的格式
- 检索增强层:提供先进的检索策略,为LLM提供相关上下文
与LangChain的区别:
LangChain: LLM应用开发全栈框架(Agent、Chain、Memory等)
↓
LlamaIndex: 专注数据接入与检索(RAG专家)
1.2 核心价值主张
- 简单性:5行代码完成RAG管道搭建
- 灵活性:可组合组件,自定义每个环节
- 性能:先进的检索算法,生产级性能
- 可扩展:插件化架构,支持任意数据源/向量库
- 生产就绪:监控、缓存、异步、错误处理
1.3 适用场景
- 文档问答系统:公司知识库、客服FAQ
- 数据分析助手:自然语言查询数据库
- 研究助手:论文/专利检索与总结
- 法律文件审查:合同条款检索
- 代码搜索:代码库语义搜索
- 多文档摘要:自动化报告生成
1.4 不支持场景
- 通用Agent框架:不是替代LangChain,可配合使用
- 复杂工作流编排:LangChain更适合多步骤推理
- 模型托管:不提供模型服务,只提供数据服务
- 实时流式处理:更适合批处理、近实时
二、核心架构设计
2.1 设计哲学
“数据先行”(Data-First):
原始数据 → 解析 → 分块 → 向量化 → 索引 → 检索 → 上下文组装 → LLM生成
每个环节都可自定义替换。
2.2 架构层次
┌─────────────────────────────────────────────────────────────┐
│ Application Layer │
│ (QueryEngine / ChatEngine / Agent / Retriever) │
└───────────────────────────┬─────────────────────────────────┘
│
┌───────────────────────────┴─────────────────────────────────┐
│ Query Pipeline │
│ Query → Query Transform → Retrieval → Response Synthesis │
└───────────────────────────┬─────────────────────────────────┘
│
┌───────────────────────────┴─────────────────────────────────┐
│ Index Layer │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ Vector │ │Keyword │ │ Tree │ │ Graph │ │
│ │ Store │ │ Index │ │ Index │ │ Index │ │
│ └──────────┘ └──────────┘ └──────────┘ └─────────────┘ │
└───────────────────────────┬─────────────────────────────────┘
│
┌───────────────────────────┴─────────────────────────────────┐
│ Data Layer │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ Document│ │ Node │ │Embedding │ │ Storage │ │
│ │ Reader │ │ Splitter│ │ Model │ │ Context │ │
│ └──────────┘ └──────────┘ └──────────┘ └────────────┘ │
└───────────────────────────┬─────────────────────────────────┘
│
┌───────────────────────────┴─────────────────────────────────┐
│ Data Sources │
│ (Files, APIs, DB, Websites, SaaS, etc.) │
└───────────────────────────────────────────────────────────┘
2.3 关键抽象
- Document:原始数据单元(文本、metadata、source)
- Node:Document分块后的单元,含embedding、relationship
- Index:组织Node的数据结构(VectorIndex、TreeIndex等)
- Retriever:从Index检索相关Node
- QueryEngine:Retriever + ResponseSynthesis
- StorageContext:管理文档、索引、向量的持久化存储
三、核心组件详解
3.1 DocumentReader(文档读取器)
作用:从各种数据源读取原始数据,转换为Document对象
内置Reader:
- 文件系统:
SimpleDirectoryReader:读取目录下所有文件(txt、md、pdf、docx等)PDFReader:解析PDF(支持扫描OCR)DocxReader:Word文档PptxReader:PowerPointImageReader:OCR识别图片文字IPYNBReader:Jupyter NotebookUnstructuredReader:通用解析器(支持多种格式)
- 网页:
BeautifulSoupWebReader:静态网页SeleniumWebReader:动态渲染页面(JavaScript)ReadabilityWebReader:只读文章正文
- 数据库:
SQLDatabaseReader:执行SQL查询SimpleMongoReader:MongoDB查询
- API:
RssReader:RSS订阅GoogleDocsReader:Google DocsNotionReader:Notion页面
- 云存储:
S3Reader:AWS S3AzureBlobStorageReader:Azure BlobGCSReader:Google Cloud Storage
- 自定义:实现
BaseReader接口
示例:
from llama_index import SimpleDirectoryReader
documents = SimpleDirectoryReader(
input_dir="./data",
recursive=True,
exclude=["*.tmp"]
).load_data()
3.2 NodeParser(节点分块器)
作用:将Document拆分为更小的Node(Chunk),每个Node独立embedding和检索
内置分块策略:
3.2.1 按大小分块
SentenceSplitter:按句子分割(最常用)chunk_size=512(字符数或token数)chunk_overlap=50(前后块重叠,保持上下文连贯)- 句子分割器(nltk、spacy、字符规则)
TokenTextSplitter:按token计数(使用tokenizer)- 适合GPT类模型,控制上下文窗口
CharacterTextSplitter:按字符数separator="\n\n"(按段落)keep_separator=True(保留分隔符)
3.2.2 语义分块
SemanticSplitterNodeParser:- 计算相邻句子的embedding相似度
- 相似度低于阈值则分割(语义 discontinuity)
- 需要embedding模型,开销较大
MetadataAwareTextSplitter:根据metadata(如章节标题)分割
3.2.3 代码分块
CodeSplitter:- 按函数/类分割(AST解析)
- 支持Java、Python、JavaScript、Go等
- 保留代码结构,适合代码搜索
3.2.4 递归分割
RecursiveCharacterTextSplitter:- 尝试按
["\n\n", "\n", " ", ""]顺序分割 - 确保每块不超过chunk_size
- 尝试按
示例:
from llama_index.node_parser import SentenceSplitter
parser = SentenceSplitter(
chunk_size=512,
chunk_overlap=50,
separator=" "
)
nodes = parser.get_nodes_from_documents(documents)
3.3 Embedding Model(嵌入模型)
作用:将文本转换为向量,用于语义检索
四类来源:
- OpenAI:
OpenAIEmbedding(text-embedding-ada-002、text-embedding-3-*)- 高质量,费用按token计费
- 支持batch请求,降低cost
- 本地模型(HuggingFace):
HuggingFaceEmbedding:任意sentence-transformers模型InstructorEmbedding:Instruct风格模型(如’instructor-large’)FastEmbedEmbedding:快速本地推理(Qdrant出品)
- 云服务:
CohereEmbedding(cohere.embed-english-v3.0)GoogleEmbedding(textembedding-gecko)AzureOpenAIEmbeddingBaiduEmbedding(文心)AliyunEmbedding(通义)
- 自定义:
- 实现
BaseEmbedding接口 - 支持业务特定领域embedding
- 实现
选择建议:
- 中小规模、高质量:OpenAI embedding
- 大规模、低成本:本地模型(bge-large-zh、all-MiniLM-L6-v2)
- 中文优先:BGE中文系列、m3e-base
- 多语言:paraphrase-multilingual-MiniLM-L12-v2
示例:
from llama_index.embeddings.openai import OpenAIEmbedding
embed_model = OpenAIEmbedding(
model="text-embedding-3-small",
dimensions=1536
)
3.4 Vector Store(向量数据库)
作用:存储Node的embedding向量,支持相似度搜索
支持30+向量数据库:
3.4.1 开源方案
- Milvus:高性能、云原生(推荐生产)
- 索引类型:HNSW、IVF_FLAT、IVF_PQ、SCANN
- 支持过滤、多模态
-集群版(Distributed)
- Qdrant:Rust编写,性能好
- HNSW索引、多向量、payload过滤
- API友好(gRPC/HTTP)
- Pinecone:托管服务,易用
- 全托管,无需运维
- 自动扩缩容
- Weaviate:GraphQL接口,模块化
- 内置vectorizer、混合搜索
- Chroma:轻量级、本地首选
- 内存模式、持久化模式
- 适合原型开发、小规模
- PGVector:PostgreSQL扩展
- 与SQL生态整合好
- HNSW、IVF索引
- Elasticsearch:全文+向量混合
- dense_vector字段
- 结合BM25,实现混合检索
- Redis:Redis Stack的向量搜索
- 适合缓存+向量搜索一体化
- ** Vespa**:完整搜索引擎,支持向量+全文
- FAISS:Facebook库,非独立服务
- ChromaDB:开源本地向量数据库
3.4.2 云服务
- Azure AI Search
- Google Vertex AI Matching Engine
- AWS OpenSearch Serverless
Vector Store集成:
from llama_index.vector_stores import ChromaVectorStore
vector_store = ChromaVectorStore(
persist_dir="./chroma_db",
collection_name="my_docs"
)
# 或从已有collection加载
import chromadb
chroma_client = chromadb.PersistentClient()
collection = chroma_client.get_or_create_collection("my_collection")
vector_store = ChromaVectorStore(chroma_collection=collection)
3.5 StorageContext(存储上下文)
作用:统一管理文档、向量、索引的持久化
配置:
from llama_index import StorageContext
storage_context = StorageContext.from_defaults(
doc_store=SimpleDocumentStore.from_persist_dir("./storage"),
vector_store=ChromaVectorStore.from_persist_dir("./storage"),
index_store=SimpleIndexStore.from_persist_dir("./storage")
)
存储类型:
SimpleDocumentStore:文档原始内容(JSON文件)SimpleIndexStore:索引元数据(JSON)SimpleKVStore:键值存储(内存或文件)- 可自定义,实现
BaseDocumentStore、BaseIndexStore接口
四、索引策略与选择
4.1 索引类型对比
| 索引类型 | 适用场景 | 检索方式 | 构建成本 | 查询速度 | 特点 |
|---|---|---|---|---|---|
| VectorIndex | 语义搜索 | 向量相似度 | 低 | 快 | 最常用,适合问答 |
| KeywordIndex | 关键词匹配 | 倒排索引(BM25) | 低 | 快 | 精确匹配、过滤 |
| TreeIndex | 层级摘要 | 树遍历 | 中 | 中 | 文档总结、层次查询 |
| ListIndex | 顺序生成 | 线性扫描 | 中 | 慢 | 列表式回答 |
| GraphIndex | 关系查询 | 图遍历 | 高 | 慢 | 复杂关系 |
| ComposableGraph | 分布式 | 子索引聚合 | 高 | 中 | 超长文档、分布式 |
4.2 VectorStoreIndex(向量索引)
最基础、最常用:
from llama_index import VectorStoreIndex, SimpleDirectoryReader
documents = SimpleDirectoryReader("./data").load_data()
index = VectorStoreIndex.from_documents(
documents,
storage_context=storage_context,
embed_model=embed_model
)
# 持久化
index.storage_context.persist(persist_dir="./storage")
# 查询
query_engine = index.as_query_engine()
response = query_engine.query("什么是RAG?")
print(response)
工作原理:
- 文档 → 分块(Node)→ embedding
- 所有Node存入Vector Store
- 查询时:query embedding → 向量搜索k个最相似Node
- 将Node的text作为context + query → LLM生成回答
参数调优:
similarity_top_k=10:检索top-k个Nodeembed_model=...:embedding模型vector_store=...:向量库show_progress=True:显示构建进度
4.3 KeywordTableIndex(关键词索引)
基于BM25的全文检索:
from llama_index import KeywordTableIndex
index = KeywordTableIndex.from_documents(documents)
response = index.as_query_engine().query("xxx")
# 与vector混合(后期查看Hybrid)
适用场景:
- 精确匹配(专有名词、代码)
- 过滤(metadata过滤)
- 作为Vector的fallback
4.4 TreeIndex(树索引)
构建文档的层次化摘要:
from llama_index import TreeIndex
index = TreeIndex.from_documents(documents)
# 查询时自动构建query-specific树
query_engine = index.as_query_engine()
response = query_engine.query("总结文档主要内容")
工作流程:
- 将chunk summary→构建树(每层摘要合并)
- 查询时:从叶子节点开始检索,向根节点回溯
- 选择最相关的子节点,最终到根节点获得全局context
适用场景:
- 文档摘要
- 需要全局理解的长文档
- 层次化Q&A(从概览到细节)
4.5 ListIndex(列表索引)
将所有chunk作为列表,逐个查询LLM:
from llama_index import ListIndex
index = ListIndex.from_documents(documents)
response = index.as_query_engine(
response_mode="tree_summarize" # 或"refine"
).query("xxx")
响应模式:
"compact":合并chunk到单个prompt"tree_summarize":递归树式总结(适合长文档)"refine":顺序迭代,每次基于前一次结果"simple_summarize":简单总结
适用场景:
- 文档摘要
- 多文档综合
- 不适合详细问答(缺少检索)
4.6 GraphIndex(图索引)
构建实体关系图:
from llama_index import GraphIndex
index = GraphIndex.from_documents(documents)
# 子图查询、路径查询
query_engine = index.as_query_engine(
response_mode="sub_questions" # 子图遍历
)
response = query_engine.query("A和B的关系?")
特点:
- 自动抽取实体和关系(可选LLM提取)
- 支持图遍历查询
- 构建成本高,查询慢
适用场景:
- 知识图谱问答
- 复杂关系推理
4.7 ComposableGraph(组合图)
多个索引的聚合:
from llama_index import ComposableGraph
graph = ComposableGraph.from_indices(
indices_list=[index1, index2, index3],
index_summaries=["summary1", "summary2", "summary3"]
)
query_engine = graph.as_query_engine()
工作流程:
- 先检索哪个sub-index相关(用summary)
- 再在该sub-index中检索具体chunk
适用场景:
- 超长文档(每章一个索引)
- 跨文档集合查询
五、检索与查询引擎
5.1 Retriever(检索器)
核心接口:retrieve(query_str: str) → List[NodeWithScore]
内置Retriever:
VectorIndexRetriever:向量检索similarity_top_k=10vector_store.query_embedding(...)
KeywordTableSimpleRetriever:BM25检索- 支持AND/OR逻辑
TreeSelectLeafRetriever:树索引叶子检索GraphRetriever:图遍历检索HybridRetriever:混合检索(向量+关键词)RouterRetriever:根据query选择retrieverQueryFusionRetriever:多检索器结果融合(RRF)
5.2 QueryEngine(查询引擎)
封装Retriever + ResponseSynthesis:
query_engine = index.as_query_engine(
retriever_mode="default", # 或"hybrid"
response_mode="compact" # 或"tree_summarize"、"refine"
)
response = query_engine.query("xxx")
响应模式:
compact:合并所有context到single prompt,适合top-k较小tree_summarize:递归总结,适合长context(先summary中间结果)refine:迭代精炼,每次基于前次结果更新,适合长contextsimple_summarize:简单调用summarize API
5.3 ChatEngine(对话引擎)
支持多轮对话:
from llama_index import ChatEngine
chat_engine = index.as_chat_engine(
chat_mode="context" # context/condense_question/react
)
response = chat_engine.chat("你好")
response = chat_engine.chat("上一问是什么?") # 有记忆
对话模式:
context:维护对话历史,拼接成contextcondense_question:将历史condense成新query再检索(更准)react:ReAct模式,支持工具调用openai:完全使用OpenAI Assistant(有状态)
5.4 QueryTransform(查询转换)
在检索前对query进行转换:
QueryRewrite:重写query,改善检索- 使用LLM自动重写,增加同义词、扩展
HybridTransformation:生成多个query(向量+关键词)StepDecoQueryTransform:问题分解(子问题)
示例:
from llama_index import QueryBundle
from llama_index.query_engine import TransformQueryEngine
from llama_index.query_engine.retriever_query_engine import RetrieverQueryEngine
retriever = index.as_retriever()
query_engine = RetrieverQueryEngine.from_args(
retriever,
query_transform=QueryRewrite(),
response_synthesizer=...
)
六、数据连接器与文档处理
6.1 文件系统
支持的格式(30+):
- 文本(txt、md、csv、json、xml、html)
- Office(docx、pptx、xlsx)
- PDF(text + image OCR)
- 代码(py、java、js、go、cpp、h、rs)
- ebook(epub、mobi)
- audio(mp3、wav - 需Whisper转录)
- 图像(png、jpg - OCR)
6.2 网页抓取
静态 vs 动态:
# 静态(快速,无JS)
from llama_index.readers.web import BeautifulSoupWebReader
reader = BeautifulSoupWebReader()
documents = reader.load_data(["https://example.com"])
# 动态(渲染后)
from llama_index.readers.web import SeleniumWebReader
reader = SeleniumWebReader()
documents = reader.load_data(["https://spa-example.com"])
高级选项:
extract_tables=True:提取表格encoding="utf-8"max_depth=2:爬取深度prevent_duplicate_links=True
6.3 数据库集成
SQL数据库:
from llama_index.readers.database import DatabaseReader
reader = DatabaseReader(
scheme="postgresql",
host="localhost",
port=5432,
user="user",
password="password",
database="dbname"
)
# 执行SQL,每行转为Document
documents = reader.load_data(
query="SELECT * FROM table WHERE condition"
)
NoSQL:
- MongoDB:
MongoDBReader - Elasticsearch:
ElasticsearchReader
6.4 API集成
Notion:
from llama_index.readers.notion import NotionPageReader
reader = NotionPageReader(
integration_token="secret_xxx"
)
documents = reader.load_data(
page_ids=["page-id-1", "page-id-2"]
)
Google Docs:
from llama_index.readers.google import GoogleDocsReader
reader = GoogleDocsReader()
documents = reader.load_data(
document_ids=["doc-id-1"],
credentials_path="./credentials.json"
)
RSS:
from llama_index.readers.web import RssReader
reader = RssReader()
documents = reader.load_data(
urls=["https://rss.example.com/feed"]
)
6.5 自定义Reader
实现BaseReader:
from llama_index.readers.base import BaseReader
from llama_index.schema import Document
class MyCustomReader(BaseReader):
def load_data(self, source: str) -> List[Document]:
# 读取逻辑
content = my_custom_parse(source)
metadata = {"source": source}
return [Document(text=content, metadata=metadata)]
七、高级检索技术
7.1 混合检索(Hybrid Search)
结合向量检索(语义)与关键词检索(精确):
from llama_index.retrievers import HybridRetriever
from llama_index.indices.keyword_table import KeywordTableIndex
# 构建两个索引(共享同一Document)
vector_index = VectorStoreIndex.from_documents(documents)
keyword_index = KeywordTableIndex.from_documents(documents)
# 混合检索器
hybrid_retriever = HybridRetriever(
vector_retriever=vector_index.as_retriever(similarity_top_k=10),
keyword_retriever=keyword_index.as_retriever(similarity_top_k=10),
mode="OR" # AND/OR/OR-dedup(去重)
)
query_engine = RetrieverQueryEngine.from_args(
retriever=hybrid_retriever,
response_synthesizer=...
)
融合策略:
OR:取并集AND:取交集OR-dedup:取并集并去重(推荐)
7.2 重排序(Reranking)
使用交叉编码器(Cross-encoder)对检索结果重排:
from llama_index.postprocessor import SentenceTransformerRerank
rerank = SentenceTransformerRerank(
model="cross-encoder/ms-marco-MiniLM-L-6-v2",
top_n=5
)
query_engine = RetrieverQueryEngine.from_args(
retriever=vector_retriever,
node_postprocessors=[rerank]
)
流程:
- 向量检索top-50
- 交叉编码器计算(query, doc)相关性分数
- 取top-5重排后结果
优势:
- 精度大幅提升( sacrificing recall)
- 适合top-k精确召回场景
云服务:
CohereRerank:Cohere rerank APIJinaRerank:Jina AI rerankYouRerank:You.com rerank
7.3 元数据过滤
检索时添加metadata过滤条件:
from llama_index import VectorStoreIndex
retriever = index.as_retriever(
similarity_top_k=10,
filters=MetadataFilters(
filters=[
MetadataFilter(
key="author",
value="John Doe",
operator="=="
),
MetadataFilter(
key="date",
value="2024-01-01",
operator=">="
)
]
)
)
过滤操作符:==、!=、>、>=、<、<=、in、nin、contains
7.4 多查询检索(Multi-Query)
将单个query扩展为多个related queries,分别检索后合并:
from llama_index.retrievers import QueryFusionRetriever
retriever = QueryFusionRetriever(
[vector_retriever, keyword_retriever],
similarity_top_k=10,
num_queries=4, # 生成4个query
mode="reciprocal_rerank", # RRF融合
use_async=True
)
生成策略:
- 默认使用LLM生成相关query(添加多样性)
- 可自定义query生成器
RRF算法:
score = sum(1 / (k + rank_i)) for each retriever
7.5 查询路由(Query Routing)
根据query选择不同的Index/Retriever:
from llama_index.retrievers import RouterRetriever
from llama_index.selectors.llm_selectors import LLMSingleSelector
router_retriever = RouterRetriever(
selector=LLMSingleSelector.from_defaults(),
retrievers={
"vector": vector_retriever,
"keyword": keyword_retriever,
"graph": graph_retriever
}
)
选择器类型:
LLMSingleSelector:LLM选择最佳retrieverLLMMultiSelector:选择多个(并行)PydanticMultiSelector:基于Pydantic模型- 自定义:实现
BaseSelector
八、查询处理与后处理
8.1 上下文组装策略
如何将检索到的Node组织成LLM prompt:
-
ContextFormatting:格式化templatetemplate = """Context information is below. --------------------- {context_str} --------------------- Given the context information and not prior knowledge, answer the query. Query: {query_str} Answer:""" -
CompactAndRefine:先compact成短context再refine -
TreeSummarize:递归tree摘要(长文档) -
Refine:迭代精炼(适合长context、流式)
8.2 响应合成器(ResponseSynthesizer)
控制LLM生成回答的方式:
from llama_index.response_synthesizers import RefineResponseSynthesizer
response_synthesizer = RefineResponseSynthesizer.from_defaults()
query_engine = RetrieverQueryEngine(
retriever=retriever,
response_synthesizer=response_synthesizer
)
合成模式:
compact:默认,一次性promptrefine:迭代,每次基于前次输出tree_summarize:递归树式simple_summarize:调用summarize endpoint
LLM配置:
from llama_index.llms import OpenAI
llm = OpenAI(model="gpt-4-turbo-preview", temperature=0)
response_synthesizer = ResponseSynthesizer.from_defaults(llm=llm)
8.3 后处理(PostProcessors)
在生成前对检索的Node处理:
SimilarityPostprocessor:按相似度分数过滤SimilarityPostprocessor(similarity_cutoff=0.7)KeywordPostprocessor:关键词过滤SentenceEmbeddingOptimizer:压缩context(删除冗余句子)PrevNextNodePostprocessor:添加上下文(prev/next Node)LongContextReorder:长context优化(把最相关放中间)MetadataReplacementPostProcessor:用metadata替换text(如用file_path替换内容)
组合使用:
from llama_index.postprocessor import (
SimilarityPostprocessor,
LongContextReorder
)
query_engine = index.as_query_engine(
node_postprocessors=[
SimilarityPostprocessor(similarity_cutoff=0.7),
LongContextReorder()
]
)
九、存储与持久化
9.1 存储层抽象
三等分存储:
- Document Store:原始documents
- Index Store:索引元数据(index结构)
- Vector Store:向量数据(embedding + node)
持久化策略:
# 方式1:一键持久化
storage_context.persist(persist_dir="./storage")
# 方式2:分别持久化
doc_store.persist(persist_path="./docs.json")
index_store.persist(persist_path="./index.json")
vector_store.persist(persist_path="./vectors/")
9.2 向量数据库持久化
不同vector store的持久化方式:
- Chroma:
vector_store = ChromaVectorStore( chroma_collection=collection, persist_directory="./chroma" ) - Milvus:
vector_store = MilvusVectorStore( dim=1536, collection_name="my_collection", uri="http://localhost:19530" ) # Milvus自身持久化,无需LlamaIndex额外persist - Pinecone:
vector_store = PineconeVectorStore( index_name="my-index", namespace="default" ) # 云服务自动持久化
9.3 增量更新
添加新文档:
from llama_index import SimpleDirectoryReader, StorageContext
# 加载已有storage
storage_context = StorageContext.from_defaults(
persist_dir="./storage"
)
# 加载新文档
new_docs = SimpleDirectoryReader("./new_data").load_data()
# 添加到原有index
index = VectorStoreIndex.from_documents(
new_docs,
storage_context=storage_context
)
# 再次持久化(合并)
storage_context.persist(persist_dir="./storage")
删除文档:
# 1. 从vector store删除(需要doc_id)
vector_store.delete(document.doc_id)
# 2. 刷新index
index.refresh_ref_docs(documents) # 增量更新
注意:
- 不是所有vector store支持删除
- 删除后需要重新build index(某些store不支持)
- 建议使用
doc_id作为唯一标识
十、性能优化与调优
10.1 分块策略优化
影响检索质量的核心:
原则:
- 块大小(chunk_size):512-1024 token为宜
- 太小:语义不完整
- 太大:噪声多,LLM上下文浪费
- 重叠(chunk_overlap):50-100 token
- 避免语义切断在关键信息
- 分块依据:
- 语义边界(句子/段落)优于固定字符
- 代码按函数/类
- Markdown按标题
实验方法:
- 固定top-k,调chunk_size
- 评估检索精度(人工或自动)
- 找到sweet spot
10.2 Embedding模型选择
权衡质量 vs 速度 vs 成本:
| 模型 | 维度 | 质量 | 速度 | 成本 | 适用 |
|---|---|---|---|---|---|
| text-embedding-ada-002 | 1536 | ★★★★★ | 中 | $$$ | 最高质量 |
| text-embedding-3-small | 1536 | ★★★★☆ | 快 | $$ | 性价比 |
| bge-large-zh | 1024 | ★★★★★ | 慢 | 0 | 中文 |
| all-MiniLM-L6-v2 | 384 | ★★★☆☆ | 极快 | 0 | 原型 |
| paraphrase-multilingual-MiniLM-L12-v2 | 384 | ★★★★☆ | 快 | 0 | 多语言 |
建议:
- 中文优先:BGE(智源)或 M3E(阿里)
- 多语言:paraphrase-multilingual
- 英文OpenAI最佳
10.3 向量索引优化
索引类型选择:
HNSW(推荐):
- 构建时间:中等
- 查询速度:快(O(log N))
- 内存占用:中
- 参数:
M(连接数,默认16-64)ef_construction(构建时候选集,默认200)ef_search(查询时候选集,越大越准越慢)
IVF_FLAT:
- 构建时间:快
- 查询速度:中(O(sqrt(N)))
- 参数:
nlist(聚类中心数,通常4*sqrt(N))
PQ(Product Quantization):
- 内存占用:极低(压缩)
- 精度损失:有
- 适合超大规模(亿级)
Milvus示例:
from llama_index.vector_stores import MilvusVectorStore
vector_store = MilvusVectorStore(
dim=1536,
collection_name="docs",
index_params={
"metric_type": "L2",
"index_type": "HNSW",
"params": {"M": 16, "efConstruction": 200}
},
search_params={
"metric_type": "L2",
"params": {"ef": 100} # ef_search
}
)
10.4 缓存策略
三层缓存:
-
Embedding缓存:相同text不重复embedding
from llama_index.embeddings import CacheEmbedding embed_model = CacheEmbedding( embed_model=OpenAIEmbedding(), cache_path="./embed_cache.json" ) -
查询结果缓存:
from llama_index.query_engine import RetrieverQueryEngine from llama_index.response_synthesizers import CompactResponseSynthesizer query_engine = RetrieverQueryEngine( retriever=retriever, response_synthesizer=CompactResponseSynthesizer(), cache=Cache() # 需实现或使用redis ) -
LLM响应缓存:使用Redis缓存query→response
from llama_index.llms import CacheLLM llm = CacheLLM( llm=OpenAI(), cache=RedisCache(redis_url="redis://localhost:6379") )
10.5 异步与并发
异步查询(提升吞吐):
import asyncio
from llama_index import SimpleDirectoryReader, VectorStoreIndex
async def async_query():
index = await VectorStoreIndex.afrom_documents(documents)
query_engine = index.as_query_engine()
response = await query_engine.aquery("xxx")
return response
asyncio.run(async_query())
并发检索:
from llama_index.retrievers import QueryFusionRetriever
import asyncio
retriever = QueryFusionRetriever(
[vector_retriever1, vector_retriever2],
similarity_top_k=10,
use_async=True # 并发调用多个retriever
)
10.6 批量构建索引
批量处理大量文档:
from llama_index.indices import SimpleIndexBuilder
# 分批次处理,避免内存溢出
builder = SimpleIndexBuilder(
documents,
embed_model=embed_model,
vector_store=vector_store,
chunk_size=512,
show_progress=True
)
builder.build_index()
10.7 LlamaDebugger(调试)
查看中间步骤:
from llama_index import set_global_handler
from llama_index.callbacks import LlamaDebugger
debugger = LlamaDebugger()
set_global_handler(debugger)
# 执行查询
response = query_engine.query("xxx")
# 查看调试信息
print(debugger.get_event_logs())
十一、评估与监控
11.1 评估框架(RAG评估)
11.1.1 内置评估模块
LlamaIndex提供评估数据集和评估器:
from llama_index.evaluation import (
DatasetGenerator,
RelevancyEvaluator,
FaithfulnessEvaluator,
CorrectnessEvaluator
)
# 1. 生成评估数据集(从文档生成QA对)
generator = DatasetGenerator.from_documents(documents)
eval_dataset = generator.generate_dataset_from_nodes(num_questions=10)
# 2. 评估查询引擎
relevancy_evaluator = RelevancyEvaluator()
faithfulness_evaluator = FaithfulnessEvaluator()
correctness_evaluator = CorrectnessEvaluator()
results = []
for query_item in eval_dataset:
response = query_engine.query(query_item.query)
relevancy = relevancy_evaluator.evaluate(
query=query_item.query,
response=response,
contexts=query_item.contexts # 期望上下文
)
faithfulness = faithfulness_evaluator.evaluate(
query=query_item.query,
response=response,
contexts=query_item.contexts
)
results.append({
"query": query_item.query,
"relevancy": relevancy.passing,
"faithfulness": faithfulness.passing
})
评估维度:
- Relevancy(相关性):检索到的context是否相关query
- Faithfulness(忠实度):回答是否基于提供的context(无幻觉)
- Correctness(正确性):回答是否正确(需参考答案)
- Semantic Similarity:与参考答案的语义相似度
- Guideline Adherence:是否符合风格指南
11.1.2 自动评估指标
使用LLM-as-a-Judge:
- 用GPT-4评估其他模型输出
- Prompt:给定query、context、response,判断是否相关、忠实
传统指标:
- Recall@K:top-k中至少一个相关即召回
- MRR(Mean Reciprocal Rank):第一个相关文档的排名的倒数均值
- NDCG(Normalized Discounted Cumulative Gain):考虑排序的加权评分
11.2 监控指标
11.2.1 检索质量监控
- 检索命中率:top-k中是否有相关doc
- 平均相似度分数:检索结果平均分(分数分布)
- 检索延迟:P50/P95/P99
- 向量查询QPS:每秒查询数
11.2.2 LLM调用监控
- Token使用量(Prompt + Completion)
- LLM延迟分布
- LLM错误率(429、500等)
- 成本统计(每千token成本)
11.2.3 应用层监控
- 端到端延迟(query→response)
- 缓存命中率
- 并发请求数
11.2.4 集成Prometheus
from llama_index.callbacks import CallbackManager
from llama_index.callbacks.open_inference_callback import OpenInferenceCallback
from llama_index.callbacks.base_handler import BaseCallbackHandler
callback_manager = CallbackManager([
OpenInferenceCallback() # 导出OpenTelemetry格式
])
query_engine = index.as_query_engine(callback_manager=callback_manager)
Prometheus指标:
rag_query_total:总查询数rag_query_duration_seconds:查询耗时rag_retrieval_duration_seconds:检索耗时rag_llm_duration_seconds:LLM耗时rag_cache_hit_total:缓存命中
十二、与LangChain对比
12.1 核心差异
| 维度 | LlamaIndex | LangChain |
|---|---|---|
| 定位 | RAG专家 | LLM应用全栈 |
| 数据层 | 强大(30+ Readers, Node分块) | 中等(Document Loaders) |
| 索引 | 多种索引(Vector/Keyword/Tree/Graph) | 主要Vector |
| 检索 | 高级(Hybrid、Rerank、Routing) | 基础 |
| Agent | 不支持或弱 | 强(Tools、Chains、Agents) |
| Memory | 不支持(需配合) | 支持 |
| 多模态 | 部分支持 | 强 |
- 学习曲线:LlamaIndex更简单(专精),LangChain更复杂(全能)
- 生产适用性:LlamaIndex更适合纯RAG场景,LangChain适合复杂Agent
12.2 如何选择
选择LlamaIndex:
- 纯RAG应用(问答、搜索)
- 数据源多样,需要复杂分块
- 检索质量要求极高(需要rerank、hybrid)
- 快速原型开发
选择LangChain:
- 需要Agent(工具调用、推理)
- 需要Memory(对话历史)
- 多模态应用(图像+文本)
- 复杂工作流(多个Chain串并联)
两者结合:
# 用LlamaIndex做Retriever,LangChain做Agent
from langchain.agents import AgentExecutor, Tool
from llama_index import VectorStoreIndex
index = VectorStoreIndex.from_documents(documents)
retriever = index.as_retriever()
# 包装为LangChain Tool
tool = Tool(
name="KnowledgeBase",
func=lambda q: retriever.retrieve(q),
description="搜索知识库"
)
agent = initialize_agent(
tools=[tool],
llm=OpenAI(),
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION
)
十三、Java生态支持
13.1 LlamaIndex Java版现状
- 项目:
com.llamaindex:llama-index-java(早期实验性质) - 状态:功能远少于Python版,社区活跃度低
- 推荐:Java项目通过REST API或gRPC调用Python部署的LlamaIndex服务
13.2 Spring AI集成(推荐)
Spring AI 2.0+ 内置LlamaIndex支持:
@Configuration
public class LlamaIndexConfig {
@Bean
public VectorStore vectorStore() {
return new SimpleVectorStore(
new InMemoryEmbeddingStore()
);
}
@Bean
public EmbeddingClient embeddingClient() {
return new OpenAIEmbeddingClient(
new OpenAiApi(apiKey, baseUrl)
);
}
}
// 使用
@Autowired
private VectorStore vectorStore;
@Autowired
private EmbeddingClient embeddingClient;
public void buildIndex(List<Document> docs) {
LlamaIndexVectorStoreAdapter adapter =
new LlamaIndexVectorStoreAdapter(vectorStore);
// Document转为LlamaIndex Node
List<Node> nodes = docs.stream()
.map(doc -> new Node(doc.getContent(), doc.getMetadata()))
.collect(Collectors.toList());
// 构建索引
VectorStoreIndex index = VectorStoreIndex.init(
nodes, embeddingClient, adapter
);
// 查询
QueryEngine queryEngine = index.asQueryEngine();
Response response = queryEngine.query("What is RAG?");
}
注意:Spring AI的LLamaIndex支持尚在早期,建议:
- Python部署LlamaIndex服务
- Java通过HTTP/gRPC调用
- 使用简化版(Spring AI内置的简单RAG)
13.3 REST API部署方案
架构:
Java App → HTTP API → Python LlamaIndex Service → Vector DB + LLM
FastAPI示例:
from fastapi import FastAPI
from llama_index import VectorStoreIndex, StorageContext
from pydantic import BaseModel
app = FastAPI()
class QueryRequest(BaseModel):
query: str
top_k: int = 10
@app.post("/query")
async def query(request: QueryRequest):
response = query_engine.query(request.query)
return {
"answer": response.response,
"sources": [node.text for node in response.source_nodes]
}
@app.post("/index/update")
async def update_index():
# 增量更新索引
...
# 启动:uvicorn main:app --host 0.0.0.0 --port 8000
Java客户端:
RestTemplate restTemplate = new RestTemplate();
String url = "http://llamaindex-service:8000/query";
Map<String, Object> request = Map.of("query", "xxx", "top_k", 10);
ResponseEntity<Map> response = restTemplate.postForEntity(url, request, Map.class);
十四、生产部署最佳实践
14.1 架构设计
推荐架构:
┌─────────────┐
│ Java App │ (Spring Boot/微服务)
└──────┬──────┘
│ HTTP/gRPC
┌──────┴──────┐
│ LlamaIndex│ 部署为独立服务(FastAPI + Uvicorn)
│ Service │ - 索引构建/更新服务(定时)
│ (Python) │ - 查询服务(实时)
└──────┬──────┘
│
┌──────┴──────┐
│ Vector DB │ (Milvus/Qdrant集群)
└──────┬──────┘
│
┌──────┴──────┐
│ Embedding │ (本地模型 or OpenAI API)
│ Service │
└─────────────┘
分离部署:
- 索引构建:批量异步,低优先级集群
- 查询服务:高可用,多副本,负载均衡
- 向量DB:集群化,分片+副本
- Embedding服务:GPU实例(本地模型)或OpenAI
14.2 索引更新策略
方案1:定期全量重建
- 优点:简单,一致性保证
- 缺点:资源消耗大,查询中断
- 适用:数据变化不频繁(<1%
方案2:增量更新
- 监听数据源变化(CDC、binlog、API webhook)
- 只更新新增/修改文档
- 删除:软删除标记,定期清理
- 推荐:LlamaIndex
refresh()API
# 增量更新示例
new_docs = get_new_documents_since(last_update)
index.refresh_ref_docs(new_docs) # 增量嵌入
方案3:双写+切换
- 新索引build在新collection
- 原子切换(rename collection)
- 零停机,但有短暂延迟
14.3 高可用与扩展
查询服务:
- 多副本(≥3)
- Nginx/HAProxy负载均衡
- 健康检查(/health端点)
- 优雅关闭(处理完现有请求再退出)
向量数据库:
- 分片(Shard):数据量大时分片
- 副本(Replica):查询负载均衡
- 异地容灾:主从复制,跨可用区
Embedding服务:
- 本地模型:GPU实例横向扩展
- OpenAI:调Bucket限制,使用多个API Key轮询
14.4 监控告警
关键指标:
- 查询QPS、错误率、延迟(P95<500ms)
- 向量查询延迟、QPS
- Embedding服务延迟、配额使用
- LLM API调用延迟、错误率、成本
- 向量DB连接数、内存、磁盘
告警阈值:
- 错误率 > 1%
- P95延迟 > 2s
- 可用性 < 99.9%
14.5 成本控制
Embedding成本:
- OpenAI embedding:$0.0001/1k tokens(ada-002)
- 估算:1GB文本 ≈ 10M tokens ≈ $1
- 优化:本地模型(bge)免费用,质量接近
LLM成本:
- 缓存高频query
- 使用便宜模型(gpt-35-turbo替代gpt-4)
- 压缩context(删除无关chunk)
- 限制top-k(减少输入token)
向量DB成本:
- 开源vs托管:Milvus自建 vs Zilliz Cloud
- 内存 vs 磁盘:HNSW需内存,PQ可磁盘
- 保留策略:删除旧索引
十五、常见问题与解决方案
Q1: 检索不到相关内容?
- 原因:
- embedding模型与领域不匹配(中文用英文模型)
- chunk_size太大,语义模糊
- 查询太长,未优化
- 解决:
- 换用领域embedding(BGE中文)
- 减小chunk_size(256-512)
- 使用query rewrite
Q2: LLM回答幻觉?
- 原因:
- 检索的context不包含答案
- context未有效传递给LLM
- LLM自身知识干扰
- 解决:
- 增加top-k,使用rerank
- 检查prompt模板,确保context明确
- 添加"仅基于上下文回答"指令
- 使用FaithfulnessEvaluator监控
Q3: 查询速度慢?
- 优化:
- 向量DB索引优化(ef_search调小)
- 减少top-k
- 使用缓存(embedding cache、query cache)
- 向量DB扩容(更多节点)
- 使用更快的embedding模型
Q4: 内存溢出?
- 原因:
- 文档太多,一次性加载
- 向量数据在内存
- LLM context过长
- 解决:
- 分批构建索引
- 使用Milvus/Pinecone(存储向量)
- 减少chunk_size和top-k
- 使用streaming generation
Q5: 多租户需求?
- 方案:
- 按用户创建不同collection(向量DB层面隔离)
- 查询时添加metadata filter
- 索引命名空间:
{tenant_id}_index - RBAC:应用层控制访问
Q6: 支持多模态?
- 当前:文本为主,图像需OCR转文本
- 方案:
- CLIP模型:图像+文本统一embedding
- 多模态LLM(GPT-4V)直接处理
- 自定义:图像OCR + 文本RAG
Q7: 实时数据更新?
- 挑战:索引更新延迟
- 方案:
- 流式更新:CDC → 消息队列 → LlamaIndex增量更新
- 短TTL缓存:5-10分钟过期,强制重新查询
- 混合:定期全量 + 实时增量
Q8: 评估RAG质量?
- 自动评估:Relevancy、Faithfulness、Correctness
- 人工评估:随机抽样,标注
- A/B测试:新旧版本对比关键指标
- 用户反馈:👍/👎按钮
Q9: 是否支持中文?
- 完全支持,但需注意:
- embedding模型:选中文优化(BGE、m3e)
- 分词器:中文专用
- LLM:GPT对中文支持好,开源中文模型(ChatGLM、Qwen)
- 向量DB:无特殊,存储向量
Q10: 生产环境稳定性?
- 异常处理:try-catch LLM/Embedding API超时
- 降级策略:embedding失败回退到keyword检索
- 熔断:Circuit Breaker保护下游API
- 重试:指数退避重试
- 监控:全链路监控,快速发现
十六、总结与展望
16.1 LlamaIndex核心优势
- 数据连接器最全(30+)
- 索引类型丰富(Vector/Keyword/Tree/Graph/Composable)
- 检索算法先进(Hybrid、Rerank、Routing、Fusion)
- 易用性极佳(几行代码完成RAG)
- 生产特性齐全(缓存、异步、监控)
16.2 适用场景
- ✅ 文档问答
- ✅ 知识库搜索
- ✅ 数据分析助手
- ✅ 研究助手
- ❌ 复杂Agent(需LangChain)
- ❌ 多模态(部分支持)
- ❌ 流式实时处理
16.3 学习路径
- 入门:VectorStoreIndex + QueryEngine(2小时)
- 进阶:高级检索(Hybrid、Rerank)+ 评估(1周)
- 高级:自定义组件 + 生产部署(1月)
- 专家:源码阅读 + 二次开发(数月)
16.4 未来方向
- 多模态索引:图像、音频向量统一
- 实时索引更新:流式数据低延迟
- Agent集成:更紧密支持ReAct等
- 云原生:K8s Operator部署
- 联邦学习:隐私保护下的联合索引
- AutoML for RAG:自动选择索引策略
文档版本:v1.0
最后更新:2025年3月
参考:https://docs.llamaindex.ai
评论区