← RAG 检索增强

多轮对话里用户问“那它呢”,RAG 检索前怎么做指代消解?

中等 查询改写 · 第 2 / 2 问 更新于 2026/09/29
RAG查询改写指代消解多轮对话
本题落地项目AI Agentic RAG高级企业知识库平台

简化版

多轮对话里,第二轮之后的问题经常省略主语、用代词指代前文,比如「那超期了呢」「它支持私有化吗」,直接拿去检索几乎等于随机。做法是检索前带上最近几轮对话历史,让模型把当前这句改写成一个不依赖上下文、能独立理解的完整问题(也叫 Query Condensation),再用它去检索。要点有四个:第一轮没有历史就跳过;历史只取最近几轮;模型返回空或跑偏时退回原问题;改写结果只用于检索,不当事实,也要记录下来方便排查。

详细版

处理流程:

  1. 判断有没有历史:第一轮直接用原问题检索,不做无谓的模型调用;
  2. 取最近几轮对话,按「用户:…… / 助手:……」的格式拼成历史;
  3. 用专门的改写模板,要求模型只输出改写后的完整问题,不回答、不解释;
  4. 校验输出:为空就退回原问题,并去掉模型偶尔加上的前缀;
  5. 用改写后的问题去检索,把改写结果和检索结果一起记入日志。

和其他改写方式的区别:多查询扩展要保留原问题一路兜底,而指代消解的原问题本身没有信息量,检索只用改写后的那一条。

完整版教学

一、为什么「那它呢」不能直接检索

看一段真实的多轮对话:

用户:GTE-3000 的保修期是多久?
助手:GTE-3000 整机保修 24 个月。
用户:那超期了呢?

第三句拿去检索,送进向量模型的只有「那超期了呢」5 个字:没有型号,没有「保修」这个主题词。向量检索编码出的向量指向不明,召回的可能是任何提到「超期」的片段,比如逾期付款、借阅超期;BM25 能匹配上的只有「超期」一个词,同样找不准。

多轮对话里,第二轮之后的问题大多不能直接拿去检索。 它们的完整含义分散在历史里,检索器看不到历史。

二、指代消解要产出什么

目标是把当前问题改写成一个独立问题(standalone question):只看这一句,不看历史,也能知道在问什么。

原问题历史里的关键信息改写后
那超期了呢?GTE-3000、保修期 24 个月GTE-3000 超过 24 个月保修期后如何处理?
它支持私有化吗?上一轮在聊「企业版」企业版是否支持私有化部署?
第二种方案呢?上一轮列出了三种部署方案第二种部署方案(容器化部署)的具体要求是什么?

注意改写和回答是两件事:改写只负责把问题补完整,不能顺手把答案写进去。一旦模型在改写里写上「超期后收费维修」这样的推测,检索就会朝着这个推测去找,结果被带偏。

三、改写模板怎么写

一个可用的模板:

下面是一段对话历史,请把用户最后这句话改写成一个不依赖上下文、可以独立理解的完整问题。
只输出改写后的问题本身,不要输出任何解释。

对话历史:
用户:GTE-3000 的保修期是多久?
助手:GTE-3000 整机保修 24 个月。

用户最后这句话:那超期了呢?

三个细节:历史要标明「用户」和「助手」,模型才分得清谁说了什么;明确要求只输出问题本身,否则模型常会加上「改写后的问题是:」这类前缀;不要求模型回答,避免把推测混进检索词。

四、历史取几轮

历史不是越多越好:

取的历史好处问题
最近 1 轮最快、最省 Token用户跨两轮指代时补不全,比如「回到刚才那个型号」
最近 3 轮(6 条消息)覆盖大多数指代多一点 Token,一般可以接受
全部历史信息最全越聊越长,改写越来越慢,早期话题还会干扰当前问题

按每轮对话 200 字估算,3 轮历史约 1200 字,加上模板本身,改写一次的输入在 1500 字左右;如果带上 20 轮完整历史,就要 8000 多字,而其中大部分和当前问题无关。取历史时要注意拿的是最近的几条:按时间倒序取、再反转成正序,而不是取出最早的几条。

易错点:历史取得越多,不只是成本变高,模型也更容易把早期话题里的实体错误地套到当前问题上。

五、什么时候跳过,怎么兜底

指代消解要多调一次模型,通常几百毫秒,所以要避免白调:

  • 第一轮没有历史,直接用原问题检索;
  • 模型返回空字符串,退回原问题,不能让检索拿着空字符串去跑,向量模型编码空文本要么报错、要么返回无意义的向量;
  • 模型输出带了编号、引号或说明文字,先清洗再用;
  • 改写结果明显偏离,比如出现了历史和当前问题里都没有的实体,可以丢弃改写结果、退回原问题。

六、要不要保留原问题一起检索

多查询扩展会把原问题放在第一条,和改写出的几条一起检索,原因是扩展可能跑偏,原问题是兜底。指代消解的情况不一样:

多查询扩展   原问题「能装在自己机房吗」本身有完整含义 → 保留,作为兜底
指代消解     原问题「那超期了呢」本身没有信息量       → 保留它只会引入噪声

所以指代消解一般只用改写后的问题检索,靠第五节的兜底规则应对改写失败。反过来,如果用户的追问本身就是完整的(比如「GTE-5000 的保修期呢」),模型改写后的问题和原问题几乎一样,这一步也不会造成损失。

七、改写结果怎么用、怎么查

改写后的问题只用于检索。生成答案时,仍然要把原问题和对话历史交给模型,让回答自然地衔接上下文,而不是生硬地复述改写句。

排查问题时,改写结果是第一个要看的地方:检索结果不对,先看改写有没有把问题补对。所以每条回答都应该记下「实际拿去检索的问题」,评测时也可以专门准备一批多轮对话用例,检查改写后的问题是否完整、是否引入了不存在的信息。

八、常见误区与追问

  • 误区:把全部对话历史拼进去一起检索就行。 历史里大量内容和当前问题无关,拼进检索词会稀释语义,还会让检索命中早期话题的片段。
  • 误区:改写时顺便让模型把答案写出来。 改写只负责补全问题,一旦混进模型的推测,检索会朝着推测的方向找,结果被带偏。
  • 误区:指代消解也要保留原问题一路兜底。 「那超期了呢」本身没有信息量,保留它只会引入噪声;兜底应该放在「改写为空或明显跑偏时退回原问题」上。
  • 误区:每一轮都要做指代消解。 第一轮没有历史,白调一次模型只是多花几百毫秒和一次调用额度。
  • 误区:历史取得越多,改写越准。 历史越长越慢,早期话题里的实体还可能被错误地套到当前问题上,一般取最近几轮就够。
  • 追问:指代消解和多查询扩展能不能同时开? 可以组合,但检索次数会继续翻倍,而且两者产出形态不同,工程上常做成单选,先用评测数据确认哪种对自己的场景更有效。
  • 追问:生成答案时用改写后的问题还是原问题? 检索用改写后的问题;生成时仍然给模型原问题和对话历史,回答才能自然衔接上下文。

九、加强记忆

多轮对话的追问往往缺主语、靠代词,「那超期了呢」拿去检索等于随机,所以检索前要先做指代消解:带上最近几轮「用户 / 助手」格式的历史,让模型只输出一个不依赖上下文的完整问题,不回答、不解释。四条规则记住:第一轮没历史就跳过,历史只取最近几轮并按时间正序排好,模型返回空或跑偏就退回原问题,改写结果只用于检索并记入日志。和多查询扩展不同,指代消解的原问题没有信息量,检索只用改写后的那一条;生成答案时仍用原问题加历史,回答才自然。

项目实战落地

项目里怎么做的

《AI Agentic RAG高级企业知识库平台》把指代消解做成查询改写的三种方式之一,检索策略里把 rewrite_type 选为「指代消解」即可启用:

  • 改写模板。 Prompt 模板 COREFERENCE_RESOLVE 在后台维护:「下面是一段对话历史,请把用户最后这句话改写成一个不依赖上下文、可以独立理解的完整问题。只输出改写后的问题本身,不要输出任何解释。」
  • 历史来源。 多轮问答时从当前会话取最近几条消息,条数由问答应用上的 max_history 控制,默认 6 条;历史按「用户:…… / 助手:……」拼进模板。
  • 跳过与兜底。 没有历史时直接返回原问题,不调模型;模型返回空内容时退回原问题。
  • 只产出一条查询。 和多查询扩展返回多条不同,指代消解只返回改写后的一条,拿它走完整的混合检索链路。
  • 留痕。 每条回答的消息记录里存下实际拿去检索的问题 rewritten_query,排查时能直接看到改写结果。

为什么这样取舍

  • 改写方式做成单选。 三种改写的产出形态不同,叠加起来检索次数会继续翻倍,开哪一种由评测数据决定。
  • 历史条数配在问答应用上。 不同应用的对话习惯不一样,客服类对话追问多,内部知识库问答单轮居多。

面试官还会追问

  • 从会话里取「最近几条」历史消息时,为什么要按 id 倒序取出来再反转?
  • 开了 Agentic 模式后,指代消解在状态图的哪一步做?召回不相关、回到改写节点重试时还会再做一次指代消解吗?

学完《AI Agentic RAG高级企业知识库平台》,上面这些追问你都会迎刃而解。

本题落地项目地狱锤炼AI Agentic RAG高级企业知识库平台基于企业知识库、PGVector 向量检索、Agentic RAG、FastAPI + LangGraph、Function Calling,实现向量 + BM25 混合检索与 RRF 融合、Rerank 重排、HyDE 与多查询改写、父子分块召回、LangGraph 状态图自适应检索、Agent 执行时间线和 LLM-as-judge 四指标评测,覆盖从基础 RAG 到高级 RAG 调优的完整闭环。FastAPILangChainLangGraphRAGPGVector源码+SQL喂饭学习教程配套面试文档环境安装文档项目运行文档 学习这个项目