2. CI/CD基础

2.1 从“手工集成”到“持续集成”:为什么AI训练链路更需要CI

在传统软件开发中,集成是一个低频且痛苦的事件。多个开发者各自维护分支,直到发布前才合并代码,往往导致“集成地狱”——冲突堆积、构建失败、缺陷在最后一刻集中爆发。持续集成(Continuous Integration, CI)的核心思想是:频繁地将代码变更合并到主干,并自动触发构建与测试,让集成问题在产生后的几分钟内暴露,而不是在发布前几周。

对于AI训练链路,CI的意义被进一步放大。模型训练代码不仅包含Python源码,还耦合了数据集版本、超参数配置、预训练权重、依赖库版本(如PyTorch/TensorFlow)、甚至GPU驱动与CUDA版本。一次微小的数据预处理逻辑改动,可能让模型收敛曲线完全漂移。若没有CI机制,训练脚本的回归问题往往要等到完整训练跑完(数小时甚至数天)才能发现,代价极高。

因此,AI场景下的CI不再只是“编译+单测”,而是扩展为数据校验、特征一致性检查、小样本训练冒烟、模型指标基线对比等一系列自动化关卡。

核心认知:CI/CD不是简单的“自动化脚本”,而是一种质量门禁(Quality Gate)体系。每一次代码提交、每一次数据更新、每一次超参调整,都应触发可量化的验证流程,确保变更不会破坏已有能力。

2.2 持续交付与持续部署:AI模型的“最后一公里”差异

持续交付(Continuous Delivery, CD)与持续部署(Continuous Deployment, CD)常被混用,但二者有明确边界:

  • 持续交付:每次变更自动通过测试并生成可发布的产物(如Docker镜像、模型服务包),但是否推送到生产环境由人工决定。适合对稳定性要求高的业务,保留“一键回滚”的审批节点。
  • 持续部署:所有通过自动化验证的变更自动部署到生产环境,无需人工干预。适合模型更新频繁、且具备完善监控与自动回滚能力的场景(如推荐系统、实时风控)。

在AI训练链路中,两者的区别直接对应模型发布策略:

环节持续交付(人工审批)持续部署(全自动)
模型产物生成模型包+评估报告,等待审核自动推送到模型仓库并上线
适用场景医疗诊断、金融风控、自动驾驶搜索排序、广告点击率预估、内容推荐
回滚策略人工触发回滚到上一版本自动监控指标,异常时自动回滚
发布频率每周/每月每天/每小时

2.3 主流CI/CD工具链:Jenkins与GitLab CI的对比与选型

工具链的选择直接影响流水线的编写范式与维护成本。以下聚焦两种最主流的工具:Jenkins(老牌通用型)与GitLab CI(一体化DevOps平台)。

2.3.1 Jenkins:灵活但需自建

Jenkins是一个开源的自动化服务器,通过插件生态覆盖从代码拉取、构建、测试到部署的全流程。其核心概念包括:

  • Pipeline:使用Groovy DSL编写,支持声明式(Declarative)与脚本式(Scripted)两种语法。
  • Agent:执行任务的节点,可以是物理机、虚拟机或Kubernetes Pod。
  • 插件:超过1800个插件,几乎可以对接任何版本控制、构建工具、云平台。

在AI场景中,Jenkins常用于需要深度定制训练环境的团队。例如,通过Kubernetes插件动态创建包含GPU驱动的Pod,执行分布式训练任务。

// Jenkinsfile(声明式流水线片段)
pipeline {
    agent { label 'gpu-runner' }
    stages {
        stage('数据校验') {
            steps { sh 'python scripts/validate_data.py --min-rows 10000' }
        }
        stage('小样本训练') {
            steps { sh 'python train.py --max-steps 200 --output /tmp/smoke_model' }
        }
        stage('指标对比') {
            steps { sh 'python compare_metrics.py --baseline s3://models/baseline --candidate /tmp/smoke_model' }
        }
    }
    post {
        failure { slackSend channel: '#ai-alert', message: "训练流水线失败: ${env.BUILD_URL}" }
    }
}

2.3.2 GitLab CI:一体化与轻量级

GitLab CI内嵌于GitLab代码仓库,使用.gitlab-ci.yml文件定义流水线。其优势在于:

  • 零额外部署:代码仓库、CI Runner、制品库(Registry)天然集成。
  • 基于Docker的Job隔离:每个Job可指定独立镜像,适合Python依赖隔离。
  • 缓存与缓存键:可缓存pip/conda依赖,加速训练环境准备。

对于AI项目,GitLab CI的父子流水线(Parent-Child Pipelines)非常实用:父流水线负责数据准备,子流水线并行执行多个超参实验。

# .gitlab-ci.yml 片段
stages:
  - validate
  - train
  - evaluate

validate_data:
  stage: validate
  image: python:3.10
  script:
    - pip install -r requirements.txt
    - python scripts/validate_dataset.py --schema schema.json

train_smoke:
  stage: train
  image: pytorch/pytorch:2.1.0-cuda12.1-cudnn8-runtime
  script:
    - python train.py --epochs 1 --batch-size 32
  artifacts:
    paths:
      - models/smoke_model.pt
    expire_in: 1 day

2.3.3 选型建议

维度JenkinsGitLab CI
安装复杂度需单独部署,配置插件随GitLab启用,开箱即用
流水线语法Groovy,学习曲线陡YAML,简洁直观
AI/GPU支持通过K8s插件动态分配GPU原生支持Kubernetes Runner
适合团队已有Jenkins运维经验、复杂发布流程GitLab重度用户、追求轻量维护

2.4 CI/CD与AI训练链路的四个关键结合点

将CI/CD理念引入AI训练,不是简单地把python train.py塞进流水线,而是需要围绕训练链路的特殊性设计自动化关卡。以下四个结合点是核心实践:

结合点一:数据变更触发训练流水线

数据版本变化(如新增样本、修正标注)是模型性能波动的主要来源。通过CI监听数据仓库(如DVC、LakeFS)的变更事件,自动触发:

  1. 数据完整性校验(行数、列数、缺失值比例)。
  2. 特征分布漂移检测(KL散度、PSI)。
  3. 小样本训练(如100步)验证数据可被模型正常消费。

结合点二:训练环境一致性保障

“在我机器上能跑”是AI开发的最大痛点。CI流水线应强制使用锁定的基础镜像(如pytorch:2.1.0-cuda12.1)和依赖锁定文件(requirements.txt或poetry.lock)。每次提交都从零构建环境,避免隐式依赖。

结合点三:模型评估指标作为质量门禁

训练完成不等于模型可用。CI阶段应自动计算评估指标(如Accuracy、F1、AUC),并与基线模型对比。若指标下降超过阈值(如AUC下降>0.01),则流水线失败,阻止模型进入部署环节。

# 伪代码:指标门禁逻辑
baseline_auc = 0.872
candidate_auc = evaluate(model, test_set)
if candidate_auc < baseline_auc - 0.01:
    raise CIError("模型AUC下降超过1%,禁止发布")

结合点四:模型产物与部署流水线衔接

训练产出的模型文件(如.pt、.onnx)应打包为带版本号的制品,并推送至模型仓库(如MLflow、S3)。部署流水线监听新版本模型,自动执行:

  • 模型格式转换(PyTorch → ONNX → TensorRT)。
  • 推理服务冒烟测试(发送10个真实请求,检查延迟与输出格式)。
  • 金丝雀发布(先切5%流量,观察业务指标)。

2.5 案例:某推荐系统团队的CI/CD训练流水线

某互联网公司推荐团队,每日更新模型。其流水线设计如下:

  1. 触发:每日凌晨2点,定时任务检查前一日用户行为日志是否就绪。
  2. 数据验证:校验日志字段完整性,统计曝光/点击分布,若点击率较前7日均值波动超过20%,则告警并暂停。
  3. 特征工程:生成特征并写入特征仓库,同时计算特征重要度排序,与上一版本对比。
  4. 分布式训练:使用8卡A100,训练1小时,每500步记录loss到TensorBoard。
  5. 离线评估:在固定测试集上计算AUC、GAUC,与线上模型对比。
  6. 人工审批:若指标提升,生成评估报告,推送至企业微信,由算法负责人点击“允许上线”。
  7. 自动部署:审批通过后,自动构建TensorRT引擎,滚动更新线上服务,初始流量5%,观察业务指标10分钟后逐步放量至100%。
效果:模型迭代周期从每周1次缩短为每天1次,且因数据质量问题导致的训练失败率从15%降至2%。

2.6 常见误区与复盘

误区一:把CI当作“跑完训练脚本”
训练脚本能跑通不代表模型质量合格。CI必须包含可量化的评估门禁,否则只是“自动化训练”,而非“持续集成”。
误区二:忽略数据版本与代码版本的关联
若流水线不记录“本次训练使用了哪份数据快照”,当模型出现问题时,将无法复现。应使用dvc或lakefs将数据版本哈希写入流水线元数据。
误区三:所有变更都跑全量训练
对于仅修改文档或配置文件注释的提交,无需触发数小时的训练。应通过路径过滤(如GitLab CI的rules:changes)或手动触发机制,区分“影响模型的变更”与“无关变更”。
复盘建议:每两周检查一次流水线耗时分布。若“环境准备”阶段耗时超过总时长的30%,应优先优化依赖缓存或使用预构建镜像;若“模型评估”阶段频繁因指标波动失败,需检查测试集是否过小或数据泄漏。