共计 2023 个字符,预计需要花费 6 分钟才能阅读完成。
背景与痛点:为什么需要 RAG?
传统的生成式对话模型(如 GPT 系列)虽然能产生流畅的文本,但在实际应用中暴露了两个核心问题:

- 事实性错误 :模型可能生成看似合理但实际错误的信息(即 ” 幻觉 ” 现象)
- 知识滞后 :模型训练后无法动态更新知识,导致回答时效性差
举个例子,当用户询问 ”2023 年诺贝尔物理学奖得主是谁 ” 时,传统模型可能给出错误答案或直接表示不知道。这正是 RAG 技术要解决的关键痛点。
RAG 技术原理:两阶段架构解析
RAG(Retrieval-Augmented Generation)的核心思想很直观:先检索相关文档,再基于检索结果生成回答。这种架构结合了检索系统的高准确性和生成模型的灵活性。
检索阶段关键技术
- 向量化表示 :使用预训练模型(如 BERT、Sentence-BERT)将文档和查询转换为稠密向量
- 相似度计算 :通常采用余弦相似度衡量查询与文档的相关性
- 索引优化 :使用 FAISS 等库实现高效的近似最近邻搜索
# 使用 Sentence-BERT 进行向量化示例
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
query_embedding = model.encode("2023 年诺贝尔物理学奖得主")
生成阶段关键技术
- 上下文融合 :将检索到的文档作为额外上下文输入生成模型
- 提示工程 :设计合理的 prompt 模板引导模型利用检索结果
- 置信度控制 :当检索结果不相关时,让模型回退到通用回答
完整实现方案
1. 文档预处理与向量化
import pandas as pd
from tqdm import tqdm
# 加载知识库文档
docs = pd.read_csv('knowledge_base.csv')
# 批量生成文档向量
doc_embeddings = []
for doc in tqdm(docs['content']):
embedding = model.encode(doc)
doc_embeddings.append(embedding)
2. 构建 FAISS 索引
import faiss
import numpy as np
# 转换为 numpy 数组
embeddings = np.array(doc_embeddings).astype('float32')
# 创建 FAISS 索引
dimension = embeddings.shape[1]
index = faiss.IndexFlatIP(dimension)
index.add(embeddings)
3. 检索增强生成
from transformers import pipeline
generator = pipeline('text-generation', model='gpt-3.5-turbo')
def rag_response(query, top_k=3):
# 1. 检索相关文档
query_embed = model.encode(query)
D, I = index.search(np.array([query_embed]), top_k)
# 2. 构造 prompt
context = "\n".join([docs.iloc[i]['content'] for i in I[0]])
prompt = f""" 基于以下信息回答问题:{context}
问题:{query}
回答:"""
# 3. 生成回答
return generator(prompt, max_length=200)
性能优化实战技巧
批处理与缓存
- 对批量查询进行并行向量化
- 对高频查询结果建立缓存
- 使用量化技术减小索引体积
索引更新策略
# 增量更新示例
def update_index(new_docs):
new_embeddings = model.encode(new_docs)
index.add(np.array(new_embeddings).astype('float32'))
避坑指南:我们踩过的坑
- 检索结果不相关 :
- 解决方案:尝试不同的 embedding 模型,调整检索阈值
-
经验:all-MiniLM-L6-v2 在英文表现好,paraphrase-multilingual-MiniLM-L12-v2 适合多语言
-
生成偏离上下文 :
- 解决方案:强化 prompt 设计,明确指示模型使用检索内容
-
示例 prompt:” 严格基于以下信息回答,若信息不足请回复 ’ 不知道 ’:\n{context}”
-
长文档处理不佳 :
- 解决方案:将大文档分块,建立层次化索引
开放性问题与思考方向
在实际应用中,我们发现几个值得深入探讨的问题:
- 如何动态评估检索结果的质量?是否需要引入二次验证机制?
- 当检索到多个矛盾的信息源时,生成模型应该如何取舍?
- 对于专业垂直领域,是否需要领域自适应的 embedding 模型?
RAG 技术正在快速发展,期待看到更多关于检索策略与生成模型协同优化的创新方案。如果你在实际应用中遇到了有趣的问题或有独特的解决方案,欢迎交流讨论!
正文完
