RAG 检索增强生成:从原理到落地
RAG(Retrieval-Augmented Generation,检索增强生成)是将大语言模型与外部知识库相结合的技术方案。它解决了 LLM 的知识时效性问题和幻觉问题,是当前企业级 AI 应用最主流的技术架构。
一、为什么需要 RAG
尽管 LLM 在很多任务上表现出色,但它存在几个固有缺陷:
- 知识截止:模型的训练数据有时间截止点,无法获取最新信息
- 幻觉问题:模型可能生成看似合理但实际错误的内容
- 领域知识不足:通用模型对企业内部知识了解有限
- 可追溯性差:无法给出回答的来源依据
RAG 通过在生成前检索相关文档,有效缓解了这些问题。
二、RAG 核心架构
一个标准的 RAG 系统包含两个阶段:索引阶段 和 查询阶段。
2.1 索引阶段
文档 → 分块(Chunking) → 向量化(Embedding) → 存入向量数据库文档分块是 RAG 的关键环节,常见的分块策略包括:
| 策略 | 优点 | 缺点 |
|---|---|---|
| 固定长度分块 | 实现简单 | 可能切断语义 |
| 按段落分块 | 保留语义完整性 | 块大小不均匀 |
| 递归分块 | 灵活适配 | 参数调优复杂 |
| 语义分块 | 语义边界最佳 | 计算成本高 |
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\n", "。", "!", "?", ".", " "]
)
chunks = splitter.split_text(document)2.2 查询阶段
用户问题 → 向量化 → 检索相似文档 → 拼接上下文 → LLM 生成回答def rag_query(question: str, vector_db, llm, top_k: int = 5):
# 1. 检索相关文档
results = vector_db.search(question, top_k=top_k)
context = "\n\n".join([doc.text for doc in results])
# 2. 构建提示词
prompt = f"""基于以下参考资料回答问题。如果资料中没有相关信息,请说明。
参考资料:
{context}
问题:{question}
回答:"""
# 3. 生成回答
answer = llm.generate(prompt)
return answer, results三、进阶优化策略
3.1 混合检索
单一的向量检索可能遗漏关键词匹配的结果。混合检索结合了稠密检索(向量相似度)和稀疏检索(BM25 关键词匹配):
class HybridRetriever:
def __init__(self, vector_db, bm25_index, alpha=0.7):
self.vector_db = vector_db
self.bm25_index = bm25_index
self.alpha = alpha # 向量检索权重
def search(self, query: str, top_k: int = 10):
# 向量检索
vector_results = self.vector_db.search(query, top_k=top_k * 2)
# BM25 检索
bm25_results = self.bm25_index.search(query, top_k=top_k * 2)
# 融合排序
return self.reciprocal_rank_fusion(
vector_results, bm25_results, top_k
)3.2 查询改写
用户的原始问题可能不够清晰或不够适合检索。查询改写可以提升检索效果:
- HyDE(Hypothetical Document Embeddings):先让 LLM 生成一个假设性回答,用回答的向量去检索
- 多查询扩展:将一个问题改写为多个不同角度的查询
- Step-Back Prompting:先提出更高层次的抽象问题
3.3 重排序
对初步检索的结果进行重排序,将最相关的文档排在前面:
from sentence_transformers import CrossEncoder
reranker = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")
def rerank(query: str, documents: list, top_k: int = 3):
pairs = [(query, doc.text) for doc in documents]
scores = reranker.predict(pairs)
ranked = sorted(zip(documents, scores), key=lambda x: x[1], reverse=True)
return [doc for doc, score in ranked[:top_k]]四、生产环境部署
4.1 向量数据库选型
| 数据库 | 特点 | 适用场景 |
|---|---|---|
| Milvus | 高性能、分布式 | 大规模生产环境 |
| ChromaDB | 轻量级、易上手 | 快速原型开发 |
| Pinecone | 全托管、零运维 | 不想自建基础设施 |
| pgvector | 基于 PostgreSQL | 已有 PG 基础设施 |
4.2 评估指标
RAG 系统的核心评估指标:
- 召回率(Recall):相关文档是否被检索到
- 精确率(Precision):检索结果中相关文档的比例
- 忠实度(Faithfulness):回答是否忠于检索到的文档
- 相关度(Relevancy):回答是否与问题相关
from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevancy, context_recall
result = evaluate(
dataset=eval_dataset,
metrics=[faithfulness, answer_relevancy, context_recall],
)
print(result)五、常见问题与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 检索不到相关内容 | 分块策略不合理 | 优化分块大小和重叠 |
| 回答包含幻觉 | 模型过度生成 | 加强提示词约束 |
| 响应延迟高 | 检索耗时长 | 使用缓存和索引优化 |
| 多轮对话效果差 | 缺少上下文管理 | 添加查询改写和历史摘要 |
RAG 技术正在快速成熟,从简单的"检索+生成"演进到模块化、可编排的复杂系统。掌握 RAG 的核心原理和优化技巧,是构建高质量 AI 应用的关键。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。