大模型有个绕不开的问题:它只记得训练时"看过"的东西。你问它公司内部的报销制度、上个月刚上线的接口文档、某个私有仓库的代码,它要么答不上来,要么一本正经地编——这就是幻觉。
RAG 就是治这个病的:先去知识库里把相关资料捞出来,再让模型基于资料回答。它不改变模型本身,而是给模型临时"开卷考试"。
这篇讲清四件事:RAG 是什么、有什么用、怎么用、什么场景适合用。
一、RAG 是什么
RAG,全称 Retrieval-Augmented Generation,检索增强生成。名字已经把流程说完了:
- Retrieval(检索):根据用户问题,从外部知识库里找出最相关的若干片段。
- Augmented(增强):把这些片段拼进提示词,作为"参考资料"。
- Generation(生成):模型基于参考资料来回答,而不是凭记忆硬编。
它是 2020 年 Facebook AI 在论文《Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks》里提出的,最初是给模型外挂一个可检索的文档库。现在几乎所有"企业知识库问答""AI 客服""文档助手"底层都是这套思路。
一句话对比:
纯大模型:模型 → 直接凭参数里的记忆回答
RAG: 问题 → 检索相关资料 → 资料 + 问题一起喂给模型 → 回答
RAG 的核心假设是:很多问题的答案不在模型的参数里,而在你的资料里。与其把资料"教"进模型(微调),不如回答时现查现用。
二、RAG 有什么用
1. 缓解幻觉,答案有依据
模型不再凭空发挥,而是被要求"只根据以下资料回答"。资料里没有的,可以明确说不知道。这比让模型自由发挥可靠得多。
2. 知识可实时更新,不用重训
这是 RAG 最大的优势。文档改了,重新入库即可,不用重新训练模型。今天上线的产品手册,明天就能被问到。微调则要重新跑一遍训练,成本高、周期长。
3. 答案可溯源
检索到的片段带原文位置,可以在回答里附上引用来源(第几篇文档、哪一段)。用户能点进去核对,这在法律、医疗、金融场景是刚需。
4. 成本远低于微调
微调要标注数据、租 GPU、反复训练;RAG 主要是检索调用,工程成本低得多。对绝大多数"想让模型知道我的私有知识"的需求,RAG 是性价比最高的方案。
5. 天然适配私有数据
公司内部文档、代码、工单、聊天记录,本来就该留在自己手里。RAG 让模型通过检索访问这些数据,不必把它们塞进训练语料。
三、RAG 和微调,怎么选
很多人第一反应是"我要不要微调一个自己的模型"。先看这张表:
| 维度 | RAG | 微调(Fine-tuning) |
|---|---|---|
| 解决的问题 | 补知识、要依据 | 改风格、调格式、学特定能力 |
| 知识更新 | 改文档即可,实时 | 需重新训练 |
| 成本 | 低 | 高(数据 + 算力 + 时间) |
| 可溯源 | 可以给引用 | 基本做不到 |
| 幻觉 | 明显缓解 | 不保证改善,甚至可能更自信地编 |
| 适合 | 知识密集型问答 | 行为/风格/格式定制 |
结论很直白:要"知道更多",用 RAG;要"表现不同",才考虑微调。两者也不冲突,可以叠加——先微调学会输出格式,再用 RAG 补知识点。
四、RAG 怎么用:两个阶段
RAG 的工程实现分离线索引和在线检索生成两段。
阶段一:离线索引(Indexing)
把文档处理成"可被检索"的形态,一次性做完:
原始文档(PDF / Markdown / 网页 / 数据库)
↓ 解析、清洗
纯文本
↓ 切分(Chunking)
文本块 chunks
↓ 嵌入(Embedding)
向量 vectors
↓ 存入
向量数据库(Vector Store)
关键动作:
- 切分(Chunking):长文档切成几百字一块。块太大检索不精准,太小上下文不完整,通常 200~800 token,块之间留一点重叠(overlap)。
- 嵌入(Embedding):用嵌入模型把每块文本转成一个高维向量(比如 1536 维)。语义相近的文本,向量距离也近。
- 存储:把向量和原文存进向量库,常见有 pgvector、Milvus、Qdrant、Chroma、FAISS。
阶段二:在线检索生成(Retrieve & Generate)
用户提问时实时执行:
用户问题
↓ 用同一个嵌入模型转向量
检索:在向量库中找最相似的 top-k 块
↓ (可选)重排 Rerank
把 top-k 块拼进提示词
↓
大模型生成答案(附引用)
一个最小可跑的示例(Node.js)
以 OpenAI 的嵌入接口 + 内存向量库为例,直观看看"检索增强"到底在做什么:
import OpenAI from 'openai'
const openai = new OpenAI()
// 1. 离线:把知识块嵌入成向量
async function embed(text) {
const res = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: text,
})
return res.data[0].embedding
}
const chunks = [
'报销需在费用发生后 7 个工作日内提交。',
'年假每满一年增加 1 天,上限 15 天。',
'服务器变更必须走工单审批,禁止直接改生产环境。',
]
const index = []
for (const text of chunks) {
index.push({ text, vector: await embed(text) })
}
// 2. 余弦相似度
function cosine(a, b) {
let dot = 0, na = 0, nb = 0
for (let i = 0; i < a.length; i++) {
dot += a[i] * b[i]
na += a[i] * a[i]
nb += b[i] * b[i]
}
return dot / (Math.sqrt(na) * Math.sqrt(nb))
}
// 3. 在线:检索最相似的 top-k
async function retrieve(question, k = 2) {
const qv = await embed(question)
return index
.map((item) => ({ ...item, score: cosine(qv, item.vector) }))
.sort((a, b) => b.score - a.score)
.slice(0, k)
}
// 4. 生成:把检索结果拼进提示词
async function ask(question) {
const hits = await retrieve(question)
const context = hits.map((h) => `- ${h.text}`).join('\n')
const res = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [
{
role: 'system',
content: '只能根据提供的资料回答,资料里没有就说“资料中未提及”。',
},
{
role: 'user',
content: `资料:\n${context}\n\n问题:${question}`,
},
],
})
return { answer: res.choices[0].message.content, sources: hits.map((h) => h.text) }
}
console.log(await ask('年假最多能有多少天?'))
真实项目里,向量库、切分、重排都会用成熟组件替换,但主干就是上面这四步:嵌入 → 检索 → 拼接 → 生成。
五、几个决定效果的关键点
RAG 看着简单,效果差往往差在这几处:
1. 切分策略
按固定长度切最省事,但会把一句话、一张表切断。更好的做法是按语义/标题结构化切:Markdown 按标题层级、PDF 按段落、代码按函数。切分质量直接决定检索质量,这是最容易被低估的一环。
2. 混合检索
只用向量检索,对专有名词、编号、精确匹配不敏感。生产里常用混合检索:BM25 关键词检索 + 向量语义检索,两路结果融合,召回更稳。
3. 重排(Rerank)
向量检索追求"快而全"(召回),但不一定准。加一个 Rerank 模型(如 bge-reranker、Cohere Rerank)对初筛结果精排,把真正相关的那几条顶上来,效果提升通常很明显。
4. 引用与"不知道"
提示词里要明确约束"只依据资料回答,没有就承认不知道",并要求附来源。否则模型仍会对着资料自由发挥。
六、什么场景适合用 RAG
适合用 RAG 的场景,有几个共同特征:知识在外部、会更新、要依据、答案偏"查得到"。
| 场景 | 为什么适合 |
|---|---|
| 企业知识库问答 | 内部文档多且变,需权限隔离和引用 |
| 智能客服 | 产品手册、FAQ 频繁更新,回答要准确 |
| 文档/代码助手 | 基于指定仓库、PDF 回答并给出处 |
| 法律、医疗、金融问答 | 强依赖专业资料,必须可溯源 |
| 长文档问答 | 把整本书/合同先入库,再按需检索 |
| 带引用的搜索问答 | 答案要能点回原文核对 |
反过来,下面这些场景 RAG 并不合适:
- 要改变说话风格、输出格式:这是微调或提示词的活,检索帮不上。
- 实时计算、结构化查询:问"上季度华东销量",该查数据库/调 API(工具调用、Function Calling),而不是检索文本。
- 纯推理、逻辑题:答案不依赖外部知识,检索没意义。
- 数据量极小:总共就几页文档,直接放进提示词(长上下文)就行,不必上检索。
七、一条选型思路
判断该不该上 RAG,问自己三个问题:
- 答案在不在我手里的资料里?在 → RAG 有戏。
- 资料会不会变?会 → RAG 比微调更划算。
- 用户需不需要看依据?需要 → RAG 几乎是唯一选择。
三个都"是",就上 RAG;如果答案是"我要模型换个说话方式",那请去看微调和提示词工程。
小结
- RAG = 检索增强生成:先查资料,再让模型基于资料回答,相当于给模型开卷考试。
- 它解决的是"模型不知道我的私有知识、还爱编"的问题,知识可更新、答案可溯源、成本低。
- 流程分两段:离线索引(切分 → 嵌入 → 存向量库),在线检索生成(问句嵌入 → 相似检索 → 拼接 → 生成)。
- 效果关键在切分、混合检索、重排、引用约束四件事。
- 选型口诀:要"知道更多"用 RAG,要"表现不同"用微调,要"实时计算"用工具调用。