基准测试指标连续四个季度上升。用户满意度却没有。团队中没有人能解释这种差距,直到有人对提示词模板进行了 diff,并注意到 Few-shot 示例正从评估器读取的同一个 CSV 文件中获取。评估集已悄然变成了上下文示例。这个指标不再衡量泛化能力。它衡量的是模型在刚被告知答案的情况下,复制与之最接近问题的能力。
这就是我想命名的失效模式:评估集到提示词的泄露 (eval-to-prompt leakage)。它在结构上与传统机器学习中的测试集污染 (test-set contamination) 完全一致,但它是通过团队刻意构建的后端通道发生的。Few-shot 检索是一个合理的工程举措。评估库是一个合理的工程产物。当两者在没有人划定界限的情况下汇集到同一个存储层时,污染就产生了。
两个语料库是如何合二为一的
大多数团队并不是故意泄露评估集的。合并是循序渐进发生的,且每一步在局部看来都是合理的。
第一季度,一个小团队精选了 200 个涵盖请求分布的示例。CSV 文件存放在与提示词模板相同的代码库中,因为当时还没有独立的评估基础设施。核心准确率指标是通过将每个示例输入当前提示词,并将输出与标注的答案进行对比来计算的。
第二季度,有人在推理提示词中添加了动态 Few-shot 检索。检索索引需要一个标注示例的来源。评估 CSV 是团队拥有的唯一标注语料库,因此检索索引指向了它。推理提示词现在会在运行时从评估 CSV 中选择三个示例并包含在上下文中。评估流水线没有变化;它仍然迭代同一个 CSV,调用同一个提示词模板,而该模板现在从它正在迭代的 CSV 中检索内容。
第三季度,团队添加了更多示例以扩大 Few-shot 覆盖范围。示例进入了同一个 CSV,因为那是存放示例的地方。评估集与 Few-shot 池同步增长,因为它们是同一个文件。
到了第四季度,评估指标已经与用户能感知到的任何东西脱节了。核心准确率是对包含答案的索引进行最近邻查找的衡量。每一个提高检索相关性的提示词更改都会拉升基准测试。但没有一个能提高泛化能力。
根本原因不是 Few-shot 检索这一举措。根本原因在于示例库和评估库是同一个物理产物,同时被服务路径和评估路径查询,且没有强制隔离。这两个语料库从未被赋予不同的名称,因此它们合并了。
为什么仪表盘上很难发现这种污染
这种泄露看起来不像是 bug。它看起来像是基准测试在按设计运行。
最近的污染研究表明,即便只是部分暴露在基准测试内容中,也能给模型提供足够的信号,使其在不学习任务的情况下获得高分。大模型会利用提示词中的微小模式,而一个能选出词法相似的评估示例的 Few-shot 检索路径,正在完美执行它的预定任务。模型并没有作弊;它只是按照工程团队的指示使用上下文窗口。基准测试输出和服务输出一起偏离了用户体验,而从仪表盘内部看,并没有任何异常需要标记。
团队的本能是信任趋势线。趋势线是真实的 —— 模型在“针对与刚在上下文中展示的标注示例非常相似的输入,产生一个与标注答案相匹配的输出”这一任务上确实变得更强了。这与用户执行的任务不同,但仪表盘没有字段来体现这种区别。
这种差距首先出现在定性审查中。产品经理打开一个采样会话,看到一个措辞稍偏离分布的问题得到了一个自信的错误答案,并询问为什么基准测试没有捕捉到它。答案是基准测试无法捕捉到它,因为基准测试只衡量模型在与其正在检索的 Few-shot 池相似的输入上的表现。分布外的案例是用户可见的全部失效模式,而这正是评估流水线在结构上无法看到的唯一情况。
这是学术基准测试团队在过去两年中一直记录的污染问题的后端通道版本。导致排行榜分数虚高的相同机制 —— 训练语料库与测试语料库之间的隐性重叠 —— 现在正在单个生产流水线内部运行,且反馈循环更短,可见度更低。
在被正式定性前的征兆
在团队识别出泄露之前,通常会出现三种信号。
首先,基准测试稳步提升,而用户报告的质量陷入停滞。每一次提示词更改都能产生可衡量的准确率提升。同期用户感知的累计改进却是持平或略微负面的。团队将这种差距解释为“用户难以取悦”或“满意度是一个滞后指标”。实际上,是基准测试偏离了它声称要衡量的东西。
其次,模型的置信度校准在评估中看起来非常好,但在生产环境中却是失准的。模型对评估输入高度自信,因为答案实际上就在上下文中。生产输入没有这种脚手架,因此相同的提示词在面对新颖的措辞时会产生过度自信的错误输出。校准误差变成了与 Few-shot 池距离的函数,而不是模型能力的函数。
第三,改写探测显示出急剧下降。如果团队从评估集中取出一部分保留数据,改写每个输入以保持语义但消除精确的词法匹配,并重新运行基准测试,准确率会下降 10 到 30 个百分点。团队在第一次发生时会把改写结果归结为“噪声”。第二次发生时,就会有人打开提示词模板。
弥合差距的模式
修复方法并不是移除少样本检索。检索增强型少样本(Retrieval-augmented few-shot)是一项合理的技术。修复的关键在于强制隔离模型在推理时可见的语料库与评估器用于评判它的语料库。为了实现这一点,必须同时落实几个原则。
存储层隔离。 将少样本池和评估集放入具有不同访问模式的独立存储中。线上路径从一个存储中检索,评估器从另一个存储中读取。代码评审不是强制执行此操作的正确层级——单个未经审核的迁移脚本就曾导致最初的隔离失效,而在忙碌的时候,代码评审仍会让同样的迁移操作通过。边界需要建立在存储层,以便在线上查询在任何配置下都无法访问评估存储。
检索路径无法触及的留存评估切片。 即使存储已经隔离,将新标注的示例填充到少样本池的诱惑最终仍会导致评估项意外进入推理语料库。防御手段是设置一个在结构上无法访问的留存切片(held-out slice)——不同的存储、不同的 schema、不同的访问凭证。留存切片应至少占评估集的 20%,且核心指标应基于该切片计算。剩下的 80% 可以作为上下文检索池,同时充分意识到这些示例是被污染的。
评估器中的污染探测。 对于每一次 Prompt 变更,评估器都应该对模型进行两次评分:一次基于原始评估输入,另一次基于留存切片的改写版本(以规避词法检索)。这两个数值之间巨大的差距意味着检索承担了大部分工作。这种探测能让团队持续了解基准测试的提升中有多少是泛化能力的提升,有多少仅仅是因为索引邻近性。
针对污染增量的发布门禁。 将被污染准确率与干净准确率之间的差距视为一项护栏指标(guardrail metric),而非仅仅是诊断指标。如果一个 Prompt 变更提升了 3 个百分点的污染准确率,却降低了 2 个百分点的干净准确率,那么它就不该发布。发布门禁迫使团队去优化用户体验到的指标,而不是由检索带来的虚假指标。
评估套件的隔离版本控制。 像传统机器学习对待测试数据那样对待评估数据:隔离、版本化,且只能通过封装好的评估流程访问。线上路径不应具有评估存储的读取权限。评估器不应写回线上存储。边界应该能够从基础设施日志中强制执行,而不是依靠团队的自觉性。
团队未曾察觉的成本陷阱
评估泄漏在单位经济效益(unit-economics)上有着鲜为人知的滞后性影响。团队每季度花费在通过增加示例库来追求基准测试分数的努力,都是一种无法转化为用户价值的质量投资。投入了工程工时,仪表盘上的数据上升了,产品却毫无起色。公司在支付改进带来的工资成本和运行更复杂 Prompt 的模型成本的同时,却没有获得相应的收入提升。将这种效应乘以四个季度,泄漏就会消耗掉团队相当大一部分产能,却产不出任何用户能感知到的东西。
下游成本更难量化,但也更危险。团队一直在建立关于哪些 Prompt 变更有效的直觉,而这些直觉是根据一个测量检索而非能力的基准测试来校准的。当领导层的决策依赖于基准测试时——“我们发布新模型,因为评估显示提升了 15 个点”——该决策所依据的数字已经脱离了现实。不分离语料库的团队发布的只是一个上扬的曲线,而不是一个更好的产品。
那个无人提及的边界
架构上的领悟细微且令人不安:示例库和评估库在磁盘上看起来一模一样,但在你的单位经济效益中表现却截然不同。即使它们都在同一个 CSV 文件里,它们也不是同一种制品。那些没有在存储层定义边界的团队,实际上是在把训练集当成基准测试发布,基于该基准测试建立的任何 Prompt 工程流程都是在针对一个受污染的目标进行优化。
防御之道在于通过架构设计使泄漏变得不可能。两个存储库。密封式访问。线上路径不可见的留存切片。在每次发布时报告增量的污染探测。这些都不是研究难题,它们是团队未曾预算的基础设施问题,因为最初的 CSV 看起来毫无危害,而合并是一个季度接一个季度慢慢发生的。
及早支付基础设施成本。否则,团队将在接下来的四个季度里去追逐一个并不存在的数字。
会员专享
余下内容仅对会员开放。
会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
- —完整文章,包含未公开存档的部分
- —可落地的工作框架,附带权衡与决策依据
- —新文章抢先看,先于公开发布
随时取消 · 一次订阅,畅读全部