4、版本管理基础:语义化版本控制(SemVer)、Git在模型管理中的应用、版本号命名规范

好,咱们进入正题。版本管理这事儿,说实话,在纯软件领域已经非常成熟了。但到了边缘计算设备上,尤其是AI模型管理这块,很多人就懵了。我见过不少团队,模型文件命名成「model_final_v2_真的不改了.onnx」——嗯,你懂的,最后往往还有一版「最终版_v3」。

今天我就把这块掰开揉碎了讲。核心就三件事:语义化版本号怎么定、Git怎么管模型、命名规范怎么统一

4.1 语义化版本控制(SemVer)在模型管理中的落地

语义化版本控制,简称 SemVer。格式很简单:主版本号.次版本号.修订号。但用在模型上,你得重新定义每个数字的含义。

我个人习惯这样映射:

版本位 软件领域含义 模型领域含义(我的建议)
主版本号 不兼容的API变更 模型架构变更、输入输出格式变化、算子集不兼容
次版本号 向下兼容的功能新增 精度提升、数据集更新、后处理逻辑优化
修订号 向下兼容的问题修正 量化参数微调、bug修复、推理性能优化

举个例子。你有一个人脸检测模型,版本号是 1.3.2。这意味着:

  • 主版本1:模型架构是MobileNet-SSD,输入640x480,输出格式固定。
  • 次版本3:从第2版到第3版,换了更大的训练数据集,mAP提升了2个点。
  • 修订号2:修复了某个光照条件下误检的bug,或者把INT8量化后的精度损失从1%降到了0.3%。

重要原则:一旦你改了模型结构,或者推理代码需要跟着改,主版本号必须加1。别偷懒。我在项目中遇到过,有人只改了次版本号,结果部署到旧设备上直接崩溃——因为新模型用了旧芯片不支持的算子。

我的小技巧:在模型的元数据文件里,直接嵌入版本号。比如ONNX模型的model.producer_name字段,或者自定义的JSON描述文件。这样模型文件本身就能自述身份。

4.2 Git在模型管理中的应用

Git管理代码没问题,但管理模型文件?很多人觉得「模型文件那么大,Git会炸」。其实不然,关键看你怎么用。

我一般分三种场景:

  1. 小模型(<10MB):直接纳入Git仓库。比如一些轻量级分类模型、唤醒词模型。方便,一条git log就能看到所有变更历史。
  2. 中等模型(10MB-100MB):用Git LFS(Large File Storage)。说白了就是把模型文件的实际内容存到远端,仓库里只保留一个指针。我建议团队统一安装LFS,并在.gitattributes里声明*.onnx filter=lfs diff=lfs merge=lfs -text
  3. 大模型(>100MB):别硬塞Git了。用模型注册中心,比如MLflow、DVC,或者自己搭一个MinIO。Git里只存model.yaml配置文件,里面记录模型文件的URL、版本号、SHA256校验值。

避坑指南:我曾经把一个300MB的模型直接push到Git仓库,结果同事clone项目花了半小时。更惨的是,每次改一行代码都要拉一遍模型文件。后来我改用LFS,但发现LFS有流量限制——免费额度用完后,团队其他人就拉不了模型了。所以,大模型还是乖乖用对象存储吧。

Git分支策略上,我推荐这样:

  • main分支:只存放经过完整测试、已部署的模型版本。
  • develop分支:存放正在迭代的模型,每天自动训练产出的版本。
  • feature/xxx分支:实验性模型,比如尝试新的backbone、新的数据增强策略。

每次模型更新,commit message要写清楚。我见过最差的commit是「update model」。好一点的应该是这样:

feat(model): 人脸检测模型升级到v1.3.0

- 更换backbone为MobileNetV3,推理速度提升30%
- 新增口罩遮挡场景的训练数据,AP提升5%
- 修复夜间模式下误检率过高的问题

模型文件: face_det_v1.3.0.onnx
SHA256: a3f8b2c1d4e5...

4.3 版本号命名规范

光有SemVer还不够。实际项目中,模型文件、配置文件、部署包,都需要一套统一的命名规范。我总结了一套「三要素命名法」:

格式{模型名称}_{版本号}_{平台/精度}.{后缀}

举个例子:

  • yolov5s_1.2.0_rk3588_fp16.rknn
  • wakeword_2.0.1_esp32_int8.tflite
  • depth_estimation_0.9.0_jetson_orin_fp32.engine

为什么这么定?

  • 模型名称:一眼知道是什么模型。
  • 版本号:严格遵循SemVer,方便回溯。
  • 平台/精度:边缘设备千差万别,RK3588和Jetson Orin的模型不能混用。精度标识(fp16/int8)也直接写在文件名里,避免部署时拿错文件。

额外建议:在模型文件的元数据里,再加一个version.json文件。内容包含:

{
  "model_name": "yolov5s",
  "semver": "1.2.0",
  "build_timestamp": "2025-03-15T10:30:00Z",
  "git_commit": "a1b2c3d4e5f6...",
  "training_dataset": "coco_2025_v3",
  "quantization": "fp16",
  "target_platform": "rk3588",
  "checksum": "sha256:a3f8b2c1d4e5..."
}

这样,即使文件名被改了,你也能从元数据里恢复所有信息。我在一个客户现场就靠这个救过急——他们运维人员把模型文件重命名了,但元数据还在,我直接写了个脚本批量恢复了版本信息。

最后,说一个我踩过的坑。版本号里不要用「v」前缀,比如v1.2.0。为什么?因为Git tag里经常用v1.2.0,模型文件名里再用v,容易混淆。而且,有些脚本解析版本号时,v1.2.01.2.0处理逻辑不一样。统一用纯数字版本号,省心。

总结一下我的习惯

  • 模型文件命名:model_1.2.0_rk3588_fp16.rknn
  • Git tag命名:model/1.2.0(用斜杠分类,方便查找)
  • 每次发布,同时打tag、更新模型注册中心、写release notes。

这套流程跑顺了,模型管理就不再是玄学,而是工程。