首页/AI/RAG 与向量库速查/多轮对话的查询改写

多轮对话的查询改写

多轮场景中用户问题常含指代与省略(“它”“那个报错”):先按会话历史把问题改写成自包含查询再检索;改写质量直接决定检索命中,改写版本要纳入日志与评测。

RAG 与向量库速查AI更新于 2026-10-13

多轮查询改写是什么

多轮对话里用户很少把问题说完整:常见“那它呢”“这个报错怎么处理”,句子依赖上文才能理解。查询改写先用最近若干轮对话把当前问题补全成一个自包含的问句,再拿这个问句去检索。改写质量直接决定检索命中率,因为向量库只认查询文本,指代词与省略成分会让检索器完全抓不到主题。改写结果与原问题都要写进日志,否则排查“为什么没检索到”时无从下手。

基本信息

输入最近 1-2 轮对话 + 当前问题
输出无指代、可独立检索的完整问句
历史窗口按 token 预算裁剪,越近的轮次权重越高
实现方式小模型或主模型做改写,也可用规则兜底
失败表现改写跑题或过度扩写,检索到无关文档

典型使用场景

  • 客服问答:用户连续追问同一工单的不同细节,第二轮起必须补全上下文实体
  • 技术文档助手:用户先问某个组件,再问“它的默认端口是多少”
  • 多轮改写与检索合并:把历史拼进查询文本一起向量化,省一次生成调用
  • 改写质量监控:抽样比对改写前后检索命中率,判断改写是否真的起作用
  • 闲聊兜底:识别出无需检索的追问,直接走对话链路省一次检索

改写与检索流程

改写与检索流程
def retrieve_for_turn(history, question):
    if is_standalone(question):                 # 已是完整问句,跳过改写
        stand_alone = question
    else:
        stand_alone = llm_rewrite(history[-2:], question)
    hits = retriever.search(stand_alone)
    log(question, stand_alone, [h.id for h in hits])   # 两个查询都留痕
    return hits

改写提示词要点

改写提示词要点
把用户最新问题改写为不含指代、可独立检索的问题;
保留专名、型号与数字;不添加原问题没有的条件;
只输出改写结果,不要解释过程。

常见改写错误与表现

错误表现处理
漏补实体改写后仍含“它”,检索结果泛化提示词要求逐项检查指代
过度扩写加入原问题没有的限定词,召回变窄限制只做补全不做推测
串话题把上一轮的旧主题带进本轮缩小历史窗口,只取近 2 轮
无谓改写完整问句被改写后反而变差先判断是否已自包含,能跳过就跳过
改写本身是一次生成调用,会增加延迟与成本:高频简单问题可先用规则判断是否已自包含,命中就跳过改写。改写的提示词版本也要记录,出问题时能区分是提示词变更还是数据变更。

易错点

  • 把整段历史直接丢进检索,模型被历史话题带偏,当前问题反而检索不到
  • 历史无限增长导致改写提示词超出预算,最后几轮对话被截断
  • 改写后不记录原问题,线上排查只能看到一个面目全非的查询
  • 改写会补全专名,但补错版本号或型号,检索到另一份文档
  • 把改写固定成大模型调用,高峰期延迟叠加,整体响应时间不可控

数据来源与参考

  • LangChain 官方文档(Conversational RAG / 查询改写)
  • Gao et al., RAG for LLMs: A Survey(多轮场景)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌