Prompt 版本管理
Prompt 是会改变行为的代码。按代码对待它,并把评测结果挂在版本上。
Prompt 决定你的系统做什么。改一条 prompt 就改变了行为,有时改得很彻底,而且不会有编译错误,也不会有类型检查。
所以 prompt 就是代码。该用的实践就是你已经在用的那些,再加上两条这种材料特有的。
放进版本控制,和代码在一起
Prompt 应该待在仓库里、文件里,像其他东西一样走评审。
另一种做法——prompt 放在数据库或管理后台里、运行时随时可改——听起来很美,实际问题不小。行为变了却没有发布、没有评审、没有记录。过去的事故没法排查,因为你复原不出当时的 prompt 是什么。
如果非工程同学必须能改 prompt,编辑界面可以留,但背后要有版本历史、评审,以及能精确查出某个时间点线上跑的是哪一版。
模板与数据分开。 把 prompt 的结构放在带占位符的文件里,运行时再注入变量。由好几个函数拼字符串拼出来的 prompt,没法作为一个整体被评审。
把评测挂在版本上
这条实践把 prompt 管理和普通文件管理区分开:没有评测结果的 prompt 版本,就是未经验证的。
每次改动都应该记下它在评测集上得了多少分。不记,你手里就只有一串修改历史,完全不知道哪几次有用。
有了它,其他做法才立得住。回滚有意义了,因为你知道上一版的分数。对比变得可行。回归也能被看见,而不是等用户来发现。
具体做法:prompt 一改就在 CI 里跑评测,把结果和版本存在一起。分数掉了,就当一次测试失败来处理。
日志里带上版本标识
每次响应都记下是哪个 prompt 版本产出的。见 LLM 系统的可观测性。
不记的话,排查上周一条糟糕的响应就只能靠猜当时的 prompt 长什么样——而在活跃开发中,prompt 的改动频率比代码还高。
用内容哈希就可以,不需要任何人为的纪律来维持。
模型版本也是配置的一部分
一条 prompt 是针对某个具体模型调出来的。同一条 prompt 换到别的模型上表现不同,有时很差。
所以可部署的单元是这一对:prompt 版本加模型版本。两个都要记日志,任意一个变了就重跑评测。
麻烦的地方在于,托管服务商更新模型时并不会改版本名,所以模型可能在你什么都没做的时候就变了。定期跑评测是唯一能发现这件事的办法——所以哪怕什么都没改,也值得把定时评测搭起来。
上线改动
但凡有点影响的改动,都不要一步全量替换。
先影子运行。 在真实流量上让新 prompt 和旧的一起跑,两个都记日志,线上仍用旧的。用真实输入做免费对比,用户侧零风险。
然后放一小部分线上流量,对比指标。见 A/B 测试 AI 功能。
让回滚变得毫不费力。 改一行配置,而不是发一次版。
组织 prompt
一条 prompt 一个文件,按用途命名。
把共用片段抽出来——输出格式说明、安全模板、公共上下文。重复的片段会各自漂移,而漂移会带来谁都不想要的不一致。
给不显然的约束加注释。 prompt 会越积越长,每一行当初都是为修某个具体失败加的,半年后没人知道哪一行防的是哪个问题。一句 加上它是因为没有它就会编造引用 的注释,能防止别人把它当冗余删掉。
这个注释习惯比听起来更值。没注释的 prompt 行会在清理时被删掉,然后那个 bug 就回来了。
要点回顾
- prompt 就是代码:进版本控制、走评审、用带占位符的文件,而不是到处拼字符串。
- 每个版本都挂一份评测结果——未经验证的 prompt 版本,正是这一条要解决的核心问题。
- 每次响应都记下 prompt 版本,并把 prompt 加模型版本当成一个可部署单元。
- 托管模型会悄悄变化;评测要按固定周期跑,不能只在改动时跑。
- 上线路径:影子运行,再放小比例流量,回滚要毫不费力。
- 给约束写上它为什么存在,否则它会被删掉,bug 会回来。
下一篇: A/B 测试 AI 功能