刚开始学 RAG 的时候,我最容易混在一起的是三个东西:大模型、向量数据库、检索链路。
后来我发现,RAG 最好不要一上来就理解成一套复杂框架,而是先理解成一句话:
先从自己的知识库里找资料,再把资料交给大模型回答。
大模型负责表达,知识库负责事实依据。RAG 想解决的核心问题,就是让回答不只依赖模型记忆,而是能基于我们自己的资料。
1. RAG 的两条链路
一个 RAG 项目通常可以拆成两条链路:
| 链路 | 什么时候运行 | 主要任务 |
|---|---|---|
| 入库链路 | 文档新增或更新时 | 清洗、切块、向量化、写入向量库 |
| 问答链路 | 用户每次提问时 | 检索相关片段、拼上下文、生成回答 |
这两个链路分清楚之后,很多问题会突然清晰。
如果问答效果不好,可能不是大模型不行,而是入库阶段切片太差、向量没写进去、元数据缺失,或者检索阶段没有把正确片段召回来。
2. 入库链路:把资料变成可以检索的 chunk
原始资料一般不能直接丢给大模型。
原因很简单:资料太长,模型上下文放不下;资料结构也不一定适合检索。
所以入库端通常会做几件事:
- 读取文档,例如 Markdown、PDF、Word。
- 清洗内容,去掉无用格式。
- 按标题、段落或固定长度切成 chunk。
- 调 embedding 模型,把 chunk 变成向量。
- 把文本、向量和元数据写入向量库。
这里有一个容易忽略的点:问题和资料最好使用同一个 embedding 模型生成向量。
如果文档用一个模型向量化,问题又用另一个模型向量化,它们可能不在同一个语义空间里,相似度就会变得不可靠。
3. 问答链路:先找资料,再回答
在线问答阶段的流程大概是:
用户问题
-> 问题向量化
-> 相似度检索
-> 拿到 TopK 文档片段
-> 拼进 Prompt
-> 大模型基于资料回答
这就是最基础的 RAG。
如果继续增强,还可以加入:
- Query Rewrite:把多轮追问改写成独立问题。
- HyDE:先让模型生成一个假设答案,再拿假设答案去检索。
- BM25:用关键词补充向量检索。
- RRF:融合多路检索结果。
- Rerank:对候选片段重新精排。
但这些增强都应该建立在基础链路可用之后。否则链路越复杂,越难判断到底是哪一步出了问题。
4. RAG 不是只装一个框架
很多框架可以帮我们封装 RAG,例如 LangChain、LangChain4j 或 Spring AI。
但真正影响效果的,往往不是“用了哪个框架”,而是这些工程细节:
- 文档怎么切片。
- 元数据有没有保留标题、来源、位置。
- 检索时 TopK 设置多少。
- 召回结果是否能被观察。
- 回答是否只基于检索上下文。
- 数据更新后旧向量有没有删除。
框架能省掉样板代码,但不能替我们决定这些策略。
5. 我现在对 RAG 的理解
现在我会把 RAG 看成一个工程系统,而不是一个单点算法。
它至少包括:
资料治理
-> 文档切片
-> 向量入库
-> 检索召回
-> 融合排序
-> 上下文构造
-> 大模型生成
-> 效果评估
只要其中一个环节不稳定,最终回答就可能不稳定。
所以学习 RAG 最好的顺序不是先堆功能,而是先跑通最小闭环,再逐步增强召回、排序和评估。
这也是我后面做知光知识社区 RAG 改造时采用的思路:先让问答链路真实可用,再做全库问答、多轮记忆、rerank 和召回率优化。
