如何基于 LLAMAIndex 快速构建 RAG 项目

基于 LlamaIndex 快速构建 RAG 项目,可以让你避免重复造轮子,专注于业务逻辑。LlamaIndex 提供了从数据加载、索引构建到查询检索的全套工具,而且对初学者友好,同时支持深度定制。下面我会带你走一遍核心流程,并给出可直接运行的代码示例。


一、LlamaIndex 简介

LlamaIndex(原名 GPT Index)是一个专门为 RAG 应用设计的开源框架,它抽象了文档解析、分块、向量化、检索、提示工程等环节,只需几行代码就能搭建一个基础 RAG 系统。同时,它也提供了丰富的自定义接口,满足复杂需求(如混合检索、重排序、多文档路由等)。


二、快速搭建步骤(以中医知识库为例)

1. 安装

pip install llama-index
# 如果你需要使用特定的向量模型或数据库,可能需要额外安装,例如:
pip install llama-index-embeddings-huggingface
pip install llama-index-vector-stores-chroma

2. 加载文档

LlamaIndex 支持多种数据源:本地文件(txt, pdf, docx)、网页、数据库等。这里我们加载一个中医古籍的 txt 文件。

from llama_index.core import SimpleDirectoryReader

# 假设你的文档放在 ./data 目录下
documents = SimpleDirectoryReader("./data").load_data()

SimpleDirectoryReader 会自动解析常见格式,返回 Document 对象列表。

3. 解析与分块(Node 化)

默认情况下,LlamaIndex 会按一定大小分割文档,你也可以自定义 Splitter

from llama_index.core.node_parser import SentenceSplitter

# 设置分块器:块大小 256 token,重叠 20 个 token
parser = SentenceSplitter(chunk_size=256, chunk_overlap=20)
nodes = parser.get_nodes_from_documents(documents)

对于中医古籍,你可能希望按条文分块,可以使用 CodeSplitter 或自定义解析器。

4. 选择嵌入模型与向量存储

  • 嵌入模型:可以使用 HuggingFace 上的模型,例如 BAAI/bge-large-zh-v1.5 或针对中医微调的模型。
  • 向量存储:默认内存存储,适合实验;生产环境可用 Chroma、FAISS、Milvus 等。
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.core import Settings

# 全局设置嵌入模型
Settings.embed_model = HuggingFaceEmbedding(
    model_name="BAAI/bge-large-zh-v1.5"
)

5. 构建索引

LlamaIndex 提供多种索引类型,最常用的是 VectorStoreIndex

from llama_index.core import VectorStoreIndex

index = VectorStoreIndex(nodes)  # 也可以直接传入 documents,内部会进行分块

如果你需要持久化索引,可以指定向量存储:

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

# 初始化 chroma 客户端
db = chromadb.PersistentClient(path="./chroma_db")
chroma_collection = db.get_or_create_collection("tcm_keji")
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, show_progress=True
)

6. 创建查询引擎

查询引擎是 RAG 的入口,它内部会执行:检索 -> 组合提示 -> 调用 LLM 生成答案。

# 默认使用 OpenAI 的 LLM(需设置 OPENAI_API_KEY 环境变量)
# 也可以使用其他 LLM,比如本地部署的模型
from llama_index.llms.openai import OpenAI
Settings.llm = OpenAI(model="gpt-3.5-turbo")

query_engine = index.as_query_engine()

7. 开始提问

response = query_engine.query("麻黄汤的组成是什么?")
print(response)

至此,一个完整的 RAG 系统已经跑起来了!


三、核心组件与自定义

1. 检索器(Retriever)

你可以单独使用检索器,查看检索到的文本块。

retriever = index.as_retriever(similarity_top_k=5)
nodes = retriever.retrieve("麻黄汤的组成")
for node in nodes:
    print(node.text)
    print(node.score)

2. 响应合成器(Response Synthesizer)

控制如何将检索到的文本块组合并生成答案。例如,可以要求模型只基于检索内容回答,不要编造。

from llama_index.core.response_synthesizers import ResponseMode

query_engine = index.as_query_engine(
    response_mode=ResponseMode.COMPACT,  # 紧凑模式,将上下文合并成一个提示
    verbose=True
)

其他模式:REFINE(逐块优化)、TREE_SUMMARIZE(树形摘要)等。

3. 自定义提示词

from llama_index.core import PromptTemplate

custom_prompt = PromptTemplate(
    "你是一位资深中医专家。请仅根据以下上下文回答问题。\n"
    "上下文:{context_str}\n"
    "问题:{query_str}\n"
    "回答:"
)

query_engine.update_prompts(
    {"response_synthesizer:text_qa_template": custom_prompt}
)

4. 混合检索

LlamaIndex 支持混合检索(向量+关键词),需要配合向量存储实现。以 Chroma 为例:

vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
# Chroma 默认支持 keyword search,需要确保 collection 有全文索引
index = VectorStoreIndex.from_vector_store(vector_store)

# 创建检索器时启用混合检索
retriever = index.as_retriever(
    vector_store_query_mode="hybrid",  # 关键参数
    similarity_top_k=5
)

5. 重排序

可以使用 SentenceTransformerRerank 模块对检索结果重排。

from llama_index.core.postprocessor import SentenceTransformerRerank

rerank = SentenceTransformerRerank(
    model="BAAI/bge-reranker-base",
    top_n=3  # 保留前3个最相关的
)

query_engine = index.as_query_engine(
    similarity_top_k=10,  # 先取10个
    node_postprocessors=[rerank]  # 后处理重排
)

6. 对话记忆

如果你需要多轮对话,可以使用 ChatEngine

chat_engine = index.as_chat_engine()
response = chat_engine.chat("麻黄汤的组成")
response = chat_engine.chat("它的剂量呢?")  # 自动继承上文

四、中医领域的适配建议

1. 处理古籍与医案

  • 古籍:按条文分块,并为每个条文添加元数据(书名、篇目、条号)。可使用 MetadataExtractor 或自定义 NodeParser
  • 医案:将医案拆分为症状、舌脉、辨证、方药等字段,分别存入元数据,或建立多个索引。

示例:添加元数据

from llama_index.core.schema import MetadataMode

node.metadata = {
    "source": "伤寒论",
    "chapter": "辨太阳病脉证并治",
    "type": "方剂",
    "formula": "麻黄汤"
}

2. 术语归一化

可以在检索前对查询进行预处理,使用自定义 QueryTransform 或直接修改查询字符串。

from llama_index.core.indices.query.query_transform import HyDEQueryTransform

# HyDE 是一种查询扩展技术,也可用于术语映射
transform = HyDEQueryTransform()
query_bundle = transform("后脖子发僵")
# 或者自己写一个简单映射
def normalize_query(query):
    replacements = {"后脖子发僵": "项强", "胃痛": "胃脘痛"}
    for k, v in replacements.items():
        query = query.replace(k, v)
    return query

3. 多文档路由

如果你的知识库包含多个子领域(如古籍库、现代教材库、医案库),可以使用 RouterQueryEngine 将问题路由到对应的子索引。

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

gujian_tool = QueryEngineTool(
    query_engine=gujian_engine,
    metadata=ToolMetadata(name="古籍", description="查询中医古籍相关内容")
)
xiandai_tool = ...
router = RouterQueryEngine.from_defaults([gujian_tool, xiandai_tool])
response = router.query("《伤寒论》中关于桂枝的用法")

五、评估与调试

LlamaIndex 内置了简单的评估工具,例如:

from llama_index.core.evaluation import FaithfulnessEvaluator, RelevancyEvaluator

evaluator = FaithfulnessEvaluator()
result = await evaluator.aevaluate(
    response=response,
    contexts=[node.text for node in source_nodes]
)
print(result.passing)  # True/False

你也可以集成 RAGAS 等评估框架。


六、完整示例代码(极简版)

import os
os.environ["OPENAI_API_KEY"] = "your-key"

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.core import Settings

# 设置 embedding 模型
Settings.embed_model = HuggingFaceEmbedding(
    model_name="BAAI/bge-large-zh-v1.5"
)

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

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

# 查询
query_engine = index.as_query_engine()
response = query_engine.query("麻黄汤的组成")
print(response)

七、总结

通过 LlamaIndex,你可以:

  • 快速搭建:几行代码完成文档加载、分块、索引、检索、生成。
  • 灵活定制:替换 embedding、LLM、向量库,添加重排序、混合检索。
  • 中医专项优化:通过元数据、自定义解析器、术语映射满足领域需求。

下一步建议:尝试加载一个小型中医数据集(比如《伤寒论》几条条文),跑通上述流程,再根据实际效果逐步加入高级特性。如果在具体环节遇到问题,欢迎继续交流!

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐