RAG 架构实战评测:Naive、Advanced、Modular 三种方案我全测了一遍
同一知识库、同一测试集,三种 RAG 架构的检索准确率、延迟、成本实测对比
AinoCode 编辑部
RAG 架构实战评测:Naive、Advanced、Modular 三种方案我全测了一遍
做 RAG 的人都知道一件事:文档切块、向量化、相似度搜索,这套流程跑通了只能算”能用了”。但召回率上不去、答案牛头不对马嘴的问题,十有八九不是模型的问题,是架构的问题。
我自己搭过不下十个 RAG 系统,踩过无数坑。这篇把三种最主流的 RAG 架构拿出来实测——不是概念对比,是我用同一个知识库、同一套测试集,跑出来的真实数据。
先交代测试环境。
知识库用的是我们团队内部的 200+ 篇技术文档(约 15 万字),涵盖运维手册、API 文档、故障处理记录。测试集是 30 个问题,由团队成员根据实际工作中遇到的真实问题整理,覆盖了”精确查找”、“多文档综合”、“模糊语义匹配”三种类型。
评测指标三个:命中率(检索到的 chunk 是否包含正确答案)、首 token 延迟、单轮查询成本。
Naive RAG:最简单,也最不可靠
Naive RAG 的流程教科书上都有:文档切分 → 向量化 → 存进向量库 → 查询时向量化检索 → 拼接 prompt 给 LLM。
听着没问题。但实际跑起来问题一大堆。
第一个问题是切块策略。我用的固定 500 token 分块、100 token 重叠。这个参数是网上教程里最常见的推荐值,但对我的技术文档来说,很多关键信息被切断了。比如一段 API 错误码说明,刚好跨在两个 chunk 的边界上,检索时要么拿到上半截要么拿到下半截,都不完整。
第二个问题是检索。Naive RAG 只做一次向量相似度搜索,top-k=5。看起来够用,但向量相似度有个致命缺陷:它对术语匹配不敏感。用户问”API 报 503 怎么排查”,如果文档里写的是”服务不可用错误”,向量模型可能根本匹配不上。
实测数据:
| 指标 | 数值 |
|---|---|
| 精确查找命中率 | 62% |
| 多文档综合命中率 | 38% |
| 模糊语义命中率 | 71% |
| 首 token 延迟 | 1.2s |
| 单轮成本 | ¥0.003 |
多文档综合 38% 这个数字,坦率讲,不可接受。用户问一个问题需要综合多份文档才能回答的情况在实际中非常多见,不到四成的命中率意味着这个系统基本没法用。
延迟倒是最低的,因为只走了一次向量检索。成本也是最低的,同样的原因。
Naive RAG 适合什么场景?文档结构简单、每份文档独立性强、用户查询都是精确关键词匹配。比如 FAQ 知识库、产品说明书这种。如果你的知识库是跨文档关联的技术文档,Naive RAG 大概率不够用。
Advanced RAG:加了一堆优化,效果确实上去了
Advanced RAG 在 Naive 的基础上加了四个关键优化:
1. 文档预处理
不再用固定分块。改用语义分块——按段落标题、章节结构自然切分。同时给每个 chunk 加元数据:来源文档、章节标题、关键词、更新时间。
这一步改动不大,但对后续检索的帮助是根本性的。有了元数据,检索就不再是纯向量匹配了,可以做混合检索。
2. 混合检索(Hybrid Search)
向量检索 + BM25 关键词检索,两路召回再 rerank。这是 Advanced RAG 最核心的改进。
向量检索负责语义匹配,BM25 负责精确术语匹配。两者互补。我用的 reranker 是 BGE-Reranker-v2-m3(开源,本地部署不花钱),对两路召回的 top-20 结果做重排序,取 top-5。
光这一步,精确查找命中率就从 62% 跳到了 84%。
3. 查询重写(Query Rewriting)
用户原始查询先过一遍 LLM,做语义扩展和术语转换。比如”API 报 503”会被重写成”API 服务不可用 503 错误排查方法 解决方案”。
这一步解决的是用户表达和文档表述不一致的问题。模糊语义命中率从 71% 提升到 89%。
4. 上下文压缩(Context Compression)
检索到的 5 个 chunk 拼起来可能超过 LLM 上下文窗口,或者包含大量无关信息。用 LLM 对检索结果做摘要压缩,只保留与查询相关的部分再送给生成模型。
这一步对延迟和成本的影响最大,后面说。
实测数据:
| 指标 | 数值 | 相比 Naive |
|---|---|---|
| 精确查找命中率 | 84% | +22% |
| 多文档综合命中率 | 72% | +34% |
| 模糊语义命中率 | 89% | +18% |
| 首 token 延迟 | 2.8s | +1.6s |
| 单轮成本 | ¥0.018 | +¥0.015 |
效果提升很明显。但代价也不小——延迟翻倍还多,成本翻了 6 倍。原因主要在于查询重写和上下文压缩各多了一次 LLM 调用。
Advanced RAG 适合大多数生产场景。命中率 70-90% 的区间对内部知识库来说基本够用了。如果你的团队能接受单次查询 3 秒左右的延迟,这是性价比最高的方案。
Modular RAG:拆成可插拔模块,灵活度最高
Modular RAG 的思路和 Advanced RAG 不一样。Advanced RAG 是一套固定的优化流程,Modular RAG 是把每个环节拆成独立模块,按需组装。
核心模块包括:
- Retriever:向量检索、BM25、知识图谱、API 调用……可选多个,并行或串行
- Router:根据查询类型决定走哪个检索路径
- Rewriter:查询扩展、分解、翻译
- Generator:LLM 生成,支持多个模型 fallback
- Reflector:对生成结果做自我校验,判断是否需要重新检索
我搭的 Modular RAG 版本在 Advanced RAG 的基础上加了 Router 和 Reflector。
Router 的逻辑是这样的:
def route_query(query: str) -> str:
if is_precise_term(query):
return "bm25"
elif is_multi_hop(query):
return "multi_hop"
elif is_code_related(query):
return "code_search"
else:
return "hybrid"
这个路由判断本身用了一个小的分类模型(本地部署的 BERT,推理不到 10ms),准确率大概 92%。
Reflector 是最后一步。生成答案后,用另一个 LLM 调用判断答案是否可靠。判断标准是:答案中引用的信息是否都能在检索结果中找到依据。如果找不到依据,标记为”可能需要重新检索”,触发第二次检索,这次用更宽泛的查询条件。
Reflector 这一步在测试中表现很有意思。30 个问题里,它标记了 5 个需要重新检索。重新检索后,其中 3 个确实找到了更好的答案。另外 2 个是误判——原来的答案其实是对的,但引用的表述和检索结果略有差异。
实测数据:
| 指标 | 数值 | 相比 Advanced |
|---|---|---|
| 精确查找命中率 | 88% | +4% |
| 多文档综合命中率 | 81% | +9% |
| 模糊语义命中率 | 93% | +4% |
| 首 token 延迟 | 3.5s | +0.7s |
| 单轮成本 | ¥0.025 | +¥0.007 |
Reflector 带来的成本增加不大,因为大部分查询(25/30)不需要二次检索。但 Router + Reflector 的架构优势在于可扩展性。比如我想接入代码搜索(针对代码仓库的 RAG),只需要加一个 Retriever 模块,不需要改其他部分。
横向对比:三种架构怎么选
把数据放在一起看更清楚:
| 指标 | Naive | Advanced | Modular |
|---|---|---|---|
| 精确查找命中率 | 62% | 84% | 88% |
| 多文档综合命中率 | 38% | 72% | 81% |
| 模糊语义命中率 | 71% | 89% | 93% |
| 首 token 延迟 | 1.2s | 2.8s | 3.5s |
| 单轮成本 | ¥0.003 | ¥0.018 | ¥0.025 |
| 开发复杂度 | 低 | 中 | 高 |
| 可扩展性 | 差 | 中 | 优 |
我自己的选型建议:
选 Naive 的情况:知识库小于 50 篇文档,用户查询类型单一,对延迟极度敏感(比如实时聊天场景)。坦率讲,这种场景在 2026 年已经不多了。
选 Advanced 的情况:大多数生产场景。知识库 50-500 篇文档,查询类型多样但可预测,团队能接受 2-3 秒延迟。混合检索 + 查询重写 + 上下文压缩这套组合拳,在命中率和成本之间取得了最佳平衡。
选 Modular 的情况:知识库 500 篇以上、查询类型不可预测、需要对接多种数据源(文档 + 代码 + API + 数据库)、或者对答案可靠性要求极高(医疗、金融场景)。Router 和 Reflector 带来的额外复杂度是值得的,因为这种规模下,单一检索路径肯定不够用。
还有一个容易被忽视的维度:维护成本。Naive RAG 出了问题,排查很简单——就是检索和生成两个环节。Advanced RAG 出了问题,你要查是预处理、检索、重写还是压缩哪个环节出了问题。Modular RAG 出了问题,模块之间的交互关系让排查变得复杂。所以 Modular RAG 需要配套的监控和日志系统,这是 Advanced RAG 不太需要的。
实测中的踩坑记录
坑 1:BM25 和向量检索的权重分配
混合检索中 BM25 和向量检索的分数范围不同,直接相加没有意义。我做了一个简单的归一化:先把两路分数分别做 min-max 归一化到 [0,1],再加权求和。权重我试了 0.5/0.5、0.3/0.7、0.7/0.3,最后发现 0.4(BM25)/0.6(向量) 效果最好。
但这不是通用的。如果你的文档里专业术语多,BM25 权重应该更高;如果文档表述口语化,向量权重应该更高。
坑 2:查询重写的过度扩展
LLM 做查询重写时,有时候会把查询扩展得太宽泛。比如用户问”怎么配置 TLS 证书”,被重写成”TLS 证书配置方法 步骤 流程 注意事项 最佳实践 常见问题”。扩展出来的词太多,BM25 匹配上了很多不相关的文档。
我的解决方案是给重写加了约束:最多扩展 3 个关键词,且必须是原文档中出现过的术语。用一个术语词典做约束,效果明显改善。
坑 3:Reflector 的误判
Reflector 判断”答案是否有依据”时,有时候会因为表述差异误判。比如检索结果说的是”服务器返回 5xx 错误”,答案写的是”服务端错误”,语义一样但字面不同,Reflector 会判定为”无依据”。
这个问题我还没找到完美的解决方案。目前的临时办法是给 Reflector 加一个”语义等价判断”的步骤,用一个小模型判断引用和原文是否语义等价。但这样又多了一次推理调用,成本再涨。
总结
RAG 不是”搭好就能用”的东西。Naive RAG 能跑通,但命中率不够。Advanced RAG 是性价比最高的生产方案。Modular RAG 是上限最高的架构,但需要投入更多开发和维护精力。
我自己的结论是,从 Advanced RAG 起步,根据实际业务需求逐步 Modular 化。不要一上来就搭 Modular RAG——很多模块你用不上,但每个模块都要维护。
毕竟,最好的 RAG 架构不是最复杂的那个,是刚好能解决你的问题、又不会引入不必要复杂度的那个。