RAG 查询改写怎么做?多查询、HyDE、Step-back 三个套路,专治文档里有就是查不到(2026实战)

你花一个下午搭好了 RAG:文档切好块、向量入库、检索、拼提示词。测试集上问「A 产品的保修期是多久」,答得挺好。第二天真实用户来问「你们家那个东西坏了还管修吗」,检索命中率直接垮掉。

文档里明明写着答案,就是检索不到。问题多半不在索引,而在查询这一头。今天讲三个修查询的经典套路:多查询、HyDE 和 Step-back,都是让同一个问题换个姿势去检索。改写只管查询这一层,检索回来之后怎么装进提示词、窗口装不下怎么办,是另一条线的事,之前写过一篇上下文管理专门讲。

先看查询为什么会失配

向量检索的原理是把问题和文档都变成向量,算距离,距离近的当作相关。这套机制有个前提:问题和答案所在的文档,在向量空间里得离得近。embedding 模型怎么选直接决定这个前提成不成立,之前写过一篇选型指南,这里不展开。

但真实场景里两者经常长得完全不一样。文档是说明书口吻:「质保期为自购买之日起 24 个月」。用户是口语:「坏了多久能免费换新」。语义相关,字面不沾边,embedding 模型算出来的距离不够近,文档排不进前列,后面的生成模型再强也读不到材料。检索研究员管这个叫查询与文档之间的语义鸿沟,是零样本检索场景里的核心难点。

顺着这个思路,修复手段也分三个方向:把一个查询变成好几个(多角度出击)、让模型先编一份假想答案(往答案的形态靠)、把具体问题抽象化(往概念层面靠)。

多查询:一次提问,三路出击

最直接的办法:让大模型把用户的问题改写成几个不同的版本,每个版本各自去检索,结果合并去重。

「坏了还管修吗」可以被改写成「保修政策是什么」「售后维修流程」「质保期多长」,三个角度各自命中一部分文档,合并之后覆盖面明显变宽。原始问题的表述缺陷,被多个变体摊平了。改写变体的数量怎么定、每一路检索多少条,和分块粒度是同一类问题,分块那篇的思路可以直接搬过来用。

LangChain 里的 MultiQueryRetriever 就是现成实现,它的默认提示词大致是这个意思:

You are an AI language model assistant. Your task is
to generate 3 different versions of the given user
question to retrieve relevant documents from a vector
database. By generating multiple perspectives on the user
question, your goal is to help the user overcome some of
the limitations of distance-based similarity search.
Provide these alternative questions separated by newlines.
Original question: {question}

生成 3 个版本、按行分隔,每个变体独立检索一遍,最后做并集去重。用法上通过 from_llm 一行接上你现有的 retriever 和大模型就能跑,原始查询默认不参与检索,想带上可以打开 include_original 开关。

代价要心里有数:变体数量就是检索次数,3 个变体等于向量库查询量翻三倍,延迟和大模型调用的钱也按倍数涨。生产环境常用的折中是 2 到 3 个变体,再多收益递减。

HyDE:让模型先编一份假答案

这个套路的思路更野:与其变着法子问,不如让大模型直接「编」一份假想的答案文档,拿这份假文档的向量去检索真文档。

听着离谱,用户的问题都还没答,凭什么先编答案?逻辑是这样的:说明书和口语提问在向量空间里离得远,但说明书和「一份长得像说明书的东西」离得近。让大模型生成一段假设性文档,哪怕细节全是错的,只要形态、用词、结构像真答案,它的向量就会落在真文档的邻居位置,把真文档带出来。

这个方法 2022 年 12 月出自滑铁卢大学等机构的论文,名字叫 HyDE,全称 Hypothetical Document Embeddings。论文的核心主张原话是:生成的文档捕捉了相关性模式,但它是虚构的,可能包含错误细节;随后用无监督对比学习训练出来的编码器把它转向真实的语料库,编码器的信息瓶颈会把错误细节过滤掉。

流程拆开是三步:

  • 第一步,零样本指令让大模型生成假设文档,不提供任何真实语料;
  • 第二步,把假设文档编码成向量,注意这里用的是检索用的同一个 embedding 模型;
  • 第三步,用这个向量在真语料里做近邻检索。

论文实验里,HyDE 在网页搜索、问答、事实验证等多个任务和多种语言上,明显超过当时的无监督检索基线 Contriever,效果接近微调过的检索器。零样本场景不用标注任何数据,这是它最大的吸引力。

实践中有三个注意点。第一,生成的假文档会额外花一次大模型调用,延迟和成本都要算。第二,假设文档写多长有讲究,太短信息不够,太长会稀释向量,一般以 100 到 200 字、一份迷你段落为宜。第三,它依赖大模型的领域常识,问题太偏门、模型编出来的内容形态完全跑偏时,效果会掉,这时候退回多查询更稳。

Step-back:先退一步问概念

第三类问题跟前两个不同。用户问「HU-32007 2026 年 6 月做的那个实验,结论是什么」,这种问题细节密度太高,直接检索往往落空:文档里未必存着这么具体的条目,就算存着,表述也对不上。

Step-back 提示法的处理方式是先让大模型把具体问题「往上抽象」一层:不直接查实验编号,先问「2026 年 6 月该课题组发表了哪些研究」。概念层面的问题命中文档的概率高得多,拿到背景材料之后再回答原始问题,具体细节放在第二轮补。

这个方法出自 Google DeepMind 研究人员 2023 年的论文,核心思想用论文自己的话说:让大模型从包含具体细节的实例中抽象出高层概念和第一性原理,再用这些概念和原理引导推理。实验数字相当可观:在 MMLU 的物理和化学子集上,PaLM-2L 分别提升了 7% 和 11%;TimeQA 提升 27%;MuSiQue 提升 7%。

它和多查询方向相反:多查询是把问题拆细、多个角度铺开;Step-back 是把问题拔高、先拿背景再抠细节。适合的场景是细节型提问、专业领域问答,以及多跳问题里第一跳容易落空的情况。

三个怎么选

一张表说清:

  • 多查询:口语化提问多、用词难预测的场景。成本是检索次数按变体数翻倍。
  • HyDE:问题与文档口吻差距大、没有标注数据的零样本场景。成本是每次多一次生成调用,对模型的领域常识有要求。
  • Step-back:细节密度高的专业提问、多跳推理。成本是两轮调用,问题本身不适合抽象时别硬用。

三者可以叠加。常见的组合是 Step-back 拿背景材料,多查询铺开检索面,最后用 rerank 重排收口。但先从单个套路开始,加一层测一层,别一口气全上。我见过把五个增强模块叠在一起的项目,出了问题没人说得清检索结果到底是哪一层改出来的。

检索质量的天花板由查询决定,生成质量的天花板由检索决定。查询改写不解决所有问题,但它通常是整套 RAG 里投入产出比最高的一层改造。你的知识库如果总有「文档里有就是查不到」的问题,先从多查询试起,十分钟就能看到区别。

发表评论