「モデルの精度が先週より落ちているけど、誰も気づいていなかった」——よくある話だ。AIシステムは一度デプロイすると「動いているから大丈夫」と思われがちだが、データの変化やモデルの更新によって静かに品質が劣化する。CI/CDパイプラインにAI品質ゲートを組み込むことで、この問題を自動検知できる。
AI品質ゲートとは何か
ソフトウェア開発におけるCI/CDは、コードが正しく動くかをテストし、合格したものだけをデプロイする仕組みだ。AI品質ゲートは、この考え方をモデルに適用したものだ。
- 新しいモデルの精度が、現行モデルより低下していないか
- テストデータに対して、設定した閾値を超えているか
- 推論レイテンシが許容範囲内に収まっているか
- 特定のエッジケースで破綻していないか
これらをPRマージやデプロイのたびに自動チェックし、基準を満たさないものは本番に出さない——それがAI品質ゲートの役割だ。
GitHub Actions によるパイプライン構成
全体構成
┌─────────────────────────────────────────┐
│ PR作成 / main pushをトリガー │
└──────────────┬──────────────────────────┘
│
┌──────────▼──────────┐
│ 1. コード品質チェック │ (lint, type check)
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ 2. ユニットテスト │ (前処理・特徴量関数)
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ 3. モデル評価 │ (精度・性能テスト)
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ 4. 品質ゲート判定 │ (閾値チェック)
└──────────┬──────────┘
│ 合格のみ通過
┌──────────▼──────────┐
│ 5. ステージングデプロイ │
└─────────────────────┘
Step 1-2: コード品質・ユニットテスト
# .github/workflows/ml-ci.yml
name: ML CI/CD Pipeline
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
code-quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
- run: pip install -r requirements.txt
- name: Lint
run: |
ruff check src/
mypy src/ --ignore-missing-imports
- name: Unit tests
run: pytest tests/unit/ -v --tb=short
Step 3: モデル評価
model-evaluation:
needs: code-quality
runs-on: ubuntu-latest
outputs:
accuracy: ${{ steps.evaluate.outputs.accuracy }}
f1_score: ${{ steps.evaluate.outputs.f1_score }}
latency_p95: ${{ steps.evaluate.outputs.latency_p95 }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
- run: pip install -r requirements.txt
- name: Download test dataset
run: |
aws s3 cp s3://your-bucket/test-data/golden_set.csv data/
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Run model evaluation
id: evaluate
run: |
python scripts/evaluate_model.py \
--model-path models/candidate/ \
--test-data data/golden_set.csv \
--output results.json
ACCURACY=$(jq -r '.accuracy' results.json)
F1=$(jq -r '.f1_score' results.json)
LATENCY=$(jq -r '.latency_p95' results.json)
echo "accuracy=$ACCURACY" >> $GITHUB_OUTPUT
echo "f1_score=$F1" >> $GITHUB_OUTPUT
echo "latency_p95=$LATENCY" >> $GITHUB_OUTPUT
Step 4: 品質ゲート判定
quality-gate:
needs: model-evaluation
runs-on: ubuntu-latest
steps:
- name: Check quality thresholds
run: |
ACCURACY=${{ needs.model-evaluation.outputs.accuracy }}
F1=${{ needs.model-evaluation.outputs.f1_score }}
LATENCY=${{ needs.model-evaluation.outputs.latency_p95 }}
FAILED=0
# 精度チェック (閾値: 90%)
if (( $(echo "$ACCURACY < 0.90" | bc -l) )); then
echo "❌ Accuracy $ACCURACY is below threshold 0.90"
FAILED=1
else
echo "✅ Accuracy $ACCURACY passed"
fi
# F1スコアチェック (閾値: 0.85)
if (( $(echo "$F1 < 0.85" | bc -l) )); then
echo "❌ F1 score $F1 is below threshold 0.85"
FAILED=1
else
echo "✅ F1 score $F1 passed"
fi
# レイテンシチェック (閾値: 500ms)
if (( $(echo "$LATENCY > 500" | bc -l) )); then
echo "❌ P95 latency ${LATENCY}ms exceeds 500ms"
FAILED=1
else
echo "✅ P95 latency ${LATENCY}ms passed"
fi
if [ "$FAILED" -eq 1 ]; then
echo "Quality gate failed. Deployment blocked."
exit 1
fi
echo "All quality checks passed. Proceeding to deployment."
モデルのリグレッションテスト
精度の絶対値チェックだけでなく、現行モデルとの比較(リグレッションテスト)も重要だ。
# scripts/regression_test.py
import json
import sys
from pathlib import Path
def compare_models(candidate_results: dict, baseline_results: dict,
tolerance: float = 0.02) -> bool:
"""
候補モデルが現行モデルより2%以上悪化していたら失敗とする
"""
metrics = ['accuracy', 'f1_score', 'precision', 'recall']
passed = True
for metric in metrics:
candidate = candidate_results[metric]
baseline = baseline_results[metric]
diff = candidate - baseline
if diff < -tolerance:
print(f"REGRESSION: {metric} dropped by {abs(diff):.3f} "
f"({baseline:.3f} → {candidate:.3f})")
passed = False
else:
print(f"OK: {metric} {baseline:.3f} → {candidate:.3f} "
f"(diff: {diff:+.3f})")
return passed
PR コメントへの結果出力
品質チェックの結果をPRのコメントとして自動投稿することで、レビュアーが確認しやすくなる。
- name: Post results to PR
uses: actions/github-script@v7
if: github.event_name == 'pull_request'
with:
script: |
const accuracy = '${{ needs.model-evaluation.outputs.accuracy }}';
const f1 = '${{ needs.model-evaluation.outputs.f1_score }}';
const latency = '${{ needs.model-evaluation.outputs.latency_p95 }}';
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 🤖 モデル品質レポート\n\n| 指標 | 値 | 閾値 | 判定 |\n|---|---|---|---|\n| Accuracy | ${accuracy} | 0.90 | ${accuracy >= 0.90 ? '✅' : '❌'} |\n| F1 Score | ${f1} | 0.85 | ${f1 >= 0.85 ? '✅' : '❌'} |\n| P95 Latency | ${latency}ms | 500ms | ${latency <= 500 ? '✅' : '❌'} |`
});
CI/CDパイプラインにAI品質ゲートを組み込むことで、「誰かが気づいたときには手遅れ」という状況を防げる。品質の劣化をシステムが自動検知し、人間は判断に集中できる——それがMLOpsの目指す姿だ。