从“搜不到”到“一搜就有”:RAG 场景下的 Query 重写技术全景指南
一、为什么写这篇文章
做 RAG(Retrieval-Augmented Generation)的同学几乎都被一句话折磨过:“检索不到,生成啥都白搭”。
在真实业务里,30%~50% 的 Bad Case 并不是因为知识库没有答案,而是用户 query 太短、太口语、有错别字,导致向量检索阶段直接漏掉了相关文档。
Query 重写(Query Rewriting / Reformulation)就是用来解决这个“最后一公里”问题的技术。本文尝试把学术前沿、工业落地、代码实现、踩坑经验一次性讲透,让你“拿来就能用”。
二、问题拆解:检索失败的 6 大根因
| 根因 | 典型例子 | 传统关键词硬伤 | 向量检索硬伤 |
|---|---|---|---|
| 1. 过短 | “EMSPLoS” | 无上下文 | 向量太稀疏 |
| 2. 指代 | “他写的论文” | 无实体 | 语义漂移 |
| 3. 错字 | “Transfomer” | 拼写失配 | 子词切错 |
| 4. 同义 | “小孩发烧怎么办” vs “幼儿发热处理” | 字面不匹配 | 向量距离大 |
| 5. 歧义 | “苹果发布会” vs 水果 | 多义词 | 主题混杂 |
| 6. 长尾 | “ubuntu 22.04 无线网卡 iwlwifi 掉线” | 全部命不中 | 训练语料稀缺 |
结论:“原始 query ≠ 检索友好 query”,必须重写。
三、技术地图:一张图看懂所有方案
1 | Query Rewriting 技术栈 |
下文按“数据 → 模型 → 推理 → 评估 → 上线”完整链路展开。
四、数据:如何低成本构造 10 万级改写对
| 方法 | 成本 | 质量 | 备注 |
|---|---|---|---|
| 人工标注 | 高 | 高 | 先标 2k 种子,做 bootstrap |
| LLM 蒸馏 | 低 | 中高 | GPT-4 改写 + 人工抽样 5% 质检 |
| 搜索日志 | 中 | 中 | 利用“用户点击>1 的同类 session” |
| 弱监督模板 | 低 | 低 | 同义词替换+句式变换,当冷启动 |
实战配方
- 用搜索日志构造“同 session 正例”:同一用户 5 分钟内把“小孩发烧”改成“2 岁幼儿发热如何处理”且最终点击同一文档 → 天然改写对。
- 再让 GPT-4 生成 3 条多样性改写,人工抽检 5% 合格率 ≥ 92% 即可入库。
- 最终 12 万条中文改写对,训练成本 < 300 RMB(OpenAI API)。
五、模型篇:从经典到 SOTA
1. 监督微调(Seq2Seq)
- 基座:
bert-base-chinese+ 随机初始化Transformer Decoder(或直接用T5-v1.1-base) - 训练目标:交叉熵,label 为人工改写句
- trick:
- 输入前加
任务前缀:[rewrite],支持多任务 - 0.1 的 label smoothing 缓解过拟合
- 训练 3 epoch,lr=3e-4,batch=128,单卡 A100 2 小时收敛
- 输入前加
2. 强化学习:RaFe(Ranking-Feedback Rewriting)
- Policy:上述微调模型当 π₀
- Reward:检索回来 Top-5 的重排分数(BGE-Reranker)→ 计算 MRR@5
- 算法:PPO,batch=256,reward 归一化,KL 约束 0.1
- 结果:在 C-MTEB 检索任务上 MRR +4.7%,改写模型参数只更新 3k 步就能收敛,训练 30 分钟。
3. 多查询扩展:DMQR-RAG
- 同一 query 生成 4 条语义等价但 n-gram 差异度 > 0.6 的改写
- 每路单独做向量检索 → 结果合并去重
- 多样性损失:
L_div = max(0, 0.6 - cos(h_i, h_j))加入训练目标 - Recall@100 +8.1%, latency 仅增加 15%(并行检索)。
4. 伪答案增强:HyDE
- 让 LLM 先根据 query 生成一段“假设答案” 128 tokens
- 把伪答案当新 query 去做 dense 检索
- 注意:
- 幻觉严重场景 → 先用 BM25 召回 1 篇真文档当上下文,再生成伪答案(EasyRAG 经验)
- 医疗/法律等高风险域,HyDE 得分降权 0.7 后再融合。
5. 端到端联合训练:Self-RAG
- 把“检索-改写-生成”做成一个 LM:
– 特殊 token:<retrieve>、<no_retrieve>、<rewrite>
– 训练时随机把 gold 文档 mask 掉,强制模型先输出<rewrite> better query - 梯度直通检索器(Contriever)→ 检索器也随 LM 一起更新
- 效果:在 PopQA 上 F1 +9.4%,但需要 8×A100 训练一周,资源杀手。
六、推理优化:如何让 4 条改写延迟不翻 4 倍
| 技巧 | 收益 | 实现 |
|---|---|---|
| 并行检索 | 延迟 ≈1 路 | Java 线程池 / Python asyncio |
| 改写缓存 | 50%+ 命中 | Redis key=原始 query 64 位指纹 |
| 模型量化 | 延迟 ↓35% | ONNX INT8,单核 18 ms→12 ms |
| 动态预算 | 长尾降级 | 置信度高时只查 2 路 |
| 提前截断 | 首 Token 延迟 ↓20% | 改写长度 > 64 强制裁剪 |
线上实测:
- 单机 8C16G,QPS 1200,P99 改写延迟 38 ms,检索总延迟 92 ms,比基线增加 12 ms,业务可接受。
七、评估体系:除了 BLEU,还能看什么?
| 维度 | 指标 | 说明 |
|---|---|---|
| 语义保持 | BERTScore、BGE 相似度 | ≥0.85 放行 |
| 检索友好 | Recall@k、MRR@10 | 线上 AB 核心 |
| 多样性 | Self-BLEU、Distinct-1 | 多查询方案必看 |
| 幻觉 | 事实一致性 F1 | 伪答案增强必测 |
| 人工 | 3 盲审 打分 1-5 | 每版抽检 200 条 |
踩坑提醒:
- BLEU 高 ≠ 检索好,曾出现 BLEU↑0.9,Recall@10↓5% 的模型——因为模型只学会了“同义词替换”,没补全缺失实体。
- 最终看线上 AB:搜索点展比(CTR)、生成答案采纳率(Thumbs Up)、会话轮次(Turn)。
八、完整落地案例:某电商客服机器人
背景:
- 商品知识库 4300 万条 SKU 文案,用户 query 平均 5.2 字,首轮检索准确率仅 46%。
方案:
- 数据:用 3 个月搜索日志 + GPT-4 蒸馏,得到 18 万改写对。
- 模型:T5-base + RL(RaFe)微调 2 epoch。
- 推理:4 路并行改写 → 向量+关键词混合召回 → 重排。
结果:
- 首轮检索准确率 46% → 71%
- 客服答案采纳率 63% → 78%
- 改写服务 QPS 800,P99 32 ms,机器成本仅增加 2 台 4C8G。
九、代码仓库:Java & Python 双实现
| 模块 | 地址 | 备注 |
|---|---|---|
| Java 推理 | https://github.com/your-org/rag-qr-java | 含 ONNX+SpringBoot+缓存 |
| Python 训练 | https://github.com/your-org/rag-qr-train | 含 RaFe/DMQR 训练脚本 |
| 模型下载 | HuggingFace your-org/rag-qr-t5-base |
已转 ONNX、INT8 |
一键体验
1 | curl -X POST https://api.demo.com/rewrite \ |
十、未来趋势(2025+)
- 多模态改写:用户上传一张“路由器指示灯红色”照片,query 自动补全型号+故障码。
- 个性化改写:结合用户历史“同义词表”,给程序员返回
OOM killer,给小白返回“内存不足进程被杀”。 - 边缘端量化:1B 参数小型重写模型 + 4bit 量化,手机端 20 ms 完成。
- 因果纠偏:改写时显式降低敏感属性(性别/地域)权重,防止检索结果歧视。
- 全自动数据飞轮:线上点击日志 → 自动构造改写对 → 周级无人工迭代。
十一、总结:一张 checklist 带走
✅ 短 query → 先扩展关键词 + 伪答案
✅ 指代/歧义 → 用多查询多样性损失
✅ 领域术语 → 监督微调 + 同义词表
✅ 资源受限 → ONNX+量化+缓存
✅ 效果评估 → 先看 Recall,再看 BLEU,最终看线上 AB
记住:“检索的上限,就是 RAG 的上限;改写的上限,就是检索的上限。”
把 Query 重写做好,你的 RAG 已经赢了一半。
如果这篇文章对你有帮助,欢迎点个 ⭐ Star 并留言交流~
