第十三章:RAG(检索增强生成)
学习目标
- 理解RAG(Retrieval-Augmented Generation)的核心原理与价值
- 掌握RAG系统的核心组件和工作流程
- 了解文档切分策略、Embedding模型选择和向量数据库对比
- 能够使用LangChain构建简单的RAG应用
- 了解RAG系统的评估方法
前置要求
建议先学习第十一章:大语言模型(LLM)详解,了解LLM的基本原理和使用方法,以便理解RAG如何增强LLM的能力。
什么是RAG?
RAG(Retrieval-Augmented Generation,检索增强生成)是一种将信息检索与大语言模型生成相结合的技术。它先从外部知识库中检索相关信息,再将检索到的信息作为上下文提供给LLM,从而生成更准确、更有依据的回答。
为什么需要RAG?
LLM存在以下局限性,RAG可以有效解决:
- 知识过时:LLM的训练数据有截止日期,无法获取最新信息
- 幻觉问题:LLM可能"编造"不存在的信息,RAG通过提供真实文档来减少幻觉
- 缺乏私有知识:LLM不了解企业内部文档、个人笔记等私有数据
- 可追溯性差:纯LLM回答无法引用信息来源,RAG可以标注出处
RAG工作流程
文档导入
将PDF、网页、数据库等外部知识导入系统
文档切分
将长文档切分为较小的文本块(Chunk)
向量化
使用Embedding模型将文本块转换为向量表示
存储索引
将向量存入向量数据库,建立索引
检索
用户提问时,将问题向量化并在数据库中检索相关文档
生成
将检索到的文档作为上下文,交给LLM生成回答
RAG的核心组件
| 组件 | 功能 | 常见选择 |
|---|---|---|
| 文档加载器 | 读取各种格式的文档(PDF、Word、网页等) | LangChain Loaders、LlamaIndex |
| 文本切分器 | 将长文档切分为适合检索的文本块 | RecursiveCharacterTextSplitter |
| Embedding模型 | 将文本转换为向量表示 | OpenAI、Sentence-BERT、BGE |
| 向量数据库 | 存储和检索向量 | Chroma、Milvus、Pinecone |
RAG的优势
- 减少幻觉:基于真实文档生成回答,提高准确性
- 知识可更新:只需更新向量数据库中的文档,无需重新训练模型
- 支持私有数据:可以整合企业内部知识库
- 可追溯来源:回答可以标注引用的文档来源
- 成本更低:相比微调,RAG的实现成本更低、速度更快
文档切分策略
文档切分(Chunking)是RAG系统中至关重要的一步,切分策略直接影响检索质量。
| 切分策略 | 原理 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 按段落切分 | 以段落分隔符(换行、空行)为边界切分 | 保持语义完整性 | 段落长度不一,可能过长或过短 | 结构化文档(文章、报告) |
| 按Token切分 | 按固定Token数量切分 | 长度均匀,便于管理 | 可能切断语义完整的句子 | 需要精确控制上下文长度 |
| 重叠窗口切分 | 固定长度切分,相邻块之间保留重叠部分 | 兼顾长度控制和语义完整性 | 存储冗余,检索结果可能重复 | 通用场景(推荐) |
推荐使用重叠窗口切分,通常设置块大小为500-1000个Token,重叠比例为10%-20%。
Embedding模型选择
| 模型 | 开发者 | 维度 | 最大长度 | 多语言支持 | 特点 |
|---|---|---|---|---|---|
| text-embedding-3-small | OpenAI | 1536 | 8191 | 较好 | 效果好、API调用简单、需付费 |
| all-MiniLM-L6-v2 | Sentence-BERT | 384 | 256 | 一般 | 轻量快速、适合英文 |
| bge-large-zh-v1.5 | BAAI (BGE) | 1024 | 512 | 优秀(中文) | 中文效果出色、开源免费 |
| m3e-base | Moka (M3E) | 768 | 512 | 良好(中文) | 中文场景常用、开源免费 |
向量数据库详细对比
| 数据库 | 特点 | 适用场景 | 是否开源 |
|---|---|---|---|
| Pinecone | 全托管云服务、无需运维、自动扩展 | 快速上线、不想管理基础设施的团队 | 否(商业服务) |
| Weaviate | 支持混合搜索(向量+关键词)、GraphQL API | 需要同时支持向量和关键词搜索的场景 | 是 |
| Milvus | 分布式架构、支持十亿级向量、性能极高 | 大规模生产环境、海量数据检索 | 是 |
| Chroma | 轻量级、嵌入式、Python友好、上手极简 | 开发测试、小规模应用、快速原型 | 是 |
| Qdrant | Rust编写、高性能、支持过滤、API丰富 | 高性能需求、需要复杂过滤条件 | 是 |
使用LangChain构建简单RAG
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_community.llms import Ollama
from langchain.chains import RetrievalQA
# 1. 加载文档
loader = TextLoader("knowledge_base.txt", encoding="utf-8")
documents = loader.load()
# 2. 切分文档
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 每块最大500个字符
chunk_overlap=50, # 块之间重叠50个字符
separators=["\n\n", "\n", "。", "!", "?", " ", ""]
)
chunks = text_splitter.split_documents(documents)
print(f"文档被切分为 {len(chunks)} 个文本块")
# 3. 初始化Embedding模型
embeddings = HuggingFaceEmbeddings(
model_name="BAAI/bge-large-zh-v1.5" # 中文Embedding模型
)
# 4. 创建向量数据库
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db" # 持久化存储目录
)
# 5. 创建检索器
retriever = vectorstore.as_retriever(
search_kwargs={"k": 3} # 检索最相关的3个文本块
)
# 6. 初始化LLM
llm = Ollama(model="qwen2.5:7b") # 使用本地Ollama运行
# 7. 构建RAG链
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff", # 将所有检索结果拼接到一起
retriever=retriever,
return_source_documents=True
)
# 8. 提问
question = "什么是机器学习?"
result = qa_chain({"query": question})
print(f"问题:{question}")
print(f"回答:{result['result']}")
print(f"引用来源:{[doc.metadata for doc in result['source_documents']]}")
RAG评估方法
评估RAG系统的质量需要从检索和生成两个维度进行:
| 评估维度 | 指标 | 说明 |
|---|---|---|
| 检索质量 | 检索准确率(Precision@K) | 检索返回的K个文档中,有多少是真正相关的 |
| 检索质量 | 检索召回率(Recall@K) | 所有相关文档中,有多少被成功检索到 |
| 生成质量 | 回答相关性 | 生成的回答是否与问题相关 |
| 生成质量 | 回答忠实度(Faithfulness) | 回答是否基于检索到的文档,而非编造 |
| 整体质量 | 端到端准确率 | 最终回答的正确性和完整性 |
常用评估框架:RAGAS(RAG Assessment)是一个专门用于评估RAG系统的开源框架,提供上述指标的自动化计算。
本章小结
- RAG通过"检索+生成"的范式,将外部知识库与大语言模型结合,有效解决了LLM的知识过时、幻觉和私有数据缺失等问题。
- RAG的核心流程包括:文档导入→切分→向量化→存储索引→检索→生成,每个环节都有多种策略和工具可选。
- 文档切分推荐使用重叠窗口策略(500-1000 Token,10%-20%重叠),Embedding模型中文场景推荐BGE或M3E。
- 向量数据库选择需考虑规模和场景:Chroma适合开发测试,Milvus适合大规模生产,Pinecone适合不想运维的团队。
- RAG评估需从检索质量(准确率、召回率)和生成质量(相关性、忠实度)两个维度综合考量。
练习题
-
RAG系统的主要目的是什么?
A. 训练更大的语言模型
B. 让LLM能够利用外部知识库来增强回答
C. 替代LLM进行文本生成
D. 加速模型的训练过程答案:B。RAG的核心目的是通过检索外部知识来增强LLM的生成能力,使回答更加准确、有依据。
-
在RAG系统中,文档切分时使用"重叠窗口"策略的主要好处是什么?
A. 减少存储空间
B. 避免在切分边界处丢失上下文信息
C. 加快检索速度
D. 减少Embedding的计算量答案:B。重叠窗口策略让相邻文本块之间保留部分重叠内容,确保即使关键信息恰好位于切分边界处,也不会被遗漏。
-
以下哪个向量数据库最适合快速原型开发和小规模应用?
A. Milvus
B. Pinecone
C. Chroma
D. Qdrant答案:C。Chroma是轻量级、嵌入式、Python友好的向量数据库,非常适合开发测试和小规模应用场景。