跳转至

检索增强生成(RAG)

RAG(Retrieval-Augmented Generation) 是将信息检索LLM 生成相结合的技术框架。它让 LLM 在回答问题前,先从外部知识库中检索相关信息,然后基于检索到的内容生成答案——从根本上缓解了 LLM 的"幻觉"和知识过时问题。


为什么需要 RAG?

LLM 虽然强大,但存在三个根本性的局限:

局限 说明 示例
知识截止 训练数据有截止日期,不知道之后发生的事 "2026 年世界杯冠军是谁?"→ 无法回答
幻觉问题 不知道时会"一本正经地胡说八道" 编造不存在的论文、虚构的统计数据
缺乏私有知识 不了解企业内部文档、个人笔记等 无法回答"公司报销流程是什么?"

RAG 的解决思路很简单:让模型开卷考试——回答问题前先查资料。

一句话理解

RAG = 搜索引擎 + LLM。先搜,再答。


RAG 的基本流程

graph LR
    A["用户提问"] --> B["检索器<br>Retriever"]
    B --> C["知识库<br>向量数据库"]
    C --> B
    B --> D["构建 Prompt<br>问题 + 检索结果"]
    D --> E["LLM 生成<br>答案"]

完整流程分三步

第 1 步:索引(Indexing)——建设知识库

将文档预处理后存入向量数据库,这是一次性的离线操作:

原始文档 → 文本切块(Chunking)→ Embedding 向量化 → 存入向量数据库

第 2 步:检索(Retrieval)——找到相关信息

用户提问时,将问题也转换为向量,在向量数据库中搜索最相似的文档块:

用户问题 → Embedding → 向量相似度搜索 → 返回 Top-K 个最相关文档块

第 3 步:生成(Generation)——基于检索结果回答

将检索到的文档块和用户问题一起喂给 LLM:

Prompt = "基于以下参考资料回答问题:\n\n[检索到的文档]\n\n问题:[用户问题]"

核心组件详解

文本切块(Chunking)

长文档需要被切分为适当大小的块(Chunk),因为:

  1. Embedding 模型有长度限制(通常 512~8192 Token)
  2. 检索时需要精确定位到具体段落,而非整篇文档
  3. LLM 的上下文窗口有限,不能塞入所有内容

常见切块策略:

策略 说明 适用场景
固定长度切块 按固定 Token 数切分(如每 512 Token) 简单场景
重叠切块 相邻块有重叠部分(如重叠 50 Token) 避免关键信息被截断
语义切块 按段落、章节、句子等语义边界切分 结构化文档
递归切块 先按大标题切,再按段落切,逐层递归 长文档、书籍

块大小的权衡

  • 块太小:缺少足够的上下文,检索结果可能不完整
  • 块太大:包含太多无关信息,稀释了关键内容
  • 通常推荐:256~1024 Token,根据文档类型调整

Embedding(向量化)

Embedding 模型将文本映射到高维向量空间,使得语义相似的文本在向量空间中距离更近

"猫喜欢在阳光下睡觉" → [0.23, -0.45, 0.87, ...] (768 维)
"小猫爱晒太阳"       → [0.21, -0.42, 0.85, ...] (768 维)  ← 向量非常接近!
"量子力学的基本原理" → [-0.56, 0.78, -0.12, ...] (768 维)  ← 向量差异很大

常用的 Embedding 模型:

模型 维度 特点
OpenAI text-embedding-3-large 3072 效果好,需 API 调用
BGE-large-zh 1024 中文效果优秀,开源
E5-mistral-7b 4096 大模型做 Embedding,效果强
GTE-Qwen2 多种 阿里开源,多语言

向量数据库

专门用于存储和高效检索向量的数据库:

数据库 特点
FAISS Meta 开源,纯本地,速度极快
Milvus 开源分布式向量数据库,适合大规模部署
ChromaDB 轻量级,适合快速原型开发
Pinecone 云服务,全托管,易上手
Weaviate 支持混合搜索(向量 + 关键词)

相似度计算

检索时需要计算用户问题向量与知识库中所有文档块向量的相似度:

余弦相似度(最常用):

\[\text{sim}(A, B) = \frac{A \cdot B}{\|A\| \times \|B\|}\]

值域为 \([-1, 1]\),1 表示完全相同,0 表示无关。


进阶 RAG 技术

查询改写(Query Rewriting)

用户的原始问题可能不适合直接用于检索。查询改写让 LLM 先优化查询:

原始问题:"这个东西怎么设置?"
→ 改写后:"如何配置系统的网络代理设置?"

常见策略: - HyDE(Hypothetical Document Embedding):让 LLM 先生成一个"假想的答案",用这个答案去检索(因为答案和文档的语义更接近) - 多查询生成:将一个问题拆成多个不同角度的子查询,分别检索后合并结果

重排序(Re-ranking)

向量检索返回的 Top-K 结果中,排序可能不够精确。Re-ranker 对检索结果进行二次排序:

向量检索 → Top 20 → Re-ranker 精排 → Top 5 → 喂给 LLM

Re-ranker 通常使用交叉编码器(Cross-Encoder),它将查询和文档拼接输入,能捕捉更细粒度的语义关系,精度显著高于向量检索的双塔模型。

单纯的向量搜索可能会遗漏关键词精确匹配的结果。混合搜索结合两种方式:

  • 向量搜索(语义):捕捉语义相似性。"汽车" 能匹配 "轿车"
  • 关键词搜索(BM25):捕捉精确匹配。专有名词、代码变量名
\[\text{最终得分} = \alpha \cdot \text{向量分数} + (1-\alpha) \cdot \text{BM25 分数}\]

多跳 RAG

有些问题需要多步检索才能回答:

问题:"OpenAI CEO 的妻子是哪年出生的?"

第 1 跳检索:"OpenAI CEO" → Sam Altman
第 2 跳检索:"Sam Altman 妻子" → 无公开信息

答:根据检索到的信息,无法确认该问题的答案。

RAG vs 微调:如何选择?

对比维度 RAG 微调
知识更新 ✅ 只需更新知识库 ❌ 需要重新训练
成本 低(只需 Embedding + 向量数据库) 高(GPU 训练)
幻觉控制 ✅ 答案有据可查 一般(仍可能幻觉)
私有知识 ✅ 天然支持 需要私有数据训练
深度理解 一般(依赖检索质量) ✅ 模型内化知识
适用场景 知识库问答、客服、文档助手 特定风格/格式、专业领域

实践建议

  • 优先尝试 RAG:成本低、见效快、易维护
  • RAG 效果不好时再考虑微调:当任务需要深度理解特定领域的"语感"或风格
  • 最佳方案往往是两者结合:用微调让模型掌握领域知识和回答风格,再用 RAG 补充最新信息

简易 RAG 实现思路

一个最小可用的 RAG 系统只需要:

1. 准备文档 → 切块
2. 调用 Embedding API → 向量化
3. 存入 FAISS / ChromaDB
4. 用户提问 → 向量化 → 检索 Top-K
5. 拼接 Prompt → 调用 LLM → 返回答案

主流框架:

框架 特点
LangChain 生态丰富,组件多,适合快速原型
LlamaIndex 专注于 RAG,索引和检索能力强
Haystack 端到端 RAG 框架,生产级