先打个比方,你自己写一篇文章,是不是先拉个提纲、打个草稿,再让主编看一眼定稿?Speculative RAG干的就是这件事。它在RAG流水线里加了一个“草稿-验证”环节:用小而快的模型基于检索到的文档快速产出多条候选推理路径,再由大模型只做“打分、择优、必要时补改”的轻量验证。这篇文章会把这套机制的原理、核心参数、落地选型和适合的业务场景一次讲透。做知识问答、客服机器人、企业知识库,对延迟和答案质量同时有要求的朋友,这篇文章值得看完。
1. 从传统RAG到Speculative RAG:瓶颈在哪,思路怎么变
1.1 传统RAG为什么又慢又容易跑偏
传统RAG的套路很简单:用户丢一个问题进来,检索器从知识库里召回十来个文档片段,全部拼接成一个超长Prompt,塞给大模型,让它“根据以上内容回答”。这个流程有三个非常要命的毛病。
第一个是上下文越长,注意力越容易“迷路”。大模型并不是真的在“读”每一个文档,它是在海量的注意力计算里寻找跟问题相关的信号。文档一多,尤其是中间位置的文档,经常被忽略,这在业界已经是共识了。你的检索结果明明有正确答案,大模型却偏偏引用了一段不痛不痒的背景介绍,答得模棱两可。
第二个是自回归生成只能一条路走到黑。大模型生成答案是一个token一个token往出吐的,一旦前几句话把方向带偏了,后面的输出要么将错就错,要么弯弯绕绕半天想兜回来,结果越绕越远。你不可能像人写文章那样划掉重来。
第三个问题大家都懂——慢。大模型每吐一个token都要做一次完整的正向计算,Prompt里塞的文档越多,首token延迟越高,生成越长,总延迟越不可控。很多RAG上线后跑不出“对话感”,就是因为用户问题已经发出去三四秒了,界面还在转圈。
这三个问题本质上指向同一个矛盾:让最强的模型去干所有的事。检索的质量它要兜底,推理的过程它要保证,最后的输出表达它还要负责。大模型再聪明,被铺天盖地的上下文一淹,照样翻车。
1.2 Speculative RAG的灵感来源:从Token级的“草稿-验证”到答案级
Speculative RAG的思路并不是凭空冒出来的。它借鉴了LLM推理加速里一个非常成熟的方法——推测解码(Speculative Decoding)。
推测解码是这样运作的:先用一个很小的草稿模型按正常自回归方式快速生成一串候选token,然后让大模型去验证这串token。如果大模型认可,就直接接受这段输出,相当于一次跳过了很多步;如果不认可,就在出错的token位置停下来,从那里重新生成。本质上是把“生成”和“验证”拆给两个模型分工完成。毕竟小模型算得快,大模型判断得准。
Speculative RAG把这个思想从“token层面”提升到了“推理路径层面”。注意,它猜的不是下一个词,而是一整条回答的思考路径。
具体来说,面对一个query,我们不要求大模型直接回答,而是先让草稿模型基于不同的文档子集,并行生成多条完整的候选答案——每条候选答案对应一个“如果从这批资料出发,这个问题该怎么答”的推理草稿。然后再把这一批草稿交给大模型,大模型不需要从头生成,只需要看看每条草稿跟对应的文档是否吻合、跟问题是否对得上,打个分,挑出最合理的那个,必要时再动手补几笔。
用个生活化类比会非常好懂。你要写一份市场调研报告,传统的做法是让一位资深专家独自把所有资料从头翻到尾,然后一口气写完。专家的能力确实强,但资料一多,看漏关键数据、中间思路跑偏、反复返工都是常事。Speculative RAG的做法是:让几个实习生每人拿一部分资料分头写初稿,各自从不同角度切入;然后专家不重新写,只看这几份初稿,对比哪份角度更好、哪份证据更扎实,选一份最靠谱的,再让它改两笔就交付。行家出手的时间被压到了最低,但质量反而因为“多条路线备选”变得更有保障。
1.3 多了一层生成,凭什么反而更快
很多人的第一反应是:多让一个小模型生成好几条候选答案,工序明明变多了,怎么会更快?
关键在于开销分布。大模型和小模型的速度差距通常是几倍到十几倍,而多条候选答案在小模型那里是可以通过批处理并行生成的——你把五条草稿的任务塞进同一个batch,在显存允许的范围内,解码时间并不会线性增长。真正贵的是验证模型的输出token,而Speculative RAG恰恰把大模型的输出从“几百个token的完整回答”压缩到了“每个候选打个分”的量级。你算一笔账就清楚了:大模型直接写200个token,和让它读5条候选答案后输出30个评价token,哪个贵?
另外,验证阶段因为看到了候选答案,就不需要再“重新发明轮子”。它做的事情是检查、判断、微调,比凭空生成要容易得多,质量自然也更稳。这才是Speculative RAG能同时优化延迟、成本和准确率的底层逻辑。
2. Speculative RAG的运行机制拆解:三层各司其职
2.1 第一层:检索与文档分组,先解决“材料”问题
Speculative RAG并没有改变检索这个地基,但它在检索结果的使用方式上做了关键调整:不把全部文档塞进同一个上下文,而是先对文档做分组。
为什么必须分组?检索器召回的一二十个文档片段,往往来自不同的章节、不同的页面,甚至不同来源。它们有的讲原理,有的讲案例,有的只是一笔带过。全部塞进同一个Prompt,草稿模型很容易被互相矛盾的表述搞糊涂,生成出来的候选答案也会显得“精神分裂”——前面在说A,后面又跳到B。
分组操作不需要搞得很复杂,我用过的方案基本是两类。一类是用embedding对检索到的文档做简单聚类,比如KMeans聚成3~6簇,每一簇代表一个主题方向;另一类是更粗放的做法,直接按检索得分排序后切块,比如top_k=24份文档,每6份一组,切4组。这两种做法我都试过,效果差异不大,真正关键的是让每个组内的文档有一定一致性。分组数量一般落在3~6之间,组数太少,候选之间没什么区分度;组数太多,每组材料不够,候选答案可能连证据都引不全。
文档分组直接决定了候选答案的多样性天花板。如果五个组都是从同一个话题切出去的,那后面生成多少条候选路径都没用,本质上还是一种答案。所以分组这一步看着不起眼,却是整个Speculative RAG里最容易被低估的环节。
2.2 第二层:草稿模型采样,生成多条推理路径
分组完成之后,轮到草稿模型上场了。草稿模型是哪个?它通常是一个规模明显小于验证模型的生成模型,7B到13B这个区间的开源模型很常见。它不需要是“最强”的,但最好是指令遵循能力强、还不会胡说八道到离谱的那种。
使用方式是对每一组文档子集,各生成至少一条候选推理路径。这里有一个多数人第一次容易犯的错:把temperature调得太低。在传统单路生成里,我们为了稳定总是把temperature压到0.1、0.2左右;但Speculative RAG要的是“多样性”,如果所有路径都是从同一个概率分布里挑出最稳的那个序列,那五条候选答案会高度相似,验证阶段相当于没得选。实操里我一般把temperature放在0.8到1.0之间,个别场景甚至放到1.1,让草稿模型敢于走不同的推理方向。
除了采样参数,草稿模型做多轮生成时最好先把query相关的公共知识压缩出来,再结合文档写答案。还有一个细化技巧:让草稿模型先输出推理链,再输出结论。这个推理链在验证阶段非常有用——大模型看到“这个答案是怎么推出来的”,远比只看一个孤零零的结论更容易判断它靠不靠谱。
候选路径的总数N一般取3到5的倍数关系。注意,N并不是越大越好。候选多了,选择空间大了,但验证模型的判断负担也大了,而且草稿模型的能力上限就摆在那里,再多个数也只是在同一个水平线上反复横跳。
2.3 第三层:验证模型打分与择优,把“写”变成“选”
验证模型就是那棵“终审专家大树”,通常是一个能力强一截的大模型。它在这个阶段拿到的输入是(query, 文档子集, 候选答案),要输出的是“这条候选答案的可信度分数”。
分数打分的方式,我实际用过的有三类,各有优缺点。最常见的是概率打分:把候选答案按特定模板拼到Prompt里,计算验证模型生成答案时的对数概率,再除以答案长度做归一化。这个分数衡量的是“在模型眼中,这个答案在给定证据下是否顺理成章”。
第二种是把多个候选放在一起两两PK,让验证模型直接输出“哪条更合理、为什么”。这种方式比较吃Prompt的写法,但效果往往更直观,尤其适合候选答案风格差异特别大的时候。
第三种是绝对阈值判断:当最佳候选的分数低于某个预设阈值时,验证模型进入精修模式;如果高于阈值,直接输出候选答案。这个方法最实用,因为不是每次都要走到精修那一步,大部分时候验证模型完成打分后就能拍板。
这里有一条红线要提醒:验证模型打分的时候,Prompt里只应该放这条候选答案对应的那份文档子集,绝不能把所有文档都丢进去。你一旦把所有文档都塞进验证Prompt,就让大模型重新回到了“被无关信息干扰”的老路上,Speculative RAG辛辛苦苦建立的“隔离带”就失效了。
2.4 精修兜底:分数不够时,验证模型怎么改
尽管我们做了分组、给了多条候选,还是可能出现所有候选答案质量都不高的情况。这时候就需要精修机制兜底。
精修不等于重写。如果验证模型每次都从头写一遍答案,那Speculative RAG省下的成本又全吐回去了。我的做法是给精修设置明确的token预算。比如最多生成200个token,只允许在候选答案的基础上做局部改动,禁止推翻重来。还有一种精修策略是让验证模型融合多个候选的优点,这在多跳推理里特别有用:A候选讲了某公司的财务数据,B候选分析了行业背景,验证模型可以把两者合并成一份更全面的回答。
需要盯住精修率这个指标。所谓精修率,就是所有请求里有百分之多少触发了精修流程。正常情况下这个比例应该在20%到30%以下。如果精修率长期超过50%,说明草稿模型的能力已经配不上验证模型了,这时候该升级的不是验证模型,而是草稿模型或者文档分组策略。这个观点很多人一开始不理解,总想着把钱花在最大的模型上,实际上瓶颈经常出在草稿那端。
3. 动手落地:技术栈选型、核心参数与效果估算
3.1 技术栈怎么选,草稿模型和验证模型怎么配
先明确一个事实:Speculative RAG不是一个开箱即用的现成组件,而是一套需要你手动编排的架构。好在每个环节都有相当成熟的开源组件可以拼装。
检索层选型我不过多展开,常用的向量检索方案配合重排器是最稳的搭配。重排器非常推荐加上,因为它能明显提升进入分组的文档质量,草稿模型生成候选答案时的“原材料”更干净,后面所有环节都会受益。
草稿模型这边,我建议从13B级别的开源模型起步,量化到4bit之后跑在消费级显卡上压力也不大。如果业务场景特别垂直,花几天时间对草稿模型做一次轻量的领域微调是非常划算的投资——这个模型承担了绝大部分生成量,它的质量每提升一点,大模型的精修压力就下降一大块。另外,草稿模型不一定要和验证模型来自同一家族。我搭过的系统里,草稿模型和验证模型来自不同厂商,也完全跑得通,因为验证阶段本质是打分判断,并不要求模型能力同一源。不过Model Family一致时,概率打分的分布会更稳定,这一点在调阈值的时候会省心很多。
验证模型的选型取决于你的预算和延迟目标。如果走商用API,建议把验证Prompt写得尽量结构化,让输出固定在“分数+意见+是否精修”的格式上,方便程序解析。如果是自部署的大模型,建议开足批处理,验证阶段天然适合batch推理。
3.2 核心流程伪代码:把思路落成可复用的骨架
整个系统最核心的控制逻辑可以用几段伪代码说清楚。以下是我用过的一个简化版本,不含具体依赖库,只演示流程骨架:
def speculative_rag(query, retriever, draft_model, verify_model, n_groups=4, candidates_per_group=2, verify_threshold=0.6): # step 1: 检索并分组 docs = retriever.retrieve(query, top_k=24) doc_groups = cluster_into_groups(docs, n_groups=n_groups) # 每组约6篇 # step 2: 草稿模型为每组生成候选推理路径 candidates = [] for group in doc_groups: prompt = build_draft_prompt(query, group) paths = draft_model.generate( prompt, num_return_sequences=candidates_per_group, temperature=0.9, top_p=0.95 ) for path in paths: candidates.append({"answer": path, "group": group}) # step 3: 验证模型打分 scored = [] for cand in candidates: score = verify_model.rank(query, cand["group"], cand["answer"]) scored.append((score, cand)) scored.sort(key=lambda x: x[0], reverse=True) best_score, best_cand = scored[0] # step 4: 低分触发精修 if best_score < verify_threshold: answer = verify_model.refine( query, best_cand["group"], best_cand["answer"], max_new_tokens=200 ) else: answer = best_cand["answer"] return answer这个骨架很简单,但它的价值在于把Speculative RAG的四个关键决策点都暴露了出来:怎么分组、草稿模型怎么采多条路径、验证模型怎么打分、精修在什么条件下触发。你后面调优,就是分别调这四个位置的参数。
3.3 三个关键参数的选择依据:N、分组数、验证阈值
第一个候选路径总数N。N等于分组数乘以每组采样数。以四组、每组两条为例,N=8,这意味着验证模型要为8条候选打分。N太少,选择空间不够;N太多,验证阶段的计算量线性上升,而且草稿模型生成的收益边际递减。我实测下来,候选总数在6到10之间是个甜点区间。你如果用的是商用API,打分按token计费,候选总数更要控制,便宜的小模型生成几十条没关系,大模型每条打分都记账。
第二个是分组数。分组数首先要受限于检索文档总数,你一共召回了24篇文档,非要分8组,每组只有3篇,材料严重不足。其次分组数要和问题复杂度挂钩。简单的单跳问题三组就够用;复杂业务问题或者需要交叉验证的多跳问题,五到六组更合适。
第三个是验证阈值。这个值本质上是“草稿质量的容忍度”。阈值设0.5会让大部分候选被直接采纳,系统快但可能有点糙;设0.7会频繁触发精修,精度上去了延迟和成本也上去了。我习惯从0.6起步,然后盯住精修率做调整:精修率太高就降阈值,答案质量反馈太差就升阈值。
下表是我给一个内部Demo做过的一组参数对比,数值仅供参考,但趋势很清楚:
| 候选总数N | 分组数 | 验证阈值 | 大模型精修触发率 | 单请求端到端延迟 | 相对传统RAG延迟 |
|---|---|---|---|---|---|
| 4 | 2 | 0.6 | 约18% | 约1.4倍基线 | 略高 |
| 6 | 3 | 0.6 | 约25% | 约1.1倍基线 | 接近持平 |
| 8 | 4 | 0.6 | 约35% | 约0.7倍基线 | 明显更低 |
| 10 | 5 | 0.7 | 约45% | 约0.8倍基线 | 有改善但边际递减 |
看这个表你会发现一个反直觉的点:候选N增加到一定程度,收益反而被精修率和验证成本吃掉。这正好印证了前面的判断——Speculative RAG不是“把N调大就完事”,而是整个流程的平衡。
3.4 延迟与成本怎么科学估算,而不是拍脑袋
很多人在草稿阶段就被劝退:“这不就是多了一次完整的小模型生成吗?怎么可能省时间?”所以我建议你按下面的步骤自己估算,而不是听别人说。
先测基线。拿你的真实任务,统计传统RAG里大模型生成答案的平均token数,记作T_base,以及每token的平均耗时。延迟基线就是Prompt处理时间加上T_base乘以单token耗时。
再测草稿层。统计草稿模型完成所有候选路径生成的总耗时。注意,这里测的是批处理后的总耗时,不是单条路径的耗时乘路径数——因为多条路径是并行生成,实测耗时增长远小于线性增长。比如8条路径的批处理,耗时就只有单条的1.5倍左右。
最后测验证层。统计验证模型平均输出token数,包括打分token和精修token。验证模型单token速度比草稿模型慢很多,但因为输出token少,总时间往往还小于草稿层。
举个例子,假设基线大模型生成200个token,单token耗时50ms,加上Prompt处理,总延迟约11到12秒。Speculative RAG这边,草稿模型批处理生成8条路径约2秒,验证模型打分输出30个token约1.8秒,有30%概率需要精修100个token,算上精修期望耗时约30%乘以5秒等于1.5秒,总延迟约5.3秒。这就是一个很典型的收益结构。你的数字可能不一样,但计算方法通用。
成本方面更直观:小模型每token成本通常比大模型低一个数量级,而大模型的输出token从200降到了几十,成本下降是很实在的。如果你的业务调用量大,这一层优化省下来的钱可能比换一个更便宜的API套餐还要多。
4. 典型应用场景:哪些业务真的适合用这套方案
4.1 知识密集问答和多跳推理场景
知识密集问答是Speculative RAG最对口的主场。典型的问题形态是“A公司的B产品对C行业有什么影响”这种,需要把多个文档里的信息串联起来做推理。传统RAG做一个全文档拼接,容易把模型带偏;Speculative RAG通过文档分组,让不同候选路径沿着不同的线索走。比如A路径只关注A公司产品本身,B路径只关注C行业背景,验证模型再看哪条路径更能解释两者的联动关系。
这种情况下,候选路径的多样性价值会被放得特别大。我见过不少案例,传统RAG给出的是“A公司发布了B产品”这种平铺直叙的回答,而Speculative RAG里有一条候选路径会把B产品的功能特性与C行业的典型痛点挂钩,最后被验证模型选出来,答案的洞察深度完全不一样。
4.2 高并发客服系统和企业知识库
客服类业务对两件事的要求几乎不可妥协:响应快、口径稳。传统的RAG流程在高峰期容易被大模型的生成时长拖垮,导致用户等待超时。Speculative RAG值得考虑的原因在于它把整体的算力压力从“一棵大树”分散到了“一棵小树在前、大树在后”的两级架构上。你甚至可以为草稿模型单独做一波扩容,因为草稿模型便宜,扩起来没心理负担;相对地,验证模型的调用次数被限制在“打分+偶尔精修”,并发压力大大缓解。
在实际部署的时候,我建议给客服场景单独维护一个候选路径缓存。同一个问题被不同用户反复问是客服系统的常态,把(query, 文档分组, 候选答案, 验证分数)缓存下来,下次完全可以直接返回最优答案,连验证模型都不用调。这个优化听着朴素,实际收益却比任何花哨的算法参数调优都大。
4.3 长文档解读:研报、财报、法律文书抓重点
长文档解读对成本和准确率的双重要求是出了名的。传统做法是把长文档切成一堆切片,然后一股脑塞进上下文,结果经常是模型对每个切片都是浅尝辄止,重点信息反而被淹没。Speculative RAG的文档分组在这里体现出了特殊价值——每个分组只关注长文档的某个局部范围,草稿模型可以在这个局部里做更充分的消化,产出的候选答案对细节的捕捉更到位。
而且验证模型打分的时候,看到的只是“候选答案+对应的文档子集”,并不需要读完整份长文档。对API计费服务来说,这意味着每次请求的输入token大幅下降,而输出token又因为只做验证而保持低位。长文档解读是最能体现Speculative RAG“以少量思考换取大量token”这种经济性的场景。
4.4 垂直领域法规解析与内部知识问答
在金融、医疗、法律这类强合规场景里,答案的依据比答案本身更重要。Speculative RAG天然适合这类场景,因为每条候选答案都可以和它对应的文档子集绑定,验证模型判断的时候可以检查“这个答案到底是不是从这几份文档里推出来的”,而不是像传统RAG那样错了都不知道错在哪。一旦业务侧追问某个结论的依据,你可以把候选答案对应的文档子集整段翻出来给对方看,可解释性直接拉满。
这种场景里,我强烈建议让草稿模型在生成候选答案时,同步输出引用了哪几条文档原文的编号。验证模型在打分时看到这个引用标记,判断会更准确;你拿到最终答案后,也能顺着引用标记做人工复核。这只是输出格式上的一个小改动,却能把整个流程的可信度提一个量级。
5. 踩坑记录:常见问题、排查思路与经验技巧
5.1 草稿模型太弱,候选路径全军覆没怎么办
最典型的症状是精修率长期超过50%,验证模型几乎每一个请求都在动手改写。很多人这时候的第一反应是换更贵的验证模型,其实是方向错了。真正该做的是先把草稿模型的质量提上来。
我的排查顺序是这样的:先随机翻几十条候选答案,看它们是不是在认真地围绕query作答。如果候选答案看起来像复读机或者答非所问,那就是草稿模型能力不够,换更大的草稿模型,或者做领域微调。如果候选答案本身有内容但经常漏细节,那问题多半出在文档分组上——每组材料太少或者分组不够聚焦。最后才考虑调整验证Prompt,让验证模型把“与问题相关的部分”和“与问题无关的部分”分别拆开来给分。反正一句话:草稿层是水,验证层是船,水不够深,船怎么都抬不起来。
5.2 验证模型打分有长度偏见,长答案总是得分高
这是打分机制里最隐蔽的问题。验证模型在对比两条候选答案时,很容易把“更长的、看起来更完整”的那条打高分,哪怕它里面的有效信息并不多。词汇都堆砌起来了,实际论证却是空的。这个问题在概率打分里尤其明显,因为长答案的对数概率天然更高。
对策非常简单有效:归一化。在对数概率打分时,分数除以答案长度的幂次,幂次一般取0.6到1.0之间,自己用历史数据抽几组样例标一下就能找到最优值。如果是用两两PK类打分,就在验证Prompt里明确写上“优先选择内容精炼、证据充分、废话最少的答案”,效果也行。
5.3 文档分组失败,候选答案高度同质化
这个问题比草稿模型弱还要隐蔽,因为它不会直接爆出高精修率,而是表现为“答案看着没毛病,但和传统RAG没啥区别,多样性的优势完全没发挥出来”。
排查方式可以做一个简单的相似度检验:把草稿模型生成的多条候选答案做两两相似度计算,如果他们都撞在0.85以上,基本上就是分组失效了。可能原因是检索文档本身高度重叠,或者是做聚类时簇间分离度不够。对策是根据文档语义进一步细分主题,或者在分组前先把重复度高的文档去重。另外别忘了把草稿模型的temperature调高一点,有时生成相似并不是因为文档重叠,而是模型自己就习惯走同一条最稳妥的路。
5.4 验证阶段被无关证据带偏,打分明显失真
我踩过一个比较深的坑:验证模型打分时,我给它的Prompt里同时放进了候选答案对应的文档子集和全量原始文档。我的本意是让它参考更多背景,结果大模型反而被无关信息干扰,给一条根本没依据的候选答案打了高分。那个分数高得离谱的场景我至今印象很深——模型完全是看哪条答案写得长、语气像那么回事就选了哪条。
后来我严格执行一个原则:验证阶段绝不出现候选答案对应分组之外的任何文档。如果确实需要全局信息,也是先把全局信息压缩成一个“摘要段”放进打分Prompt,而不是把原文铺开。这个原则救了我很多次,也让我意识到Speculative RAG中“信息隔离”的价值。它不只是一个效率优化,更是一个质量保障。
5.5 延迟还可以从哪些细节里抠出来
最后分享几个延迟优化的细节。第一个是草稿模型和验证模型尽量部署在同一张卡或者同一批节点上,避免设备间拷贝带来的额外耗时。第二个是候选路径的生成尽量充分利用批量推理,注意在框架里一次性传入多个生成任务,而不是用循环逐个调接口。第三个是精修时把max_new_tokens卡死,这既能省时间又可以防止验证模型撒开了重写。第四个是用结构化输出让验证模型直接吐出JSON格式的分数和意见,这会极大减少解析和二次处理的负担。这些小碎片的优化单独看都省不了几百毫秒,但叠在一起,体感差异会非常明显。
另外还要提醒一句:Speculative RAG的上线最好有灰度对照。把传统RAG和Speculative RAG各跑一部分流量,对比答案准确率、延迟、成本三个指标,再决定全量切换。这个建议可能在聪明人看来有点多余,但我见过不止一次因为分组参数或者草稿模型没调好就全量上线、然后又紧急回滚的事故。技术方案再漂亮,上线流程也得一步一步来。
我个人实际做完几个项目后的体会是,Speculative RAG真正让人舒服的点,不单是延迟和成本省了,而是你把“生成权”和“判断权”分离之后,整个系统就像装了调节阀——想降低成本就调小草稿模型,想提升质量就调高验证阈值,想加快速度就压缩候选数量。每一块都在可控范围内,排障思路也清晰了很多。最后再送你一个小技巧:草稿模型生成候选时,可以在Prompt里加上一句“请先列出证据要点,再基于要点给出答案”,这比直接让它写答案更能逼出高质量的中间推理链,验证模型的打分也会变得更准确。后续如果想继续折腾,还可以训练一个专门用来给候选打分的轻量排序器,彻底替代验证模型的打分环节,那样就又是一个新故事了。