侧边栏壁纸
博主头像
毕业帮 博主等级

提供丰富的资源和服务,涵盖从论文写作、毕业设计、职业规划、就业准备等多个方面

  • 累计撰写 84 篇文章
  • 累计创建 18 个标签
  • 累计收到 3 条评论

目 录CONTENT

文章目录

LlamaIndex 全面技术详解

流苏
2026-03-11 / 0 评论 / 0 点赞 / 87 阅读 / 0 字 / 正在检测是否收录...
温馨提示:
本文最后更新于2026-03-11,若内容或图片失效,请留言反馈。 部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

LlamaIndex 全面技术详解

构建生产级RAG应用的企业级框架


目录


一、LlamaIndex 概述

1.1 什么是LlamaIndex

LlamaIndex(前身为GPT Index)是一个专门为LLM应用设计的数据框架,核心解决私有数据接入LLM的问题。

核心定位:

  • 数据连接层:连接私有数据(文档、数据库、API)与LLM
  • 索引构建层:将非结构化/结构化数据转换为LLM可高效检索的格式
  • 检索增强层:提供先进的检索策略,为LLM提供相关上下文

与LangChain的区别:

LangChain: LLM应用开发全栈框架(Agent、Chain、Memory等)
    ↓
LlamaIndex: 专注数据接入与检索(RAG专家)

1.2 核心价值主张

  1. 简单性:5行代码完成RAG管道搭建
  2. 灵活性:可组合组件,自定义每个环节
  3. 性能:先进的检索算法,生产级性能
  4. 可扩展:插件化架构,支持任意数据源/向量库
  5. 生产就绪:监控、缓存、异步、错误处理

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:PowerPoint
    • ImageReader:OCR识别图片文字
    • IPYNBReader:Jupyter Notebook
    • UnstructuredReader:通用解析器(支持多种格式)
  • 网页:
    • BeautifulSoupWebReader:静态网页
    • SeleniumWebReader:动态渲染页面(JavaScript)
    • ReadabilityWebReader:只读文章正文
  • 数据库:
    • SQLDatabaseReader:执行SQL查询
    • SimpleMongoReader:MongoDB查询
  • API:
    • RssReader:RSS订阅
    • GoogleDocsReader:Google Docs
    • NotionReader:Notion页面
  • 云存储:
    • S3Reader:AWS S3
    • AzureBlobStorageReader:Azure Blob
    • GCSReader: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(嵌入模型)

作用:将文本转换为向量,用于语义检索

四类来源:

  1. OpenAI:OpenAIEmbedding(text-embedding-ada-002、text-embedding-3-*)
    • 高质量,费用按token计费
    • 支持batch请求,降低cost
  2. 本地模型(HuggingFace):
    • HuggingFaceEmbedding:任意sentence-transformers模型
    • InstructorEmbedding:Instruct风格模型(如’instructor-large’)
    • FastEmbedEmbedding:快速本地推理(Qdrant出品)
  3. 云服务:
    • CohereEmbedding(cohere.embed-english-v3.0)
    • GoogleEmbedding(textembedding-gecko)
    • AzureOpenAIEmbedding
    • BaiduEmbedding(文心)
    • AliyunEmbedding(通义)
  4. 自定义:
    • 实现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)

工作原理:

  1. 文档 → 分块(Node)→ embedding
  2. 所有Node存入Vector Store
  3. 查询时:query embedding → 向量搜索k个最相似Node
  4. 将Node的text作为context + query → LLM生成回答

参数调优:

  • similarity_top_k=10:检索top-k个Node
  • embed_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("总结文档主要内容")

工作流程:

  1. 将chunk summary→构建树(每层摘要合并)
  2. 查询时:从叶子节点开始检索,向根节点回溯
  3. 选择最相关的子节点,最终到根节点获得全局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()

工作流程:

  1. 先检索哪个sub-index相关(用summary)
  2. 再在该sub-index中检索具体chunk

适用场景:

  • 超长文档(每章一个索引)
  • 跨文档集合查询

五、检索与查询引擎

5.1 Retriever(检索器)

核心接口:retrieve(query_str: str) → List[NodeWithScore]

内置Retriever:

  • VectorIndexRetriever:向量检索
    • similarity_top_k=10
    • vector_store.query_embedding(...)
  • KeywordTableSimpleRetriever:BM25检索
    • 支持AND/OR逻辑
  • TreeSelectLeafRetriever:树索引叶子检索
  • GraphRetriever:图遍历检索
  • HybridRetriever:混合检索(向量+关键词)
  • RouterRetriever:根据query选择retriever
  • QueryFusionRetriever:多检索器结果融合(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:迭代精炼,每次基于前次结果更新,适合长context
  • simple_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:维护对话历史,拼接成context
  • condense_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]
)

流程:

  1. 向量检索top-50
  2. 交叉编码器计算(query, doc)相关性分数
  3. 取top-5重排后结果

优势:

  • 精度大幅提升( sacrificing recall)
  • 适合top-k精确召回场景

云服务:

  • CohereRerank:Cohere rerank API
  • JinaRerank:Jina AI rerank
  • YouRerank: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选择最佳retriever
  • LLMMultiSelector:选择多个(并行)
  • PydanticMultiSelector:基于Pydantic模型
  • 自定义:实现BaseSelector

八、查询处理与后处理

8.1 上下文组装策略

如何将检索到的Node组织成LLM prompt:

  • ContextFormatting:格式化template

    template = """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:默认,一次性prompt
  • refine:迭代,每次基于前次输出
  • 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按标题

实验方法:

  1. 固定top-k,调chunk_size
  2. 评估检索精度(人工或自动)
  3. 找到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 缓存策略

三层缓存:

  1. Embedding缓存:相同text不重复embedding

    from llama_index.embeddings import CacheEmbedding
    
    embed_model = CacheEmbedding(
        embed_model=OpenAIEmbedding(),
        cache_path="./embed_cache.json"
    )
    
  2. 查询结果缓存:

    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
    )
    
  3. 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支持尚在早期,建议:

  1. Python部署LlamaIndex服务
  2. Java通过HTTP/gRPC调用
  3. 使用简化版(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核心优势

  1. 数据连接器最全(30+)
  2. 索引类型丰富(Vector/Keyword/Tree/Graph/Composable)
  3. 检索算法先进(Hybrid、Rerank、Routing、Fusion)
  4. 易用性极佳(几行代码完成RAG)
  5. 生产特性齐全(缓存、异步、监控)

16.2 适用场景

  • ✅ 文档问答
  • ✅ 知识库搜索
  • ✅ 数据分析助手
  • ✅ 研究助手
  • ❌ 复杂Agent(需LangChain)
  • ❌ 多模态(部分支持)
  • ❌ 流式实时处理

16.3 学习路径

  1. 入门:VectorStoreIndex + QueryEngine(2小时)
  2. 进阶:高级检索(Hybrid、Rerank)+ 评估(1周)
  3. 高级:自定义组件 + 生产部署(1月)
  4. 专家:源码阅读 + 二次开发(数月)

16.4 未来方向

  • 多模态索引:图像、音频向量统一
  • 实时索引更新:流式数据低延迟
  • Agent集成:更紧密支持ReAct等
  • 云原生:K8s Operator部署
  • 联邦学习:隐私保护下的联合索引
  • AutoML for RAG:自动选择索引策略

文档版本:v1.0
最后更新:2025年3月
参考:https://docs.llamaindex.ai

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区