سجل النماذج والتقديم

نشر Canary واختبار A/B

3 دقيقة للقراءة

نشر نماذج ML بأمان يتطلب إطلاق تدريجي وتحقق قائم على البيانات. نشر Canary واختبار A/B يُقللان المخاطر بينما يُعظمان التعلم.

استراتيجيات النشر

الاستراتيجية المخاطرة سرعة التراجع حالة الاستخدام
Big Bang عالية بطيء التطوير فقط
Blue-Green متوسطة سريع تبديل سريع
Canary منخفضة سريع إنتاج ML
اختبار A/B منخفضة سريع مقارنة النماذج

نشر Canary

المفهوم

انشر النموذج الجديد لنسبة صغيرة من حركة المرور، راقب المقاييس، ثم زد تدريجياً.

تدفق حركة المرور:
┌─────────────────────────────────────────────┐
│                                             │
│  المستخدمون (100%)                           │
│      │                                      │
│      ▼                                      │
│  ┌─────────┐                                │
│  │  موزع   │                                │
│  │ الحمل   │                                │
│  └────┬────┘                                │
│       │                                     │
│   ┌───┴───┐                                 │
│   │       │                                 │
│   ▼       ▼                                 │
│ ┌───┐   ┌───┐                               │
│ │95%│   │ 5%│  ◄── Canary                   │
│ │v1 │   │v2 │                               │
│ └───┘   └───┘                               │
└─────────────────────────────────────────────┘

تنفيذ Kubernetes

# model-v1-deployment.yaml (مستقر)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: fraud-detector-stable
  labels:
    app: fraud-detector
    version: v1
spec:
  replicas: 9  # 90% من حركة المرور
  selector:
    matchLabels:
      app: fraud-detector
      version: v1
  template:
    metadata:
      labels:
        app: fraud-detector
        version: v1
    spec:
      containers:
      - name: model
        image: myregistry/fraud-detector:v1
        ports:
        - containerPort: 3000
---
# model-v2-deployment.yaml (canary)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: fraud-detector-canary
  labels:
    app: fraud-detector
    version: v2
spec:
  replicas: 1  # 10% من حركة المرور
  selector:
    matchLabels:
      app: fraud-detector
      version: v2
  template:
    metadata:
      labels:
        app: fraud-detector
        version: v2
    spec:
      containers:
      - name: model
        image: myregistry/fraud-detector:v2
        ports:
        - containerPort: 3000
---
# service.yaml (يوجه لكليهما)
apiVersion: v1
kind: Service
metadata:
  name: fraud-detector
spec:
  selector:
    app: fraud-detector  # يطابق v1 و v2
  ports:
  - port: 80
    targetPort: 3000

تقسيم حركة المرور مع Istio

# virtual-service.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: fraud-detector
spec:
  hosts:
  - fraud-detector
  http:
  - route:
    - destination:
        host: fraud-detector
        subset: stable
      weight: 95
    - destination:
        host: fraud-detector
        subset: canary
      weight: 5
---
# destination-rule.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: fraud-detector
spec:
  host: fraud-detector
  subsets:
  - name: stable
    labels:
      version: v1
  - name: canary
    labels:
      version: v2

سكربت الإطلاق التدريجي

# canary_rollout.py
import subprocess
import time
from typing import Callable

def update_traffic_weight(canary_weight: int):
    """حدّث وزن VirtualService في Istio."""
    stable_weight = 100 - canary_weight

    patch = f'''
    spec:
      http:
      - route:
        - destination:
            host: fraud-detector
            subset: stable
          weight: {stable_weight}
        - destination:
            host: fraud-detector
            subset: canary
          weight: {canary_weight}
    '''

    subprocess.run([
        "kubectl", "patch", "virtualservice", "fraud-detector",
        "--type=merge", "-p", patch
    ])

def canary_rollout(
    check_metrics: Callable[[], bool],
    weights: list[int] = [5, 10, 25, 50, 100],
    wait_minutes: int = 10
):
    """زد حركة مرور canary تدريجياً إذا نجحت المقاييس."""
    for weight in weights:
        print(f"تعيين وزن canary إلى {weight}%")
        update_traffic_weight(weight)

        print(f"انتظار {wait_minutes} دقائق...")
        time.sleep(wait_minutes * 60)

        if not check_metrics():
            print("فشل فحص المقاييس! التراجع...")
            update_traffic_weight(0)
            return False

        print(f"نجحت المقاييس عند {weight}%")

    print("اكتمل إطلاق canary!")
    return True

# الاستخدام
def check_model_metrics() -> bool:
    """تحقق إذا كان نموذج canary يفي بـ SLOs."""
    # استعلم Prometheus/Grafana
    latency_ok = get_p99_latency("canary") < 100  # مللي ثانية
    error_rate_ok = get_error_rate("canary") < 0.01  # 1%
    accuracy_ok = get_accuracy("canary") > 0.90

    return latency_ok and error_rate_ok and accuracy_ok

canary_rollout(check_model_metrics)

اختبار A/B للنماذج

المفهوم

قسّم حركة المرور بين النماذج لقياس تأثير الأعمال، ليس فقط المقاييس التقنية.

Canary اختبار A/B
تحقق من الاستقرار قس تأثير الأعمال
إطلاق سريع أهمية إحصائية
مقاييس تقنية مقاييس أعمال
مؤقت يمكن أن يستمر لأسابيع

التنفيذ مع Feature Flags

# ab_test_router.py
import hashlib
from enum import Enum

class ModelVariant(Enum):
    CONTROL = "v1"
    TREATMENT = "v2"

def get_variant(user_id: str, experiment: str, treatment_pct: int = 50) -> ModelVariant:
    """تعيين حتمي بناءً على user_id."""
    hash_input = f"{user_id}:{experiment}"
    hash_value = int(hashlib.md5(hash_input.encode()).hexdigest(), 16)
    bucket = hash_value % 100

    if bucket < treatment_pct:
        return ModelVariant.TREATMENT
    return ModelVariant.CONTROL

# الاستخدام في الخدمة
class FraudDetectorABTest:
    def __init__(self):
        self.model_v1 = load_model("fraud_detector:v1")
        self.model_v2 = load_model("fraud_detector:v2")

    def predict(self, user_id: str, features: dict) -> dict:
        variant = get_variant(user_id, "fraud_model_v2_test")

        if variant == ModelVariant.TREATMENT:
            model = self.model_v2
        else:
            model = self.model_v1

        prediction = model.predict(features)

        # سجّل للتحليل
        log_prediction(
            user_id=user_id,
            variant=variant.value,
            prediction=prediction,
            timestamp=time.time()
        )

        return {
            "prediction": prediction,
            "variant": variant.value
        }

التحليل الإحصائي

# ab_analysis.py
import scipy.stats as stats
import pandas as pd

def analyze_ab_test(
    control_conversions: int,
    control_total: int,
    treatment_conversions: int,
    treatment_total: int,
    confidence: float = 0.95
) -> dict:
    """حلل نتائج اختبار A/B."""
    control_rate = control_conversions / control_total
    treatment_rate = treatment_conversions / treatment_total

    # اختبار z لنسبتين
    pooled = (control_conversions + treatment_conversions) / (control_total + treatment_total)
    se = (pooled * (1 - pooled) * (1/control_total + 1/treatment_total)) ** 0.5
    z_stat = (treatment_rate - control_rate) / se
    p_value = 2 * (1 - stats.norm.cdf(abs(z_stat)))

    # فاصل الثقة
    z_critical = stats.norm.ppf((1 + confidence) / 2)
    diff = treatment_rate - control_rate
    margin = z_critical * se

    return {
        "control_rate": control_rate,
        "treatment_rate": treatment_rate,
        "lift": (treatment_rate - control_rate) / control_rate * 100,
        "p_value": p_value,
        "significant": p_value < (1 - confidence),
        "confidence_interval": (diff - margin, diff + margin)
    }

# مثال استخدام
results = analyze_ab_test(
    control_conversions=450,
    control_total=10000,
    treatment_conversions=520,
    treatment_total=10000
)

print(f"Control: {results['control_rate']:.2%}")
print(f"Treatment: {results['treatment_rate']:.2%}")
print(f"الرفع: {results['lift']:.1f}%")
print(f"P-value: {results['p_value']:.4f}")
print(f"ذو دلالة: {results['significant']}")

مراقبة نشر Canary

المقاييس الرئيسية للتتبع

# prometheus-rules.yaml
groups:
- name: canary-alerts
  rules:
  - alert: CanaryHighLatency
    expr: |
      histogram_quantile(0.99,
        sum(rate(http_request_duration_seconds_bucket{version="canary"}[5m]))
        by (le)
      ) > 0.5
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "زمن استجابة canary p99 فوق 500ms"

  - alert: CanaryHighErrorRate
    expr: |
      sum(rate(http_requests_total{version="canary",status=~"5.."}[5m]))
      /
      sum(rate(http_requests_total{version="canary"}[5m]))
      > 0.05
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "معدل خطأ canary فوق 5%"

استعلام لوحة Grafana

# قارن زمن الاستجابة بين الإصدارات
histogram_quantile(0.99,
  sum by (version, le) (
    rate(http_request_duration_seconds_bucket[5m])
  )
)

# قارن معدلات الأخطاء
sum by (version) (
  rate(http_requests_total{status=~"5.."}[5m])
) / sum by (version) (
  rate(http_requests_total[5m])
)

التراجع الآلي

Argo Rollouts

# rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: fraud-detector
spec:
  replicas: 10
  selector:
    matchLabels:
      app: fraud-detector
  template:
    metadata:
      labels:
        app: fraud-detector
    spec:
      containers:
      - name: model
        image: myregistry/fraud-detector:v2
  strategy:
    canary:
      steps:
      - setWeight: 5
      - pause: {duration: 10m}
      - setWeight: 20
      - pause: {duration: 10m}
      - setWeight: 50
      - pause: {duration: 10m}
      - setWeight: 100
      analysis:
        templates:
        - templateName: success-rate
        startingStep: 1
---
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: success-rate
spec:
  metrics:
  - name: success-rate
    interval: 1m
    successCondition: result[0] >= 0.95
    provider:
      prometheus:
        address: http://prometheus:9090
        query: |
          sum(rate(http_requests_total{status!~"5.."}[5m]))
          /
          sum(rate(http_requests_total[5m]))

أفضل الممارسات

الممارسة لماذا
ابدأ صغيراً 1-5% canary أولي
راقب مقاييس الأعمال ليس فقط زمن الاستجابة/الأخطاء
أتمت التراجع تفاعل أسرع من البشر
استخدم توجيه حتمي تجربة مستخدم متسقة
شغّل وقتاً كافياً أهمية إحصائية

الرؤية الرئيسية: نشر النموذج الآمن تكراري—انشر صغيراً، قس التأثير، أتمت القرارات، ودائماً لديك خطة تراجع.

الوحدة التالية: مراقبة ML وعمليات الإنتاج. :::

اختبار

الوحدة 5: سجل النماذج والتقديم

خذ الاختبار