从原理到工程落地:RAG(Retrieval-Augmented Generation)技术全解

0 阅读24分钟

从原理到工程落地:RAG(Retrieval-Augmented Generation)技术全解

这不是一篇“RAG 是什么”的入门短文,而是一篇面向工程实践的完整技术博客。
如果你已经会用大模型,但还不清楚为什么模型会“胡说八道”、为什么向量检索不稳定、为什么 chunk 切分一改效果就崩,那么这篇文章会把 RAG 的核心问题讲透。


请添加图片描述

一、什么是 RAG?

RAG,全称 Retrieval-Augmented Generation,中文通常翻译为 检索增强生成

它的核心思想非常直接:

不要只依赖大模型参数里“记住”的知识,而是在回答问题前,先从外部知识库中检索相关内容,再把检索结果作为上下文交给大模型生成答案。

也就是说,RAG 不是让模型“凭记忆作答”,而是让模型“先查资料,再回答”。

从系统结构上看,RAG 通常由两部分组成:

  1. Retrieval(检索):从外部知识库中找出与问题最相关的信息;
  2. Generation(生成):将这些信息连同用户问题一起输入大模型,生成最终答案。

二、为什么需要 RAG?

大语言模型很强,但它天生有几个问题:

1. 参数知识是“静态的”

模型训练完成后,它内部知识就被冻结了。
如果外部世界发生变化,比如:

  • 公司制度更新
  • 新论文发布
  • 数据库新增记录
  • 产品价格变动
  • 法规修订

那么模型参数里的知识很可能已经过时。

2. 大模型容易幻觉(Hallucination)

当模型“不知道答案”时,它经常不会老实说不知道,而是生成一个语言上流畅但事实错误的回答。
这在聊天场景里只是体验问题,但在以下场景里就会变成严重风险:

  • 医疗问答
  • 法律咨询
  • 金融风控
  • 企业知识库问答
  • 科研辅助

3. 私有知识不在预训练语料中

企业内部文档、项目规范、代码仓库、会议纪要、个人笔记,这些内容通常不可能出现在通用大模型的预训练数据中。

所以,如果你希望模型回答“你自己的知识”,就必须给它接入外部知识源。


三、RAG 的本质:让 LLM 从“闭卷考试”变成“开卷考试”

用一句话概括:

RAG = 大模型 + 外部知识库 + 检索机制 + 上下文注入

如果把大模型比作一个学生:

  • 纯 LLM:闭卷考试,只能凭记忆答题;
  • RAG:开卷考试,可以先翻资料再作答。

这件事带来的意义非常大:

  • 提升答案的事实准确性
  • 降低幻觉
  • 支持私有知识接入
  • 支持实时知识更新
  • 让回答具备可追溯性(可以给出引用来源)

四、RAG 的标准工作流

一个典型 RAG 系统通常分成两条链路:

  • 离线链路:构建知识库
  • 在线链路:检索并生成回答

五、离线链路:如何把文档变成“可检索知识”

离线链路的目标是:

把原始文档处理成适合检索的结构化知识索引。

典型步骤如下:

1. 文档采集

知识源可以来自:

  • PDF
  • Word
  • Markdown
  • 网页
  • 数据库记录
  • FAQ
  • Wiki
  • 代码仓库
  • API 文档
  • 日志与工单系统

2. 文档清洗

原始文档往往并不适合直接检索,需要先清洗:

  • 去掉页眉页脚
  • 去掉目录噪声
  • 去掉重复段落
  • 处理 OCR 错误
  • 保留标题层级
  • 保留表格、公式、代码块边界
  • 标记元数据(来源、时间、作者、标签、权限)

清洗质量会直接影响后续检索质量。很多 RAG 项目效果差,不是模型不行,而是知识入库阶段就已经污染了。

3. Chunk 切分

这是 RAG 中最关键的步骤之一。

因为大多数检索系统不是按整本书检索,而是按“片段”检索。
所以必须把文档切成多个小块,也就是 chunk

为什么不能整篇文档直接向量化?

因为整篇文档太长,会导致:

  • 语义被平均化,关键信息被稀释
  • 检索粒度过粗
  • 命中相关内容时带来大量无关上下文
  • 占用上下文窗口
常见切分策略
(1)固定长度切分

例如每 500 个 token 切一段,重叠 100 个 token。

优点:

  • 简单直接
  • 易实现

缺点:

  • 容易切断语义
  • 可能把完整定义拆开
  • 对结构化文档不友好
(2)按段落/标题结构切分

依据 Markdown 标题、PDF 章节、HTML DOM 结构切分。

优点:

  • 更符合语义边界
  • 更适合技术文档、规范文档

缺点:

  • 依赖文档结构质量
  • 某些段落仍然可能过长
(3)语义切分

通过 embedding 相似度、句间边界检测等方式,自动寻找语义断点。

优点:

  • 更精细
  • 理论上更符合语义单元

缺点:

  • 实现复杂
  • 工程成本高
Chunk 重叠(overlap)

为了避免关键信息落在 chunk 边界上,通常会给相邻 chunk 添加一定重叠。

例如:

  • chunk_size = 500
  • overlap = 100

这样前后 chunk 会共享一部分内容,提高召回稳定性。

Chunk 大小没有统一最优值

很多人会问:“chunk 到底设多少最好?”

答案是:没有绝对最优,只能结合任务调优。

经验上:

  • FAQ / 短问答:chunk 可小一些
  • 技术文档 / API 文档:chunk 中等
  • 法律合同 / 医疗报告:更依赖结构化切分
  • 需要跨段推理的任务:chunk 不能太碎

六、向量化:把文本变成可计算的表示

切分后的 chunk 需要送入 Embedding 模型,转成向量表示。

设某个文本 chunk 为 dd,它经过 embedding 模型后得到向量:

dRn\mathbf{d} \in \mathbb{R}^n

用户查询 qq 也会被编码成向量:

qRn\mathbf{q} \in \mathbb{R}^n

这样,文本相似性问题就被转化成向量相似性问题。

1. 为什么向量能表示语义?

Embedding 模型的目标,是让“语义相近”的文本在向量空间中彼此靠近,让“语义不相关”的文本彼此远离。

例如:

  • “如何安装 Python” 与 “Python 安装步骤”
  • “什么是向量数据库” 与 “向量库原理”

它们在表面文字上不同,但语义接近,因此向量距离应该更近。

2. 常见相似度计算

最常用的是 余弦相似度

sim(q,d)=qdqd\text{sim}(\mathbf{q}, \mathbf{d}) = \frac{\mathbf{q} \cdot \mathbf{d}}{||\mathbf{q}|| \, ||\mathbf{d}||}

它衡量的是两个向量夹角的接近程度。
值越大,表示语义越相近。

除了余弦相似度,还常用:

  • 点积(dot product)
  • 欧氏距离(Euclidean distance)
  • 内积近似

3. Embedding 模型的选择很重要

RAG 的上限,很多时候不在 LLM,而在检索质量。
而检索质量的核心之一,就是 embedding 模型。

选择 embedding 模型时,需要考虑:

  • 是否支持中文
  • 是否适合长文本
  • 是否适合问答匹配
  • 是否支持多语言
  • 维度大小
  • 推理速度
  • 部署成本

七、索引构建:为什么不能暴力逐条比对?

假设知识库里有 100 万个 chunk。
每次用户提问,都要把 query 向量和这 100 万个向量逐一计算相似度,那在线延迟会非常高。

所以需要构建向量索引,以支持近似最近邻搜索(ANN, Approximate Nearest Neighbor)。

1. 常见向量索引结构

(1)Flat Index

最直接的方式,全部向量暴力比较。

优点:

  • 结果最准确

缺点:

  • 大规模场景不可用
(2)IVF(Inverted File Index)

先把向量空间聚类,检索时先定位到若干簇,再在局部搜索。

优点:

  • 检索速度快

缺点:

  • 可能损失少量召回率
(3)HNSW(Hierarchical Navigable Small World)

一种图索引结构,通过多层近邻图实现高效搜索。

优点:

  • 检索速度快
  • 召回率高
  • 工程上非常常用

缺点:

  • 建索引内存开销较大
(4)PQ / OPQ

通过量化压缩向量,降低存储成本。

优点:

  • 节省内存
  • 适合超大规模向量库

缺点:

  • 存在量化误差

2. 常见向量数据库

常见方案包括:

  • FAISS
  • Milvus
  • Weaviate
  • Qdrant
  • Pinecone
  • Elasticsearch / OpenSearch(支持向量检索)
  • pgvector(PostgreSQL 扩展)

在小规模实验中,FAISS 很常见;
在生产级系统中,更常见的是带过滤、权限、持久化能力的向量数据库。


八、在线链路:用户提问后系统到底做了什么?

当用户输入一个问题时,RAG 系统通常会经历以下步骤:

flowchart TD
    A[用户问题] --> B[Query 预处理]
    B --> C[Embedding 编码]
    C --> D[向量检索 Top-k]
    D --> E[重排序 Rerank]
    E --> F[上下文组装]
    F --> G[Prompt 构建]
    G --> H[LLM 生成答案]
    H --> I[返回答案与引用]

下面逐步展开。


九、Query 预处理:为什么“原始问题”不一定适合直接检索?

用户的自然语言问题并不总是最适合检索的形式。
因此,很多系统会在检索前先做查询改写。

1. 常见 Query 预处理操作

  • 拼写纠错
  • 同义词扩展
  • 去除口语噪声
  • 补全省略信息
  • 多轮对话改写为独立问题
  • 查询分解(复杂问题拆为多个子问题)

例如:

原问题:

它的训练阶段是怎么做的?

如果直接检索,系统不知道“它”是谁。
必须结合对话历史改写为:

某篇论文在训练阶段的具体流程是什么?

2. 多查询检索(Multi-Query Retrieval)

一个问题可以生成多个语义等价的检索表达,例如:

  • RAG 的 rerank 是做什么的
  • 重排序在 RAG 中的作用
  • 为什么向量检索后还要二次排序

然后把多路检索结果融合,能提高召回率。

3. HyDE(Hypothetical Document Embeddings)

HyDE 的思想是:

先让 LLM “假想”写出一段可能的答案,再拿这段答案去做检索。

因为有些问题本身太短,语义稀疏,不利于检索;
而“假想答案”往往包含更丰富的语义线索,从而帮助召回更相关文档。


十、检索:Sparse、Dense、Hybrid 到底有什么区别?

RAG 的检索并不只有“向量检索”一种。

1. Sparse Retrieval(稀疏检索)

典型代表:BM25。

它基于关键词匹配、词频、逆文档频率等统计特征来检索文档。

优点
  • 对关键词、术语、专有名词很敏感
  • 可解释性强
  • 不依赖 embedding 模型
缺点
  • 语义泛化弱
  • 同义表达不容易匹配

2. Dense Retrieval(稠密检索)

即 embedding 向量检索。

优点
  • 擅长语义匹配
  • 对同义表达更鲁棒
缺点
  • 对精确术语、缩写、数字、版本号可能不敏感
  • 结果可解释性较弱

3. Hybrid Retrieval(混合检索)

工程上最常用。
即同时结合:

  • BM25 这类 sparse 检索
  • embedding 这类 dense 检索

再把两路结果融合。

为什么 Hybrid 常常更强?

因为它同时覆盖了两类能力:

  • 关键词精确命中
  • 语义相似匹配

尤其在技术文档、代码、企业知识库中,Hybrid 往往显著强于只用单一路径。


十一、Top-k 召回不是结束,Rerank 才是关键

很多初学者把 RAG 理解成:

向量检索 Top-3,然后直接丢给 LLM。

这在小 demo 里能跑,但在真实系统里往往不够。

因为第一阶段检索主要追求 高召回,会把“可能相关”的内容都拿回来;
但真正送给 LLM 的上下文窗口很有限,所以必须做第二阶段筛选,也就是 Rerank(重排序)

1. 为什么需要 Rerank?

向量召回的特点是“快,但不够精”。
它擅长从海量知识中筛出候选,但不能保证排序绝对最优。

Rerank 模型则更精细。它通常对每个候选文档和 query 做更深入的交互建模,然后输出更可靠的相关性分数。

2. Rerank 的典型方式

(1)Cross-Encoder

把 query 和 candidate chunk 拼接后一起送进模型,让模型直接判断相关性。

优点:

  • 精度高
  • 排序质量好

缺点:

  • 不能预先离线编码文档
(2)LLM as Judge

让大模型直接判断:

给定问题和候选文档,这段文档是否真的能支持回答?

优点:

  • 语义理解强

缺点:

  • 成本高
  • 延迟大

3. 为什么 Rerank 对 RAG 极其重要?

因为真正影响答案质量的,往往不是“有没有召回到相关文档”,而是:

最终喂给 LLM 的那几段上下文,是否真的最关键。

如果上下文中充满:

  • 高相似但不关键的信息
  • 重复内容
  • 噪声片段
  • 过时版本

那么 LLM 仍然会答偏。


十二、上下文组装:不是把检索结果简单拼起来就行

检索后的内容还需要做“上下文编排”。

1. 常见问题

如果直接把 Top-k chunk 按顺序拼接,可能出现:

  • 大量重复内容
  • 上下文断裂
  • 片段之间逻辑不连贯
  • 重要信息被埋没
  • 超出上下文长度限制

2. 常见优化策略

(1)去重

不同 chunk 可能来自同一段或高度相似内容,需要去重。

(2)按来源分组

同一文档的多个 chunk 可以合并展示,保持上下文完整性。

(3)父子块检索(Parent-Child Retrieval)

一种常见策略是:

  • 用小 chunk 建索引,提升检索粒度
  • 命中后返回其所属的大段父块,提升上下文完整性

这可以同时兼顾:

  • 检索精确度
  • 生成时的语义完整度
(4)最大边际相关性(MMR)

MMR 的目标不是只找“最像”的文档,而是同时兼顾:

  • 与 query 的相关性
  • 结果之间的多样性

其核心思想可写为:

MMR=argmaxdiRS[λSim(q,di)(1λ)maxdjSSim(di,dj)]\text{MMR} = \arg\max_{d_i \in R \setminus S} \left[ \lambda \cdot \text{Sim}(q, d_i) - (1-\lambda)\cdot \max_{d_j \in S}\text{Sim}(d_i, d_j) \right]

含义是:

  • 既要与问题相关
  • 又不要和已选内容太重复

这在 RAG 中非常重要,因为很多时候检索返回的多个结果只是“换个说法重复同一件事”。


十三、生成阶段:RAG 不是“让 LLM 随便发挥”

很多人以为只要把检索结果塞给大模型,答案自然就会更准确。
实际上不是。

1. Prompt 设计极其关键

一个常见的 RAG Prompt 模板:

你是一个基于知识库回答问题的助手。
请严格依据给定上下文回答,不要使用上下文之外的知识。
如果上下文不足以回答,请明确说明“根据当前资料无法确定”。

【问题】
{question}

【上下文】
{context}

【要求】
1. 优先使用上下文中的明确信息
2. 不要编造不存在的事实
3. 若存在多个来源冲突,指出冲突
4. 尽量给出引用来源

2. 生成阶段的几个关键约束

(1)限制模型只基于证据回答

这是降低幻觉的核心手段之一。

(2)要求模型显式说明“不知道”

比起“猜一个答案”,生产系统更需要“诚实拒答”。

(3)输出引用来源

例如:

  • 文档标题
  • 段落编号
  • URL
  • 页码
  • chunk ID

这样用户可以验证答案是否可信。

(4)处理冲突信息

如果知识库中存在多个版本,系统应该具备冲突识别与版本优先策略,而不是盲目融合。


十四、一个最小可运行的 RAG 示例(Python 版)

下面给出一个非常简化的 RAG 实现,用于展示核心流程。

1. 安装依赖

pip install sentence-transformers faiss-cpu transformers torch

2. 构建索引

from sentence_transformers import SentenceTransformer
import faiss
import numpy as np

# 1. 模拟知识库
documents = [
    "RAG 是 Retrieval-Augmented Generation,即检索增强生成。",
    "BM25 是经典的稀疏检索算法,依赖关键词匹配。",
    "Dense Retrieval 使用 embedding 向量进行语义检索。",
    "Rerank 用于对召回结果进行二次精排,提高最终上下文质量。",
    "MMR 可以在相关性和多样性之间做平衡。"
]

# 2. 加载 embedding 模型
embed_model = SentenceTransformer("BAAI/bge-base-zh-v1.5")

# 3. 文档向量化
doc_embeddings = embed_model.encode(documents, normalize_embeddings=True)
doc_embeddings = np.array(doc_embeddings, dtype=np.float32)

# 4. 建立 FAISS 索引
dim = doc_embeddings.shape[1]
index = faiss.IndexFlatIP(dim)  # 归一化后,内积等价于余弦相似度排序
index.add(doc_embeddings)

3. 检索

def retrieve(query, top_k=3):
    query_vec = embed_model.encode([query], normalize_embeddings=True)
    query_vec = np.array(query_vec, dtype=np.float32)
    scores, indices = index.search(query_vec, top_k)

    results = []
    for score, idx in zip(scores[0], indices[0]):
        results.append({
            "text": documents[idx],
            "score": float(score)
        })
    return results

query = "RAG 里面 rerank 是干什么的?"
results = retrieve(query, top_k=3)

for item in results:
    print(item)

4. 拼接上下文并生成

from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

gen_model_name = "Qwen/Qwen2.5-1.5B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(gen_model_name)
model = AutoModelForCausalLM.from_pretrained(
    gen_model_name,
    torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
    device_map="auto"
)

def generate_answer(query, retrieved_docs):
    context = "\n".join([f"- {x['text']}" for x in retrieved_docs])

    prompt = f"""
你是一个基于知识库回答问题的助手。
请严格根据给定上下文回答问题,不要编造。

【问题】
{query}

【上下文】
{context}

【回答】
"""

    messages = [{"role": "user", "content": prompt}]
    text = tokenizer.apply_chat_template(
        messages,
        tokenize=False,
        add_generation_prompt=True
    )
    inputs = tokenizer([text], return_tensors="pt").to(model.device)

    outputs = model.generate(
        **inputs,
        max_new_tokens=256,
        do_sample=False
    )

    response = tokenizer.decode(outputs[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True)
    return response

answer = generate_answer(query, results)
print(answer)

5. 这个最小示例省略了什么?

这个 demo 只是帮助理解主流程,真实生产系统通常还要补上:

  • 文档清洗
  • chunk 切分
  • 元数据过滤
  • 混合检索
  • reranker
  • 权限控制
  • 缓存
  • 引用回溯
  • 失败兜底
  • 评估系统
  • 监控与日志

十五、RAG 的核心优化点:真正决定效果的不是“接没接向量库”

很多项目之所以做出来“像玩具”,根本原因是只完成了最表层的架构拼装:

文档切分 -> embedding -> 向量库 -> Top-k -> LLM

这只是 RAG 的骨架,不是高质量 RAG 的完整形态。

下面这些点,才是真正影响效果的核心。


十六、优化点 1:Chunk 设计决定了知识表达颗粒度

常见失败模式

1. chunk 太大

问题:

  • 多个主题混在一起
  • 相似度被平均化
  • 召回到一大段无关内容
2. chunk 太小

问题:

  • 语义不完整
  • 定义、条件、结论被拆散
  • LLM 看不到完整证据链
3. 结构信息丢失

例如 API 文档中:

  • 标题
  • 参数说明
  • 返回值
  • 异常说明

如果切分时把这些结构打散,检索效果会明显下降。

实战建议

  • 优先保留标题层级
  • 对代码、表格、公式、列表做结构保留
  • 使用 parent-child 方案提升完整性
  • 对不同文档类型使用不同切分器

十七、优化点 2:Embedding 模型和任务要匹配

并不是任何 embedding 模型都适合任何任务。

1. 技术文档 vs 通用问答

技术文档通常包含:

  • 专有名词
  • 缩写
  • 版本号
  • 参数名
  • 函数名
  • 代码符号

如果 embedding 模型对这些不敏感,语义检索会“看起来相关,实际不准”。

2. 中文检索要注意中文模型适配

中文 RAG 如果直接用英文为主的 embedding 模型,效果通常不稳定。
需要优先选择中文或多语言表现好的 embedding 模型。

3. Query-Document 不一定是同分布

用户提问通常是口语化的,而文档通常是书面化、规范化的。
这意味着检索系统实际上在做 跨风格匹配
因此,专门为检索训练的 embedding 模型,通常比通用句向量模型更合适。


十八、优化点 3:Hybrid Retrieval 往往比纯向量检索更稳

纯向量检索的典型问题是:

  • “TCP 503” 这类关键词不够敏感
  • 版本号、数字、报错码检索差
  • 专有名词容易漂移到相似语义但错误文档

而 BM25 这种关键词检索,恰好擅长这些内容。

常见融合方式

(1)加权融合

设 dense 检索得分为 sds_d,sparse 检索得分为 sss_s,可构造融合分数:

s=αsd+(1α)sss = \alpha s_d + (1-\alpha) s_s

其中 α\alpha 为权重系数。

(2)RRF(Reciprocal Rank Fusion)

RRF 是非常常见的排序融合方法:

RRF(d)=rR1k+rankr(d)\text{RRF}(d) = \sum_{r \in R} \frac{1}{k + \text{rank}_r(d)}

其中:

  • RR 表示多个排序器
  • rankr(d)\text{rank}_r(d) 表示文档 dd 在排序器 rr 中的排名
  • kk 是平滑项

它不依赖不同系统分数的绝对尺度,工程上很稳。


十九、优化点 4:Rerank 是“最后一公里”

如果说 embedding 检索负责“大范围找候选”,那么 rerank 负责“把真正该看的那几段挑出来”。

一个常见工程配置

  • 向量检索召回 Top-50
  • BM25 召回 Top-50
  • 融合去重后保留 Top-30
  • 用 reranker 排序后取 Top-5
  • Top-5 进入 LLM

这通常比直接 Top-3 向量检索要稳得多。

为什么?

因为真实世界文档很复杂。
高相似度不等于高支持度。

举个例子:

问题:

Redis 为什么会出现缓存击穿?

候选文档 A:

Redis 是一个高性能内存数据库,适用于缓存场景。

候选文档 B:

缓存击穿通常指热点 key 在失效瞬间,大量请求直接打到数据库。常见解决方法包括互斥锁、逻辑过期、热点预热等。

A 可能“主题相关”,但对回答帮助不大;
B 才是真正支持回答的证据。

rerank 的作用,就是把 B 排到前面。


二十、优化点 5:上下文不只是“相关”,还要“可回答”

很多人只看检索相似度,不看一个更本质的问题:

这段文档能不能真正支持回答当前问题?

这是两个层次:

  • 相关(relevant)
  • 可回答(answer-bearing)

一个文档可能谈的是同一个主题,但不包含问题所需的关键事实。
因此,生产级 RAG 更应该关注“支持度”而不是单纯的“相似度”。


二十一、优化点 6:让模型学会拒答,比强行回答更重要

高质量 RAG 系统必须有明确的拒答机制。

为什么?

因为检索失败有很多种情况:

  • 知识库里根本没有答案
  • 召回结果不够相关
  • 上下文存在冲突
  • 问题超出知识域
  • 当前权限下无法访问对应文档

这时最危险的行为不是“不回答”,而是“编一个看起来合理的答案”。

常见做法

  • 设置最低检索分数阈值
  • 设置 rerank 分数阈值
  • 让模型输出“不足以回答”
  • 给出“建议补充资料/换个问法”

二十二、RAG 的评估:不能只看最终回答像不像

RAG 是一个多阶段系统,因此评估必须拆开看。


二十三、检索阶段评估指标

1. Recall@k

表示正确文档是否出现在前 kk 个结果里。

如果问题对应的标准答案文档在 Top-5 中被召回,则 Recall@5 命中。

2. Precision@k

kk 个结果中有多少是真正相关的。

3. MRR(Mean Reciprocal Rank)

关注第一个正确结果出现得有多靠前:

MRR=1Ni=1N1ranki\text{MRR} = \frac{1}{N} \sum_{i=1}^{N} \frac{1}{\text{rank}_i}

如果正确文档排第 1,得分就是 1;
排第 5,得分就是 1/51/5

4. nDCG

适用于多相关度等级场景,衡量排序整体质量。


二十四、生成阶段评估指标

1. Exact Match / F1

适合事实问答、抽取式任务。

2. Faithfulness(忠实性)

答案是否真的被上下文支持。
这是 RAG 最核心的指标之一。

3. Answer Relevance

答案是否真正回应了问题,而不是泛泛而谈。

4. Context Precision / Context Recall

检索到的上下文是否既相关又充分。


二十五、生产系统还需要哪些工程能力?

一个真正可上线的 RAG 系统,通常不止是“模型 + 向量库”。

1. 元数据过滤

例如只检索:

  • 某个部门的文档
  • 某个时间范围内的版本
  • 某个产品线的知识
  • 某个权限级别允许访问的内容

2. 权限控制

企业场景里非常关键。
不能让用户通过自然语言绕过权限系统,查到不该看的文档。

3. 增量更新

知识库不是一次性建完就结束,必须支持:

  • 新文档增量入库
  • 老文档版本替换
  • 删除失效内容
  • 重建索引

4. 缓存

缓存可以放在多个层次:

  • query 改写缓存
  • embedding 缓存
  • 检索结果缓存
  • 最终回答缓存

5. 监控与可观测性

需要记录:

  • 用户问题
  • 检索结果
  • rerank 排序
  • 最终上下文
  • LLM 输出
  • 延迟
  • token 开销
  • 错误率
  • 拒答率

否则出了问题根本不知道是:

  • query 改写错了
  • 检索没召回
  • rerank 排偏了
  • prompt 失效了
  • LLM 自己发挥了

二十六、RAG 常见误区

误区 1:接入向量数据库就等于做了 RAG

不是。
这只能说明你完成了“向量检索”这一环,不代表整体系统有效。

误区 2:换更大的 LLM 就能解决检索问题

不是。
如果上下文本身不对,模型越大,往往只是“更流畅地答错”。

误区 3:检索相似度高,答案就一定准

不是。
相似度高只能说明“像”,不代表“能回答”。

误区 4:Top-k 越大越好

不是。
上下文越多,不一定越好。
过多无关信息会干扰生成,甚至让答案质量下降。

误区 5:RAG 只适合问答

也不是。
RAG 还可以用于:

  • 摘要生成
  • 代码辅助
  • 合同分析
  • 多文档对比
  • 医疗报告辅助
  • 学术文献检索与归纳
  • Agent 工具调用前的知识补充

二十七、RAG 的进阶方向

如果你已经掌握了基础 RAG,下一步可以关注这些方向。

1. Agentic RAG

不再是一轮固定流程,而是让系统具备更强的决策能力,例如:

  • 是否需要检索
  • 检索几轮
  • 是否改写 query
  • 是否继续追问
  • 是否调用外部工具

2. GraphRAG

把知识表示为图结构,而不是纯文本块,适合:

  • 多跳推理
  • 实体关系问答
  • 知识图谱增强场景

3. Multi-hop RAG

针对复杂问题,先拆解成多个子问题,再分阶段检索与推理。

4. Multimodal RAG

检索对象不再只是文本,还包括:

  • 图片
  • 表格
  • PDF 页面
  • 医学影像
  • 视频片段
  • 音频转录

5. Long-context + RAG

即使长上下文模型越来越强,RAG 也不会消失。
因为长上下文解决的是“能装下多少”,而 RAG 解决的是“该装什么”。


二十八、一个更贴近生产的 RAG 架构建议

如果你要做一个可用的企业级 RAG,建议最少包含以下模块:

[文档接入层]
  PDF / Word / Markdown / 网页 / 数据库 / API

[预处理层]
  清洗 / 去重 / 结构解析 / 元数据抽取 / 权限标记

[切分层]
  结构化 chunk / overlap / parent-child

[索引层]
  embedding + vector index + BM25 index

[检索层]
  query rewrite / hybrid retrieval / metadata filter

[排序层]
  reranker / MMR / 去重 / 上下文压缩

[生成层]
  prompt template / citation / refusal / conflict handling

[评估监控层]
  retrieval metrics / faithfulness / latency / token cost / tracing

这套架构才是真正“能落地”的 RAG,而不是实验室式 demo。


二十九、RAG 的一句工程总结

如果只用一句话总结 RAG 的本质,我会这样说:

RAG 不是“给大模型多喂点文本”,而是“建立一套从外部知识中精确找证据、筛证据、组织证据、再基于证据回答”的系统工程。

它的难点不在某一个模型,而在整个链路的协同:

  • 文档如何切
  • 向量如何表征
  • 检索如何召回
  • 排序如何精排
  • 上下文如何组织
  • 模型如何约束
  • 系统如何评估

真正强的 RAG,从来不是某个单点特别强,而是每一个环节都没有明显短板。


三十、结语

RAG 的价值,不只是“让 LLM 接一个知识库”,而是给大模型带来三种关键能力:

  1. 知识外置:知识不再被封死在参数里;
  2. 事实约束:回答必须尽量被证据支持;
  3. 可持续更新:文档一更新,系统能力就能更新。

从研究到工业落地,RAG 之所以重要,恰恰是因为它站在“大模型能力”和“真实业务知识”之间,充当了连接二者的桥梁。

如果说预训练模型提供的是“语言理解与生成能力”,
那么 RAG 提供的就是“把能力接上真实世界知识”的方法。


附:适合作为 CSDN 标签的关键词

RAG
检索增强生成
大语言模型
LLM
向量数据库
Embedding
FAISS
BM25
Rerank
Hybrid Retrieval
知识库问答
Prompt Engineering
AI 应用开发

附:适合作为封面摘要的一段话

RAG(Retrieval-Augmented Generation,检索增强生成)是当前大模型落地最核心的技术路线之一。它通过“先检索、再生成”的机制,让模型不再只依赖参数记忆作答,而是能够基于外部知识库进行更准确、更可追溯的回答。本文将从原理、架构、检索策略、Rerank、上下文组装、评估体系到工程实践,系统拆解 RAG 的完整技术链路。