RAG学习笔记:让大模型先查资料再回答问题
好家伙,
这次我们来聊 RAG.
RAG 这个词最近出现得很多,但如果只是记住它的英文全称,其实没什么用.
我更关心的是:
它到底解决什么问题?
为什么一个普通大模型问答不够用?
文档是怎么变成知识库的?
用户提问时系统背后到底发生了什么?
所以这篇文章不准备一上来堆概念.
还是从一个很实际的问题开始:
我有一堆项目文档,配置表,接口说明,设计笔记.
我想直接问它们问题.
比如:
某个配置字段是什么意思?
有哪些文档提到了某个角色?
这个系统的部署流程是什么?
某个功能的设计依据在哪里?
如果直接问普通大模型,它很可能不知道.
因为这些资料在我的本地,不在它的训练数据里.
那么问题来了:
我不希望模型瞎猜.
我希望它先查我的资料,再回答.
这就是 RAG 最核心的价值.
0.背景:为什么需要RAG
先看普通大模型问答.
它的流程大概是:
用户问题 -> 大模型 -> 答案
这个流程很简单.
但它有几个问题.
0.1 大模型不知道我的私有资料
大模型知道很多通用知识.
但它不知道我电脑里的:
项目文档
策划案
配置表
部署笔记
内部接口说明
个人学习笔记
如果这些资料没有被放进上下文,模型就只能靠已有知识猜.
这个时候它回答得越流畅,反而越危险.
因为你很难分辨它是在基于资料回答,还是在编.
0.2 文档太多,人工翻效率低
项目一大,资料会越来越多.
比如一个游戏项目里可能有:
文案文档
战斗配置表
技能配置表
装备配置表
后端部署文档
接口说明
测试记录
人工一个个搜,效率很低.
而且有些问题不是关键词能直接搜出来的.
比如:
这个字段是不是和套装效果有关?
有没有哪个文档解释过战斗监控?
这个配置表里的 name 和 title 有什么区别?
这些问题更偏语义.
传统搜索不一定好用.
0.3 我们想要的是先找证据
所以真正想要的流程应该是:
用户提问-> 系统先找相关资料-> 把资料交给大模型-> 大模型基于资料回答-> 最后给出来源
这就是 RAG.
它不是让模型凭空变聪明.
而是给模型加了一个"查资料"的步骤.
1.RAG是什么
RAG 的全称是:
Retrieval-Augmented Generation
拆开看:
Retrieval 检索
Augmented 增强
Generation 生成
连起来就是:
检索增强生成
我自己的理解更简单:
RAG = 先从知识库找资料,再让大模型基于资料回答.
普通问答:
问题 -> 大模型 -> 答案
RAG 问答:
问题-> 检索知识库-> 找到相关资料-> 资料 + 问题 一起给大模型-> 答案 + 来源
噢,这样一看就清楚了.
RAG 不是替代大模型.
它是给大模型补上一个外部知识来源.
2.RAG整体流程
一个基础 RAG 系统,大概分两部分:
1. 建库阶段
2. 查询阶段
2.1 建库阶段
建库阶段就是把资料整理成可以检索的形式.
流程大概是:
读取文档-> 清洗文本-> 切成片段-> 生成 embedding-> 写入向量数据库
比如:
Markdown 文档
Word 文档
txt 文本
Excel 配置表
都会被转成一条条知识记录.
每条记录一般包含:
文本内容
向量
来源文件
chunk 序号
额外元数据
2.2 查询阶段
用户提问时,流程大概是:
用户问题-> 生成问题 embedding-> 去向量数据库检索相似内容-> 取 Top K 相关片段-> 拼成 Prompt-> 让大模型回答-> 返回答案和来源
这里最关键的是:
大模型看到的不是空问题.
它看到的是问题 + 检索出来的资料.
所以它的回答就有了依据.
3.文档怎么进入知识库
RAG 的第一步不是问答.
而是文档处理.
如果文档处理得很粗糙,后面模型再强也救不回来.
3.1 文本类文档
像 Markdown,txt,Word 这种文档,一般先提取文本.
然后按段落切块.
比如:
原文档-> chunk 0-> chunk 1-> chunk 2
切块时要注意两个问题:
块太大,检索不精准
块太小,上下文容易断
所以常见做法是:
按段落切块 + 保留一点 overlap
也就是相邻片段之间保留一点重叠内容.
这样可以避免一句话刚好被切断.
3.2 Excel配置表
Excel 就不能完全按普通文本处理.
尤其是游戏项目里的配置表.
常见结构可能是:
第 1 行: 中文字段名
第 2 行: 字段 code
第 3 行以后: 数据记录
这种表格更适合按行处理.
也就是说:
一行配置 = 一条知识记录
并且要保存:
文件路径
Sheet 名
行号
中文字段名
字段 code
否则后面回答时,只能说"查到了相关配置".
但说不清到底在哪个表,哪个 sheet,哪一行.
这就不够可用.
4.Embedding和向量是什么
RAG 里面经常会提到 embedding.
这个词听起来有点抽象.
我现在这样理解:
embedding = 把文本变成一组数字
比如一句话:
RAG 适合做项目知识库问答
经过 embedding 模型以后,会变成:
[0.12, -0.08, 0.33, ...]
这一组数字就是向量.
它表示这段文本的语义位置.
如果两段文本意思接近,它们的向量距离也会比较接近.
比如:
RAG 适合做知识库问答
检索增强生成可以用于内部文档问答
这两句话虽然字面不完全一样,但语义接近.
所以向量检索能把它们关联起来.
这就是 RAG 比普通关键词搜索更灵活的地方.
5.向量数据库负责什么
向量生成出来以后,要存到一个地方.
这个地方就是向量数据库.
常见的有:
Qdrant
Milvus
Chroma
Weaviate
向量数据库主要做几件事:
1. 保存文档片段的向量
2. 保存文档片段的 payload
3. 根据问题向量检索相似片段
4. 返回相似度分数 score
这里 payload 很重要.
不要只存向量.
一条比较完整的 payload 可能长这样:
{"text": "File: skill.xlsx\nSheet: Skill\nRow: 12\n名称(name): 火球术","source": "配置表/skill.xlsx","fileType": ".xlsx","sheet": "Skill","rowNumber": 12,"chunkIndex": 0
}
向量负责:
找得准
payload 负责:
说得清
没有 payload,最后就很难展示来源.
6.用户提问时发生了什么
假设用户问:
套装描述的方法是什么?
系统第一步不是直接调用大模型.
而是先把这个问题也变成向量:
问题文本 -> 问题向量
然后拿问题向量去向量数据库里搜.
比如取前 6 条:
Top 1 score=0.72
Top 2 score=0.66
Top 3 score=0.51
Top 4 score=0.31
Top 5 score=0.28
Top 6 score=0.20
这里要注意:
不是所有结果都应该给大模型.
如果 score 太低,说明它可能只是"看起来有点像",但并不能真正回答问题.
所以需要设置一个最低相关度.
比如:
score >= 0.48 才进入上下文
如果没有任何片段达到阈值,系统应该回答:
根据当前资料无法确定。
这句话很重要.
因为 RAG 系统最怕的不是回答少.
最怕的是资料不够还硬编.
7.Prompt怎么约束模型
检索到资料以后,还要把资料放进 prompt.
这里 prompt 不能太随便.
一个比较稳的 prompt 思路是:
你是一个项目内部知识库助手.
请使用中文回答.
只能使用提供的资料.
如果资料足够,直接回答.
如果资料只提供部分线索,说明"资料只提供了部分线索".
如果资料不足,说明"根据当前资料无法确定".
最后附上来源.
这里的核心是:
限制模型不要脱离资料发挥.
也就是说,模型可以负责组织语言.
但证据必须来自检索结果.
这就是 RAG 和普通聊天最大的区别.
8.RAG为什么一定要显示来源
我觉得 RAG 里"来源"不是附加功能.
它是核心功能.
如果系统只回答:
套装描述通过 desc 字段配置。
这个答案看起来有用.
但用户还是会问:
你从哪看到的?
在哪个文件?
哪一行?
所以更好的回答应该带来源:
来源:
配置表/equip.xlsx / Sheet: Equip / Row: 12 / score=0.6231
这样用户可以回到原始资料验证.
对于项目知识库来说,能验证比会说更重要.
尤其是配置表,部署文档,接口说明这种内容.
答错了可能会直接影响开发和测试.
9.RAG适合什么场景
RAG 很适合这些场景:
1. 公司内部知识库
2. 项目文档问答
3. 游戏文案和配置表查询
4. 个人学习笔记检索
5. 客服知识库
6. 部署文档和故障排查
这些场景有一个共同点:
资料很多
资料会变
需要基于资料回答
最好能给来源
所以 RAG 很适合.
因为它不需要重新训练模型.
资料变了,重新导入知识库就行.
10.RAG不适合什么场景
RAG 也不是万能的.
有些场景不适合只靠 RAG.
10.1 精确数值筛选
比如:
找出攻击力大于 50 的装备
这个问题更适合数据库查询.
因为它是结构化筛选.
RAG 可以帮你解释字段含义.
但真正筛选数值,数据库更稳定.
10.2 复杂计算
比如:
按照这套公式计算最终伤害
这类问题应该走明确的计算逻辑.
不要让模型凭感觉算.
10.3 资料根本不存在
如果知识库里没有导入相关资料,RAG 也答不出来.
它不是凭空造知识.
它只是帮你更好地使用已有资料.
10.4 图片和扫描件
如果资料是图片或者扫描件,但没有 OCR,那系统读不到文字.
这种情况需要先做 OCR.
否则 RAG 根本不知道图片里写了什么.
11.本地RAG项目可以怎么搭
一个本地 RAG MVP 可以这样搭:
Ollama 跑本地模型
bge-m3 做 embedding
qwen 类模型 做回答
Qdrant 存向量
Node/Go/Python 提供 API
Web 页面 展示答案和来源
流程大概是:
文档目录-> 解析 Markdown / txt / docx / xlsx-> 切块或按行处理-> 生成 embedding-> 写入 Qdrant-> Web 页面提问-> 返回答案和来源
本地方案的好处:
1. 数据不出本机
2. 可以接内部资料
3. 成本低
4. 适合先做 MVP 验证
限制也很明显:
1. 速度取决于本地模型
2. 大批量导入会比较慢
3. 没有鉴权时只能本机或内网用
4. 高并发能力有限
所以一开始不要追求大而全.
先导入一小批真实资料.
然后准备 10 个真实问题去问.
如果答案能被来源验证,这个方向就有价值.
12.总结
这次整理 RAG,我最大的收获是:
RAG 的核心不是让模型记住资料.
而是让模型回答前先检索资料.
它的核心链路是:
文档-> 切块-> embedding-> 向量数据库-> 检索-> prompt-> 回答和来源
几个关键点:
1. 文档解析质量决定知识库质量
2. 切块策略会影响检索效果
3. payload 元数据决定答案能不能追溯
4. score 过滤可以减少低质量上下文
5. prompt 要限制模型只基于资料回答
6. 来源展示是 RAG 的核心能力
踩坑点也很清楚:
1. 不要把所有文档粗暴拼成一大段
2. 不要只存文本不存来源
3. 不要把低相关度结果硬塞给模型
4. 不要指望 RAG 替代结构化数据库
5. 不要让模型在资料不足时强行回答
最后一句话总结:
RAG 不是魔法.
它是一套让大模型先查资料,再回答问题的工程流程.
把这条流程跑通以后,大模型才真正能服务我们的项目文档,配置表和内部知识库.
