这道题其实是在问,检索准了为什么生成还是不行,本质就是检索和生成之间的解耦问题。很多人觉得检索准了回答自然好,但实际落地中,瓶颈往往在中间环节和生成阶段。
具体说一下,我拿客服退款场景举个例子。用户问“我昨天买的东西降价了,能不能退差价?”检索模块把退货政策、满减规则、订单状态好几篇文档都捞回来了,每篇单独看都对。但如果你把这些文档一股脑拼接进prompt,顺序乱的,关键信息被淹没,模型可能就只看到“满减”这个词,然后回答“满减活动不可叠加”,完全没处理“降价退差价”这个核心诉求。这就是典型的检索准但生成崩。
那原因到底在哪?我一般分三个层面看。先说上下文组织。文档拼接顺序很关键,比如把最相关的政策放前面,但实际中经常是检索得分排序直接灌进去,而得分高的不一定是对生成最关键的。还有冗余问题,多篇文档信息重叠,占满上下文窗口,真正有用的信息反而被挤掉。再一个,不同文档之间可能有信息冲突,比如一篇说“7天内可退差价”,另一篇说“促销商品不退差价”,模型没指令去消解,就会乱。
然后看提示设计。很多时候prompt里就一句“根据以下文档回答问题”,没有明确约束说“优先基于文档,不确定就说不知道”。模型生成自由度一高,就开始自己编。这里有个坑:temperature设高了容易[[幻觉]],设低了又可能太保守,连文档里有的信息都不引用。
另外还要看模型本身。有些模型指令遵循能力弱,你给它一堆文档,它分不清哪些是事实哪些是噪声。尤其小模型,上下文一长就丢失信息。
那怎么调优呢?我一般按四层递进。先从检索后处理下手,这是性价比最高的。比如加个[[Rerank]],把文档按生成相关性重新排序,而不是按检索分数排。冲突检测也很实用,比如两篇文档结论矛盾,可以用摘要融合或者直接标记让模型判断。上下文压缩工具比如LLMLingua,能去掉冗余,腾出空间给有效信息。
第二步是提示优化。明确告诉模型“基于以下文档回答,如果文档没提到,就说不知道”,并且要求引用来源。还可以加个兜底策略:如果模型不确定,就拒绝回答,别硬编。
第三步是模型层面。如果条件允许,用[[RAG]]场景的[[SFT]]数据微调一下模型,让它学会怎么利用检索结果。调低temperature到0.1-0.3,减少随机性。模型本身也尽量选上下文窗口大的,比如128k的,这样能塞更多文档。
第四步是系统架构升级。比如用[[Self-RAG]]让模型自己判断检索结果是否足够,不够就再检索。或者用[[Corrective RAG]],发现检索质量差时主动纠正。但这些架构复杂度高,前提是前两步已经优化到位,不然直接上架构容易出bug还难排查。
说到这,其实有个容易被忽略的点:文档本身的质量。如果知识库里的文档本身就过时、矛盾、或者粒度不对,你再怎么调检索和提示都没用。所以我会把RAG看成从数据到提示到模型的完整链路,而数据质量是地基。
最后落地时,我有个快速验证路径:先人工检查拼接后的prompt,看看上下文是不是清晰、信息有没有冲突。这一步能暴露80%的问题。然后再逐步调重排、提示、模型参数,别一上来就调temperature或换模型,那样容易盲目。
所以我的整体判断是:检索准只是起点,真正的工程挑战在怎么把检索到的信息组织成模型能理解的输入。我更倾向于先花精力在数据清洗和上下文组织上,再考虑模型和架构升级。