تصور کنید یک نقص کوچک در سرویسدهنده، تنها به دلیل تکرار خودکار و کورکورانهٔ یک خطای ۴۲۹، به یک فاجعهٔ مالی در محیط عملیاتی تبدیل شود. اگر شما یک مهندس بکاند هستید که با APIهای مدلهای زبانی بزرگ برخورد میکند، احتمالاً آنها را مانند هر سرویس REST دیگری میبینید؛ اما این رویکرد، واقعیتهای عملیاتی هوش مصنوعی زاینده را نادیده میگیرد. این ریسک در تاریخ ۲ جولای ۲۰۲۶، در یک راهنمای فنی مفصل از وبسایت dev.to برجسته شد. این مقاله استدلال میکند که برخورد با این شکستها بهعنوان خطاهای استاندارد HTTP، اپلیکیشنها را کندتر کرده و عیبیابی آنها را دشوارتر میکند.
اکثر مهندسان با دستورالعملهای استاندارد آشنا هستند: کد ۴۰۰ به معنای بدساخت بودن درخواست است، ۴۰۱ یعنی احراز هویت شکست خورده است، ۴۲۹ به معنای محدودیت نرخ (Rate Limit) است و ۵۰۰ یعنی مشکلی در سمت سرور رخ داده است. راهکار معمول این است که چند بار تکرار (Retry) شود، یک تأخیر نمایی (Exponential Backoff) اضافه شود، بدنه پاسخ ثبت (Log) شود و سپس از آن عبور کرد. در حالی که این روش برای APIهای معمولی REST کاربرد دارد، اما برای ارائهدهندگان LLM خطرناک است. حتی زمانی که ارائهدهندگان از کدهای وضعیت استاندارد HTTP استفاده میکنند، معنای عملیاتی آنها به قدری متفاوت است که برخورد با آنها به عنوان شکستهای عادی میتواند اپلیکیشن را گرانتر و کندتر کند.
همانطور که در تحلیل قبلی ما دربارهی اعتبارسنجی SQL بدون هزینههای مدل زبانی اشاره کردیم، تمرکز اکنون از کاهش هزینه به مهندسی قابلیت اطمینان تغییر یافته است. در یک API سنتی، خطای ۴۰۰ به معنای این است که شکل درخواست نادرست است. اما در بافت LLM، خطای ۴۰۰ اغلب سیگنالی از یک شکست در سطح محصول در مدیریت بودجهٔ پرامپت است. برای یک توسعهدهنده، این تفاوت یعنی فاصله میان اصلاح یک غلط املایی در کد و بازطراحی کل سازوکار بازیابی اسناد در سیستم.
فریب کد وضعیت ۴۲۹
طبق گزارش dev.to، پاسخ ۴۲۹ یا «درخواستهای بیش از حد» (Too Many Requests)، یک ساختار یکپارچه نیست. این کد میتواند چندین وضعیت متمایز را نمایندگی کند که هر کدام نیاز به مدیریت متضاد دارند:
- محدودیتهای نرخ موقت: این خطاها به شکل
{"error": {"message": "Rate limit reached", "type": "rate_limit_error"}}ظاهر میشوند. در این مورد، تکرار درخواست با استراتژی Backoff واقعاً ممکن است کمک کند. - اتمام قطعی سهمیه (Quota): این خطاها به شکل
{"error": {"message": "You exceeded your current quota", "type": "insufficient_quota"}}نمایش داده میشوند. در اینجا تکرار درخواست هیچ کمکی نمیکند؛ بلکه فقط باعث افزایش تأخیر (Latency) میشود، لاگهای سیستم را پر از نویز میکند و تجربه کاربر را وخیمتر میکند. - فشار در سطح مدل: ممکن است یک مدل خاص در حالت بیشبار (Overloaded) باشد، در حالی که مدل دیگری از همان ارائهدهنده، یا حتی ارائهدهندهای کاملاً متفاوت، همچنان در دسترس باشد.
- مشکلات حساب یا صورتحساب: شکستهای کلی مربوط به حساب کاربری که با صبر کردن یا تکرار درخواست حل نمیشوند.
خطر تکرارهای کورکورانه
تکرارهای خودکار میتوانند خسارت را چند برابر کنند، بهویژه در گردشهای کاری عاملمحور (Agentic) — شبیه به کارمندی که وقتی جواب تلفن را نمیگیرد، هر ۱۰ ثانیه دوباره زنگ میزند و باعث ترافیک خط میشود. این پیچیدگی در مدیریت خطاها میتواند منجر به رفتارهای پیشبینیناپذیری شود؛ برای مثال، اشتباه در تشخیص کدهای وضعیت مانند ۴۰۴ در پروتکل MCP میتواند باعث قطع کامل دسترسی عاملها به ابزارهای حیاتی شود. فرض کنید کاربر گزارشی را درخواست میکند؛ بکاند درخواست را به LLM میفرستد و این درخواست پس از ۳۰ ثانیه دچار Time-out میشود. اگر کد بهطور ساده سه بار تکرار شود، ممکن است درخواست اول هنوز در سمت سرور در حال اجرا باشد. درخواست دوم ممکن است یک پاسخ تکراری تولید کند و درخواست سوم به یک محدودیت نرخ دیگر برخورد کند. در نهایت، کاربر مدت زمان بیشتری منتظر میماند، صورتحساب توکنهای شما افزایش مییابد و لاگها چهار تلاش برای یک اقدام واحد را نشان میدهند.
این مسئله زمانی حیاتی میشود که مدلهای زبانی باعث فعال شدن ابزارها شوند، ایمیل بفرستند، تیکتها را بهروزرسانی کنند، در دیتابیس بنویسند یا سیستمهای خارجی را فراخوانی کنند. تکرارهای کورکورانه میتوانند اثرات جانبی تکراری (Duplicate Side Effects) در سیستمهای خارجی ایجاد کنند. نویسنده پیشنهاد میکند منطق shouldRetry بر اساس «نوع عملیات» تعریف شود، نه فقط بر اساس کد وضعیت.
با تعریف یک LlmOperationType — مانند simple_completion (تکمیل ساده)، streaming_chat (چت استریمی)، tool_calling_agent (عامل فراخوانی ابزار)، background_batch_job (کار دستهای پسزمینه) یا structured_output (خروجی ساختاریافته) — توسعهدهندگان میتوانند منطق خود را دقیق کنند. برای مثال، یک tool_calling_agent یا streaming_chat تنها در صورتی باید تکرار شود که وضعیت ۵۰۰ یا بالاتر باشد، در حالی که یک simple_completion ممکن است روی ۴۲۹ تکرار شود. اگر نوع خطا بهطور خاص insufficient_quota باشد یا وضعیت ۴۰۰، ۴۰۱ یا ۴۰۳ باشد، سیستم باید فوراً مقدار false را برای تکرار بازگرداند.
پنجره زمینه و شکستهای استریم
خطاهای مربوط به طول متن معمولاً با کد ۴۰۰ باز میگردند. بهترین پاسخ، یک اصلاح در سطح محصول است، زیرا نشان میدهد اپلیکیشن بودجهٔ پرامپت را درست مدیریت نکرده است. راهکارهای سیستماتیک برای حل این مشکل شامل موارد زیر است:
- خلاصهسازی پیامهای قدیمی در تاریخچه گفتگو.
- کاهش حجم اسناد بازیابیشده از خط لوله تولید بازیابیافزا (RAG) — شبیه به وقتی که بهجای خواندن کل کتاب برای جواب دادن، فقط پاراگرافهای کلیدی را بیرون میکشید.
- کاهش حجم خروجیهای ابزارها.
- سوییچ به مدلی با پنجرهٔ زمینه (Context Window) — میزان متنی که مدل همزمان در ذهن نگه میدارد، شبیه به میز کاری که جا برای چند ورق دارد — بزرگتر.
- درخواست از کاربر برای محدود کردن وظیفه یا تقسیم کار به چندین فراخوانی مجزا.
در سطح سیستم، این راهنما پیشنهاد میکند تابع classifyLlmError پیاده شود. اگر یک خطای ۴۰۰ شامل متن "context length" بود، باید تحت دسته context_window_exceeded طبقهبندی شود. اگر خطای ۴۲۹ شامل کلمه "quota" بود، به عنوان quota_exceeded شناخته شود، در حالی که یک ۴۲۹ عمومی صرفاً rate_limited است.
استریم (Streaming) موضوع را پیچیدهتر میکند چون شکستها «وضعیتهای محصول ناقص» ایجاد میکنند. ممکن است مدل ۸۰٪ پاسخ را تولید کند و سپس ارتباط قطع شود. محصول باید تصمیم بگیرد که آیا خروجی ناقص باید نمایش داده شود، آیا رابط کاربری (UI) باید آن را به عنوان «ناقص» علامتگذاری کند، یا اینکه بکاند باید کل فرآیند را از ابتدا تکرار کند. برای محصولات چت، خروجی ناقص ممکن است مفید باشد. اما برای تولید کد، میتواند گمراهکننده باشد. برای تولید JSON، خروجی ناقص اغلب نامعتبر است و نباید مستقیماً مصرف شود.
برای مدیریت این وضعیت، نویسنده پیشنهاد میکند وضعیت استریم را بهطور صریح با استفاده از یک شیء StreamState ردیابی کنید که شامل requestId (شناسه درخواست)، برچسب زمانی startedAt (زمان شروع)، receivedTokens (توکنهای دریافت شده)، partialText (متن ناقص) و یک متغیر Boolean برای completed (تکمیل شده) باشد. اگر هیچ توکنی دریافت نشده باشد، اپلیکیشن میتواند بهطور خودکار تکرار کند؛ اگر توکنی دریافت شده باشد، میتواند نشانگر «ناقص» را نمایش دهد؛ و اگر JSON مورد انتظار بوده، باید خروجی را دور ریخته یا تعمیر کند.
پیادهسازی جایگزینی مدل (Fallback)
تغییر از مدل A به مدل B یک راهکار جهانی نیست. مدلهای مختلف در پنجره زمینه، قیمت، پشتیبانی از ابار، قابلیت اطمینان در JSON، پروفایل تأخیر، رفتار در رد درخواستها (Refusal) و کیفیت استدلال تفاوت دارند. یک جایگزینی خاموش از یک مدل با استدلال بالا به یک مدل کوچکتر، میتواند باعث افت کیفیت محصول شود، حتی اگر درخواست از نظر فنی «موفق» شود.
برای حل این مشکل، راهنما توصیه میکند مدلها را در کلاسهای وظیفهای سازماندهی کنید:
- استدلال بالا (High Reasoning):
gpt-4.1,claude-3-5-sonnet,gemini-1.5-pro. - چت سریع (Fast Chat):
gpt-4.1-mini,claude-3-haiku,gemini-1.5-flash. - دستهای ارزان (Cheap Batch):
gpt-4.1-mini,gemini-1.5-flash.
قوانین جایگزینی باید وابسته به وظیفه باشند. خلاصهسازی معمولاً میتواند جایگزینی را تحمل کند، اما تحلیلهای حقوقی یا مالی خیر. عاملهای فراخوانی ابزار به مدلهایی نیاز دارند که پشتیبانی سازگار از ابزار داشته باشند و گردشهای کاری خروجی ساختاریافته به مدلهایی نیاز دارند که طرحوارهها (Schemas) را با دقت دنبال کنند. مدلهایی که توسط کاربر انتخاب شدهاند هرگز نباید بهطور خاموش جایگزین شوند. استفاده از درگاههای مسیریابی مانند TokenBay اجازه میدهد این قوانین متمرکز شوند و در حالی که سطح API آشنا باقی میماند، انتخاب مدل و مسیریابی صریح شود.
ساخت یک تاکسونومی خطا
عیبیابی مؤثر نیازمند ثبت دادههای بیشتر از یک کد وضعیت ساده است. این راهنما پیشنهاد میکند مجموعهای جامع از فیلدها برای هر شکست ردیابی شود:
provider(مثلاً "openai") وmodel(مثلاً "gpt-4.1-mini").operation(مثلاً "support_ticket_summary" - خلاصهسازی تیکت پشتیبانی).error_category(مثلاً "rate_limited").input_tokens_estimated(تخمین توکنهای ورودی، مثلاً ۱۸۴۲۰) وoutput_tokens_received(توکنهای خروجی دریافت شده).streaming(مقدار Boolean) وretry_count(تعداد تکرارها).fallback_used(آیا از جایگزین استفاده شد) وlatency_ms(تأخیر به میلیثانیه، مثلاً ۱۲۸۳۳).
بدون این دادهها، قابلیت اطمینان تنها با «اسکرینشات و حس درونی» مدیریت میشود. در واقع، بسیاری از شکستهای پیچیده در عاملها به صورت «خطاهای خاموش» رخ میدهند که حتی داوران LLM نیز قادر به شناسایی آنها نیستند، به همین دلیل استفاده از مکانیسمهای مداخلاتی برای ردیابی دقیقتر این خطاها ضروری است. توسعه یک تاکسونومی داخلی LlmErrorCategory — شامل مواردی چون auth_error (خطای احراز هویت)، rate_limited (محدودیت نرخ)، quota_exceeded (اتمام سهمیه)، context_window_exceeded (اتمام پنجره زمینه)، content_refused (محتوای رد شده)، provider_unavailable (عدم دسترسی ارائهدهنده)، stream_interrupted (قطع استریم)، invalid_tool_call (فراخوانی ابزار نامعتبر) و malformed_structured_output (خروجی ساختاریافته بدساخت) — به اپلیکیشن اجازه میدهد بهطور سازگار تصمیم بگیرد که آیا تکرار کند، جایگزین شود یا به تیم هشدار دهد.
ماتریس مدیریت خطاها
به عنوان یک نقطه شروع کاربردی، نویسنده یک ماتریس مدیریت پیشنهاد میکند:
| دسته خطا | تکرار؟ | جایگزینی؟ | رفتار محصول |
|---|---|---|---|
auth_error |
خیر | خیر | درخواست از ادمین برای بررسی کلید API |
quota_exceeded |
خیر | شاید | توضیح درباره محدودیت ظرفیت یا مشکل صورتحساب |
rate_limited |
بله (با تأخیر) | شاید | صفبندی یا نمایش تأخیر کوتاه |
context_window_exceeded |
خیر | شاید | خلاصهسازی، کوتاه کردن یا تقسیم وظیفه |
provider_unavailable |
بله | بله | تکرار یا سوییچ به مدل دیگر |
stream_interrupted |
بستگی دارد | بستگی دارد | نمایش وضعیت ناقص |
content_refused |
خیر | خیر | درخواست از کاربر برای بازبینی درخواست |
malformed_structured_output |
بله (محدود) | شاید | تعمیر یا تولید مجدد |
invalid_tool_call |
شاید | خیر | اعتبارسنجی طرحواره و تکرار با احتیاط |
این تغییر دیدگاه مانع از آن میشود که توسعهدهندگان تظاهر کنند کدهای وضعیت HTTP حاوی تمام بافت عملیاتی مورد نیاز برای یک اپلیکیشن AI در سطح تولید هستند. با ساختن یک لایه خطا که حالتهای شکست خاص LLM را میشناسد، کاربران وضعیتهای خراب کمتری میبینند و لاگها برای تحلیل منطقیتر میشوند.
گام بعدی شما
- منطق تکرار (Retry) خود را از کد وضعیت HTTP به تاکسونومی
LlmErrorCategoryتغییر دهید. - برای عملیات حساس مانند فراخوانی ابزار، تکرارهای خودکار روی خطاهای ۴۰۰ و ۴۲۹ را غیرفعال کنید.
- یک سیستم نظارتی برای ثبت
fallback_usedایجاد کنید تا بفهمید چه مقدار از ترافیک شما به مدلهای ضعیفتر منتقل میشود.
اما مدیریت این خطاها تنها نیمی از مسیر است؛ بهینهسازی هزینه استنتاج با استفاده از مدلهای کوچکتر را در تحلیل بعدی ما بررسی خواهیم کرد.




گفتگو