
RAG技术详解:从检索增强生成到知识库问答实战
前言
RAG(Retrieval Augmented Generation,检索增强生成)是2024-2025年大模型应用最火热的架构之一。它解决了两大核心问题:知识时效性和幻觉问题。本文从原理出发,详解RAG全链路技术栈。
一、为什么需要RAG?
大模型虽然强大,但存在固有局限:
| 问题 | 描述 | RAG解决方案 |
|---|---|---|
| 知识截止日期 | 训练数据有时效限制 | 实时检索最新知识 |
| 幻觉 | 模型会编造不存在的事实 | 答案基于检索到的真实文档 |
| 私有知识 | 企业内部知识不在模型中 | 接入私有知识库检索 |
| 可追溯性 | 无法知道答案的来源 | 检索文档可作为引用来源 |
二、RAG核心架构
一张图理解RAG全流程:

RAG工作流程:
- 索引阶段(Indexing):将文档切分成chunk,通过Embedding模型编码,存入向量数据库
- 检索阶段(Retrieval):用户query编码为向量,在向量库中检索Top-K相关文档
- 生成阶段(Generation):将检索到的文档作为上下文,一起送给LLM生成答案
三、向量数据库选型
| 数据库 | 优势 | 适用场景 | 开源 |
|---|---|---|---|
| Milvus | 性能强、功能全 | 生产级大规模 | ✅ |
| Chroma | 轻量、易用 | 快速原型 | ✅ |
| Qdrant | Rust实现、高性能 | 云原生部署 | ✅ |
| Weaviate | 原生混合检索 | 多模态 | ✅ |
| FAISS | Facebook出品 | 离线场景 | ✅ |
四、Embedding模型选择
python
# 主流Embedding模型对比
from sentence_transformers import SentenceTransformer
models = {
'bge-large-zh': '星辰语义平台-BGE-Large-ZH', # 中文最优
'm3e-large': 'm3e-large', # 源码开源
'text2vec-large': 'text2vec-large-chinese', # 中文支持好
'e5-large-v2': 'E5-Large-V2', # 多语言支持
}
# 使用示例
model = SentenceTransformer('BAAI/bge-large-zh-v1.5')
query_embedding = model.encode("如何优化Transformer的推理速度?")
doc_embeddings = model.encode(["FlashAttention是一种高效的注意力机制..."])
中文Embedding模型推荐:
| 模型 | 维度 | 中文效果 | 特点 |
|---|---|---|---|
| BGE-Large-ZH | 1024 | ⭐⭐⭐⭐⭐ | 效果最佳 |
| M3E-Large | 1024 | ⭐⭐⭐⭐ | 开源可商用 |
| text2vec-large | 1024 | ⭐⭐⭐⭐ | 适合中文 |
五、检索优化技术
5.1 混合检索
单一向量检索有局限,实际场景推荐混合检索:
python
# 混合检索示例:向量检索 + 关键词检索
from rank_bm25 import BM25Okapi
import numpy as np
def hybrid_search(query, vector_db, top_k=5, alpha=0.7):
"""
alpha: 向量检索权重,(1-alpha)为关键词检索权重
"""
# 1. 向量检索
vector_results = vector_db.search(
embed(query), top_k=top_k*2
)
# 2. BM25关键词检索
bm25_scores = bm25_model.get_scores(tokenize(query))
bm25_results = np.argsort(bm25_scores)[::-1][:top_k*2]
# 3. RRF融合排序
fused_scores = {}
for rank, doc_id in enumerate(vector_results):
fused_scores[doc_id] = fused_scores.get(doc_id, 0) + alpha * (1 / (60 + rank))
for rank, doc_id in enumerate(bm25_results):
fused_scores[doc_id] = fused_scores.get(doc_id, 0) + (1-alpha) * (1 / (60 + rank))
return sorted(fused_scores.items(), key=lambda x: -x[1])[:top_k]
5.2 重排序(Reranker)
初筛结果用Cross-Encoder重排,提升精度:
python
from sentence_transformers import CrossEncoder
# 使用BAAI/bge-reranker-large重排序
reranker = CrossEncoder('BAAI/bge-reranker-large')
def rerank(query, candidates, top_n=5):
pairs = [[query, doc] for doc in candidates]
scores = reranker.predict(pairs)
reranked = sorted(zip(candidates, scores), key=lambda x: -x[1])
return [doc for doc, _ in reranked[:top_n]]
5.3 查询改写(Query Rewrite)
用户query往往不够精准,需要改写:
python
# 使用大模型改写查询
def query_rewrite(query, llm):
rewrite_prompt = f"""
请将下面这个查询改写成3个不同的表达方式,每个一行:
原查询:{query}
要求:
1. 保持原意
2. 使用不同的表述方式
3. 可以补充缺失的背景信息
"""
response = llm.invoke(rewrite_prompt)
rewrites = response.content.strip().split('\n')
return rewrites[:3]
六、文档处理实战
6.1 文档加载与切分
python
from langchain_community.document_loaders import PyPDFLoader, UnstructuredMarkdownLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 加载PDF文档
loader = PyPDFLoader("技术文档.pdf")
documents = loader.load()
# 切分策略:按段落,保持上下文
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 每块token数
chunk_overlap=100, # 块间重叠,保证连续性
separators=["\n\n", "\n", "。", "!", "?", " ", ""]
)
chunks = text_splitter.split_documents(documents)
print(f"切分后得到 {len(chunks)} 个文本块")
6.2 元数据增强
python
# 为每个chunk添加元数据,便于后续过滤
for i, chunk in enumerate(chunks):
chunk.metadata = {
"source": "技术文档.pdf",
"page": i // 10 + 1, # 估算页码
"chunk_id": i,
"category": "架构设计", # 可按章节自动标注
"timestamp": "2024-12-01"
}
七、RAG评估与优化
7.1 评估指标
python
# RAG评估框架RAGAS
from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevancy, context_relevancy, context_precision
# 准备评估数据
eval_dataset = [
{
"question": "Transformer的注意力机制原理是什么?",
"answer": "Transformer使用自注意力机制...",
"contexts": ["注意力机制通过Query、Key、V..."],
"ground_truth": "Transformer通过缩放点积注意力..."
}
]
# 评估
result = evaluate(eval_dataset, metrics=[faithfulness, answer_relevancy])
print(result)
7.2 迭代优化流程
查询 → 检索 → 生成 → 评估 → 发现问题 → 优化
常见问题及解决方案:
├── 召回不准确 → 优化Embedding/混合检索
├── 上下文过长 → 使用Context Compression
├── 生成幻觉 → 增加 faithfulness prompt
└── 答案不完整 → 添加query扩展
八、生产级RAG架构
┌──────────────────────────────────────────────────────┐
│ RAG生产架构 │
├──────────────────────────────────────────────────────┤
│ 数据源:PDF/Word/网页/数据库 │
│ ↓ │
│ 文档解析:PyMuPDF / Unstructured │
│ ↓ │
│ 文本切分:RecursiveCharacterTextSplitter │
│ ↓ │
│ Embedding:BGE-Large-ZH │
│ ↓ │
│ 向量数据库:Milvus / Qdrant │
├──────────────────────────────────────────────────────┤
│ 查询 pipeline:改写→检索→重排→压缩 │
├──────────────────────────────────────────────────────┤
│ 生成:GPT-4 / Qwen / GLM │
│ ↓ │
│ 评估:RAGAS / Trulens │
└──────────────────────────────────────────────────────┘
九、总结
RAG是当前大模型落地最成熟的技术路径。建议学习路线:
- 入门:理解RAG基本流程,会用LangChain实现
- 进阶:掌握混合检索、重排序、Query改写
- 生产:了解评估体系、缓存策略、增量更新
未来RAG将向多模态、主动学习、自适应检索方向演进。
推荐学习资源:
- RAG综述论文:arxiv.org/abs/2312.10997
- LangChain RAG教程:python.langchain.com
- 星辰语义平台:BAAI/bge模型