پرش به محتوای اصلی
پرش به محتوای مقاله

پاسخ‌های معتبر JSON باعث فساد خاموش داده‌ها در خط لوله تولید شد

·۳۱ مرداد ۱۴۰۵۶ دقیقه مطالعه۲ بازدید
راهنما
شناسه مشتری اختراع شده بود، اما JSON معتبر بود.
شناسه مشتری اختراع شده بود، اما JSON معتبر بود.
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

برخلاف بحث‌های کلی درباره توهم، این گزارش یک متدولوژی عملی برای تبدیل «فساد خاموش» به «خطای مرئی» از طریق لایه‌بندی اعتبارسنجی و حلقه بازخورد (Feedback Loop) ارائه می‌دهد.

تصور کنید در ۲۱ اوت ۲۰۲۶ یک گزارش تولیدی دریافت می‌کنید که ۱۱ تراکنش را به شناسه‌های مشتریانی متصل کرده که اصلاً در پایگاه داده وجود ندارند. هیچ خطایی صادر نشده، هیچ وب‌هوکی شکست نخورده و تمام لاگ‌ها وضعیت «موفق» را نشان می‌دهند. این خط لوله که روی سرورهای MonkeyCode اجرا می‌شد، دقیقاً همان کاری را کرد که به او دستور داده شده بود: تجزیه JSON، اعتبارسنجی ساختار و ثبت رکورد.

این شکست در سیستمی رخ داد که برای استخراج جزئیات تراکنش از ایمیل‌های پشتیبانی با استفاده از یک مدل رایگان از طریق درگاه MonkeyCode طراحی شده بود. وظیفه اصلی مدل این بود که خروجی را در قالب JSON ساختاریافته برگرداند. چون ظاهر خروجی بی‌نقص بود، خطا تا زمانی که یک کوئری دستی SQL رکوردهای «یتیم» را شناس کرد، نامرئی ماند. لازم به ذکر است که این مقاله به عنوان بخشی از فعالیت‌های ترویجی محصولات MonkeyCode تهیه شده است. شکست توصیف شده یک باگ محصول نیست، بلکه یک شکاف طراحی در خط لوله است که با هر مدلی که JSON برمی‌گرداند رخ می‌دهد.

این وضعیت شبیه نگهبانی است که فقط اندازه و رنگ کارت شناسایی را چک می‌کند، اما هرگز بررسی نمی‌کند که آیا نام روی کارت در لیست کارکنان هست یا خیر. سیستم «شکل» داده را چک کرد اما «حقیقت» آن را نادیده گرفت. همان‌طور که در تحلیل‌های قبلی ما درباره‌ی توهمات مدل‌های زبانی اشاره کردیم، خطرناک‌ترین خطاها آن‌هایی هستند که شبیه موفقیت به نظر می‌رسند. این موضوع یادآور بررسی‌های ما درباره وب‌هوک‌های پرداخت است که در آن AI باعث پنهان شدن خطاهای بحرانی در محیط تولید شد.

کالبدشکافی یک شکست خاموش

توسعه‌دهنده با استفاده از یک کوئری LEFT JOIN متوجه وجود رکوردهای یتیم شد: SELECT t.transaction_id, t.customer_id, c.name FROM transactions t LEFT JOIN customers c ON c.id = t.customer_id WHERE c.id IS NULL;. ۱۱ ردیف بازگشت که همگی شناسه‌هایی مثل "CUST-48291" داشتند؛ شناسه‌هایی که کاملاً با فرمت مورد انتظار مطابقت داشتند.

بر اساس مستندات فنی این پروژه، توسعه‌دهنده پیش از یافتن علت ریشه‌ای، سه فرضیه اشتباه را دنبال کرد:

  1. کوئری گزارش: اجرای مجدد کوئری روی یک تراکنش که می‌دانست سالم است، ثابت کرد که SQL درست است.
  2. تداخل زمانی (Race Conditions): برچسب‌های زمانی نشان دادند که شناسه‌های یتیم ساعت‌ها بعد از آخرین وارد کردن (Import) مشتریان ثبت شده بودند، که این موضوع تأخیر در همگام‌سازی را رد می‌کرد.
  3. بریدگی متن (Truncation): بررسی طول پاسخ‌ها تایید کرد که تمام خروجی‌های مدل کامل بوده‌اند و هیچ بخشی از JSON قطع نشده بود.

در نهایت، چاپ خروجی خام مدل حقیقت را فاش کرد. JSON معتبر بود، انواع داده‌ها درست بود و فرمت صحیح بود، اما شناسه مشتری کاملاً ساختگی بود. علت ریشه‌ای، دستوری در پرامپت بود که به مدل می‌گفت: «اگر مشتری بدیهی به نظر می‌رسد، او را استنتاج کن».

وقتی ایمیل فاقد شناسه واضح بود، مدل با اعتمادبه‌نفس یک شناسه اختراع کرد. این بدترین نوع شکست مدل است زیرا دقیقاً شبیه موفقیت به نظر می‌رسد. سیستم به دلیل سه شکاف طراحی خاص سکوت کرد:

  • کوری معنایی: تجزیه‌کننده فقط فرمت (با استفاده از Regex ^CUST-\d{4,6}) را چک می‌کرد، نه وجود واقعی شناسه در دیتابیس را.
  • تایید زودهنگام: سیستم بلافاصله بعد از تجزیه، پیام را تایید (Acknowledge) می‌کرد، به این معنی که رویداد پیش از هرگونه بررسی ارجاعی از صف حذف می‌شد.
  • سستی پایگاه داده: جدول تراکنش‌ها فاقد محدودیت کلید خارجی (Foreign Key) روی ستون customer_id بود و اجازه ثبت رکوردهای «شبح» را می‌داد.

پیاده‌سازی دفاع سه لایه

برای رفع این مشکل، یک سلسله‌مراتب اعتبارسنجی طراحی شد تا خطاها در ارزان‌ترین مرحله ممکن شناسایی شوند.

لایه ۱: اعتبارسنجی طرح (Schema Validation)
سیستم اکنون با استفاده از jsonschema قوانین سخت‌گیرانه‌ای را اجرا می‌کند. طرح TRANSACTION_SCHEMA اکنون نیازمند transaction_id (با الگوی ^txn_[a-z0-9]+)، customer_id (با الگوی ^CUST-[0-9]{4,6})، amount (حداقل ۰)، currency (دقیقاً ۳ کاراکتر) و یک برچسب زمانی با فرمت date-time است. برای جلوگیری از تغییرات ناگهانی در ساختار خروجی مدل‌ها، می‌توان از رویکردهایی مشابه گیت‌های نوع در C++ برای مهار Drift در JSON Schema استفاده کرد.

لایه ۲: بررسی ارجاعی (Referential Check)
سیستم اکنون پیش از ثبت رکورد، تایید می‌کند که customer_id واقعاً در جدول مشتریان وجود دارد. اگر شناسه در مجموعه known_ids نباشد، رکورد رد می‌شود.

لایه ۳: تلاش مجدد با بازخورد
اگر بررسی ارجاعی شکست بخورد، سیستم خطای اعتبارسنجی خاص را به مدل برمی‌گرداند. متن بازخورد صراحتاً می‌گوید: «JSON قبلی شکست خورد: [خطا]. اگر نمی‌توانی شناسه واقعی را در ایمیل پیدا کنی، همان شیء را با مقدار null برای customer_id برگردان».

سازوکار حلقه بازخورد

این منطق تلاش مجدد برای جلوگیری از «طوفان تلاش مجدد» (Retry Storms) و اتمام سهمیه نرخ (Rate Limit) در نسخه‌های رایگان، به یک بار محدود شده است. تجربه یک حادثه قبلی با طوفان تلاش مجدد به توسعه‌دهنده آموخت که حلقه را به جای سه بار، روی یک بار محدود کند. این چالش با مشکلات رایج در فراخوانی‌های API مدل‌های زبانی که با وجود پاسخ‌های خالی، وضعیت 200 برمی‌گردانند همسو است و نیاز به استراتژی‌های پایداری دقیق‌تری دارد.

اگر تلاش دوم شکست بخورد، پاسخ خام به یک صف پیام‌های مرده (Dead-letter Queue) در حافظه بادوام فرستاده می‌شود. نکته حیاتی این است که پیام اصلی تا زمانی که داده‌ها به عنوان «صحیح» تایید نشوند، تایید (Ack) نمی‌شوند. تایید زودهنگام یعنی از دست دادن رویداد؛ با تاخیر در تایید، سیستم تضمین می‌کند هیچ داده‌ای در فرآیند اعتبارسنجی گم نشود.

ماتریس مدیریت خطا

توسعه‌دهنده از یک جدول تصمیم برای تعیین مقصد هر شکست استفاده می‌کند:

  • شکست در تجزیه: JSON نامعتبر یا بریده شده، یک بار تلاش مجدد می‌کند و سپس به صف پیام‌های مرده می‌رود.
  • شکست در طرح: فیلدهای گم‌شده یا انواع غلط، یک بار با بازخورد تلاش می‌کنند و سپس به صف پیام‌های مرده می‌روند.
  • شکست در ارجاع: شناسه‌های معتبر از نظر فرمت اما ناشناخته، یک بار با بازخورد تلاش می‌کنند و سپس به صف پیام‌های مرده می‌روند.
  • شکست در ثبت: نقض محدودیت‌های دیتابیس باعث می‌شود پیام بدون تایید، برای بررسی دستی پارک شود.

این رویکرد، فساد خاموش را به یک شکاف مرئی تبدیل کرد. در هفته پس از اصلاح، همان شناسه‌های ساختگی دوباره ظاهر شدند، اما حلقه تلاش مجدد آن‌ها را به null تبدیل کرد و رکوردها با ایمیل خام برای بررسی انسانی ذخیره شدند.

محدودیت‌ها و موازنه ها

این سیستم یک راهکار جهانی نیست. تلاش مجدد با بازخورد، هزینه استنتاج (Inference) — لحظه‌ای که مدل واقعاً جواب تولید می‌کند، شبیه خودِ آشپزی نه دوره آموزش آشپز — را افزایش می‌دهد و می‌تواند باعث برخورد با محدودیت‌های نرخ در طرح‌های رایگان شود. همچنین اگر مدل غیرقطعی باشد و حلقه بازخورد همگرا نشود، به جای تلاش مجدد، صف بررسی انسانی لازم است.

علاوه بر این، اگر مشتریان و تراکنش‌ها در یک دسته (Batch) ایجاد شوند، بررسی ارجاعی باید بعد از تکمیل کل دسته اجرا شود، نه به صورت رکورد به رکورد. برای کاربردهایی که شناسه‌های غلط را تحمل می‌کنند، این لایه‌ها زیاده‌روی است؛ هدف باید افزودن ارزان‌ترین چکی باشد که شکست مشاهده‌شده را می‌گیرد.

برای توسعه‌دهندگان، این یعنی «معتبر بودن فرمت» جایگزینی برای «صحیح بودن» نیست. شکاف میان یک رشته JSON معتبر و یک رکورد صادقانه در دیتابیس، جایی است که فساد خاموش زندگی می‌کند. خطرناک‌ترین شکست‌های مدل، آن‌هایی هستند که دقیقاً شبیه موفقیت به نظر می‌رسند.

اگر در حال حاضر پیام‌ها را پیش از تایید معنایی داده‌ها تایید می‌کنید، احتمالاً در حال از دست دادن رویدادها یا ذخیره ارواح هستید. راه حل این است که بررسی را به همان لایه‌ای منتقل کنید که داده‌ها در آن نوشته می‌شوند.

گام بعدی شما

  • تمام خط لوله‌هایی که از خروجی JSON مدل‌ها استفاده می‌کنند را برای «صحت معنایی» (Semantic Correctness) بازبینی کنید.
  • محدودیت‌های کلید خارجی (Foreign Key) را در دیتابیس‌های تولیدی فعال کنید تا از ورود داده‌های یتیم جلوگیری شود.
  • استراتژی تایید پیام‌ها (Ack) را تغییر دهید تا تنها پس از اعتبارسنجی کامل داده‌ها رخ دهد.

اما داستان مدیریت خطاهای پیچیده‌تر در سیستم‌های عامل‌محور حتی چالش‌برانگیزتر است — به تحلیل ما درباره‌ی معماری Agentic Workflows مراجعه کنید.

چرا این موضوع مهم است؟

این موضوع بر اساس تجربه عملی نشان می‌دهد که تکیه بر JSON Mode یا ابزارهای مشابه برای تضمین صحت داده‌ها کافی نیست. عدم پیاده‌سازی لایه‌های بررسی ارجاعی می‌تواند منجر به تخریب تدریجی و نامرئی پایگاه داده‌های تجاری شود.

تأثیر برای ایران

برای توسعه‌دهندگان ایرانی که از مدل‌های رایگان یا APIهای محدود استفاده می‌کنند، پیاده‌سازی لایه بررسی ارجاعی در سمت سرور، تنها راه مقابله با توهمات مدل‌ها بدون افزایش هزینه است.

·نگاه ما
تحریریه دات‌هوش

اعتماد به خروجی‌های ساختاریافته مدل‌ها یکی از بزرگ‌ترین تله‌های فعلی در مهندسی نرم‌افزار است. این حادثه ثابت می‌کند که در سیستم‌های مبتنی بر هوش مصنوعی، اعتبارسنجی باید از لایه سینتکس (ساختار) به لایه سمانتیک (معنا) منتقل شود. به نظر ما، توسعه‌دهندگان باید فرض کنند که مدل‌ها در صورت نبود داده، به جای اعلام ناتوانی، به صورت پیش‌فرض «دروغ‌های ساختاریافته» می‌گویند.

منابع

این گزارش با خط‌لولهٔ خودکار دات‌هوش از منابع معتبر جهانی تدوین و زیر نظر تحریریه منتشر شده است. روش کار ما

گفتگو

پنج‌شنبه‌های هوش‌محور

بسته‌ی هفتگی دات‌هوش

۵ خبر، ۲ ابزار، ۱ پرامپت در هر شماره. به‌زودی راه‌اندازی می‌شود — هر پنج‌شنبه صبح.

خبر کلیدی
ابزار کاربردی
پرامپت حرفه‌ای
تحلیل پژوهش
به‌زودی
زاویه‌ی ایرانی
به‌زودی
تمرین این هفته
به‌زودی

راهنماهای دات‌هوش

راهنماهای کاربردیِ دات‌هوش برای کار با هوش مصنوعی — از همین‌جا شروع کنید:

دات‌هوش

راهنمای فارسی هوش مصنوعی — با نگاه به ایران

اخبار روزانه، معرفی ابزارها و مدل‌ها، و آموزشِ کار با هوش مصنوعی؛ همیشه با این پرسش که از ایران چه چیزی کار می‌کند و چه چیزی نه.