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

گزارش فنی: شناسایی باگ‌های خاموش در لایه‌های پیکربندی مدل‌ها

·۱۵ شهریور ۱۴۰۵۶ دقیقه مطالعه
تبلیغ‌شده اما پیاده‌نشده: تنظیماتی که همه‌جا هستند جز در مسیر اجرای کد
تبلیغ‌شده اما پیاده‌نشده: تنظیماتی که همه‌جا هستند جز در مسیر اجرای کد
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

شناسایی یک کلاس جدید از باگ‌های «سیم‌کشی نشده» (Unwired) که در آن تضاد میان UI و کد، به‌جای ایجاد خطا، منجر به اجرای خاموشِ پیش‌فرض‌ها می‌شود.

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

این الگو به عنوان یک مشکل سیستمی در اکوسیستم Agent-CLI ظاهر شده است. در اولین هفته از سپتامبر ۲۰۲۶، دو پایگاه کد (Codebase) مجزا، بیماری یکسانی را آشکار کردند: تنظیماتی که پیکربندی‌شده به نظر می‌رسند اما در مسیر اجرا به‌طور خاموش نادیده گرفته می‌شوند. این وضعیت «معماهای تولیدی» (Production Mysteries) ایجاد می‌کند؛ جایی که مدل‌های گران‌قیمت استفاده می‌شوند یا پرامپت‌های حیاتی نادیده گرفته می‌شوند، بدون اینکه حتی یک خطای ساده در لاگ‌ها ثبت شود.

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

تله‌ی پیش‌فرض‌های خاموش

در مورد clio-coder — یک عامل کدنویس برای توسعه‌دهندگان نرم‌افزارهای علمی و HPC — دو تنظیم مربوط به فشرده‌سازی متن (Compaction) شامل context.compaction.model و context.compaction.systemPrompt به‌طور کامل مستند شده و در رابط کاربری تنظیمات حضور داشتند. این تنظیمات در سه مکان مشخص تبلیغ شده بودند: رابط کاربری تنظیمات، اسکیمای تنظیمات در مسیر src/core/config.ts:721-722 و مستندات در مسیر docs/guide/configuration-reference.md:32-33.

با این حال، یک ممیزی فنی (Issue #324) فاش کرد که ارکستراتور سیستم هرگز این کلیدها را نمی‌خواند. مسیر اجرا دو شکست حیاتی را نشان داد:

اول اینکه تابع resolveCompactionModel در مسیر src/entry/orchestrator.ts:533-548 تنها مقادیر settings.chat.target و settings.chat.model را می‌خواند و context.compaction.model را به‌طور کامل نادیده می‌گرفت. دوم اینکه تابع runCompactionFlow در مسیر src/entry/orchestrator.ts:646-690 تابع compact را فراخوانی می‌کرد اما هرگز آرگومان systemPrompt را به آن پاس نمی‌داد، با وجود اینکه خودِ تابع در مسیر src/domains/session/compaction/compact.ts:103 پذیرای این آرگومان بود.

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

راه‌حل این مشکل (Commit 8e70da27 که در نسخه v0.4.3 تقریباً ۹۰ دقیقه پس از گزارش مشکل منتشر شد) یک اصل طراحی هسته‌ای را تثبیت کرد: «یک مسیر مدل صریح اما نامعتبر، یا یک فایل پرامپت غیرقابل خواندن، باید به‌طور مشهود شکست بخورد و هرگز نباید به‌طور خاموش به حالت پیش‌فرض بازگردد.»

جایگزینی مخرب (Destructive Override)

نسخه ظریف‌تری از این شکست در openai/codex (Issue #42918) مشاهده شد. در اینجا تنظیمات خوانده می‌شدند، اما مکانیزم خواندن آن‌ها مخرب بود. وقتی کاربر یک مقدار تک‌مقداری (Scalar Override) برای بودجه توکن ارائه می‌داد، سیستم به‌جای ادغام (Merge) آن با مقادیر پیش‌فرض، کل شیء پیکربندی را جایگزین می‌کرد.

این موضوع از طریق یک تست A/B دو مرحله‌ای اثبات شد. در اجرای اول، با استفاده از پیش‌فرض‌های مدل برای gpt-5.6-luna و فعال بودن experimental_mode=true تگ <context_window_guidance> حضور داشت. در اجرای دوم، با افزودن تنها یک مقدار جایگزین یعنی features.token_budget.reminder_threshold_tokens=14000 باعث شد تگ <context_window_guidance> به‌طور کامل ناپدید شود.

مکانیزم این خطا (یافته شده در rust-v0.153.4) این است که تابع has_explicit_settings برای هر کلید بودجه توکنی به‌جز دو مورد خاص، مقدار true برمی‌گرداند. این امر باعث می‌شود ساختار TurnContext مقدار use_model_token_budget_defaults = false را تنظیم کند. در نتیجه، resolve_token_budget شیء پیکربندی شده توسط کاربر را مستقیماً برمی‌گرداند بدون اینکه فیلدهای مشخص‌نشده را ادغام کند. از آنجایی که TokenBudgetConfig::default پرامپت جایگزین، بافر جایگزین و پیام راهنما را خالی می‌گذارد، کاربر به‌طور تصادفی با تغییر یک تنظیم زمانی، سه پیش‌فرض عملیاتی حیاتی را حذف کرد.

علاوه بر این، یکی از تحلیل‌گران (84dnnvbdvp-debug) اشاره کرد که چون این مقدار Boolean تنها یک بار در هنگام ساخت TurnContext ثبت می‌شود، اگر مدل در مراحل بعدی تغییر کند، بودجه دوباره بر اساس مدل جدید محاسبه می‌شود اما مقدار ثابت false همچنان مانع از اعمال پیش‌فرض‌های مدل جدید می‌شود.

چهار شکل شکست پیکربندی

تحلیل این حوادث و شکاف‌های تله‌متری مرتبط، چهار الگوی متمایز از این کلاس شکست را آشکار می‌کند:

  • تبلیغ‌شده اما هرگز خوانده‌نشده: کلید در اسکیما، مستندات و UI وجود دارد اما در مسیر اجرا غایب است. مثال: مورد clio-coder#324.
  • جایگزینی که پیش‌فرض‌ها را ریست می‌کند: تنظیم یک کلید خاص، تمام کلیدهای هم‌رده در یک شیء تو در تو را حذف می‌کند. مثال: مورد openai/codex#42918.
  • توصیه در لباس آستانه (Threshold): کلید وجود دارد و اجرا می‌شود، اما معنای واقعی آن با نامش متفاوت است. در یک مورد (claude-code#91188)، یک مقدار قابل تنظیم به‌جای تغییر آستانه‌ی اجرا، متن توصیه را جابه‌جا می‌کرد و واحد اندازه‌گیری آن در یک مسیر UTF-16 و در مسیری دیگر بر اساس بایت بود.
  • جمع‌آوری‌شده اما هرگز ارتقا نیافته: داده‌ها در یک Struct یا فیلد تله‌متری پر می‌شوند اما هیچ مسیر کدی هرگز آن‌ها را نمایش نمی‌دهد. مثال: تله‌متری استخراج OpenViking که در آن یک شمارنده خطا در errors[] وجود داشت اما هرگز به متریک‌های نهایی تبدیل نشد.

هزینه شکست‌های خاموش

این باگ‌ها به‌ویژه فریبنده هستند زیرا از سیستم‌های تشخیص استاندارد عبور می‌کنند. یک گزینه حذف‌شده قابل کشف است چون کاربر نمی‌تواند آن را پیدا کند. اما یک گزینه «سیم‌کشی نشده»، بررسی اسکیما را پاس می‌کند، در مستندات رندر می‌شود و در UI ذخیره می‌گردد.

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

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

چک‌لیست تشخیص برای توسعه‌دهندگان

برای یافتن این شکاف‌ها در یک استک فنی، گزارش پیشنهادی یک ممیزی ۱۰ دقیقه‌ای را ارائه می‌دهد:

۱. جست‌وجوی (Grep) مسیر اجرا: کلید را در منطق کد جست‌وجو کنید، نه فقط در پارسر تنظیمات. اگر تنظیمی در اسکیما، مستندات و UI هست اما تنها جایی که به آن اشاره شده پارسر است، آن تنظیم مرده است.
۲. قرار دادن مقدار نگهبان (Sentinel): یک مقدار مضحک اما معتبر ست کنید؛ مثلاً نام مدلی که قطعاً پیش‌فرض نیست یا یک فایل پرامپت حاوی یک کلمه منحصر‌به‌فرد. اگر رفتار سیستم با حالت پیش‌فرض دقیقاً یکسان (Byte-identical) باقی ماند، کلید سیم‌کشی نشده است.
۳. بررسی معناشناسی جایگزینی (Override Semantics): برای هر شیء پیکربندی تو در تو، بررسی کنید که آیا تنظیم یک فیلد با پیش‌فرض‌ها ادغام می‌شود یا کل شیء را جایگزین می‌کند. الگوی «جایگزین-اگر-موجود-بود» جایی است که باگ‌های مشابه codex#42918 پنهان می‌شوند.
۴. تأیید تله‌متری: بپرسید آیا یک فیلد پر شده هرگز در لاگ، متریک یا پرامپت ظاهر می‌شود؟ فیلدی که پر می‌شود اما هرگز خوانده نمی‌شود، صرفاً یک شکاف تله‌متری است که لباس تنظیمات پوشیده است.
۵. افزودن شمارنده اجرا (Fired-counter): هنگام سیم‌کشی یک گزینه واقعی، اولین باری که مقدار آن به مسیر اجرا می‌رسد را لاگ کنید. این ارزان‌ترین راه برای اثبات زنده بودن یک گزینه است.

این کلاس از باگ‌ها نشان‌دهنده یک شکاف رو به رشد در ابزارهای هوش مصنوعی است: در حال حاضر هیچ Linter یا مجموعه تست سیستماتیکی وجود ندارد که تأیید کند یک گزینه پیکربندی مستند، واقعاً به محل فراخوانی (Call site) خود می‌رسد.

گام بعدی شما

  • ممیزی مسیر اجرا: اگر توسعه‌دهنده هستید، کلیدهای تنظیمات را نه فقط در پارسر، بلکه در منطق اصلی کد جست‌وجو کنید.
  • استفاده از مقادیر نگهبان (Sentinel): مقادیر غیرمعمول اما معتبر را ست کنید؛ اگر رفتار مدل با حالت پیش‌فرض هیچ تفاوتی نداشت، یعنی تنظیمات شما سیم‌کشی نشده است.
  • بررسی ادغام تنظیمات: مطمئن شوید تغییر یک فیلد در اشیاء تو در تو، باعث حذف سایر مقادیر پیش‌فرض نمی‌شود.

اما این نقص‌ها تنها بخشی از چالش‌های زیرساختی است؛ برای درک اینکه چگونه مدیریت حافظه در مدل‌های جدید این هزینه‌ها را تغییر می‌دهد، به تحلیل ما درباره‌ی KV Cache مراجعه کنید.

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

این موضوع اعتبار فنی ابزارهای AI را به چالش می‌کشد و نشان می‌دهد که اعتماد به رابط کاربری در سیستم‌های پیچیده خطرناک است. بر اساس تجربه مهندسی، نبودِ تست‌های اتوماتیک برای تطبیق مستندات با کد، ریسک عملیاتی را افزایش می‌دهد.

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

برای توسعه‌دهندگان ایرانی که از ابزارهای Open-source برای ساخت عامل‌های محلی استفاده می‌کنند، این هشدار به معنای ضرورت ممیزی دستی کدهاست و نباید صرفاً به مستندات ابزارهای خارجی اعتماد کنند.

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

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

منابع

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

گفتگو

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

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

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

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

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

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

دات‌هوش

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

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