1、先搞清楚多轮对话下检索为什么容易失败
多轮对话里,用户 query 常常不完整:
- 指代:“它充电快吗?”——“它”指什么?
- 省略:“那续航呢?”——省略了主语和比较对象。
- 依赖上文:“还有别的吗?”——需要知道在问什么类别。
- 话题切换:“那 iPhone 15 呢?”——需要知道对比的是谁。
如果直接把当前 query 丢给检索:
- 向量检索不知道“它”是什么,可能召回无关文档。
- 关键词检索更糟,query 里根本没有实体词。
- 结果就是检索失败,生成幻觉。
所以需要把不完整的 query 补全成可检索的 query。
2、查询改写(Query Rewriting)解决什么问题
目标:把依赖上下文的 query 改写成独立、完整、可检索的 query。
常见方法:
(1)把历史对话拼进 query
最简单的方法:
改写后的 query = 最近 N 轮对话 + 当前 query
- 优点:简单,不用额外模型。
- 缺点:历史太长会引入噪声,超出检索模型输入限制。
- 适合:轮次少、上下文短的场景。
(2)用 LLM 做指代消解和补全
把历史对话和当前 query 给 LLM,让它改写成完整 query:
输入:历史对话 + 当前 query
输出:独立的完整 query
例子:
- 历史:“iPhone 15 的电池怎么样?”
- 当前:“那它充电快吗?”
- 改写:“iPhone 15 充电快吗?”
优点:
- 效果好,能处理指代、省略、话题切换。
- 灵活,可以控制改写风格。
缺点:
- 需要额外 LLM 调用,增加延迟和成本。
- 改写可能引入偏差或错误。
- 需要 prompt 设计好。
(3)用专门的小模型做改写
- 训练一个专门的 query rewriting 模型。
- 比 LLM 快,成本低。
- 但需要标注数据。
(4)对话状态跟踪(DST)
- 维护对话状态:当前话题、实体、意图。
- 用状态补全 query。
- 适合任务型对话,但实现复杂。
(5)规则 + 模型混合
- 简单指代用规则。
- 复杂情况用模型。
- 平衡成本和效果。
关键取舍:
- 改写用 LLM 还是小模型?效果 vs 成本。
- 拼多少轮历史?上下文完整 vs 噪声。
- 改写会不会引入偏差?需要评估。
- 改写后要不要保留原 query?可以两路都检索。
3、查询扩展(Query Expansion)解决什么问题
目标:把 query 扩展成多个相关 query 或补充同义词,提高召回。
常见方法:
(1)同义词扩展
- “续航” → “电池续航”“电池寿命”“电池容量”。
- 解决词汇鸿沟。
(2)多查询生成(Multi-Query)
- 用 LLM 把原 query 生成多个不同表达的 query。
- 每个 query 独立检索,结果融合。
- 代表:LangChain 的 MultiQueryRetriever。
例子:
原 query:“iPhone 15 续航”
扩展:
- “iPhone 15 电池续航”
- “iPhone 15 电池容量”
- “iPhone 15 电池使用时间”
(3)HyDE(Hypothetical Document Embeddings)
优点:
- 提高召回率。
- 解决 query 和文档表达不一致的问题。
缺点:
- 需要额外 LLM 调用。
- 可能引入不相关 query,增加噪声。
- 多路检索增加延迟。
(4)伪相关反馈(Pseudo-Relevance Feedback)
- 先检索一轮,取 Top-K 文档。
- 从文档里提取关键词,扩展 query。
- 再检索一轮。
- 经典 IR 方法,RAG 里也可以用。
(5)知识图谱扩展
关键取舍:
- 扩展多少 query?太多噪声大,太少召回不足。
- 多路结果怎么融合?RRF 或分数融合。
- 扩展会不会跑偏?需要评估。
4、改写和扩展的区别
| 维度 | 查询改写 | 查询扩展 |
|---|
| 目标 | 让 query 完整、准确 | 让 query 覆盖更多表达 |
| 解决 | 指代、省略、上下文依赖 | 词汇鸿沟、召回不足 |
| 方法 | 拼历史、LLM 改写、DST | 同义词、Multi-Query、HyDE |
| 结果 | 一个改写后的 query | 多个 query 或扩展词 |
| 阶段 | 检索前 | 检索前或检索中 |
| 风险 | 改写偏差 | 引入噪声 query |
一句话:
- 改写:把 query 补完整。
- 扩展:把 query 铺开。
- 两者可以结合:先改写,再扩展。
5、完整方案:多轮对话 RAG 检索
一个完整的多轮对话 RAG 检索链路:
历史对话 + 当前 query
↓
查询改写(补全指代、省略)
↓
查询扩展(同义词、Multi-Query、HyDE)
↓
多路检索(向量 + 关键词)
↓
结果融合(RRF)
↓
重排序(Cross-Encoder)
↓
生成
6、如何评估改写和扩展效果
- 检索指标:Recall@K、MRR、NDCG。
- 端到端:Answer Correctness、Faithfulness。
- 对比实验:不改写 vs 改写 vs 改写+扩展。
- 人工抽查:改写后的 query 是否准确。
- 延迟和成本:额外 LLM 调用的开销。
关键:改写和扩展不是越多越好,要用评估数据验证。
7、一句话总结
多轮对话下,query 常依赖上下文,检索容易失败。查询改写负责补全指代和省略,把 query 变成独立完整的问题;查询扩展负责补充同义词和多种表达,提高召回。两者可以结合,先改写再扩展,多路检索后融合重排序。关键是用评估数据验证效果,平衡延迟和成本。
8、这道面试题的质量点评
优点
- 场景真实:多轮对话是 RAG 最典型的落地场景。
- 技术聚焦:改写和扩展是解决上下文依赖的核心手段。
- 区分度好:
- 初级:能说“把历史对话拼进去”。
- 中级:能说指代消解、LLM 改写。
- 高级:能说 HyDE、Multi-Query、评估、融合。
- 有追问空间:可以追问改写模型选型、多路融合、评估方法、延迟成本。
缺点
- 改写和扩展层级不同:一个补全,一个铺开,放一起需要搭桥。
- 缺少评估环节:没问怎么判断改写/扩展有没有效果。
- 范围稍窄:没提对话状态跟踪、检索后重排序等其他方案。
- 容易背名词:可能只列 HyDE、Multi-Query,说不清取舍。
总体评价
质量:中上偏上。 适合中高级岗位,能有效区分“知道多轮对话难”和“真正处理过多轮 RAG”的人。建议追问:
“改写用 LLM 还是小模型?为什么?”
“HyDE 的原理是什么?有什么风险?”
“多路检索结果怎么融合?”
“改写和扩展怎么评估?”
“改写引入偏差怎么办?”
9、怎么回答才是最好的
回答原则
- 先给场景:多轮对话 query 不完整,检索失败。
- 区分改写和扩展:一个补全,一个铺开。
- 分方法说:每种方法讲清原理、优缺点、适用场景。
- 讲融合和评估:多路检索后 RRF、重排序、评估指标。
- 主动提风险:改写偏差、扩展噪声、延迟成本。
- 结合实践:说“我们用 LLM 改写 + Multi-Query + RRF”。
推荐回答结构
“多轮对话里,用户 query 常有指代、省略、依赖上文,直接检索会失败。所以要改写和扩展。”
“查询改写是把 query 补完整。最简单是拼历史对话,但历史长了有噪声。更好的是用 LLM 做指代消解,把‘它充电快吗’改写成‘iPhone 15 充电快吗’。也可以用专门小模型或对话状态跟踪。改写的关键取舍是效果 vs 成本,以及改写偏差。”
“查询扩展是把 query 铺开。常见有同义词扩展、Multi-Query 生成多个表达、HyDE 用假设答案检索、伪相关反馈。扩展提高召回,但可能引入噪声 query,增加延迟。”
“两者可以结合:先改写补全,再扩展多路。多路检索用 RRF 融合,再 Cross-Encoder 重排序,最后生成。”
“评估上,用 Recall@K、MRR、NDCG 看检索,用 Answer Correctness、Faithfulness 看端到端。对比不改写、改写、改写+扩展。我们实际用 LLM 改写 + Multi-Query + RRF,但会控制扩展数量,避免噪声和延迟。”
加分点
- 提到 指代消解、省略补全、LLM 改写、对话状态跟踪。
- 提到 同义词、Multi-Query、HyDE、伪相关反馈。
- 提到 RRF 融合、Cross-Encoder 重排序。
- 提到 改写偏差、扩展噪声、延迟成本。
- 提到 Recall@K、MRR、NDCG、Faithfulness。
- 结合真实多轮 RAG 经验。
减分点
- 只说“把历史对话拼进去”。
- 分不清改写和扩展。
- 不知道 HyDE、Multi-Query。
- 不提评估和风险。
- 说“扩展越多越好”。
评论专区
评论加载中...登录后即可发表评论