这道题其实本质在问一件事:你怎么让大模型在生成时,既充分利用检索到的上下文,又不被它带偏,还能产出可信的回答。核心就两个点,让模型明确知道‘要回答什么’和‘能参考什么’,同时把信息密度做到最大,别让指令淹没在资料里。
先说说最常见的模板结构。最通用的就是经典QA式,系统指令先定好角色,说‘你是基于文档回答的助手,严格根据参考资料回答,资料不足就说明’,然后把检索结果拼进去,最后放用户问题。这个模板好处是简单直接,但有个坑,如果检索结果太长或太杂,模型容易忽略指令。所以我会在模板末尾加一段明确的约束,比如‘优先综合多段资料,不确定时回答“根据现有资料无法确定”’。
再一个就是带引用标记的模板,这个在防[[Hallucination]]和溯源时特别有用。我会给每段资料编个号,比如[1][2],要求模型回答时必须带引用标记。这样下游校验时,一眼就能看出哪句话对应哪段资料。不过前提是检索结果本身质量要过关,如果资料本身就不相关,模型硬引用反而会误导用户。
还有对话历史融合式,主要用在多轮[[RAG]]场景。比如客服系统里,用户先问‘退款政策’,再追问‘那退货运费谁出’,这时候要把历史对话和当前检索到的资料一起放进去,模型才能理解上下文。但这里有个风险,历史对话太长会稀释当前资料的重要性,所以我会控制历史轮数,最多保留两轮。
进阶策略里我重点讲两个。一个是动态[[Few-shot]],从检索结果里挑一两个高质量问答对作为示例,注入到Prompt里。这比单纯给指令更直观,模型看到例子就知道该怎么组织答案。但前提是检索到的示例确实优质,如果示例本身有错,反而会带偏模型。另一个是上下文[[重排序]],把最相关的文档放在Prompt末尾,利用[[In-Context Learning]]的近因效应。这个在实测中效果很明显,但要注意,如果相关性判断不准,把不相关的放末尾,模型反而会忽略真正重要的资料。
落地时有个常见失败场景:检索到的上下文中,不同资料相互矛盾。比如企业SOP文档,旧版本说‘满200减50’,新版本说‘满300减80’,模型如果只依赖其中一段就会出错。我的做法是在Prompt里加一句‘如果资料冲突,以最新时间戳为准’,同时要求模型输出时注明‘根据某年某月版本’。
说到这,其实还有一个更激进的方向,让模型自己决定要不要调用检索,而不是每次都硬塞上下文。比如[[Self-RAG]]的思路,模型先生成一个初步答案,再判断是否需要检索补充。这个在知识库更新频繁的场景特别有用,但实现复杂度也高。
所以整体上,我更倾向于根据不同场景组合使用模板:客服退款这种高频简单问题,经典QA式加引用标记就够了;政策解读这种依赖多段资料的,就加动态Few-shot和重排序。核心前提是检索质量要过硬,否则Prompt设计得再好也白搭。