CI/CD لأنظمة ML

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

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

استراتيجيات النشر لـ ML تتجاوز نشر البرمجيات القياسي. يختبر المحاورون معرفتك بالكناري والأزرق-الأخضر والظل واختبار A/B للنماذج.

مقارنة استراتيجيات النشر

الاستراتيجية مستوى المخاطر حالة الاستخدام وقت التراجع
الأزرق-الأخضر منخفض التبديل الكامل، تراجع سريع ثوانٍ
الكناري منخفض طرح تدريجي مع مقاييس دقائق
الظل منخفض جداً الاختبار بدون تأثير على المستخدم لا ينطبق
اختبار A/B متوسط مقارنة مقاييس الأعمال ساعات

سؤال المقابلة: اختيار استراتيجية النشر

السؤال: "أنت تنشر نموذج توصيات جديد. أي استراتيجية ستستخدم ولماذا؟"

إطار الإجابة:

def choose_deployment_strategy(context):
    # نشر الظل أولاً لجميع النماذج الجديدة
    if context["model_is_new"]:
        return {
            "phase_1": "نشر الظل (أسبوع واحد)",
            "phase_2": "الكناري (5% → 25% → 50% → 100%)",
            "rationale": "الظل يتحقق من الدقة بدون مخاطر، الكناري يتحقق من التوسع"
        }

    # الكناري للتحسينات التكرارية
    if context["incremental_improvement"]:
        return {
            "strategy": "الكناري",
            "rollout": "10% → 25% → 50% → 100%",
            "rationale": "عائلة نموذج معروفة، نحتاج فقط للتحقق من التحسن"
        }

    # اختبار A/B لقرارات الأعمال
    if context["need_business_metrics"]:
        return {
            "strategy": "اختبار A/B",
            "duration": "2-4 أسابيع",
            "rationale": "نحتاج أهمية إحصائية على الإيرادات/التفاعل"
        }

    return "الكناري مع التراجع التلقائي"

تنفيذ نشر الكناري

# Kubernetes canary مع Istio
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: model-serving
spec:
  hosts:
    - model-serving
  http:
    # الكناري: 10% من الحركة
    - match:
        - headers:
            x-canary-override:
              exact: "true"
      route:
        - destination:
            host: model-serving-canary
            port:
              number: 8080
    - route:
        - destination:
            host: model-serving-stable
            port:
              number: 8080
          weight: 90
        - destination:
            host: model-serving-canary
            port:
              number: 8080
          weight: 10

سكريبت ترقية الكناري:

def promote_canary(model_name: str, current_weight: int, target_weight: int):
    """زيادة حركة الكناري تدريجياً"""

    # الحصول على المقاييس الحالية
    canary_metrics = get_canary_metrics(model_name)
    stable_metrics = get_stable_metrics(model_name)

    # التحقق من صحة الكناري
    checks = {
        "error_rate": canary_metrics["error_rate"] <= stable_metrics["error_rate"] * 1.1,
        "latency_p99": canary_metrics["latency_p99"] <= stable_metrics["latency_p99"] * 1.2,
        "accuracy": canary_metrics["accuracy"] >= stable_metrics["accuracy"] * 0.95
    }

    if all(checks.values()):
        update_traffic_weight(model_name, target_weight)
        log.info(f"تمت ترقية الكناري {model_name} إلى {target_weight}%")
    else:
        failed_checks = [k for k, v in checks.items() if not v]
        log.error(f"تم حظر ترقية الكناري: {failed_checks}")
        trigger_rollback(model_name)

نشر الظل

# نشر الظل: تشغيل النموذج الجديد بالتوازي دون التأثير على المستخدمين
async def predict_with_shadow(request):
    # النموذج الأساسي (يقدم الاستجابة)
    primary_response = await primary_model.predict(request.features)

    # نموذج الظل (غير متزامن، لا تأثير على الاستجابة)
    asyncio.create_task(
        shadow_prediction(request.features, primary_response)
    )

    return primary_response

async def shadow_prediction(features, primary_response):
    """مقارنة نموذج الظل بالإنتاج"""
    try:
        shadow_response = await shadow_model.predict(features)

        # تسجيل المقارنة (لا تحجب)
        comparison = {
            "primary_prediction": primary_response,
            "shadow_prediction": shadow_response,
            "match": primary_response == shadow_response,
            "timestamp": datetime.utcnow()
        }

        await metrics.log_shadow_comparison(comparison)

    except Exception as e:
        # أخطاء الظل لا تؤثر أبداً على الإنتاج
        log.warning(f"خطأ نموذج الظل: {e}")

استراتيجيات التراجع

# معايير التراجع الآلي
rollback_triggers:
  immediate:
    - error_rate > 5%
    - latency_p99 > 2x الأساس
    - النموذج يرجع توقعات null

  gradual:
    - error_rate > 2% لمدة 5 دقائق
    - انخفاض الدقة > 5%
    - تحول توزيع التوقعات > 20%

rollback_procedure:
  1. إيقاف حركة الكناري (الوزن = 0)
  2. توسيع النشر المستقر
  3. تنبيه المهندس المناوب
  4. إنشاء تذكرة حادث
  5. حفظ سجلات الكناري للتحليل

نقاط حديث المقابلة

key_points:
  shadow_first: "دائماً نشر الظل لعائلات النماذج الجديدة لالتقاط المشاكل قبل أي تأثير على المستخدم"

  canary_metrics: "نراقب معدل الخطأ، زمن الاستجابة، والمقاييس الخاصة بالنموذج مثل توزيع ثقة التوقع"

  auto_rollback: "التراجع الآلي عند ارتفاع معدل الخطأ، لكن التدخل اليدوي لمشاكل الدقة لأنها تحتاج تحقيق"

  a_b_testing: "احجز اختبارات A/B لمقاييس الأعمال - تتطلب أهمية إحصائية تستغرق 2-4 أسابيع"

رؤية خبير: "الفرق الرئيسي عن البرمجيات التقليدية: نماذج ML يمكن أن تتدهور بصمت. النموذج الذي يرجع توقعات خاطئة مع 200 OK أسوأ من الخطأ - لهذا السبب نشر الظل قيّم جداً."

في الدرس التالي، سنغطي GitOps والبنية التحتية ككود لـ ML. :::

اختبار

الوحدة 5: CI/CD لأنظمة ML

خذ الاختبار