3110 字
约 10 分钟
15
S22-A10 · 提示与模板的版本管理:改了怎么知道变好
提示改了一版,手感上更稳了,上线一周后投诉变多。难的地方不在于回滚——回滚只要一分钟,难的是当时凭什么判断它变好了。没有判据,改与不改都是掷硬币;有判据,改动才是一次可评估的发布。
1. 提示与代码的本质差异在哪
| 维度 | 普通代码 | 提示与模板 |
|---|---|---|
| 变更反馈 | 编译或测试立刻报错 | 只有输出质量变化,无异常 |
| 失败形态 | 抛错、超时、状态码 | 安静地给出更差的答案 |
| 依赖 | 库版本 | 库版本 + 模型版本 + 采样参数 |
| 回滚判定 | 错误率下降 | 需要先定义"什么算退化" |
| 评审 | diff 可读、可推理 | diff 可读,但后果不可推理 |
最后一行决定了一切:改一个函数你能预见影响面,改一句措辞不能。所以提示的版本管理核心不是"存版本",而是存判据。
// 一次提示发布的最小记录:改了什么、凭什么认为更好、怎么退
─── diff ─── 只改一句也要能看清单句(不要整段重写)
─── evidence ─── 评测切片 + 线上指标各一份
─── revert ─── 回滚目标版本号,必须在发布前就填好
2. 变更的三类效果与对应检测
| 效果 | 表现 | 检测方法 | 处置 |
|---|---|---|---|
| 明显变好 | 主指标与格式指标同时改善 | 离线评测集 + 线上指标 | 保留,记录原因 |
| 无差别 | 指标在噪声内波动 | 多次重跑取分布,而非单次 | 不保留,减少维护面 |
| 局部变好、全局变差 | 目标任务改善,其它任务退化 | 分任务/分场景切片对比 | 拆成更窄的场景或回滚 |
第三类是最常见的失误来源:只测了改动针对的那类问题,没测没动的地方。检测的关键动作是分片对比,把评测集按场景切开,看改动是否只在目标切片上升。
3. 判据不只准确率
| 指标 | 口径 | 退化信号 |
|---|---|---|
| 任务准确率 | 人工判定的正确率(无标准答案时用 rubric) | 目标切片升、其它切片降 |
| 格式合规率 | 可被程序解析的输出占比 | 解析失败率上升但人工看不出 |
| 拒答率 | 该答而拒的比例 | 上升说明约束写过头 |
| 长度分布 | 输出的 P50/P95 字符数 | 中位数漂移说明提示在膨胀 |
| 首 token 延迟 | 提示长度带来的直接成本 | 变长即变贵,与质量无关 |
只盯准确率会漏掉两类事故:格式坏了(下游解析失败)和拒答多了(用户觉得"变笨")。格式合规率是工程侧最该先看的指标,因为它是唯一能被程序自动判定的。
4. 评测集怎么造,以及它一定会过拟合
| 样本类型 | 来源 | 作用 | 失效方式 |
|---|---|---|---|
| 真实失败样本 | 线上工单、人工标记的 bad case | 最贴近真实分布 | 反复调优后被"背下来" |
| 边界样本 | 空输入、超长输入、多语言混排 | 防崩溃 | 覆盖不全,永远补不完 |
| 对抗样本 | 注入、诱导、角色越界尝试 | 防越界 | 一旦写进评测集就失去突袭性 |
| 正常样本 | 抽样线上真实流量 | 防"修好一个坏十个" | 抽样偏差导致过度乐观 |
自建评测集一定会过拟合:你越按它调,它越不能代表未来。可操作的对策有三条——保留一份不参与调优的留出集(只在发版前跑一次)、定期用新样本替换旧样本、把线上指标当第二判据,而不是把评测集通过率当结论。
5. 四种管理形态与回滚速度
| 形态 | 改动成本 | 回滚速度 | 主要风险 |
|---|---|---|---|
| 代码里的常量 | 需要发版 | 分钟级(重新部署) | 与业务代码耦合,回滚带走其它改动 |
| 配置文件(随镜像) | 需要发版 | 分钟级 | 与代码不同步,出现"哪个版本"的争论 |
| 配置中心 | 即时 | 秒级 | 无评审即可改,越权变更 |
| 数据库 | 即时 | 秒级 | 无法 diff、无版本史,最容易失控 |
// 配置中心结构:按场景收敛版本,禁止就地覆盖
prompt:
scene: SCENE_A
version: v12 // 单调递增,不写 latest
template_ref: tmpl/SCENE_A/v12.md
params: { tone: concise, max_items: 5 }
model_ref: MODEL_ID@MODEL_VERSION // 提示与模型必须成对记录
rollback_to: v11
选择形态的依据是回滚要多快,不是"哪种更先进":回滚窗口是秒级的场景(对客对话)用配置中心;日级窗口(离线批处理)用随代码发版就够。
6. 提示与模型是联合变量
改了模型不重测提示,等于把两个变量一起动。记录必须成对:
// 一次"行为版本"由四元组唯一确定,任一项变化都算一次发布
{
"prompt_version": "v12",
"model": "MODEL_ID",
"model_version": "MODEL_VERSION",
"decode_params": { "temperature": 0.2, "top_p": 0.9 }
}
// 归因顺序:先固定提示换模型,再固定模型换提示
─── 1) 锁模型,比提示 v11 vs v12 ─── 变化归因于提示
─── 2) 锁提示 v12,比模型 A vs B ─── 变化归因于模型
─── 3) 两者都要动 ─── 当成两次发布,中间必须各跑一次评测
7. A/B 的统计陷阱
| 陷阱 | 表现 | 处理 |
|---|---|---|
| 样本量不足 | 50 次调用就宣布提升 5% | 按效应量定样本量,不按"看起来够了" |
| 多重比较 | 同时比 8 个指标,总有一个显著 | 先定主指标,其余只做观察 |
| 流量不随机 | 灰度按用户 ID 分段,与人群特征相关 | 随机分流,检查分流后的分布一致性 |
| 效应量太小 | 真实差异在噪声内,长期跑也测不出 | 只对可感知的差异做实验 |
| 提前看结果 | 边跑边看,看到显著就停 | 固定观测窗口,避免 peek 偏差 |
// 定样本量的粗口径:先定最小可感知差异,再决定要看多少条
─── 1) 主指标基线 p0(如 0.80)与最小可感知提升 d(如 0.02)
─── 2) 用二项分布的常规公式估每组样本量,量级通常在每组数千条
─── 3) 达不到样本量就接受"这次测不出来",不要用直觉补缺口
分组指标必须按版本切分统计,否则新老提示混算,A/B 变成平均。
8. 腐化的信号
| 信号 | 观察方式 | 说明 |
|---|---|---|
| 越来越长 | 平均提示长度单调上升 | 每加一条例外都在付 token 与延迟成本 |
| 例外越堆越多 | 条件分支数增长 | 从规则变成特例的集合,无法推理 |
| 互相矛盾 | 规则之间冲突,模型自行取舍 | 表现为输出不稳定 |
| 只增不删 | 从未删除过规则 | 说明没有人在做减法 |
| 改一处坏一处 | 每次改动都要修旧问题 | 提示已超出可维护复杂度 |
// 腐化度量:长度与分支数进入版本记录,随版本画趋势
─── 1) 长度 ─── wc -c tmpl/SCENE_A/v*.md
─── 2) 分支 ─── grep -c '如果\|若\|when' tmpl/SCENE_A/v12.md
─── 3) 判定 ─── 长度与分支同时上升且准确率持平,就该做减法而不是继续加规则
9. 模板化的边界
| 部分 | 该参数化 | 该写死 |
|---|---|---|
| 语气、长度、条数 | 参数化(按场景调) | — |
| 输出格式与字段名 | 参数化,但由代码生成 | — |
| 安全与拒绝边界 | — | 写死,不接受运行时覆盖 |
| 业务口径与定义 | — | 写死,改动走评审 |
| 少样本示例 | 可参数化,但需随版本记录 | 与口径绑定的示例写死 |
判断依据是"谁能改":能被业务侧随时改的部分参数化,改错代价高的部分写死。把拒绝边界做成可配置,等于把它交给变更最随意的人。
// 结构分层:越靠下越不该动,动它等于换功能而不是调优
─── 产品层 ─── 语气、长度、条数(可按租户配置)
─── 接口层 ─── 输出字段与解析规则(由代码生成,不手写)
─── 口径层 ─── 业务定义与边界(评审 + 版本记录)
─── 安全层 ─── 拒绝边界与身份约束(写死,不进入配置)
10. 度量
| 指标 | 口径 | 用途 |
|---|---|---|
| 评测通过率 | 评测集通过数 / 总数(分片统计) | 每次发版的准入门槛 |
| 回滚次数 | 单位时间内提示回滚次数 | 高说明评测与线上不一致 |
| 平均提示长度 | 每场景 P50/P95 字符数 | 成本与腐化趋势 |
| 变更到发现退化时长 | 上线到告警/投诉的时间差 | 反映线上判据是否有效 |
| 格式合规率 | 可解析输出占比 | 最廉价的质量哨兵 |
11. 排错:管了版本仍然反复
| 现象 | 更可能的原因 | 处理 |
|---|---|---|
| 评测通过、线上变差 | 评测集过拟合,或线上分布不同 | 用留出集 + 线上分片指标复核 |
| 同一个提示有两份"最新版" | 版本标识用了 latest 或按时间取 | 版本单调递增且不可变 |
| 回滚后问题没消失 | 同时动了模型或参数 | 回滚按四元组整组回退 |
| 提示改动没人知道 | 配置中心可无评审直改 | 变更留操作者与原因 |
| 修好 A 场景坏了 B 场景 | 未做分片对比 | 每次改动跑全切片评测 |
12. 边界
| 场景 | 判断 | 理由 |
|---|---|---|
| 一次性任务、用完即弃 | 不建版本,只留结果 | 演进收益为零 |
| 输出可由人即时判断的低风险环节 | 只留审计记录,不建评测集 | 人已是判据 |
| 模型本身要换 | 提示版本管理的收益被模型差异淹没 | 先稳定模型再谈提示 |
| 单场景、单一开发者 | 文件 + 评审即可,不上配置中心 | 平台成本高于收益 |
| 提示极短(一句指令) | 只需版本记录与回滚路径 | 复杂度不在这里 |
13. 自测
- 提示改动和普通代码改动,失败形态上最关键的区别是什么?
- 为什么"局部变好、全局变差"最容易漏检,该怎么测?
- 评测集一定会过拟合,三条对策里哪一条最容易被跳过?
- 为什么提示与模型必须成对记录才能做归因?
- A/B 做到一半看到显著就停,会引入什么偏差?
- 哪些内容该参数化、哪些必须写死,判断依据是什么?
S22-A10 · 提示与模板的版本管理:改了怎么知道变好
https://www.clxhxhhr.top/posts/6283/ 评论
0 条
还没有评论,先写一条吧。