AI项目的持续集成与部署

ML系统的CI/CD管线设计,覆盖模型注册、A/B部署、自动回滚与模型监控


一、ML CI/CD与传统CI/CD的差异

1.1 三维版本控制

传统软件CI/CD vs ML CI/CD
==========================

传统软件:一维版本控制
  代码版本 --> 构建 --> 测试 --> 部署

ML系统:三维版本控制
  代码版本 --|
  数据版本 --|--> 训练 --> 验证 --> 注册 --> 部署
  配置版本 --|

  每一维的变化都可能触发重新训练和部署
  三维的组合使版本管理复杂度呈指数级增长

1.2 ML CI/CD管线全景

ML CI/CD管线全景图
==================

[CI阶段]
  代码提交
    |
    v
  代码质量检查
  +-- lint (flake8/black)
  +-- type check (mypy)
  +-- unit tests
  +-- security scan
    |
    v
  数据验证
  +-- schema validation
  +-- distribution check
  +-- freshness check
    |
    v
  模型训练
  +-- 特征工程
  +-- 模型训练
  +-- 超参数记录
    |
    v
  模型验证
  +-- 性能指标测试
  +-- 偏见检测
  +-- 推理延迟测试
  +-- 模型大小检查

[CD阶段]
    |
    v
  模型注册
  +-- 版本化存储
  +-- Model Card生成
  +-- 审批流程
    |
    v
  Staging部署
  +-- 集成测试
  +-- 影子模式(Shadow Mode)
    |
    v
  Production部署
  +-- 金丝雀发布
  +-- A/B测试
  +-- 全量发布
    |
    v
  持续监控
  +-- 性能监控
  +-- 数据漂移检测
  +-- 自动告警
  +-- 自动回滚

1.3 触发条件矩阵

触发事件 CI 训练 CD 说明
代码提交 标准代码检查
代码合并到main 条件 涉及模型代码才触发训练
新数据到达 条件 定时或数据量触发
配置变更 超参数/特征配置
模型注册 模型通过验证后
性能告警 模型性能下降触发重训
定时触发 周期性重训(如每周)

二、持续集成(CI)

2.1 代码质量门禁

# .github/workflows/ml-ci.yml
name: ML CI Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  code-quality:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: pip install -r requirements.txt -r requirements-dev.txt

      - name: Code formatting
        run: black --check src/ tests/

      - name: Linting
        run: flake8 src/ tests/

      - name: Type checking
        run: mypy src/ --ignore-missing-imports

      - name: Unit tests
        run: pytest tests/unit/ -v --cov=src/ --cov-report=xml

      - name: Security scan
        run: bandit -r src/ -ll

  data-validation:
    runs-on: ubuntu-latest
    needs: code-quality
    steps:
      - name: Validate data schema
        run: python scripts/validate_data.py --schema schemas/input_v2.json

      - name: Check data distribution
        run: python scripts/check_distribution.py --reference baseline_stats.json

  model-tests:
    runs-on: ubuntu-latest
    needs: data-validation
    steps:
      - name: Model unit tests
        run: pytest tests/model/ -v

      - name: Inference latency test
        run: python scripts/benchmark_inference.py --max-latency-ms 100

      - name: Model size check
        run: python scripts/check_model_size.py --max-size-mb 500

2.2 数据验证门禁

# 数据验证框架(基于Great Expectations模式)
class DataValidator:
    """ML管线数据验证门禁"""

    def validate(self, dataset, schema_path):
        """执行数据验证"""
        results = {
            "passed": True,
            "checks": [],
        }

        # Check 1: Schema验证
        schema_result = self._check_schema(dataset, schema_path)
        results["checks"].append(schema_result)

        # Check 2: 完整性验证
        completeness = self._check_completeness(dataset)
        results["checks"].append(completeness)

        # Check 3: 分布验证
        distribution = self._check_distribution(dataset)
        results["checks"].append(distribution)

        # Check 4: 新鲜度验证
        freshness = self._check_freshness(dataset)
        results["checks"].append(freshness)

        # Check 5: 唯一性验证
        uniqueness = self._check_uniqueness(dataset)
        results["checks"].append(uniqueness)

        # 汇总
        results["passed"] = all(
            c["passed"] for c in results["checks"]
        )

        return results

    def _check_distribution(self, dataset):
        """检查数据分布是否漂移"""
        # 与上一版本的训练数据分布对比
        # 使用PSI(Population Stability Index)
        # PSI < 0.1: 稳定
        # PSI 0.1-0.25: 需关注
        # PSI > 0.25: 显著漂移,阻断管线
        pass

2.3 模型验证门禁

模型验证门禁(Model Validation Gate)
====================================

[性能门禁](必须全部通过)
  主指标 >= 基线 + 最小提升阈值
  所有护栏指标不低于基线
  推理延迟(P99) <= 设定阈值

[公平性门禁](必须全部通过)
  各子群性能差异 < 10%
  预测正例率差异 < 5%
  无已知偏见模式

[鲁棒性门禁](推荐通过)
  对抗样本测试通过率 > 90%
  噪声数据测试不崩溃
  边界输入测试正常

[资源门禁](必须通过)
  模型文件大小 <= 限制
  显存需求 <= 目标GPU容量
  加载时间 <= 设定阈值

门禁策略:
  全部通过 --> 自动进入CD
  必须类未通过 --> 阻断,通知团队
  推荐类未通过 --> 警告,人工决策

三、模型注册与版本管理

3.1 模型注册表架构

模型注册表(Model Registry)
============================

+--模型注册表--------------------------------------------+
|                                                        |
|  模型名称: recommendation-model                        |
|                                                        |
|  版本列表:                                              |
|  +------+--------+---------+----------+-------+        |
|  | 版本 | 阶段   | 指标    | 创建时间  | 创建者 |        |
|  +------+--------+---------+----------+-------+        |
|  | v3.2 | Prod   | AUC:0.76| 02-20    | 张三  |        |
|  | v3.1 | Archive| AUC:0.74| 02-01    | 张三  |        |
|  | v3.0 | Archive| AUC:0.72| 01-15    | 李四  |        |
|  | v2.9 | Archive| AUC:0.71| 01-01    | 李四  |        |
|  +------+--------+---------+----------+-------+        |
|                                                        |
|  阶段流转:                                              |
|  None --> Staging --> Production --> Archived           |
|                                                        |
|  元数据:                                                |
|  - 训练数据版本                                         |
|  - 训练配置                                             |
|  - 依赖环境                                             |
|  - Model Card                                          |
|  - 性能报告                                             |
+--------------------------------------------------------+

3.2 模型版本命名规范

模型版本命名规范
================

格式: {model_name}-v{major}.{minor}.{patch}

  major: 架构变更(如从双塔到Transformer)
  minor: 显著性能提升(如AUC +2%以上)
  patch: 小幅调优/bug修复(如超参微调)

示例:
  rec-model-v3.0.0  新Transformer架构
  rec-model-v3.1.0  新增用户序列特征,AUC +3%
  rec-model-v3.1.1  修复特征缺失导致的预测异常
  rec-model-v3.2.0  多任务学习,CTR +5%

标签:
  latest    最新训练的模型
  staging   通过验证待部署的模型
  production 当前线上运行的模型
  champion   A/B测试中的当前冠军
  challenger A/B测试中的挑战者

3.3 Model Card标准

Model Card 模板
===============

# 模型卡片: rec-model-v3.2

## 模型概述
  名称: recommendation-model
  版本: v3.2.0
  类型: 推荐排序模型
  框架: PyTorch 2.1
  任务: 点击率预测(CTR Prediction)

## 训练数据
  数据源: 用户行为日志
  时间范围: 2025-09 至 2026-02
  数据量: 5000万条交互记录
  用户数: 200万
  物品数: 50万
  数据版本: data-v20260220-abc123

## 性能指标
  | 指标 | 训练集 | 验证集 | 测试集 |
  |------|--------|--------|--------|
  | AUC  | 0.79   | 0.77   | 0.76   |
  | LogLoss | 0.38 | 0.41  | 0.42   |
  | CTR@10 | 4.2% | 3.9%  | 3.8%   |

## 公平性评估
  | 用户群体 | AUC | CTR差异 |
  |----------|-----|---------|
  | 新用户(<30天) | 0.68 | -15% |
  | 活跃用户 | 0.80 | +5% |
  | 低活用户 | 0.72 | -8% |

## 推理性能
  延迟(P50): 25ms
  延迟(P99): 62ms
  吞吐量: 2000 QPS (单GPU)
  模型大小: 1.2GB
  GPU需求: T4 16GB

## 局限性
  1. 冷启动用户效果差(AUC 0.68)
  2. 长尾物品曝光不足
  3. 高并发(>3000QPS)时延迟上升

## 伦理考量
  - 可能强化信息茧房效应
  - 建议配合多样性策略使用
  - 不用于涉及歧视性决策的场景

## 维护信息
  创建者: @张三
  审核者: @李四
  创建日期: 2026-02-20
  下次重训: 2026-03-20

四、持续部署(CD)

4.1 部署策略对比

策略 风险 复杂度 验证效果 回滚速度 适用场景
直接替换 内部工具
蓝绿部署 低频更新
金丝雀 推荐默认
A/B测试 优秀 模型效果验证
影子模式 极低 优秀 N/A 首次部署

4.2 A/B测试部署架构

A/B测试部署架构
===============

用户请求
    |
    v
[流量路由层]
    |
    +-- Hash(user_id) % 100
    |
    +--  0-89 (90%流量)     --> [模型A: Champion]
    |                            当前线上模型
    |                            rec-model-v3.1
    |
    +-- 90-99 (10%流量)     --> [模型B: Challenger]
                                 新候选模型
                                 rec-model-v3.2
    |
    v
[结果收集层]
    |
    +-- 用户行为日志
    +-- 指标计算
    +-- 统计显著性检验
    |
    v
[决策层]
    |
    +-- p < 0.05 且 Challenger更优 --> 升级Challenger
    +-- p < 0.05 且 Champion更优 --> 保留Champion
    +-- p >= 0.05 --> 延长测试或增加流量

4.3 金丝雀发布流程

# 金丝雀发布自动化流程
class CanaryDeployment:
    """渐进式金丝雀发布"""

    STAGES = [
        {"name": "canary_1%", "traffic": 0.01, "duration_hours": 2,
         "success_criteria": {"error_rate": "<0.1%", "latency_p99": "<100ms"}},
        {"name": "canary_5%", "traffic": 0.05, "duration_hours": 4,
         "success_criteria": {"error_rate": "<0.1%", "latency_p99": "<100ms",
                             "metric_regression": "<2%"}},
        {"name": "canary_25%", "traffic": 0.25, "duration_hours": 12,
         "success_criteria": {"error_rate": "<0.1%", "latency_p99": "<100ms",
                             "metric_regression": "<1%"}},
        {"name": "canary_50%", "traffic": 0.50, "duration_hours": 24,
         "success_criteria": {"error_rate": "<0.05%", "latency_p99": "<80ms",
                             "metric_improvement": ">0%"}},
        {"name": "full_rollout", "traffic": 1.00, "duration_hours": 0,
         "success_criteria": {}},
    ]

    async def execute(self, new_model_version):
        """执行金丝雀发布"""
        for stage in self.STAGES:
            # 1. 调整流量比例
            await self.set_traffic_split(stage["traffic"])

            # 2. 等待观察期
            await asyncio.sleep(stage["duration_hours"] * 3600)

            # 3. 检查成功标准
            metrics = await self.collect_metrics()
            if not self.check_criteria(metrics, stage["success_criteria"]):
                # 不满足标准,自动回滚
                await self.rollback()
                return {"status": "rolled_back", "stage": stage["name"],
                        "reason": metrics}

            # 4. 满足标准,继续下一阶段

        return {"status": "success", "version": new_model_version}

    async def rollback(self):
        """紧急回滚到上一版本"""
        await self.set_traffic_split(0)  # 新模型流量归零
        # Champion模型自动接管100%流量

4.4 模型服务架构

模型服务架构
============

[API网关层]
  Nginx/Kong --> 限流 + 认证 + 路由
       |
       v
[推理服务层]
  +--Triton Inference Server / TorchServe / Seldon Core--+
  |                                                       |
  |  模型A (Champion)        模型B (Challenger)            |
  |  +----------------+     +----------------+            |
  |  | Worker Pool    |     | Worker Pool    |            |
  |  | GPU: 4x T4    |     | GPU: 1x T4    |            |
  |  | Batch: 32     |     | Batch: 32     |            |
  |  | Replicas: 2   |     | Replicas: 1   |            |
  |  +----------------+     +----------------+            |
  |                                                       |
  |  [模型缓存]                                            |
  |  热模型常驻GPU显存                                      |
  |  冷模型从对象存储按需加载                                |
  +-------------------------------------------------------+
       |
       v
[特征服务层]
  Feature Store --> 在线特征查询(Redis/DynamoDB)
       |
       v
[结果处理层]
  后处理 --> 业务规则 --> 结果缓存 --> 返回

五、持续监控

5.1 监控指标体系

# ML系统监控指标体系
monitoring_metrics = {
    "系统指标": {
        "latency_p50": "推理延迟P50",
        "latency_p99": "推理延迟P99",
        "throughput": "每秒处理请求数",
        "error_rate": "错误率",
        "gpu_utilization": "GPU利用率",
        "memory_usage": "显存使用率",
    },
    "模型指标": {
        "prediction_distribution": "预测值分布",
        "feature_distribution": "特征值分布",
        "model_staleness": "模型新鲜度(距上次训练天数)",
        "online_metric": "在线业务指标(CTR/CVR等)",
    },
    "数据指标": {
        "data_freshness": "数据新鲜度",
        "feature_missing_rate": "特征缺失率",
        "schema_violations": "Schema违规次数",
        "data_volume": "数据量变化",
    },
    "业务指标": {
        "conversion_rate": "转化率",
        "user_engagement": "用户参与度",
        "revenue_impact": "收入影响",
    },
}

5.2 数据漂移检测

数据漂移检测方案
================

检测维度:
  1. 特征分布漂移(Feature Drift)
     方法:PSI / KS检验 / Chi-square检验
     频率:每小时

  2. 标签分布漂移(Label Drift)
     方法:PSI / 比例检验
     频率:每日

  3. 概念漂移(Concept Drift)
     方法:在线指标监控 / ADWIN算法
     频率:实时

  4. 预测分布漂移(Prediction Drift)
     方法:PSI / 分布距离
     频率:每小时

告警阈值:
  +--指标--+--正常--+--警告--+--严重--+
  | PSI    | <0.1   | 0.1-0.25| >0.25  |
  | KS p值 | >0.05  | 0.01-05 | <0.01  |
  | 缺失率 | <1%    | 1%-5%   | >5%    |
  | 指标降幅| <2%   | 2%-5%   | >5%    |
  +--------+--------+---------+--------+

响应策略:
  正常 --> 继续监控
  警告 --> 通知团队 + 增加监控频率
  严重 --> 触发自动回滚/重训流程

5.3 自动回滚机制

# 自动回滚决策器
class AutoRollbackController:
    """基于监控指标的自动回滚"""

    ROLLBACK_RULES = [
        {
            "name": "error_rate_spike",
            "condition": "error_rate > 1% for 5 minutes",
            "action": "immediate_rollback",
            "severity": "critical",
        },
        {
            "name": "latency_degradation",
            "condition": "latency_p99 > 200ms for 10 minutes",
            "action": "rollback_after_confirmation",
            "severity": "high",
        },
        {
            "name": "metric_regression",
            "condition": "online_CTR < baseline_CTR * 0.95 for 1 hour",
            "action": "rollback_after_confirmation",
            "severity": "high",
        },
        {
            "name": "prediction_anomaly",
            "condition": "prediction_std > 3 * baseline_std for 30 minutes",
            "action": "alert_and_investigate",
            "severity": "medium",
        },
    ]

    async def evaluate(self, current_metrics):
        """评估是否需要回滚"""
        for rule in self.ROLLBACK_RULES:
            if self._check_condition(rule["condition"], current_metrics):
                if rule["action"] == "immediate_rollback":
                    await self._execute_rollback()
                    await self._notify_team(rule)
                elif rule["action"] == "rollback_after_confirmation":
                    await self._notify_and_wait_confirmation(rule)
                elif rule["action"] == "alert_and_investigate":
                    await self._notify_team(rule)

    async def _execute_rollback(self):
        """执行回滚"""
        # 1. 将流量切回Champion模型
        # 2. 下线Challenger模型
        # 3. 记录回滚事件
        # 4. 保存现场信息(指标快照、日志)
        pass

六、基础设施即代码

6.1 ML管线编排

# 使用Airflow/Dagster定义ML管线
# 示例:完整的训练-验证-部署管线

# 管线定义(DAG)
ml_pipeline = {
    "name": "recommendation_model_pipeline",
    "schedule": "0 2 * * 1",  # 每周一凌晨2点

    "tasks": [
        {
            "id": "data_extraction",
            "type": "python",
            "script": "scripts/extract_data.py",
            "params": {"date_range": "7d"},
        },
        {
            "id": "data_validation",
            "type": "python",
            "script": "scripts/validate_data.py",
            "depends_on": ["data_extraction"],
            "on_failure": "abort_pipeline",
        },
        {
            "id": "feature_engineering",
            "type": "python",
            "script": "scripts/build_features.py",
            "depends_on": ["data_validation"],
        },
        {
            "id": "model_training",
            "type": "python",
            "script": "scripts/train_model.py",
            "depends_on": ["feature_engineering"],
            "resources": {"gpu": "2xA100", "memory": "64GB"},
        },
        {
            "id": "model_evaluation",
            "type": "python",
            "script": "scripts/evaluate_model.py",
            "depends_on": ["model_training"],
        },
        {
            "id": "model_validation_gate",
            "type": "gate",
            "depends_on": ["model_evaluation"],
            "criteria": {
                "auc": ">= 0.75",
                "latency_p99": "<= 100ms",
                "model_size": "<= 2GB",
            },
        },
        {
            "id": "model_registration",
            "type": "python",
            "script": "scripts/register_model.py",
            "depends_on": ["model_validation_gate"],
        },
        {
            "id": "staging_deployment",
            "type": "deploy",
            "target": "staging",
            "depends_on": ["model_registration"],
        },
        {
            "id": "integration_tests",
            "type": "python",
            "script": "scripts/integration_test.py",
            "depends_on": ["staging_deployment"],
        },
        {
            "id": "canary_deployment",
            "type": "deploy",
            "target": "production",
            "strategy": "canary",
            "depends_on": ["integration_tests"],
            "requires_approval": True,
        },
    ],
}

6.2 环境管理

# ML训练环境Dockerfile
FROM nvidia/cuda:12.1.0-cudnn8-runtime-ubuntu22.04

# 系统依赖
RUN apt-get update && apt-get install -y \
    python3.11 python3-pip git && \
    rm -rf /var/lib/apt/lists/*

# Python依赖(固定版本)
COPY requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir -r /app/requirements.txt

# 应用代码
COPY src/ /app/src/
COPY configs/ /app/configs/
COPY scripts/ /app/scripts/

WORKDIR /app

# 健康检查
HEALTHCHECK --interval=30s --timeout=10s \
    CMD python3 -c "import torch; assert torch.cuda.is_available()"

# 入口
ENTRYPOINT ["python3"]
# ML推理服务 Kubernetes部署
apiVersion: apps/v1
kind: Deployment
metadata:
  name: rec-model-serving
spec:
  replicas: 3
  selector:
    matchLabels:
      app: rec-model
  template:
    spec:
      containers:
        - name: model-server
          image: registry/rec-model:v3.2.0
          resources:
            limits:
              nvidia.com/gpu: 1
              memory: "8Gi"
            requests:
              nvidia.com/gpu: 1
              memory: "4Gi"
          ports:
            - containerPort: 8080
          readinessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 30
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            periodSeconds: 60

七、工具链选型

7.1 MLOps工具对比

工具 定位 核心功能 部署方式 推荐场景
MLflow 实验+注册 实验追踪、模型注册 自部署 中小团队
Kubeflow 全栈MLOps 管线编排、服务部署 K8s 大团队
Airflow 管线编排 DAG调度、监控 自部署/云 数据团队
Seldon Core 模型服务 多模型服务、A/B K8s 大规模服务
Triton 推理服务 高性能推理、多框架 Docker/K8s 高并发
DVC 数据版本 数据版本控制 Git集成 所有团队
Evidently 监控 数据漂移、模型监控 Python库 快速集成
W&B 实验管理 实验追踪、可视化 SaaS 研究团队

7.2 推荐工具组合

小型团队(5人以下)推荐组合
===========================
  实验管理:MLflow (自部署)
  数据版本:DVC
  CI/CD:GitHub Actions
  模型服务:FastAPI + Docker
  监控:Evidently + Grafana

中型团队(5-20人)推荐组合
===========================
  实验管理:W&B (SaaS)
  数据版本:DVC + S3
  管线编排:Airflow
  CI/CD:GitHub Actions + ArgoCD
  模型服务:Triton / Seldon Core
  监控:Evidently + Prometheus + Grafana

大型团队(20人以上)推荐组合
===========================
  平台:Kubeflow / SageMaker / Vertex AI
  实验管理:W&B Enterprise
  数据版本:Delta Lake / LakeFS
  管线编排:Kubeflow Pipelines
  CI/CD:Jenkins / GitLab CI + ArgoCD
  模型服务:Triton + Istio (服务网格)
  监控:自建监控平台

八、实施路线图

ML CI/CD建设路线图
==================

Phase 1 (1-2周): 基础CI
  [ ] 代码质量检查自动化(lint/test/type)
  [ ] 基础单元测试覆盖
  [ ] Git工作流规范(分支策略)
  [ ] Docker化开发环境

Phase 2 (2-4周): 数据+模型管线
  [ ] 数据验证框架部署
  [ ] 模型训练自动化
  [ ] 模型验证门禁
  [ ] 实验追踪工具部署

Phase 3 (4-8周): 模型注册+CD
  [ ] 模型注册表建设
  [ ] Model Card标准化
  [ ] Staging环境部署自动化
  [ ] 金丝雀发布流程

Phase 4 (8-12周): 监控+自动化
  [ ] 在线监控仪表板
  [ ] 数据漂移检测
  [ ] 自动回滚机制
  [ ] A/B测试基础设施

Phase 5 (持续): 优化
  [ ] 管线执行效率优化
  [ ] GPU资源调度优化
  [ ] 成本监控与优化
  [ ] 全流程可观测性

Maurice | maurice_wen@proton.me