跳到主要内容

增长速度快于评估套件的系统提示词

· 阅读需 11 分钟
Tian Pan
Software Engineer

你发布 Agent 的那天,系统提示词(System Prompt)仅包含三条规则和一个语气指令。评估测试集(Eval suite)为每条规则覆盖了十个案例,CI 徽章是绿色的,团队理所当然地感到自豪。十八个月后,同样的提示词变成了四十条规则、六个工具描述、四个 Few-shot 示例、两个安全前导语,以及一个在每次事故后都会增加一项的拒绝分类法。相比之下,评估测试集可能只增加了二十个案例——每个事故增加一个,且都是在压力下编写的,从未针对通过日常提示词 PR 悄无声息引入的几十条规则进行补测。

当 PR 发布时,团队仍然会说“评估通过了”。他们实际的意思是“我们十八个月前编写的评估,在针对那些评估已无法完全描述的提示词时依然通过了。”置信区间的分母在默默扩大,而分子几乎固定不变。下一次触及三十七条未测试规则之一的提示词修改,将被一个对其毫无判断力的测试集评定为安全。

这与没有测试的代码模式相同,只是提示词的增长与评估的增长之间的不对称性让情况变得更糟。一条提示词规则只有一行——输入、提交 PR、从读得懂英语的队友那里获得点赞、发布。而一个评估案例是一个结构化的产物——编写输入、编写预期行为、编写评分器(grader)、将其集成到 CI 中、标记其覆盖范围。前者只需要三十秒,后者需要一个下午。这两个层面正以不同的梯度演进,唯一能让它们保持同步的,只有团队对上次审计测试集时存在哪些规则的记忆。

提示词是没有编译器的代码平面

对系统提示词的常规解读是将其视为指令——模型所依赖的自然语言引导。这种构架虽然正确但并无用处。一个更有用的构架是:系统提示词是一组可寻址、可单独测试的规则,只是恰好以纯文本形式编码。每条规则都是一份契约:在条件 X 下,模型应产生行为 Y。规则是用英语编写的这一事实并不意味着它们不是规范;它只意味着编译器就是模型本身,而编译发生在推理阶段,且作用于你可能采样也可能未采样的流量上。

当你以这种方式看待提示词时,你开始提出的问题就是你会对一个服务提出的问题。这个提示词编码了多少条规则?其中哪些有测试?哪些有生效的测试——即产生有意义的通过/失败,而不是退化为“模型没崩溃”?哪些规则相互冲突?哪些规则已经失效——由一个触发场景不再出现在生产流量中的评估所维护?

这些问题中没有一个可以通过阅读提示词来回答。只有通过将提示词视为工具的输入才能回答。不构建这些工具的团队是在凭信念行事,相信“我们知道里面有什么”——而一旦最初的作者轮换出团队,这种信念就是剩下的唯一东西了。

规则是如何在没有测试的情况下进入的

提示词增长与评估增长之间的双轨漂移有几条特征性的进入路径。识别它们是阻止它们的大部分工作。

第一种是事故补丁。生产环境产生了错误的输出,事后分析确定根本原因是提示词未能预见到某种场景,修复方案是在系统提示词中增加一个新句子,并且针对该特定场景的回归测试在同一天被添加到测试集中。新规则有了覆盖。到目前为止一切都很好——除非在下一个 Sprint 中,同一位作者为了解决新规则边缘情况与旧行为的重叠,在相邻规则中添加了一个澄清条款。这个澄清条款在没有自带测试的情况下发布了,因为没有事故来推动它。随事故而来的规则经过了测试;而与之并存的规则却没有。

第二种是安全插件。一项新法规、一类新的误用、或来自安全审查的新发布阻碍因素产生了一个前导语。前导语被视为政策而非逻辑——它由政策团队审查、批准并合并。政策文本很少伴随评估案例,因为负责政策的团队并不负责评估测试集。规则作为文本进入提示词,别无他处。

第三种是 Few-shot 渐长。有人注意到模型在给定示例时能很好地处理特定的歧义,于是他们添加了一个示例。然后有人添加了第二个示例来覆盖相邻的案例。然后是第三个。六个月后,提示词有了四个 Few-shot 示例,它们共同暗示了一条团队从未明确写下的行为规则。规则存在,规则塑造输出,规则未经过测试——而且与其他两条路径不同,规则甚至没有被写成规则。它是示例的一种涌现属性。

第四种是工具描述重写。工具目录发生了变化;描述被更新以反映新的参数或新的返回结构;提示词的工具部分增长了二十行。编写更改的是工具团队而非提示词团队,而提示词团队没有注意到新的描述隐含了一种使用模式,该模式与系统提示词中三页前的某条规则相冲突。

在这些路径中的每一条中,规则通过低摩擦进入,而评估则因为高摩擦未能进入。结构性的修复方案是反转这种摩擦。

覆盖率是一个比率,而分母才是难点

加载中…
References:Let's stay in touch and Follow me for more thoughts and updates