最近在做知识库问答,用的RAG流程,检索回来的chunk明明有答案,但模型经常自己发挥,甚至把两个不同文档的内容缝合起来。我试过在prompt里加“请严格基于以下内容回答”,但效果不稳定,有时候还是会自由发挥。想问问大家,在写RAG的prompt时,有没有什么结构化的技巧?比如要不要把检索片段编号、加分隔符、或者强制要求“如果原文没有就直说不知道”?另外,是不是需要针对不同模型(比如GPT-4和开源模型)调整prompt措辞?我目前用的模板就是“context: … question: …”,感觉太简陋了,求指点。
RAG里Prompt模板怎么设计才能让大模型老实引用原文?
全部回复
共 26 条把检索片段编号加进prompt,让模型按编号引用,能明显减少缝合,你可以试试。
不同模型确实吃不同措辞,开源模型更吃“如果没找到就回复不知道”这种硬约束。
我试过把检索片段编号后让模型按编号引用,配合“请引用编号对应的原文”这种指令,比单纯说“严格基于内容”管用不少。另外分隔符别用那种花哨的符号,直接上XML标签或Markdown引用块,模型更认这个。还有一点,不同模型确实吃不同套路,GPT-4对“如果原文没提就答不知道”执行力强,但开源模型可能得在后面补一句“不要推测”才行。你那模板确实太裸了,建议把每个chunk单独成段,再明确标注来源文档ID,能少很多缝合问题。
试试把检索片段分段编号,再让模型按编号引用,幻觉能少一截,顺便用分隔符隔开每个片段。
你这个模板确实是太素了,光靠一句“严格基于”对大模型来说约束力很弱,它分不清哪些是检索来的事实、哪些是它自己的联想。我试过把每个chunk前面加上[1][2]这种编号,然后prompt里明确写“回答时只允许引用编号片段中的原句,引用格式用(片段X)”,效果会好不少,至少缝合情况少多了。还有就是分隔符别用“context:”这种,换成那种不常见的符号比如###或者```,让模型能清晰感知到边界,不然它容易把上下文和问题混在一起。另外你提到“没有就直说不知道”,这个一定要写,而且最好加一句“如果片段之间有矛盾,请明确指出矛盾点”,这样能逼它去比较而不是自己脑补。关于模型差异,我感觉GPT-4对指令的跟随强很多,措辞随意点也行,但开源模型像Llama或Qwen,你得把要求拆成短句,甚至用“你必须”“禁止”这种强命令词,不然它真会自由发挥。我还有个疑问,你检索回来的chunk有没有做重排序?有时候不是prompt的问题,是相关片段排得太靠后,模型注意力不够就忽略了,你可以试试把最相关的三个片段固定在开头试试。
我之前也踩过这个坑,光靠一句“严格基于原文”根本压不住模型的发挥欲。后来我把模板改成了三段式:先明确角色和任务边界,再放带编号的检索片段,最后给一个“答案格式”示例,比如“根据片段2,答案是……”,效果一下子稳了很多。编号这个动作特别关键,它相当于给模型一个锚点,让它知道引用是能被检查的,它就不敢瞎编了。另外我强烈建议在prompt里加上“如果以上片段没有直接回答,请输出‘信息不足’”,这比让模型自己判断“不知道”要可靠得多,因为它会倾向于把“相关但不对题”的内容也当成答案。至于模型差异,我感觉GPT-4对这种结构化模板的服从性高一些,开源模型像Llama系反而需要更直白的指令,比如直接写“禁止总结,禁止推测”,甚至可以把示例里的“缝合”行为作为反面案例写进去。还有个小技巧,把检索片段之间的分隔符用特殊符号(比如三条横线)而不是换行,能减少模型把不同文档内容串起来的概率。你可以试试把context和question的顺序调换,让问题在前片段在后,有些模型对后置信息的遵从度更高,这个跟注意力机制有关。
给每个chunk加编号,让模型用编号引用,基本能治胡说,试试看。