你有没有过这种冲动:网站有几百篇文章,想做一个「站内 AI 助手」,于是把全部文章正文拼进 system prompt,再问问题?
我最初也是这么干的。直到账单出来、回答开始胡说八道、长文章直接超出上下文窗口——才意识到这是条弯路。
这篇教程把 RAG(Retrieval-Augmented Generation,检索增强生成)讲透:为什么不要「全塞进 prompt」,正确的姿势是什么,怎么用硅基流动免费的两个模型(嵌入 BAAI/bge-m3 + 重排 BAAI/bge-reranker-v2-m3)搭出又准又省钱的问答系统。
想白嫖这两个免费模型,可以用这个注册链接:https://cloud.siliconflow.cn/i/MBwLMSrY
一、什么是 RAG(Why)
RAG = Retrieval-Augmented Generation(检索增强生成):在让大模型生成答案之前,先从外部知识库里检索出最相关的资料,把这些资料连同问题一起交给大模型,让它「带着资料」回答。
它的核心思想一句话:让模型「现查现答」,而不是指望它把全世界的 knowledge 都背在参数里。
为什么会出现 RAG?
大模型本身有几个天生的天花板:
- 知识有截止日期:模型只在训练数据时间点之前「懂」,之后的事一概不知。
- 看不到你的私有数据:公司文档、你的博客、客户聊天记录,模型训练时根本没见过。
- 上下文窗口有限:哪怕有 200K 上下文,也装不下整个知识库。
- 会一本正经地胡说(幻觉 / Hallucination):资料里没有的内容,它也会编得头头是道。
2020 年 Meta 等提出的 Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks 论文,就是为了让模型在回答时「先查资料」,从而缓解上述问题。后来随着向量数据库和 embedding 模型成熟,RAG 成了落地 LLM 应用最主流的范式。
它解决了什么问题 / 与传统大模型回答的区别
| 传统大模型回答 | RAG 增强回答 | |
|---|---|---|
| 知识来源 | 训练时「背」进去的参数 | 实时检索的外部资料 |
| 时效性 | 停在训练截止日 | 资料更新即生效 |
| 私有数据 | 看不到 | 能检索到 |
| 可溯源 | 无法引用出处 | 能给出资料来源 |
| 幻觉 | 容易编造 | 有资料约束,显著降低 |
一句话:传统大模型是「凭记忆考试」,RAG 是「开卷考试」。
二、为什么需要 RAG
重点说痛点,这恰恰是 RAG 存在的理由:
- 大模型知识会过时:2024 年的模型答不了 2026 年的新政策、新 API。
- 容易产生幻觉(Hallucination):没有资料时,模型会自信地编造事实、链接、数字。
- 无法直接访问企业私有数据:内部 Wiki、合同、工单,模型根本不知道。
- Prompt 太长,Token 成本高:把全站文章塞进 prompt,每次提问都重发几百万 token。
- 无法引用资料来源:用户无法核实「这句话到底出自哪里」,不信任。
RAG 把「记忆」和「查资料」解耦——模型负责推理和表达,知识存放在外面随时可更新。
三、RAG 的工作流程
一张流程图就能说清:
flowchart LR Q[用户问题] --> E[Embedding 向量化] E --> V[(Vector Database 向量库)] V --> R[Retriever 检索 Top-K] R --> RR[Reranker 重排 可选] RR --> L[LLM 生成答案]
放到文字里就是:
用户问题
↓
Embedding(向量化:把问题变成向量)
↓
Vector Database(向量数据库里存着所有资料的向量)
↓
Retriever(检索:找出和问题向量最相似的若干段)
↓
Reranker(重排,可选:对召回结果按真实相关性重新打分)
↓
LLM(带着最相关的资料生成答案)
每一步的作用:
- Embedding:把自然语言变成一串数字(向量),让「语义相似」可以被「数学距离」衡量。
- Vector Database:存放所有资料的向量,支持「按向量找最近邻」的高效检索。
- Retriever:用问题的向量去库里做最近邻搜索,粗筛出候选(如 15 段)。
- Reranker:把「问题 + 每个候选」拼起来重新打分,精排出真正最相关的(如 5 段)。这是质量的关键一步。
- LLM:只消费 top-N 资料,生成带出处的答案。
四、RAG 的核心组件
1. Embedding(嵌入模型)
把文本映射成固定维度的稠密向量。维度常见的有 768 / 1024 / 1536。中文场景首选 BAAI/bge-m3(1024 维,中英文都强),在硅基流动上免费。
那「向量」到底是什么?
一句话:向量就是一串数字,代表一段文本在「语义空间」里的坐标。
想象一张地图:每篇文章、每句话都是一个点,语义相近的句子在地图上离得近,不相关的离得远。但文字本身没法直接算「距离」,所以嵌入模型把它变成一串定长的数字,比如 1024 维的 [0.12, -0.03, 0.87, …]。这串数字就是那句话的「坐标」。
- 维度越高,能表达的语义越细腻(1024 维比 384 维装得下更多细微差别)。
- 「语义相似」≈「向量距离近」:用余弦相似度(两个向量夹角的余弦)衡量,越接近 1 越相关,越接近 0 越不相关。
大模型「读」的是向量吗?——这是个常见误解
不是。要把两件事分清楚:
- 向量只用来「检索」:检索阶段,系统把问题也变成向量,去向量库里找「离得最近」的几个文本片段。这一步全是数学计算(算距离、排序),大模型不参与。
- 真正喂给大模型的是「原文」:检索完成后,系统把对应的原始文本片段(注意,不是那串数字)拼进 prompt,大模型读的是这些文字,再据此生成答案。
所以更准确的说法是:向量负责「找得准」,大模型负责「读得懂」。 向量是给检索器用的「地址」,不是给大模型读的「内容」。也是因为这个分工,RAG 才能用很便宜的模型就答得准——大模型看到的只是精挑细选出来的几段文字。
2. Chunk(文本切分)
把长文档切成小段(chunk)。RAG 的检索粒度是 chunk,不是整篇文档。切得太粗→召回不精准;太细→语义被切碎。常见甜区是 300~500 字。
3. Vector Database(向量数据库)
专门存向量、支持 ANN(近似最近邻)检索的数据库。可选 Qdrant / Milvus / Chroma / FAISS,或直接在 Postgres 里用 pgvector 扩展(本博客用的就是它)。
4. Retriever(检索器)
负责「问题向量 → 候选 chunk」的粗筛。核心是余弦相似度 / 内积 / 欧氏距离。
5. Reranker(重排模型)
Cross-Encoder 结构,比单纯余弦准得多。把 query + 候选 一起喂进去打分。BAAI/bge-reranker-v2-m3 在硅基流动上同样免费。
6. LLM(生成模型)
最后消费 top-N 资料生成答案。因为只看到几段,所以可以用更便宜的模型,成本骤降。
它们如何配合:嵌入模型负责「入库」和「查」时的向量化;向量库+检索器负责粗筛;重排模型负责精排;LLM 负责表达。前三者决定「找得准」,最后一个决定「答得好」。
五、RAG 的优势
- 回答更准确:带着真实资料回答,而不是凭空编。
- 降低幻觉:有资料约束,编造空间被压缩。
- 可引用来源:每条答案能附上出处段落,用户可核实。
- 知识实时更新:往库里加新文档即可,不用动模型。
- 降低 Token 消耗:只送 top-N 段(几千 token),不是全库。
- 可使用更便宜的生成模型:因为上下文短而精,小模型也答得不错。
- 企业数据无需重新训练模型:知识在外面,模型参数不动。
六、RAG 与微调(Fine-tuning)的区别
这是高频搜索话题,一张表说清:
| 维度 | RAG | 微调(Fine-tuning) |
|---|---|---|
| 知识更新 | 快(加文档即生效) | 慢(需重新训练) |
| 是否修改模型 | 不改参数 | 修改模型权重 |
| 实时更新知识 | 支持 | 不支持,需重训 |
| 成本 | 低(主要是检索+少量生成) | 高(训练算力+数据标注) |
| 适合场景 | 知识库 / 检索问答 | 让模型学会某种「能力 / 风格」 |
重点:很多企业实际采用 「RAG + 微调」组合——用 RAG 提供最新、可溯源的知识,用微调让模型掌握特定的表达风格或任务格式。不是二选一。
七、如何搭建一个 RAG
完整流程:
- 准备文档:博客文章、PDF、Wiki、工单等原始资料。
- 文本切分(Chunk):按语义切成 300~500 字的小段。
- Embedding:用 bge-m3 把每段变成向量。
- 写入向量数据库:
chunk + 向量 + 元数据入库。 - 用户提问:问题进来。
- 检索:问题向量化后,在库里召回 Top-15。
- 重排(可选但推荐):用 bge-reranker 重排,取 Top-5。
- 交给 LLM 回答:把 Top-5 拼进 prompt,生成答案并附来源。
八、常见开源方案(生态一览)
框架
- LangChain(最流行,组件多)
- LlamaIndex(数据接入与索引见长)
- Haystack(企业级 pipeline)
Embedding 模型
- BGE(
BAAI/bge-m3等,中英文强,硅基流动免费) - Jina Embeddings
- Nomic Embed
向量数据库
- Qdrant(Go 写,性能好,易部署)
- Milvus(大规模分布式)
- Chroma(轻量,开发友好)
- FAISS(Meta 的向量检索库,常作底层引擎)
Reranker
- BGE Reranker(
BAAI/bge-reranker-v2-m3,免费) - Jina Reranker
九、如何优化 RAG(最容易忽略、却最有价值)
- Chunk 大小怎么选:300~500 字是常见甜区;超长文档可先按标题/段落结构切。
- Chunk 是否需要重叠(Overlap):建议留 10%~20% 重叠,避免一句话被切断导致语义丢失。
- Hybrid Search(混合检索):向量检索(语义)+ 关键词检索(BM25 / 全文索引)融合(RRF),召回率明显更高。本博客资源站就是「向量 + ilike 词法」双路 RRF 融合。
- Metadata Filter(元数据过滤):先按时间、分类、作者过滤,再检索,能大幅降噪(比如只搜「2026 年的教程」)。
- Top-K 如何设置:召回 15~20、重排后取 5,是稳妥起点;太长反而引入噪声。
- 是否需要 Reranker:几乎总是「需要」——它能把余弦召回的误排纠正回来,质量提升肉眼可见。
- 如何降低 Token 成本:只送重排后的 Top-5;生成模型选便宜的;嵌入/重排用免费模型。
- 如何提高召回率:混合检索 + 元数据过滤 + 合理 chunk + overlap + 重排,四管齐下。
十、RAG 的应用场景(适合什么场景)
- 企业知识库:员工问制度、流程、产品文档。
- AI 客服:检索历史工单与 FAQ,给出准确答复。
- PDF 问答:上传合同 / 论文 / 手册,直接问内容。
- API 文档助手:开发者问「这个接口怎么调」,定位到对应段落。
- 法律咨询:检索法条与判例(须人工复核,不可直接采信)。
- 医疗知识助手:检索指南与文献(同理,辅助而非替代专业判断)。
- 教育平台:按教材章节答疑、出练习题。
- 博客问答:就像本博客的「就这篇文章问 AI」——读者对某一篇提问,模型只基于该文作答。
十一、常见误区
- RAG ≠ 微调:一个补知识,一个学能力,别混为一谈。
- RAG 不会让模型变聪明:它只是给资料,模型本身能力不变。
- RAG 不是数据库:它是「检索 + 生成」的范式,底层才用数据库。
- RAG 不是搜索引擎:它最终要生成自然语言答案,不是返回链接列表。
- RAG 不一定比微调更适合所有场景:要模型「学会新能力/新风格」还是得微调。
- Reranker 不是必须的:但加了通常显著更好,属于「可选但强烈推荐」。
- Chunk 越大不一定越好:过大反而稀释相关性、浪费 token。
十二、实战案例:本博客的「就这篇文章问 AI」
以这个博客为例,真实架构是:
Markdown 文章(知识库)
↓ 自动切分(按段落 / 标题)
↓ bge-m3 生成 Embedding
↓ 存入向量库(本博客用 Postgres + pgvector;你也可以用 Qdrant)
↓
用户提问
↓ bge-m3 向量化问题
↓ 向量库召回相关文章片段(Top-15)
↓ bge-reranker-v2-m3 重排(Top-5)
↓ 调用硅基流动的 DeepSeek(或更便宜的免费模型)生成答案
一次完整的问答流程(伪代码,可直接落地):
// ① 索引阶段(写文章时跑一次)
const chunks = splitByHeading(markdownText); // 自动切分
const vectors = await embed(chunks); // bge-m3 向量化
await db.insert(chunks.map((c, i) => ({ content: c, embedding: vectors[i] })));
// ② 提问阶段
const queryVec = (await embed([question]))[0]; // 问题向量化
const candidates = await db.search(queryVec, 15); // 向量库召回 Top-15
const ranked = await rerank(question, candidates, 5); // bge-reranker 重排取 Top-5
const context = ranked.map(r => candidates[r.index]).join('\n\n');
// ③ 生成(只送 5 段,便宜又准)
const answer = await chatWithLLM(`
请根据以下资料回答,并标注来源:
${context}
问题:${question}
`);
嵌入与重排调用硅基流动的免费模型:
const SF_KEY = process.env.SILICONFLOW_API_KEY!;
// 嵌入:BAAI/bge-m3(免费,1024 维)
async function embed(texts: string[]): Promise<number[][]> {
const r = await fetch('https://api.siliconflow.cn/v1/embeddings', {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${SF_KEY}` },
body: JSON.stringify({ model: 'BAAI/bge-m3', input: texts, encoding_format: 'float' }),
});
const j = await r.json();
return j.data.map((d: any) => d.embedding as number[]);
}
// 重排:BAAI/bge-reranker-v2-m3(免费)
async function rerank(query: string, documents: string[], topN = 5) {
const r = await fetch('https://api.siliconflow.cn/v1/rerank', {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${SF_KEY}` },
body: JSON.stringify({ model: 'BAAI/bge-reranker-v2-m3', query, documents, top_n: topN }),
});
return (await r.json()).results; // [{ index, relevance_score }] 已按分数排序
}
完整 SQL(pgvector 建表 + 余弦召回)和成本对比,见我另一篇短文;核心结论:嵌入 + 重排都免费,生成模型只看 Top-5(约 3000 token),比「全塞 prompt」省 99%+。
小结
RAG 的精髓就一句话:知识放向量库,提问时只送最相关的几段给大模型。
- 嵌入用
BAAI/bge-m3(免费) - 重排用
BAAI/bge-reranker-v2-m3(免费) - 向量库用 pgvector / Qdrant
- 生成模型只看 Top-5
照这个结构搭,你的 AI 问答会更准、更快、便宜一个数量级。想白嫖这两个免费模型,注册链接:https://cloud.siliconflow.cn/i/MBwLMSrY
本文代码可直接复用——事实上这个博客自己的「就这篇文章问 AI」功能,跑的就是同一套管线。