mcpField
M
ml-ops-engineer

ml-ops-engineer

github.com/borghei云与 DevOps1.0k174 次安装1 周前更新
代码仓库

关于 ml-ops-engineer

面向 MLOps 工程师的技能,涵盖模型部署、训练流水线、模型注册、漂移监控、特征存储和 ML CI/CD。附带脚本可管理模型版本、检测数据漂移并验证流水线定义。

主要功能

  1. 01规划和扩展训练流水线
  2. 02配置实时或批量模型部署
  3. 03管理模型注册与版本阶段
  4. 04检测数据漂移并配置监控告警
  5. 05定义特征存储和实验跟踪模式
  6. 06验证流水线结构与部署门槛

适用场景

  1. 01设计模型从训练到部署的流程
  2. 02比较并晋升模型版本
  3. 03对比参考数据与生产数据以检测漂移
  4. 04部署前检查 ML 流水线定义

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/borghei/claude-skills --skill ml-ops-engineer

安装后在 Claude Code 中输入/ml-ops-engineer确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

REFERENCE.md
scripts/
drift_detector.py
model_registry.py
pipeline_validator.py

详细介绍

MLOps 工程师

该 Agent 以资深 MLOps 工程师的身份工作,负责将模型部署到生产环境、编排训练流水线、监控模型健康状况、管理特征存储,并自动化 ML CI/CD。

先澄清

部署前,请先确认以下输入。若有信息缺失或含糊不清,且会影响结果,请先询问;若不会影响结果,则采用合理的默认值,并说明所用默认值。

  • 服务模式 + 延迟 SLA: 实时服务(FastAPI/K8s)或批处理,以及 P99 目标(决定整个部署架构)。
  • 当前 MLOps 成熟度: 手动、流水线、CI/CD 或完整 MLOps(用于确定应优先弥补的高影响差距)。
  • 模型制品 + 注册表/基础设施: 框架、存储位置和目标平台(MLflow、K8s)(决定服务和注册表配置)。
  • 监控阈值: 漂移和准确率下降的限值,以及检查频率(决定告警规则和漂移检测)。

针对当前请求,询问最重要的两到三项输入,而不是把整份清单都问一遍。如果用户希望直接获得结果,请直接提供,并在开头说明所作假设。

工作流

  1. 评估 ML 成熟度 -- 判断当前级别(手动 Notebook、自动化流水线或完整 CI/CD)。确定应优先弥补的高影响差距。
  2. 构建或扩展训练流水线 -- 定义获取数据、验证、预处理、训练和评估阶段。使用 Kubeflow、Airflow 或同类工具。设置准确率阈值作为部署门槛(例如,> 0.85)。
  3. 部署模型以提供服务 -- 根据延迟要求选择实时服务(FastAPI + K8s)或批处理(Spark/Parquet)。配置健康检查、自动扩缩容和资源限制。
  4. 在模型注册表中注册 -- 在 MLflow 中记录参数、指标和制品。将胜出的版本切换到 Production 阶段;归档之前的版本。
  5. 添加监控 -- 设置延迟(P50/P95/P99)、错误率、预测分布和特征漂移仪表板。配置告警阈值。
  6. 端到端验证 -- 对服务端点运行冒烟测试。确认监控仪表板有数据。验证回滚流程是否有效。

MLOps 成熟度模型

级别能力关键信号
0 - 手动Jupyter Notebook、手动部署模型未进行版本控制
1 - 流水线自动化训练、模型版本化正在使用 MLflow 跟踪
2 - CI/CD持续训练、自动化测试特征存储已投入运行
3 - 完整 MLOps基于漂移自动重新训练、A/B 测试由 SLA 支持的监控

实时服务示例

# model_server.py -- FastAPI model serving
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import mlflow.pyfunc, time

app = FastAPI()
model = mlflow.pyfunc.load_model("models:/fraud_detector/Production")

class PredictionRequest(BaseModel):
    features: list[float]

class PredictionResponse(BaseModel):
    prediction: float
    model_version: str
    latency_ms: float

@app.post("/predict", response_model=PredictionResponse)
async def predict(req: PredictionRequest):
    start = time.time()
    try:
        pred = model.predict([req.features])[0]
        return PredictionResponse(
            prediction=pred,
            model_version=model.metadata.run_id,
            latency_ms=(time.time() - start) * 1000,
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/health")
async def health():
    return {"status": "healthy", "model_loaded": model is not None}

Kubernetes 部署

# k8s/model-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: model-server
spec:
  replicas: 3
  selector:
    matchLabels: {app: model-server}
  template:
    metadata:
      labels: {app: model-server}
    spec:
      containers:
      - name: model-server
        image: gcr.io/project/model-server:v1.2.3
        ports: [{containerPort: 8080}]
        resources:
          requests: {memory: "2Gi", cpu: "1000m"}
          limits: {memory: "4Gi", cpu: "2000m", nvidia.com/gpu: 1}
        env:
        - {name: MODEL_URI, value: "s3://models/production/v1.2.3"}
        readinessProbe:
          httpGet: {path: /health, port: 8080}
          initialDelaySeconds: 30
          periodSeconds: 10
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: model-server-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: model-server
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target: {type: Utilization, averageUtilization: 70}

漂移检测

# monitoring/drift_detector.py
import numpy as np
from scipy import stats
from dataclasses import dataclass

@dataclass
class DriftResult:
    feature: str
    drift_score: float
    is_drifted: bool
    p_value: float

def detect_drift(reference: np.ndarray, current: np.ndarray, threshold: float = 0.05) -> DriftResult:
    """Detect distribution drift using Kolmogorov-Smirnov test."""
    statistic, p_value = stats.ks_2samp(reference, current)
    return DriftResult(feature="", drift_score=statistic, is_drifted=p_value < threshold, p_value=p_value)

def monitor_all_features(reference: dict, current: dict, threshold: float = 0.05) -> list[DriftResult]:
    """Run drift detection across all features; return list of results."""
    results = []
    for feat in reference:
        r = detect_drift(reference[feat], current[feat], threshold)
        r.feature = feat
        results.append(r)
    return results

告警规则

ALERT_RULES = {
    "latency_p99":    {"threshold": 200,  "severity": "warning",  "msg": "P99 latency exceeded 200 ms"},
    "error_rate":     {"threshold": 0.01, "severity": "critical", "msg": "Error rate exceeded 1%"},
    "accuracy_drop":  {"threshold": 0.05, "severity": "critical", "msg": "Accuracy dropped > 5%"},
    "drift_score":    {"threshold": 0.15, "severity": "warning",  "msg": "Feature drift detected"},
}

特征存储(Feast)

# features/customer_features.py
from feast import Entity, Feature, FeatureView, FileSource, ValueType
from datetime import timedelta

customer = Entity(name="customer_id", value_type=ValueType.INT64)

customer_stats = FeatureView(
    name="customer_stats",
    entities=["customer_id"],
    ttl=timedelta(days=1),
    features=[
        Feature(name="total_purchases",       dtype=ValueType.FLOAT),
        Feature(name="avg_order_value",        dtype=ValueType.FLOAT),
        Feature(name="days_since_last_order",  dtype=ValueType.INT32),
        Feature(name="lifetime_value",         dtype=ValueType.FLOAT),
    ],
    online=True,
    source=FileSource(
        path="gs://features/customer_stats.parquet",
        timestamp_field="event_timestamp",
    ),
)

服务期间的在线检索:

from feast import FeatureStore
store = FeatureStore(repo_path=".")
features = store.get_online_features(
    features=["customer_stats:total_purchases", "customer_stats:avg_order_value"],
    entity_rows=[{"customer_id": 1234}],
).to_dict()

实验跟踪(MLflow)

import mlflow

mlflow.set_tracking_uri("http://mlflow.company.com")
mlflow.set_experiment("fraud_detection")

with mlflow.start_run(run_name="xgboost_v2"):
    mlflow.log_params({"n_estimators": 100, "max_depth": 6, "learning_rate": 0.1})
    model = train_model(X_train, y_train)
    mlflow.log_metrics({
        "accuracy": accuracy_score(y_test, preds),
        "f1": f1_score(y_test, preds),
    })
    mlflow.sklearn.log_model(model, "model", registered_model_name="fraud_detector")

如需扩展流水线示例(Kubeflow、Airflow DAG、完整 CI/CD 工作流),请参阅 REFERENCE.md。

参考资料

  • REFERENCE.md -- 扩展模式:Kubeflow 流水线、Airflow DAG、CI/CD 工作流、模型注册表操作

脚本

python scripts/model_registry.py register --name fraud_detector --version v2.3 --metrics '{"f1":0.91,"auc":0.95}' --params '{"n_estimators":200}'
python scripts/model_registry.py promote --name fraud_detector --version v2.3 --stage production
python scripts/model_registry.py list --stage production --json
python scripts/model_registry.py compare --name fraud_detector --versions v2.2 v2.3
python scripts/drift_detector.py --reference train_data.csv --current prod_data.csv
python scripts/drift_detector.py --reference baseline.csv --current latest.csv --threshold 0.1 --json
python scripts/pipeline_validator.py --pipeline pipeline.json --strict
python scripts/pipeline_validator.py --pipeline pipeline.json --json

工具参考

工具用途主要标志
model_registry.py使用指标、参数和生命周期阶段注册、晋级、列出并比较模型版本register --name --version --metrics --params、promote --stage、list、compare --versions、--json
drift_detector.py使用 KS 统计量、PSI 和卡方检验检测参考数据集与当前数据集之间的数据/模型漂移--reference <csv>、--current <csv>、--columns、--threshold、--json
pipeline_validator.py验证 ML 流水线定义的完整性、阶段顺序、评估门槛和回滚配置--pipeline <json>、--strict、--json

故障排查

问题可能原因解决方法
模型延迟超过 P99 SLA(> 200 ms)模型过大、输入预处理缓慢,或 Pod 资源不足对服务端点进行性能分析;考虑模型蒸馏、输入缓存,或增加 CPU/内存限制
drift_detector.py 将所有特征都标记为漂移阈值过低,或参考数据的时间段与预期不同提高阈值(尝试 0.15-0.2),或使用更具代表性的时间窗口重新生成参考数据集
流水线未通过评估门禁模型准确率低于配置的阈值检查上游的数据质量问题;使用 drift_detector.py 比较特征分布;使用新数据重新训练
模型注册表显示“已注册”错误完全相同的名称 + 版本组合之前已注册使用新的版本字符串(例如 v2.3.1),或在旧条目是测试条目时将其删除
Kubernetes Pod 在模型服务中反复崩溃重启模型大小超过内存限制导致 OOM 终止,或健康检查超时时间过短增加 resources.limits.memory;对于大型模型,延长就绪探针的 initialDelaySeconds
特征存储返回过时特征物化任务失败,或运行时间超出 TTL 窗口检查物化日志;重新运行 materialize_features;考虑缩短 TTL 或添加新鲜度告警
pipeline_validator.py 报告 STAGE_ORDER 错误流水线阶段的定义顺序不符合预期(data -> transform -> train -> evaluate -> deploy)重新排序阶段,使其遵循标准顺序;验证器要求数据阶段位于训练阶段之前

成功标准

  • 所有生产模型在接收流量前,均已在模型注册表中注册版本、指标和参数。
  • 按计划定期运行漂移检测(至少每周一次),并在 PSI > 0.2 或 KS > 0.15 时发出告警。
  • ML 流水线在部署前通过 pipeline_validator.py --strict 验证,且无任何错误。
  • 模型服务延迟保持在 SLA 范围内:P50 < 50 ms、P95 < 100 ms、P99 < 200 ms。
  • 每次将模型晋升到生产环境时,都会自动归档之前的生产版本。
  • 回滚到之前的模型版本在 5 分钟内完成,且零停机。
  • 流水线阶段包含评估门禁,当准确率低于定义的阈值时阻止部署。

范围与限制

范围内: 模型部署(实时和批处理)、ML 流水线编排、模型注册表管理、漂移检测(数据漂移、概念漂移、预测漂移)、特征存储模式、监控与告警、Kubernetes 部署配置,以及 ML 的 CI/CD。

范围外: 模型架构设计和算法选择(参见 data-scientist)、原始数据摄取流水线、BI 仪表板开发,以及业务战略。

限制: Python 工具仅使用 Python 标准库。drift_detector.py 使用近似方法计算 KS 统计量和 PSI,适用于大多数分布,但不支持多变量漂移检测,也不支持 Evidently/Alibi Detect 集成。model_registry.py 将状态存储在本地 JSON 文件中——用于生产环境时,请集成 MLflow Model Registry 或类似平台。pipeline_validator.py 会验证结构和约定,但不会执行流水线阶段。

集成点

  • 数据科学家(data-analytics/data-scientist):接收带有实验元数据的训练模型;将效果最佳的实验晋升至注册表以进行部署。
  • 分析工程师(data-analytics/analytics-engineer):特征工程管道可能依赖 dbt 集市模型;架构变更会触发管道重新验证。
  • 工程团队(engineering/senior-ml-engineer):协作优化模型架构,以满足服务约束(延迟、内存、GPU)。
  • 基础设施(engineering/):Kubernetes 配置、自动扩缩策略和 CI/CD 工作流由平台工程团队共同管理。
  • 商业智能(data-analytics/business-intelligence):模型预测可能会提供给 BI 仪表板;监控指标会显示在运营仪表板中。

评论

支持 Markdown