Skip to content

RAG 架构与工程落地 ​

上一篇解决了「怎么让 LLM 说话」。但 LLM 有个致命短板:它不知道你公司内部的知识。 你问它「我们公司的请假流程是什么」,它要么诚实地说「我不知道」,要么一本正经地编一段。

这一篇回答一个核心问题:当你需要让 LLM 回答「只有你才知道的事实」时,怎么办。 RAG(Retrieval-Augmented Generation,检索增强生成)是当前唯一经济可行的答案。读完你会发现,RAG 的骨架极其朴素,但它的工程细节才是决定「能用」还是「不能用」的关键——而这些细节,恰恰是大多数人学漏的。


1. RAG 是什么:给 LLM 配一张「开卷小抄」 ​

1.1 闭卷 vs 开卷 ​

闭卷考试 vs 开卷考试,就是原生 LLM 和 RAG 的关系。这个类比能帮你瞬间建立直觉:

维度闭卷(原生 LLM)开卷(RAG)
知识来源脑子里背过的(预训练数据,会过时)现场翻书(实时检索)
答错的后果一本正经胡说八道(幻觉)翻错页会答错,翻对了就有凭据
更新成本要重新训练(天价)往书架加本新书(增量灌库)
能否标出处不能能——直接贴原文

一句话心智模型:RAG = 给 LLM 配一个私有图书馆 + 一个精准的管理员。 管理员(检索)先把最相关的几页挑出来,连同问题一起递给 LLM;LLM 基于这些「原材料」续写答案,还能标注「这段来自哪本书」。

一旦建立这个画面,你就会发现一个贯穿全文的规律:RAG 的所有组件——向量库、Embedding、Chunk、Rerank、引用回链——都只是在优化「管理员怎么更快更准地把对的书挑出来」。 这句话记牢,后面每个组件你都不会迷路。


2. 为什么需要 RAG:原生 LLM 的三道死锁 ​

直接拿 gpt-4o 回答「我们公司的请假流程」,你会同时撞上三堵墙:

死锁现象为什么原生 LLM 解决不了
知识不在「我不知道贵司的 HR 政策」训练数据里没有你的私有文档
知识过时回答的是去年的通识训练有截止日期,新政策它没见过
没法溯源自信地编一段生成式本质决定它无法标注出处

2.1 三种方案对比:为什么是 RAG ​

面对「让模型懂我的私有知识」,市面上有三条路,成本天差地别:

方案原理成本更新能溯源适用
继续预训练把私有数据重训进模型百万级每次重训❌几乎不做
微调 Fine-tuning小样本调权重万~十万级增量微调❌改口吻/格式,非注入知识
RAG问时现查,把原文塞进 Prompt接入成本秒级增量✅95% 企业知识问答

一个行业共识,也是新手最容易走岔的坑:先上 RAG,别上微调。

原因在于两者的使命根本不同:

  • 微调解决的是「模型不会说话」——改它的口吻、格式、风格;
  • RAG解决的是「模型不知道事实」——注入它没见过的知识。

绝大多数「公司 AI 助手」,要的是后者:你要的不是「更懂你的模型」,而是「能查你资料的模型」。 而「查资料」这件事,微调天生做不到——它把知识「背」进权重里,就没法实时更新、也没法溯源。所以一上来就微调,是典型的「用错了工具」。

2.2 RAG 的本质:一个公式讲清所有花哨概念 ​

RAG 的本质,用公式说清,胜过千言万语:

text
原生 LLM:answer = LLM(question)
RAG:     answer = LLM(question + retrieve(question, knowledgeBase))

整个 RAG 体系的所有优化,都只是在优化 retrieve() 这一个函数——怎么把最相关的几段原文挑出来。 切片、Embedding、混合检索、Rerank……所有让你眼花缭乱的名词,最后都收敛到这一句话上。记住它,你就有了「纲」,后面所有「目」都挂在它下面。


3. 两条流水线 + 五个组件 ​

3.1 最重要的架构原则:两条流水线必须独立 ​

生产级 RAG 一定是两条独立的流水线:

  • 离线流水线(灌库):数据源 → 同步 → 切片 → Embedding → 向量库
  • 在线流水线(问答):提问 → 改写 → 召回 → Rerank → 组装 Prompt → 生成 → 引用回链

把两者混在一起做,是新手最常见的错误。 为什么必须分开?因为它们的节奏、触发方式、失败后果完全不同:灌库是「离线、批量、慢一点无所谓」;问答是「在线、实时、必须快」。混在一起,一个批量灌库任务就会拖慢在线问答的延迟。

3.2 五个组件,各管一件事 ​

组件职责一句话
Chunker把长文档切成小片段切片质量决定召回上限
Embedding把文本变成向量语义相近 → 向量相近
向量库存向量 + 快速检索找「最像」的片段
Rerank对召回结果二次精排性价比最高的一步优化
Citation答案对回原文出处建立信任的杠杆

这五个组件的责任边界非常清晰,后面几节就是逐个讲透它们各自的「坑」。


4. 离线流水线:最容易被低估的脏活 ​

离线灌库看似「不就是切片+向量化吗」,实则是决定 RAG 效果上限的最脏、最被低估的活。

4.1 切片(Chunking)是效果的天花板 ​

切片切得好不好,直接决定召回质量的上限——切片切烂了,后面 Rerank 再强也救不回来(因为它能选的候选本身就错了)。三条口诀:

口诀一:带重叠。 相邻 chunk 重叠 10%~20%,防止一段语义被硬生生切在 chunk 边界上。比如一句话「……审批流程如下」被切到 chunk A 结尾,而真正的流程在 chunk B 开头,不重叠就召回不全。

口诀二:带 metadata。 每个 chunk 强制带 {doc_id, title, section, url, tenant_id}。这是后续过滤、引用回链、权限隔离的命脉——没有 metadata,你后面什么都做不了。

口诀三:注入标题路径。 给每个 chunk 文本前加「《文档标题》→ 章节标题」。因为 chunk 会被独立召回、独立理解,如果不带标题,「它的审批流程」里的「它」就丢了,模型根本不知道这段在讲谁。

4.2 换 Embedding 模型 = 整库重灌 ​

这是生产级 RAG 最沉重、最容易被忽视的运维成本:

查询向量和文档向量必须来自同一个模型。 因为向量空间是「模型专属」的——A 模型把「猫」映射到坐标 (0.1, 0.8),B 模型可能映射到 (0.9, 0.2)。你拿 A 模型的查询向量,去 B 模型的文档向量库里搜,搜出来的全是乱码。

所以一旦上线后决定换 Embedding 模型,整个向量库必须全量重灌。这不是「改个配置」的小事,而是一次全量数据迁移。

结论:选型阶段务必跑一批真实业务样本做召回率对比,别凭榜单拍板。中文场景开源首选 bge-m3 或 bce-embedding——先想清楚、测清楚,再定模型,因为定了之后就很难换。

4.3 向量库选型:先别急着上专用库 ​

一条经验法则,能帮你省掉一大笔不必要的运维成本:

百万级 chunk 以内,用你已有的 PgVector 或 ES 就够,不新增组件。 只有数据上到千万级、或 QPS 很高,才值得引入 Milvus 这类专用向量库。

原因很实在:新组件 = 新的监控、备份、运维人力。为了一百万条向量,专门养一个 Milvus 集群,这笔账不划算。先复用已有基础设施,等规模真的逼上来了,再迁移。


5. 在线流水线:怎么查得准 ​

在线问答这条流水线,是决定「用户体感好还是差」的关键。四步,每一步都有它的诀窍。

5.1 Query 改写:提问质量的第一道闸门 ​

用户原始提问通常很烂——短、有代词、有口语。直接拿去检索,效果很差:

  • 「那生病呢?」——「生病」指什么?前面聊的请假?病假?
  • 「这个怎么弄?」——「这个」指代不明。

几个套路:问题澄清(补全主语)、同义扩写(提高召回)、多轮消解(把「那生病呢」还原成「那生病请假怎么请」)。

落地技巧:改写本身就是一次小 LLM 调用(用便宜模型即可),把改写和意图识别合并在一个 Prompt 里一次拿到,别拆成多次调用——省一次调用,就省一份延迟和成本。

5.2 混合检索:别只靠语义向量 ​

这是新手最常犯的「技术选型错误」——以为「向量检索就够了」。其实有两类查询,向量的表现截然不同:

  • 语义相似(「怎么请假」「休假流程」)→ 稠密向量擅长;
  • 精确术语(型号编码 iPhone 15 Pro Max、订单号 ORDER-2024-001)→ 关键词(BM25)反而更准,因为「iPhone 15 Pro Max」这种精确字符串,向量相似度反而不如 BM25 的字符匹配。

生产推荐做法(混合检索):向量召回 TopK=20 + BM25 召回 TopK=20 → 融合去重(用 RRF 算法)→ 再进 Rerank。两者互补,召回率显著高于任一单用。

5.3 Rerank:性价比最高的一步优化 ​

Rerank 是「精排」,粗排(向量召回)从千万文档里捞 20 条,精排(Rerank)从 20 条里选出最相关的 Top 5。

Reranker 是「句对打分」模型——它直接对「问题 + 候选片段」这一对做精细的相关性打分,精度比「向量余弦相似度」这种粗排高得多。

加一个 Reranker,通常能把命中率从 ~70% 拉到 ~90%,延迟只增加几十毫秒。 这是 RAG 所有优化里性价比最高的一步——投入最小,收益最大。如果只做一件优化,就做这个。

5.4 引用回链:让答案「有据可依」 ​

Prompt 里要求模型用 [doc_id:chunk_id] 标注事实出处,后处理程序再把这些 ID 换成可点击的链接/脚注。

企业场景里,没有引用的 AI 回答 = 「一个不敢签字的专家意见」。 引用让用户一眼判断能不能信、原文在哪、要不要进一步核实。这是 RAG 能在法务、医疗、HR 这类严肃场景落地、而原生 LLM 不能的关键差异——因为它能溯源,所以能被审计、被信任。


6. 怎么守住可靠 + 安全(本篇命门) ​

RAG 的命门是「可靠 + 安全」双线,缺一不可。

6.1 可靠:没有评测集,RAG 就是盲调 ​

你改了切片参数、换了模型、加了 Rerank——到底变好还是变差?只能靠数据说。 否则就是「盲调」,改了半天,可能越改越差还不自知。

至少要拉一个指标:Recall@K(该被召回的片段,有没有出现在 Top K 里)。

工程化做法:建一个 (问题, 标准答案, 必含片段ID) 的评测集,任何改动都先跑评测基线再合入。这和 09 篇的「评测集」是同一套方法论——RAG 的可靠,同样建立在可量化的评测之上,而不是「感觉不错」。

6.2 安全:权限隔离必须做在每一层 ​

企业知识库一定有权限边界——A 部门的文档,B 部门不该看到。这是安全级问题,三个硬性要求,一个都不能省:

  1. 灌库时:每个 chunk 的 metadata 必须带 {tenant_id, visibility};
  2. 检索时:强制 filter={tenant_id: X},绝不要在召回后靠应用层兜底过滤(那样会有越权检索漏洞——不该召回的片段已经被召回了,再过滤已经太晚);
  3. 生成后:再做一次「引用 ID 是否属于该用户」的二次校验,兜底防线。

核心原则:权限过滤必须「下沉」到检索这一层(向量库的 filter),而不是「上浮」到应用层事后补救。 这一层没守住,后面全都白搭。


7. 最常踩的几个坑 ​

现象根因正确姿势
Top 5 总没有真正相关的Chunk 切太大 / 模型不适配减小 chunk;换中文 embedding
答案里出现 [doc=XYZ] 但库里没有LLM 编造引用 ID后处理校验 ID 是否存在,不存在整句丢弃
加了 RAG 反而更糟召回根本没命中先单独测检索层 Recall@K,别盯着最终答案
A 租户查到 B 租户的文档检索没做 metadata 过滤检索强制 filter,生成后再二次校验
只靠向量检索,精确术语搜不到忽略了关键词检索混合检索:向量 + BM25,再 RRF 融合
换了 embedding 模型,全库乱码查询/文档向量不同源换模型必须整库重灌

8. 记住这一句 ​

RAG 的本质 = 把 P(答案|问题) 改造成 P(答案|问题, 检索到的上下文);其余所有组件都只是优化 retrieve() 这一个函数。

三条硬规则:两条流水线独立、Embedding 一换整库重灌、没有评测集的 RAG 等于盲调。

下一篇预告:RAG 解决了「懂资料」,可 LLM 还是只会「说」,不会「做」——它不能查数据库、不能调 API、不能操作系统。这就到了 04 · Function Calling 与 Agent 范式。

Released under the MIT License.