面试官你好,这道题问[[RAG]]的分类,其实本质是在问检索和生成之间的耦合度是怎么演进的。我理解RAG不是一种固定的架构,它从最早的简单拼接,到后来加各种优化,再到最近模块化、[[Agent]]化,其实是检索和生成从硬耦合走向解耦的过程。
先说最早的一代,[[Naive RAG]]。它的流程很简单:离线把文档切成块、做 [[Embedding]] 存进 [[Vector Database]],用户提问时检索出最相关的几个块,直接拼到Prompt里交给LLM生成。这个架构最大的问题是检索和生成是硬耦合的,一次检索结果就决定了输出质量,如果检索错了,模型只能硬着头皮基于错误信息来回答,就会出现 [[Hallucination]]。所以它只适合单跳、确定性强的场景,比如内部文档里的简单事实问答,像查员工手册里年假天数这种。换个场景,比如客服问退款政策,用户可能说'我买的东西降价了',Naive RAG直接搜'降价'可能搜不到退款条款,这就挂了。
所以后来出现了Advanced RAG,它的核心是在检索的前、中、后都加优化。检索前做查询改写或扩展,比如用 HyDE 先生成一个假设文档再检索;检索中用 [[Hybrid Search]] 融合关键词和向量,再用 [[Cross-Encoder]] 做 [[重排]];检索后做上下文压缩,把检索回来的长文本摘要成关键信息,避免把噪声带进生成。这里有一个关键点:不是所有场景都需要重排。如果知识库质量高、[[分块]]合理,直接用 [[BM25]] 加向量检索的混合就够用了;只有噪声多、需要精确排序的场景,比如企业合规文档,才需要加重排。我实际落地企业知识库时,最关注的是检索后的上下文压缩,因为LLM对输入长度敏感,压缩能直接提升生成的准确率和速度。但这里有个坑:压缩本身也会丢失信息,所以需要设计好压缩策略,比如只保留跟问题最相关的段落。
再后来就是[[Modular RAG]],也叫[[Agentic RAG]]。它把检索和生成彻底解耦,引入一个调度器来决定什么时候检索、检索什么、要不要多轮迭代。比如 [[Self-RAG]] 让模型在生成时输出反思token,判断当前答案是否需要更多证据;[[ReAct]] 则是边推理边检索,像人类查资料一样一步步逼近答案。这个架构灵活性最高,但延迟和成本也最高。它的典型场景是科研分析或多跳推理,比如问'某药物对某疾病的疗效,对比传统疗法有哪些优势',需要先查到药物数据,再查疾病背景,再对比,一次检索搞不定。
那么这三类怎么选呢?我的经验是:不要孤立地选一类,而是根据场景混合使用。比如做一个客服退款系统,可以先用Naive快速搭一个原型验证可行性;然后加上查询改写和重排,变成Advanced;如果遇到复杂退款纠纷需要查多份政策,再引入调度器做多轮检索。边界划分上,Naive适合单跳、确定性场景;Advanced适合噪声多但仍是单跳的场景;Modular适合多跳、开放域复杂任务。但真正落地时,我常常把Advanced和Modular结合,比如用Modular的调度器来控制Advanced的检索流程,而不是完全照搬论文。
不过这里有个延伸点值得留意:Modular RAG里的调度器如何决定何时停止迭代?如果不停,可能会浪费token甚至陷入循环。我倾向于用置信度阈值加最大轮数来控制,但更优雅的做法是用 [[Faithfulness]] 评估当前答案对检索结果的支持度,低于阈值就继续检索。
最后总结一下我的工程师判断:RAG不是越高级越好,Naive有它快速验证的价值,Advanced适合优化体验,Modular解决复杂问题。我会把RAG的选型看成一条演进路径,从简单开始,按需加复杂度,避免过度设计。前提是索引质量要够好,否则后面所有优化都是白费。如果面试官感兴趣,我们可以再深入聊聊调度器的具体实现。