W3D4 学习手册 1.总览2.Rewrite3.Multi-Query4.Decomp5.压缩 6.对比7.拒答8.引用9.落地10.评测 11.实战12.坑达标①达标②自测速记

FDE W3D4 学习手册 · Query 优化

W3 Day4 · A 级(必须掌握,面试核心)· 4h · 学完能讲透"用户原始问句如何被改写成更适合检索/生成的形式、无答案如何拒答、引用如何保真"

本日定位:前面已讲检索与生成,W3D4 聚焦"进检索前的 Query 优化"和"出答案时的可靠性(拒答 + 引用)"。这是 RAG 工程里性价比最高、面试最常被深挖的一块。
学完能回答:① Query Rewrite / Multi-Query / Decomposition 各自解决什么问题、什么时候用;② 引用准确性怎么保证、无答案时怎么拒答。
使用方法:通读原理 → 重点看「面试话术」「易错点」→ 做自测清单 → 配合《FDE-W3D4-评测题.md》。选中不熟的词可标注(左下★重要 / 右下📌待查)。
参考资源:LangChain Query 改写(python.langchain.com/docs/how_to/query_transformer)、LangChain RAG 进阶教程;中文可搜 B站「LangChain RAG 查询改写 / Multi-Query」实操。

一、Query 优化总览:为什么要改用户的问句

用户原始问句(original query)往往不适合直接检索:措辞口语化、缺上下文、含指代("它""这个")、与知识库文档用词不一致、或问题过大需要拆分。Query 优化就是在"检索前"对问句做变换,让召回更准、答案更稳。

原始 Query → 改写/扩展/分解/压缩 → 优化后的 Query(们) → 检索 → 生成
手段核心动作解决的核心问题
Query Rewrite重写一句话,纠正/补全/对齐术语措辞不匹配、缺上下文、口语化
Multi-Query生成多个不同角度的问句并行检索单问句召回不足、视角单一
Query Decomposition拆成多个子问题逐个/依赖回答复杂复合问题、需要多跳推理
Context Compression压缩召回上下文或压缩历史上下文过长、噪声多、超 token
Query 优化 = "在检索前把用户问题变得更好检索"。本质是用一次(或几次)LLM 调用,提升后续检索/生成的质量——属于"以算力换召回"的工程权衡。
在医疗保险知识库里,用户常问"我那个特药能不能报"——"那个特药"缺指代、术语不对齐。Rewrite 把它变成"投保人在 XX 保单下申请奥希替尼(肺癌靶向药)的特药理赔,是否符合报销范围",检索命中率立刻提升。

二、Query Rewrite(查询改写)

2.1 原理

用 LLM 把原始 query 重写为一个语义等价但更适合检索的问句。典型做法:

2.2 实现(LangChain MultiQueryRetriever / query_transformer 思路)

# 简化示意:用 LLM 做 query rewrite
rewrite_prompt = """你是保险知识库检索助手。把用户问题改写成一句
术语标准、信息完整、适合在保险条款库中检索的问题。
只输出改写后的问题,不要解释。
用户问题:{question}
投保人画像:{profile}"""
better_q = llm.invoke(rewrite_prompt.format(question=q, profile=profile))

2.3 什么时候用

Query Rewrite = "用 LLM 把一句话改写得更会检索"。重点是术语对齐 + 补全上下文 + 消歧。适合口语化、术语不匹配、多轮指代场景。
① Rewrite 可能"改坏"——改写后语义漂移或引入幻觉事实,所以改写结果要只用于检索,不直接当答案,且最好保留原始 query 做兜底召回。② 改写会增加一次 LLM 调用(延迟+成本),高频场景要考虑缓存(相同/相似 query 复用改写结果)。③ 别让模型在改写时"偷偷回答"问题,要约束它只输出改写问句。

三、Multi-Query(多查询并行检索)

3.1 原理

一个问题往往可以从多个角度表述。Multi-Query 让 LLM 生成 N 个不同表述/不同侧重点的 query,分别检索,再把各路召回的文档去重合并后喂给生成模型。核心收益是提高召回覆盖率

original query → LLM 生成 {q1, q2, q3} → 分别检索 → 文档去重合并 → 生成

3.2 适合场景

3.3 代价与注意

Multi-Query = "一个问题生成多个角度问句,分别检索后合并去重"。解决"单问句召回不够全"。代价是 N 倍检索成本,合并后要去重 + 最好 Rerank。
医疗保险案例:用户问"异地就医怎么报"。可生成:①"异地转诊备案流程" ②"异地就医报销比例与起付线" ③"异地就医材料清单" 三路检索合并,覆盖流程/比例/材料三个侧面,单问句很难一次召回全。
① Multi-Query 不等于"多路召回一定更好"——若生成的 query 彼此高度相似,只是浪费算力。要控制多样性(prompt 里要求"不同角度、不要同义复述")。② 合并去重不当会导致上下文里有大量重复条款,挤掉真正有用的内容。③ 多路召回会让"引用准确性"更难(多源混杂),需要记录每片 chunk 来自哪一路。

四、Query Decomposition(查询分解 / 子问题)

4.1 原理

复杂复合问题,先让 LLM 拆成若干子问题,再分别检索回答,最后汇总。分两类:

复杂问题 → 分解 → [子问题1, 子问题2, ...] → 逐个检索+回答 → 汇总最终答案

4.2 什么时候用

4.3 工程要点

Query Decomposition = "把复杂问题拆成子问题,分别检索回答再汇总"。适合多跳/复合问题。分独立并行与依赖顺序两类,要保留依赖图便于溯源。
保险案例:「投保人同时有重疾险和百万医疗,确诊肺癌做靶向治疗,两份保单各自能报多少、有没有先后顺序?」→ 拆成:①重疾险对肺癌的给付责任 ②百万医疗对靶向治疗的报销责任 ③两份保单的补偿/给付关系(是否重复报销)。三个子问题分别检索后汇总,单问句无法答全。
① 不是所有"长问题"都要分解——简单并列问题直接 Multi-Query 或单检索即可,过度分解增加延迟。② 依赖型分解易出错:前置子问题答错会连锁污染后续。要有早停/校验。③ 汇总阶段如果忘记"哪些子问题其实没检索到答案",容易编造,需把"无答案子问题"显式带入最终拒答逻辑。

五、Context Compression(上下文压缩)

5.1 原理

检索回来一堆 chunk 后,其中很多与问题无关。Context Compression 通过压缩/过滤只保留与 query 相关的片段,降低噪声、节省 token、提升生成质量。两类做法:

在保险场景,检索回 10 片条款,但真正相关的可能只有 2 片里的 3 句话。压缩后只把"与报销比例相关的句子"送入生成,既省 token 又减少模型被无关条款带偏的概率。

5.2 与 Rewrite/Decomposition 的区别

手段作用阶段目标
Rewrite / Multi-Query / Decomp检索前(优化 query)让召回更准更全
Context Compression检索后(优化 context)让送入生成的上下文更干净
Context Compression = "检索后把无关 chunk 过滤/抽句,只留相关片段"。作用在检索后,和检索前的 Rewrite 互补。降低噪声、省 token、提质量。
① 压缩本身也可能丢信息(把关键一句误判为无关),对拒答判断尤其危险——压缩掉"无此条款"的证据会导致模型硬答。压缩要保留"否定/缺失"类信号。② 用 LLM 做压缩又多一次调用,简单场景用 Rerank + 截断 topK 即可,不必上压缩。③ 压缩后的片段要保留来源标记,否则引用失真。

六、三种 Query 策略对比与选型

维度Query RewriteMulti-QueryQuery Decomposition
输出1 个改写问句N 个并列问句若干子问题(可有依赖)
解决措辞/术语不匹配、缺上下文单问句召回不全复杂/多跳复合问题
成本1 次 LLM 调用N 次检索(1 次改写)多次检索+多次 LLM
风险改写语义漂移query 同质化浪费依赖链错误连锁
典型组合几乎必做+ Rewrite 后再扩+ 每子问题再用 Rewrite
工程建议(组合拳):Rewrite 是地基(几乎每次都做);召回不稳上 Multi-Query;问题复杂上 Decomposition;召回噪声大再上 Context Compression。不要一上来全开,按问题难度分级路由。
三者是不同维度:Rewrite 改"一句话的表达",Multi-Query 扩"多视角",Decomposition 拆"多子问题"。生产里按问题难度分级:简单→Rewrite,召回不足→+Multi-Query,复杂多跳→+Decomposition。

七、无答案拒答(Refusal)

7.1 为什么必须拒答

企业知识库(保险条款、特药目录)里没有的信息,模型绝不能硬编——错误理赔结论会造成真实经济损失与合规风险。无答案时应明确拒答并引导

7.2 实现方式

7.3 拒答不等于"甩锅"

好的拒答要给出口:说明缺什么信息、建议联系谁/查哪个渠道(如"未在知识库找到该城市异地就医细则,建议联系保单客服确认"),而不是冷冰冰"不知道"。

拒答 = "知识库没有就承认没有,绝不硬编"。用 should_refuse 字段 + 检索分数阈值双保险;且拒答要给出口(缺什么、找谁),不是冷拒。
① 别只靠关键词检测"我不知道"——模型可能说"未查询到相关条款""暂无对应规定",要靠字段 + 语义判定。② 检索分数阈值设太高是"该答却拒"(漏答),太低是"乱答"(幻觉),阈值要靠评测集校准。③ 拒答要进评测(拒答准确率),否则模型倾向"自信地编"以讨好用户。

八、引用准确性(Citation Accuracy)

8.1 为什么重要

保险场景,答案若没有可核查来源,无法审计、无法追责。引用准确性 = 答案里每条结论都能精确对应到知识库中的具体 chunk / 文档段落,且不能"张冠李戴"。

8.2 保证手段

8.3 常见失真

引用准确性 = "每条结论都能精确对应真实存在的 chunk,且不张冠李戴"。靠检索即绑定 id + 结构化引用输出 + 引用校验。保险场景关系到合规审计,必须可回溯。
① Multi-Query / Decomposition 多路召回后,如果不记录每片来源,引用极易混乱——去重合并时必须保留来源标记。② 模型爱"凑引用",把不相关的 chunk 标上显得有依据,要校验"该 chunk 是否真支持该 claim"。③ 引用粒度要合适:引到 chunk 比引到整篇文档更可核查。

九、工程落地:改写模型与提示设计

9.1 改写用"小模型"还是"大模型"

9.2 提示设计要点

9.3 评测闭环

改写/拒答/引用都要进评测集(见 W3D5):改写看是否提升召回;拒答看拒答准确率;引用看引用准确率与幻觉率。

工程上 Query 优化是一层"可观测、可降级"的服务:改写失败可 fallback 用原 query 检索;多路召回失败可降级单路;拒答判定失败可默认"进生成但题目没有就拒"。所有分支都要有降级,不能让整条链路卡死。

十、怎么评测 Query 优化与可靠性

对象评测指标怎么做
Rewrite改写后召回提升同一批问题,对比"原 query"与"改写 query"的 Hit Rate@K / nDCG
Multi-Query召回覆盖率对比单 query vs 多 query 合并后的 Recall@K
Decomposition子问题准确率人工/LLM 判定分解是否合理、是否覆盖必要子问题
拒答拒答准确率should_refuse 集上测 precision/recall(详见 W3D5)
引用引用准确率人工/LLM 判定每句结论的引用是否正确且真实存在
评测 Query 优化要"对照实验":Rewrite 比原 query 召回高多少;拒答/引用靠专门标注集测准确率。没有对照就不知道优化有没有用。

十一、医疗保险实战案例:特药理赔问答

场景:投保人问"我去年买的百万医疗,现在确诊肺癌要吃奥希替尼,这个药能报吗?还有报销比例多少?"

  1. Rewrite:补全画像 → "持有 XX 百万医疗险的投保人,确诊肺癌需使用奥希替尼(靶向药),该药品是否在特药目录内、报销比例及自付要求为何?"
  2. Multi-Query:生成 ①"奥希替尼 特药目录 纳入情况" ②"百万医疗 靶向药 报销比例" ③"肺癌 靶向治疗 免赔额/自付比例"。
  3. Decomposition(若问题含"先报重疾还是先报医疗"):拆成重疾给付责任、医疗报销责任、补偿关系三子问题。
  4. 拒答:若知识库无"奥希替尼具体比例",输出 should_refuse=true,引导"以保单批单/客服确认为准"。
  5. 引用:答案每条挂 chunk_id(特药目录条目、报销比例条款),前端可点开复核。
真实系统里这层 Query 优化是"用户无感但效果显著"的部分:同一句口语,优化后把召回命中率从 60% 提到 90%+,且拒答更准、引用可审计,这正是面试时能讲出"业务价值"的点。

十二、常见坑与排查清单

十三、面试达标线①:三种 Query 策略各解决什么、何时用

策略解决的核心问题什么时候用
Query Rewrite口语化/术语不匹配/缺上下文/指代几乎每次都做(地基);多轮对话、术语不对齐
Multi-Query单问句召回不全、视角单一语义宽泛、答案分散多处、单检索 topK 不稳
Query Decomposition复杂复合 / 多跳推理问题问题需多步推理、依赖多个条件或文档
Context Compression检索后噪声多、上下文过长召回噪声大、超 token、需提生成质量
核心话术:Rewrite 改"表达"(地基必做),Multi-Query 扩"视角"(解决召回不全),Decomposition 拆"子问题"(解决多跳复杂)。三者作用在不同维度,可组合,但按问题难度分级路由,不盲目全开。

十四、面试达标线②:引用准确性怎么保证、无答案怎么拒答

14.1 引用准确性保证

检索即绑定 id → 结构化引用输出(claim↔chunk_id) → 引用校验(该chunk是否真支持该claim) → 前端回溯高亮
  1. 每片 chunk 带 doc_id/chunk_id,生成时只允许从这些 id 引用。
  2. 答案 JSON 要求 citations:[{claim, chunk_id}],每句结论挂来源。
  3. 后处理校验:引用 id 真实存在 + 该 chunk 确实支持该 claim(可做二次 LLM 判定)。
  4. 多路召回合并时必须保留来源标记,否则引用混乱。

14.2 无答案拒答

  1. 检索分数阈值:topK 相关分都低于门槛 → 直接判无答案。
  2. 结构化 should_refuse 字段 + 生成时 prompt 约束"无依据就拒"。
  3. 拒答要给出口(缺什么信息、建议联系谁),不是冷拒。
  4. 拒答进评测集测拒答准确率,防止模型"自信硬编"。
引用靠"检索即绑定 + 结构化输出 + 引用校验"三位一体;拒答靠"检索分数阈值 + should_refuse 字段 + 评测闭环"双保险。两者都是企业 RAG 可靠性的核心,保险场景尤甚(可审计、防幻觉)。

十五、W3D4 自测清单

十六、高频面试题速记卡

Q:Query Rewrite 和 Multi-Query 有什么区别?
Rewrite 是把"一句话改写表达更好"(输出 1 句);Multi-Query 是把"一个问题扩成多视角问句并行检索"(输出 N 句)。前者改表达,后者扩视角。
Q:什么时候用 Query Decomposition?
问题复杂、需要多跳推理或依赖多个文档/条件时。拆成子问题分别检索回答再汇总;分独立并行与依赖顺序两类。
Q:Multi-Query 合并后为什么要去重和 Rerank?
多路召回有重复 chunk 会挤占上下文;且不同路质量不一,Rerank 重新排序避免劣币驱逐良币。
Q:怎么保证引用准确性?
检索即绑定 chunk_id;答案结构化引用(claim↔chunk_id);后处理校验"该 chunk 是否真支持该 claim";多路召回保留来源标记;前端可回溯。
Q:无答案时怎么拒答?
检索分数阈值 + should_refuse 字段 + prompt 约束;拒答要给出口(缺什么、找谁),并进入评测集测拒答准确率。
Q:Rewrite 有什么风险?
改写语义漂移、引入幻觉事实;增加延迟成本。应对:约束只改表达不加事实、保留原 query 兜底、对高频 query 缓存。
Q:Context Compression 在检索前还是检索后?
检索后。对召回 chunk 过滤/抽句,降低噪声省 token;与检索前的 Rewrite 互补。注意别压掉"无此条款"的否定证据。
Q:为什么拒答比硬答更重要(保险场景)?
错误理赔结论造成真实经济损失和合规风险;拒答可审计、可引导,硬编会误导决策。拒答准确率是 RAG 核心评测指标。
Q:Query 优化这几种策略要全开吗?
不要。按问题难度分级路由:简单→Rewrite,召回不足→+Multi-Query,复杂多跳→+Decomposition,噪声大→+Compression。
Q:Decomposition 的依赖链错误有什么危害?
前置子问题答错会连锁污染后续子问题,最终汇总全错。要设最大层数、早停、对子问题结果做校验。
FDE W3D4 学习手册 · Query 优化(面试级)· 配合《FDE-W3D4-评测题.md》自测
📌 待查★ 重要