最近在搭一个简单的RAG问答系统,用的开源Embedding+GPT-3.5。我发现一个问题:当检索到的文档里确实没有答案时,模型还是容易瞎编。我看网上说可以在System Prompt里加“如果你不知道答案,请直接说不知道”,但实际试下来效果很飘——有时候明明相关文档缺失,它还是强行推理出一段话。我试过把检索阈值调高,但那样召回率又太低。想请教下大家,有没有更稳定的Prompt写法,或者是不是需要结合后处理逻辑来判空?先谢谢了。
RAG系统里用Prompt让LLM“不知道就说不知道”,效果总不理想
全部回复
共 147 条光靠prompt确实不靠谱,我一般会加个二次校验,让模型先判断文档能不能回答再生成。
光靠Prompt确实很难压住,模型看到点相关内容就忍不住往下编。我一般的做法是让模型先输出结构化结果,比如带个“是否找到答案”的字段,再在代码里判断,只有明确命中才让它生成正文。阈值的话可以分两档,高阈值直接答,中间那段就只回答“不确定”,别硬凑。另外System Prompt里可以要求它引用原文句子,编不出来就说明该拒答了。
光靠System Prompt确实很难稳住,这个坑我也踩过。模型在面对“看似相关但实际没答案”的上下文时,倾向去拼凑一个合理回答,因为它训练时就没怎么学过“拒答”这种动作。我后来改了个思路,把“不知道”拆成两种:一种是检索完全没命中,一种是命中了但文档里没直接答案,这两种走不同分支处理。前者可以设个相似度阈值直接短路掉,不调LLM;后者我是在Prompt里要求它先输出一段“证据检查”再给答案,比如让它逐条列出检索片段里有没有支持答案的句子,没有就输出固定标记。这个固定标记后面用代码判一下,命中就返回兜底话术,不命中才展示模型答案。另外可以试试让模型输出JSON,字段里带confidence和evidence,比让它自由发挥稳定不少。阈值调高召回掉是正常的,可以考虑混合检索或者加个rerank,把判空这件事从Prompt层挪到工程层会更靠谱。
我搭RAG的时候也踩过这个坑,光靠System Prompt确实不太稳,模型有种“必须回答点什么”的惯性。后来我把Prompt改成了一个显式的两段式判断,先让它输出“检索内容是否包含答案”的标记,再决定要不要答,这样比单纯说“不知道就说不知道”靠谱一些。另外你可以试试在检索层做文章,比如对Top-K结果做重排序,或者用交叉编码器算一下query和文档的相关性分数,低于某个阈值就直接走兜底逻辑,不让模型碰。还有个偏工程的做法是让模型输出结构化格式,比如answer字段为空或者confidence很低就触发“暂时没有找到相关信息”。阈值调高召回掉是正常的,所以关键是别把判空完全压给生成模型,得前后配合。我现在的方案是Prompt里加few-shot示例,专门给一个“文档不相关”的样本,效果比纯指令好不少。
刚入门,这个对我帮助很大。
这个思路不错,收藏了。
学到了,感谢分享!