RAG 工程与检索系统设计
一个系统讲解 RAG 从 demo 到生产的工程专栏。
RAG 不是"向量数据库 + 大模型"这么简单。真正的生产级 RAG 系统要处理文档解析、分块、Embedding、索引构建、权限过滤、混合召回、重排序、上下文压缩、引用溯源、增量更新、质量评估、成本延迟控制,以及 Agent 长期记忆。任何一环做错,最终都会表现为同一个症状:模型看似会回答,实际不可信。
本专栏从一次用户提问的完整生命周期出发,拆解 RAG 系统的每个工程边界。
flowchart LR
subgraph OFF [离线 · 知识进入系统]
direction TB
D[文档解析] --> C[分块] --> M[metadata / 权限] --> E[Embedding] --> IDX[索引 · 增量更新]
end
Q[用户提问] --> QR[查询理解与改写]
QR --> PERM[权限边界]
PERM --> REC[多路召回<br/>稠密 + 稀疏]
REC --> RR[重排序]
RR --> PK[上下文打包<br/>token 预算内的证据密度]
PK --> GEN[生成 + 引用校验]
GEN --> LOG[日志 / 反馈 / 评估]
IDX -.供给.-> REC
LOG -.回流.-> OFF
这个专栏最不一样的地方:它从失败讲起。 第 3 章不讲怎么做对,先把四大失败家族摊开——找不到(Retrieval Miss)、找错(Retrieval Error)、塞不下(Context Packing Failure)、答不准(Generation Failure),外加一个被普遍忽视的第五类:延迟失败。再讲它们怎么级联放大、怎么做结构化归因、每类失败该配哪个指标,以及五个合成事故场景的 postmortem 演练。
理由很简单:RAG 出问题时的症状永远是同一句「答得不对」,而原因可能在八个阶段中的任何一个。不会归因,调参就是抽奖。
读完你能做到什么
- 把一次提问拆成八个可观测的阶段。 每个阶段的输入输出契约、降级与 fallback 路径、并行化空间,以及端到端 trace 怎么设计(第2章 请求生命周期)。
- 给线上问题定位到具体阶段。 四大失败家族 + 延迟失败的判据、每类失败的最小可观测指标集、error budget 的量化管理(第3章 失败模式)。
- 把分块这件事做对。 三大策略的取舍、Contextual Chunk、重叠与 metadata 继承、parent-child 多级分块、代码/表格/对话这些特殊内容怎么切,还有真实参数的经验区间与策略变更时的迁移工程(第6章 分块)。
- 建一条混合召回链路。 稠密与稀疏各自的失效场景、混合搜索的融合策略、重排序把候选变成证据(第12章 稀疏检索、第13章 混合搜索、第14章 重排序)。
- 让答案可追溯。 上下文打包在 token 预算内保留证据密度、引用与 grounding 校验(第16章 上下文打包、第17章 引用与溯源)。
- 做权限正确的企业知识库。 metadata 设计与权限过滤要在检索之前发生,而不是在生成之后补救;索引怎么增量更新(第7章 权限、第8章 增量索引)。
- 评估与调优。 RAG 该测什么、怎么对照迭代、成本与延迟怎么压(第20章 评估、第21章 成本与延迟),最后一章是完整的生产落地(第22章)。
这个专栏的讲法
先失败,后成功。 第 3 章的失败地图是本专栏的坐标系,后面每一章都能挂回去:这一章解决的是哪一类失败。
给经验区间,不给"最佳实践"。 分块参数、召回数量、rerank 的取舍——这些数字都带着适用条件,而不是一句"建议 512"。
覆盖到 Agent。 长期记忆与 GraphRAG 两章把 RAG 接到 Agent 上(第18章 长期记忆、第19章 GraphRAG),这是「检索增强」向「智能体」过渡的那一段。
适合谁读
- 正在做企业知识库 / 客服问答 / 代码检索的工程师。 权限、增量、溯源这三章是你绕不开的。
- RAG 系统架构师与搜索工程师。 混合召回与重排序那几章是搜索的老本行在 LLM 时代的新形态。
- Agent 开发者。 Agent 的长期记忆本质上就是一套 RAG。
不适合:想用二十行代码搭个问答 demo 的读者——那不需要这个专栏。这里讲的是 demo 之后的那些事。
版本与核实口径
这个专栏没有单一的基准源码仓库——它讲的是方法论,横跨十几个独立演进的开源组件。所以有必要把"正文里的断言是对着什么核的"写清楚。
一、涉及具体产品能力的说法,对着下面这些版本核过。 读的时候请注意你手上的版本,尤其是过滤语义、多租户机制这类各家差异极大、且还在快速变化的部分:
| 组件 | 核实所依据的版本 |
|---|---|
| Qdrant | v1.19.1 |
| pgvector | v0.8.6 |
| Milvus | v3.0.1 |
| FAISS | v1.15.0 |
| unstructured | 0.27.5(2026-08-28 发布的 tag;此后上游又发了 0.27.6、0.27.8,未逐一复核;版本演进的说法另查了 0.10.x / 0.11.0 的 CHANGELOG) |
| LangChain | langchain 1.2.15 / langchain-core 1.2.26 / langchain-text-splitters 1.1.1 / langchain-classic 1.0.3(1.x 把一批 0.x 遗留组件挪进了这个独立包) |
| LlamaIndex | llama-index-core 0.14.24 |
| Ragas | v0.4.3 |
核实时间为 2026 年 9 月。没有标注版本的功能描述,是指该组件长期稳定的通用能力;凡是"某功能在某版本引入"这类说法,正文里会写明版本,否则就是核不实后删掉了版本号。
表里给的是核实时各组件的当期版本。正文里还有不少"某功能在某个更早的版本引入"的断言(Qdrant 1.7 / 1.10 / 1.11、Milvus 2.4 / 3.0、pgvector 0.8.0 等),这类断言是切到对应 tag 上回溯核实的(读该 tag 的源码或 CHANGELOG),不是拿当期分支的现状去倒推——所以表里的版本号和正文里的版本号不是一回事,不必对齐。
二、模型、价格、上下文窗口这类会过期的数字,一律按"当期定价页为准"处理。 正文出现绝对金额时,会同时给出算式(量 × 单价),这样单价变了你能自己重算。模型 ID 按各家官方写法给出(例如 claude-sonnet-4-6 用连字符,不是点号)。
三、性能数字的口径。 这是最容易被误用的部分,本专栏的规矩是:
- 可引用的:来自公开论文或厂商公开报告、且注明出处的数字(例如第 3 章、第 6 章引用的 Anthropic Contextual Retrieval 的 top-20 失败率)。这类数字只在它自己的语料上成立,用来判断方向,不能当作你的预期值。
- 可推算的:从维度、字节数、token 数算得出来的量(索引内存、embedding 账单、chunk 数量)。正文尽量给算式而不是结论数。
- 必须自测的:recall、QPS、P99、OCR 准确率、embedding 吞吐、chunk 甜点长度——这些没有通用值,正文一律不给具体数字,只给"怎么测""曲线该是什么形状""看到什么形状说明哪里有问题"。
如果你在正文里发现了一个没有出处、又不属于上面前两类的性能数字,那是遗漏,欢迎指出来。
四、论文引用。 标题、第一作者、年份、arXiv 编号逐条核对过;年份统一按正式发表年(会议/期刊)书写,与 arXiv 首次提交年不同不算错。核不实的编号一律删除,只保留标题。
目录
开篇
第一部分:RAG 系统全景
第二部分:知识进入系统
- 第5章 文档解析:PDF、HTML、Markdown、代码仓库
- 第6章 Chunking:固定分块、结构化分块与语义分块
- 第7章 Metadata 与权限模型:让知识带着边界进入索引
- 第8章 增量索引:更新、删除、重建与一致性
第三部分:表示与索引
- 第9章 Embedding:文本如何变成可检索的向量
- 第10章 向量索引:Flat、HNSW、IVF 与 PQ 的工程直觉
- 第11章 向量数据库:Qdrant、Milvus、pgvector 的架构取舍
- 第12章 稀疏检索:BM25 为什么仍然重要
第四部分:召回、排序与上下文
- 第13章 Hybrid Search:向量召回与关键词召回的融合
- 第14章 Rerank:把"大致相关"变成"真正可用"
- 第15章 Query Rewrite:让用户问题变成可检索问题
- 第16章 Context Packing:把证据装进有限上下文
- 第17章 引用、溯源与答案可信度
第五部分:Agent Memory 与 GraphRAG
第六部分:生产化
版权声明
本专栏内容为 杨艺韬 版权所有,保留一切权利。未经书面许可,不得全文或大段转载、改编、翻译,或用于任何商业用途(含以本专栏内容训练模型、生成衍生课程或商品)。
欢迎分享本专栏的链接。引用少量内容用于评论、教学或研究时,请署名 杨艺韬 并附上原文链接。