你的 RAG 系统检索结果很准,但最终答案还是有幻觉,Prompt 怎么写的?System Prompt 和 User Prompt 怎么分工
P1 · rag · 🏢 京东
🏷 标签:rag, prompt-engineering, system-prompt, user-prompt, hallucination
1️⃣ 考察意图
这道题考察的是RAG系统Prompt Engineering的工程取舍与系统设计能力,而非单纯背概念。面试官已明确“检索结果很准”,所以你的回答必须跳过“优化检索”这个低级陷阱,直接切入Prompt如何强制模型切断参数知识、只依赖检索文档这一核心矛盾。刁钻点在于:很多人以为幻觉是模型能力问题,但实际是Prompt约束强度不够或分工不清。答好了能展示你对RAG幻觉根因的深刻理解,以及System/User Prompt分工设计的系统性思维,这是P1进阶工程师的硬实力。
2️⃣ 标准答
核心原则:RAG Prompt 的本质是“知识隔离”——让模型变成一台只读检索文档的“文档翻译器”,而不是一个会调用自身参数知识的“百科问答机”。
System Prompt:定义“文档翻译器”的角色与规则
- 角色定义:明确告诉模型“你是一个文档问答助手,你的所有知识来源于下方提供的文档,不要使用你训练时学到的任何外部知识”。这步是切断参数知识的第一道防线。
- 强约束措辞:使用“只能”、“必须”、“禁止”等绝对化词汇,而非“尽量”、“建议”。例如:“你只能基于以下文档内容回答。如果文档中没有相关信息,必须直接回答‘文档中未提及’,禁止自行编造或推测。” 工程取舍:软约束(如“尽量基于文档”)在模型面对模糊问题时,仍会倾向调用参数知识,导致幻觉;硬约束虽可能让模型在文档信息不足时拒绝回答,但这是可控的,比幻觉好。
- 引用要求:强制模型在答案中标注引用来源。例如:“每个事实性陈述后,必须用[文档编号]标注来源。如果无法标注引用,说明该陈述不在文档中,需删除。” 这能倒逼模型逐句核对文档,显著降低幻觉。实际落地坑:模型有时会编造引用(如引用不存在的段落),需在后处理中做引用验证(如用BM25检查引用段落是否真的包含该事实)。
- 拒绝策略:定义清晰的拒绝回答场景。例如:“如果问题与文档无关,或文档信息不足以回答,请回复‘根据现有文档,无法回答该问题’。” 这避免了模型强行回答导致的幻觉。
User Prompt:格式化“文档+问题”输入
- 文档结构化:将检索到的文档按统一格式组织,例如:“【文档1】标题:XXX,内容:XXX\n【文档2】标题:XXX,内容:XXX”。先文档后问题,让模型先“读”文档再“答”问题。工程取舍:如果文档很长,需在User Prompt中做摘要或截断,但摘要可能丢失关键信息,导致模型依赖参数知识补全。解法是使用滑动窗口或分层摘要,确保关键事实不被遗漏。
- 问题清晰化:将用户原始问题直接放入User Prompt,例如:“基于以上文档,回答以下问题:XXX”。避免在User Prompt中重复System Prompt的约束,保持职责分离。
- 上下文管理:对于多轮对话,将历史对话也结构化放入User Prompt,例如:“历史对话:\n用户:XXX\n助手:XXX\n当前问题:XXX”。注意:历史对话中的模型回答可能包含幻觉,需在User Prompt中明确“历史对话仅供参考,当前回答必须基于最新文档”。
实际落地的坑与解法
- 坑1:模型忽略System Prompt。某些模型(如早期GPT-3.5)对System Prompt的遵循度不高。解法:在User Prompt末尾重复关键约束,例如:“再次强调:只能基于文档回答,禁止编造。” 或者使用Few-shot示例,在User Prompt中给出一个“文档+正确回答”的样例。
- 坑2:文档过长导致模型“遗忘”。当检索结果有10+个文档时,模型可能忽略中间文档。解法:在User Prompt中按相关性排序文档,并添加“请优先参考【文档1】和【文档2】”的指令。同时,使用FlashAttention等长上下文技术,或对文档做重排序(rerank)后只保留Top-3。
- 坑3:模型“过度引用”。模型可能每句话都加引用,但引用内容与事实不符。解法:在后处理中做引用验证,例如用DPR或ColBERT检查引用段落与陈述的语义相似度,低于阈值则删除该引用并重新生成。
3️⃣ 答题模板(30 秒电梯版)
“这个问题我从System Prompt、User Prompt、以及实际落地坑三个层面回答。System Prompt层面,核心是定义‘文档翻译器’角色,用‘只能/必须/禁止’等硬约束切断参数知识,并强制引用标注。User Prompt层面,关键是格式化文档并先文档后问题,保持职责分离。实际落地坑包括模型忽略System Prompt、文档过长导致遗忘、以及模型编造引用,解法分别是重复约束、相关性排序后截断、以及后处理引用验证。总结一句:RAG Prompt的本质是知识隔离,约束强度决定幻觉率。”
4️⃣ 高频追问 & 应对
追问 1:如果模型在System Prompt里写了“只能基于文档”,但回答还是幻觉,你怎么排查?
首先,检查User Prompt中的文档是否真的包含答案所需信息。如果文档缺失,模型可能被迫调用参数知识。其次,检查模型是否忽略了System Prompt——可以在User Prompt末尾重复关键约束,看幻觉是否下降。最后,检查引用标注:如果模型编造引用,说明它没有真正核对文档。解法是加一个后处理步骤:用BM25或DPR验证引用段落是否真的包含该事实,不通过则重新生成。
追问 2:你的System Prompt里用了“只能”和“必须”,但有些模型对这类指令不敏感,怎么办?
这是实际落地中的常见坑。解法有三:一是用Few-shot示例,在User Prompt中给一个“文档+正确回答”的样例,让模型模仿。二是调整模型,选择对System Prompt遵循度更高的模型(如Claude系列)。三是做Prompt调优实验,对比不同措辞(如“只能” vs “请尽量”)下的幻觉率,用A/B测试找到最优版本。如果模型实在不听话,考虑用后处理规则做硬性过滤,比如检测答案中是否有文档中不存在的实体。
追问 3:你的User Prompt里“先文档后问题”,但如果文档很长(比如10页PDF),模型会忽略中间内容,怎么办?
这是长上下文场景的经典问题。解法:一是对文档做重排序(rerank),只保留Top-3最相关的文档,减少输入长度。二是使用分层摘要:先对每个文档做摘要,再将摘要放入User Prompt,并附上“如需详细信息,请参考原文”的指令。三是利用FlashAttention等长上下文技术,但注意这不能完全解决“中间遗忘”问题。实际工程中,我倾向于用rerank + Top-3截断,因为实验显示【通用知识】Top-3文档已能覆盖90%以上的答案所需信息。
5️⃣ 避坑 · 常见错误答法
- ❌ 答:“可能是检索结果不够准,需要优化检索。” → ✅ 正确切入:面试官已明确“检索结果很准”,所以必须跳过检索,直接分析Prompt约束强度。核心是“知识隔离”,而非检索质量。
- ❌ 答:“换更强的模型,比如GPT-4,幻觉就没了。” → ✅ 正确切入:模型能力不是根因,Prompt设计才是。即使GPT-4,如果System Prompt是“尽量基于文档”,它仍会调用参数知识。必须用硬约束强制模型只读文档。
- ❌ 答:“System Prompt写角色,User Prompt写问题,分工明确就行。” → ✅ 正确切入:分工只是基础,关键是约束措辞强度(“只能” vs “尽量”)和引用要求。没有引用标注,模型无法逐句核对文档,幻觉率会高很多。
6️⃣ 简历呼应
- 如果你有RAG项目:从“实际落地坑”切入,比如“在金融保险RAG项目中,我通过System Prompt的硬约束和User Prompt的文档结构化,将幻觉率从15%降到3%。具体做法是……”。强调你做过A/B测试,对比了不同约束措辞的效果。
- 如果你只做过传统NLP:用“Prompt Engineering vs Fine-tuning”类比迁移。比如“传统NLP中,我们通过Fine-tuning让模型学会特定任务;RAG中,Prompt就是‘零样本Fine-tuning’,System Prompt定义任务边界,User Prompt提供输入数据。我的经验是……”。突出你对Prompt本质的理解。
- 如果你是校招无项目:聚焦论文复现demo。比如“我复现了‘Self-RAG’论文,其中System Prompt定义了‘是否检索’和‘是否引用’的规则。我在此基础上做了改进,加入引用验证后处理,幻觉率下降20%”。展示你对前沿工作的理解和动手能力。
- 《Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection》
- 《REALM: Retrieval-Augmented Language Model Pre-Training》
- 《RAGAS: Automated Evaluation of Retrieval Augmented Generation》
- 《Lost in the Middle: How Language Models Use Long Contexts》
- 《Prompt Engineering Guide》by DAIR.AI(System Prompt设计章节)