最近在搭一个简单的RAG系统(基于LangChain+GPT-4),检索到的文档片段大多能对上,但模型回答时经常“自由发挥”——比如原文说“价格是100元”,它给我输出“价格约100-120元”。我试过在System Prompt里写“请严格基于检索内容回答”,但效果不稳定。想请教一下大家:
1. 是不是应该在User Prompt里把检索到的片段和问题分开写?比如用“【参考文档】”标记?
2. 有没有什么特定的指令模板,比如“如果参考文档中没有明确信息,请直接说不知道”?
3. 用Few-shot示例会不会让模型更守规矩?还是说简单粗暴加temperature=0就行?
我现在主要卡在“忠实度”和“流畅性”的平衡上,求各位大佬指点!
RAG里Prompt怎么写才能让大模型老实引用原文,不乱编?
全部回复
共 151 条我之前也遇到过这问题,光是system prompt压不住,后来把检索片段直接塞进user prompt里用分隔符框起来,再明确说“只准引用框内内容,没写就答不知道”,效果好了很多。temperature=0确实有用,但别指望它解决所有事,模型该编还是编。Few-shot我试过,放一两个对比示例(一个引用了、一个拒答了)比单纯说教管用,但别放太多,不然容易把格式带偏。你要是还不行,试试把prompt里“基于参考”改成“只能使用以下内容”,措辞强硬点真不一样。
我踩过这坑,把参考文档和问题分开放进user prompt,再加句“没写就答不知道”,比system管用。
few-shot不如调temperature到0.2,再让模型先复述原文再作答,基本能压住瞎编。
你这问题我太有共鸣了,纯靠system prompt压确实容易翻车。我自己的做法是把参考文档用XML标签包起来放在user prompt最前面,然后明确写一句“只能引用
你这个情况太典型了,我试过把检索片段用【参考文档】包起来放在User Prompt里,效果确实比一股脑全塞给模型强。另外Temperature调低挺管用的,但别直接归零,0.1左右能减少很多自由发挥。Few-shot我试过,成本有点高,不如在提示词里加一句“若文档未提及,请明确回复‘未找到相关信息’”,比单纯说“严格引用”有效得多。对了,你用的是GPT-4还是4o?不同版本对指令的遵循程度差别挺大的。
你试下把参考文档直接怼进user prompt里,用分隔符隔开再让模型逐条对照引用,比system里喊口号管用。
我之前也踩过这个坑,后来发现关键不是“告诉它别乱编”,而是把“能编的空间”堵死。你提到用【参考文档】标记,这个方向是对的,而且我强烈建议把检索片段直接放在User Prompt里,用分隔符跟问题隔开,同时明确写“只能使用上述文档中的原句或同义转述”。光在System Prompt里喊口号没用,因为模型对越靠近输出的指令越敏感。
关于“没有明确信息就说不知道”,这招实测有效,但措辞得狠一点,比如“若参考文档未提及,必须回答‘信息不足’,禁止推测或估算”。我试过加温度=0,确实能减少发散,但代价是回答变得机械,有时连文档里有的细节也漏掉,所以建议配合few-shot用——给一个“文档说价格100元,问题问价格,答案是100元”的正例,再给一个“文档没提价格,问题问价格,答案是信息不足”的反例,模型会明显收敛。
不过我还有个疑问,你用的检索片段本身会不会有截断问题?有时候片段结尾是个半截句子,模型误以为原文就是那样,然后自己补全后半句。我后来把片段切得稍微长一点,或者把多段都塞进去,让模型自己比较,反而更不容易编。你可以试试看是不是这个原因。
我最近也在搞这个,试下来最管用的是把检索片段单独放在User Prompt里,用明确标签隔开,然后在指令里加一句“只能引用标签内原文,禁止推断价格、时间等具体数值”。temperature=0确实有帮助,但别全指望它,GPT-4有时候温度设0也会脑补。Few-shot我觉得得看场景,你要是能准备两三个“原文模糊→模型拒答”的正反例,效果比单纯写规则稳得多。另外你那个“约100-120元”的问题,可以试试在System Prompt里点名要求“若原文未给出区间,不得自行扩展”,我这么改完基本没再犯过。
我一般把检索片段放user prompt里用【】框起来,再跟一句“没写到的别猜”,效果比单改system强。
提示词里加一句“只允许原样摘抄,不确定就答不知道”比啥都管用,temperature=0只是辅助。
我试过用“【参考文档】”这种标记,确实比混在一起好一点。但光靠Prompt不够,关键还是得在代码里做后处理,比如抽出来的答案如果跟原文数字对不上就重新生成一次。Few-shot有用,不过示例得针对你这种“改数字”的毛病来写,不然模型还是照编。temperature=0能减少随机性,但治不了它“理解性发挥”,该编还是编。
温度调到0确实有用,但别指望它能根治,模型该编还是会编。我一般会在user prompt里把检索片段用特殊标记包起来,然后加一句“只允许引用标记内的原文,超出范围就回答不知道”,比光在system里写管用。Few-shot我也试过,放一两个“原文没提就直接拒答”的例子,效果还行,但会吃token。另外建议你检查下检索片段是不是太长了,噪音多的话模型更容易自己脑补。