محلي مقابل الحدودي — ميزانية الأمر

fallback strategy — تركيب نماذج كتير

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

أي production app بيستخدم نموذج واحد عنده single point of failure. النموذج ممكن يكون نازل. النموذج ممكن يرجّع قمامة على شكل input معيّن. النموذج ممكن يطلع بره الـprice لـuse case لو الـvendor عدّل التسعيرة. والحاجة اللي الفرق بتخطط لها أقل — النموذج ممكن يتشال على جدول معلن والكود بتاعك لسه بيناديه. الـpattern الناضج هو إنك تركّب نماذج كتير بـfallback logic صريح.

الفشل اللي الكل بينساه: النموذج رايح

كل vendor بينشر صفحة deprecation، وكل vendor في الآخر بيشيل النموذج اللي إنت بتناديه. ده مش حدث نادر ومش من غير إعلان — ده التزام بتاريخ تقدر تقراه النهارده:

الـvendorالجدول موجود فين
AnthropicModel deprecations — بيقول حالة النموذج وتاريخ الـdeprecation وتاريخ الشيل لكل model ID
OpenAIDeprecations — تواريخ الإغلاق والبديل الموصى بيه
GoogleModel versions and lifecycle — تواريخ الشيل لكل نموذج

النماذج التلاتة اللي الكورس ده صوّرها مثال حي. كانوا حاليين وقت الـcaptures في أبريل 2026. اقرا الصفحات دي النهارده قبل ما تنقل أي model ID من الكورس ده لكود production: واحد منهم على الأقل عنده تاريخ شيل جوه الشهور الجاية، والـrequest للنموذج المشيل ما بيضعفش — بيفشل.

وعشان كده طبقة الـrouting اللي تحت تستاهل تتبني حتى لو إنت مستخدم نموذج واحد بس. النظام اللي عنده مسار fallback عنده أصلاً مكان يبعت له الـtraffic يوم ما الشيل يحصل. النظام اللي ماعندوش عنده outage وإعادة كتابة.

العادة التشغيلية صغيرة: حط صفحة الـdeprecation لكل نموذج بتناديه على تذكير ربع سنوي، وخلّي الـmodel ID في الـconfiguration مش مكتوب في مكان الـcall. الاتنين بياخدوا دقايق. ولا واحد فيهم مثير. وهما الفرق بين migration وحادثة.

الـ3 patterns اللي بتشتغل

Pattern 1 — primary + fallback. الأبسط. ابعت الـrequest للنموذج المفضّل عندك. لو الـresponse مش صالح (JSON parse فشل، body فاضي، error response، مخرج متقطّع)، حاول تاني على نموذج تاني. اختيارياً، بعد N فشل على الأساسي، حوّل كل الـtraffic للـfallback لفترة cooldown. ده الـsetup الإنتاجي الأشهر.

async function classifyWithFallback(input: string) {
  let reason: string;
  try {
    const r = await callPrimary(input);
    if (isValid(r)) return { result: r, model: "primary", fallbackReason: null };
    reason = "invalid-response";
  } catch (err) {
    reason = err instanceof Error ? err.name : "unknown-error";
  }
  const r = await callSecondary(input);
  return { result: r, model: "secondary", fallbackReason: reason };
}

خد بالك من اللي الـfunction دي بترجّعه. مش الإجابة بس — كمان أنهي نموذج طلّعها وليه الـfallback اشتعل. الـcatch {} الفاضي كان هيبقى أقصر، وكان هيرمي الحقلين اللي القسم اللي تحت "اللي تـlog-ه" بيقول إنك ما تقدرش تشتغل من غيرهم. معالجة الأخطاء اللي بترمي الخطأ هي أشهر طريقة طبقة الـfallback تبقى بيها مستحيلة الـdebug.

Pattern 2 — cheap-first, escalate. للمهام اللي أغلب inputs بتاعتها سهلة وكام منهم صعبين، وجّه كل حاجة لنموذج صغير الأول. لو إجابة النموذج الصغير فشلت في فحص تقدر تشغّله فعلاً، اطلع لنموذج أكبر. ده بيقلّل التكلفة على الأغلبية السهلة وبيدفع للنموذج الغالي بس على الباقي الصعب.

الـpattern كله بيعيش أو بيموت على الفحص ده، فلازم يكون signal حقيقي:

async function summariseEscalating(text: string) {
  const small = await callSmallModel(text);

  const needsEscalation =
    small.stopReason === "max_tokens" ||   // خلصت المساحة — ناقص
    small.refusal ||                        // رفض المهمة
    !passesTaskCheck(small.text);           // اختبار الصلاحية بتاعك إنت

  if (needsEscalation) return await callFrontierModel(text);
  return small;
}

نسخة أقدم من الدرس ده كانت بتطلع لنموذج أكبر لما مخرج النموذج الصغير يبقى تحت 50 token. اقرا ده قبال المهمة: الـfunction دي بتلخّص. التلخيص القصير هو الهدف. الشرط ده بيطلع لنموذج أغلى بالظبط لما النموذج الرخيص ينجح — وده بيقلب الاقتصاد اللي الـpattern موجود عشان يعمله. الطول مش مؤشر جودة؛ ده مؤشر طول. اطلع على stop reason، أو رفض صريح، أو فحص بيعبّر عن معنى "صح" في مهمتك.

Pattern 3 — verifier-on-top. نموذجين على نفس الـinput. الأول بيطلّع إجابة. التاني بيـverify الإجابة قبال الـinput. لو الـverifier رفض، اعمل regenerate. الـpattern ده overkill لإعادة كتابة نبرة بس أساسي لـcode generation، financial extraction، أو أي حاجة الغلط فيها غالي.

إزاي تعرف أنهي pattern مناسب

المهمة دي محتاجة أنهي fallback pattern؟

تكلفة وصول إجابة غلط للمستخدم قد إيه؟

الـpatterns قابلة للتركيب، والشجرة بتديك نقطة البداية مش الشكل النهائي للـarchitecture.

الـpatterns قابلة للـstacking. real production system ممكن يستخدم Pattern 2 بنموذج open-weight self-hosted كالنموذج الرخيص و Claude Sonnet 4.5 كالـescalation، بالإضافة لـverifier Pattern 3 فوق مسار Claude لأعلى 1% رهانات من الـrequests.

اللي تـlog-ه

أي multi-model setup محتاج 3 logging fields لكل request:

  1. أنهي نموذج طلّع الإجابة النهائية. ولا تقدرش تـdebug "ليه المستخدم بيشتكي من مخرج غريب؟" — المستخدم ما بيعرفش أنهي نموذج ردّ.
  2. ليه الـfallbacks اشتعلت (parse error، response فاضي، confidence قليل، manual override). ده الـdataset بتاعك لتحسين routing logic على الزمن.
  3. Cost per request. تكاليف الـtokens بتختلف عبر النماذج؛ تكاليف الـrequests بتختلف أكتر أول ما تحسب الـfallbacks. الـlog-هم عشان تقدر تثبت التوفير للـCTO.

الـlogging ده هو الأساس بتاع تقرير المقارنة اللي هتشحنه في المشروع الختامي. تقرير هاجر مش هيقول بس "إحنا المفروض نستخدم النماذج دي للمهام دي". هيورّي التوزيع الفعلي للـcost-per-request قبل وبعد تغيير الـrouting، معدل اشتعال الـfallback، وdrجات الجودة اللي بتظهر للمستخدم. من غير logging، ولا حاجة في ده قابلة للإثبات.

الـmodule الجاي: المشروع الختامي — انقل prompt واحد عبر 8 نماذج واشحن تقرير مقارنة حقيقي. :::

اختبار

الوحدة 5: محلي مقابل الحدودي — ميزانية الأمر

خذ الاختبار
هل كان هذا الدرس مفيدًا؟

سجّل الدخول للتقييم