RAG 改写与 Prompt 链路
RAG 查询改写与检索后 Prompt 的端到端链路
原题:在RAG系统中,请详细说明query改写的策略方法,以及检索到相关文档后如何构建有效的提示词来生成最终答案。
Prompt工程 · 百度真题
30 秒回答
- query改写的常见策略(扩展、分解、澄清、假设文档嵌入)
- 提示词构建的核心要素(系统指令、上下文组织、引用标注、不确定性处理)
- 实际工程中的权衡取舍(延迟vs质量、成本vs覆盖)
回答与解析
答案要点
- query改写的常见策略(扩展、分解、澄清、假设文档嵌入)
- 提示词构建的核心要素(系统指令、上下文组织、引用标注、不确定性处理)
- 实际工程中的权衡取舍(延迟vs质量、成本vs覆盖)
一、Query改写策略
1. 查询扩展(Query Expansion)
- 同义词/近义词扩展:用LLM生成语义等价表述,提升召回率
- HyDE(假设文档嵌入):让模型先写"理想答案",用答案去检索而非原始query
- 子查询生成:将复杂问题拆为多个子问题并行检索,适合多跳推理场景
2. 查询分解(Query Decomposition)
- 把"比较A和B的优缺点"拆成" A的优点是什么" + "B的优点是什么"
- 每个子查询独立检索,最后合并结果
3. 查询澄清(Query Clarification)
- 当query模糊时,先让模型生成澄清问题,获取用户反馈后再检索
- 适合对话式RAG,首轮交互确定意图
4. 伪相关反馈(Pseudo-Relevance Feedback)
- 首轮检索Top-K结果,提取关键词扩展原query,做二次检索
二、提示词构建要点
1. 上下文组织
- 按相关性排序文档,高分在前
- 去重:相同内容只保留一份
- 截断策略:优先保留开头/结尾,中间用"..."省略
- 元信息标注:来源、时间、可信度分数
2. 核心指令设计
- 引用要求:强制模型标注答案来源,如"根据[1]..."
- 不确定性处理:明确指令"若文档不足以回答,请说明"
- 冲突处理:"若文档信息矛盾,列出不同观点并说明依据"
3. 结构化模板示例
【系统指令】
你是一个严谨的问答助手,请基于提供的参考资料回答,必须标注引用。
【参考资料】
[1] {doc_content} (来源: {source}, 日期: {date})
[2] ...
【用户问题】
{original_query}
【要求】
- 直接回答,不要复述问题
- 不确定时明确说明
- 引用格式:[编号]
4. 进阶技巧
- 重排序提示:把检索分数作为文本提示注入,帮助模型判断可信度
- 动态上下文:根据query类型选择不同提示模板(事实型/观点型/计算型)
- 负样本提示:主动告知"以下文档与问题无关,请忽略",过滤噪声
三、工程权衡
| 策略 | 收益 | 成本 |
|---|---|---|
| HyDE | 召回+15-20% | 多一次LLM调用 |
| 查询分解 | 多跳问题准确率提升 | 延迟×N,需并行化 |
| 长上下文重排序 | 答案相关性提升 | 受限于模型长度 |
实际落地中,建议先做离线评测确定改写策略的收益,再逐步上线;提示词用A/B测试验证不同指令模板的效果。
口语版讲法(约4分钟)
- query改写本质是弥合用户表达与文档表达之间的语义鸿沟
- 改写策略要按场景选,实际落地常是组合拳
- 提示词构建的核心是让模型知道怎么用文档、怎么处理不确定性
- 工程上要权衡收益与成本,先离线验证再上线
这道题问的是RAG系统里两个关键环节:一是怎么把用户的问题改得更适合检索,二是拿到文档后怎么组织提示词让模型好好回答。说白了,query改写的本质是弥合用户表达和文档表达之间的语义鸿沟,而提示词构建的核心是教会模型怎么用文档、怎么处理不确定性。
先说query改写。常见策略其实分几类,但真正落地你会发现很少只用一种,往往是组合着来。比如查询扩展,最简单的是用LLM生成同义词或近义词,把“退款流程”扩展成“退货退款步骤”“取消订单退钱”之类的,这样能提升召回。更高级一点的是HyDE,就是让模型先基于问题写一段“理想答案”,然后用这段答案去检索,而不是用原问题。这个在文档表述和用户问法差异大的时候特别有效。再一个就是查询分解,比如用户问“比较A和B的优缺点”,我会拆成“A的优点”“A的缺点”“B的优点”“B的缺点”四个子查询,分别检索再合并。这个适合多跳推理场景。另外还有查询澄清,当用户的query特别模糊,比如只说了“这个功能怎么用”,我会先让模型反问一下“您指的是哪个功能?”,等用户明确后再检索,这在对话式RAG里很实用。
这里有个边界要注意:HyDE适合语义差异大的场景,但代价是多一次LLM调用,如果系统对延迟敏感,可能就不合适。查询分解虽然能提升多跳问题的准确率,但子查询之间可能有信息重叠,需要去重,而且延迟会乘以N倍,所以必须并行化。真正落地时,我通常会根据业务场景选主策略,再辅以其他策略。举个例子,在客服退款场景里,用户可能说“我前天买的那个东西坏了”,这个query很模糊,我会先用查询澄清确定订单,然后用查询扩展把“坏了”扩展成“破损”“不工作”“有瑕疵”等,再检索。
说完改写,再讲提示词构建。拿到相关文档后,怎么组织成有效的提示词?核心是三点:上下文组织、指令设计、还有不确定性处理。上下文组织上,我会按相关性排序,高分在前,并且去重,相同内容只保留一份。如果文档太长,我会优先保留开头和结尾,中间用省略号,因为很多模型对中间内容的注意力较弱。元信息比如来源、时间、可信度分数也要标上,帮助模型判断。
指令设计上,我一般会强制要求模型标注引用,比如“根据[1]”,这样能减少Hallucination。同时明确告诉模型,如果文档不足以回答,就说不知道,不要编。如果文档信息矛盾,要列出不同观点并说明依据。这里有个坑:很多工程上线时只想着让模型多答,结果模型硬答导致错误,所以不确定性处理一定要在指令里写死。
进阶一点,我还会做重排序提示,就是把Rerank的分数作为文本提示注入,比如“文档A可信度0.95,文档B可信度0.4”,帮助模型判断哪些信息更可靠。另外,根据query类型动态选择提示模板,事实型问题用严格引用模板,观点型问题可以宽松一些。还有一个技巧是负样本提示,主动告知“以下文档与问题无关,请忽略”,这能过滤掉检索带来的噪声。
当然,实际工程中要权衡。比如HyDE能提升召回15%-20%,但多一次LLM调用,延迟和成本都上去了。查询分解也是,准确率提升但延迟翻倍。所以上线前我会先做离线评测,用RAGAS之类的框架评估不同策略的收益,再逐步上线。提示词模板也要用A/B测试验证效果。
所以整体上,我更倾向于把query改写和提示词构建看作一个系统来设计,先根据业务场景选主策略,再通过离线评测和A/B测试逐步调优,而不是一上来就堆所有策略。
关键一句:HyDE和查询分解在提升召回和准确率的同时,会引入额外的LLM调用和延迟,需要离线评测和A/B测试来验证收益。
面试官还可能这样问
- 问法 1 · 场景切入
假设你在做一个智能客服系统,用户问‘我的订单为什么还没到’,你从知识库检索到一堆物流文档。你怎么把用户这个原始问题改一改,让检索更准?检索完之后,又怎么把这些文档拼成一个回答,让用户觉得靠谱?
- 问法 2 · 层层追问
RAG里用户问的问题有时候很模糊,比如‘那个功能怎么用’,你会怎么处理这个query?……如果改成几个子问题去检索,效果会更好吗?……那检索到文档之后,你怎么组织提示词,才能让模型既引用原文又不照搬?
- 问法 3 · 直球架构
请系统讲讲RAG中query改写的策略,有哪些主流方法?以及检索到文档后,构建提示词生成答案有哪些关键要点?可以结合工程权衡来说。