推理模型在问答系统中答非所问的案例屡见不鲜:用户问“苹果手机电池不耐用怎么办”,模型回答“苹果公司最新财报显示营收增长”;用户说“那个地方怎么走”,模型丢出一段旅游攻略。这类错误并非因为模型缺乏语言理解能力,而是查询处理链路没有把用户的原始表述改写成适合推理模型执行的目标形式。回答偏离的深层原因是原始Query与推理模型期望的语义输入之间存在着一条鸿沟,这条鸿沟需要靠Query Reformulation和意图识别来填平。

Query Reformulation的目标是消解自然语言中的模糊性,把用户口语化、省略化、指代化的问句改写成信息完整、语义明确的规范查询。意图识别则进一步把改写后的查询归入具体的意图类别,比如事实型问答、操作指导、对比分析、多跳推理等,并提取关键槽位。两者配合才能在推理模型面前呈现一个干净、可执行的任务描述,而不是一堆需要额外猜谜的原始文本。
一、答非所问的根源:原始Query与推理目标之间的鸿沟
推理模型通常在大规模文本上做过预训练,对自然语言有很强的拟合能力,但这并不意味着它擅长从一句模糊的话里还原用户的真实意图。举个常见例子,用户在多轮对话中先问“iPhone 15的续航怎么样”,得到回答后又追问“那充电速度呢”。第二个问题省略了主体“iPhone 15”,同时隐含了对比意图。如果直接把“那充电速度呢”作为独立Query丢给推理模型,模型很可能回答一个通用充电速度知识,而不是针对iPhone 15的评测数据。
另一个更隐蔽的问题是语义多义和指代不明。例如用户查找技术资料时问“如何在Linux里修改环境变量”,这里的“环境变量”可能指系统级变量、用户级变量或某个shell会话的临时变量,不同层级对应完全不同的配置文件和方法。没有Query Reformulation,模型只能猜一个最常见的方案,而用户实际所处的是容器内仅当前会话有效的场景,答案自然驴唇不对马嘴。意图识别可以进一步区分用户是想要快速操作步骤,还是希望理解环境变量的加载顺序原理,这两者对推理深度和输出结构的要求差异极大。
还有一类答非所问来自槽位缺失。用户问“帮我看看那个服务为什么起不来”,这里的“那个服务”指代不明,也没说明启动环境是Kubernetes、Docker还是裸机。模型只能凭概率回答一个泛泛的排障流程,忽略了用户真正关心的异常日志。Query Reformulation要做的事情就是把缺失的槽位通过对话历史、上下文或主动澄清补全,让推理模型看到的是“Kubernetes集群中nginx-ingress服务在更新配置后无法启动,请分析可能原因并给出排查步骤”。只有拿到这种信息密度,推理模型才能产出对得上的答案。
二、Query Reformulation:把模糊问题改写成可推理的精确问题
Query Reformulation在实现上可以分为基于规则、基于模板和基于生成模型三种路线。基于规则和模板的方法适合领域明确的场景,例如客服机器人可以把“怎么退货”改写成“请说明退换货流程,包括条件、时间和运费承担方”。优点是速度快、可控性强,缺点是扩展性差,面对长尾表达容易失效。基于生成模型的方法则利用大语言模型自身去做改写,输入一条提示词要求模型补齐指代、消除歧义、展开缩写,输出结构化的规范查询。
一个典型的改写提示词可以这样设计:告诉模型原始Query可能存在的省略和指代,要求结合上下文输出完整问题,并保留所有关键信息。例如在多轮对话中,把上下文一并传入,让模型识别出上一轮提到的实体并代入当前问题。下面是一个基于Python调用大模型做改写的示例:
import openai
def reformulate_query(current_query, conversation_history):
prompt = f"""你是查询改写助手。请根据对话历史,把用户当前问题改写成完整、无歧义、适合推理模型理解的规范查询。
对话历史:
{conversation_history}
当前问题:{current_query}
要求:
1. 补齐所有省略的主语、宾语和上下文指代。
2. 消除一词多义,同一实体使用完整名称。
3. 保留用户原始意图,不要增加额外推测。
输出改写后的查询:"""
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0.1
)
return response.choices[0].message.content.strip()
history = "用户:iPhone 15的续航怎么样?\n助手:iPhone 15在标准测试下视频播放可达20小时。"
query = "那充电速度呢?"
print(reformulate_query(query, history))
# 期望输出:iPhone 15的充电速度怎么样?
这个例子里,生成模型自动把“那”替换成了“iPhone 15”,并补全了“充电速度”这个属性。对于更复杂的场景,还可以要求模型输出JSON格式,同时给出改写理由和槽位提取结果。比如用户问“那个红帽的系统怎么装数据库”,改写后的输出可以是{"reformulated_query": "在Red Hat Enterprise Linux上如何安装PostgreSQL数据库?", "filled_slots": {"os": "RHEL", "database": "PostgreSQL"}}。这种结构化输出直接为后续的意图识别和推理提供了可解析的输入。
基于检索增强的改写方法也值得关注。分词后先做指代消解,再通过实体链接把模糊指称映射到知识库中的具体实体,最后套用模板生成规范查询。这种方法在垂直领域准确率很高,但需要维护实体词典和关系映射。实际系统往往把规则和生成式方法混合使用:先跑一轮规则,命中高频缩写和指代就快速改写;规则没命中的再走大模型生成,兼顾响应速度和覆盖率。改写结果一定要经过质量校验,比如检查是否丢失关键词、是否引入了新的歧义,避免把“苹果”这个水果改写成“苹果公司”这种过度推断。
三、意图识别:为推理模型指定正确的推理方向
意图识别是从改写后的查询或原始查询中判断用户究竟想完成什么任务。简单意图可以分成事实查询、步骤指导、原因分析、对比、推荐、计算等几类;复杂场景下还要进一步细分出子意图,并做槽位填充。传统做法是训练一个文本分类模型,输入Query,输出意图标签。但只做粗粒度分类远远不够,因为同一个意图下用户的期望输出形式可能差异巨大。比如“怎么安装Python”和“详细解释pip和conda的区别”都属于指导类意图,但前者需要步骤列表,后者需要对比表格。
更实用的方式是把意图识别和槽位填充联合起来做,输出一个包含intent和slots的结构化对象。举一个多轮对话中的例子:用户先说“部署一个Nginx”,接着说“用HTTPS”。第一轮的意图是deploy_service,槽位包括service=nginx;第二轮的意图是configure_ssl,需要结合上文的service槽位。如果把每一轮Query单独送去分类,第二轮因为没有上下文很容易被识别成general_chat或者security_question,导致推理模型答非所问。所以在做意图识别前先完成Query Reformulation,让模型看到“为Nginx服务配置HTTPS”,意图识别才会稳定。
下面是一个使用简单规则匹配和BERT微调模型混合做意图识别的Python示意:
from transformers import pipeline
intent_classifier = pipeline("text-classification", model="intent-model-finetuned")
def recognize_intent(query):
query_lower = query.lower()
if "怎么安装" in query_lower or "如何部署" in query_lower:
return {"intent": "how_to_install", "slots": extract_service(query)}
result = intent_classifier(query)[0]
return {"intent": result["label"], "slots": []}
def extract_service(query):
services = ["nginx", "mysql", "redis", "postgresql"]
found = [s for s in services if s in query.lower()]
return {"service": found[0] if found else None}
print(recognize_intent("怎么安装Nginx并且配置HTTPS"))
# 期望输出:{'intent': 'how_to_install', 'slots': {'service': 'nginx'}}
实际项目中,意图识别模型需要根据业务数据持续迭代。常见的做法是先收集一批真实用户日志,人工标注意图和槽位,微调一个预训练模型。对于新出现的意图,可以先放到兜底类别,积累一定量样本后再训练。此外,意图识别可以和推理模型共享部分编码层,减少推理时延。如果推理模型本身就是大语言模型,也可以直接在提示词中要求模型输出意图分类结果,比如让模型先回答“用户意图是什么,关键槽位有哪些”,再做后续推理,这种思维链式的做法能有效约束模型行为。
四、落地实践:在RAG与Agent场景中组合Query Reformulation和意图识别
RAG(检索增强生成)系统对查询质量尤其敏感,因为检索结果直接决定了推理模型的输入上下文。如果原始Query带有口语化噪声,向量检索很可能召回无关文档,即使推理模型再强也只能在错误材料上做文章。把Query Reformulation放在检索之前,能极大提升召回的准确率和覆盖率。例如用户问“那个蓝白色logo的数据库咋备份”,改写后变成“MySQL数据库如何备份”,向量检索就能找到准确的官方文档段落。意图识别则帮助RAG系统决定检索策略:事实类问题用密集检索,步骤类问题结合命令示例,分析类问题可能需要多路召回并做重排。
在Agent场景下,意图识别更直接决定了工具调用的方向。一个智能运维Agent收到“把那个跑得慢的服务重启一下”,如果直接调用通用重启工具会非常危险。必须先通过改写补全服务名、环境、集群等槽位,再识别意图为restart_service且属于高风险操作,触发权限确认流程。Agent框架可以在规划阶段把改写后的查询和识别出的意图一并交给推理核心,让模型在执行路径上不迷路。下面展示一个Agent内部的任务分发逻辑:
def dispatch_task(user_query, context):
reformulated = reformulate_query(user_query, context)
intent_info = recognize_intent(reformulated)
if intent_info["intent"] == "restart_service":
confirm_slots = check_missing_slots(intent_info["slots"], ["cluster", "service_name", "environment"])
if confirm_slots:
return ask_user_for_clarification(confirm_slots)
return trigger_restart_with_audit(intent_info["slots"])
elif intent_info["intent"] == "query_metrics":
return build_monitoring_dashboard(intent_info["slots"])
else:
return fallback_chat(reformulated)
组合方案还需要关注延迟和成本。Query Reformulation和意图识别如果都走大模型调用,会增加响应时间和Token消耗。可以设置缓存:对频繁出现的改写结果直接复用,意图识别用轻量级模型本地部署。如果系统要求毫秒级响应,可以先用规则做第一层过滤,只有规则无法覆盖的复杂Query才升级到大模型处理。另外,Rewrite和Intent识别可以并行执行吗?部分可以,但意图识别往往依赖改写后的完整信息,尤其在多轮对话中,所以通常采用串行方式,先改写再识别。
工程实现上,建议把Query Reformulation和意图识别封装成独立的微服务,统一输入输出接口,方便A/B测试和灰度切换。监控指标至少要包括:改写后的查询保留原意的比例、意图识别的准确率、最终答案与用户反馈的一致性。定期抽样人工评估,把答非所问的案例拉出来逐个分析,定位是改写丢信息、意图分错还是推理模型自身能力不足。只有把每个环节的噪声压下去,推理模型才能把注意力放在真正需要深度思考的问题上,而不是浪费在猜测用户到底要什么。
Query Reformulation意图识别问答推理修改时间:2026-09-17 10:19:25