یک سیستم که با اطمینان اشتباه میکند، یک ریسک است، اما سیستمی که از حدس زدن امتناع میکند، یک دارایی است. در چهارمین بخش از سری «آیا میتوان جایگزینی برای LLMها ساخت» — پس از بررسی حافظه واقعی، خوداصلاحی و ذخیرهسازهای دانش — پروژه AuraSDK روشی را برای تولید خودکار تستهای ویژگی (Property Tests) در زبان Rust معرفی کرد که پیش از ثبت در دیسک، از یک فرآیند سختگیرانه رد-و-تأیید عبور میکنند.
تستهای نرمافزاری سنتی بر اساس توافقات پیشفرض هستند؛ یعنی اگر باگی باعث نقض یک ادعای از پیشنوشتشده نشود، شناسایی نمیشود. این وضعیت پارادوکسی ایجاد میکند که در آن یک مخزن کد (Repository) ممکن است در تستهای cargo سبز باشد، اما باگی در یکی از توابعش زنده مانده باشد. برای سیستمهای خودکار، هدف تنها اجرای تست نیست، بلکه ساخت «داوران» جدیدی است که بتوانند یک پیادهسازی درست را از یک پیادهسازی «ظاهراً درست اما غلط» تفکیک کنند.
طبق مستندات این پروژه، تولید بازیابیافزا (RAG) — که شبیه دانشآموزی است که قبل از جواب دادن، اول کتاب درسی را باز میکند و از آن نقل میآورد — در اینجا جای خود را به مشاهده مستقیم رفتار کد میدهد. همانطور که در تحلیلهای قبلی ما دربارهی امنیت مدلهای بازمتن اشاره کردیم، تکیه بر خروجیهای احتمالی بدون اعتبارسنجی سخت، منجر به توهمات فنی میشود. این چالش در ارزیابیهای گستردهتر نیز دیده میشود؛ برای مثال، تا حد زیادی خطاهای فنی سبب شکست مدلها در آزمونهای سخت کدنویسی شدهاند که نشان میدهد تکیه صرف بر احتمالات در محیطهای تولیدی ناکافاست.
مکانیزم داوران ابداعی
نوشتن یک ادعای ساده آسان است، اما خطرناکترین تست آن نیست که چیزی نمییابد، بلکه تستی است که با اطمینان روی کد درست، خطا میگیرد. برای مثال، یک سیستم ممکن است چندین اجرا را مشاهده کند و نتیجه بگیرد که «هرگاه خروجی خالی نباشد، طول آن همیشه حداقل ۳ است». این ممکن است تنها یک مرز اتفاقی در نمونههای مشاهدهشده باشد و نه یک قانون ذاتی در نرمافزار. برای جلوگیری از این مورد، AuraSDK یک فرآیند پنجمرحلهای محدودشده را اجرا میکند:
- مشاهده اجرا (Execution Observation): سیستم اجرای زنده کد را میبیند تا ویژگیهای سادهای را پیشنهاد دهد.
- حمله فعال (Active Attack): سیستم سعی میکند ویژگی کاندید را روی کد درست بشکند تا مطمئن شود تعمیم نادرست نیست و به یک نتیجهگیری عجولانه منجر نشده است.
- نشانه گذاری تعمیم (Scarring the Generalization): اگر ویژگی غلط باشد، سیستم آن را رد کرده یا تعمیم را «زخمی» میکند تا در آینده اتهام نادرست نزند و از تکرار خطای مشابه جلوگیری کند.
- تست جهش (Mutation Testing): بازماندگان در برابر جهشهای نگه داشته شده (held-out mutations) آزمایش میشوند تا تأیید شود واقعاً قادر به شناسایی باگها هستند.
- یکپارچهسازی با Cargo: ویژگیهای تأییدشده به توابع
#[test]در فایلtests/judges.rsتبدیل شده و با ابزار استاندارد cargo test اجرا میشوند.
این یک «داور ابداعی» است؛ نه صرفاً متنی که یک مدل در قالب متن آزاد تولید کرده، بلکه داوری محدود شده که از دل نتایج بیرون آمده و مجبور شده برای بقا، از سد رد-و-تأیید عبور کند. حکم نهایی نه توسط یک Wrapper پایتونی یا یک LLM، بلکه توسط کامپایلر Rust و ابزار cargo test صادر میشود. این رویکرد یادآور تلاش برای جایگزینی گیتهای مکانیکی با مهندسی پرامپت است تا از طریق ساختارهای سختگیرانه، نرخ خطای عاملهای هوشمند کاهش یابد.
آزمون گیتها و نتایج
به گزارش تیم توسعه، این آزمایش برای اثبات مکانیزم از پنج گیت خاص عبور کرد: ابتدا یک دنیای پایتونی مصنوعی، سپس پلی به cargo test واقعی، مقایسه هفت پورت از توابع Aura با یک استخراجکننده استاتیک (static miner)، رندر یک داور ویژگی در Rust و در نهایت گیت کد-دنیا روی بدنه توابع واقعی Aura.
دو نتیجه اولیه بسیار افشاگر بود زیرا از پیشفرضها فاصله داشت. اول اینکه، یک گیت اولیه در بخش «Real Cargo gate» با وجود نرخ کشت (Kill rate) ۱.۰ و نرخ خطای (False-fire) ۰.۰، در نهایت به عنوان NOT_PROVEN علامت زده شد، زیرا قانون آن بیش از حد بدیهی و تکراری بود. این موضوع منجر به افزودن یک جهش به نام abs_ratio شد که توانست تستهای ضعیف Cargo و داوران مرزی را پاس کند اما در برابر ویژگی حسابی matches_division شکست بخورد.
دوم اینکه، پژوهشگران دریافتند انتقال صرف نتایج از پایتون به Rust نوعی خودفریبی است. در نسخهی نهایی، هر ویژگی باید دقیقاً به عنوان یک #[test] واقعی رندر شود تا دقیقاً همان نتیجهی cargo test هم برای گروه متد و هم برای گروه کنترل استفاده شود و هیچ اثر جانبی یا تفاوت محیطی وجود نداشته باشد.
واژگان و گیت نهایی
اسکریپت نهایی، یعنی scripts/run_invented_judge_cargo_property_gate.py روی ۶ تابع واقعی از AuraSDK اجرا شد: filter_selected ،disjoint ،accuracy_per_mille ،پروجکشن شمارش در prune_deaths ،نسخه بیتی presence_jaccard_rank_key و has_duplicates.
در این مرحله، ۱۲ جهش به سبک cargo-mutants ایجاد شد. چهار مورد از آنها به عنوان یک بررسی سلامت (sanity check) توسط تستهای پایه Cargo کشته شدند. هشت مورد باقیمانده که از مجموعه تستهای ضعیف جان به در بردند، به اهداف داوران جدید تبدیل شدند. برای اطمینان از اینکه سیستم به دنبال کشف ریاضیات تصادفی و دلخواه نمیرود، از یک واژگان محدود و قابل حسابرسی از توابع اولیه ویژگی استفاده شد:
- محدودههای
>=و<= - طول اسکالر (Scalar length)
- روابط زیرمجموعه (Subset relationships)
- خروجی خالی در برابر ورودی خالی
- تقارن (Symmetry)
- یکنواختی (Monotonicity)
- ناورداهای جایگشتی (Permutation invariants)
نتیجه در مرزهای شکننده
در شرایط «مرزهای پایدار» (Stable bounds)، جایی که ورودیهای آینده در محدوده اجراهای قبلی باقی میمانند، هر دو روش داور ابداعی و استخراجکننده استاتیک عالی عمل کردند (نرخ کشت ۱.۰۰، نرخ خطای ۰.۰۰ و خالص +۱.۰۰). اما ارزش واقعی در رژیم «مرزهای شکننده» ظاهر شد؛ جایی که موارد درست در آینده، از مرزهای اتفاقیِ مشاهدهشده در آثار قبلی عبور میکنند:
- داور ابداعی: نرخ کشت ۰.۷۵، نرخ خطای ۰.۰۰ (خالص +۰.۷۵).
- استخراجکننده استاتیک: نرخ کشت ۱.۰۰، نرخ خطای ۰.۵۰ (خالص -۰.۵۰).
در نگاه اول استخراجکننده استاتیک بهتر به نظر میرسد چون همه جهشها را کشت، اما در ۵۰٪ از موارد نگه داشته شده، به کد درست اتهام زد (False-fire). داور ابداعی یک جهش را از دست داد چون مرز کاندیدش اتفاقی بود؛ در اینجا فرآیند، آن تعمیم را «زخمی» کرد و بهجای صادر کردن یک حکم غلط، پاسخ «امتناع» (ABSTAIN) داد.
تحلیل: ارزش امتناع
این تغییر، هدف را از «به حداکثر رساندن نرخ کشت» به «به حداقل رساندن فریب» تغییر میدهد. برای توسعهدهندگان، تستی که باگ را مییابد مفید است، اما تستی که بهصورت متناوب روی کد درست خطا میدهد، یک قاتل بهرهوری است. AuraSDK با اجبار داور به کسب حق نوشتن (از طریق بقا در برابر رد-و-تأیید)، دقت (Precision) را بر بازیابی (Recall) اولویت میدهد. مزیت کلیدی در «بیشتر کشتن» نیست، بلکه در امتناع از دروغ گفتن است، زمانی که شواهد کافی برای توجیه یک تعمیم وجود ندارد.
این نتایج ثابت میکند که یک سیستم میتواند از یک فرمول چهاربخشی استفاده کند: نتایج (بهجای خواندن استاتیک)، مثالهای نقض (بهجای اولین فرضیه محتمل)، امتناع از قضاوت تحت نظارت شدید و در نهایت اجرای مستقل در زنجیره ابزار استاندارد پروژه. بدون بخش آخر، بسیار ساده است که بهجای سنجش کیفیت تست، بهطور تصادفی کیفیت یک ارزیاب (Evaluator) را اندازه بگیرید.
محدودیتها و مقیاسبندی
این پروژه مرزهای شفافی را حفظ کرده است. جهشها بهصورت دستی و به سبک cargo-mutants نوشته شدند و نه توسط خود ابزار تولید گشتند. مولدهای ورودی-کاوشگر (Probe-input) بهصورت دستی مشخص شدند، مقیاس آزمایش به ۶ تابع و ۸ جهش محدود بود و واژگان ویژگیها از پیش تعریف شده بودند. این یک گیت کد-دنیا است و هنوز گواهی بر کل یک مخزن کد یا مشخصات دلخواه نیست.
برای حل کامل تستهای خودکار، این گامهای دستی باید با ابزارهای مستقل جایگزین شوند یا در یک حلقه کامل توسعه ادغام گردند. با این حال، این رویکرد بسیار قویتر از «تکمیل خودکار ادعاها» است؛ سیستم صرفاً متن تست نمینویسد، بلکه با شکست دادن تلاشهای رد-کننده بر روی کد درست، حق نوشتن آن را به دست میآورد.
منتظر مرحله بعدی این سری باشید که بررسی خواهد کرد آیا این حلقهها میتوانند یک ردپای (Trace) مفید را در طول زمان حفظ کنند، در حالی که سیستم از نگاه کردن به آینده منع شده است.
گام بعدی شما
- بررسی مستندات cargo-mutants برای درک نحوه ایجاد جهش در کدهای Rust.
- مطالعه مفاهیم Property-Based Testing برای جایگزینی تستهای مقداری (Unit Tests) با تستهای ویژگی.
- تحلیل اثر امتناع از قضاوت در سیستمهای Agentic برای کاهش نرخ توهم.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو