mcpField
L
llmops-platform-engineering

llmops-platform-engineering

github.com/bagelholeクラウド・DevOps1.2k316 回インストール23 週間前に更新
リポジトリ

llmops-platform-engineering について

社内 LLM プラットフォームの構築と運用を支援するエンジニアリングスキルです。評価ゲート、A/B テスト、Kubernetes でのモデル提供、ガバナンス、運用を扱います。

主な機能

  1. 01LLM プラットフォームの制御面とデータ面の設計
  2. 02評価ゲートを含む CI/CD の構築
  3. 03モデルバージョンの A/B テスト設定
  4. 04Kubernetes モデルサービングのデプロイ
  5. 05ガバナンス、可観測性、コスト分析の設定

活用シーン

  1. 01チーム向け社内 LLM プラットフォームの構築
  2. 02リリース前の品質・安全性評価
  3. 03モデルバージョン間の性能比較
  4. 04モデル昇格と本番デプロイの管理

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/bagelhole/devops-security-agent-skills --skill llmops-platform-engineering

インストール後、Claude Code で/llmops-platform-engineeringを入力して読み込まれたか確認します。

詳細

LLMOps プラットフォームエンジニアリング

信頼性、コスト、コンプライアンスを損なうことなく迅速な実験を可能にする、社内 LLM プラットフォームを設計・運用します。

このスキルを使用する場面

  • チームが LLM を活用した機能をデプロイ・管理できる社内プラットフォームを構築する
  • モデル評価ゲートを含む CI/CD パイプラインを設計する
  • モデルバージョン向けの A/B テストインフラストラクチャを構築する
  • Kubernetes ベースのモデルサービングインフラストラクチャを作成する
  • モデル昇格のガバナンスワークフローを確立する

前提条件

  • GPU ノードプールを備えた Kubernetes クラスター(またはクラウド推論 API へのアクセス)
  • コンテナレジストリ(Harbor、ECR、GCR、または ACR)
  • CI/CD システム(GitHub Actions、GitLab CI、または Argo Workflows)
  • オブザーバビリティスタック(Prometheus + Grafana + OpenTelemetry)
  • モデルレジストリ(MLflow またはカスタムメタデータストア)

成果

  • 実験から本番環境までの標準化された経路
  • 品質と安全性のゲートによる安全なモデルロールアウト
  • 推論、ベクトル DB、オブザーバビリティ向けの再利用可能なインフラモジュール
  • プラットフォーム、アプリ、セキュリティ各チーム間で明確な責任体制

リファレンスアーキテクチャ

  1. コントロールプレーン:モデルレジストリ、プロンプト/バージョンカタログ、ポリシーチェック、評価パイプライン。
  2. データプレーン:推論ゲートウェイ、ベクトルデータベース、キャッシュ、フィーチャーストア。
  3. 運用プレーン:テレメトリ、アラート、SLO ダッシュボード、コスト分析。
  4. セキュリティプレーン:IAM 境界、シークレットのローテーション、コンテンツフィルター、監査ログ。

モデル昇格パイプライン

# .github/workflows/model-promotion.yaml
name: Model Promotion Pipeline
on:
  workflow_dispatch:
    inputs:
      model_name:
        description: "Model identifier"
        required: true
      model_version:
        description: "Model version to promote"
        required: true
      target_env:
        description: "Target environment"
        required: true
        type: choice
        options: [staging, production]

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

      - name: Run quality evaluation suite
        run: |
          python -m evals.run \
            --model "${{ inputs.model_name }}:${{ inputs.model_version }}" \
            --suite quality \
            --output results/quality.json

      - name: Run safety evaluation suite
        run: |
          python -m evals.run \
            --model "${{ inputs.model_name }}:${{ inputs.model_version }}" \
            --suite safety \
            --output results/safety.json

      - name: Run latency benchmark
        run: |
          python -m evals.benchmark \
            --model "${{ inputs.model_name }}:${{ inputs.model_version }}" \
            --concurrent-users 50 \
            --duration 300 \
            --output results/latency.json

      - name: Gate check - quality
        run: |
          python -m evals.gate_check \
            --results results/quality.json \
            --threshold-file thresholds/quality.yaml

      - name: Gate check - safety
        run: |
          python -m evals.gate_check \
            --results results/safety.json \
            --threshold-file thresholds/safety.yaml

      - name: Gate check - latency
        run: |
          python -m evals.gate_check \
            --results results/latency.json \
            --threshold-file thresholds/latency.yaml

      - name: Upload eval evidence
        uses: actions/upload-artifact@v4
        with:
          name: eval-results-${{ inputs.model_version }}
          path: results/

  approve:
    needs: evaluate
    runs-on: ubuntu-latest
    environment: ${{ inputs.target_env }}
    steps:
      - name: Record approval
        run: |
          echo "Approved by: ${{ github.actor }}"
          echo "Model: ${{ inputs.model_name }}:${{ inputs.model_version }}"
          echo "Target: ${{ inputs.target_env }}"
          echo "Time: $(date -u +%Y-%m-%dT%H:%M:%SZ)"

  deploy:
    needs: approve
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy canary
        run: |
          kubectl set image deployment/${{ inputs.model_name }}-canary \
            model=${{ inputs.model_name }}:${{ inputs.model_version }} \
            -n ai-${{ inputs.target_env }}

      - name: Wait for canary validation (15 min)
        run: |
          python -m canary.validate \
            --deployment ${{ inputs.model_name }}-canary \
            --namespace ai-${{ inputs.target_env }} \
            --duration 900 \
            --quality-threshold 0.85 \
            --error-rate-threshold 0.02

      - name: Promote to full rollout
        run: |
          kubectl set image deployment/${{ inputs.model_name }} \
            model=${{ inputs.model_name }}:${{ inputs.model_version }} \
            -n ai-${{ inputs.target_env }}
          kubectl rollout status deployment/${{ inputs.model_name }} \
            -n ai-${{ inputs.target_env }} --timeout=300s

評価ゲートのしきい値

# thresholds/quality.yaml
gates:
  groundedness:
    metric: groundedness_score
    min: 0.85
    comparison: gte
  task_success:
    metric: task_success_rate
    min: 0.90
    comparison: gte
  hallucination:
    metric: hallucination_rate
    max: 0.08
    comparison: lte
  regression:
    metric: quality_delta_vs_baseline
    min: -0.02
    comparison: gte
    description: "Must not regress more than 2% vs current production"

# thresholds/latency.yaml
gates:
  p50_latency:
    metric: latency_p50_ms
    max: 800
    comparison: lte
  p95_latency:
    metric: latency_p95_ms
    max: 2000
    comparison: lte
  p99_latency:
    metric: latency_p99_ms
    max: 5000
    comparison: lte
  throughput:
    metric: requests_per_second
    min: 50
    comparison: gte

A/B テストの設定

# ab-test-config.yaml
apiVersion: gateway.ai/v1
kind: ABTest
metadata:
  name: model-comparison-q1
  namespace: ai-production
spec:
  duration: 7d
  traffic_split:
    control:
      model: gpt-4o-2024-08-06
      weight: 70
    treatment:
      model: gpt-4o-2025-01-15
      weight: 30
  metrics:
    primary:
      - task_success_rate
      - user_satisfaction_score
    secondary:
      - latency_p95
      - cost_per_request
      - hallucination_rate
  guardrails:
    auto_rollback_if:
      - metric: task_success_rate
        threshold: 0.80
        window: 1h
      - metric: hallucination_rate
        threshold: 0.15
        window: 30m
  assignment:
    strategy: sticky_user
    hash_key: user_id

Kubernetes モデルサービングのデプロイ

# model-serving-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: llm-inference
  namespace: ai-production
  labels:
    app: llm-inference
    model: gpt-4o
    version: "2025-01"
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: llm-inference
  template:
    metadata:
      labels:
        app: llm-inference
        model: gpt-4o
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8080"
        prometheus.io/path: "/metrics"
    spec:
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchLabels:
              app: llm-inference
      containers:
        - name: model
          image: registry.internal/vllm-server:0.4.1
          args:
            - "--model=/models/current"
            - "--tensor-parallel-size=1"
            - "--max-model-len=8192"
            - "--gpu-memory-utilization=0.90"
          ports:
            - containerPort: 8000
              name: inference
            - containerPort: 8080
              name: metrics
          resources:
            requests:
              cpu: "4"
              memory: "16Gi"
              nvidia.com/gpu: "1"
            limits:
              cpu: "8"
              memory: "32Gi"
              nvidia.com/gpu: "1"
          readinessProbe:
            httpGet:
              path: /health
              port: 8000
            initialDelaySeconds: 60
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /health
              port: 8000
            initialDelaySeconds: 120
            periodSeconds: 30
          volumeMounts:
            - name: model-weights
              mountPath: /models
              readOnly: true
            - name: config
              mountPath: /etc/vllm
      volumes:
        - name: model-weights
          persistentVolumeClaim:
            claimName: model-weights-pvc
        - name: config
          configMap:
            name: vllm-config
      tolerations:
        - key: nvidia.com/gpu
          operator: Exists
          effect: NoSchedule
      nodeSelector:
        gpu-type: a100
---
apiVersion: v1
kind: Service
metadata:
  name: llm-inference
  namespace: ai-production
spec:
  selector:
    app: llm-inference
  ports:
    - name: inference
      port: 8000
      targetPort: 8000
    - name: metrics
      port: 8080
      targetPort: 8080
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: llm-inference-hpa
  namespace: ai-production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: llm-inference
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Pods
      pods:
        metric:
          name: llm_queue_depth
        target:
          type: AverageValue
          averageValue: "5"
    - type: Pods
      pods:
        metric:
          name: gpu_utilization_percent
        target:
          type: AverageValue
          averageValue: "75"
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
        - type: Pods
          value: 2
          periodSeconds: 120
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Pods
          value: 1
          periodSeconds: 300

AI サービス向け CI/CD 設計

  • 依存関係とモデルハッシュを固定した不変のコンテナをビルドします。
  • 環境昇格を使用します:dev -> stage -> prod。
  • 次の場合はデプロイを失敗させます:
    • 回帰評価の結果がベースラインを下回る
    • 安全性テストの結果がリスクしきい値を超える
    • p95 レイテンシが SLO の予算を超える
  • 監査に備えてデプロイの証跡(コミット SHA、評価レポート、承認者)を保存します。

運用 SLO

シグナル目標測定期間
可用性99.9%30 日間のローリング
p95 レイテンシ< 1200ms5 分単位
リクエストあたりのコスト< $0.051 時間平均
タスク成功率> 90%24 時間のローリング
グラウンデッドネス> 85%24 時間のローリング

プラットフォームのガードレール

  • テナントごとのクォータとモデルの許可リストを適用します。
  • 自動化経路では構造化出力の契約を必須にします。
  • 重要なワークフローでは、デフォルトでリスクの低いモデル設定を使用します。
  • 本番環境では、制約のないツール実行を無効にします。

ツールスタック(例)

レイヤーツール
オーケストレーションArgo Workflows、GitHub Actions、Airflow
モデルレジストリMLflow、カスタムメタデータ DB
ゲートウェイLiteLLM、Envoy ベースの API ゲートウェイ
オブザーバビリティOpenTelemetry + Prometheus + Grafana + Langfuse
ポリシーデプロイ時と実行時のチェック向け OPA/Rego
評価RAGAS、カスタム評価ハーネス、Promptfoo
サービングvLLM、TGI、Triton Inference Server

トラブルシューティング

問題診断解決策
カナリアが品質ゲートに失敗する評価結果をベースラインと比較するモデル設定を調整するか、バージョンをロールバックする
デプロイのロールアウトが停止するPod のイベントとリソースクォータを確認するリソース制限またはノードの利用可能性を修正する
A/B テストで有意差が見られないトラフィックの分割とサンプルサイズを確認するテスト期間を延長するか、処置群の比率を増やす
モデルのコールドスタートが遅すぎるモデルの重みのダウンロードサイズが大きいキャッシュ済みの PVC または init コンテナを使用する
評価パイプラインが不安定モデル出力が非決定的評価時の temperature を 0 に設定し、サンプルサイズを増やす

関連スキル

コメント