做知识库问答项目这两年,我最大的感触是:很多人其实没真正搞懂 RAG 和大模型之间的关系,就被一堆概念推着走了。一会儿看到"RAG 能解决幻觉",一会儿又有人说"别折腾了直接微调",还有人把 RAG 当成一个模型、当成一个插件,稀里糊涂地接线,效果出不来就两头抱怨。
先说结论:RAG(Retrieval-Augmented Generation,检索增强生成)不是一个新模型,也不是大模型的附属品,它是一套把"外部资料"喂给大模型的工程方案。它解决的是大模型"不知道你的私有数据、不知道最新信息、还会一本正经地胡说八道"这三个老大难问题。这篇文章我会从原理讲到落地,从检索讲到生成,把 RAG 和大模型的实际分工、协作边界、瓶颈排查一次讲透。适合想自建知识库的技术人、在企业里做私有化问答的工程师,以及还在纠结"RAG 和微调到底选谁"的决策者。
1. RAG 是什么:先搞清大模型"缺什么"
1.1 大模型的知识断层与幻觉根源
要理解 RAG,得先理解大模型的问题。一个训练好的大模型(LLM),它的知识是"冻结"的,训练时数据截止到某个时间点,之后就再也不更新。你问它上周的新闻、问它你们公司内部的制度、问它某个私有数据库里的统计数字,它要么说"不知道",要么给出一个看起来合理但完全是编的答案。
这个"编答案"的现象在行业里叫幻觉(Hallucination)。大模型的本质是"根据上文预测下文"的统计模型,它在生成令牌时,并不会像搜索引擎一样去查一份事实表,而是把最可能出现的词拼接出来。一旦问题超出它的知识覆盖范围,它就顺着语言习惯往下编。这也是为什么很多人第一次和 ChatGPT 聊专业问题时,会被那种"自信的语气"误导,直到核对原文才发现全是错的。
我见过最典型的场景:让大模型帮忙写一份企业内部报销流程文档,它给出的流程步骤听起来特别合理,甚至连部门名字都对,但实际执行时根本对不上——因为它训练时见过太多公司文档的句式,于是"仿写"了一份。这种问题靠调 Prompt 只能缓解,不能根除,因为根源是"模型本身没有这些事实"。
1.2 RAG 的基本工作流:检索 + 生成
RAG 的思路说白了很简单:既然模型没有这个知识,那我们就先到外部资料里把这个知识找出来,再把它塞进 Prompt,让模型"看着资料回答"。
完整流程分两段。第一段是离线索引阶段:把企业文档、知识库文本切分成小段(chunk),每一段通过 Embedding 模型转换成向量,写进向量数据库。第二段是在线问答阶段:用户提问时,先把用户的问题(query)也转成向量,到向量库里做相似度检索,找出最相关的几个文本片段,再把"原始问题 + 检索到的片段"一起组装成 Prompt 发给大模型,最后由大模型生成答案。
注意,这里大模型并没有"学到"新知识,它只是获得了"临时参考材料"。你可以把大模型理解成一个能力很强的实习生,它聪明、表达流畅、逻辑严谨,但内存有限;RAG 就是你在开卷考试前递给它的参考书,它翻着书回答问题,准确率自然高很多。
1.3 为什么要在模型外面套"检索"这一层
有人会问:直接把资料全塞进 Prompt 不就行了?为什么还要搞检索、向量数据库?这里有个现实约束:大模型的上下文窗口(Context Window)是有限的,从早期的 4K、8K token,到现在的 128K、200K token,虽然看着很大,但一份完整的企业手册往往有几十万字,根本塞不下。
即便强行塞进去,大模型对超长上下文的"注意力"也是会被稀释的——中间部分的内容容易被忽略,这就是所谓的"Lost in the Middle"。你给它的资料越多,它越不知道哪句是重点。与其赌大模型的注意力分配,不如先在外面做一个精准的筛选:既然我的知识库有十万个片段,用户问的是 A,那我只需要把最相关的 A1、A2、A3 这几个片段找出来送进去,既节省 token 成本,又降低噪声干扰。
所以 RAG 的本质不是"增强模型",而是"增强输入质量"。它保证大模型在生成之前,先获得一份高质量、高相关性的参考材料,然后让大模型在这个材料范围内作答。这层检索机制,就是解决"知识来源"的问题。
2. RAG 与大模型的协作分工:谁记忆、谁思考
2.1 记忆与推理的边界
如果把大模型比作一个"最强大脑",RAG 就是它的"外置硬盘"。模型的参数量决定了它的通识推理能力——它懂得语法、逻辑、多轮对话、代码结构;RAG 决定的是它能"调用"哪些事实。
很多初学者会犯一个错误:总想让模型当"记忆体",希望它把知识库里的内容"背下来"。比如问"这个项目从 2020 年到 2024 年的营收走势是怎么样的",如果知识库里有对应的财报文档,RAG 可以完美回答;但如果知识库里根本没有这份文档,你无论如何调 Prompt 也不可能让模型答出来。所以记忆这一层,RAG 必须自己扛;推理这一层,则必须交给大模型的自然语言理解能力。两者不是替代关系,而是分工关系:RAG 负责把候选资料压缩到几段精华,大模型负责把这些零散片段组织成连贯、准确、符合用户意图的回答。
2.2 上下文窗口的真实约束
上下文窗口是 RAG 设计里绕不开的物理条件。很多人只关注"窗口多大",忽略了"窗口里装什么"其实更关键。比如一个 128K 窗口的模型,你把 100K token 的原文塞给它,它确实能容纳,但是:
第一,你是按 token 计费的,塞得越多成本越高;第二,生成速度会明显下降,因为模型要对每个输入 token 计算注意力;第三,在长文本中定位关键信息的能力会衰减,越靠中间的信息越容易被忽视。以上三点决定了,RAG 里的"检索"不是可选优化,而是刚需。
我在本地部署测试时就踩过这个坑。最开始图省事,把整本手册(大概 8 万字)直接丢给本地大模型,结果模型回答问题时总是抓不住重点,明明答案就在文档的第 6000 个 token 附近,它却回答得模模糊糊。后来改成 RAG 检索 Top-3 片段(每个片段约 300 字)后再生成,效果立竿见影。这就是"少即是多"的典型例子。
2.3 Prompt 在 RAG 链路里的角色
RAG 链路里 Prompt 承担的角色比很多人想象中更重要,它不只是"把资料粘在用户问题前面",而是要通过结构约束大模型的输出行为。我实际使用的 Prompt 框架通常是三层:
第一层是系统指令,明确告诉模型"你是一个问答助手,只能依据给定资料回答,不要使用自己的先验知识编造内容";第二层是参考材料,用清晰的标记(比如<doc>标签)把检索结果分隔开来;第三层是约束条件,要求"如果资料中没有答案,直接回答'资料中未找到相关信息',不要强行作答"。
说到这里,我提醒一个很容易被忽略的细节:同一个大模型,同一个知识库,如果 Prompt 里加上"请引用原文中的具体表述"这一句,回答的准确率和可验证性就会高很多。模型会更倾向于从资料中抽取句子,而不是自由发挥。这说明 RAG 的效果不仅取决于"检索得准不准",还取决于"生成的约束到不到位",二者缺一不可。
3. 从零到一:RAG 落地全流程拆解
3.1 文档解析与切分:换题难处
RAG 项目真正的第一个坑,一般不在模型,而在"文档怎么进知识库"。大多数知识库丢进来的都是 PDF、Word、Markdown,还有扫描件。你要先把它们解析成纯文本,这一步远比想象中麻烦。纯文本一方面要处理 PDF 里的表格、多栏排版、页眉页脚,另一方面要决定如何把文档切分成 chunk。
Chunk 切分有几个实操经验分享给小实践。第一,固定字数切分(比如每 500 字一块)的通用性很强,但很容易把两个话题拦腰斩断;实用的做法是"按标题结构切分",先识别文档的章节层级,再保证一个 chunk 尽量落在同一个语义单元内。第二,chunk 之间要保留一定重叠(overlap),比如切 500 字、重叠 50 字,避免关键句子恰好被切碎导致检索不到。第三,表格数据建议单独处理,保持行结构,再跟上下文拼接,否则向量化之后很难被准确检索。
提示:如果没有专门的文档解析工具,用成熟的内容抽取类模型(如支持表格还原的文档解析模型)效果远好于直接用正则表达式解析 PDF。这是我做了几个项目后的切身体会。
3.2 Embedding 向量化与向量库选型
切完 chunk 之后,每一段文本都要转成向量。这里涉及两个选择:Embedding 模型和向量数据库。
Embedding 模型负责把文本映射成高维向量,常见的有 BGE、OpenAI 的 text-embedding-3、以及各种国产中文模型。经验是:中文场景优先选择针对中文优化过的 Embedding 模型,效果提升非常明显。因为通用 Embedding 模型对中文的语义表征能力参差不齐,如果只是简单调用英文模型的中文接口,检索精度可能会打七折。
向量数据库方面,本地小项目可以直接用 Chroma、FAISS(文件型、部署简单)入门;生产环境则建议上 Milvus 或 Elasticsearch(支持向量检索和关键词检索混合),以便后续扩展到千万级数据。我个人的建议是:项目刚起步别追求重量级组件,先用轻量级方案把链路跑通,等数据量到了几十万条以上再迁到正式集群。
这里强调一下"向量检索"的局限:它本质上是语义相似度计算。如果用户的问题和文档片段用词差异大但语义相近(比如"怎么申请年假"和"休假制度的规定"),向量模型通常能找到;如果用户的问题包含精确的人名、编号、日期,比如"查询单号 T-2024-001 的状态",向量检索不一定是最优解。生产级 RAG 一般还会叠加 BM25 关键词检索做合并,这个我后面会展开说。
3.3 检索增强:从召回 Top-K 到重排序
检索阶段的核心参数是 Top-K,也就是每次从向量库里取多少个候选片段进入 Prompt。Top-K 太小,容易漏掉关键信息;太大,噪声会明显增多。我的经验是:业务知识库场景,Top-K 从 3 到 5 起步,如果回答质量不稳定,先调这个参数,而不是盲改 Prompt。
更进阶的做法是加入重排序(Rerank)。向量检索第一次先粗召回 Top-50 候选,然后让一个专门的 Rerank 模型(或者更强的大模型)对这些候选按相关性精排,只把最终 Top-3 送入 Prompt。推理链路看起来多了两步,但效果提升常常非常明显。
打个比方,向量检索引擎就像一个海选评委,快速从十万件参赛作品里捞出五十件差不多的;Rerank 模型则是决赛评委,逐一细看,最终选出与题目最匹配的三件。多出来的这一步计算成本不高,但对最终答案的质量影响很大。
3.4 生成阶段:Prompt 组装与答案输出
当检索拿到片段后,PromPT 组装讲究几个原则。
第一,必须"引用锚定"。我习惯在每个检索片段前标注来源编号,比如<doc id="1">、<doc id="2">,然后在 Prompt 里要求模型以"根据资料 [1]"的方式输出,方便事后核对。这不仅让答案可验证,也能在用户误读时溯源,责任边界清楚。
第二,设置"拒绝回答"的兜底指令。如果检索到的资料与问题相关性太低,宁可让模型说"知识库中未找到相关答案",也不要让它在低质量上下文里硬编。这里涉及一个很常见的误区:很多人把这个兜底指令写在最后一句,结果被模型忽略了。正确做法是把它放在系统指令最前部,并在用户 Prompt 里再次强调。
第三,控制生成长度与风格。知识库问答不是聊天,答案应该尽量简洁、分点输出,避免模型在资料基础上做过多的"发散补充"。你可以在 Prompt 里明确"回答不超过 300 字"或"只总结给定内容,不额外补充背景知识",效果立竿见影。
3.5 零基础本地部署方案:Ollama + 轻量向量库
如果你完全零基础,想在本机体验一个真正的本地 RAG 知识库,可以参考我梳理的最小可用方案。
第一步,安装 Ollama,下拉一个大模型(比如 qwen2.5 7b 或 llama3.1 8b),命令是ollama run qwen2.5:7b,这一步主要验证本地推理跑得通。
第二步,下拉一个 Embedding 模型,Ollama 也支持,比如ollama pull bge-m3。
第三步,准备知识库文档,用 Python 读取后按标题或固定长度切分,调用 Embedding 模型生成向量,存入本地 Chroma(一个pip install chromadb就能用)。
第四步,写一个简单的查询脚本:用户输入问题 → 做向量检索 → 取 Top-3 片段 → 拼接 Prompt → 发给本地大模型 → 返回答案。
你会发现整个链路没有任何云端依赖,完全离线可跑,特别适合知识敏感型企业做技术验证。别把本地 RAG 想得太神秘,它本质上就是这几个组件的串联。我见过很多企业从这一套最小方案起步,验证效果后才再评估是否上 Milvus、是否接 Dify 这类正式平台。
4. RAG 与大模型微调:什么时候选谁
4.1 微调到底在解决什么问题
很多人在搜"RAG"的同时,也常搜"大模型微调"。它们经常被放在一起比较,但本质相去甚远。微调(Fine-tuning)是在已训练好的大模型基础上,用特定领域的数据继续训练,更新模型的部分或全部参数,让它学到某种稳定的行为模式或领域风格。
微调适合解决的场景是:让模型在"表达方式"上更像某个领域,比如把模型调成客服口吻、让它学会写特定结构的报告、或者让它稳定输出 JSON 格式。它是在改造模型自身的"行为基因"。
但微调不是用来"喂新知识"的最优手段。为什么?假设你要微调模型记住你们公司所有部门的报销审批节点,而业务数据每周都在变。你不可能每变一次就微调一次模型,成本太高、周期太长,而且微调过程中还可能发生灾难性遗忘——模型记住了新知识,却忘了原本会的老知识。
4.2 选择原则:静态知识用微调,动态/私有知识用 RAG
我给一个简明的选择框架:
如果知识是相对稳定的、需要模型"内化"的表达风格或领域逻辑(比如医疗诊断报告的书写风格、法律文书的段落结构),优先微调。
如果知识是私有的、动态的、或需要精确对齐的事实(比如企业制度、产品手册、实时财报、客服FAQ),优先RAG。
如果两者都要:先用 RAG 做知识供给和事实检索,再用微调调整模型的回答风格和输出格式。两者不是互斥的,而是分层的。大模型负责"怎么答",RAG 负责"答什么依据"。
4.3 我为什么更推荐先上 RAG
在大多数企业内部场景里,我都不建议一上来就微调。原因很现实:微调需要准备大量高质量标注数据,需要 GPU 资源,需要实验调参,而且一发牵全身——模型变了,原来所有 Prompt 可能都要重新验证。RAG 则不同,它不动模型本身,只动检索链路和知识库。这意味着我可以随时更新知识库内容而不影响模型,也可以随时切换不同的大模型底座(比如从开源模型换到商业 API)。
有一个场景让我更加笃定:客户的知识库里有 1 万份 PDF,总计超过 500 万字,同时他们需要每周更新最新的合同模板。用微调方案,光是重新整理训练语料就够喝一壶的;用 RAG,只需要增量更新文档、重新向量化几个文件,几分钟搞定。所以从工程维护角度看,RAG 的"可更新性"是它最大的优势。
5. RAG 实战瓶颈与高频问题排查
5.1 检索召回不到?看看切分和 Embedding
最常见的 RAG 翻车现场是:明明知识库里有答案,但模型说"没有找到相关答案"。这时候多数问题出在检索而非生成。
第一,检查切分是否太粗。如果整个大章节被切成一个超长 chunk,向量平均化之后,"唯一相关的关键句"被大量无关文本稀释,相关性评分自然被压低。解法是减小 chunk 长度,或改用按段落切分。
第二,检查 Embedding 模型是否匹配。你用的 Embedding 模型对领域词汇不敏感,就会导致"句意相近但用词不同"的文本匹配不上。比如科技企业知识库里满是型号、专有名词,通用 Embedding 就可能频繁失手。换个领域词覆盖更好的中文 Embedding 模型,往往立刻见效。
第三,在向量检索之外加一路关键词检索。用 BM25 先按字面命中拉一批候选,再与向量检索做融合(RRF),是业界常用的找齐方式。混合检索能覆盖"语义但不字面"和"字面但语义不同"两类情况。
5.2 回答出现幻觉或事实错误?查引用的边界
如果检索链路没问题,但回答还是自由发挥,那就是生成阶段约束不够。我在实践中总结过几个排查点:
首先确认参考片段是否真的进入了 Prompt。用 LangChain 这类框架时,如果某一环的模板变量没写对,可能出现"检索到了但没有传给模型"的低级错误,模型盲答,自然就跑偏了。排查方法很简单:打印最终发给模型的 Prompt,眼见为实。
其次,检查系统指令中是否明确要求"依据资料作答"。有些模型在用户问题直白、资料相关但不够充分时会"强行补全"。除了加拒绝指令之外,还可以在 Prompt 示例里放一个"资料不足时拒绝回答"的 few-shot 例子。模型看到范例后,行为会明显收敛。
最后,考虑对答案做"事后验证":把模型生成的每条结论拆开,回向量库做一次相似度核对,如果找到一个断言完全找不到出处,就把它标记出来或直接替换。这是成本较高、但专业性很强的方案,适合对准确率要求极高的行业。
5.3 知识库越来越大?性能与成本要提前规划
当 chunk 数从几千涨到几百万时,RAG 链路会暴露出一堆性能问题。全库暴力扫描一万条不至于出问题,但到千万条就必须做量化压缩和分区索引;并发请求一多,向量数据库和推理服务的连接池、超时等配置也要重新调。
成本方面,最大的开销通常不是向量库,而是大模型 API 的 token 费用。日常问答里检索部分只花少量 token,生成部分才是大头。如果每天十万次问答,长答案的成本会非常惊人。解法是加一层缓存:相同或高度相似的问题直接复用历史答案,而不是每次都重新检索、重新生成,我实测能省掉三成以上的成本,响应速度也跟着上来。
5.4 本地部署常见问题速查
很多读者用 Ollama 等工具做本地 RAG 时总会碰到几个固定问题。表格整理一下,方便直接对照排查:
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 本地模型回答极慢 | 纯 CPU 推理或模型过大 | 换 7B 以下的量化版模型,或启用 GPU 推理 |
| 检索结果总是不相关 | 知识库文件编码乱、切分混乱 | 统一转 UTF-8,按结构重新切分验证 |
| 生成内容偏长偏散 | Prompt 缺少长度与格式约束 | 增加"回答不超过 N 字、分点输出"约束 |
| 多文档回答互相矛盾 | Top-K 过大、噪声片段混入 | 降低 Top-K,或增加 Rerank 精排流程 |
| 高频问题成本暴涨 | 重复计算过多、无缓存 | 加相似问缓存层,复用历史结果 |
6. 几个热搜问题的一次性解答
6.1 RAG 知识库能存图片吗
这道题其实要拆开看。RAG 链路里的"知识"本质上是以向量形式存在的文本。如果你把图片直接喂进标准文本 RAG,系统读不了,因为它没有视觉通道。但如果你想检索图片,常见做法有两条路:一是为图片生成类似"图像字幕"的文字描述,把描述存进向量库,检索时只匹配描述,返回图片路径;二是使用多模态 Embedding 模型(CLIP 一类的方案),直接把图片和文本映射到同一向量空间,实现图文交叉检索。
所以答案是:标准 RAG 不直接存图片,但通过"给图片写描述"或"多模态向量模型"就能让它支持。按我现有项目的经验,前者便宜可靠、实现简单;后者效果好,但基础设施复杂度更高。
6.2 大模型如何理解文档
大模型本身没有文档编辑器,它只认识文本 token。所谓"理解文档",本质上是先把 PDF、Word、扫描件转换成能提取的文本或 OCR 文本,进行切分,然后通过检索进入 Prompt。文档里如果包含复杂的表格、图表,常规文本化会损失很多语义,这时要么保留表格结构,要么在 Prompt 里提供 Markdown 形式的表格文本。理解了这层,"大模型能不能看懂复杂文档"就不再是个玄学问题,而是一个你能不能做好前处理的问题。
6.3 企业私有化部署怎么选
企业要接 RAG,通常绕不开"私有化"这个词。文档不出域的前提之下,有两种常见路径:纯粹本地部署,成本低、响应快、天然离线,比如 Ollama + 开源模型 + 内网向量库;另一种是私有云 + 商业模型 API 的闭环,数据不出企业 VPC,但享受更稳定的大模型推理能力。
从我的经验看,企业里最稳妥的方案往往是混合式:用开源模型做检索阶段的 Embedding 和重排序(这两个模型参数量小、效果好),用经过安全评估的商业模型做生成阶段的主力,敏感场景再切换到完全离线的大模型。这样既保证了知识库数据不出域,又能获得较好的问答质量,成本和体验之间能取得相对平衡。
7. 落地 RAG 之后,我的一些实在话
做 RAG 项目做到最后,真正考验人的往往不是模型选型,而是你对知识库质量、文档结构和用户提问习惯的理解。我个人的体会是:RAG 的上限由三块决定——知识库内容质量、检索精度、生成约束力度。这三块没有一块是"装上就能行"的,都需要持续打磨。
如果要从零启动一个 RAG 项目,我的建议顺序是:先用手头最容易出效果的小知识库(比如几十篇 FAQ 或制度文档)跑通全流程;再逐步扩量到几千篇并引入混合检索;上线前一定要设计好引用标注和"答不上来"的闭环反馈渠道。你会发现,当你的 RAG 链路稳定运行后,大模型反而退回到一个相对"工具化"的位置——它很重要,但不再是决定成败的变量。
最后分享一个很多教程没讲透的细节:RAG 里最有价值的打磨点其实在"切分"和"重排"之间。一个和业务紧密对齐的切分方式、一套和领域语料适配的重排策略,效果往往比换一个更大的生成模型提升更明显。用不用得到这句话,等你自己的项目跑到瓶颈期,自然就理解了。