جهاز مكالمة الوظيفة
Type: Build
Languages: Python
Prerequisites: Phase 13 lessons 01-07, Phase 14 lesson 01
Time: ~90 minutes
أهداف التعلم
- إغلف معالج الأدوات في وقت وقف لكل مكالمة يعيد خطأ منخفض بدلاً من تعليق الحلقة.
- تطبيق تعريفي إعادة محاولة الردع مع الارتباك والحد الأقصى عدد المحاولات.
- حاولت إعادة التكرار على مفتاح الاختلاف حتى لا تجري محاولة إعادة السباقات التي تمارس بطيئة الأصلية مرتين.
- استثناءات معالج الخرائط والخطأ النقل على غلاف خطأ واحد حلقة الحزام يفهم بالفعل.
- التسليم المتوازي المحدود مع حد التزامن بحيث أن إشعال من أربعين مكالمة أداة لا ينفذ حلقة الحدث.
حيث يجلس المرسل
بين حلقة الحرف (المرحلة العشرين) و سجل الأدوات (المرحلة العشرين و واحد). يقوم النقل (المرحلة العشرين و اثنين) بإغذاء الحلقة. يقدم الحلقة مكالمة أدوات إلى المرسل. يقوم المرسل بالاتصال إلى السجل، ويجري تشغيل المعاملة، ويرد إما نتيجة أو غلاف خطأ على شكل JSON-RPC.
flowchart TD
loop[harness loop]
disp[dispatcher]
reg[tool registry]
handler[handler]
loop --> disp
disp -->|get name| reg
disp -->|validate args| reg
disp -->|asyncio.wait_for handler args timeout| handler
handler -->|success| disp
handler -->|TimeoutError -> retry or fail| disp
handler -->|Exception -> map to error code| disp
disp -->|Ok result or DispatchError| loopالجهاز المُبعث هو الطبقة الوحيدة التي تعرف عن التوقيتات، والإعادة التجربة، والإعفاء. الحلقة لا تعرف. السجل لا يعرف. المُعامل لا يعرف. هذا العزل هو النقطة.
توقيت المدة
كل أداة لديها وقت استغناء افتراضي. سجل السجل يحمل timeout_msالمُرسل يُغلبها من إغلاق مكالمة عندما يمر الحزام واحدasyncio.wait_forفي وقت وقف، يتم إلغاء مهمة المدير والرئيس العائدDispatchError(kind="timeout"). . .
إن التوقف ليس خطأ قابل للتحويل افتراضي للأدوات غير ذات القدرة على التأثير.db.writeو قد يكون قد ارتكب أو لم يرتكب ذلك، و قد يكون محاولة إعادة التأهيل تكرر الكتابة.idempotentالعلامة من سجل السجل أدوات غير قادرة على المحاولة مرة أخرى أدوات غير قادرة على المحاولة
التجربة المُرجعة مع التخلف المتعرض
سياسة إعادة المحاولة ثلاث محاولات أقصى.
textattempt 1 -> delay 0
attempt 2 -> delay 0.1s * (1 + random[0..0.5])
attempt 3 -> delay 0.4s * (1 + random[0..0.5])فقطtimeoutوtransientالخطأ حاول مرة أخرى.schemaخطأ،not_foundأوinternalخطأ لا يحاول مرة أخرى. أخطاء الخطة هي تحديدية. لا تغير التجربة مرة أخرى النتيجة وتحرق الميزانية.
حلقة إعادة المحاولة تحترم الميزانية من الحزمة. إذا كان ميزانية المدعو صفر مكالمات الأداة المتبقية، فإن المرسل يفشل بسرعة في المحاولة الأولى ويسترجع kind="budget_exceeded". . .
مفتاح الاختفاء
محاولة إعادة إطلاق النار بينما الأصلي لا يزال في الطيران هو خطأ إنتاج حقيقي. الدعوة الأولى تعلق في أربعة نقاط تسعة ثواني (بعد فترة وقف الوقت مباشرة).payments.chargeلقد قمت بتحميل مرتين
المُرسل يقبل إختياريّةidempotency_keyإذا كان نفس المفتاح في الطيران عند وصول مكالمة، ينتظر المرسل المستقبل في الطيران ويرد نتيجه. الاحتفاظ بالمفتاح لمدة ستين ثانية بعد الانتهاء لتستيعاب التجربات المتأخرة.
المفتاح هو مسؤولية المُتصل، الحزام يستخرجها من المخطط:f"{step_id}:{tool_name}:{hash(args)}". لا يخترع المرسل المفاتيح، لأن استنباط مفتاح من الحجج وحدها يجعل مكالمات مختلفة من الناحية الدلوية تبدو نفسها.
غلاف الخطأ
إرسال فشل يعيد شكل واحد
textDispatchError
kind : "timeout" | "transient" | "schema" | "not_found" | "internal" | "budget_exceeded"
message : str
attempts : int
jsonrpc_code: int (one of -32601, -32602, -32603)خرائط حلقة الحزامkindإلى الولاية التاليةschemaوnot_foundاذهب إلىon_errorو تُفعّل إعادة التخطيطtimeoutوtransientاذهب إلىon_errorو قد يستعيد أو لا يستعيد حسب المحاولاتbudget_exceededمحفزاتon_budget_exceeded. . .
حد التنافسية على المروحة
gather(*calls)يعمل جميع التشغيلات في وقت واحد. مع أربعين مكالمة أداة، وهذا هو أربعين مصدر مفتوح أو أربعين أنابيب فرعية العملية. معظم الخلفيات لا تحب أربعين اتصال متوازي من عميل واحد.
المُرسل يُغلفgatherفي جهاز التشغيل. الحد الافتراضي المتزامن هو ثمانية. كل مكالمة اكتسب جهاز التشغيل قبل إرسالها وتطلق عند الانتهاء.gather-المخرجات ذات الشكل ولكن الجدول المحدد
التدفق لمكالمة واحدة
flowchart TD
start([caller: dispatch name, args, opts])
validate[registry.validate name, args]
schema_err[DispatchError kind=schema]
idem_check{idempotency cache?}
in_flight[await existing future]
cached[return cached result]
attempt[asyncio.wait_for handler args, timeout]
success[cache + return result]
timeout_branch{TimeoutError + idempotent?}
retry[retry with backoff]
fail[DispatchError]
transient_branch{TransientError?}
other[map Exception to kind, no retry]
exhausted[DispatchError]
start --> validate
validate -->|errors| schema_err
validate -->|ok| idem_check
idem_check -->|hit in flight| in_flight
idem_check -->|hit recent| cached
idem_check -->|miss| attempt
attempt --> success
attempt --> timeout_branch
timeout_branch -->|yes| retry
timeout_branch -->|no| fail
attempt --> transient_branch
transient_branch -->|yes, attempts left| retry
transient_branch -->|exhausted| exhausted
attempt --> other
retry --> attemptكيفية قراءة الرمز
code/main.pyيحددDispatcher،DispatchErrorوTransientError.المرسل يأخذ سجل على البناء .التزام الموافقةdispatch(name, args, ...)هي نقطة دخول الوحيدة. يتم تطبيق توقيتات لكل محاولة داخل الخط_run_with_retriesاستخدام asyncio.wait_for. .gather_bounded(calls)يدير العديد من الرسائل مع الحد المتزامن.
code/tests/test_dispatcher.pyتغطي إطلاق وقت وقف، وإعادة المحاولة على الخطأ المتجاري، وعدم إعادة المحاولة على خطأ مخطط، وتخفيض القدرة على الاستخدام (مكالمتين متزامنين مع انهيار نفس المفتاح إلى استدعاء واحد للمعامل) ، وتقييد التزامن (المركز في العمل).
الاختبارات تستخدمasyncio.sleep(0)و تحديديةCounter-المعالجة القائمة على المعدات، بحيث أنهيتها في ملايين الثانية ولا تعتمد على توقيت الساعة الحائطية.
الذهاب إلى أبعد
إضافة إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافيتين إضافات إضافيتين إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إضافات إdispatch.attemptوdispatch.retryحدث) ، ثانيا، قطع الدوائر: بعد فشل N في نافذة، يحصل الأداة على فترة تبريد حيث العثورات تعود على الفور مع kind="circuit_open"كلاً منهما يتناسب على هذا المُرسل دون تغيير العقد
الدرس 24 يعلق المُرسل إلى عميل خطط و تنفيذ حتى ترى جميع الأجزاء الأربعة في حركة.
This free lesson is part of the AI Engineering from Scratch curriculum. Read the full explanation, run the lesson code, and verify the result in the interactive reader or from the repository source.
Browse the complete course catalog or open this lesson on GitHub.