最近 AI 模型逐渐火热,作为一名程序员当然要追寻时代的潮流,学习了部分 AI 知识,其中 RAG 和 Agent 都比较出名。趁着这个时间,我来简单讲解一下 RAG,后续可能还会继续学习并分享这部分内容。


什么是 RAG?

RAG 全称 Retrieval-Augmented Generation,也就是检索增强生成

简单来说,RAG 就是给大模型配了一个外挂知识库。模型自己不知道的东西,先去知识库里面翻一翻,找到相关的资料,然后再基于这些资料来回答你的问题。

我们都知道 LLM(大语言模型)是有局限的,它的底层是 Transformer 架构,本质上是一个"文字接龙"游戏 —— 根据前面的文字预测后面最可能出现的文字。这就导致一个问题:当模型遇到自己不懂的东西时,它不会说"我不知道",而是会一本正经地胡说八道,也就是所谓的"幻觉"。

RAG 的诞生就很好地解决了这个问题。它的核心思路特别朴素:你不是容易编?那我先帮你把答案找好,你照着答案说就行了。

打个比方:

  • 没有 RAG 的大模型 = 闭卷考试,全靠记忆力,记不住就瞎编
  • 有 RAG 的大模型 = 开卷考试,可以翻书找答案,准确率大幅提升

RAG 可以解决什么问题?

1. 幻觉问题

大模型最大的痛点就是幻觉 —— 对用户的回答胡编乱造,而且编得特别像那么回事,让你真假难辨。

比如你问它"某某公司 2024 年的营收是多少",它可能会非常自信地给你一个数字,但这个数字完全是它编的。有了 RAG 之后,模型会先去知识库里找这家公司的财报数据,基于真实数据回答,准确性大幅提升。

2. 知识过时

模型训练完成之后,它所知道的东西都是当时训练时候接触到的信息,并不会自动进化。比如一个 2023 年训练的模型,你问它 2024 年发生了什么,它是真的不知道。

RAG 的知识库可以随时更新。你只需要把最新的文档扔进知识库,模型就能"学到"最新的知识,不需要重新训练。

3. 没有私有数据

这是企业场景中最核心的需求。你公司的内部文档、技术手册、客户资料,这些东西不可能出现在大模型的训练数据中。通过知识库,我们可以搭建一个自己的私人模型,给公司或者团队进行使用。

举个例子:你把公司的员工手册放进知识库,新员工就可以直接问 AI"年假有多少天"、“报销流程是什么”,AI 会基于员工手册给出准确的回答。

4. 答案溯源

对于一些严肃的问答场景(法律、医疗、金融),必须要能追溯答案的来源。RAG 可以在回答中标注"这段话来自哪个文档的哪一页",让用户自己去核实。这样就避免了模型瞎编造成严重的后果。

比如回答法律问题时引用具体的法条,回答医疗问题时引用临床指南,这些引用都是可以追溯验证的。


RAG 和微调有什么区别?

你可能会问:要让模型学会新知识,直接微调(Fine-tuning)不行吗?为什么还要搞 RAG?

这两个方案各有优劣,简单对比一下:

维度 RAG(检索增强) 微调(Fine-tuning)
成本 低,只需要搭建检索系统 高,需要 GPU 训练
更新知识 往知识库加文档就行,分钟级 需要重新训练,小时到天级
准确性 高,基于原文回答 可能产生幻觉
答案溯源 支持,能标注引用来源 不支持
适用场景 知识密集型问答 调整模型的风格和行为
数据隐私 数据在自己的库里,可控 数据需要参与训练

一句话总结:RAG 是给模型"查资料",微调是给模型"补课"。大多数企业场景下,RAG 是更实用的选择。


RAG 的核心概念

在讲工作原理之前,先搞清楚几个核心概念,不然后面可能看不懂。

Embedding(向量嵌入)

这是 RAG 里面最重要的概念。

我们人类理解文字靠语义,但计算机只认数字。Embedding 就是把一段文字变成一组数字(向量),而且意思相近的文字,变成的数字也相近

比如:

  • “苹果手机” → [0.2, 0.8, 0.1, 0.5, …]
  • “iPhone” → [0.21, 0.79, 0.12, 0.48, …]
  • “今天天气不错” → [0.9, 0.1, 0.7, 0.3, …]

你会发现"苹果手机"和"iPhone"的向量非常接近,但跟"今天天气不错"差得很远。这就是 Embedding 的魔力 —— 它把语义相似性转化成了数学上的距离问题。

常见的 Embedding 模型:OpenAI 的 text-embedding-3、阿里云的 text-embedding-v3、开源的 BGE 等。

向量数据库

有了向量,总得有地方存吧?向量数据库就是专门存储和检索向量的数据库。

普通数据库的查询是"帮我找 name = ‘张三’ 的记录",向量数据库的查询是"帮我找和这个向量最相似的 Top 10 个向量"。

常见的向量数据库:Milvus、Pinecone、Weaviate、Chroma。也有一些传统数据库加了向量检索功能,比如 Elasticsearch 8.x、PostgreSQL + pgvector。

相似度计算

怎么衡量两个向量"像不像"?主要有两种方法:

余弦相似度(Cosine Similarity):计算两个向量之间的夹角。夹角越小,越相似。值域是 -1 到 1,1 表示完全相同。这是最常用的方法。

欧氏距离(Euclidean Distance):计算两个向量之间的直线距离。距离越小,越相似。

大多数 RAG 系统用的是余弦相似度。

分块(Chunking)

一篇文档可能有几万字,但用户的问题通常只对应其中一小段。如果把整篇文档丢给模型,既浪费 token(花钱),又可能干扰模型找到重点。

所以我们需要把文档切成小块(chunk),每块存一个向量。检索的时候只返回最相关的几个小块,而不是整篇文档。

切块看起来简单,实际上很有讲究:切太大,检索不精准;切太小,语义不完整。一般每块 100-500 个 token 比较合适。


RAG 的工作原理

RAG 的工作原理主要分为三步,我们一步一步来看。

第一步:处理文档(离线阶段)

上传文档 → 解析文档 → 文本分块 → 向量化 → 向量存储

这一步是在用户提问之前就完成的,属于"备货"阶段。

上传文档

用户把文档(PDF、Word、Excel、Markdown 等)上传到系统。

解析文档

不同格式的文档,解析方式完全不同:

  • PDF:这是最复杂的。PDF 本质上是一种"画图指令",它告诉渲染器在哪个坐标画什么字,并不像 Word 那样有明确的段落结构。所以 PDF 解析需要做版面分析 —— 用 AI 模型识别页面上哪些是标题、哪些是正文、哪些是表格、哪些是图片。对于扫描件类型的 PDF,还需要 OCR(光学字符识别)把图片中的文字识别出来。
  • Word:结构相对清晰,可以直接提取段落、标题、表格等。
  • Excel:按行或按表格提取,通常转成文字描述。
  • Markdown/TXT:最简单,直接按段落分割。

解析质量直接决定了后续所有环节的上限。这个阶段如果把文字弄错了、把表格弄乱了,后面检索再准也没用。所以业界有一句话:RAG 的第一道坎是解析

文本分块

解析出来的文本需要切成小块。主要有三种分块策略:

固定大小分块:按固定的 token 数(比如每 128 个 token)切一刀。优点是简单,缺点是可能把一句话从中间切断。

基于分隔符分块:按句号、换行符、章节标题等自然边界切分。比固定大小更合理,但可能导致块大小不均匀。

语义分块:用 Embedding 模型计算相邻句子的语义相似度,在相似度突然下降的位置切分。理论上最优,但计算成本高。

实际项目中,通常是把这些策略混合使用 —— 先按自然段落分割,再按 token 数合并或拆分,确保每个块既有完整语义又不会太长。

向量化

把每个文本块送进 Embedding 模型,得到一个高维向量(比如 1024 维的浮点数数组)。

这一步的关键是选对模型。Embedding 模型的质量直接决定了"语义相似的内容能不能被检索到"。如果模型觉得"盈利增长"和"利润提升"不像,那检索就废了。

向量存储

把文本块的原文和对应的向量一起存入向量数据库(或带向量能力的搜索引擎)。每条记录大概长这样:

{
  "id": "chunk_001",
  "content": "公司2023年营收达到50亿元,同比增长15%...",
  "vector": [0.12, 0.34, 0.56, ...],    // 1024维向量
  "metadata": {
    "source": "年报.pdf",
    "page": 5
  }
}

到这里,"备货"就完成了。知识库已经准备好了,等待用户来提问。


第二步:查询检索(在线阶段)

用户查询 → 查询向量化 → 相似度检索 → 结果重排 → 上下文组装
用户查询

用户输入一个问题,比如"公司去年的营收增长了多少?"

查询向量化

把用户的问题用同一个 Embedding 模型转成向量。这里有一个关键点:查询和文档必须用同一个模型,否则它们的向量在不同的空间里,无法比较相似度。

相似度检索

拿着查询向量去向量数据库里找最相似的文本块。

这一步有两种主流策略:

纯向量检索:只比较向量的余弦相似度。优点是能理解语义("营收"和"收入"能匹配上),缺点是对具体的数字、人名等精确信息不敏感。

混合检索(推荐):向量检索 + 关键词检索同时进行,然后把两者的结果融合。这样既能匹配语义,又能精确匹配关键词,两全其美。

举个例子:用户问"2023年Q3营收"

  • 向量检索能匹配到"第三季度收入"(语义相似)
  • 关键词检索能精确匹配到含有"2023"和"Q3"的文本块
  • 两者结合,效果最好
结果重排(Rerank)

检索返回的结果可能有几十条,但质量参差不齐。重排(Rerank)就是对这些初步结果做精细化排序,把最相关的排到前面。

简单理解,检索是"海选",重排是"决赛"。

重排模型(Cross-Encoder)比普通的 Embedding 模型(Bi-Encoder)更精确,因为它会把查询和文档拼在一起一起看,能更好地理解两者之间的关系。但代价是速度慢,所以只能对少量候选做重排,不能对全量数据做。

这就形成了经典的漏斗架构

全量文档 → 粗排(向量检索,快但粗)→ 精排(Rerank模型,慢但精)→ Top-K 结果
上下文组装

把排序后的 Top-K 个文本块(通常 3-5 个)组装成"参考资料",准备塞进提示词里。


第三步:增强生成

构建提示词 → 大语言模型 → 最终答案
构建提示词

把用户的问题和检索到的参考资料按照一定的模板组装成提示词。一个典型的提示词长这样:

你是一个专业的助手,请基于以下参考资料回答用户的问题。
如果参考资料中没有相关信息,请诚实地说"我不知道"。

参考资料:
[1] 公司2023年营收达到50亿元,同比增长15%...
[2] 第三季度单季营收18亿元,创历史新高...
[3] 公司预计2024年营收目标为60亿元...

用户问题:公司去年的营收增长了多少?

请基于以上参考资料回答。

提示词设计有几个要点:

  • 明确角色:告诉模型它是什么身份
  • 给出规则:特别是"不知道就说不知道"这条,防止幻觉
  • 标注来源:要求模型在回答中引用参考资料的编号,方便溯源
  • 参考资料在前,问题在后:这样模型先"看"完资料再思考问题
大语言模型生成

提示词发送给 LLM,模型基于参考资料生成回答。由于参考资料是真实的文档内容,模型的回答会更加准确、更有依据。

最终答案

模型返回的回答可能长这样:

根据参考资料,公司2023年营收达到50亿元,同比增长了15% [1]。其中第三季度单季营收18亿元,创下历史新高 [2]。

方括号里的数字就是引用标注,用户可以点击查看对应的原文,验证答案是否准确。


RAG 常见的坑

坑 1:分块太大或太小

分块太大(比如一整页),检索出来一大段文字,真正有用的可能就一两句,大量无关信息会干扰模型判断。分块太小(比如一两句话),语义不完整,模型理解不了上下文。

建议:从 128-256 个 token 开始尝试,根据实际效果调整。

坑 2:解析质量差

特别是 PDF 文档。很多 PDF 看起来排版整齐,但内部结构混乱 —— 多栏排版、表格嵌套、扫描件等情况,简单的文本提取工具根本处理不好。如果解析出来的文本顺序是乱的、表格变成了一堆散乱的数字,后面再怎么优化也是白搭。

建议:选用专业的 PDF 解析方案(比如 DeepDoc、Unstructured),而不是简单的 PyPDF2。

坑 3:没有做重排序

只靠向量检索的初步结果就直接用,精度通常不够。加一个 Rerank 模型做精排,往往能显著提升效果,是性价比很高的优化手段。

坑 4:提示词设计不当

最常见的错误是没有告诉模型"不知道就说不知道"。模型会默认尽力回答,即使参考资料里没有相关信息也会编造。明确的指令约束非常重要。

坑 5:Embedding 模型不匹配

用英文 Embedding 模型处理中文文档,或者查询和文档用了不同的 Embedding 模型,都会导致检索效果大幅下降。

建议:中文场景选中文或多语言模型,查询和文档必须用同一个模型。


总结

RAG 的核心思想其实非常简单:先帮模型找到答案,再让模型组织语言

它不是什么高深莫测的黑科技,而是一个非常工程化的解决方案。每一步(解析、分块、向量化、检索、重排、生成)都有成熟的工具和方案可以选用。

对于程序员来说,RAG 是一个值得深入学习的方向。它不需要你有深度学习的理论基础(那是训练模型的人需要的),更多的是系统设计和工程优化能力 —— 怎么解析文档更准确、怎么分块更合理、怎么检索更精准、怎么提示词更有效。

如果你想动手实践,推荐的技术栈:

  • 文档解析:DeepDoc / Unstructured / LlamaParse
  • Embedding 模型:text-embedding-v3(阿里云) / BGE(开源)
  • 向量存储:Elasticsearch / Milvus / Chroma
  • LLM:DeepSeek / Qwen / GPT-4
  • 框架:LangChain / LlamaIndex / RAGFlow
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐