零基础理解 RAG:从文档分块、向量化到相似度检索,带你搞懂检索增强生成的底层核心逻辑
2026/6/1 19:38:33 网站建设 项目流程

零基础理解 RAG:从文档分块、向量化到相似度检索,带你搞懂检索增强生成的底层核心逻辑

前言

今天下午,天空放晴。一缕暖洋洋的斜阳洒在我的原木书桌上。

我的小狗 Token 正趴在脚边打着小呼噜。在这个惬意的时刻,我想和大家分享大模型领域中听起来很神秘,但原理其实特别温柔的技术——RAG(检索增强生成)。

简单来说,大模型就像是一个参加“闭卷考试”的学生。他虽然读过很多书、非常聪明,但有些细节时间久了就会记错,甚至开始胡言乱语(幻觉)。

而 RAG 技术,就是允许这个学生在考试时“翻书查资料”。

今天我带大家彻底抛开复杂的学术公式,用最直白的大白话和最简单的 Python 源码,带你彻底搞懂 RAG 系统的三大核心支柱。


一、底层原理

1.1 RAG 的三大步骤

RAG 全称是 Retrieval-Augmented Generation(检索增强生成)。它的运作可以比作我们在图书馆找书并写报告的过程。

graph TD A["本地参考文档 (如 戚风蛋糕菜谱)"] -->|"第一步: 课本切片 (Chunking)"| B["独立知识卡片列表"] B -->|"第二步: 贴上位置坐标 (Embedding)"| C["向量特征库"] D["用户提问: 为什么蛋糕会塌陷?"] -->|"转化为查询向量"| E["查询坐标"] C & E -->|"第三步: 翻书对比 (Similarity Search)"| F["找出最相近的前 2 张卡片"] F -->|"作为背景上下文"| G["拼装完整的 Prompt 喂给大模型"] G --> H["大模型输出温馨且准确的回答"]

三大支柱环节:

  • 文档分块 (Document Chunking):一本十万字的书,大模型是一下子看不过来的。我们需要把它切成一两百字的小段落(我们叫知识卡片)。
  • 向量化 (Embedding):把文字转换为代表语义坐标的数字向量。在数字空间里,“戚风蛋糕”和“烘焙面点”会被排在很近的坐标上。
  • 相似度检索 (Similarity Search):当用户提问时,我们把问题也变成坐标,在库里找出离问题坐标最近的几个小段落,把它们贴在问题后面送给大模型。

1.2 效果对比

体验维度纯大模型直接回答 (无 RAG)开启 RAG 翻书辅助回答
回答准确度中等 (容易胡编乱造不存在的知识)极高(句句有依据,全部来自本地参考书)
实时时效性差 (无法知晓今天发生的最新消息)极强(只要把今天的新闻放入知识库即可)
隐私保护度差 (可能需要把机密数据发送到云端训练)极好(私密文档保留在本地,大模型仅做整理)
开发成本极高 (需要重新微调训练大模型,烧钱)极低(普通电脑上运行几十行代码即可搭建)

二、快速上手:手写一个最简文档切片器

切片时,如果直接粗暴切断,很容易把一句话从中间切开。我们需要设置“重叠度(Overlap)”,让相邻的卡片之间有一点重复的字,保证意思连贯。

def 极简文档切片器(原始文本: str, 块大小: int = 50, 重叠大小: int = 15) -> list[str]: """ 将一整段长文本,按照固定大小和重叠字符进行物理分块 """ 知识卡片列表 = [] 起止索引 = 0 文本长度 = len(原始文本) while 起止索引 < 文本长度: # 计算当前卡片的结束位置 结束索引 = min(起止索引 + 块大小, 文本长度) # 截取文本块 文本块 = 原始文本[起止索引:结束索引] 知识卡片列表.append(文本块.strip()) # 每次向前移动:块大小减去重叠大小,保留部分重复内容 起止索引 += (块大小 - 重叠大小) # 避免陷入死循环 if 结束索引 == 文本长度: break return 知识卡片列表

三、核心 API 与深水区

3.1 纯手写特征相似度算法

在把卡片做成向量后,我们如何用 Python 计算它们和用户提问的吻合度呢?下面我们用数学里的夹角余弦算法实现一个检索核心。

import math def 模拟提取文本特征(文本: str) -> list[float]: """ 模拟文本特征提取。实际开发中我们直接调用 Embedding 接口。 这里通过统计几个核心敏感词出现的频次,生成一个 3 维特征向量。 """ 关键词 = ["蛋糕", "温度", "塌陷"] 特征向量 = [0.1, 0.1, 0.1] # 给予微小的底噪值 # 统计词频映射为高维坐标 for 索引, 词 in enumerate(关键词): if 词 in 文本: 特征向量[索引] += 1.0 return 特征向量 def 计算余弦夹角(向量甲: list[float], 向量乙: list[float]) -> float: """ 计算两个特征向量的余弦夹角值。越接近 1 代表语义越贴近。 """ 点积 = sum(x * y for x, y in zip(向量甲, 向量乙)) 模长甲 = math.sqrt(sum(x * x for x in 向量甲)) 模长乙 = math.sqrt(sum(y * y for y in 向量乙)) if 模长甲 == 0 or 模长乙 == 0: return 0.0 return 点积 / (模长甲 * 模长乙)

四、实战演练

现在我们把切片、特征提取和匹配组合起来。模拟一本关于“戚风蛋糕烘焙技巧”的知识库,输入问题:“为什么我的蛋糕塌陷了?”

def 运行RAG测试(): # 模拟一份关于烘焙的本地参考文档 菜谱课本 = ( "戚风蛋糕需要上下火 150 度烘焙 50 分钟。如果在烘焙中途频繁打开烤箱门," "会导致烤箱内部温度骤降,热胀冷缩会引起蛋糕顶部严重塌陷。同时,如果" "蛋白霜打发不足,内部气孔结构太弱,出炉后没有及时倒扣,也会发生塌陷。" "另外,烤箱的摆放位置要平稳,避免震动。" ) print("🧸 步骤 1:正在给课本进行切片分块...") 卡片库 = 极简文档切片器(菜谱课本, 块大小=60, 重叠大小=20) for 索引, 卡片 in enumerate(卡片库): print(f" [知识卡片 #{索引+1}]: {卡片}") # 2. 将所有卡片转化为模拟特征向量 向量库 = [模拟提取文本特征(卡片) for 卡片 in 卡片库] print("\n🧸 步骤 2:收到用户发问...") 用户提问 = "为什么我的戚风蛋糕会塌陷缩腰?" 提问特征 = 模拟提取文本特征(用户提问) print(f" 提问: {用户提问} | 转化为特征: {提问特征}") # 3. 相似度检索 相似度结果 = [] for 索引, 向量 in enumerate(向量库): 得分 = 计算余弦夹角(提问特征, 向量) 相似度结果.append((得分, 卡片库[索引])) # 按得分从大到小排序 相似度结果.sort(key=lambda x: x[0], reverse=True) print("\n🧸 步骤 3:翻书查阅完毕,匹配出的最相关卡片:") print("=" * 60) print(f" [匹配分: {相似度结果[0][0]:.4f}] 内容: {相似度结果[0][1]}") print("=" * 60) print("(我们会把这段内容作为背景,贴在问题后面送给大模型整理。)") if __name__ == "__main__": 运行RAG测试()

运行输出:

🧸 步骤 1:正在给课本进行切片分块... [知识卡片 #1]: 戚风蛋糕需要上下火 150 度烘焙 50 分钟。如果在烘焙中途频繁打开烤箱门, [知识卡片 #2]: 频繁打开烤箱门,会导致烤箱内部温度骤降,热胀冷缩会引起蛋糕顶部严重塌陷。同时,如果 [知识卡片 #3]: 热胀冷缩会引起蛋糕顶部严重塌陷。同时,如果蛋白霜打发不足,内部气孔结构太弱, [知识卡片 #4]: 蛋白霜打发不足,内部气孔结构太弱,出炉后没有及时倒扣,也会发生塌陷。另外,烤箱的摆放位置要平稳,避免震动。 🧸 步骤 2:收到用户发问... 提问: 为什么我的戚风蛋糕会塌陷缩腰? | 转化为特征: [1.1, 0.1, 1.1] 🧸 步骤 3:翻书查阅完毕,匹配出的最相关卡片: ============================================================ [匹配分: 0.9852] 内容: 热胀冷缩会引起蛋糕顶部严重塌陷。同时,如果蛋白霜打发不足,内部气孔结构太弱, ============================================================ (我们会把这段内容作为背景,贴在问题后面送给大模型整理。)

你看,AI 在后台仅仅通过极简单的特征比对,就帮我们把含有“塌陷”和“蛋糕”关联最深的那一张知识卡片(卡片 #3)精准挑了出来!


五、避坑指南

在亲自动手写 RAG 的过程中,有几个小边界一定要守好:

5.1 块大小 (Chunk Size) 设得过大或过小

⚠️问题表现:如果每个卡片切成 2000 字(过大),大模型阅读时容易漏掉中间的细节;如果切成 5 个字(过小),大模型就会因为缺乏上下文(比如只读到“导致塌陷”四个字,根本不知道是在说蛋糕还是桥梁)而无法理解。

最佳实践:在中文字符下,每个卡片的长度一般推荐设在 150 到 400 字之间,重叠度设在 10% 到 20% 之间,体验最温柔稳定。

5.2 盲目选择不支持中文的 Embedding 模型

⚠️检索失效:有些开发包默认使用英文的向量模型,对中文的语义距离计算完全不准。输入“番茄”和“西红柿”,它们算出的向量距离相隔十万八千里。


六、总结

把知识拆碎,分类存档,在需要的时候温柔唤醒。

RAG 的精髓,其实就是给聪明的大模型递上一本打开了的参考书。

用最简单的逻辑把这些底层环节想明白,你会发现,大模型技术也并没有那么遥不可及。

好啦,窗外夕阳已经落下, Token 已经乖乖衔着它的饭盆看着我了。祝大家今天也收获了新的知识,我们下期见!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询