更新于

LlamaIndex 中文 RAG 完整教程


LlamaIndex 与 LangChain 同期出现,专注做 RAG。论 chain 能力不如 LangChain 全,但论”文档加载 → index → 查询”这条链路它做得最深。本文给中文 RAG 实战教程。

一、安装

pip install llama-index
pip install llama-index-llms-openai
pip install llama-index-embeddings-openai
pip install llama-index-vector-stores-chroma

按需安装其它 reader / vector store 包。

二、配置中转

from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.core import Settings

Settings.llm = OpenAI(
    api_base="https://yotradeapi.com/v1",
    api_key="sk-yo-...",
    model="claude-sonnet-4-6",   # 通过中转走 Claude
)

Settings.embed_model = OpenAIEmbedding(
    api_base="https://yotradeapi.com/v1",
    api_key="sk-yo-...",
    model="text-embedding-3-large",
)

全局配置。后续所有 chain 用这个 llm + embedding。

三、最简 RAG

from llama_index.core import SimpleDirectoryReader, VectorStoreIndex

# 加载文档
documents = SimpleDirectoryReader("./docs").load_data()

# 建 index(自动 embed)
index = VectorStoreIndex.from_documents(documents)

# 持久化
index.storage_context.persist(persist_dir="./storage")

# 查询
query_engine = index.as_query_engine()
response = query_engine.query("我们的退货政策是什么?")
print(response)

10 行 RAG。SimpleDirectoryReader 自动识别 PDF / Word / Markdown / Text。

四、持久化与重载

from llama_index.core import StorageContext, load_index_from_storage

# 重启后重载,不需要重新 embed
storage_context = StorageContext.from_defaults(persist_dir="./storage")
index = load_index_from_storage(storage_context)

避免重复花 embed 钱。

五、用 Chroma 替代默认向量库

默认 in-memory + JSON 持久化,大数据量慢。换 Chroma:

import chromadb
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.core import StorageContext, VectorStoreIndex

chroma_client = chromadb.PersistentClient(path="./chroma_db")
chroma_collection = chroma_client.get_or_create_collection("docs")

vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)

index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)

10k+ 文档场景Chroma 性能比默认快 10 倍以上

六、Chunk 策略

from llama_index.core.node_parser import SentenceSplitter

splitter = SentenceSplitter(
    chunk_size=512,        # 每块约 512 tokens
    chunk_overlap=50,       # overlap 50
    separator="\n\n",       # 段落分隔
)

Settings.node_parser = splitter

详见 中文 RAG 工程实战

七、加 Rerank

from llama_index.postprocessor.cohere_rerank import CohereRerank
# 或用 LLM-as-reranker(贵但通用)

rerank = CohereRerank(api_key="...", top_n=3)

query_engine = index.as_query_engine(
    similarity_top_k=10,
    node_postprocessors=[rerank],
)

召回 10 → rerank 取 top 3。准确率显著提升。

八、Multi-Document Query

from llama_index.core.tools import QueryEngineTool, ToolMetadata
from llama_index.core.query_engine import SubQuestionQueryEngine

# 两份文档各自 index
docs_a = VectorStoreIndex.from_documents(load_a())
docs_b = VectorStoreIndex.from_documents(load_b())

tools = [
    QueryEngineTool(
        query_engine=docs_a.as_query_engine(),
        metadata=ToolMetadata(name="docs_a", description="产品文档"),
    ),
    QueryEngineTool(
        query_engine=docs_b.as_query_engine(),
        metadata=ToolMetadata(name="docs_b", description="API 文档"),
    ),
]

query_engine = SubQuestionQueryEngine.from_defaults(query_engine_tools=tools)
response = query_engine.query("产品如何接入 API?")

会自动把问题拆成 sub-question 分别查 a / b,再综合。

九、Agent + RAG

from llama_index.core.agent.workflow import FunctionAgent
from llama_index.core.tools import FunctionTool

def get_user_status(user_id: str) -> str:
    """查用户当前订阅状态"""
    return f"user {user_id} is active"

agent = FunctionAgent(
    name="assistant",
    tools=[
        QueryEngineTool(query_engine=docs_a.as_query_engine(), metadata=ToolMetadata(name="kb", description="知识库")),
        FunctionTool.from_defaults(get_user_status),
    ],
    llm=Settings.llm,
)

response = await agent.run("用户 alice 是否能用 X 功能?")

Agent 知道何时查文档、何时查用户状态。

十、流式

streaming = query_engine.query_stream("...")
for chunk in streaming.response_gen:
    print(chunk, end="")

或者用 as_chat_engine()

chat_engine = index.as_chat_engine(
    chat_mode="condense_plus_context",
    streaming=True,
)
response = chat_engine.stream_chat("...")
for token in response.response_gen:
    print(token, end="")

十一、Metadata 过滤

from llama_index.core.vector_stores import MetadataFilters, ExactMatchFilter

filters = MetadataFilters(filters=[
    ExactMatchFilter(key="category", value="legal"),
    ExactMatchFilter(key="language", value="zh"),
])

query_engine = index.as_query_engine(filters=filters)

按 metadata 限制检索范围。多租户 RAG 必备

十二、LlamaIndex vs LangChain

维度LlamaIndexLangChain
专注RAG通用 chain
文档加载器极多
Vector store 集成极多
Agent完整
LCEL 风格部分
学习曲线

简单决策

  • 以 RAG 为主 → LlamaIndex
  • 复杂 agent + chain → LangChain
  • 想自己控制更多 → 裸 SDK

十三、生产部署注意

  1. Embedding 一次性算清:上线前批量 embed,运行时只 query
  2. Vector store 备份:定期 dump
  3. 新文档增量加:用 insert_nodes() 不要重建 index
  4. 查询缓存:相同问题缓存 30 秒
  5. 监控 token:每个 query 都消耗,监控异常
  6. rerank 看场景:高准确度场景上,速度敏感不上

十四、相关阅读

LlamaIndex 同时需要 chat + embedding 接口?YoTradeApi 一把 Key 接两个端点,按上面配置接入。