登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  人工智能

AI 评测集为什么会被提示词污染:固定模板、变量隔离与回归验收

来源:17golang原创

时间:2026-08-24 12:33:42 496浏览 收藏

评测集分数突然上涨,未必是模型真的变好了。更常见的原因是上一轮提示词、答案示例或调试字段被写回了样本,模型在测试时提前看到了本不该出现的线索。排查这类污染,要把“样本原文、渲染后的提示词、模型输出”分开留存,再用固定快照做回归。

先把评测输入冻结成只读快照,再检查变量是否跨样本复用;只看最终分数,通常定位不到提示词污染。

要点速览
  • 评测样本只保存任务事实,不保存上一轮的提示词和模型输出。
  • 模板渲染必须使用一次性上下文,调试信息与正式输入分离。
  • 回归验收同时比对输入快照、渲染结果和输出分布。

先确认分数上涨发生在哪一层

把一次评测拆成三份可追溯的证据:case.jsonl 是原始样本,rendered.jsonl 是送入模型的最终文本,result.jsonl 是模型响应。三者都绑定同一个 case_id,绝对不能互相覆盖。若原始样本没有任何改动,渲染文本里却多出上一轮参考答案或者之前的调试标记,问题就出在模板渲染环节。

case_id=qa-017
input: 用户要求解释一个超时错误
expected: 能指出超时发生在连接建立阶段
rendered: system + task + input
output: 模型最终回答

先统计每个 case_id 对应渲染文本的哈希值。同一份样本在不同轮次渲染得到不同哈希值,不一定是错误;模板版本调整、系统提示词改动或者变量值更新都可能造成差异。但如果变化来源是另一个样本的答案、人工批注或者调试日志,就得立刻停止单纯的分数对比排查。

评测样本经过模板渲染到模型输出的调用链,标出变量串入位置

最容易串入的三个变量

第一类是循环外的可变字符串。代码把上一条样本内容拼进 prompt 后没有做清空处理,下一条样本自然就继承了前面的内容。第二类是全局共享的字典或者列表,渲染函数修改了传入的公共对象,后续样本读取到的就是被改写后的副本。第三类是重试记录:第一次请求失败时写入的错误说明,被误当成下一次请求的上下文带入。

变量隔离没必要依赖复杂框架,核心规则是让渲染函数只接收只读的样本数据,最后返回全新的字符串。下面的写法把历史输出放进独立的观测对象,正式提示词完全不会引用到这部分内容:

def render_case(case, template):
    values = {
        "question": case["question"],
        "constraints": tuple(case.get("constraints", ()))
    }
    prompt = template.format(**values)
    return {"case_id": case["case_id"], "prompt": prompt}

def record_result(rendered, response, trace):
    trace.append({"case_id": rendered["case_id"], "output": response})

这里的核心不是函数命名,而是明确边界:render_case 不读取 trace 模块里的历史数据,record_result 也不会往回改写 prompt 内容。如果评测场景必须加入检索资料或者少量示例,要为每个样本单独创建新列表,同时在日志里记录资料来源的唯一标识。

用哈希和抽样复核抓住污染证据

每次评测启动前,先为原始样本和当前模板生成 SHA-256 快照;每条渲染结果再单独记录 template_versioncase_idinput_sha256。验收时先核对元数据,再校验文本内容,这比从长篇大段的模型输出里人工找线索效率高很多。

抽样复核至少覆盖三类样本:队列第一条、触发过重试的样本,以及上一轮得分波动最大的样本。检查内容里有没有出现其他 case_id、内部人工评语、参考答案或者“只输出 JSON”这类不属于当前样本的字段。如果是包含用户隐私的评测集,日志里只保留哈希和脱敏片段,不要把完整输入同步到公共看板。

评测回归检查面板对比输入哈希、模板版本与输出分布

回归验收不要只看平均分

修复相关问题后,重新跑一遍同一份冻结的快照,至少比对四项内容:渲染文本哈希是否稳定、污染关键词命中数是否归零、各类别样本数量是否完全一致、之前的失败样本是否还能稳定复现。平均分可以作为最终结果指标,但绝对不能代替输入层的证据校验。

一个实用的门禁规则是:输入快照哈希不变,模板版本明确,污染扫描结果为零,同时重点样本的输出差异有人工可解释的依据。如果修复后分数回落,别为了拉高数字就把旧输出重新塞回提示词;先确认模型行为变化确实来自完全干净的输入。

常见问题

提示词里放少量上一轮输出一定算污染吗?

不一定。如果这是评测设计明确要求的多轮上下文内容,并且归属到当前样本的输入范畴,就应该写进样本定义里同时参与快照校验。没有提前声明、跨样本引用、无法追溯来源的上一轮输出,才是需要阻断的污染。

为什么单元测试通过,批量评测仍会串数据?

单元测试通常每次只会渲染一个样本,没办法暴露循环复用可变对象的问题。补一组顺序测试用例:先渲染包含长答案的样本,再渲染空答案样本,然后断言第二条提示词里不包含第一条的任何内容。

只保存最终提示词够不够?

不够。还要同步保存原始样本哈希、模板版本和变量来源信息,不然你只能看到最终渲染结果,没法判断差异是来自样本改动、模板调整,还是渲染阶段串入了多余数据。

发布前检查清单

  • 原始样本设为只读快照,case_id 唯一且样本总数稳定。
  • 渲染函数不读取历史输出,重试记录和正式输入分开存储。
  • 三份证据都记录哈希、模板版本和样本标识。
  • 首条、重试条目和分数变化最大条目完成抽样复核。
  • 污染关键词命中数为零,平均分之外的分布变化有明确解释。
声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>