دو وظیفه که شبیه یکی به نظر میرسند
یک agent که عمل میکند و یک agent که آن عمل را نمره میدهد، اغلب از همان checkpoint، همان prompt scaffold و همان serving stack ساخته میشوند. این راحت است، و پیشفرض اشتباهی است. یک مدل تصمیم و یک مدل شواهد مجموعههای نیازمندی متفاوتی دارند، و رفتار کردن با آنها بهعنوان یک مصنوع واحد، حالتهای شکستشان را به شکلهایی به هم گره میزند که بیسروصدا ارزیابی را بیاعتبار میکند.
یک مدل تصمیم برای کیفیت عمل تحت یک policy بهینه میشود: با گرفتن یک state، فراخوانی ابزار، پیام یا گام بعدی برنامه را تولید کند که هدف را در بودجههای latency و هزینه پیش ببرد. یک مدل شواهد برای calibration، پایداری و مقاومت در برابر framing بهینه میشود. باید داوری تولید کند که وقتی عبارتبندی کنشگر تغییر میکند ثابت بماند، و وقتی مطمئن نیست صادقانه تنزل کند.
اینها دو اندازه از یک چیز نیستند. دو مشخصات جداگانهاند.
مدلهای تصمیم و مدلهای شواهد مجموعههای نیازمندی متفاوتی دارند
یک مدل تصمیم با آنچه در پاییندست اتفاق میافتد قضاوت میشود. آیا تیکت بسته شد، آیا تست پاس شد، آیا retrieval سند درست را برگرداند. خواص مفیدش throughput، قابلیت اطمینان در استفاده از ابزار، و توانایی بازیابی از یک گام میانی بد است. latency مهم است چون مدل داخل یک حلقه قرار دارد. یک مدل تصمیم کند، مدل تصمیم بدتری است حتی اگر استدلالش بهتر باشد، چون حلقه بودجه دارد.
یک مدل شواهد با کیفیت نمراتش در برابر یک مرجع قضاوت میشود. خواص مفیدش calibration است (نمره ۰.۷ یعنی تقریباً ۰.۷)، پایداری (ورودی یکسان در اجراها و ترتیبهای مختلف نمره یکسان میگیرد)، و استقلال از framing کنشگر. باید بهقدری کند باشد که دقیق عمل کند و بهقدری ارزان که در مقیاس suite اجرا شود.
نیازمندیها در جهتهای مخالف کشیده میشوند. مدلهای تصمیم از فشردهسازی تهاجمی context و خروجیهای قاطع و مطمئن سود میبرند. مدلهای شواهد از خروجیهای محافظهکارانه و عدمقطعیت صریح سود میبرند. مدلی که برای قاطع بودن آموزش دیده یا prompt شده، بنا به ساختار، برای این کار که بگوید «مطمئن نیستم این درست است» مناسب نیست.
چرا وزنهای مشترک ارزیابی را میشکنند
وقتی داور از کنشگر مشتق میشود، نقاط کور کنشگر را به ارث میبرد. اگر کنشگر بهطور سیستماتیک یک قالب تاریخ را اشتباه بخواند، داوری با همان وزنها و همان توزیع آموزشی، تمایل دارد آن اشتباه را بپذیرد. شکست بهصورت پاسخ غلط ظاهر نمیشود؛ بهصورت نمره قبولی ظاهر میشود. ارزیابی سلامت گزارش میدهد در حالی که سیستم خراب است.

این فرضی نیست. حالت عادی حلقههای خودنمرهدهی است، جایی که از همان مدل خواسته میشود خروجی خودش را بررسی کند. بررسی با خطا همبسته است، پس بررسی اطلاعات کمی اضافه میکند. در بدترین حالت اطلاعات منفی اضافه میکند: نمره بالا است دقیقاً چون کنشگر و داور همان prior غلط را به اشتراک میگذارند.
حلقههای خودبهبودی مشکل را تشدید میکنند. اگر کنشگر در برابر نمرات داور fine-tune یا prompt-optimise شود، ترجیحات داور را یاد میگیرد نه وظیفه را. gradient به هر چیزی اشاره میکند که داور تصادفاً پاداش میدهد، از جمله idiosyncrasyهایش. در طول تکرارها سیستم در ارضای داور بهتر میشود و در کار هیچ بهتر نمیشود. معیار ارزیابی بالا میرود؛ محصول نه.
داورهای مستقل در هر اجرا هزینه بیشتری دارند. در بیشتر موارد، تنها مکانیزمی هستند که میتوانند خطای سیستماتیک را تشخیص دهند، چون آن خطا را به اشتراک نمیگذارند. تمام نکته جداسازی همین است.
یک الگوی جداسازی
با داور مثل یک dependency با چرخه حیات خودش رفتار کنید.
داور را مستقل نسخهبندی کنید و آن را برای هر suite pin کنید
داور یک config flag نیست. یک مصنوع است با یک نسخه، یک prompt، یک مدل و یک پیکربندی decoding. هر چهار مورد را برای هر suite ارزیابی pin کنید، همانطور که نسخه یک کتابخانه را در lockfile pin میکنید. وقتی داور تغییر میکند، نمرات suite دیگر با اجرای قبلی قابل مقایسه نیستند، و سیستم باید این را بگوید نه اینکه بیسروصدا بین نسخهها diff بگیرد.
یک مکانیزم مشخص: یک judge manifest را در کنار هر suite ذخیره کنید.
suite: checkout-agent-v4
judge:
model: evidence-judge-2024-11
prompt_hash: 9f2c1a
decoding: {temperature: 0.0, top_p: 1.0}
rubric_version: 3
actor:
model: checkout-actor-2024-11
prompt_hash: 4b7e02
هر ردیف نمرهای که harness م
یک holdout برچسبخورده توسط انسان نمونهگیری کنید تا drift داور را تشخیص دهید
drift کنشگر مظنون معمول است، اما drift داور همان چیزی است که اندازهگیری را خراب میکند. یک مجموعه کوچک برچسبخورده توسط انسان را hold out کنید که کنشگر هرگز روی آن آموزش نمیبیند و داور هرگز در برابر آن tune نمیشود. داور را طبق یک برنامه زمانی روی آن اجرا کنید. اگر توافق داور با برچسبهای انسانی خارج از باند تاریخیاش حرکت کند، داور drift کرده است، و هر نمرهای که از آخرین اجرای پاک تولید کرده مشکوک است.
holdout لازم نیست بزرگ باشد. باید پایدار باشد، توسط فرایندی مستقل از داور برچسب خورده باشد، و بهقدر کافی بررسی شود که drift قبل از اینکه به یک تصمیم deployment اطلاع دهد گرفته شود.
هویت داور را با هر نمره ثبت کنید
مقایسههای تاریخی فقط وقتی معتبرند که ابزار اندازهگیری یکسان باشد. وقتی نمرهای ذخیره میشود، hash judge manifest را با آن ذخیره کنید. داشبوردها باید از رسم خط روند در مرز نسخه داور امتناع کنند، یا مرز را صریحاً نمایش دهند. این لولهکشی غیرجذاب است، و تفاوت بین یک معیار و یک ادعاست.
معاوضههایی که باید پذیرفت
داوری مستقل به هر اجرای ارزیابی latency و هزینه اضافه میکند. یک داور جداگانه یعنی یک فراخوانی مدل دوم بهازای هر آیتم، یا یک batch job روی suite، بهعلاوه زیرساخت برای نسخهبندی و serving آن. برای suiteهای بزرگ این یک قلم هزینه واقعی است، و قیمت اندازهگیریای است که میتواند خطاهای سیستماتیک کنشگر را تشخیص دهد.
نسخهبندی داور کار مهاجرت ایجاد میکند. وقتی داور ارتقا مییابد، نمرات قبل و بعد مستقیماً قابل مقایسه نیستند. یا داور قدیمی زنده نگه داشته میشود تا suite تاریخی را دوباره نمره دهد، یا suite دوباره baseline میشود و ناپیوستگی مستند میشود. هر دو کار هستند. هیچکدام قابل اجتناب نیست اگر ارزیابی قرار است به یک تصمیم deployment اطلاع دهد، چون تصمیمی که بر اعداد غیرقابل مقایسه گرفته شود، حدسی است که لباس داشبورد پوشیده.
جایگزین ارزانتر و بدتر است: داوری که وزنهای کنشگر را به اشتراک میگذارد، بنا به ساختار با آن موافق است، و موفقیت گزارش میدهد. آن سیستم ارزیابی نمیشود. دارد چاپلوسی میشود.
مرز یک انتخاب طراحی است
خط بین مدلهایی که تصمیم میگیرند و مدلهایی که داوری میکنند، یک مرز طراحی است، نه یک مرز اندازه. درباره استفاده از مدل بزرگتر برای نمرهدهی به مدل کوچکتر نیست، یا برعکس. درباره دو مصنوع با اهداف متفاوت، حالتهای شکست متفاوت و چرخههای حیات متفاوت است. تیمهایی که مرز را آگاهانه ترسیم میکنند، ارزیابیهایی به دست میآورند که میتوانند بر اساس آن عمل کنند. تیمهایی که آن را فرو میریزند، عددی به دست میآورند که بالا میرود، و سیستمی که بالا نمیرود.
