☰
从Naive到Agentic:RAG系统演进与实战经验全解析
2026/10/19 11:20:33 网站建设 项目流程

做AI应用开发的朋友,大概率都有过这种体验:模型聊起通用知识头头是道,一落到你公司的内部文档、最新产品资料、某个领域的专业细节,就开始一本正经地胡说八道。把资料喂给模型?上下文塞不下。微调?成本高、周期长,过几天资料一更新又得重来。于是检索增强生成(RAG)成了大家默认的解法——先检索相关资料,再把资料拼进Prompt让模型作答。但真正动手之后会发现,从最朴素的Naive RAG到能应对复杂问题的Agentic RAG,中间还有一大段路要走。这篇就把我实际搭建和迭代RAG系统的经验完整拆开,讲清楚每一代方案到底解决了什么问题、代价是什么、什么时候该升级。

我自己从最早“切文档-存向量-拼Prompt”的简易版本,一路做到带查询规划和自我反思的Agent制式系统,踩过的坑不少,也总结了不少可以直接抄作业的判断标准。这篇文章既适合刚接触RAG、准备搭第一个知识库问答的新手,也适合已经在跑RAG但被召回不准、答非所问折磨的开发者。内容不追求炫技,重点是把演进逻辑和实操细节讲透。

1. 先别急着调代码,搞清楚RAG到底在解决什么问题

1.1 模型再聪明也改不了三个“先天不足”

很多人上来就问“RAG用哪个向量库好”“chunk_size设多少”,但我觉得第一步应该是想明白:RAG到底在补模型的什么短板。拿我自己的实践经验来说,大模型有三个问题靠调Prompt和微调都很难根治。

第一个是知识新鲜度问题。模型训练完之后,它的知识就定格在那个时间点了。你问它最新的产品版本、新发布的功能、刚改的流程规范,它只能靠猜。我见过不少团队想用“加上当前日期再让模型推理”的方式硬解,效果很勉强,因为模型压根没有这部分知识的来源,你再怎么引导也是无米之炊。

第二个是私有知识问题。公司内部的制度文档、项目复盘、技术方案、客户记录,这些内容根本不会出现在模型的训练数据里。模型不知道就是不知道,它唯一能做的是编一个逻辑通顺的答案出来——这恰恰是大家最害怕的“幻觉”。

第三个是知识密度问题。有些垂直领域其实公开资料很多,但模型在训练时只“读过”而没“记住”。让它复述大致概念可以,一旦涉及精确数字、条文编号、公式细节,它就模棱两可。

RAG的思路很直接:既然模型记不住,那就给它开卷考试。每次提问时,先从外部知识库里检索相关的资料片段,把这些片段作为上下文交给模型,让它在限定资料范围内作答。这相当于给模型配了一个随时更新的资料库,你不用重新训练就能让它掌握新知识。

用一个生活化的类比就好理解了:模型像一个知识面很广但记忆模糊的助手,你直接问它,它凭印象答;但如果你先翻好资料、把相关段落摆在它面前,让它“照着资料说”,准确率会提升一大截。RAG系统做的,就是把“翻资料”这个动作自动化、规模化。

1.2 RAG不是万能胶:适合什么、不适合什么

我必须泼一盆冷水:RAG并不是所有问题的答案。我见过太多人把RAG当锤子,看什么都像钉子,结果项目上线后效果不理想,反过来怀疑RAG没用。实际上,RAG有非常明确的适用边界。

适合RAG的场景,核心特征是答案能在资料里直接找到。典型的包括:企业内部知识库问答、产品文档自助查询、法律法规条文检索、学术论文辅助阅读、电商客服售后答疑。这些场景里,用户的问题和文档中的某段内容有比较直接的对应关系,检索到正确片段后,模型只需要做“阅读理解”和“整理转述”,不需要太多额外推理。

不太适合RAG的场景,通常是那些需要多步推理、全局统计或高度综合的任务。举个例子,你问“根据这个季度所有项目的工时记录,分析一下哪些环节最容易延期”,这类问题看起来也能检索,但答案分散在几十上百条记录里,单纯用“取top-k个相似文档”的方式根本凑不齐完整信息。又比如“帮我算一下公司上个月的服务器总成本”,如果资料是全量明细,RAG检索出来的片段只能覆盖其中一小部分,模型没法基于残缺上下文给出准确数字。

还有一个容易被忽略的边界:资料本身质量就很差时,RAG就是在垃圾堆里找宝藏。我之前接手过一个项目,原始资料是大量扫描件的OCR结果,错字连篇、段落错乱,检索出来倒是能“命中”,但内容根本没法用。后来先花了两周做数据清洗和版面重构,效果才起来。所以做RAG之前,先问自己三个问题:资料有没有覆盖答案?资料能不能被正确读取?答案是不是能靠“引用片段”回答?如果前两个存疑,先解决数据问题再谈检索策略。

认清边界之后,再来看具体的技术演进,就会有方向感:不同代的RAG方案,本质上是在不同复杂度的任务里,用不同成本的机制去换取准确率。

2. Naive RAG:最小闭环能跑,但别指望它“稳”

2.1 最小可用流程:从资料入库到回答生成

Naive RAG是绝大多数人接触RAG的第一步,也是我当时搭的第一个版本。它不复杂,核心就四步:切分、向量化、存储、检索生成。我把每一步的关键细节拆开讲。

第一步是文本切分。原始文档不能整篇塞进向量库,因为太长的文本向量化后会丢失细节,检索时也不够精准。常见做法是按固定长度切块,比如512个token或1000个字符一段,相邻块之间留一些重叠,避免关键信息正好被切在边界上。更合理的方式是按文档结构切,比如先按标题层级分章节,再按段落切分,这样每一块的内容主题更集中。这个选择会直接影响后面的检索效果,后面我会单独展开。

第二步是向量化。把每个文本块通过嵌入模型转换成一个高维向量,让语义相近的文本在向量空间里距离更近。这里最关键的是选嵌入模型。我当时对比过好几款主流的通用嵌入模型,发现它们在通用语料上成绩都差不多,但换到垂直领域的文档上,差异会立刻显现出来。原因不复杂:嵌入模型在训练时见没见过类似领域的文本,直接决定它能不能把领域内的专业词汇映射到合理位置。所以选模型时最好拿你自己的业务语料做一个小验证集,而不是只看公开榜单。

第三步是存进向量数据库。向量数据库负责两件事:存向量、做近似检索。库里的每个向量都带着原文内容和元信息,比如来源文档、页码、章节标题。选型上,需要考虑数据量级、并发量和是否要复杂的过滤条件,但初期其实差别不大,关键是把数据管好。

第四步是检索和生成。用户提问时,先把问题转成向量,在库里找出最相似的top-k个文本块,最后把这些文本块作为上下文,拼进Prompt,让模型基于这些内容生成回答。伪代码可以写成这样:

def naive_rag(query, k=5): q_vec = embed(query) docs = vector_store.search(q_vec, top_k=k) context = format_context(docs) # 拼接检索到的文本块 prompt = f"请只根据以下资料回答问题,不要使用资料之外的信息。\n\n资料:\n{context}\n\n问题:{query}\n回答:" return llm.complete(prompt)

我把关键参数整理成一张表,方便你对照调整:

参数我的常用起点作用调参方向
chunk_size512~1024字符控制每个文本块的内容量资料主题较碎时调小,连续性强时调大
chunk_overlap50~150字符缓解切块切断语义的问题过大浪费token,过小挡不住边界截断
top_k5~8控制注入Prompt的片段数量检索不准时先调大,再配合重排
embedding模型根据领域选决定语义匹配的上限用业务样本评测后替换
检索类型向量检索按语义相似度召回后续可加混合检索

这个最小闭环跑通之后,你就拥有了一个看起来“什么都能答两句”的知识库问答系统。但注意,只是“能答”,离“答得好”还有距离。

2.2 四宗罪:我在朴素方案里踩过的坑

Naive RAG的缺陷,在我实际使用时几乎全踩了一遍。它不是不能用,而是“能用”和“好用”之间的差距非常大。我归纳成四个核心问题。

第一是召回不精准。向量检索本质上是“模糊匹配”,它对语义相近的内容表现不错,但对精确信息非常迟钝。比如你问“合同编号HT-2024-0018”,正确的那个文档里写着这个编号,但向量检索可能把“HT-2024-0081”这种看着很像的段落给召回来了,因为它们在向量空间里距离很近。再比如查某个产品型号、某个接口的具体参数,向量检索经常把一堆泛泛而谈的介绍排在最前面,真正的关键信息沉在后面。这在纯文本语义场景还能忍,在代码、型号、编号这类精确制表符很常见的业务场景里,几乎是致命的。

第二是上下文污染。top_k个文本块拼在一起,未必每一块都对答案有贡献。某些块可能是同名术语的错误含义,某些块可能只是主题相关但根本没有回答问题的关键信息。把这些噪声塞进Prompt,模型会被带偏。我遇到过很典型的case:用户问某功能的开启方式,检索回来的5个文档里只有1个真正讲了操作步骤,另外4个是功能介绍和市场宣传文案。最终模型把宣传文案里的描述当成了操作步骤,答得还特别自信。这时候你甚至不能说模型“错”了,它是被垃圾输入带偏了。

第三是信息断裂。复杂问题的答案往往分散在多个不同文档中,每一块都只包含一部分。Naive RAG每次只做一轮检索,拿到的就是“局部视图”。模型看完这些零散的片段,就像盲人摸象,它需要在缺少全局信息的情况下硬着头皮回答,结果自然不够完整。这个问题的根因不在生成模型,而是检索机制压根没设计成“支持多跳信息整合”。

第四是幻觉没有真正根治。很多人以为用了RAG,幻觉就消失了。实际操作下来,“不基于资料瞎编”的情况确实少了,但出现了另一种更隐蔽的幻觉:模型会把检索到的片段重新组织时,把A文档的时间安到B文档的事件上,或者在转述时自己补充了一个原文没有的限定词。如果你没有要求模型严格引用原文,它还是会在上下文的基础上“自由发挥”。

这四个问题叠加起来,Naive RAG给人的感受就是“时灵时不灵”。但反过来想,这些问题也给了我们非常明确的优化方向:检索不准就升级检索,上下文太脏就清洗上下文,单轮信息不全就增加多轮检索能力。第二条路的起点,正是进阶RAG那套“模块化改造”。

2.3 不换架构,先让朴素版变靠谱的三招

在正式进入进阶方案之前,有三个成本极低的招数,能让Naive RAG先站稳。这些本身就是我踩坑后总结的止损动作。

第一招,混合检索。向量检索擅长语义相似,但对关键字和精确匹配非常弱。传统的关键字检索(比如BM25)则正好相反,它在“合同编号、人名、型号、专有名词”这类场景表现非常好。把两者结合起来,分别检索、再用一定规则合并排序,能同时兼顾“找得像”和“找得准”。我的经验是,很多你以为“向量检索不行”的case,加上BM25之后立刻就好了。代价是检索链路多了一步,但复杂度很低,收益很明显。

第二招,把top_k调大,然后做重排。单纯把top_k从小调大,噪声也会跟着变大,反而可能让效果更差。关键在于调大召回范围后,要在一百多个候选里面重新挑出最相关的5到8个。这个过程通常用重排模型来做:对每个候选,计算它和Query之间的细粒度相关性分数,按分数重新排序。实际上这才是更合理的两级流程:先用便宜的粗排保证召回率,再用稍贵一点的精排保证准确率。放在RAG里,就是向量检索负责“大海捞针”,重排负责“百里挑一”。

第三招,在Prompt里立规矩。Prompt对生成端的改善最直接也最容易被忽略。我在Naive阶段就把这句话写进了所有知识库问答的Prompt:“如果资料中没有明确答案,请直接回答‘资料中未找到相关信息’,不要自行推测。”同时要求模型在给出关键事实时标注来自哪一份资料的哪个标题。这一步不改变检索质量,但能显著减少“硬编答案”的情况,也给后面的排查留下了线索。

做完这三件事,你的朴素RAG会从“时灵时不灵”变成“大部分时候靠谱”。但它仍然是单轮、静态的检索机制,面对那些需要拆解、规划、多轮搜索的复杂任务,还是不够。

3. 进阶RAG:把链路拆开,每个环节都可以单独优化

3.1 查询端改造:路由、改写与假设性答案

进阶RAG和Naive RAG最大的区别,是把“查询-检索-生成”这条直线链路,拆解成多个可以独立调节的环节。这里面最容易出效果、也最好理解的,是查询端的改造。核心思路是:不要让用户原始的提问直接去碰撞向量库,而是先对问题做一次预处理,让检索目标更明确。

查询路由是最基本的手段。一个系统中往往不只是单一的知识库,可能有产品文档、技术支持库、销售话术库、内部制度库,它们的语料特征和检索需求各不相同。查询路由负责判断当前问题应该去哪个库、走哪种检索策略。实现上可以用一个轻量级分类器,也可以让模型直接决策。我用的方案是让模型从预设的几个检索策略里选一个,比如“产品文档精确查询”“技术库语义查询”“数据库直接匹配”。这个动作本身不产生答案,但能显著避免“跨库检索带回一堆不相关内容”的尴尬。

查询改写解决的是“问题本身表达不清”的问题。用户的真实提问往往带口语、指代、省略。比如多轮对话里问“那它的授权方式呢”,“它”指的是上一轮讨论的产品。如果直接把这句话拿去检索,向量库根本不知道“它”是谁。查询改写就是用模型把用户问题转成一个完整、独立、信息充分的检索表达式。我做成了一句话:先补全省略的主宾语,再拆掉口语化表达,必要时翻译成更适合检索的短语组合。实测下来,这在多轮对话场景里效果提升非常明显。

另一个有趣的改造叫“假设性答案”。它的思路是先让模型基于当前问题生成一个“假答案”,然后拿这个假答案去向量库检索,而不是用原始Query去检索。听起来有些绕,但背后的逻辑是:用户提问往往是简短的,而文档中的表述是完整的、上下文丰富的。直接拿简短的Query去做向量相似度计算,可能找不到语义上关联但并不字面相似的文档。模型生成的假答案带着完整的上下文链条,能“钓”出更准确的资料。我记得第一次试用这个方案时,一个检索不到答案的疑难case突然就通了。当然,代价是生成假答案多了一次LLM调用,延迟和成本都会增加。

3.2 检索端改造:多路召回与重排

查询端做完了预处理,下一步轮到检索端。Naive阶段我们只有一路向量检索,进阶的思路是把“一路”变成“多路”,再把结果汇总去重。多路召回的核心信念是:不同的检索策略各有所长,它们看到的“相关”是不同维度的相关,组合起来才能覆盖更多正确答案。

我常用的多路召回是三路并行。第一路是向量语义检索,负责捕获同义改写、概念相近的内容;第二路是关键字检索,负责精确匹配编号、术语、人名;第三路是根据元信息的过滤查询,比如限定时间范围、文档类型、作者。三路结果合并后,同一个文档可能从不同路都被召回,这时要做去重和分数融合。简单的融合可以直接加权求和,稍微讲究一点可以用倒数排名融合这类策略。我的经验是,融合规则不用太复杂,关键是要保留每路的“独门优势”。

多路召回得到的是候选集,接下来交给重排模块做精排。这一步和我在Naive阶段推荐的做法本质相同,但在进阶阶段它的作用更关键,因为多路召回的候选量更大、来源更杂,噪声更多。重排模型的任务是:逐对计算Query和每个候选片段的细粒度相关性,打一个精确分数,把最有用的一小段选出来。这也符合两级检索的原理,一级快而宽,二级精而准。

检索端改造的取舍,主要体现在资源和延迟上。多路召回意味着多几路索引的查询,重排意味着每次都要对几十上百个片段调用一遍模型。我实测下来,一次完整的多路召回加重排,比单纯的向量检索要多花几百毫秒甚至一两秒。所以不是所有流量都值得走完整链路,可以根据问题类型做分级处理:简单问题走快速通道,复杂问题走精排通道。这样既保住了体验,又押对了准确率。

3.3 生成端改造:压缩上下文与强制溯源

很多人优化RAG时把全部精力放在检索上,忽略了生成端同样是效果瓶颈。进阶阶段的第三个改造点,就是这“最后一公里”。

上下文压缩是第一个值得做的动作。多路召回和重排之后,你选出的top-k个片段仍然可能包含大量无关铺垫。比如一个文本块有两三百字,真正和问题相关的只有一句话。把整块塞进Prompt,不仅浪费token,更会稀释模型对关键信息的注意力。上下文压缩的思路,是用一个轻量模型对每个选中的片段做“提炼”,只保留和Query相关的句子或短语,再拼接给生成模型。实测下来,它对答案聚焦度的提升非常明显,同时还降低了成本。要注意的是压缩会损失一些上下文关联信息,所以压缩的粒度需要反复调。

强制溯源是另一个让我少踩很多坑的设计。我要求在生成阶段不仅输出答案,还要标注答案是基于哪些资料得到的。实现方式可以是在Prompt里要求“在每条关键结论后标注来源编号,编号对应参考资料的标题”。效果有两层:一层是模型因为知道要被溯源,会收敛到资料内容上,而不是自由发挥;另一层是后续如果有人质疑某个答案,你可以快速定位到它是从哪份原始资料里来的。这等于给系统装了一根审计线。

还有一个容易被忽视的生成端细节:Prompt的措辞方式。同一个上下文,你用“基于以下内容回答问题”和“请严格依据以下内容回答,不要添加资料之外的信息,如果资料无法回答请明说”,得到的结果差异可能很大。前一种描述给模型留了太多想象空间,后一种把边界画得很清楚。这个反差我做过很多次对比,每次前者的错误率和编造率都明显更高。

进阶RAG处理问题的能力,已经比Naive高出一个量级。但它依然是一个“先定流程、再执行”的架构:查询改写、多路召回、重排、压缩,这些动作的先后顺序和触发条件是开发者预先写死的。当问题变成“我需要先搞明白这个客户项目的背景,再去查他们用的框架,然后对比两版方案的差异”这种需要动态规划和跳转的复杂任务时,固定流程就开始显得僵化了。

4. Agentic RAG:让模型像分析师一样主动找资料

4.1 核心变化:控制权从“流程”交还给“模型”

到了Agentic RAG,做的就不再是“优化某个环节”,而是把整个链路视作一个可以由模型动态决策的智能体。它和进阶RAG的本质区别,不在于多用了某个高级算法,而在于控制权的转移。

在Naive和进阶阶段,流程是人定的:人规定先改写、再检索、再重排、最后生成。模型只是流程里被调用的一环,它没有权力决定“这一步我是不是该换个关键词”“刚才检索到的资料够不够我回答”。所有判断都由开发者在代码里写死。Agentic RAG则相反,它让模型始终处于决策位置:模型自己决定下一步该做什么动作,是做一次检索、改写一次查询、还是直接给出最终答案。

这种设计顺应了一个直觉:复杂问题本来就没有统一的解决路径。有些问题检索一次就够,有些问题需要先查A再查B,有些问题得把两次检索结果结合才能得出结论。与其为所有可能性写一套臃肿的流程控制代码,不如把“遇到什么情况走哪条路”的决策交给模型。模型就像一个分析师:先看一眼任务,判断需要哪些信息,查资料,如果发现信息不够,再换一个角度接着查,直到有把握才写结论。

但我得提醒一句,Agentic RAG绝不是Magic。它把原来由开发者承担的“流程设计”责任,部分转移给了模型的推理能力。模型本身的判断力、你的Prompt设计、工具定义的清晰度、安全的约束,都会直接影响最终效果。这不是一个“从Naive换到Agentic就自动变好”的升级,而是一次架构思路的切换。

4.2 一个可以落地的Agentic流程长什么样

我用一个自己在实际项目中落地过的流程来说明。整套系统包含四个核心工具:向量库检索、关键字检索、文档元数据查询、搜索引擎式的网页检索。模型在一个循环里运行,每个回合做三个动作:判断、执行、评估。

伪代码大致是这样的:

def agentic_rag(question, max_rounds=5): state = { "question": question, "context": [], # 已收集的资料 "missing": [], # 缺失的信息 "answer": None } for _ in range(max_rounds): action = llm.decide_next_action(state) if action.type == "search": new_docs = run_search(action.query, action.tool) state["context"] += new_docs state["last_action"] = action elif action.type == "ask_clarify": return "还需要您明确:" + action.question elif action.type == "answer": state["answer"] = llm.generate_answer(state["context"]) return state["answer"] else: # 判断资料是否足以回答 verdict = llm.evaluate_sufficiency(state["context"]) if verdict.is_sufficient: state["answer"] = llm.generate_answer(state["context"]) return state["answer"] else: state["missing"] = verdict.missing_info state["answer"] = llm.generate_answer(state["context"]) return state["answer"]

第一次接触这个循环可能会觉得复杂,我拆开讲每一步实际在做什么。

第一步是规划。模型拿到用户问题后,先拆解任务:这个问题有没有子问题?需要哪些信息?从哪里查最合适?比如“对比A方案和B方案在跨平台开发中的适用性”,模型会把它拆成三个信息需求:A方案的特点、B方案的特点、跨平台开发场景的关键指标。这一步是否做好,直接决定后面的检索是否有方向感。

第二步是执行。模型为自己的每个信息需求选定工具并生成检索式。这里和Naive版本的一个明显差别是:模型会检索多次,每次针对一个子问题。比如先查A方案,再查B方案,两次检索用的Query是完全不同的,而不是拿同一个Query重复搜索。

第三步是反思。检索完一批资料后,模型要评估:现在手里的信息够不够回答原始问题?如果我缺一部分信息,缺的是什么、应该再去哪里找?这个自我评估是Agentic RAG的灵魂。它让系统具备了进阶RAG没有的“闭环”:检索结果不理想时,不再是“就这样得了”,而是产生新的检索意图、新的查询词、新一轮检索。

第四步是生成。当模型判断资料足够时,它会综合多轮检索到的信息,组织成最终答案,并在关键处引用资料来源。这比Naive版本单轮拼接top-k的效果要扎实得多,因为上下文是经过多轮筛选和补全的,模型面对的“拼图”比之前完整。

我在实际项目中跑通这个流程后,最大的感受是:它解决的是Naive和进阶版本里“信息不够却硬要回答”的结构性缺陷。多轮、可反思、可规划的机制,让系统在面对需要多方信息整合的复杂问题时,终于有了合理的应对方式。

4.3 设计Agentic RAG的三个关键权衡

Agentic RAG的灵活性不是免费的。我把落地过程中最重要的三个权衡放在这里,这些都是文档里很少写的经验。

第一个权衡是推理成本。每一次“决定下一步做什么”都是一次LLM调用。一个复杂问题从规划、多轮检索到最终回答,可能消耗5到10次甚至更多的LLM请求。token费用、响应延迟都会成倍增长。所以在设计时一定要给循环设硬边界,比如最大迭代次数、单轮检索返回条数、上下文总量上限。同时可以按问题复杂度分流:简单FAQ根本不走Agentic,直接快速通道回答;只有检测到问题可能需要多步推理时,才进Agentic模式。

第二个权衡是工具权限。模型拥有了自主调用检索工具的权力,随之而来的风险是“乱调用”或者“被恶意Prompt引导调用不该用的内容”。我建议给每个工具设置清晰的权限边界和使用条件。比如在Agent初始化提示词里写明“只有在需要内部数据时才允许调用文档检索工具”“不得连续重复检索同一关键词”。这些限制可能会让Agent显得“笨”一些,但能守住底线。我见过不做限制的Agent,在几轮对话后越查越偏,最后甚至检索出大量无关内容,把后面的生成彻底带崩。

第三个权衡是评估复杂度。Agentic RAG是动态路径,同一道问题每次运行走的可能不是同一条检索路线。这让效果评估变得棘手:你很难用固定的“命中哪篇文档”这种标准衡量检索好坏,需要更多地看最终答案的正确性、完整性、引用质量。这要求我把评测集设计成“答案导向”的而不是“检索路径导向”的,也意味着bad case的定位要花更多工夫。后面我会专门讲评估方法。

走到这里,三代RAG的技术脉络基本清晰了。但我知道很多人的困惑是“那我到底该用哪一代”。这个问题的答案,不能只看技术优劣,要回到业务需求。

5. 三代同框:选型判断、评估方法与避坑清单

5.1 选型不是越高级越好

我见过不少团队,一听说Agentic RAG是趋势,就急着把整个系统重写成多智能体架构,结果效果没提升多少,成本和复杂度却翻了几倍。选型正确的做法是用评测数据说话,而不是追逐概念。我先把三代方案放在一起对比,你对照着看会更清楚。

维度Naive RAG进阶RAGAgentic RAG
核心机制单轮向量检索+生成查询改写/多路召回/重排等模块化优化模型自主规划、检索、反思、再检索
检索主动权完全由代码固定部分由配置控制由模型动态决策
适用场景简单FAQ、单文档问答多库检索、长文档精读、对话式问答多跳推理、跨文档综合分析、动态调研
准确率上限较低中高高,但依赖模型推理能力
延迟与成本低中等明显偏高
系统复杂度低中高,需要Prompt、工具、安全等配套
维护难度简单中等较高,需要持续调优和监控

我的建议非常明确:从Naive起步,先跑通一个端到端可用的基线版本。然后把最痛的那个问题找出来——是召回不准、上下文太乱、还是多轮信息不够?根据痛点去加对应的进阶模块。绝大多数业务,做到“进阶RAG”已经足够扎实。只有当你明确遇到“需要跨多个来源汇总信息、需要根据中间结果调整检索方向”这类任务时,才值得付出额外成本上Agentic。盲从新概念,只会让你花更多钱修一个本不存在的需求。

有了选型方向后,还缺少一个判断依据——拿什么标准来衡量效果。这就要靠系统性的评测。

5.2 评测分开做:检索端和生成端各看各的

RAG系统评测中最常见的错误,是只看最终答案的“感觉对不对”。这种模糊的主观评价既无法定位问题,也无法驱动迭代。我采用的是“检索端和生成端分开评测”的框架,这是我持续调试RAG最依赖的方法论。

检索端回答的问题是:该找到的资料,我们找到了吗?我常用的指标包括召回率和命中率。召回率衡量的是“正确答案对应的资料片段,是否出现在我们检索出来的候选集里”;命中率稍微简化,看的是整个对话中有多少比例的问题,检索到了包含答案的那篇文档。这块能帮你判断问题出在“召回不够”还是“排序不对”。如果召回到位但排名靠后,可能是重排没调好;如果干脆没召回到,要回头检查分块、嵌入模型和检索策略。

生成端回答的问题是:给定检索到的资料,模型生成的回答对不对?我看三个维度:答案正确性,即最终结论是否是事实正确的;忠实度,即答案是否严格基于提供的资料,有没有擅自外推或编造;完整性,即该覆盖的要点有没有漏掉。忠实度是我特别看重的,因为它是“幻觉是否被压住”的直接体现。

评测集怎么建,是另一个关键。很多人拿模型生成一批问答对就开测,这样的评测集会自带偏差。我更推荐让业务方根据真实的用户问题梳理出50到200条有代表性的评测样本,同时标注清楚答案在原始资料中的出处。这样每一轮改动后,都能快速回归一遍评测集,看到改动带来的变化是正向还是负向。这就像给RAG装了仪表盘,没有仪表盘的车,你不敢踩油门。

5.3 避坑清单:那些资料里不会写的细节

做了这么久的RAG,我积攒了一批“资料里不会写”的经验。我把它们整理成避坑清单,这些都是真金白银换来的教训。

语料质量第一。RAG的检索上限由语料决定,生成效果由检索决定。语料里有大量重复、矛盾、过期或格式混乱的内容,后面的所有优化都会在同一个天花板上撞头。先花时间做文档清洗、去重、版本梳理、结构标注,收益率远高于调任何检索参数。

嵌入模型不能随便选。通用榜单上的第一名,拿到你的业务领域里不一定好用。我选嵌入模型的流程是先准备一小组真实业务问答样本,测它的召回命中率,再对比两三个候选模型。这个过程很轻量,但能帮你避开“接到手才发现模型完全无法理解业务黑话”的尴尬。

不要迷信“更大top_k”。top_k从5调到20,召回的准确率不见得更高,但token消耗和模型注意力分散的问题会立刻出现。把top_k当成“候选池的大小”看待,同时搭配重排来决定最终进入Prompt的内容,才是正确用法。

权限和合规要提前设计。RAG系统接入了公司内部文档后,就天然面临“谁能问什么”的问题。如果不在检索或生成层做权限过滤,用户完全可以通过巧妙的提问拿到他不该看到的内容。我处理这个问题的做法是在元数据层面打权限标签,检索结果再按用户身份过滤一遍,确保上下文里不会出现越权内容。

最后一条也是最重要的:RAG是系统,不是脚本。它涉及数据、检索、推理、评估、监控多个环节,任何一个环节失衡,整体都会出问题。不要指望一次部署就万事大吉,持续用bad case驱动迭代,才是让系统真正变稳的路径。

我在开始做RAG时,也走过一段“从Naive直接跳Agentic”的弯路,最后发现当时的瓶颈根本不在检索主动权,而在数据清洗和召回准确率。后来老老实实把基础打好,再逐步加入查询改写、多路召回、重排这些模块,效果稳步提升。到现在我反而形成了一个习惯:每接手一个RAG项目,先不急着定架构,花时间把业务场景的数据特征和真实问题样本摸清。因为越是在技术的快速迭代期,“解决问题”和“堆新技术”之间的距离就越容易被拉远。RAG的进化路径并不神秘,它就是一套增强组合拳的成长史。祝你把这套组合拳打顺。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询