资讯动态

RAG提示词设计实战:从模板搭建到防幻觉优化

发布时间:2026/10/20 11:48:01 来源:尧图企业网站定制
做RAG项目的人多半都听老手念叨过一句话检索抓得准生成就成功了一大半。这话对但也不全对。我见过太多团队把向量检索、重排调得漂漂亮亮Top5召回结果非常准结果大模型一张嘴就翻车——要么把文档里没出现的信息编得有模有样要么把多份来源里互相矛盾的内容硬揉成一团要么干脆无视检索上下文凭自己的训练记忆自说自话。问题出在哪十有八九出在提示词上。RAG的提示词和普通问答的提示词完全是两回事。它不是简单地把“你是助手”和“根据上下文回答”拼在一起就完事儿。在RAG链路里提示词至少要承担三重任务明确告诉模型哪些内容是可信依据、哪些内容可以忽略约束模型在引用与不编造之间找平衡同时还要支持多轮对话、处理检索噪声。这篇是【ACP-LLM】RAG系列的第一篇专门拆解RAG场景下的提示词设计。我会先讲清楚RAG提示词为什么难写再给出一套可以直接抄的模板结构最后把我实践中踩过的坑和排查方法全部摊开来说。如果你是正在做知识库问答、企业文档助手、智能客服这类应用的开发者或者刚接触RAG想系统性入门的人这篇文章应该能帮你节省大量试错时间。1. 先搞清楚RAG提示词到底站在链路的哪个位置1.1 一次完整问答里提示词其实有多个入口很多做RAG的新手对提示词的理解非常单一认为提示词就是最后发给大模型的那些指令。但如果你把一个标准的RAG问答流程完整走一遍就会发现提示词至少出现在三个关键位置。第一个位置是查询改写阶段。用户原始提问可能很口语化比如“那个方案的成本是多少”“这个和上一个问题有什么关系”这种问题直接拿去向量检索召回效果往往很差。所以通常要先用一个LLM调用把用户问题改写成适合检索的正式查询这一步本身就是一次提示词工程。第二个位置是检索后的上下文组织阶段。你可能召回了5到8个文本块有的相关、有的不相关、有的互相重叠你需要决定如何把这些内容拼进提示词要不要让模型先压缩一下这些都是通过提示词来控制的。第三个位置才是最终生成阶段也就是大多数人说的主提示词包含了系统角色、上下文内容、用户问题这几个部分。这三个入口任何一个没设计好整个RAG的效果都会打折扣。我在实际项目里见过不少案例检索链路完全没动只是优化了查询改写阶段的提示词整体准确率就提升了十几个百分点。所以提示词在RAG里不是一个点而是一条线。1.2 为什么不能用普通Prompt的思维去做RAG提示词普通问答的提示词核心是引导模型调用自身能力去回答比如“你是一位资深律师请从专业角度分析……”。模型拥有大量自由度知识来自参数记忆。RAG提示词完全不同它的核心诉求是让模型当一个可信的信息搬运工而不是一个知识渊博的专家。你严格要求它只依据给定文档回答这就产生了一个根本性冲突大模型天生习惯凭记忆补全信息你要用提示词强行压制这种习惯让它把上游检索到的内容当作唯一信息来源。这种差异带来几个直接的提示词设计原则。第一上下文不是越多越好。普通Prompt你可以把背景信息、示例、约束条件一股脑塞进去。RAG里塞太多无关块模型会更倾向于从最显眼但不是最相关的内容里找答案甚至被噪声内容带偏。第二指令必须明确区分“依据”和“干扰”。普通Prompt里你不需要告诉模型“忽略某部分内容”RAG提示词里你要主动声明检索结果中可能含有无关内容模型需要批判性地使用。第三要对模型的“自信”设防。普通问答中有时我们希望模型果断给出判断但RAG场景里你必须让模型在信息不足时坦然说不知道而不是硬答。一句话总结普通Prompt是在释放模型的能力RAG提示词是在给模型的能力上锁同时只留一扇通往检索结果的窗户。理解了这点后面的模板设计才立得住。2. RAG提示词核心组件逐个拆解2.1 系统级指令角色、边界与任务范围整个RAG提示词里系统级指令System Prompt是压舱石它决定了模型整体以什么姿态处理任务。我常用的写法包含四个要素角色定义、知识边界声明、任务目标说明、全局约束。角色定义不能太虚。说“你是一个知识库助手”太宽泛我更推荐结合业务定位去描述比如“你是某企业内部制度知识库的问答助手负责基于已上传的制度文档解答员工疑问”。这样模型会对回答风格有基本预期。知识边界声明是RAG提示词里最不能少的一句。典型写法是“你只能使用用户提供的检索文档中的信息来回答不能使用你自己的先验知识”。实测下来这句话对抑制幻觉有明显帮助但有一定概率会让模型过度保守连常识性的补充都不敢说。所以我会在后面加一个豁免条款“在检索文档信息不足时你可以基于常识进行一般性补充但必须明确标注此部分不属于检索文档内容。”任务目标说明是告诉模型“你面对的是什么样的调用场景”。比如“用户通过对话查询知识库你的目标是给用户一个简洁、准确、可追溯的答案”这能让模型主动控制回答篇幅不会长篇大论把检索到的内容原样倒出来。全局约束部分通常放输出格式要求。比如“回答中涉及文档内容时请在句末使用[来源编号]标注对应文档块”“如果检索文档与问题无关直接回答‘未找到相关信息’不要尝试猜测”。这些约束在后续小节里会展开细说。2.2 上下文注入组块格式与来源标注的写法RAG提示词里检索结果的注入方式会直接影响模型的引用精度。很多人在这一步偷懒把检索到的文本块用普通换行隔开直接拼进提示词结果模型根本分不清哪些内容是哪来的也不会正确引用。我给一个在实践中非常好用的格式化方案。把检索结果定义为多个“文档块”每一块用固定标签包裹document sourcedoc_id_001/source chunk_idchunk_003/chunk_id content 这里是检索到的文本块内容... /content /document document sourcedoc_id_002/source chunk_idchunk_010/chunk_id content 这里是另一个检索到的文本块内容... /content /document然后在系统提示词中告诉模型“以上内容中每个 代表一个检索到的文本片段表示来源文档编号chunk_id表示片段编号。回答时如需引用请使用[来源编号-片段编号]格式例如[doc_id_001-chunk_003]。”这种结构的价值是双向的。对模型来说它有了清晰的信息颗粒度知道引用时该绑定到哪个具体来源对下游应用来说用户点击引用标记时你能准确跳转到对应的原文位置这在企业知识库场景里几乎是刚需。这里有一个关键技巧检索结果在提示词中的摆放顺序会显著影响模型的关注权重。模型对上下文早期的内容往往分配更多注意力。实测下来把相关性最高的文档块放在所有文档块的最前面比随机排序能小幅提升答案准确率。如果你的检索排序本身已经做得不错注意保持这个顺序不变如果检索分数不可靠那宁可先做一轮重排或压缩。2.3 防幻觉设计置信度表达与拒绝回答机制RAG最让人头疼的问题就是模型编造文档里不存在的信息。提示词是普通开发者对抗幻觉的第一道防线。我的做法是在系统提示词中加入压力测试式约束大意是“如果检索文档中没有任何内容可以回答问题你必须明确回复‘知识库中未找到相关信息’并在后面用一句话说明你的尝试过程例如‘我检索了与XX相关的文档但未能找到匹配内容’。绝对禁止编造或猜测答案。”这个措辞看起来简单但有两个容易被忽略的细节。一是“说明尝试过程”这个要求它本质上是在诱导模型进入一个验证性思维模式降低模型直接“编造”的概率因为模型要先在逻辑上承认自己找不到才能给出拒绝回答而这一步自我声明会触发模型对不确定性的判断。二是“绝对禁止”这种强否定词中文大模型对强否定词有一定的遵从倾向虽然不如英文模型稳定但总体有效。另外一个很实用的技巧是使用“双通道回答”比如要求模型在正式回答前先进行内部判断如果检索内容与问题相关度低于某个阈值走拒绝流程否则正常回答。这种让模型先判断再回答的提示词结构实测比直接要求“根据检索内容回答”的准确率更高代价是多消耗一些推理时间和Token。我还会在提示词里固定加入一句“注意检索到的文档块可能包含无关或重复内容应以最相关的部分为准忽略无关内容。”这句话能明显降低模型被低质量检索块带偏的概率。说白了RAG系统里检索不可能永远干净提示词做好“抗污染”设计比拼命优化检索算法更划算。3. 实操从零搭一个能落地的RAG提示词模板3.1 从业务需求倒推提示词功能清单直接给模板前先讲一个原则提示词不是越多越好而是要看业务场景需要什么。我拿一个真实做过的“企业制度问答助手”来举例这个场景的核心需求有三个支持员工用自然语言查询休假、报销、考勤等制度条款回答必须给出制度原文依据多轮对话中能理解“那如果请假超过三天呢”这种指代。从这三个需求出发提示词需要的功能点就很清晰了。需要支持查询改写模块把指代句补全为完整问题需要强制引用机制标注来源还需要在连续对话中保留关键上下文但避免把上一轮检索结果全部灌入提示词。至于角色设定则不需要复杂的人设保持中性、严谨即可。从需求倒推还有一个好处你会在设计阶段自然过滤掉不需要的功能。比如如果你的用户只想快速得到是或否的答案那就不需要让模型输出长篇幅分析如果不需要跨文档综合就不用设计复杂的多文档融合逻辑。3.2 查询改写阶段提示词写法查询改写是RAG提示词里最容易被省掉的一环。直接用用户原始问题去检索在多轮对话场景下几乎必然出现召回失败。这里给一个我常用的改写提示词模板你是一个面向知识库检索的查询改写助手。你的任务是把用户当前的提问改写成一个适合向量检索的独立查询。 要求 1. 如果当前问题包含了明确的指代词如“这个”“那个”“它”“其”请结合对话历史将其替换为具体名词。 2. 如果当前问题本身已经完整清晰直接输出原问题。 3. 不要添加对话历史中不存在的信息。 4. 只输出改写后的查询文本不要有任何解释或前后缀。 5. 改写后的查询应尽量包含领域关键词便于检索匹配。 对话历史 {chat_history} 当前提问 {user_question}这个模板的核心是第1条和第3条。第1条解决指代消解第3条防止模型在改写中自己加料这一点很容易被忽略。有些情况下模型为了“完善”查询会把用户没有明说的条件补进去导致检索结果跑偏。所以“不要添加对话历史中不存在的信息”必须写死。在一些强结构化领域我还会在改写指令中追加“关键词扩展”要求比如“如果查询涉及专业术语缩写请补充完整名称”。这能提高召回率但要注意扩展词的准确性否则反而引入噪声。3.3 主生成阶段提示词模板与参数配套这是整个RAG提示词的核心。我给出一个经过多轮调优的中文模板可以直接复制修改使用你是企业知识库智能问答助手。你的职责是基于系统提供的制度文档片段准确回答员工提出的问题。 严格遵守以下规则 1. 只能依据上面“检索文档”部分提供的内容进行回答不得使用自己的先验知识。 2. 如果检索文档与问题无关或不足以回答问题请回复“知识库中未找到相关信息”并简要说明检索方向。 3. 回答中如需引用文档内容请在句末使用标注格式[来源编号-片段编号]。 4. 如果多个文档块内容存在冲突请优先采用出现次数较多、信息更完整的内容并在回答中说明存在不一致必要时列举各文档的说法。 5. 回答要简洁、准确直接给出结论不要复述检索文档原文不要输出多余的分析过程。 检索文档 document sourcedoc_id_001/source chunk_idchunk_003/chunk_id content {检索到的文本块} /content /document ... document sourcedoc_id_002/source chunk_idchunk_010/chunk_id content {检索到的文本块} /content /document 对话历史 {chat_history} 用户问题 {user_question}模板写完要注意配套参数设置。我在RAG任务里通常把temperature设为0.2到0.3之间既保留一定的表达多样性又不至于让模型自由发挥到编造答案。top_p设置在0.85左右。有些人会直接把temperature设成0认为这样最稳定。实测下来0确实能减少幻觉但会让回答变得僵硬尤其在多轮对话中容易重复已有说法。我更推荐0.2稳而不过度保守。还有一个重要细节检索文档部分要放在对话历史之前还是之后我试过多种排布最终认为“检索文档—对话历史—用户问题”的顺序效果最好。模型先看到权威依据再看到历史最后看到当前提问整个推理路径最清晰。如果把对话历史放在最前面模型容易把注意力放在聊天语境上弱化文档的存在感。3.4 上下文压缩提示词解决信息过载RAG系统召回的结果经常有不相关或重复的情况。原来我直接在主提示词中丢入全部召回块但在一个检索召回过多、文档块过长的场景下Prompt总Token会迅速膨胀既增加成本又影响生成质量。后来我加了一个“上下文压缩”环节效果很好。压缩提示词的大致逻辑是让模型从多个文档块中剔除与用户问题无关的信息合并重复内容只保留最关键的部分并以相同XML格式输出。这一步可以放在生成阶段之前也可以作为一个后处理步骤。你是一个检索结果压缩助手。下面是从知识库中检索到的若干文档块请根据用户问题从中筛选出最相关的内容进行压缩汇总。 要求 1. 保留与问题直接相关的信息剔除无关内容。 2. 对多个文档块中重复的信息进行合并。 3. 压缩后的内容必须保持原始语义不得修改或用你自己的知识补充。 4. 请保留来源标注信息压缩后的每个段落仍使用document标签包裹。 用户问题 {user_question} 检索文档块 {document_blocks}压缩之后主提示词里的上下文总量可能减少40%-60%模型面对的信息噪声大幅下降。不过要留意压缩本身也是一次LLM调用会有延迟和成本适合在检索块数量多或文本块长度大的场景使用。如果检索结果已经非常干净或者系统对首字延迟要求极高就不要做压缩直接用。4. 常见问题与排查技巧实录4.1 模型总是无视检索结果凭记忆回答这是我被问得最多的问题。现象是检索结果里明明有标准答案模型却用自己的理解回答甚至直接编造。排查方向有三个。第一看检索块是否放在提示词过靠后的位置。有些框架默认把上下文放在系统提示词之后看似没问题但如果上下文很长模型读到后面注意力已经下降检索内容反而成了“背景噪音”。解决方法是把检索块前移到紧挨系统提示词的位置并加上“检索文档”的显式标识。第二看上下文块是否过长。当单个文档块超过模型上下文窗口的30%模型对局部信息的感知会钝化。建议按语义分块把块长度控制在200到500个Token内。第三检查提示词里是否给了模型“跳出”的借口。比如角色设定中带有“你是一位资深HR专家”类似表述模型会不由自主地启用领域知识降低对检索内容的依赖。RAG场景的角色描述应中性化可改为“你是知识库问答系统的输出模块”。4.2 多文档块内容冲突模型强行和稀泥企业制度文档经常出现新版本替代旧版本、A部门与B部门规定不一致等情况。模型默认倾向于在多个冲突观点之间“融合”输出一个看似中立但实际两边都不对的说法。我推荐的提示词写法是第3节模板中的第4条要求模型优先选择信息更完整、出现次数更多的内容同时要在回答中明确提示“当前检索文档中存在不一致说法”。这样模型收到如实呈现矛盾的指令后就不太可能强行和稀泥。如果业务上允许还可以再加一条“如果冲突无法调和请分别列出各来源说法让用户自行判断”。这里有个需要用提示词配合后端的点平时要做好版本号管理。如果文档块中有明显的更新时间字段可以在提示词中加入“优先使用较新版本”的规则。但这需要保证分块时把版本号一并保留了。4.3 提示词Token超限正文内容被截断这是工程上必然会遇到的问题。提示词里塞了历史对话、检索块、系统指令一个大点的知识库问答很容易超过模型的上下文窗口限制。把上下文窗口扩大是一个办法但成本会直线上升而且过长的上下文反而会引入新的注意力噪声。我的实践做法是三层递进。第一层检索块只保留最相关的TopKK值从5可以压到3很多场景下准确率不降反升。第二层对话历史做滑窗只保留最近两轮。第三层启用压缩提示词也就是第3.4节的内容先让模型把检索结果缩掉一半再进入主提示词。另外提醒一句设定Token上限时不能卡在模型窗口的最大值要为生成留出至少30%的余量否则可能出现生成一半被系统截断的情况。这属于工程红线踩过的人都知道。4.4 提示词效果到底怎么评估RAG提示词的改动如果没有量化评估约等于在盲调。我给一个轻量级评估思路准备一个30-50条问题的小测试集按业务重点分成几类比如“简单事实问答”“多跳推理”“指代追问”“无法回答类”。每一轮修改提示词后跑一遍测试集用三个方面打分答案准确率、引用命中率、拒答正确率。下面是我常用的一个小记录表问题类型用例数准确率引用命中率拒答正确率备注简单事实问答1593%87%-模板v3后引用下降指代追问1080%90%-改写模块修复指代后提升无关问题10--70%拒答偏高考虑放宽边界评估完不能只看总体准确率。引用命中率单独看很重要它是判断模型是否真正“跟着文档走”的关键指标。如果准确率还不错但引用经常张冠李戴说明提示词对来源标注的约束不够需要像2.2节那样强化格式绑定。5. 从提示词看向RAG系统的整体调优5.1 提示词不是万能的边界在哪做提示词做得越久越要承认一个事实提示词能解决的只有“模型会用检索结果”的问题如果检索本身召回的就是一堆错内容提示词写得再精妙也无济于事。但提示词可以作为检索质量的一面镜子。当模型频繁触发“知识库中未找到相关信息”的拒答分支大概率是查询改写或召回环节出了问题当模型总是引用同一个文档块大概率是检索排序对某类内容存在偏置。用好拒答率和引用分布这两个信号你能快速定位到RAG链路中真正需要优化的环节。所以我的建议是做RAG不要一头扎进提示词调优里出不来。提示词的合理投入周期是两周左右达到稳定效果后应该把精力逐步移向分块策略、Embedding选型、重排模型这些同样影响最终效果的方向。5.2 关于【ACP-LLM】这个系列的安排这篇文章是【ACP-LLM】系列中关于RAG提示词的入门篇。后续我会继续整理RAG相关的更多主题包括分块策略的细节与评估、查询改写进阶、多路召回与重排实践以及RAG系统整体评测方案。每个主题都会保持本篇的风格少讲空泛的原理多讲可复用的方案和踩坑记录。如果你正在做RAG应用欢迎对照本篇的模板先跑一个最小可行性版本再根据你的场景去调整。提示词这个东西看起来是写几行字的事但里面藏着大量需要实测才知道的经验。最后再分享一个我个人的习惯每次修改RAG提示词我都会把改动版本、评估分数、甚至当时模型的输出样本截图一起归档。这样当线上效果出现波动时我可以快速回溯是提示词改动引入的还是上游数据或检索变化导致的。这个习惯帮我省了非常多的排查时间也推荐你试试。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑