检索效果很大程度上取决于用户提问的质量。实际场景中,用户输入往往简短、口语化,甚至缺少关键上下文,直接使用原始问题检索容易“搜不到”或“搜不准”。查询改写就是针对这一痛点,在检索前自动优化用户的提问,让检索更鲁棒、更全面。
1. 为什么需要改写查询
用户不会像写搜索代码一样提问,常见问题包括:
- 表述模糊:“那个政策怎么说的?”——缺少具体指代。
- 用词不一致:用户说“降薪”,知识库中写的是“薪酬调整”。
- 问题过于宽泛:“介绍一下产品。”——实际可能是想了解价格、规格或保修。
- 多意图混合:“支持哪些支付方式,退货怎么处理?”——一次问了两件事。
直接用原始提问去向量检索,很容易因为用词不匹配或者语义分散而召回无关内容。查询改写就是在这一步充当“翻译官”,把用户问题转换成更适合检索的形态,从而提升召回质量。
2. 问题扩展:补全语义,丰富检索维度
问题扩展的核心思路是,给原始问题补充背景、同义词或相关概念,让生成的检索查询更“充实”,增加命中相关文档的机会。
实现方式
- 基于大模型生成扩展:将原始问题送给 LLM,配合提示词要求生成更详细、更明确的版本。例如:
- 原始问题:“年假怎么算?”
- 改写后:“根据员工手册,年假天数如何根据工龄计算?未休完的年假如何处理?”
- 同义词替换与领域术语映射:维护一个领域词表,将用户用词映射为知识库中的标准术语。比如将“退出”映射为“离职”,“赔钱”映射为“理赔”。
- 混合历史上下文:在多轮对话中,将上一轮的问题和回答作为背景拼入当前问题,形成完整的检索条件,避免指代不明。
实际效果
问题扩展后,检索 query 更接近知识库中文本的表达方式,提高了向量相似度计算的准确性。尤其在用户输入极其简短(如“报销标准”)的情况下,扩展能大幅减少零召回或低相关度召回的情况。
注意点
- 不要过度扩展导致 query 臃肿、噪声增加,一般控制在 1~3 句话以内。
- 对于意图本身清晰、用词精准的问题(如“X200 型号重量”),扩展反而可能引入歧义,可先判断问题复杂度再决定是否改写。
3. 多查询生成:打出一套检索“组合拳”
有些问题很难用一个查询覆盖所有相关方面。多查询生成的做法是,从一个用户问题出发,生成多个不同视角的检索语句,然后合并各查询的结果,去重后一起作为候选片段。这相当于对问题进行“分解”或从多个侧面去搜索。
典型场景
- 复杂问题:“公司对新员工的培训计划和考核标准是什么?”
可以拆解为:
- “新员工培训计划包括哪些内容?”
- “新员工考核标准及通过条件”
- “试用期考核流程”
- 角度互补:“这个产品适合什么人用?”
可生成:
- “产品目标用户群”
- “产品适用场景”
- “用户评价与案例”
实现方式
最直接的方法是用 LLM 根据原始问题生成多个检索查询。提示词可以设计为:“请将以下问题拆解为 2~3 个更具体的子问题或不同表述方式,目的是从不同角度进行信息检索:{用户问题}”。
得到多个子查询后,分别到向量库中检索,将各子查询的 top‑k 结果汇集、去重,再按相关度排序或直接送入生成阶段。
实际效果
这种“打组合拳”的方式,明显提升了那些需要综合多份文档才能完整回答的问题的覆盖度。比如政策类问题可能分散在总则、细则和补充通知中,单个查询很难同时命中,多查询能有效捞出不同章节的内容。
实现建议
- 子查询数量不宜过多,一般 2~4 个即可,避免过度消耗检索资源。
- 结果合并后,注意相同片段去重,防止多次出现的片段过度影响生成权重。
- 可结合相关性分数或片段位置,对合并结果重新排序,确保最重要的信息排在前面。
4. 实用策略小结
在实际搭建中,查询改写可以作为一个轻量的前置模块,串接在检索之前。下面是几个实用的实施原则:
- 按需触发:并非所有问题都需要改写。可先用规则或轻量模型判断问题是否过于简短、含混,再决定是否启用改写。
- 改写记录:保留改写过程的日志,便于追溯问题理解是否正确,也方便后续调优。
- 与用户澄清结合:在关键业务场景,如果改写后检索的相关度仍然很低,可回退为反问用户进行澄清,而不是强行给一个可能错误的答案。
查询改写虽然没有引入新的数据库或模型架构,但它是打通“用户自然表达”和“系统精准检索”的重要润滑剂,往往能以极低成本换来检索点击率的明显提升。