共计 2097 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点:为什么需要 RAG?
传统生成模型(如 GPT 系列)在知识密集型任务中面临三个核心问题:

- 事实性错误 :模型可能生成看似合理但实际错误的答案(Hallucination)
- 知识滞后 :预训练后模型参数固定,无法动态更新知识
- 长尾失效 :对专业领域或低频知识的表现不稳定
以医疗问答场景为例,2023 年 JAMA Internal Medicine 的研究显示:GPT- 4 在临床问题上错误率高达 27%,其中 63% 的错误属于事实性错误。
技术对比:检索方案的选型
向量检索(如 FAISS)
- 优点 :
- 毫秒级响应(100 万条数据约 50ms)
- 支持稠密向量 + 稀疏向量混合检索
- 成熟的增量索引方案
- 缺点 :
- 需要高质量 embedding 模型
- 对多跳推理支持较弱
图数据库检索(如 Neo4j)
- 优点 :
- 天然支持关系推理
- 可解释性强
- 缺点 :
- 千级节点时延迟明显上升
- 需要人工设计 schema
实际选型建议:
# 混合检索方案伪代码
if 需要精确匹配 (如产品 ID):
走传统数据库查询
elif 需要语义搜索:
走向量检索
elif 需要关系推理:
走图数据库
核心架构设计
典型 RAG 系统包含以下关键模块:
- Query 预处理层
- 拼写纠正(pySpellChecker)
- 同义词扩展(WordNet)
-
意图识别(BERT 分类)
-
检索层
- 向量索引(FAISS/HNSW)
-
混合分数 = 0.6 语义相似度 + 0.4BM25
-
生成层
- 提示词工程:
请基于以下证据回答问题:{context} 问题:{query} 要求:如证据不足请回答 "不确定"
代码实现实战
FAISS 检索优化
import faiss
import numpy as np
class VectorSearch:
"""FAISS 向量检索封装
Attributes:
index: FAISS 索引对象
dimension: 向量维度
"""
def __init__(self, dimension: int):
self.index = faiss.IndexFlatIP(dimension)
def add_vectors(self, vectors: np.ndarray):
"""批量添加向量"""
assert vectors.ndim == 2
self.index.add(vectors)
def search(self, query: np.ndarray, k=5) -> tuple:
"""带 score 的 topk 检索"""
D, I = self.index.search(query, k)
return D[0], I[0] # 分数, ID 列表
LangChain 集成示例
from langchain.chains import RetrievalQA
from langchain.embeddings import HuggingFaceEmbeddings
# 1. 初始化检索器
embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5")
retriever = FAISS.load_local("index_dir", embeddings).as_retriever()
# 2. 构建问答链
qa_chain = RetrievalQA.from_chain_type(llm=ChatOpenAI(temperature=0),
chain_type="stuff",
retriever=retriever,
return_source_documents=True
)
# 3. 带溯源的回答
result = qa_chain({"query": "肺癌的早期症状有哪些?"})
print(f"Answer: {result['result']}")
print(f"Sources: {result['source_documents']}")
生产环境关键考量
冷启动优化
- 预计算策略:
- 对知识库所有段落预生成 embedding
- 建立 FAQ 的缓存回答
多租户隔离
# 通过命名空间隔离
index = faiss.IndexIDMap2()
index.add_with_ids(
vectors,
ids=namespace_id * 1e6 + doc_ids # 前几位表示租户
)
常见陷阱与解决方案
- 低召回率问题
- 现象:检索不到相关文档
-
解决:
- 添加 query 扩展(如 ” 咳嗽 医学名称 ”)
- 调整检索权重(BM25 vs 向量)
-
生成偏离问题
- 现象:模型忽略检索结果
-
解决:
- 在 prompt 中加入强制引用标记
- 使用 LLM-as-judge 验证一致性
-
时效性问题
- 现象:回答过时信息
- 解决:
- 建立版本化索引(每周增量更新)
- 添加时效性过滤器
延伸思考
- 当检索到冲突证据时(如不同论文结论相反),如何设计仲裁机制?
- 如何评估 RAG 系统的事实准确性(相比传统 NLP 指标)?
- 在实时性要求极高的场景(如股票咨询),如何优化端到端延迟?
参考文献
正文完
