RAG 检索增强生成详解

📅 发布于 2026-07-31 15:30:07 🔄 更新于 2026-07-31 15:30:07
⏱️ 阅读时间 15 min read 📝 字数 3570 👁️ 阅读量 Loading...

RAG 是什么

RAG 的全称是 Retrieval-Augmented Generation,即检索增强生成

它是一种让大模型在回答问题前,先去外部知识库中查找相关资料,再根据查到的资料生成答案的技术。

为什么需要 RAG:大模型的知识困局

第一个困境:知识有截止日期

大模型的知识来自于训练数据,而训练数据是有时间窗口的。比如 ChatGPT 的某个版本,训练数据的截止日期是 2023 年 4 月,那么 2023 年 4 月之后发生的任何事情,它都不知道。你问它 2026 年发生了什么大事,它要么说不知道,要么就开始「编」。

第二个困境:不知道私有数据

大模型不知道你公司的私有数据。你公司的产品文档、内部规章制度、客户信息、项目资料……这些数据从来没有出现在大模型的训练集中,它怎么可能知道?

第三个困境:幻觉问题

大模型会「幻觉」。所谓幻觉,就是大模型会非常自信地说出一些听起来很专业但完全是编造的内容。你问它一个不存在的研究论文,它能给你编出一个标题、作者、摘要、甚至 DOI 号,看起来像模像样,但全是假的。这在需要高准确性的场景(比如医疗、法律、金融)中,是不可接受的。

RAG 的局限性

RAG 并不能解决所有问题:

  • 不能改变大模型的推理能力 —— 如果模型本身推理不行,给再多资料也没用
  • 不能改变大模型的输出风格 —— 如果你希望模型用特定风格回答,这需要微调
  • 不能保证 100% 的准确性 —— 检索可能召回错误的文档,模型也可能曲解文档内容

RAG 的完整流程

一个完整的 RAG 分为两个阶段:索引阶段查询阶段

索引阶段:把知识「整理好」

第一步:文档加载

这一步是把各种格式的文档加载进来。企业里的文档格式五花八门,PDF、Word、Excel、PPT、HTML、Markdown……每种格式都有不同的解析方式。比如 PDF 就比较麻烦,尤其是包含表格、图片、多栏排版的 PDF,解析起来很费劲。这一步的目标是把各种格式的文档统一转成纯文本。

第二步:文档切割(Chunking)

文档加载完之后,你不可能把一整本 100 页的文档直接扔给大模型,因为大模型的上下文窗口是有限的。所以需要把长文档切成一个个小的文本块(Chunk),每个文本块大概几百到几千个字符。

但切割这个事情没有看起来那么简单。你如果机械地按固定长度切,很可能一句话被切成了两半,或者一个完整的段落被拆开了,这样检索的时候就会丢失上下文。所以文档切割策略是 RAG 系统中非常关键的一环。

第三步:向量化(Embedding)

文本块切好之后,下一步是把每个文本块转换成一个数学向量(一串数字)。这个步骤叫 Embedding(嵌入)。你可以这样理解:Embedding 模型把一段文本「翻译」成了一个高维空间中的坐标点,语义相近的文本在这个空间中的距离也相近。

比如「今天天气很好」和「今天阳光明媚」这两句话意思差不多,它们经过 Embedding 之后,在向量空间中的距离就会很近。而「今天天气很好」和「Python 是一种编程语言」意思差很远,在向量空间中的距离也会很远。

第四步:存入向量数据库

最后一步,就是把所有文本块的向量存入向量数据库。向量数据库是专门用来存储和检索向量的数据库,它能高效地进行「相似度搜索」,也就是给你一个查询向量,它能快速找到和它最相近的 Top-K 个向量。

这一步做完,你的知识库就建好了。

查询阶段:让大模型翻书找答案

第一步:用户提问向量化

用户提出一个问题,比如「公司年假政策是什么」。系统首先用同样的 Embedding 模型,把这个问题也转换成一个向量。

第二步:相似度检索

拿着问题的向量,去向量数据库中进行相似度搜索,找到和这个问题语义最相近的 Top-K 个文本块。比如可能检索出了这样几个文本块:

  • 「公司全职员工入职满一年后享有 10 天带薪年假」
  • 「年假可以拆分使用,每次不少于半天」
  • 「未使用的年假可以累积到下一年,但最多累积 5 天」

第三步:构造增强 Prompt

把检索出来的文本块和用户的原始问题拼在一起,构造一个增强版的 Prompt。大概长这样:

请根据以下参考资料回答用户的问题。参考资料:[检索出的文本块]。用户问题:公司年假政策是什么?

第四步:大模型生成回答

把增强版的 Prompt 发给大模型,大模型基于这些真实的参考资料来生成回答。因为它有了具体的参考资料,就不会凭空编造了。

完整流程一览

把索引阶段和查询阶段合在一起,就是 RAG 的完整工作流程:

  • 索引阶段(离线):文档加载 → 文档切割 → 文本向量化 → 存入向量数据库
  • 查询阶段(在线):用户提问 → 问题向量化 → 向量检索 → 构造增强 Prompt → 大模型生成回答

这是最基础的 RAG 流程,也被称为 Naive RAG(朴素 RAG)。

微调和 RAG 的区别

什么是微调

微调(Fine-tuning),简单来说就是拿一个已经预训练好的大模型,用你自己的数据对它进行进一步的训练,让它在特定领域或特定任务上表现更好。

打个比方。大模型预训练完之后,就像一个高中毕业生,知识面很广,语数外理化生样样都懂一些。但如果你要让他当一个专业的医生,就需要送他去医学院继续学习,这个过程就类似于「微调」。

微调的方式也有不同的级别:

  • 全量微调 —— 更新模型的所有参数,效果最好但成本极高,需要大量 GPU 资源,一般只有大厂才玩得起
  • 参数高效微调(LoRA) —— 只训练一个很小的「低秩适配器」,不动模型主体,硬件需求大幅降低,一张消费级显卡就能跑
  • 指令微调 —— 用「指令-回答」格式的数据来微调,目的是让模型学会听懂指令、按指令来回答,而不是自由发挥

核心维度对比

知识更新方式

这是两者最核心的差异。微调要更新知识,就得重新训练模型,成本高、周期长。你们公司每个月都更新产品手册吧?如果用微调,每个月都得重新训练一次模型,想想都觉得累。但 RAG 就简单多了,只需要把新的产品手册替换掉知识库里的旧文档,重新做一下索引就行,模型完全不用动,成本极低,而且几乎可以实时更新。

准确性

微调的模型是靠「记忆」来回答的,就像闭卷考试,有可能记错或者记混。而且很多人有个误解,以为微调后模型就会严格按照训练数据来回答,其实不是的。微调更多是让模型学到了数据的「模式」和「风格」,对具体事实的准确性并不一定有保障。RAG 就不一样了,回答是基于检索到的真实文档的,可追溯、可验证,只要检索不出大问题,准确性通常比微调更高。

语言风格控制

这个维度反而是微调的强项。如果你希望模型用文言文回答、用特定的客服话术回答、模仿某个名人的说话方式,微调能做到。因为它在训练过程中就学会了这种风格。RAG 对输出风格的控制能力就比较有限了,检索到的内容只是给模型的「参考」,但模型最终怎么组织语言,还是取决于模型本身。

成本

两者的成本结构不一样。微调的初始成本高,你需要准备大量高质量训练数据、租 GPU 资源,但推理阶段的成本相对较低,因为不需要走检索流程。RAG 正好反过来,初始成本低,不需要训练模型,建个知识库就行,但每次查询都有检索开销,token 消耗也更多,因为你得把检索到的文档都塞进 Prompt 里。

RAG 文档切割策略

策略一:固定大小切割

按照固定好的字符串数或 token 数来进行切割。

缺点:破坏了语义。

为了缓解这个问题,通常会引入重叠(Overlap),也就是相邻的两个文本块之间有一段重复的内容。比如每个块 500 字符,重叠 50 字符,这样即使句子被切开了,相邻块之间还有一部分重复信息可以保持连贯。

不过重叠也不能解决所有问题,只能算是一个「补丁」。

策略二:递归字符切割

核心思路:按照文本的自然边界来进行切割。

会先尝试分隔符的优先级来进行切割,如果切出来的块数还是太大,就用单换行符来切割,如果还是太大,就用句号来进行切割……以此类推,直到块的大小符合要求。

这样做的好处是,它尽量保持段落、句子、短语的自然完整性,不会把一句话从中间切开。

策略三:基于文档结构的切割

这种方法是利用文档本身的格式结构来切割。

比如 Markdown 文档,可以按照标题层级来切:一级标题下面是一块,二级标题下面是一块。这样切出来的内容天然具有语义完整性。

策略四:语义切割

前面三种方法都是基于「规则」的,不管内容是什么,都按照预设的规则来切。语义切割则不一样,它是基于内容的语义相似度来决定在哪切。

核心思想是:把语义相似的句子放在一起,语义发生转折的地方就是切割点。

策略五:Agent 驱动的智能切割

具体做法是:先用上述方法生成初始的文本块,然后用 LLM 来审视每个块,判断这个块的内容是否完整、是否需要和相邻的块合并或拆分。LLM 充当一个「智能编辑」的角色,根据对内容的理解来做出切割决策。

RAG 检索增强生成详解

作者:felinus

本文链接: https://felinus-blog.vercel.app/posts/f8882829/

本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。