تصور کنید یک مشتری پرمصرف، بهطور اتفاقی تمام بودجهٔ پردازش شما را مصرف کند و کل خط لولهٔ هوش مصنوعی شرکت را برای سایر کاربران متوقف سازد. برای حل این بحران، در ۲۳ اوت ۲۰۲۶، یک راهنمای فنی در dev.to الگویی معماری برای APIهای بازشناسی گفتار (ASR) در محیط Node.js معرفی کرد که با ایزولهکردن حجم کاری هر مشتری، از این شکستهای سیستمی جلوگیری میکند.
بسیاری از توسعهدهندگان در ابتدا از طراحی سادهای استفاده میکنند: ارسال مستقیم فایل صوتی به API و انتظار برای پاسخ. این رویکرد خطرناک است چون تأخیر کاربر را با ظرفیت ارائهدهنده گره میزند. اگر یک مشتری دستهای عظیم از فایلها را آپلود کند، تمام ظرفیت همزمانی (Concurrency Budget) را اشغال کرده و سایر کاربران را در وضعیت انتظار میگذارد. علاوه بر این، در این مدل، یک درخواست HTTP ساده مسئول کاری است که ممکن است بسیار طولانیتر از زمان تعیینشده برای Timeout باشد و منجر به قطع شدن اتصال پیش از دریافت پاسخ شود.
برای حل این مشکل، معماری پیشنهادی فرآیند تبدیل متن را به یک صف اختصاصی برای هر مشتری منتقل میکند. در این حالت، سیستم بهجای درخواست مستقیم، کار را سریعاً میپذیرد، یک شناسهٔ کار (Job ID) اختصاص میدهد و آن را بهصورت عادلانه زمانبندی میکند. این کار باعث میشود چرخهٔ درخواست HTTP از زمان واقعی پردازش — که برای فایلهای صوتی طولانی بسیار زیاد است — جدا شود. برای یک استودیوی بازیسازی، هدف تنها دریافت متن نیست، بلکه اجرای مجموعهای از عملیات در CRM است که به یک ناشر، شریک پلتفرم یا خریدار تبلیغات متصل باشد. این سطح از انتساب (Attribution) برای پاسخ به این سؤال دشوار ماهانه ضروری است: کدام مشتری دقیقاً باعث ایجاد این هزینهٔ هوش مصنوعی شده است؟
همانطور که در تحلیلهای قبلی ما دربارهی بهینهسازی هزینههای استنتاج اشاره کردیم، جداسازی لایهی پذیرش از لایهی اجرا، کلید مقیاسپذیری در محیطهای چندمستاجری (Multi-tenant) است.
مدیریت محدودیت نرخ (Rate Limit) ۴۲۹
هستهٔ این سیستم نحوهٔ برخورد با پاسخهای HTTP 429 (درخواستهای بیش از حد) است. به نقل از این راهنما، خطای ۴۲۹ باید بهجای یک شکست، بهعنوان یک «پاسخ زمانبندی» تلقی شود. از آنجا که ارائهدهندگان مختلف محدودیتهای متفاوتی را بر اساس حساب کاربری و قراردادهای مختلف اعمال میکنند، زمانبند نباید فرض کند که یک شمارندهٔ جهانی ساده برای درخواست در دقیقه (RPM) تمام خطاهای ۴۲۹ را توضیح میدهد.
- هدرهای Retry-After: سیستم باید مقدار
Retry-Afterرا تحلیل کند. این سیستم باید هر دو فرمت «ثانیههای صحیح» (Integer-seconds) و «تاریخ HTTP» (HTTP-date) را پشتیبانی کند. این مقدار به عنوان حداقل تأخیر پیش از تلاش بعدی در نظر گرفته میشود. - عقبنشینی جایگزین (Fallback Backoff): اگر هدر مذکور موجود نباشد یا نامعتبر باشد، سیستم باید از روش Exponential Backoff (عقبنشینی نمایی) با سقف مشخص، همراه با Jitter (تغییرات تصادفی کوچک) استفاده کند. ایجاد یک حلقه تکرار سریع (Tight retry loop) توصیه نمیشود، زیرا باعث مصرف بیهوده درخواستها شده و روند بازیابی را کندتر میکند. این موضوع یادآور چالشهای مدیریت خطا در درخواستهای مدلهای زبانی است که در تحلیل ما درباره اشتباهات رایج بازخوانی درخواستهای LLM و راهکارهای TypeScript به تفصیل بررسی شده است.
- تفکیک خطاها: پاسخهای 4xx غیر از ۴۲۹ — مانند خطاهای مربوط به قابلیتها، احراز هویت، پیکربندی یا ورودیهای نامعتبر — بهعنوان مشکلات دائمی شناخته میشوند. تکرار خودکار این خطاها ناامن است. سیستم باید بدنهٔ پاسخ را برای تشخیص دقیقتر همراه با Job ذخیره کند، تلاش را به عنوان «شکست خورده» علامتگذاری کند و اجازه دهد یک اپراتور یا یک قانون محصولی (Product Rule) درباره گام بعدی تصمیم بگیرد.
رویکرد ماشین وضعیت (State Machine)
برای پایداری بکاند و راستگویی رابط کاربری CRM، این سیستم از یک ماشین وضعیت کوچک با TypeScript استفاده میکند. هر کار بین پنج وضعیت صریح جابهجا میشود: pending (در انتظار)، running (در حال اجرا)، retry_wait (انتظار برای تکرار)، complete (تکمیل شده) و failed (شکست خورده).
این ساختار اجازه میدهد یک Worker مسئول تماس با ارائهدهنده باشد، در حالی که اپلیکیشن اصلی پاسخگو باقی میماند. درخواست آپلود صرفاً شناسهٔ کار و وضعیت pending را برمیگرداند و مدیریت تعامل با API و جابهجایی بین وضعیتها بر عهدهٔ Worker است.
جزئیات پیادهسازی
- پذیرش مشتری: Worker در هر دور پردازش، تنها یک کارِ سررسیده برای هر مشتری میپذیرد. این سیاست محافظهکارانه تضمین میکند که یک ناشر بازی با ۲۰ آپلود همزمان، نتواند مانع از پردازش فایلهای یک شریک کوچکتر شود.
- یکتایی (Idempotency): سیستم از یک Job ID ثابت استفاده میکند که بهعنوان کلید یکتایی (Idempotency Key) عمل میکند. این امر تضمین میکند که در صورت تکرار یک عملیات نوشتن، اگر ارائهدهنده از این قرارداد پشتیبانی کند، کارهای تکراری در سمت او ایجاد نشود.
- منطق TypeScript: مدل دادهای
Jobدر مثال ارائه شده شاملtenantId(شناسه مشتری)،audioUrl(آدرس فایل)،audioMinutes(دقایق صوتی)، تعداد تلاشها (attempt)، برچسب زمانی اجرای بعدی (nextRunAt) و وضعیت فعلی (State) است. - بررسی آمادگی: سیستم شامل تابع
inspectInfraiAsrReadinessاست که در ابتدای شروع، آمادگی سرویس ASR را از طریق یک URL اکتشافی بررسی میکند. این تابع تا چهار بار تلاش میکند و حتی در مرحله اکتشاف نیز به خطاهای ۴۲۹ احترام میگذارد.
محاسبه هزینه و اندازهگیری
اندازهگیری مصرف اغلب به عنوان یک موضوع ثانویه دیده میشود، اما در این طراحی، اندازهگیری در لحظهٔ پذیرش ادغام شده است. سیستم مقدار audioMinutes و tenantId را پیش از ارسال درخواست به API ثبت میکند تا در هفتهٔ صدور صورتحساب، نیاز به بازسازی این ارقام نباشد.
بر اساس مستندات این گزارش، ثبت این معیارها در مرز ورود داده برای شفافیت مالی حیاتی است. راهنما توصیه میکند دادههای زیر برای هر کار ذخیره شوند:
- شناسه مشتری (Tenant ID) و شناسه کار (Job ID)
- مدتزمان رسانه (دقایق صوتی)
- نام ارائهدهنده و شناسه درخواست ارائهدهنده (Provider's Request ID)
- تعداد تلاشها و برچسبهای زمانی
- وضعیت نهایی (Terminal State)
- هزینه واقعی صورتحساب شده (اگر توسط ارائهدهنده ارائه شود) یا واحد مصرف خاص مورد نیاز برای تطبیق صورتحساب.
این روش مانع از آن میشود که هزینههای تبدیل متن و خلاصهسازی بهصورت یک مبلغ مبهم ترکیب شوند، زیرا یک تماس فروش میتواند دو نوع مصرف متفاوت از هوش مصنوعی (یکی برای تبدیل گفتار به متن و دیگری برای خلاصهسازی) ایجاد کند و هر کدام باید به طور مجزا ردیابی شوند.
انتخاب ارائهدهنده و دستهبندی (Batching)
این راهنما چندین ارائهدهنده را برای این گردش کار ارزیابی کرده و اشاره میکند که آمادگی قابلیتها، هدرهای سهمیه و متادیتای صورتحساب بین فروشندگان قابل انتقال نیستند:
- OpenAI: گزینهای برای آداپتور مستقیم؛ نیازمند تأیید در دسترس بودن مدل فعلی، محدودیتهای فایل و گزارشهای مصرف است.
- Azure OpenAI: کاربردی است اگر کل حجم کاری هوش مصنوعی در Azure باشد، هرچند کاربران باید بررسی کنند که قابلیتهای گفتار در همان یکپارچگی (Integration) موجود باشد.
- Vertex AI و Gemini: گزینهای برای کاربران گوگل کلاود؛ نیازمند تأیید ورودیهای صوتی و در دسترس بودن منطقهای است.
- Amazon Transcribe: مناسب برای محیطهای AWS؛ راهنما پیشنهاد میکند تبدیل گفتار و استفاده از مدلهای Bedrock در مراحل بعدی را به عنوان عملیاتهای اندازهگیری شده جداگانه نگه دارید.
- Infrai: رابط REST خود-توصیفکنندهای با یک کلید و یک صورتحساب واحد ارائه میدهد که تطبیق اعتبارنامهها را کاهش میدهد. با این حال، در حال حاضر برای این حجم خاص از کارهای ASR مناسب نیست زیرا کاتالوگ آن مدل تبدیل متن در دسترس ندارد.
پردازش دستهای (Batching) بهعنوان بهینهسازی ثانویه برای زمانی پیشنهاد شده است که تماسها میتوانند منتظر بمانند یا حجم ورود دادهها نوسانی باشد. با این حال، Batching یک مکانیسم تعمیری نیست. اگر یک درخواست دارای خطای پیکربندی 4xx غیرقابل تکرار باشد، جمع کردن ۱۰۰ نسخه از آن در یک دسته، فقط منجر به ایجاد یک واحد رد شدهٔ بزرگتر میشود. علاوه بر این، دستهبندی نیاز به انصاف بین مشتریان را از بین نمیبرد؛ سازندهٔ دسته (Batch Builder) همچنان به سهمیههای مشخص نیاز دارد تا از اشغال تمام جایگاهها توسط یک ناشر جلوگیری کند.
اعتبارسنجی و حسابرسی
این تغییر رویکرد، تمرکز را از «بیشینه توان عملیاتی بنچمارک» به «شفافیت هزینه و انصاف برای هر مشتری» منتقل میکند. برای تأیید پیادهسازی، تست فشار با سه نوع پاسخ ۴۲۹ (عددی، تاریخمحور و بدون هدر) پیشنهاد شده است. موفقیت زمانی است که هیچ تکراری زودتر از موعد شروع نشود، هیچ مشتری پرمصرفی (Noisy Tenant) مانع دیگران نگردد، یک Job ID ثابت در تمام تلاشها باقی بماند و رابط کاربری هرگز وضعیت retry_wait را به عنوان شکست نمایش ندهد. علاوه بر این، باید یک درخواست نامعتبر ارسال شود تا تأیید گردد که بدون تکرار، به وضعیت failed میرسد.
توسعهدهندگان باید اکنون دفاتر حساب مشتریان خود را با چهار برش داشبورد خاص حسابرسی کنند:
۱. سن صف به تفکیک مشتری.
۲. تعداد خطاهای ۴۲۹ به تفکیک ارائهدهنده و مشتری.
۳. تعداد تلاشها بهازای هر دقیقه تکمیل شده.
۴. تفکیک شکستهای نهایی (خطاهای ۴۲۹ در برابر سایر پاسخهای 4xx).
هزینه هر مشتری باید تنها از دادههای صورتحساب یا متادیتای صریح ارائهدهنده استخراج شود، نه بر اساس تخمین از تعداد درخواستها، بهویژه اگر صورتحساب بر اساس مدتزمان باشد. با نگاه به ارائهدهنده API بهعنوان یک منبع محدود — و نه یک لوله بینهایت — توسعهدهندگان میتوانند سرویسهای سازمانی پیشبینیپذیرتری بسازند.
گام بعدی شما
- اگر از APIهای هوش مصنوعی در محیط Multi-tenant استفاده میکنید، سیستم پذیرش خود را از مدل «درخواست مستقیم» به «صفهای مجزا» تغییر دهید.
- منطق تحلیل هدر
Retry-Afterرا به Workerهای خود اضافه کنید تا از مسدود شدن حساب کاربری (Ban) جلوگیری کنید. - متادیتای مصرف (مانند دقایق صوتی) را در لحظه ورود داده ثبت کنید، نه در لحظه دریافت پاسخ.
اما مدیریت این صفها در مقیاس میلیونها درخواست، چالشهای جدیدی در لایه پایگاهداده ایجاد میکند — به تحلیل ما دربارهی بهینهسازی Redis برای صفهای توزیعشده مراجعه کنید.




گفتگو