الوحدة 7 — نقاط النهاية وتقسيم حركة المرور والتوسّع
يوجد نموذج في السجلّ منذ الوحدة 6، لكنّه لا يخدم أحدًا. نقطة النهاية (Endpoint) هي عنوان HTTP يستقبل استدعاءات التوقّع الحيّة، ويوزّعها على إصدار واحد أو أكثر من النموذج. هذه الوحدة تُنشئ نقطة، تنشر عليها إصدارَين بتقسيم 90/10، تضبط التوسّع تلقائيًّا، وتُشغِّل تسجيل الطلبات في BigQuery للمراقبة.
بنية نقطة النهاية
نقطة النهاية كائن دائم بعنوان ثابت. نُنشئها مرّة، ثم تعيش سنينَ ونعدّل ما يُنشَر تحتها. نموذج (أو إصدار) واحد لا يمكن أن يستقبل حركةً بلا نقطة، لأنّ Vertex يُدير حدود التوسّع، عزل الحاويات، وتسجيل الطلبات على مستوى النقطة.
from google.cloud import aiplatform
aiplatform.init(project="fraud-detection-lab", location="europe-west1")
endpoint = aiplatform.Endpoint.create(
display_name="fraud-endpoint",
labels={"env": "prod", "usecase": "fraud"},
)
print(endpoint.resource_name)
نقطة النهاية الفارغة لا تكلّف شيئًا؛ الفاتورة تبدأ عند نشر إصدار عليها.
النشر الأوّل
نشر الإصدار الأوّل بحصّة 100 %:
model_v2 = aiplatform.Model("fraud-xgb@2") # الإصدار 2 حرفيًّا
endpoint.deploy(
model=model_v2,
deployed_model_display_name="fraud-xgb-v2",
machine_type="n1-standard-2",
min_replica_count=1,
max_replica_count=4,
traffic_split={"0": 100}, # كلّ الحركة إلى النموذج الوحيد
service_account="sa-endpoint@fraud-detection-lab.iam.gserviceaccount.com",
enable_access_logging=True,
)
النقاط الأربع للانتباه:
min_replica_count=1: نُسخة واحدة دومًا مشتغلة.min=0ممكن لتصفير الفاتورة عند الخمول، لكنّ استيقاظ حاوية مضغوطة يأخذ من 10 إلى 30 ثانية على أوّل طلب — كارثة على استجابة كشف الاحتيال المطلوبة تحت 200 مللي ثانية.max_replica_count=4: حدّ أعلى يحدّ الفاتورة عند فورة حركة. Vertex يضبط التوسّع بين الحدَّين حسب استعمال المعالج.machine_type: للتوقّع الفوريّ من نموذج XGBoost خفيف،n1-standard-2كافية. لا نحتاج وحدة معالجة رسوميّة للاستدلال إلّا للنماذج العصبيّة العميقة.enable_access_logging=True: تسجيل كلّ طلب واستجابته في Cloud Logging.
بعد نجاح النشر (بضع دقائق)، الاستدعاء:
resp = endpoint.predict(instances=[
{"amount": 245.0, "merchant_country": "TN", "device_id": "d-83", ...},
])
print(resp.predictions[0])
# 0.032 ⇒ احتمال احتيال 3.2 %
تقسيم حركة المرور: النشر الأزرق-الأخضر و«الكنّاريّ»
الإصدار الجديد (fraud-xgb@3) اجتاز التقييم، وحان وقت نشره. بدل تبديل صاعق (كلّ الحركة دفعة واحدة)، نُشغّله على 10 % لمدّة 24 ساعة قبل الاعتماد الكامل:
model_v3 = aiplatform.Model("fraud-xgb@3")
endpoint.deploy(
model=model_v3,
deployed_model_display_name="fraud-xgb-v3",
machine_type="n1-standard-2",
min_replica_count=1,
max_replica_count=4,
traffic_split={"<deployed_model_id_v2>": 90, "<deployed_model_id_v3>": 10},
)
يُحدَّد <deployed_model_id_v2> من endpoint.list_models()؛ Vertex يُعطي معرِّفًا للنموذج المنشور (يختلف عن معرِّف الإصدار في السجلّ).
بعد يوم مراقبة، ننقل النسبة تدريجيًّا:
endpoint.update_traffic_split({
"<deployed_model_id_v2>": 50,
"<deployed_model_id_v3>": 50,
})
# بعد ساعات إضافيّة:
endpoint.update_traffic_split({
"<deployed_model_id_v2>": 0,
"<deployed_model_id_v3>": 100,
})
# ثمّ سحب الإصدار القديم:
endpoint.undeploy(deployed_model_id="<deployed_model_id_v2>")
مكاسب هذه المقاربة، مقارنة بتبديل صاعق:
- الاستجابة: نراقب زمن الاستجابة على النسخة الجديدة تحت 10 % من الحركة قبل أن تُصبح المسؤولة عن كلّ شيء.
- جودة التنبّؤ: بيانات حقيقيّة قصيرة الأجل تتيح مقارنة معدّل الإنذارات الخاطئة بين النسختين على نفس المُدخَل.
- العودة الفوريّة: إن انكشف انحدار،
update_traffic_splitيُعيد 100 % إلى الإصدار السابق في ثوانٍ، بلا إعادة نشر.
التقسيم بين إصدارَين هو ما يُسمّى نشرًا «كنّاريًّا» (canary deployment). ثلاثة إصدارات ({v1: 80, v2: 10, v3: 10}) ممكن لكن نادر الحاجة.
التوسّع التلقائيّ
Vertex يزيد وينقص عدد النُّسخ بين min_replica_count وmax_replica_count وفق استعمال المعالج (CPU utilization). القاعدة الافتراضيّة: كلّ نسخة تعمل بين 40 % و60 % من المعالج. تجاوز 60 % طويلًا يُطلق نسخة إضافيّة؛ نزول تحت 40 % لعشر دقائق يُنقص نسخة.
قرارات المعاملات:
- ضع
minبحيث يُدير الطلب المعتاد بلا استيقاظ بارد. لكشف الاحتيال ذي حركة ثابتة: 1 تكفي. - ضع
maxعند سقف يحفظ الفاتورة عند هجوم أو فورة موسميّة. عشرة نُسخ = 500 دولار في اليوم؛ حدّده وفق ميزانيّتك، لا وفق حجم توقّعك. - توسّع نسخة يستغرق دقيقة أو دقيقتين. إن كانت فورة حركتك دقيقة، حاجتك ليست تلقائيّة أوسع، بل
minأعلى.
المُسرِّعات على نقطة النهاية
نموذج XGBoost خفيف لا يستفيد من GPU للاستدلال. لنماذج عصبيّة كبيرة (Transformer، رؤية عميقة):
endpoint.deploy(
model=big_model,
machine_type="n1-standard-8",
accelerator_type="NVIDIA_TESLA_T4",
accelerator_count=1,
min_replica_count=1,
max_replica_count=2,
)
كلّ نسخة تحمل الآن T4 خاصّتها. الفاتورة تصير 250 دولارًا تقريبًا في اليوم لنسختين مشتغلتين على مدار 24 ساعة. القرار: هل تستحقّ الاستجابة الأسرع هذه الكلفة، أم يُفضَّل التوقّع بالدفعات (الوحدة 8)؟
تسجيل الطلبات إلى BigQuery
المراقبة الحقيقيّة تبدأ حين نُسجّل الاستدعاءات:
endpoint.enable_model_deployment_monitoring(
logging_sampling_rate=1.0,
bigquery_tables_prefix="bq://fraud-detection-lab.monitoring.fraud_endpoint",
)
كلّ استدعاء يُحوَّل إلى صفّ في جدول BigQuery، مع المُدخَل، التنبّؤ، الطابع الزمنيّ، ومعرِّف النسخة المستقبِلة. الاستفادات:
- ملاحظة انحراف البيانات: مقارنة أسبوعيّة لتوزيع
amountمع توزيع التدريب تكشف انحرافًا مبكرًا. - مقارنة كنّاريّة عادلة: نسبة الإنذار على v2 مقابل v3 على أسبوع كامل من الطلبات نفسها.
- إعادة تدريب موثَّقة: بعد شهر، بيانات الإنتاج مع توسيمها المتأخّر تصير مجموعة تدريب حقيقيّة.
نسبة العيّنة 1.0 (كلّ الطلبات) مقبولة لحجم كشف الاحتيال (ملايين في اليوم). لخدمات ذات مليار طلب يوميًّا نُقلِّصها إلى 0.05.
السرّية والتنظيم
مؤشِّرات القراءة الحسّاسة (رقم البطاقة، البيانات الشخصيّة) لا تُرسَل إلى نقطة النهاية أصلًا. البنية الصحيحة: خدمة وسيطة تُحوِّل المدخل إلى ميزات مجهولة (بصمة أحاديّة الاتّجاه للبطاقة، مُقنَّعة الأرقام) ثمّ ترسل الميزات إلى Vertex. النموذج لا يحتاج البيانات الأصليّة، والفاتورة التنظيميّة تنخفض كثيرًا.
min_replica_count=0 وسعر الاستجابة الأوّليةتصفير النُّسخ عند الخمول يُوفِّر الفاتورة لكنّ الطلب الأوّل يستيقظ حاوية باردة: من 10 إلى 30 ثانية. لكشف احتيال يجب أن يجيب تحت 200 مللي ثانية، هذا مقتل. min=0 مقبول لخدمة داخليّة نادرة الاستعمال (تقرير أسبوعيّ يشغِّله المدير)، لا لخدمة الإنتاج.
access loggingعند تعطُّل استدعاء (خطأ 5xx)، سجلّات الوصول تعرض المدخل الذي تسبَّب. بدونها، عليك إعادة إنتاج المشكلة بمعطيات صنعتها بنفسك — قد لا تجد الحالة أبدًا. enable_access_logging=True منذ اليوم الأوّل.