有一次线上事故让我彻底改了工作习惯。一个调度 Agent 忽然开始拒绝正常任务,排查了代码、日志、环境变量,最后发现同事在系统提示词里加了一句“如果用户请求有歧义,直接拒绝并说明原因”。他以为只是调了个语气,结果整个 Agent 的决策边界全变了。

我问他:改 Prompt 之前,你知道这会改变行为吗?他说知道一点。我又问:那你为什么没发版本变更?他愣住了。
这事让我认真想了一个问题:Prompt 改了,到底算不算 Agent 的新版本?如果算,版本号该怎么编排?如果不算,那什么才算?
Agent 不是一段代码,是一锅随时会变浓的汤
传统软件的版本管理很简单:源码变了,编译产物就变,打个版本号。Agent 不一样。你在生产环境跑的 Agent,由至少四个独立变化的组件组合而成:
- 编排逻辑:决定 Agent 先做什么、后做什么的代码或流程图。
- Prompt:系统提示词、few-shot 示例、输出格式规范。
- 模型:底层的大模型,以及具体是哪个快照(比如 gpt-4-0613)。
- 工具:Agent 能调用的函数、API Schema、工具描述。
再加上温度、top_p、max_tokens 这类推理参数,变量更多。
问题在于,这四个组件里任何一个发生变化,都可能改变 Agent 的输出分布。传统软件里,换个图片资源不会改变逻辑;Agent 里,换个措辞可能就改变了行为。这就是为什么你不能照搬 Git tag 的管理方式。
我最早把 Prompt 当配置,直到线上事故教我做人
刚做 Agent 平台的时候,我潜意识里觉得代码才是版本的主体。Prompt 嘛,顶多算个配置文件。于是我们给 Prompt 建了个在线编辑面板,改了就直接保存,不经过版本仓库。后来发生一件尴尬的事:客服 Agent 的输出质量突然下降,我们翻遍代码没找到异常,最后发现是产品经理在前一天通过面板微调了几个示例。
没有历史记录,没有 diff,没有任何人能说清线上跑的是哪一版 Prompt。我那时候才意识到:Prompt 不是配置,Prompt 是 Agent 的可执行逻辑的一部分。
为什么这么说?因为模型在没有 Prompt 的时候,是无差别的语言概率模型;有了 Prompt,它才变成“会客服的 Agent”。你往 Prompt 里加一句“先道歉再解释”,它就多了一个分支,这和代码里加一个 if 语句没有本质区别。
Prompt 算不算“新版本”?算,而且比代码改一行更算
你可能会想:代码是确定性的,Prompt 只是影响模型发挥。但事实是,Prompt 对行为的影响往往比代码更直接。OpenAI 的 Prompt Engineering 指南里反复强调:提示词的细微变化会显著改变模型的响应。一句“直接拒绝”可以让一个客服 Agent 从一个乐于助人的接线员变成防御式客服。
所以,修改 Prompt 绝对算版本变更。而且因为它的影响力常常超出直觉,你反而更应该在版本号上体现出来,至少让团队知道“Agent 的行为可能变了”。
把语义化版本搬到 Agent:MAJOR、MINOR、PATCH 分别对应什么
语义化版本规定:MAJOR 用于不兼容的 API 变更,MINOR 用于向后兼容的功能新增,PATCH 用于向后兼容的问题修复。这套规则搬到 Agent 上时,判断标准从“API 兼容性”换成“行为兼容性”。语义化版本规范中的数字含义依然成立。
| 变化范围 | 示例 | 版本段 |
|---|---|---|
| 行为不兼容 | 换模型(GPT-3.5 → GPT-4)、重构编排逻辑、改动 Agent 的核心角色设定(从客服改成销售) | MAJOR |
| 功能新增(向后兼容) | 新增工具调用、追加 few-shot 示例、在 Prompt 里增加新指令但不改变原有行为 | MINOR |
| 问题修复(向后兼容) | 修正 Prompt 拼写、调整示例顺序、降低温度以减少随机性 | PATCH |
注意,这个映射的关键是:版本号的分寸不是由你改了什么决定的,而是由改动对行为的影响程度决定的。同一个 Prompt 修改,在不同任务里可能算 MINOR,也可能算 MAJOR。比如给客服 Agent 加一句“语气更亲切”,也许只是 PATCH;但如果让一个技术客服开始处理退款,这是行为不兼容,必须 MAJOR。
要做到这种判断,你需要一个回归测试集,至少要有一条覆盖关键场景的 Prompt 用例。没有测试集,你只能在出事后捶胸顿足。
光有版本号不够:用指纹锁定“线上这锅汤”
版本号是给人看的,但人记不住每个版本的组件清单。比如 v3.1.0 是“加了新工具”,但是模型也升级了,Prompt 也微调了,光靠版本号你没法精确复现。
所以我会建议在版本号之外,为每次发布生成一个Agent 指纹(fingerprint):把代码 commit、Prompt 版本、模型标识、工具集版本、推理参数组合哈希。下面是我实际的记录格式:
{
"fingerprint": "sha256:3f9a7c...",
"semver": "3.1.0",
"code_commit": "a1b2c3",
"prompt_version": "p14",
"model": "gpt-4-0613",
"tools_version": "t3.2",
"config": {"temperature": 0.2}
}
每次上线前生成并存入元数据。回滚时按指纹重建,而不是翻聊天记录找“当时用的哪个 Prompt”。
模型版本和 Prompt 版本都是组件版本,不是 Agent 版本。你可以把 gpt-4-0613 视作一个依赖,就像后端代码依赖某个库的版本。Agent 版本号应该反映这些依赖组合而成的整体行为。
落地这套机制,最少需要四步
- 把 Prompt 移入 Git 仓库,和代码一起走评审、打 tag。不要再用单独面板直接改线上。这一步能解决 80% 的混乱。
- 为 Agent 定义一份“成分清单”,至少包含代码提交、Prompt 版本、模型标识、工具版本和推理参数。部署时自动生成指纹,写入元数据。
- 建一个覆盖核心任务的回归测试集。每次版本变更前跑一遍,用输出分布差异决定该升 MAJOR 还是 MINOR。
- 把版本号写进日志和监控。线上出问题时,日志里每一个 Agent 调用都带上 semver 和 fingerprint,你才能快速定位“这锅汤是哪天炖的”。
这套流程不花哨,但能救你命。
问答:四个常见的版本号纠结点
我就改了个错别字,算 PATCH 吗?
算。错别字可能导致模型误解概率,哪怕很低。既然动了,就标记,养成每次变更都发一个小版本的习惯。
我给 Prompt 加了一个新能力,但旧功能都正常,算 MINOR 吗?
算,前提是你有测试集验证旧功能没被破坏。如果新指令干扰了旧行为,那要升 MAJOR。
把底层模型从 GPT-3.5 换成 GPT-4,Prompt 没动,算 MAJOR 吗?
几乎肯定,因为输出分布会出现广泛差异,你现有调用方可能产生行为变化。注意区分:是模型版本变了,不是 Agent 版本号本身变了。你应该把“模型升级”记为一次 Agent 的 MAJOR 发布。
版本号有什么用?反正输出是随机的。
版本号不是用来保证行为确定的,它是用来保证“你能够识别出线上跑的是哪一个组合”。组合一致,随机性仍然存在,但分布大致可预期。你管理的是概率分布,不是单次输出。
管理的是概率分布,不是确定性代码
最后说一点我的判断。Agent 版本管理没有银弹,因为 LLM 的采样机制决定了同样的指纹也可能产生不一样的输出。所以“行为兼容”永远是一个统计概念,而不是布尔值。你不能说“这版和上版行为一样”,只能说“在测试集上,输出分布的差异在可接受范围内”。
这恰恰是为什么版本管理更重要:当随机性存在时,你更需要一个可复现的基线,否则你根本无法判断线上行为是版本问题、数据漂移还是单纯运气差。
我相信未来会有专门的 Agent 版本管理系统,像 Docker 管理镜像一样,把代码、Prompt、模型、工具组合打包成不可变快照,用哈希定位,用语义化版本号交流。在那之前,自己动手先做起来,总比出了事再翻聊天记录强。
原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/1422.html