hanhan的BLOG
← 返回文章

初识 RAG(Retrieval-Augmented Generation)

2026-05-31
agent

1.引言

1.1为什么需要RAG

你训练了一台号称”无所不知”的机器,结果发现:

  • 它不知道今天发生了什么
  • 它不知道你公司内部的任何事
  • 你问它一个冷门事实,它给你编得头头是道 你没办法给它重新训练,因为成本太高啦。

所以你做了一个工程上的妥协: 每次问问题之前,你先去资料库里搜一圈,把搜到的相关内容贴到问题前面,再一起扔给机器。 机器还是那个机器,但因为面前摆了参考资料,回答质量就上去了。 RAG 就是这个贴资料、提前搜的动作。它不是让 LLM 变聪明了,它只是让 LLM 获取到那些它本来就没有记的东西。

1.2简单流程示意

无RAG:
用户输入——>拼prompt——>LLM生成

有RAG:
原始资料存入
用户输入——>检索相关信息——>拼prompt——>LLM生成

2.RAG是怎么干活的

RAG包括两部分:数据存入、数据检索

以一篇 PDF 的处理作简单流程示例

2.1数据存入

数据存入一般是一个离线的过程,整个过程跟用户毫无关系,不上线也一样跑。耗时长一点无所谓,反正不用等用户。

1.提取文本

通过PyPDF2等PDF处理库把PDF转化为文本

2.数据清洗

保留有用的文本:

  • 去掉页眉页脚、页码
  • 合并被 PDF 换行打断的句子
  • 去掉多余空格和乱码字符
  • 去掉水印文字、版权声明等噪音
  • 保留表格结构(转成 markdown table 或自然语言)

3.文本分块

按照某种规则对文本进行分块

原始文本(一段差旅政策):

3.1 住宿标准
从北京出差到上海,住宿标准为每人每天不超过500元。从北京出差到广州,住宿标准为每人每天不超过450元。一线城市统一按500元上限执行。
3.2 交通标准
高铁二等座或飞机经济舱。特殊情况需升舱的,需提前报直属领导审批。
3.3 餐饮补贴
每人每天100元包干,无需发票。出差天数按实际住宿天数计算。

语义切块(按标题层级3.1 3.2 3.3切):

  块1:
  3.1 住宿标准 从北京出差到上海,住宿标准为每人每天不超过500元。从北京出差到广州,住宿标准为每人每天不超过450元。一线城市统一按500元上限执行。
  块2:
  3.2 交通标准 高铁二等座或飞机经济舱。特殊情况需升舱的,需提前报直属领导审批。
  块3:
  3.3 餐饮补贴 每人每天100元包干,无需发票。出差天数按实际住宿天数计算。

4.向量化入库

对每个文本块向量化处理

chunk_text ="3.1 住宿标准 从北京出差到上海,住宿标准为..."
vector = embedding_model.encode(chunk_text)

数据块存入向量库

2.2数据检索

用户提问:“去上海出差酒店能报多少钱?“

1.问题向量化

“去上海出差酒店能报多少钱?”——>embedding 模型——> [ 0.091, -0.382, 0.776, …, 0.205 ]

2.计算相似度(余弦距离)

问题向量 vs 块1向量 → 距离 0.12 ← 最近,内容就是讲住宿的
问题向量 vs 块2向量 → 距离 0.71
问题向量 vs 块3向量 → 距离 0.68

3.排序取 top-K

这里K取2,也就是块1和块3

4.拼prompt

把检索到的资料塞到prompt里传给LLM

基于以下参考资料回答:
1.住宿标准:每人每天不超过500元(一线城市),广州450元 
2.餐饮补贴:每人每天100元包干,无需发票 

3.RAG工程上一些关键的地方

每一块儿都有好多好多可以讲的地方,之后有机会再补充,现在就粗略介绍一下

1.Chunking 策略

是什么:
文档怎么切块——固定大小切、按语义切、小块检索+大块生成(检索用小粒度精确命中,生成时把前后邻块也拼进 prompt 补足上下文)。

为什么:
块太小缺上下文,LLM 看了答不准;块太大塞进无关内容,稀释检索精度。没有通用最优参数,要按文档类型动态调整——政策条款要小块,法律合同要大块。

2.Hybrid Search(混合检索)

是什么:
同时结合关键词匹配(如 BM25、TF-IDF)与向量语义匹配(如 Embedding + 余弦相似度)的搜索技术。它会分别计算两种检索方式的得分,再通过加权、排序等方法合并为一个最终结果,从而取长补短。

为什么:
向量搜索遇到专有名词和编号之类的数据会失效——模型不认识这串东西,给不出有意义的向量;关键词搜索遇到同义不同字的表达(退费 vs 退款)会漏掉。两者盲区正好错开,合起来就不容易漏。

3.Reranking(精排)

是什么:
粗检用 embedding 向量距离快速筛出 top-50,精排是把每条候选文档和问题拼在一起,让模型逐字比对后重新打分排序,不是比两个独立向量。

为什么:
纯向量相似度只看全局语义,细节会丢。用户体感就是「搜出来的东西沾边但不直接相关」。reranker 是性价比最高的效果提升手段——不用动索引,加一个步骤就能大幅提高精确率。

4.评估体系

是什么:
一个是检索质量——不看最终答案,只看搜出来的文档对不对:该找到的有没有(召回率)、找出来的多少是真正相关的(精确率)、最相关的排第几(MRR)······ 另一个是生成质量——看 LLM 有没有好好用检索结果:答案说的是不是资料里有的(忠实度,防止瞎编)、答案有没有真回答问题(相关性,防止跑题)······

为什么:
没有评估体系的 RAG 等于盲调。 而且检索和LLM生成两个环节经常此消彼长——例如,加了检索召回率,多捞了些文档回来,看起来检索更全了,但多捞的东西里夹了不相关的,干扰了 LLM,答案反而比之前更差——没有分别评估这两块就不知道这个退化是检索带进来的噪音害的,还是 LLM 自己出了问题。

······