今天,我们就来聊聊让RAG更好用的关键技术:Query Rewrite(查询改写),以及如何写出一个工业级的改写 Prompt。
01 为什么我们需要“翻译官”?
搜索引擎(无论是传统的 Keyword Search 还是现在的 Vector Search)都有一个毛病:它听不懂“人话”,它只信“关键词”和“语义密度”。
用户的输入通常有三个特征:
模糊(Ambiguous): “那个多少钱?”(那个是哪个?)口语化(Colloquial): “网挂了。”(数据库里叫“网络连接中断”。)多意图(Multi-intent): “对比一下 A 和 B。”(需要分别查 A,再查 B。)如果你直接拿用户的 Raw Query 去搜,那就是典型的 Garbage In, Garbage Out。
我们需要用一个 LLM 做中间层,把“用户的嘴”翻译成“机器的脑”。
02 策略一:去口语化与关键词提取
第一种场景,用户说得太随意。我们要让 AI 扮演一个“SEO 专家”。
❌ 用户的输入:
“我的电脑突然蓝屏了,全是英文,动不了,急!”
✅ 我们想要的搜索词:
“Windows 蓝屏死机 BSOD 英文报错 解决方案”
Prompt 写法:
<role>
你是一个搜索引擎优化(SEO)专家。你的任务是将用户的口语化描述,转化为精准的搜索引擎关键词。
</role>
<rules>
1. 去除所有情绪化词语(如“急”、“怎么办”)。
2. 提取核心实体(如“电脑”、“蓝屏”)。
3. 补充专业术语(将“动不了”转化为“死机”或“冻结”)。
4. 输出格式为一行,用空格分隔关键词。
</rules>
<user_query>
我的电脑突然蓝屏了,全是英文,动不了,急!
</user_query>
效果: 这样搜出来的文档,命中率会提升一个数量级。
03 策略二:指代消解(Coreference Resolution)
第二种场景,也是最痛的场景:多轮对话中的“这个”、“那个”。
用户(第一轮): “介绍一下特斯拉 Model 3。”如果你拿“它续航多久”去搜,鬼知道“它”是谁。
这时候,改写 Prompt 的核心任务是“补全上下文”。
Prompt 写法:
<instruction>
你是一个对话上下文补全助手。
用户的最新问题中可能包含代词(如“它”、“这个”)。
请根据【历史对话】,将最新问题改写为一个独立、完整的句子。
如果最新问题已经独立完整,则原样输出。
</instruction>
<history>
User: 介绍一下特斯拉 Model 3。
AI: Model 3 是特斯拉的一款入门级电动轿车...
</history>
<current_query>
它续航多久?
</current_query>
AI 改写结果:
“特斯拉 Model 3 的续航里程是多少?”
这才是数据库能听懂的语言。
04 策略三:多路拆解(Multi-Query)
第三种场景,用户的问题太贪心,一句话里塞了两个任务。
用户输入: “比亚迪汉和特斯拉 Model 3 谁的电池更好?”如果你拿这句话去搜,可能搜不到一篇同时详细讲这两款车电池对比的完美文档。
最好的办法是:先查比亚迪,再查特斯拉。
Prompt 写法:
<task>
你是一个查询分析器。用户的问题可能涉及多个实体或多个方面。
请将用户的问题拆解为 2-3 个独立的、简单的搜索查询(Sub-Queries)。
输出格式:JSON 列表。
</task>
<user_query>
比亚迪汉和特斯拉 Model 3 谁的电池更好?
</user_query>
AI 输出结果:
[
"比亚迪汉 电池技术参数 刀片电池",
"特斯拉 Model 3 电池类型 续航表现",
"比亚迪汉 vs 特斯拉 Model 3 电池评测对比"
]
然后在后台,我们会并发执行这 3 次搜索,把结果汇总后再喂给模型。这叫 Query Expansion(查询扩展)。
05 一个工业级的“全能改写” Prompt
在实际工程中,我们通常不会写三个 Prompt,而是把这些逻辑封装在一个结构化 Prompt 里。
拿去即用,不谢:
### Role
你是一个查询重写专家,负责将用户的输入转化为向量数据库能理解的精准查询。
### History Context
{{chat_history}}
### User Input
{{user_input}}
### Instructions
1. **消歧义**:如果用户输入包含代词(它/这),请根据 History 替换为具体实体。
2. **去噪**:去除“帮我查一下”、“我想知道”等无意义的引导词。
3. **关键词化**:将口语转换为专业术语(例:将“连不上网”转换为“网络连接故障”)。
4. **多视角扩展**:如果问题复杂,生成 3 个不同维度的搜索词(一个是精准匹配,一个是语义扩展,一个是问题拆解)。
### Output Format
请直接输出 JSON 格式,不要包含任何解释:
{
"rewritten_queries": [
"查询1",
"查询2",
"查询3"
]
}
写在最后
做搜索和 RAG,功夫在诗外。
当你发现检索效果不好的时候,不要一上来就去调向量模型(Embedding Model),也不要去死磕知识库的切片(Chunking)。
先看看你的输入端。
把那句模糊的“人话”,翻译成精准的“机器话”,往往是 ROI(投入产出比)最高的优化手段。
Prompt 是一座桥。
左边是用户混乱的思绪,右边是数据库严谨的索引。
你的工作,就是把这座桥搭好。