跳到主要内容

K3.3 查询改写:先把问题问对

一直在优化的是右半边​

K3.1 讲关键词、K3.2 讲混合与融合——两节都在回答同一个问题:拿到一句话,怎么从库里找得更准。

现在把镜头往左移一格,看看那句话本身。

真实用户是这么提问的:

  • 「能退吗」——三个字,一个可检索的词都没有;
  • 「那它多少钱」——「它」指的是上一轮说的东西,这一句里没有;
  • 「苹果多少钱、包邮吗」——一句话问了两件事,答案在两段完全不相干的文字里;
  • 「攒的分有什么用」——口语问句,而库里写的是「每消费 1 元累计 1 积分」。

这些话是说给人听的,不是写给检索器的。你的嵌入模型再好、混合检索调得再精,喂进去的是一句「能退吗」,出来的也只能是碰运气的结果。

所以还有一步,位置在检索之前:先把问题改写成适合检索的样子。

四种改法,其中一种会帮倒忙​

🎮 动手实验
查询改写:先把问题问对
前两节都在优化「怎么找」。这一节换个思路:用户递过来的那句话,本身可能就不适合拿去检索。四个场景,逐个点开看改写前后的差别。
用户打字很省,「能退吗」三个字里一个可检索的词都没有——它离知识库里任何一段都不近,检索只能瞎排。
退货政策:商品支持七天无理由退货,需保持包装完好,生鲜类除外。换货流程:如需换货,请在订单页点击「申请换货」,我们将安排上门取件。配送时效:普通快递 3–5 天送达,偏远地区顺延;付费加急可次日达。运费规则:订单满 99 元包邮,未满收取 10 元运费;生鲜一律加收冷链费。支付方式:支持微信、支付宝、银行卡以及货到付款。开发票:订单完成后 30 天内可申请电子发票,纸质发票需额外邮寄。会员权益:黑卡会员享全场 95 折、专属客服和生日礼券。积分规则:每消费 1 元累计 1 积分,100 积分可抵 1 元。X9 Pro 参数:X9 Pro 搭载 6.7 英寸屏幕,5000mAh 大电池,支持 100W 快充。冰糖心苹果:阿克苏冰糖心苹果,脆甜多汁,5 斤装,满 99 包邮。苹果手机充电线:苹果手机原装充电线,支持快充,一年质保。原始改写
策略:澄清改写:把口语补成完整、带关键词的检索式
原始:「能退吗」
改写:「七天无理由退货的条件和政策」
改写前 top-3
1支付方式71%
2会员权益71%
3X9 Pro 参数67%
改写后 top-3
1🎯 退货政策99%
2换货流程93%
3冰糖心苹果69%
✅ 目标段落:改写前命中 0/1,改写后命中 1/1
最基础也最有效的一种。补全的是**检索需要的词**,不是让问题变长——「七天」「无理由」「退货」「政策」每一个都在往正确的那片区域靠。
💡 要点:检索的质量上限,一半取决于**查询本身**。用户的原话是说给人听的,不是写给检索器的——中间加一步改写,往往比换更好的嵌入模型见效快。
但它不免费:每次改写都要多调一次模型(延迟 + 成本),而且**改写器自己也会犯错**(场景 ④)。所以它要有开关、要能回退、要进评测——别当成无脑加分项。
语料和坐标沿用 [K1/K3/K4](./01-keyword-search.mdx) 的同一套小网店知识库,两维「语义坐标」是真实高维空间的概念缩影。

四个场景请逐个点开:

场景 ①:澄清。 「能退吗」在语义空间里落在正中间——离谁都不近,top-3 捞回来的是支付方式、会员权益、X9 Pro,全都不相干。改写成「七天无理由退货的条件和政策」之后,查询点一下子跳到退货那片区域,命中率 99%。补的不是字数,是检索需要的词。

场景 ②:拆分。 「苹果多少钱包邮吗」问了两件事。看那个原始查询点——它卡在「苹果」和「运费」中间,哪边都够不着,改写前只捞到了苹果、漏了运费规则。拆成两个子查询各查各的,再把结果合并,两个目标全部命中。

复合问题是 RAG 最常见的死法之一:答案分散在多段里,而检索只给你一个查询点。

场景 ③:HyDE。 这个最有意思。「攒的分有什么用」是个口语问句,而库里那段是陈述句「每消费 1 元累计 1 积分,100 积分可抵 1 元」。问句和答句的写法差得远,向量上也就未必挨得近——改写前积分规则连 top-3 都没进。

HyDE 的做法反直觉:先让模型凭空编一个答案,比如「消费可累计积分,积分能按比例抵扣现金使用」,然后拿这个假答案去检索。

它编的内容可能是错的(比例、门槛都可能瞎写),但这不重要——它的写法像一个答案,于是在向量空间里落到了「答案该在的那片区域」,一下子命中真正的那一段。

用答案找答案,比用问题找答案更准。

场景 ④:改坏了。 「苹果什么时候发货」——用户问的是水果,而且这个问题本来就检索得很好(冰糖心苹果排第一,92%)。结果改写器自作聪明,把「苹果」补成了「苹果手机 X9 Pro」,查询点从水果区被拽到配件区,原本排第一的答案彻底消失。

改写不是免费的加分项

场景 ④ 不是我为了凑数编的反例,它是改写最真实的风险。三笔账要算:

一、延迟和成本。 每次改写都要多调一次模型。一个原本 800 毫秒的检索问答,加上改写可能变成 1.5 秒;成本也多一份。对高频、低价值的查询,这笔钱不一定划算。

二、改写器自己会犯错。 它要猜用户的意图,而猜错的代价是把一个本来好好的查询带偏。尤其是歧义词(苹果、小米)和领域术语(用户说的缩写它自作主张展开成了别的东西)。

三、多轮场景里它最容易错。 「那它多少钱」需要改写器正确理解上文说的是哪个「它」——上文一长,指代消解就开始出错,而错了之后整条链路都在为一个错误的问题服务。

所以实践上的三条:① 别对所有查询无脑改写(原查询已经很明确时跳过,或者「原查询 + 改写查询」两路都跑再融合);② 改写要能回退(改写结果检索不到东西时,退回原查询);③ 把改写当成一个可开关的组件,进 K6 的评测——它到底提升了多少,要用数字说话,不能凭感觉。

一张选型表​

用户的问题长什么样该用哪种改写代价
太短太口语,没有可检索的词澄清改写:补成完整检索式一次模型调用
多轮对话里带代词、省略主语指代消解:把上文的主语补回来一次调用;上文越长越容易错
一句话问了好几件事拆分:拆成子查询,多路召回后合并N 次检索,结果要去重
问句形式,和库里的陈述句对不上HyDE:编个假答案去检索一次调用;假答案可能带偏
一个说法可能有多种表述多查询扩展:生成 3~5 个变体一起查N 次检索;靠 RRF 融合

最后一行值得单说:多查询扩展是最省心的一种——不追求「改对」,而是生成好几个说法一起查,再用 K3.2 的 RRF 把几路结果融合。它不需要改写器猜准意图(猜错一个还有别的兜底),代价是检索次数翻几倍。

本节要点
  • 检索的质量上限,一半取决于查询本身。用户的原话是说给人听的,不是写给检索器的。
  • 澄清补关键词、指代消解补主语、拆分对付一句话问几件事、HyDE 对付问句与答句对不上、多查询扩展用数量换命中。
  • HyDE 的反直觉之处:让模型编一个假答案去检索,假答案的事实可以是错的——它只负责把查询点挪到「答案该在的区域」。用答案找答案,比用问题找答案更准。
  • 改写不是免费的:多一次模型调用(延迟 + 成本),而且改写器会把对的问题改错(歧义词、多轮指代是重灾区)。
  • 三条实践:别无脑全改(或原查询 + 改写两路都跑)、改写要能回退、把改写当可开关组件进评测。

小结​

📝 动手自测0/3
1. HyDE 让模型先编一个「假答案」再拿去检索。假答案的内容可能是错的,为什么还有效?
2. 「苹果多少钱、包邮吗」这类问题,为什么单靠调 top-k 或换更好的嵌入模型往往解决不了?
3. 关于查询改写的风险,下面哪个说法是对的?

延伸阅读​