人人都会AI编程

历史问题补全

更新时间:2026-07-12

在单轮问答中,用户的问题通常是完整的,比如“公司的出差报销流程是怎样的?”系统可以直接拿去检索。但在真实对话场景下,用户往往会连续追问,问题变得简略且依赖上下文:

  • “那住宿标准呢?”
  • “有没有时间限制?”
  • “国外出差也一样吗?”

如果把这些原样问题直接送入检索,向量相似度搜索很难将它们与知识库中的文档片段匹配起来。因为检索器看到的是一个孤立的、语义残缺的句子,不知道“那”指代什么、“国外出差”的前置条件是什么。结果往往是召回一堆无关内容,最终回答答非所问。

历史问题补全要解决的就是这个问题:把用户在对话中的简略提问,还原成一个自包含、无需依赖历史即可理解的完整问题,再拿去检索。 这相当于把多轮对话中的“半句话”补全成“整句话”,让检索器能够正常工作。

常见实现思路

用得最多、成本也最可控的做法,是用一个轻量化的补全指令调用大模型。提前把最近几轮对话记录整理好,连同当前用户的简略问题一起送给模型,要求它输出补全后的完整版本。模型的角色只是改写,不负责回答事实,因此幻觉影响较小。

一个典型的补全提示可以像这样:

你是一个将对话中的简略提问改写成完整问题的助手。请根据对话历史,把用户的最新提问补充成一个独立清楚的完整问题,不要添加额外信息。

对话历史:
用户:出差能报销哪些费用?
助手:交通、住宿和餐饮都可以按规定报销。
用户:住宿有上限吗?
助手:一线城市每晚不超过500元。
用户:那餐饮呢?

完整问题:

模型输出:“出差期间的餐饮费报销标准是什么?”这个完整问题,就可以正常进入检索流程了。

也可以采用更轻量的规则方法,比如通过指代消解替换“它”“这个”为前文实体,但这通常覆盖不全,不够灵活。实践中使用小型、低成本或者本地部署的模型完成补全已经足够,延迟增加也微乎其微。

几个实用细节

  • 历史窗口要适度。只保留最近 3~5 轮对话即可,过长反而容易引入无关上下文,让补全偏离当前关注点。
  • 保留原始语句作为辅助。即使有了补全问题,仍可以将原始问题作为检索的辅助信号,比如将两个向量做加权融合,或用原始问题做关键词匹配,防止补全过程过度曲解用户意图。
  • 补全结果可缓存。如果用户连续两次输入同样简略问句(如重复“那价格呢?”),可以直接复用上一次的补全结果,避免重复调用模型。
  • 处理补全失败。如果模型无法根据历史确定补全内容(比如历史对话不相关),最稳妥的做法是原样使用用户输入进行检索,并在回答时请求用户澄清,而不是强行编造。

实际效果感受

在我们部署过的企业问答助手中,启用历史问题补全后,多轮追问场景下的检索命中率提升了大约 20%~30%。用户体验改善尤其明显:不再需要每次都把问题说得像第一次提问那样完整,对话更接近人与人之间的自然交流。

这种补全方法实现简单、开销极小,却能有效弥补检索式系统在多轮对话中的短板,是让 RAG 方案真正“能聊下去”的关键一环。