RAG和传统检索方法的区别

接入与开发

从工程落地角度讲清 RAG 与传统关键词检索在召回、排序、超时降级和日志评测上的差别,帮你判断什么场景该用哪套。

很多人接完模型才发现,用户问的是自己内部资料,光靠关键词搜出来的东西答不上来;换成向量召回,又出现答非所问、引用错段落的毛病。这篇不重复原理课,只给一套对照和排查顺序:先看数据长什么样,再决定用关键词、向量还是两者混着来,以及接进生产后超时、并发、降级、日志、评测这几件事分别该怎么留口子。

两者到底差在哪:匹配的是字面还是语义

先把两种做法拆开看。关键词检索(BM25、倒排索引那一套)做的是:把查询切词、把文档切词,看哪些词撞上了,再按命中词的重要程度和出现次数打分。它看见的是「字一样不一样」。向量检索做的是:把整段话压成一串数字,再算两串数字离得近不近。它看见的是「意思近不近」。这个底层差异,决定了它们各自的强项和翻车点。

对比项关键词检索向量检索
看什么词有没有原样撞上两段意思离得近不近
算分依据命中词权重 + 词频 + 文档长度向量之间的距离/相似度
专有名词、错误码、型号命中准,几乎不会漏容易被语义稀释,反而召错
同义改写、口语长问句换个说法就搜不到通常能兜住
典型翻车用户没写文档里的词召回话题相近但答案不对的段落

结论不是谁更先进,而是看你的资料里「用户提问用词」和「文档用词」重合度高不高。重合高,比如客服查错误码、运维查日志编号、开发查函数名,关键词就够用,还更稳更省。用户习惯换说法、跨语言提问、一上来就是一大段口语长问句,才需要向量来补位。

  • 用户提问常带编号、型号、错误码、专有名词 → 优先关键词
  • 用户提问多是完整句子、带口语、爱换同义词 → 向量能明显补位
  • 资料以表格数字、代码片段、短编号为主 → 谨慎上向量,切块容易把语义打散
  • 资料是大段说明文、教程、政策条款 → 向量更适合,关键词容易因用词不同而漏
  • 两种用户都有 → 混合检索,先关键词保底再向量补召回

想验证重合度,不用猜,拿你真实的历史提问去跑一遍就行:把用户原话丢进关键词检索,看命中率;再看漏掉的那些,是不是都因为换了说法。这个漏检比例,基本就决定了你要不要加向量。

先看手里这批资料长什么样,再定方案

选 RAG 还是传统检索,先别急着比技术高低,把手里的资料摊开看一眼更快。同一批资料里往往混着好几种东西:订单号、日志 ID、指标名这种结构化字段,长文档说明类,还有合同、手册这类既有术语又有长句的。把它们分开放,方案基本就自己浮出来了。

资料长什么样典型例子优先走哪条路
结构化字段订单号、日志 ID、指标名、枚举状态关键词或数据库精确查
长文档说明产品说明、制度解读、FAQ 正文向量召回
术语加长句合同条款、设备手册、规范文件混合检索

提问方式也要一起看。用户在搜索框里敲的是几个关键词、或者从下拉里选一个条件,传统检索更省,快且结果可解释;用户直接甩一整句自然语言问「这个流程卡在哪一步」,向量或混合更稳,因为它能接住同义改写和口语说法。两种需求都存在时,别硬用一个方案通吃,按入口分流更实际。

  1. 抽一批真实查询从日志、客服记录、搜索框历史里捞几十条,覆盖上面几种资料类型和两种提问方式,不要自己编理想问题。
  2. 人工标答案位置逐条标出「正确答案在哪一段」,标到段落或字段级别,这是后面判断的唯一依据。
  3. 两种方式各跑一遍同一批查询分别用关键词检索和向量召回跑,看目标段落有没有排进前几条。
  4. 按类型下结论哪类资料、哪种提问下谁更稳,就分别记下来,不要合并成一个总分。

这套小规模对照不适用两种情况:一是查询量极小、几天才来一条,标注成本不划算;二是资料本身还在频繁改结构,跑出来的结论过两周就失效。遇到这两种,先把清洗和数据结构稳住,再回头做对照。真要查各家 API 的具体能力边界和当时的数字,到站内模型资料库和价格页核对。

下一步把标注表格建起来,几十条就够,跑完再决定用哪套,比拍脑袋选靠谱得多;需要对照各家方案时可去看站内评测与工具目录。

混合检索与重排:把两套结果并成一条路

单靠一路召回,总有一头漏。关键词那路擅长精确命中:专有名词、编号、代码片段、人名地名,只要字面对上就捞得回来;向量那路擅长语义补漏:用户换个说法、用同义词、描述一个概念,它也能找到意思相近的段落。工程上的常见做法是两路并行召回再合并,让两种能力互相兜底,而不是纠结选哪一路。

召回路径擅长容易翻车的地方
关键词(倒排 / BM25 类)精确字面命中、术语和编号换个说法就找不到,只认字面
向量(语义相似)同义替换、模糊描述、跨表述字面命中但语义偏的项也会被拉进来
合并后统一排序两路候选放同一把尺子上比两路分数尺度不同,直接相加会偏袒某一路
加一层重排对候选做二次精细打分慢且贵,候选太少时纯属浪费
  1. 第一步:两路并行召回,各取一批候选关键词和向量各跑一次,各自保留一批候选,先别急着截断成最终条数。目的是把两边的「可能有用」都留住。
  2. 第二步:合并去重,统一排序同一段被两路都召回的,去重后只留一份,并给它一点加权(两路都认可通常更靠谱)。两路分数尺度不一样,别直接相加,用排名融合这类只看位次的方式更稳。
  3. 第三步:对合并后的候选做重排用一个更慢但更准的模型,对「问题 + 候选段落」成对打分。这一步专门压掉「字面命中但答非所问」的项——它在关键词那路分数很高,但只要读完发现没回答问题上,重排就会把它往下压。
  4. 第四步:控制进上下文的条数排序完之后只取靠前的几条喂给模型。先从小批量试起,看回答质量有没有掉;塞太多段落会稀释重点、推高成本。具体几条得按你的文档颗粒度(一段是一句话还是一整节)和模型上下文预算来定。
  • 候选取多少:先小批量验证再加,别一上来就放大,观测指标再决定
  • 重排用不用:召回候选本来就只有个位数、且人工已确认准确,再加一层重排属于白花钱
  • 进上下文几条:按文档颗粒度和模型上下文预算定,可以先到 AI 模型库(/models) 核对候选模型的上下文规格
  • 验证方式:固定一批问题,对比「加重排」和「不加重排」的回答质量,收益看指标说话
  • 什么情况下不适用:候选量很小、延迟敏感、文档颗粒度极粗(一条就是整篇)时,重排和精细排序的收益都会明显下降

接进生产前,超时、并发、降级、日志、评测各留什么口子

把 RAG 接进生产,最怕的不是效果差一点,而是整条链路一慢全慢、一挂全挂。这一节不讲原理,只讲你在上线前应该在代码里留出的几个口子:超时、并发、降级、日志、评测。每一个口子都对应一个具体的排查动作,别等出事才补。

超时:检索和生成分开设,别用一个总超时包住

一个常见错误是给整个请求设一个总超时,结果检索卡住时你既拿不到关键词结果,也拿不到模型回答,用户就是干等。正确做法是两段各设各的超时:检索段一个上限,生成段一个上限。检索超时后先返回关键词结果或明确提示「没找到相关资料」,比整体超时体验好得多。基线延迟别凭感觉,先去 接口测速(/tools/speed-test) 把向量库和模型接口各自量一遍,再定阈值。

  • 检索段超时:超时后走关键词兜底,或返回「未找到」并让模型裸答,不要静默卡住
  • 生成段超时:超时后返回已检索到的片段摘要,至少让用户看到有资料
  • 两段超时不要共用同一个计时器,检索超时不应该连带砍掉生成预算
  • 超时阈值按 接口测速(/tools/speed-test) 的实测分位数来定,不要抄别人的数字

并发与降级:设上限、排顺序,别让链路一起挂

向量库和模型接口都要设并发上限,超了就让请求排队或做退避重试,避免把下游打爆。降级要有明确顺序,不能是「全挂」。建议的顺序是:混合检索 → 纯关键词 → 直接让模型裸答并标注「未引用资料」。每一步都要能单独触发,而不是等上一层完全失败才走下一层。

层级触发条件用户看到什么
混合检索正常状态带引用的答案
纯关键词向量召回超时或失败关键词命中的片段,可能没有重排
模型裸答检索整体不可用答案 + 明确标注「未引用站内资料」

这个表的价值在于:出问题时你能一眼看出用户现在处于哪一层,而不是只看到「接口报错」。注意,如果业务本身对引用准确性要求极高,裸答这一层可能不适用,宁可返回「暂时查不到」也别给无依据的答案。

日志:每次请求至少记这几项,不然没法复盘

很多团队上线后只记一个耗时和状态码,出了问题根本不知道是哪一段拉胯。每次请求至少记:查询原文、走了哪条召回路径、命中了几段、用的哪个索引版本、重排后的排序。有了这几项,你才能回答「是检索没召回,还是召回后排序排坏了,还是模型没用好资料」。

查询原文
用户到底问了什么,别只存 hash 或 id
召回路径
这次走的是混合、纯关键词还是兜底,决定后面怎么看
命中段数
召回了几段、进重排的有几段,判断是召回不足还是排序问题
索引版本
切块或嵌入模型换过之后,对不上版本就没法归因
重排后排序
前几段是什么,直接决定模型看到什么

评测:攒小样本,每次改动都跑一遍

只靠一两次人工体感调 RAG,非常容易改好一类问题、改坏另一类问题。做法是攒一批带标准答案的小样本,覆盖你真正关心的几类问题。之后每次改切块、换嵌入模型、调排序,都跑一遍同一批样本,对比命中率和答案正确率。

  1. 攒样本挑 20~50 条真实问题,人工写好标准答案和应该命中的资料片段,不用多,但要覆盖各类问法
  2. 定指标至少看两个:召回命中率(该出现的片段有没有出现)和答案正确率(生成有没有用对资料)
  3. 固定跑法每次只改一个变量,跑同一批样本,把两次结果并排看,别凭印象说「感觉变好了」
  4. 看回归重点盯那些上次对、这次错的样本,它们才是改坏的地方

这套口子不能保证效果一定好,它保证的是:出问题时你知道去哪看、改完之后你知道有没有改坏。如果团队只有一两个人维护,可以先从日志和一份小评测集做起,超时和降级可以后补,但别一直不补。

什么情况下你其实不需要上 RAG

判断要不要上 RAG,第一刀不是砍在模型上,而是砍在「资料有多少」。如果你手上的知识总量就是几十页说明文档、几百个字段的配置表,那它压根撑不起一套检索系统。先把这批资料整个塞进上下文,让模型直接读,比搭一套切分、向量化、召回的链路快得多,也省掉一堆调参的麻烦。

  • 统计一下原始资料的总字数和字段数,别估,实际数一遍
  • 拿这个总量去对比你打算用的模型上下文窗口,看是全塞得下还是塞不下
  • 塞得下就先做单轮直读的版本,跑一批真实问题看答案质量
  • 只有发现明显塞不下、或者每次请求都逼近上限时,才回头考虑检索

这里有个常见误区:很多人对「上下文」到底指什么、怎么算、超了会怎样,其实没算清账就开始选型。建议先去 基础概念词典:Token、上下文、温度 把上下文和 Token 的关系搞明白,能算出你这批资料大概占多少空间,再谈要不要检索。算完账往往会发现,小体量资料上 RAG 纯属多余的一层。

这几种需求,检索本身就不是正解

除了资料量小,还有一类场景是「问题形态」决定了不该用检索。如果你要的是固定格式的字段提取,或者需要精确的数值计算,结构化查询和工具调用比向量召回直接得多。检索擅长的是找相关段落,不擅长保证某个字段一定被准确取出。

需求类型更合适的做法为什么不首选检索
字段提取(如从表单抽固定几项)结构化解析或工具调用检索只保证找到段落,不保证字段精确
数值计算(求和、比对、换算)代码或计算工具模型做算术容易出错,检索不解决算准问题
精确 ID / 编号直达数据库索引或关键词精确匹配向量是近似的,精确命中反而更快更省
开放问答、资料分散检索再交给模型组织语言这时候检索才有存在价值

判断标准可以简化成一句:如果查询本身就是一串明确 ID 或编号,你要的是「精确等于」,那就别硬套向量。传统全文检索甚至数据库索引,在这种场景下响应更快、成本更低、结果更确定。硬上向量,等于给自己多加一层不确定性:明明该命中,可能因为相似度排序没排第一而漏掉。

定位不了答案在哪,先别急着选方法

  1. 问自己:答案大概在哪份资料里如果连大致范围都说不出,说明资料没被整理过,不是检索方法的问题
  2. 先把资料做基本归类按主题、部门或用途分文件夹,标注每份大概讲什么,这一步不需要任何技术
  3. 再判断资料量是否适合直读整理后往往总量变小,可能直读就够了,检索自然不必上
  4. 最后才决定要不要检索顺序反了,资料没治理好,上 RAG 还是传统检索,两种方法都救不了
先搞清楚答案在哪,再谈用什么去把它找出来;跳过第一步,后面选什么方法都是碰运气。

所以「不需要 RAG」不是偷懒,而是一种正确的取舍。资料小、需求结构化、查询精确、数据没治理,这四种情况下,先别上检索,把上下文算清、把资料理清、把工具用对,往往更省事也更准。真正该上检索的时候,是因为问题模糊、答案分散,而不是因为「大家都这么做」。

常见问题

是不是有了向量检索就可以完全不要关键词检索了?

不行。专有名词、错误码、型号、编号这类字面匹配是向量最容易翻车的地方,用户问某个具体编号时,关键词几乎是必留的一路。稳妥做法是两路都留着做混合召回,谁擅长谁上,而不是二选一。

我改了切块大小或换了嵌入模型,怎么知道是变好还是变坏?

别靠单次观感。先固定一批真实查询并标好正确答案位置,改动前后各跑一遍,比命中位置和答案正确率,同时观察延迟和成本有没有明显变差。没有这组样本,任何改动都只是赌。

检索没召回到正确段落,一般先查哪一环?

按顺序查:原始文档清洗有没有把关键内容切掉,切块有没有把一段完整意思劈开,查询有没有被改写跑偏,召回路数够不够(是否只走了单路),最后才怀疑重排排序。多数问题出在前两步。

本文依据各平台公开文档与官方公告整理,只做中文归纳;具体做法、参数与限制以官方文档为准。