اگر هر خطای API را با یک درخواست مجدد پاسخ میدهید، در واقع دارید بودجه استنتاج خود را دور میریزید. تصمیم برای تکرار یک فراخوانی مدل، یک تصمیم مالی است، نه یک واکنش فنی ساده. در ۱۱ اکتبر ۲۰۲۶، یک راهنمای عملی در وبسایت dev.to منتشر شد که جزئیات یک کارگاه ۷۰ دقیقهای را شرح میداد. هدف این کارگاه متوقف کردن عادت «تکرار خودکار» در برنامههای هوش مصنوعی از طریق پیادهسازی یک طبقهبندیکننده محلی است.
بسیاری از توسعهدهندگان هر خطای API را یک اختلال موقت میبینند. این رویکرد باعث اتلاف ظرفیت مشترک و توجه تیمها میشود، بهویژه زمانی که از نقاط انتهایی (Endpoints) رایگان استفاده میکنند. برای مثال، یک «زمان انتظار» (Transport Timeout) و یک «رد درخواست به دلیل ساختار اشتباه» (Schema Rejection) هر دو در لاگها به شکل شکست ظاهر میشوند، اما فقط مورد اول توجیهپذیر است که دوباره تلاش کنیم. تکرار در مورد دوم، صرفاً اتلاف منابع است.
همانطور که در تحلیلهای قبلی ما دربارهی بهینهسازی هزینههای مدلهای زبانی اشاره کردیم، کاهش هزینهها باید از لایه منطق برنامه شروع شود. این کارگاه منطق تصمیمگیری را از یک شعار مبهم («تلاش دوباره کن») به یک قرارداد محلی سختگیرانه تبدیل میکند. این سیستم تضمین میکند که کلاینت درخواستی را که سرور به دلیلی دائمی رد کرده است، تکرار نکند. در اینجا هدف، ارزیابی کیفیت پاسخ مدل نیست، بلکه برچسبگذاری خودِ شکست است. این رویکرد دقیقاً مکمل روشهایی است که در آن ثبت خروجیهای مدل در قالب Snapshot برای مقابله با خطاهای نامشخص ارزیابی پیشنهاد شده است تا از نوسانات پاسخها جلوگیری شود.
چارچوب سه-اقدامی
مرکز این آموزش، یک ماتریس تصمیمگیری است که دانشجویان را مجبور میکند برای هر شکست، یکی از سه اقدام زیر را توجیه کنند. تا دقیقه هفتادم، هر دانشجو باید بتواند این اقدامات را با یک رکورد، یک دلیل و یک مقدار بولی (Boolean) برای فراخوانی دوم دفاع کند:
- تکرار یکباره (Retry Once): تنها یک تلاش اضافی مجاز است. اگر درخواست دوم هم با همان خطا مواجه شد، فرآیند باید متوقف شود. این مورد زمانی استفاده میشود که احتمال دارد مشکلات انتقال داده بدون نیاز به ویرایش قرارداد (Contract) برطرف شوند.
- توقف (Stop): کلاینت نباید دوباره درخواست بفرستد تا زمانی که یک انسان برای تغییر درخواست، اعتبارنامهها یا قرارداد وارد شود. این اتفاق زمانی میافتد که بودجه آموزشیِ «یکبار تلاش» تمام شده باشد یا فراخوانی از اساس خراب باشد.
- بررسی (Inspect): زمانی که ردیف خطا ناقص یا مبهم است، سیستم نباید حدس بزند؛ بلکه باید خطا را برای بررسی انسانی نمایش دهد. این کار از به ارث بردن مسیر تکرار گذرا در شرایطی که علت خطا نامشخص است، جلوگیری میکند.
پیادهسازی فنی و منطق
این کارگاه از اسکریپتی به نام retry_gate.py استفاده میکند که با پایتون ۳.۱۱ یا نسخههای جدیدتر نوشته شده است. برای حفظ استقلال از آینههای بستههای نرمافزاری (Package Mirrors)، این اسکریپت تنها از کتابخانه استاندارد پایتون استفاده میکند و هیچ وابستگی به شخص ثالث ندارد. دانشجویان تنها به یک ترمینال، یک ویرایشگر متن و لیست نمونههای (Fixtures) ارائه شده در داخل ماژول نیاز دارند.
طبق مستندات این کارگاه، طبقهبندیکننده از یک سلسلهمراتب سختگیرانه برای تعیین نتیجه پیروی میکند. ترتیب این بررسیها برای منطق برنامه حیاتی است:
- بودجه تکرار: ابتدا پرچم
already_retriedبررسی میشود. اگر مقدار آن True باشد، بدون توجه به کد خطا، بلافاصله دستور توقف با دلیل «بودجه تکرار قبلاً مصرف شده است» صادر میشود. این کار تضمین میکند که بودجه آموزشی یکبار-تلاش به شدت اجرا شود. - خطاهای انتقال: اسکریپت به دنبال خطاهای کلی مانند
timeout،connection_resetیاdns_temporaryمیگردد. این موارد واجد شرایط تکرار یکباره هستند زیرا مشکلات انتقال ممکن است بدون تغییر در قرارداد برطرف شوند. - شکستهای دائمی: کدهای وضعیت ۴۰۰، ۴۰۱، ۴۰۳، ۴۰۴، ۴۱۳ و ۴۲۲ منجر به توقف میشوند، زیرا تکرار همان فراخوانی، قرارداد را اصلاح نمیکند (مثلاً در موارد مربوط به وضعیت کلاینت یا احراز هویت).
- محدودیت نرخ (Rate Limits): کد ۴۲۹ صراحتاً به عنوان بررسی برچسب میخورد. در استخرهای رایگان مشترک، محدودیت نرخ ممکن است یک سقف دائمی باشد نه یک نوسان کوتاه، بنابراین نیاز به قانون انسانی دارد و نباید مسیر تکرار گذرا را دنبال کند.
- وضعیتهای گذرا: کدهای ۴۰۸، ۵۰۰، ۵۰۲، ۵۰۳ و ۵۰۴ مشروط به موجود بودن بودجه، مجاز به تکرار یکباره هستند. اگر
already_retriedبرابر True باشد، اقدام به توقف تغییر میکند. - موارد خاص: بدنه خالی در پاسخهای موفق (کد ۲۰۰ بدون محتوا) یا کدهای وضعیت مفقود، به بخش بررسی هدایت میشوند. هر وضعیت تعریفنشدهای نیز به
inspectمیرود تا از حدس زدن در مورد تکرار جلوگیری شود، که این امر یک شکست در بررسی خروجی محسوب میشود.
جزئیات جدول تصمیمگیری
اسکریپت در واقع یک نسخه قابل اجرا از یک قرارداد خاص است. دانشجویان ماتریسی را پیاده میکنند که در آن اعداد وضعیت، یک زیرمجموعه آموزشی هستند. هر کد تعریفنشدهای باید به جای تکرار خاموش، به inspect ختم شود:
- سیگنالهای انتقال (
timeout,connection_reset,dns_temporary) $
ightarrow$retry_once(فراخوانی دوم: بله، یکبار). - وضعیتهای گذرا (۴۰۸، ۵۰۰، ۵۰۲، ۵۰۳، ۵۰۴) $
ightarrow$retry_once(فراخوانی دوم: بله، یکبار؛ توقف در صورت True بودنalready_retried). - اتمام بودجه (
already_retriedis true) $
ightarrow$stop(فراخوانی دوم: خیر). - شکست قرارداد (۴۰۰، ۴۰۱، ۴۰۳، ۴۰۴، ۴۱۳، ۴۲۲) $
ightarrow$stop(فراخوانی دوم: خیر). - محدودیت نرخ (۴۲۹) $
ightarrow$inspect(فراخوانی دوم: خیر). - پاسخهای ناقص (۲۰۰ با بدنه خالی) $
ightarrow$inspect(فراخوانی دوم: خیر). - موارد ناشناخته (وضعیت مفقود یا تعریفنشده) $
ightarrow$inspect(فراخوانی دوم: خیر).
برنامه آموزشی ۷۰ دقیقهای
این کارگاه به صورت یک آزمایشگاه زمانبندی شده با چکهای خروجی مشخص برای هر بلوک طراحی شده است. به مربیان توصیه میشود اسکریپت را قبل از ورود دانشجویان در فضای کاری قرار دهند. ده دقیقه زمان اضافی در بلوکهای میانی برای رفع خطاهای مربوط به نسخه پایتون یا مسیرها (Path) در نظر گرفته شده است. ده دقیقه پایانی برای بررسی محدودیتها رزرو شده است، نه برای دموهای زندهای که قبلاً اندازهگیری نشدهاند.
- دقیقه ۰ تا ۱۰: دانشجویان سه اقدام اصلی را بدون نگاه به کد تعریف میکنند. آنها باید مثالی از حالت «توقف» از روی تمرینات معمول HTTP بیاورند، مانند نبود اعتبارنامه یا رد شدن ساختار (Schema). شکایتها درباره کیفیت مدل به عنوان تعریف معتبر پذیرفته نمیشوند زیرا به کلاینت نمیگویند چه کاری انجام دهد. این بلوک تنها زمانی پایان مییابد که هر زوج بتواند به متغیر بولی که اجازه فراخوانی دوم را میدهد، اشاره کند.
- دقیقه ۱۰ تا ۲۵: دانشجویان ماژول را روی ۷ نمونه شکست ثبتشده اجرا میکنند. آنها باید به یک خلاصه طراحیشده برسند که در آن
checked=7وfailed=0باشد. این یک مشخصه (Specification) است و نه یک عدد مربوط به عملکرد. اگر پایتون در دسترس نباشد، این مرحله میتواند به صورت بررسی دستی روی کاغذ انجام شود، هرچند این مسیر کندتر است. - دقیقه ۲۵ تا ۴۵: دانشجویان برای ردیفهای خاص دفاعیه مینویسند. آنها باید توضیح دهند چرا عدم تطابق ساختار (۴۲۲) با تکرار حل نمیشود و چرا کد ۴۲۹ میتواند بار روی یک استخر رایگان مشترک را افزایش دهد. آنها باید نام فیلدی که شواهد را حمل میکرد (مانند
statusیاerrorیاalready_retried) ذکر کنند. - دقیقه ۴۵ تا ۶۰: دانشجویان تابع
plan_nextرا ردیابی میکنند تا تایید کنند که برای تمام ردیفها به جز اولین ۵۰۳ و Timeout، برنامه «پرش» (Skip) است. سپس یک نمونهt8(وضعیت ۴۰۹، اقدام مورد انتظارinspectو برنامه مورد انتظارskip) اضافه میکنند تا مسیر سقوط (Fall-through) تعریفنشده را تست کنند. قانون موجود باید این مورد را بدون نیاز به شاخه جدید بپذیرد و منجر به خلاصهchecked=8وfailed=0شود. - دقیقه ۶۰ تا ۷۰: دانشجویان یادداشتی شامل سه موردی که اسکریپت قادر به تصمیمگیری درباره آنها نیست ارسال میکنند. موارد معتبر شامل فراخوانیهای ابزار غیر-idempotent، کدهای ۴۲۹ دارای هدر
Retry-Afterیا کدهای اختصاصی تامینکننده خارج از مجموعه آموزشی است. شکایتهای مبهم درباره هزینه یا سرعت پذیرفته نیستند زیرا بررسیکننده هرگز این سیگنالها را ندیده است.
یکپارچگی با میزبانهای آزمایشگاه
در این راهنما از MonkeyCode به عنوان میزبان احتمالی برای دسترسی رایگان به مدلها و گزینههای سرور رایگان یاد شده است. با این حال، تأکید میشود که طبقهبندیکننده محلی، محصول اصلی است. میزبان صرفاً مکانی برای اعمال برچسبها روی لاگهای سانسورشده پس از پایدار شدن منطق است.
از آنجایی که هدف طبقهبندی رکوردهایی است که مربی قبلاً ثبت یا ساخته است، استفاده از کلید زنده (Live Key) خارج از محدوده است. این اسکریپت یک ابزار آموزشی با چک خروجی طراحیشده است، نه بنچمارکی برای یک میزبان تولیدی. اگر آزمایشگاهی از گزینههای رایگان MonkeyCode استفاده میکند، دانشجویان باید ابتدا ردیفهای خطای سانسورشده را طبقهبندی کنند. اگر مستندات میزبان با کارگاه در تضاد بود، دانشجویان باید از مستندات پیروی کنند اما نمونههای محلی را به عنوان محصول نمرهگذاری شده حفظ کنند.
برای حفظ حریم خصوصی، راهنما قوانین سختگیرانهای برای خروجی لاگها تعیین میکند. هر لاگی که از میزبان صادر میشود باید فاقد موارد زیر باشد:
- پرامپتها و تکمیلهای خام (Raw prompts and completions)
- هدرهای احراز هویت (Authorization headers)
- شناسههای کاربر (User identifiers)
رشتههای خطای تامینکننده باید به یک مجموعه تگ کوچک (مانند timeout یا connection_reset) نگاشت شوند. رشتههای ناشناخته باید خالی بمانند تا طبقهبندیکننده با آنها به عنوان inspect برخورد کند و نه تکرار خودکار.
محدودیتهای این رویکرد
این کارگاه اذعان میکند که این یک ابزار آموزشی است، نه یک کتابخانه آماده برای محیط تولید (Production). این ابزار برای دورههایی که بر کتابخانههای تکرار پیشرفته با Jitter، مدارشکنها (Circuit Breakers) یا کلیدهای Idempotency تمرکز دارند، مناسب نیست. همچنین اگر دانشجویان با دادههای محافظتشده سروکار دارند یا هدف مقایسه کیفیت مدل است، باید از این تمرین صرف از آن بگذرد، زیرا هیچ ردیفی شامل پاسخهایی برای امتیازدهی نیست. این چالشها مشابه تلههای حافظه در کدنویسی با AI است که باعث میشود دموهای موفق در محیط واقعی شکست بخورند.
محدودیتهای فنی خاص عبارتند از:
- تشخیص ساده بدنه: اسکریپت تفاوتی بین مقدار null در JSON، یک رشته شامل فضای خالی و یک کلید مفقود قائل نمیشود.
- ترمز آموزشی: سیاست «یکبار تکرار» یک محدودیت ساده شده است و ممکن است در زمان وقوع طوفانهای گسترده خطای ۵۰۳ ناکافی باشد.
- فقدان زمینه: اسکریپت توکنها، تأخیر یا عمق صف را اندازه نمیگیرد و اثرات جانبی فراخوانیهای ابزار غیر-idempotent را نمیبیند. چنین مواردی باید حتی اگر وضعیت گذرا به نظر میرسید، به عنوان توقف علامتگذاری شوند.
- قوانین ایستا: در محیط واقعی، کد ۴۲۹ همراه با راهنمای
Retry-Afterبرای به تعویق انداختن درخواست ایمن است، اما چون این نمونهها چنین راهنمایی ندارند، برچسب صادقانه برای آنهاinspectباقی میماند.
تسهیلگری و نمرهدهی
مربیان تشویق میشوند که از تبدیل یادداشت پایانی به رقابت بین ابزارها جلوگیری کنند، زیرا محیط فاقد نتایج اندازهگیری شده از تامینکنندگان است. نمرهدهی باید بر اساس دلایل مکتوب، عبور از چککننده محلی و لیست محدودیتها باشد، نه تعداد درخواستهای زندهی ارسالی. کار در گروههای دو نفره توصیه میشود تا اطمینان حاصل شود هر فرد میتواند فیلدی را که توجیهکننده اقدام توقف بود، شناسایی کند.
اگر پایتون در دسترس نباشد، بررسی روی کاغذ همچنان پذیرفته است، به شرطی که مقادیر بولی دقیقاً با جدول مطابقت داشته باشند. نتیجه اصلی قابل تست است: هفت ردیف محلی، سه اقدام و یک نگهبان که از تکرار بدون دلیل جلوگیری میکند. ماژول را اجرا کنید، خلاصه طراحیشده را تایید کنید و تنها پس از آن، نقشه فیلدها را به لاگهای میزبان متصل کنید. برای کسانی که به دنبال پایداری در دموهای زنده هستند، الگوی Cassette راهکاری برای بستن نشتهای مهندسی و جلوگیری از شکستهای پیشبینینشده است.
این تغییر در رویکرد، تمرکز توسعهدهنده را از «امید به موفقیت» به «طبقهبندی شکست» منتقل میکند. با تبدیل طبقهبندیکننده به یک قرارداد، تیمها میتوانند هزینههای API را کاهش داده و مشاهدهپذیری خطوط لوله هوش مصنوعی خود را بهبود ببخشند.
گام بعدی شما
- اسکریپت
retry_gate.pyرا روی لاگهای فعلی پروژه خود اجرا کنید تا درصد درخواستهای تکراری بیهوده را بسنجید. - یک ماتریس تصمیمگیری برای کدهای خطای خاصِ تامینکننده مدل خود (مانند OpenAI یا Anthropic) طراحی کنید.
- منطق «بودجه تکرار» را به لایه Middleware برنامه خود اضافه کنید تا از حلقههای تکرار بینهایت جلوگیری شود.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو