最近在做知识库问答,用的RAG流程,检索回来的chunk明明有答案,但模型经常自己发挥,甚至把两个不同文档的内容缝合起来。我试过在prompt里加“请严格基于以下内容回答”,但效果不稳定,有时候还是会自由发挥。想问问大家,在写RAG的prompt时,有没有什么结构化的技巧?比如要不要把检索片段编号、加分隔符、或者强制要求“如果原文没有就直说不知道”?另外,是不是需要针对不同模型(比如GPT-4和开源模型)调整prompt措辞?我目前用的模板就是“context: … question: …”,感觉太简陋了,求指点。
RAG里Prompt模板怎么设计才能让大模型老实引用原文?
全部回复
共 49 条你这个情况太常见了,我一开始也踩过一模一样的坑,检索明明没问题,结果模型硬是把两篇文档拼在一起编了个新答案。后来我最大的体会是,光靠一句“请严格基于以下内容”基本没用,模型对这类泛泛的指令敏感度很低。我现在会把检索片段用编号和明确的边界符包起来,比如每个chunk前面加个来源标记,然后要求回答时必须带上引用编号,这样它乱编的成本会高很多。另外“如果原文没有就直说不知道”这句一定要写,而且要写得具体点,别只说“不知道”,我会写成“若检索内容中没有明确依据,请直接回答未找到相关信息,不要推测”。还有一个点挺关键的,就是别把问题和context挤在一起,最好用清晰的分段结构,让模型能区分指令区和资料区。至于不同模型,确实要调,GPT-4相对听话,开源小模型更吃格式和强约束,有时候还得把指令重复一遍放在context后面。你也可以试试让它先复述相关原文再作答,虽然多花点token,但引用准确率会明显好一些。
你这个“context: … question: …”确实太素了,模型不跑偏才怪。我自己的经验是,光加“严格基于以下内容”基本没用,得把约束拆成可执行的动作。比如我会把每个chunk用编号和来源标出来,像【片段1|文档A】这样,然后要求模型先复述它用到的片段编号,再给答案,最后加一句“若片段中没有明确依据,请只输出‘未找到’”。这样它想缝合两个文档时,至少会在复述环节露馅。另外分隔符挺关键的,用明显的三引号或者XML标签包住context,比直接拼在prompt里稳很多,尤其是开源模型对格式更敏感。GPT-4确实更吃“系统指令”那一套,可以在system里写死引用规则,开源模型则要把规则塞在context后面反复强调。还有个小技巧是让模型逐句标注引用来源,虽然啰嗦,但能逼它老实点。温度也别忽略,调到0或0.1,自由发挥会少一大截。
光加“严格基于原文”确实不够,模型该编还是编。我一般会把每个chunk用[1][2]编号,然后要求回答里必须带上引用标记,比如“根据[2]……”,这样它想缝合也会露馅。另外加一句“若上下文未明确提及,直接回复‘根据已有信息无法回答’”,比单纯说不知道更管用。不同模型确实吃不同话术,GPT-4对结构化指令更敏感,开源小模型反而要写得更直白、步骤更细。
你这个“context+question”的模板确实太素了,模型很容易忽略上下文自己编。我一般会把检索片段编号,每个chunk用分隔符隔开,然后明确写“只允许使用上述编号内容作答,没提到的就说不知道”。另外加一句“引用时请标注来源编号”,能逼着它对照原文,缝合现象会少很多。不同模型确实要微调措辞,开源模型对指令跟随弱一些,得更直白甚至重复强调。
你这个“context + question”确实太素了。我一般会把检索片段用编号和分隔符包起来,然后明确要求“只用这些片段,引用时标出编号,没写就回答不知道”,这样模型偷懒缝合的概率会小很多。另外不同模型吃这套的程度真不一样,GPT-4对格式指令比较敏感,有些开源模型反而容易忽略编号,得把约束写得更硬一点。你也可以试试把“先判断有没有答案”单独作为一步,让它别急着生成。
你这个“context+question”确实太素了,模型很容易把检索片段当参考而不是唯一依据。我一般会把每个chunk标上编号和来源,然后加一句“只允许引用编号内的原句,找不到就回答‘未提及’”,效果稳不少。另外最好把指令放在context后面、question前面,模型对末尾指令更敏感。不同模型确实要微调,GPT-4比较吃结构化格式,开源模型更认直白的禁止性指令。
我之前也踩过这个坑,后来在prompt里加了编号和明确引用要求,比如让模型每句话后面标上来源chunk的编号,效果好了不少。另外“如果原文没有就直说不知道”这句一定要写死,不然模型总爱自己编。开源模型确实更不听话,措辞得比GPT-4更直白强硬一点,甚至要重复强调两遍。你可以试试把context用特殊符号包起来,比如###,再配上“只允许使用###内的信息”这种约束。
我之前也踩过这个坑,后来把context拆成带编号的片段,每个片段前加一句“来源X:”,然后在指令里明确要求引用时标出来源编号,缝合问题少了很多。另外“如果原文没有就直说不知道”这句一定要写死,不能只靠“请严格基于”,模型会当耳旁风。不同模型确实吃不同措辞,GPT-4对结构化格式更敏感,开源模型反而喜欢简短直接的指令,得分开调。
我踩过这个坑,光说“严格基于原文”确实不够。我的经验是给每个chunk加编号,然后要求模型引用时带上编号,比如“根据[2]”,这样它缝合不同片段时自己就会别扭。另外在末尾加一句“若上下文未提及,必须回答‘未找到相关信息’”,比单纯说“别瞎编”管用很多。不同模型确实有差异,开源模型对指令跟随弱一些,可以把约束拆成几步小任务,别一股脑塞。