在AI大模型开发中,随着模型版本迭代频繁、依赖复杂、部署环境多样,构建一套高效可靠的持续集成与持续交付(CI/CD)流程显得尤为重要。本文将从零开始讲解如何为一个大模型项目设计完整的CI/CD流水线,涵盖代码提交、测试、打包、部署到生产环境的全过程。
文章内容包含:
说明:相比传统软件项目,大模型CI/CD增加了模型质量评估、性能测试等关键环节。
环境 | 用途 | 特点 |
---|---|---|
开发环境 | 本地调试 | 快速迭代,无需严格一致性 |
测试环境 | 自动化测试 | 接近生产配置 |
预发环境 | 全链路验证 | 完全模拟生产 |
生产环境 | 对外服务 | 高可用、高安全 |
工具 | 描述 | 适用场景 |
---|---|---|
Terraform | 支持多云基础设施管理 | 跨平台资源编排 |
Ansible | 无Agent部署,适合轻量任务 | 快速搭建服务器 |
Pulumi | 支持多种编程语言定义资源 | 开发者友好 |
Helm | Kubernetes包管理器 | K8s应用部署 |
建议采用语义化版本号 MAJOR.MINOR.PATCH
:
v1.2.3
1
: 主要功能更新或重大变更2
: 新增非破坏性功能3
: Bug修复或小改进✅ 最佳实践:每次合并到main分支时自动生成新版本标签,并记录变更日志。
使用Locust进行API吞吐量测试:
from locust import HttpUser, task, between
class ModelUser(HttpUser):
wait_time = between(0.1, 0.5)
@task
def predict(self):
payload = {
"prompt": "请解释什么是量子计算",
"max_new_tokens": 100
}
self.client.post("/predict", json=payload)
运行命令:
locust -f performance_test.py
访问 http://localhost:8089
查看并发测试结果。
使用datasets
库进行自动化评估:
from datasets import load_metric
bleu = load_metric("bleu")
references = [["the cat is on the mat"]]
predictions = ["the cat is on the mat"]
result = bleu.compute(predictions=predictions, references=references)
print(result)
输出:
{'bleu': 1.0, 'precisions': [1.0, 1.0, 1.0, 1.0], 'brevity_penalty': 1.0, 'length_ratio': 1.0, 'length_penalty': 1.0}
编写Pytest测试用例确保输出一致性:
import pytest
from model_service import ModelService
model = ModelService(model_name="gpt2")
def test_regression():
output = model.generate("你好")
assert "你好" in output
执行命令:
pytest regression_test.py -v
使用Flask实现简单的A/B路由:
from flask import Flask
import random
app = Flask(__name__)
models = {"A": "ModelV1", "B": "ModelV2"}
@app.route("/predict")
def predict():
group = random.choice(["A", "B"])
result = f"调用 {models[group]}"
return {"group": group, "result": result}
if __name__ == "__main__":
app.run()
# k8s-bluegreen.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: model-service-green
spec:
replicas: 3
selector:
matchLabels:
app: model-service
version: green
template:
metadata:
labels:
app: model-service
version: green
spec:
containers:
- name: model-container
image: registry.example.com/model:v1.0.0
---
apiVersion: service/v1
kind: Service
metadata:
name: model-service
spec:
selector:
app: model-service
version: green
ports:
- protocol: TCP
port: 80
targetPort: 5000
✅ 切换方式:修改Service中的version标签即可切换流量。
使用Argo Rollouts实现渐进式发布:
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: model-rollout
spec:
replicas: 5
strategy:
canary:
steps:
- setWeight: 20
- pause: {}
- setWeight: 40
- pause: {duration: 60}
- setWeight: 100
template:
spec:
containers:
- name: model
image: registry.example.com/model:v2.0.0
效果:逐步将20% -> 40% -> 100%流量迁移到新版本。
通过Git Tag快速回退版本:
git checkout v1.0.0
git tag -d latest
git push origin :latest
git tag latest
git push origin --tags
️ 在CI中监听Tag事件并重新部署旧版本。
使用Flask实现动态开关:
FEATURE_FLAGS = {
"new_model": False
}
@app.route("/toggle/new-model")
def toggle_new_model():
FEATURE_FLAGS["new_model"] = not FEATURE_FLAGS["new_model"]
return {"status": FEATURE_FLAGS["new_model"]}
指标 | 描述 |
---|---|
http_requests_total{status} |
请求总数及状态码 |
model_latency_seconds |
模型响应延迟 |
gpu_usage_percent |
GPU利用率 |
tokens_per_second |
吞吐量 |
Prometheus告警规则示例:
groups:
- name: model-alerts
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.1
for: 2m
labels:
severity: warning
annotations:
summary: "高错误率"
description: "5xx错误率超过10%"
前端埋点上报用户满意度评分:
fetch('/feedback', {
method: 'POST',
body: JSON.stringify({query_id: "abc123", rating: 4})
});
后端记录至数据库:
@app.route('/feedback', methods=['POST'])
def record_feedback():
data = request.json
db.insert("feedback", data)
return {"status": "ok"}
使用Prometheus + Alertmanager实现实时告警:
receivers:
- name: slack-webhook
slack_configs:
- api_url: https://hooks.slack.com/services/TOKEN
channel: '#alerts'
text: "{{ range .Alerts }}{{ .Status }}: {{ .Labels.alertname }}\n{{ end }}"
.github/workflows/ci-cd.yml
)name: Model CI/CD Pipeline
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- run: pip install -r requirements.txt
- run: python train.py
- run: python test.py
- run: docker build -t registry.example.com/model:${{ github.sha }}
- run: docker push registry.example.com/model:${{ github.sha }}
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- run: helm upgrade --install model-release ./helm-chart --set image.tag=${{ github.sha }}
FROM nvidia/cuda:12.1-base
# 安装基础依赖
RUN apt-get update && apt-get install -y git curl wget
# 安装Python
RUN apt-get install -y python3-pip
# 设置工作目录
WORKDIR /app
# 缓存依赖提升构建速度
COPY requirements.txt .
RUN pip install -r requirements.txt
# 拷贝代码
COPY . .
# 使用缓存加速模型加载
ENV HF_HOME=/cache/huggingface
RUN mkdir -p $HF_HOME
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "5000"]
helm-chart/values.yaml
)image:
repository: registry.example.com/model
tag: latest
pullPolicy: IfNotPresent
replicaCount: 3
service:
type: ClusterIP
port: 80
targetPort: 5000
resources:
limits:
cpu: "4"
memory: "16Gi"
nvidia.com/gpu: 1
main
分支;对于依赖多个子模型的大项目,可使用以下结构:
models/
├── encoder/
│ └── model.pth
├── decoder/
│ └── model.pth
└── tokenizer/
└── vocab.json
在Docker中统一挂载:
COPY models/ /models/
ENV MODEL_PATH=/models
使用OpenTelemetry采集分布式追踪数据:
from opentelemetry import trace
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
trace.set_tracer_provider(TracerProvider())
jaeger_exporter = JaegerExporter(
agent_host_name="jaeger",
agent_port=6831,
)
trace.get_tracer_provider().add_span_processor(BatchSpanProcessor(jaeger_exporter))
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("model_inference"):
# 执行推理逻辑
✅ 推荐使用 GitFlow 或 GitHub Flow。
类别 | 审查重点 |
---|---|
模型部分 | 训练参数合理性、过拟合风险 |
数据处理 | 数据泄露、清洗逻辑 |
API接口 | 输入输出格式、异常处理 |
性能 | 并发控制、资源占用情况 |
使用FastAPI内置Swagger UI:
from fastapi import FastAPI
app = FastAPI()
@app.get("/predict")
async def predict(prompt: str, max_new_tokens: int = 100):
"""
生成文本
- **prompt**: 输入提示词
- **max_new_tokens**: 最大生成长度
"""
return {"response": "Hello World"}
访问 /docs
查看交互式文档。
阶段 | 特征 |
---|---|
L1 | 手动构建与部署 |
L2 | 自动化测试 |
L3 | 自动化部署 |
L4 | 金丝雀发布 + 回滚 |
L5 | 全链路可观测 + 自动修复 |
维度 | DevOps | MLOps | 融合要点 |
---|---|---|---|
关注点 | 应用部署 | 模型生命周期 | 模型注册、实验跟踪 |
工具 | Jenkins/GitLab CI | MLflow/Kubeflow | 统一CI/CD平台 |
流程 | Code → Build → Deploy | Data → Train → Evaluate | 加入模型评估阶段 |
# 安装Prometheus
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack
# 安装Node Exporter(用于采集GPU信息)
kubectl apply -f https://raw.githubusercontent.com/NVIDIA/gpu-monitoring-tools/master/exporters/node-feature-discovery/nfd.yaml
第51篇:大模型服务的可观测性设计 —— 日志、监控、追踪三位一体
敬请关注!
欢迎订阅专栏《AI大模型应知应会100篇》持续更新中!