最近在做一个基于RAG的问答系统,向量库用的是Milvus,检索top3片段拼进Prompt里让模型回答。但发现模型经常忽略检索到的内容,还是按自己知识瞎答,甚至编造一些原文没有的细节。目前用的Prompt是“根据以下资料回答问题:{context}\n问题:{question}”,感觉太简单了。看网上有人加“如果资料中没有答案就说不知道”,试了效果也不稳定。想请教各位,RAG场景下Prompt到底该怎么设计?有没有什么结构化的模板或者技巧?是不是还需要在检索后做重排序?真心求教,谢谢!
RAG系统里Prompt到底该怎么写才能让模型不瞎编?试了好几种模板效果都一般
全部回复
共 12 条我之前也踩过这个坑,光在prompt里写“没有就说不知道”确实不太管用,模型该编还是编。后来我把context里每个片段前面加上序号和来源,让它回答时先引用片段编号再作答,瞎编的情况明显少了很多。另外你可以试试把指令放后面而不是开头,有些模型对末尾的约束更敏感。重排序建议加上,top3里经常混进不相关的片段,反而干扰模型判断。
刚入门,这个对我帮助很大。
检索回来的片段可以加个相关性打分,分低的直接别塞进去,不然模型容易被带偏。
我后来把指令改成“只依据下面资料回答,资料里没提到的就别补充,直接说无法确定”,效果明显稳了不少。另外检索top3有时候噪声太大,建议加个重排序或者相似度阈值过滤,不然模型容易被无关片段带偏。还有个技巧是把资料编号,让模型回答时带上引用来源,能逼着它盯着原文。
我之前也踩过这个坑,光靠改Prompt其实治标不治本。你可以试试把指令写得更硬一点,比如“只允许依据下面片段回答,片段里没有的就直说没有”,再把片段标上编号让模型引用,这样它瞎编的概率会低不少。另外top3可能不够,重排序确实值得加,bge-reranker这类模型能把真正相关的片段顶上来,比单纯调Prompt管用。
我踩过同样的坑,后来发现光改Prompt不够,得把指令写得更硬一点。比如明确说“只允许用下面资料回答,资料里没有的直接说找不到”,再加一句“引用原文时保留原句”,模型编造的概率会低不少。另外top3片段可能太散了,可以试试重排序或者把相似度低的直接过滤掉,不然噪声一多模型更容易跑偏。
这个问题其实挺常见的,模型忽略检索内容很多时候不是Prompt的锅,而是检索本身就没给到足够精准的东西。你top3片段如果相关性不够,模型自然倾向于用自己的先验知识去补,尤其是它“觉得”自己知道答案的时候。我之前也踩过这个坑,后来发现把检索结果排序做好,比反复改Prompt管用得多。可以试试加一个cross-encoder做重排,或者用相似度阈值过滤掉低分片段,宁可少给也别给噪音。Prompt方面,我现在的写法是把指令拆开,比如先明确角色和任务边界,再给context,最后单独强调“只允许基于上述内容回答,没提到就说没有”。另外有个小技巧是把问题放在context前面,有些模型对位置敏感,这样能减少它被长文本带偏。还有个思路是让模型先复述检索到的关键句再作答,相当于强制它先“看”一遍。你用的什么模型?不同模型对Prompt结构的敏感度差别挺大的。
写得挺好,建议补充一些性能数据。
有没有更详细的教程推荐?
我之前也遇到过类似问题,后来换了方案。
有没有更详细的教程推荐?
加点“只依据资料回答,没提到就说不知道”还不够,关键得让模型先引用原文再作答,能明显压住瞎编。