如何基于 LLAMAIndex 快速构建 RAG 项目
目录
如何基于 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、向量库,添加重排序、混合检索。
- 中医专项优化:通过元数据、自定义解析器、术语映射满足领域需求。
下一步建议:尝试加载一个小型中医数据集(比如《伤寒论》几条条文),跑通上述流程,再根据实际效果逐步加入高级特性。如果在具体环节遇到问题,欢迎继续交流!
更多推荐



所有评论(0)