فاز 10 · درس 10

ارزیابی مدل‌های زبانی: از بنچمارک تا بستر تست اختصاصی

نوع
ساختنی
زمان
حدود 90 دقیقه
زبان‌ها
Python
یک ترازوی سنجش دقیق در کنار برگه آزمون و مدال‌های شطرنج در یک فضای آزمایشگاهی مهندسی نرم‌افزار
فهرست مطالب
  1. اهداف یادگیری
  2. صورت مسئله
  3. مفاهیم پایه
  4. چشم‌انداز روش‌های ارزیابی
  5. چرا بنچمارک‌ها کارایی خود را از دست می‌دهند؟
  6. پرپلکسیتی: یک بررسی سلامت سریع
  7. مدل زبانی در نقش داور (LLM-as-judge)
  8. رتبه‌بندی ELO بر پایه‌ی مقایسه‌های دونفره
  9. فریم‌ورک‌های ارزیابی
  10. ساخت ارزیابی‌های سفارشی
  11. پیاده‌سازی
  12. گام 1: فریم‌ورک ارزیابی مینیمال
  13. گام 2: توابع امتیازدهی
  14. گام 3: سیستم رتبه‌بندی ELO
  15. گام 4: محاسبه‌ی پرپلکسیتی
  16. گام 5: تجمیع نتایج
  17. گام 6: اجرای پایپ‌لاین کامل
  18. گام 7: تورنمنت ELO
  19. گام 8: مقایسه‌ی پرپلکسیتی
  20. استفاده از ابزارها
  21. ابزار lm-evaluation-harness (از EleutherAI)
  22. ابزار promptfoo
  23. ارزیابی سامانه‌های RAG با ابزار RAGAS
  24. ارائه‌ی محصول نهایی
  25. تمرین‌ها
  26. اصطلاحات کلیدی
  27. برای مطالعه‌ی بیشتر

بسیاری از توسعه‌دهندگان هنگام انتخاب یا ارزیابی مدل‌های زبانی، تنها به رده‌بندی‌ها و بنچمارک‌های عمومی مانند MMLU یا HumanEval تکیه می‌کنند. اما در عمل، کسب امتیاز بالای 85% در یک بنچمارک استاندارد تضمینی برای پاسخ‌گویی دقیق به داده‌های کسب‌وکار شما نیست. پدیده‌هایی مثل اشباع آزمون‌ها، آلودگی داده‌های پیش‌آموزش و رفتارهای غیرمنتظره در تسک‌های ساده باعث شده‌اند که اتکای صرف به اعداد عمومی خطایی پرهزینه باشد.

در این درس یاد می‌گیرید که چگونه فراتر از ادعاهای بازاریابی آزمایشگاه‌های هوش مصنوعی گام بردارید و بستر ارزیابی سفارشی (Custom Eval Harness) خود را بسازید. با پیاده‌سازی توابع امتیازدهی دقیق، روش مدل زبانی در نقش داور (LLM-as-judge) و سیستم‌های رتبه‌بندی نسبی مثل ELO، یاد می‌گیرید مدل‌ها را دقیقاً بر اساس همان سناریوها و داده‌هایی محک بزنید که در محیط پروداکشن قرار است با آن‌ها درگیر شوند.

اگر برای ارزیابی مدل‌ها از API سرویس‌های خارجی استفاده می‌کنید، توجه داشته باشید که دسترسی به برخی ارائه‌دهندگان ابری یا سرویس‌های API از IP ایران محدود یا مسدود است و پرداخت ارزی برای آن‌ها با کارت‌های بانکی داخلی ممکن نیست. در این موارد می‌توانید برای سناریوهای سبک‌تر از مدل‌های باز کوچک به‌صورت محلی بهره ببرید یا با استفاده از گیت‌وی‌های ارائه‌دهنده‌ی API سازگار با فرمت OpenAI، بسترهای ارزیابی را با کمترین تغییر در کد راه‌اندازی کنید.

قانون گودهارت: وقتی یک معیار تبدیل به هدف شود، دیگر معیار خوبی نخواهد بود. تمام آزمایشگاه‌های پیشرو بنچمارک‌ها را دور می‌زنند و بازی می‌دهند. امتیازات MMLU بالا می‌رود، اما مدل‌ها هنوز نمی‌توانند تعداد حروف R را در کلمه‌ی «strawberry» به‌درستی بشمارند. تنها ارزیابی‌ای (eval) که واقعاً اهمیت دارد، ارزیابی اختصاصی خودِ شماست؛ روی تسکِ شما و با داده‌های شما.

اهداف یادگیری

  • ساخت یک بستر ارزیابی (evaluation harness) سفارشی برای اجرای بنچمارک‌های چندگزینه‌ای و پاسخ‌باز روی مدل‌های زبانی
  • توضیح دلایل اشباع بنچمارک‌های استاندارد (مثل MMLU و HumanEval) و ناتوانی آن‌ها در تفکیک مدل‌های پیشرو
  • پیاده‌سازی ارزیابی‌های مختص تسک با معیارهای مناسب: تطابق دقیق (exact match)، معیار F1، معیار BLEU و امتیازدهی با مدل زبانی در نقش داور (LLM-as-judge)
  • طراحی یک مجموعه‌ی ارزیابی سفارشی برای کاربرد مشخص خودتان، به‌جای اتکای صرف به جدول‌های رده‌بندی (leaderboards) عمومی

صورت مسئله

بنچمارک MMLU در سال 2020 با 15,908 پرسش در 57 موضوع مختلف منتشر شد. ظرف سه سال، مدل‌های پیشرو آن را اشباع کردند. مدل GPT-4 امتیاز 86.4% را کسب کرد، Claude 3 Opus به 86.8% رسید و Llama 3 405B امتیاز 88.6% را ثبت کرد. جدول رده‌بندی در بازه‌ای محدود به 3 درصد فشرده شد؛ جایی که تفاوت‌ها ناشی از نویز آماری است، نه اختلاف واقعی در توانمندی مدل‌ها.

در همین حال، همان مدل‌ها در تسک‌هایی شکست می‌خورند که یک کودک 10 ساله بدون مکث انجامشان می‌دهد. مدل Claude 3.5 Sonnet با امتیاز 88.7% در MMLU، اوایل حتی نمی‌توانست حروف کلمه‌ی «strawberry» را بشمارد؛ کاری که به هیچ دانش عمومی یا استدلالی نیاز ندارد و صرفاً یک پیمایش ساده در سطح کاراکتر است. بنچمارک HumanEval تولید کد را با 164 مسئله می‌سنجد. مدل‌ها در آن امتیاز بالای 90% می‌گیرند، اما همچنان کدی تولید می‌کنند که در حالت‌های خاصِ (edge cases) پیش‌پاافتاده از کار می‌افتد؛ خطاهایی که هر برنامه‌نویس تازه‌کاری متوجه آن‌ها می‌شود.

شکاف میان عملکرد در بنچمارک و قابلیت اطمینان در دنیای واقعی، چالش اصلی ارزیابی مدل‌های زبانی است. بنچمارک‌ها فقط می‌گویند مدل روی همان بنچمارک چطور کار می‌کند. آن‌ها تقریباً هیچ داده‌ای درباره‌ی عملکرد مدل روی تسک خاص شما، داده‌های واقعی شما و تحت حالت‌های شکست اختصاصی سیستم شما ارائه نمی‌دهند. اگر قرار است بات پشتیبانی مشتریان بسازید، MMLU هیچ دردی از شما دوا نمی‌کند. اگر دستیار کدنویسی می‌سازید، HumanEval فقط تولید توابع مستقل را می‌سنجد و هیچ بینشی درباره‌ی دیباگ، ریفکتور یا توضیح کدهای میان‌فایلی به شما نمی‌دهد.

به ارزیابی‌های سفارشی نیاز دارید؛ نه به این خاطر که بنچمارک‌ها کاملاً بی‌فایده‌اند (آن‌ها برای انتخاب اولیه‌ی مدل‌ها خوبند)، بلکه چون ارزیابی نهایی باید دقیقاً با شرایط استقرار شما در محیط پروداکشن همخوانی داشته باشد.

مفاهیم پایه

چشم‌انداز روش‌های ارزیابی

ارزیابی‌ها در سه دسته‌ی کلی قرار می‌گیرند که هرکدام هزینه و کیفیت سیگنال متفاوتی دارند:

بنچمارک‌ها مجموعه‌آزمون‌های استاندارد هستند: MMLU، HumanEval، SWE-bench، MATH، ARC و HellaSwag. مدل را روی بنچمارک اجرا می‌کنید و یک امتیاز تحویل می‌گیرید. مزیت روش: آزمون برای همه یکسان است، بنابراین مقایسه‌ی مدل‌ها ممکن می‌شود. عیب روش: مدل‌ها و داده‌های آموزش روز‌به‌روز بیشتر به این بنچمارک‌ها آلوده می‌شوند. آزمایشگاه‌ها مدل‌ها را با داده‌هایی آموزش می‌دهند که پرسش‌های بنچمارک را هم شامل می‌شود. امتیازها بالا می‌رود، اما شاید توانمندی واقعی تغییری نکند.

ارزیابی‌های سفارشی (Custom evals) مجموعه‌آزمون‌هایی هستند که برای کاربرد مشخص خودتان می‌سازید. ورودی‌ها، خروجی‌های مورد انتظار و تابع امتیازدهی را خودتان تعیین می‌کنید. سامانه‌ی خلاصه‌ساز متون حقوقی روی اسناد حقوقی سنجیده می‌شود؛ تولیدکننده‌ی SQL روی اسکیماهای پایگاه داده‌ی خودتان محک می‌خورد. ساخت این ارزیابی‌ها پرهزینه است، اما تنها ارزیابی‌هایی هستند که عملکرد در محیط پروداکشن را به‌درستی پیش‌بینی می‌کنند.

ارزیابی‌های انسانی (Human evals) از ارزیاب‌های انسانیِ پولی برای داوری خروجی‌ها بر اساس معیارهایی مانند سودمندی، صحت، روانی کلام و ایمنی استفاده می‌کنند. این شیوه سنگ محک اصلی برای تسک‌های پاسخ‌باز است؛ یعنی جاهایی که امتیازدهی خودکار ناکام می‌ماند. پروژه‌ی Chatbot Arena بیش از 2 میلیون رأی ترجیح انسانی را روی بیش از 100 مدل جمع‌آوری کرده است. معایب این شیوه: هزینه (بین 0.10 تا 2.00 دلار برای هر قضاوت) و سرعت پایین (از چند ساعت تا چند روز).

چشم‌انداز ارزیابیانتخاب اولیه مدلموارد مبهمبنچمارک‌ها(MMLU, HumanEval)ارزان، استانداردقابل تقلب، قدیمیارزیابی‌های سفارشیوظیفه شما، داده شمابالاترین سیگنالساخت پرهزینهارزیابی‌های انسانی(Chatbot Arena)استاندارد طلاییکند، پرهزینه

چرا بنچمارک‌ها کارایی خود را از دست می‌دهند؟

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

آلودگی داده‌ها (Data contamination): مجموعه‌های آموزشی از سطح وب جمع‌آوری می‌شوند. سوالات بنچمارک‌ها هم در اینترنت در دسترس هستند. در نتیجه، مدل‌ها در طول آموزش پاسخ‌ها را می‌بینند. این موضوع به‌معنای سنتی کلمه تقلب نیست؛ آزمایشگاه‌ها داده‌های بنچمارک را عمداً وارد داده‌ها نمی‌کنند، اما در مقیاس عظیم وب‌اسکریپینگ، تفکیک و حذف کامل آن‌ها عملاً ناممکن است.

آموزش برای آزمون (Teaching to the test): آزمایشگاه‌ها ترکیب داده‌های آموزشی را برای عملکرد بهتر در بنچمارک‌ها بهینه‌سازی می‌کنند. اگر 5% از ترکیب داده‌های آموزش سوالات چندگزینه‌ای مشابه MMLU باشد، مدل فرمت و توزیع پاسخ‌ها را یاد می‌گیرد. آزمون MMLU چهارگزینه‌ای است. مدل‌ها یاد می‌گیرند که توزیع گزینه‌ها تقریباً بین A/B/C/D یکنواخت است؛ این آگاهی حتی وقتی مدل جواب را نمی‌داند هم به کمکش می‌آید.

اشباع (Saturation): وقتی تمام مدل‌های پیشرو امتیازی بین 85% تا 90% کسب می‌کنند، بنچمارک دیگر قدرت تفکیک نخواهد داشت. آن 10 الی 15 درصد سوال باقیمانده ممکن است مبهم باشند، برچسب اشتباه خورده باشند یا به دانشی بسیار خاص و نامتعارف نیاز داشته باشند. بهبود امتیاز از 87% به 89% در MMLU شاید فقط به این معنا باشد که مدل دو سوال خاص دیگر را حفظ کرده است، نه اینکه باهوش‌تر شده باشد.

پرپلکسیتی: یک بررسی سلامت سریع

پرپلکسیتی (Perplexity) میزان غافلگیری مدل را در مواجهه با توالی‌ای از توکن‌ها اندازه می‌گیرد. از نظر ریاضی، این معیار برابر است با نمایی‌شده‌ی میانگین منفیِ درست‌نمایی لگاریتمی (log-likelihood):

PPL=exp⁡(−1N∑ilog⁡P(tokeni∣context))\text{PPL} = \exp\left(-\frac{1}{N} \sum_i \log P(\text{token}_i \mid \text{context})\right)

پرپلکسیتیِ 10 یعنی مدل به‌طور میانگین در جایگاه هر توکن، به اندازه‌ی انتخاب تصادفی و یکنواخت بین 10 گزینه بلاتکلیف است. عدد کمتر نشان‌دهنده‌ی عملکرد بهتر است. مدل GPT-2 روی WikiText-103 پرپلکسیتی حدود 30 دارد؛ GPT-3 به حدود 20 می‌رسد و Llama 3 8B حدود 7 است.

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

مدل زبانی در نقش داور (LLM-as-judge)

از یک مدل قوی برای ارزیابی خروجی‌های مدلی ضعیف‌تر استفاده کنید. ایده ساده است: از GPT-4o یا Claude Sonnet بخواهید به پاسخ از نظر صحت، میزان کمک‌کنندگی و ایمنی بین 1 تا 5 امتیاز بدهد. این کار با GPT-4o-mini حدود 0.01 دلار به ازای هر قضاوت هزینه دارد و به شکلی غافلگیرکننده با قضاوت انسان‌ها همبستگی بالایی نشان می‌دهد؛ حدود 80% توافق در بیشتر تسک‌ها.

پرامپت امتیازدهی حتی از خودِ مدل هم مهم‌تر است. یک پرامپت مبهم («به این پاسخ نمره بده») نمرات پر از نویزی تولید می‌کند. یک پرامپت ساختاریافته همراه با شیوه‌نامه‌ی نمره‌دهی (rubric) («اگر پاسخ از نظر علمی درست است و به منبع ارجاع داده امتیاز 5 بده؛ اگر درست است اما منبع ندارد 4 بده؛ اگر بخشی از آن درست است 3 بده...») امتیازاتی پایدار و تکرارپذیر به دست می‌دهد.

حالت‌های شکست: مدل‌های داور دچار سوگیری موقعیت (position bias، یعنی ترجیح پاسخ اول در مقایسه‌های دونفره)، سوگیری پرحرفی (verbosity bias، یعنی ترجیح پاسخ‌های طولانی‌تر) و ترجیح خود (self-preference، یعنی تمایل GPT-4 به دادن امتیاز بالاتر به خروجی‌های خودش نسبت به خروجی‌های معادل Claude) هستند. راهکارها: تصادفی کردن ترتیب گزینه‌ها، نرمال‌سازی بر اساس طول متن و استفاده از مدل داوری متفاوت با مدل در حال ارزیابی.

رتبه‌بندی ELO بر پایه‌ی مقایسه‌های دونفره

این همان رویکرد Chatbot Arena است. دو پاسخِ ارائه‌شده به یک پرامپت از دو مدل مختلف را نشان دهید. یک انسان (یا مدل زبانی در نقش داور) پاسخ بهتر را انتخاب می‌کند. از دل هزاران مقایسه‌ی این‌چنینی، رتبه‌ی ELO برای هر مدل محاسبه می‌شود؛ دقیقاً همان سیستمی که در شطرنج استفاده می‌شود.

مزایای ELO: رتبه‌بندی نسبی بسیار قابل‌اعتمادتر از نمره‌دهی مطلق است، تساوی‌ها را به‌خوبی مدیریت می‌کند و در مقایسه با امتیازدهی مستقل به تک‌تک خروجی‌ها، با تعداد مقایسه‌ی کمتری همگرا می‌شود. تا اوایل سال 2026، جدول رده‌بندی Chatbot Arena نشان می‌دهد که GPT-4o، Claude 3.5 Sonnet و Gemini 1.5 Pro در صدر جدول، کمتر از 20 امتیاز ELO با یکدیگر فاصله دارند.

پایپ‌لاین امتیازدهی ELOپرامپتخروجی مدل Aخروجی مدل Bداور(انسان یا LLM)برد A / برد B / مساویبه‌روزرسانی ELOK=32

فریم‌ورک‌های ارزیابی

lm-evaluation-harness (از EleutherAI): فریم‌ورک استاندارد و متن‌باز برای ارزیابی. از بیش از 200 بنچمارک پشتیبانی می‌کند. می‌توانید هر مدل Hugging Face را با یک دستور روی MMLU، HellaSwag، ARC و غیره بسنجید. این ابزار در Open LLM Leaderboard به کار می‌رود.

RAGAS: فریم‌ورک ارزیابی اختصاصی برای پایپ‌لاین‌های RAG. معیارهایی مانند وفاداری (آیا پاسخ به بافتار بازیابی‌شده متکی است؟)، ارتباط (آیا بافتار بازیابی‌شده به سوال مرتبط است؟) و درستی پاسخ را اندازه می‌گیرد.

promptfoo: ابزاری پیکربندی‌محور برای ارزیابی در مهندسی پرامپت. سناریوهای آزمون را در فایل YAML تعریف کنید، آن‌ها را روی چندین مدل اجرا نمایید و گزارشی از قبولی/ردی بگیرید. برای آزمون‌های رگرسیونِ پرامپت عالی است؛ تا مطمئن شوید تغییر در پرامپت، سناریوهای آزمون قبلی را خراب نمی‌کند.

ساخت ارزیابی‌های سفارشی

تنها ارزیابی‌ای که برای محیط پروداکشن اهمیت دارد. مراحل کار:

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

  2. ایجاد سناریوهای آزمون: حداقل 50 مورد برای ارزیابی نمونه‌ی اولیه، و بیش از 200 مورد برای پروداکشن. هر سناریوی آزمون یک زوج (input, expected_output) است. حالت‌های خاص را حتماً بگنجانید: ورودی‌های خالی، ورودی‌های خصمانه (adversarial)، ورودی‌های مبهم و ورودی‌هایی به زبان‌های دیگر.

  3. تعیین سازوکار امتیازدهی: تطابق دقیق برای خروجی‌های ساختاریافته؛ معیارهای BLEU/ROUGE برای شباهت متنی؛ مدل زبانی در نقش داور برای سنجش کیفیت خروجی‌های پاسخ‌باز؛ معیار F1 برای تسک‌های استخراج اطلاعات. معیارهای مختلف را با ضریب وزنی ترکیب کنید.

  4. اتوماسیون: کل فرآیند ارزیابی باید با یک دستور اجرا شود، بدون دخالت دست. نتایج را در قالبی ذخیره کنید که امکان مقایسه در طول زمان را فراهم کند.

  5. رهگیری روند در گذر زمان: یک امتیاز ارزیابی به‌تنهایی بی‌معنی است؛ شما به نمودار روند نیاز دارید. آیا بعد از آخرین تغییر پرامپت نمره بهتر شد؟ آیا پس از تعویض مدل دچار افت عملکرد شدید؟ ارزیابی‌ها را همگام با پرامپت‌هایتان نسخه‌بندی کنید.

نوع ارزیابی هزینه در هر قضاوت سازگاری با انسان بهترین کاربرد برای
تطابق دقیق حدود 0 دلار 100% (در صورت امکان تطبیق) خروجی ساختاریافته، دسته‌بندی
BLEU/ROUGE حدود 0 دلار حدود 60% ترجمه، خلاصه‌سازی
مدل زبانی در نقش داور حدود 0.01 دلار حدود 80% تولید محتوای پاسخ‌باز
ارزیابی انسانی 0.10 تا 2.00 دلار ارزیابی مبنا (همان داده‌ی واقعی است) تسک‌های مبهم، حساس و پرریسک
پرپلکسیتیتابع زیان (loss) را بکشید
PERPLEXITYPerplexity is the exponential of cross-entropy loss, read as the effective number of equally likely choices the model is deciding between per token. A model that guessed uniformly over a vocabulary of size V would score perplexity exactly V (the orange line), so any useful model must land well below it.
پرپلکسیتی برابر با تابع نمایی زیان آنتروپی متقاطع است و به عنوان تعداد گزینه‌های محتمل و برابری تفسیر می‌شود که مدل برای هر توکن میان آن‌ها تصمیم می‌گیرد. مدلی که به‌طور یکنواخت از میان واژگانی با اندازه V حدس بزند، دقیقاً نمره پرپلکسیتی V (خط نارنجی) خواهد داشت؛ بنابراین هر مدل کارآمدی باید مقداری به مراتب کمتر از آن به دست آورد.

پیاده‌سازی

گام 1: فریم‌ورک ارزیابی مینیمال

مفاهیم پایه‌ای را تعریف کنید. هر سناریوی ارزیابی شامل یک ورودی، خروجی مورد انتظار و یک دیکشنری اختیاری از متادیتا است. تابع امتیازدهی نیز پیش‌بینی و داده‌ی مرجع را می‌گیرد و امتیازی بین 0 و 1 برمی‌گرداند.

import json
from collections import Counter

class EvalCase:
    def __init__(self, input_text, expected, metadata=None):
        self.input_text = input_text
        self.expected = expected
        self.metadata = metadata or {}

class EvalSuite:
    def __init__(self, name, cases, scorers):
        self.name = name
        self.cases = cases
        self.scorers = scorers

    def run(self, model_fn):
        results = []
        for case in self.cases:
            prediction = model_fn(case.input_text)
            scores = {}
            for scorer_name, scorer_fn in self.scorers.items():
                scores[scorer_name] = scorer_fn(prediction, case.expected)
            results.append({
                "input": case.input_text,
                "expected": case.expected,
                "prediction": prediction,
                "scores": scores,
            })
        return results

گام 2: توابع امتیازدهی

توابع تطابق دقیق، F1 توکنی و یک مدل زبانی در نقش داورِ شبیه‌سازی‌شده را بسازید.

def exact_match(prediction, expected):
    return 1.0 if prediction.strip().lower() == expected.strip().lower() else 0.0

def token_f1(prediction, expected):
    pred_tokens = set(prediction.lower().split())
    exp_tokens = set(expected.lower().split())
    if not pred_tokens or not exp_tokens:
        return 0.0
    common = pred_tokens & exp_tokens
    precision = len(common) / len(pred_tokens)
    recall = len(common) / len(exp_tokens)
    if precision + recall == 0:
        return 0.0
    return 2 * (precision * recall) / (precision + recall)

def llm_judge_simulated(prediction, expected):
    pred_words = set(prediction.lower().split())
    exp_words = set(expected.lower().split())
    if not exp_words:
        return 0.0
    overlap = len(pred_words & exp_words) / len(exp_words)
    length_penalty = min(1.0, len(prediction) / max(len(expected), 1))
    return round(overlap * 0.7 + length_penalty * 0.3, 3)

گام 3: سیستم رتبه‌بندی ELO

مقایسه‌های دونفره همراه با به‌روزرسانی رتبه‌ی ELO را پیاده‌سازی کنید. این دقیقاً همان سیستمی است که Chatbot Arena برای رتبه‌بندی مدل‌ها به کار می‌برد.

class ELOTracker:
    def __init__(self, k=32, initial_rating=1500):
        self.ratings = {}
        self.k = k
        self.initial_rating = initial_rating
        self.history = []

    def _ensure_player(self, name):
        if name not in self.ratings:
            self.ratings[name] = self.initial_rating

    def expected_score(self, rating_a, rating_b):
        return 1 / (1 + 10 ** ((rating_b - rating_a) / 400))

    def record_match(self, player_a, player_b, outcome):
        self._ensure_player(player_a)
        self._ensure_player(player_b)

        ea = self.expected_score(self.ratings[player_a], self.ratings[player_b])
        eb = 1 - ea

        if outcome == "a":
            sa, sb = 1.0, 0.0
        elif outcome == "b":
            sa, sb = 0.0, 1.0
        else:
            sa, sb = 0.5, 0.5

        self.ratings[player_a] += self.k * (sa - ea)
        self.ratings[player_b] += self.k * (sb - eb)

        self.history.append({
            "a": player_a, "b": player_b,
            "outcome": outcome,
            "rating_a": round(self.ratings[player_a], 1),
            "rating_b": round(self.ratings[player_b], 1),
        })

    def leaderboard(self):
        return sorted(self.ratings.items(), key=lambda x: -x[1])

گام 4: محاسبه‌ی پرپلکسیتی

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

import numpy as np

def perplexity(log_probs):
    if not log_probs:
        return float("inf")
    avg_neg_log_prob = -np.mean(log_probs)
    return float(np.exp(avg_neg_log_prob))

def token_log_probs_simulated(text, model_quality=0.8):
    np.random.seed(hash(text) % 2**31)
    tokens = text.split()
    log_probs = []
    for i, token in enumerate(tokens):
        base_prob = model_quality
        if len(token) > 8:
            base_prob *= 0.6
        if i == 0:
            base_prob *= 0.7
        prob = np.clip(base_prob + np.random.normal(0, 0.1), 0.01, 0.99)
        log_probs.append(float(np.log(prob)))
    return log_probs

گام 5: تجمیع نتایج

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

def summarize_results(results, threshold=0.8):
    all_scores = {}
    for r in results:
        for metric, score in r["scores"].items():
            all_scores.setdefault(metric, []).append(score)

    summary = {}
    for metric, scores in all_scores.items():
        arr = np.array(scores)
        summary[metric] = {
            "mean": round(float(np.mean(arr)), 3),
            "median": round(float(np.median(arr)), 3),
            "std": round(float(np.std(arr)), 3),
            "min": round(float(np.min(arr)), 3),
            "max": round(float(np.max(arr)), 3),
            "pass_rate": round(float(np.mean(arr >= threshold)), 3),
            "n": len(scores),
        }
    return summary

def print_summary(summary, suite_name="Eval"):
    print(f"\n{'=' * 60}")
    print(f"  {suite_name} Summary")
    print(f"{'=' * 60}")
    for metric, stats in summary.items():
        print(f"\n  {metric}:")
        print(f"    Mean:      {stats['mean']:.3f}")
        print(f"    Median:    {stats['median']:.3f}")
        print(f"    Std:       {stats['std']:.3f}")
        print(f"    Range:     [{stats['min']:.3f}, {stats['max']:.3f}]")
        print(f"    Pass rate: {stats['pass_rate']:.1%} (threshold >= 0.8)")
        print(f"    N:         {stats['n']}")

گام 6: اجرای پایپ‌لاین کامل

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

def demo_model_good(prompt):
    responses = {
        "What is the capital of France?": "Paris",
        "What is 2 + 2?": "4",
        "Who wrote Hamlet?": "William Shakespeare",
        "What language is PyTorch written in?": "Python and C++",
        "What is the boiling point of water?": "100 degrees Celsius",
    }
    return responses.get(prompt, "I don't know")

def demo_model_bad(prompt):
    responses = {
        "What is the capital of France?": "Paris is the capital city of France",
        "What is 2 + 2?": "The answer is four",
        "Who wrote Hamlet?": "Shakespeare",
        "What language is PyTorch written in?": "Python",
        "What is the boiling point of water?": "212 Fahrenheit",
    }
    return responses.get(prompt, "Unknown")

cases = [
    EvalCase("What is the capital of France?", "Paris"),
    EvalCase("What is 2 + 2?", "4"),
    EvalCase("Who wrote Hamlet?", "William Shakespeare"),
    EvalCase("What language is PyTorch written in?", "Python and C++"),
    EvalCase("What is the boiling point of water?", "100 degrees Celsius"),
]

suite = EvalSuite(
    name="General Knowledge",
    cases=cases,
    scorers={
        "exact_match": exact_match,
        "token_f1": token_f1,
        "llm_judge": llm_judge_simulated,
    },
)

results_good = suite.run(demo_model_good)
results_bad = suite.run(demo_model_bad)

print_summary(summarize_results(results_good), "Model A (concise)")
print_summary(summarize_results(results_bad), "Model B (verbose)")

مدل «خوب» پاسخ‌های دقیق می‌دهد؛ درحالی‌که مدل «بد» پاسخ‌هایی طولانی با بازنویسی متن ارائه می‌کند. معیار تطابق دقیق، مدل پرحرف را شدیداً جریمه می‌کند. در مقابل، معیارهای Token F1 و مدل زبانی در نقش داور برخورد ملایم‌تری دارند. این سناریو نشان می‌دهد چرا انتخاب معیار اهمیت زیادی دارد: یک مدل واحد ممکن است بسته به روش امتیازدهی شما، عالی یا کاملاً افتضاح به نظر برسد.

گام 7: تورنمنت ELO

مقایسه‌های دونفره میان مدل‌ها را در چندین دور اجرا کنید.

elo = ELOTracker(k=32)

for case in cases:
    pred_a = demo_model_good(case.input_text)
    pred_b = demo_model_bad(case.input_text)

    score_a = token_f1(pred_a, case.expected)
    score_b = token_f1(pred_b, case.expected)

    if score_a > score_b:
        outcome = "a"
    elif score_b > score_a:
        outcome = "b"
    else:
        outcome = "tie"

    elo.record_match("model_a_concise", "model_b_verbose", outcome)

print("\nELO Leaderboard:")
for name, rating in elo.leaderboard():
    print(f"  {name}: {rating:.0f}")

گام 8: مقایسه‌ی پرپلکسیتی

پرپلکسیتی را در میان «مدل‌ها»یی با سطوح کیفی متفاوت بررسی و مقایسه کنید.

test_text = "The quick brown fox jumps over the lazy dog in the garden"

for quality, label in [(0.9, "Strong model"), (0.7, "Medium model"), (0.4, "Weak model")]:
    log_probs = token_log_probs_simulated(test_text, model_quality=quality)
    ppl = perplexity(log_probs)
    print(f"  {label} (quality={quality}): perplexity = {ppl:.2f}")

استفاده از ابزارها

ابزار lm-evaluation-harness (از EleutherAI)

ابزار استاندارد برای اجرای بنچمارک‌ها روی هر مدلی.

# pip install lm-eval
# خط فرمان:
# lm_eval --model hf --model_args pretrained=meta-llama/Llama-3.1-8B --tasks mmlu --batch_size 8

# رابط پایتون (Python API):
# import lm_eval
# results = lm_eval.simple_evaluate(
#     model="hf",
#     model_args="pretrained=meta-llama/Llama-3.1-8B",
#     tasks=["mmlu", "hellaswag", "arc_easy"],
#     batch_size=8,
# )
# print(results["results"])

ابزار promptfoo

ارزیابی مبتنی بر فایل‌های پیکربندی برای مهندسی پرامپت. آزمون‌ها را در فایل YAML تعریف کنید و خروجی چندین ارائه‌دهنده‌ی مدل را بسنجید.

# promptfoo.yaml
providers:
  - openai:gpt-4o-mini
  - anthropic:claude-3-haiku

prompts:
  - "Answer in one word: {{question}}"

tests:
  - vars:
      question: "What is the capital of France?"
    assert:
      - type: contains
        value: "Paris"
  - vars:
      question: "What is 2 + 2?"
    assert:
      - type: equals
        value: "4"

ارزیابی سامانه‌های RAG با ابزار RAGAS

# pip install ragas
# from ragas import evaluate
# from ragas.metrics import faithfulness, answer_relevancy, context_precision
#
# result = evaluate(
#     dataset,
#     metrics=[faithfulness, answer_relevancy, context_precision],
# )
# print(result)

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

ارائه‌ی محصول نهایی

این درس فایل outputs/prompt-eval-designer.md را تولید می‌کند؛ پرامپتی با قابلیت استفاده‌ی مجدد که برای هر تسکی، مجموعه‌ی ارزیابی سفارشی طراحی می‌کند. شرح تسک را به آن بدهید تا سناریوهای آزمون، توابع امتیازدهی و آستانه‌ی قبولی/ردی پیشنهادی را برایتان بسازد.

همچنین فایل outputs/skill-llm-evaluation.md تولید می‌شود؛ یک چارچوب تصمیم‌گیری برای انتخاب استراتژی ارزیابی مناسب بر اساس نوع تسک، بودجه و الزامات تاخیر سیستم.

تمرین‌ها

  1. یک تابع امتیازدهی تحت عنوان «یکدستی» (consistency) اضافه کنید که یک ورودی ثابت را 5 بار به مدل بفرستد و میزان یکسان بودن خروجی‌ها را اندازه بگیرد. خروجی‌های متناقض روی ورودی‌های قطعی نشان‌دهنده‌ی پرامپت‌های ناپایدار یا مقادیر دمای (temperature) بالا هستند.

  2. سیستم رهگیری ELO را توسعه دهید تا از چندین تابع داوری مختلف (تطابق دقیق، F1 و مدل زبانی در نقش داور) پشتیبانی کند و به هرکدام وزن بدهد. بررسی کنید که وزن‌دهی سنگین به تطابق دقیق در مقایسه با F1، چه تغییری در جدول رده‌بندی ایجاد می‌کند.

  3. یک مجموعه‌ی ارزیابی برای تسکی مشخص طراحی کنید: دسته‌بندی ایمیل‌ها در 5 گروه مختلف. 100 سناریوی آزمون با مثال‌های متنوع، از جمله حالت‌های خاص (ایمیل‌هایی که می‌توانند در چند دسته قرار بگیرند، ایمیل‌های خالی، ایمیل‌هایی به زبان‌های دیگر) بسازید. عملکرد «مدل‌های» مختلف (مبتنی بر قانون، تطابق کلمات کلیدی، و مدل زبانی شبیه‌سازی‌شده) را اندازه بگیرید.

  4. سازوکار شناسایی آلودگی داده را پیاده‌سازی کنید: با داشتن مجموعه‌ای از پرسش‌های ارزیابی و یک پیکره‌ی متنی آموزشی، بررسی کنید چه درصدی از سوالات ارزیابی (یا بازنویسی‌های بسیار نزدیک به آن) در داده‌های آموزشی دیده می‌شوند. این همان روشی است که پژوهشگران برای اعتبارسنجی بنچمارک‌ها استفاده می‌کنند.

  5. یک ابزار «مقایسه‌ی تفاوت مدل‌ها» (model diff) بسازید. این ابزار با گرفتن نتایج ارزیابی دو نسخه‌ی مختلف از یک مدل، باید مشخص کند دقیقاً کدام سناریوهای آزمون بهتر شده‌اند، کدام پسرفت داشته‌اند و کدام تغییری نکرده‌اند. این ابزار معادل دستور diff در دنیای ارزیابی است؛ ابزاری حیاتی برای اینکه بفهمید یک تغییر به بهبود سیستم انجامیده یا به آن لطمه زده است.

اصطلاحات کلیدی

اصطلاح اصطلاح رایج معنای دقیق فنی
MMLU «همان بنچمارک اصلی» بنچمارک Massive Multitask Language Understanding شامل 15,908 سوال چندگزینه‌ای در 57 موضوع که تا سال 2025 با کسب امتیاز بالای 88% اشباع شد
HumanEval «ارزیابی کدنویسی» مجموعه‌ای شامل 164 مسئله‌ی تکمیل تابع پایتون از OpenAI که صرفاً تولید توابع مجزا را ارزیابی می‌کند
SWE-bench «ارزیابی واقعی کدنویسی» 2,294 ایشوی گیت‌هاب از 12 ریپازیتوری پایتون که حل کامل باگ‌ها از جمله تولید تست را به‌صورت سرتاسری می‌سنجد
Perplexity «میزان گیجی مدل» exp⁡(−avg(log⁡P(tokeni given context)))\exp(-\mathop{\mathrm{avg}}(\log P(\text{token}_i \text{ given context})))؛ هرچه کمتر باشد یعنی مدل احتمال بالاتری را به توکن‌های واقعی اختصاص داده است
رتبه‌ی ELO «رده‌بندی شطرنجی برای مدل‌ها» یک سیستم رتبه‌بندی مهارت نسبی بر اساس سابقه‌ی برد و باخت در مقایسه‌های دونفره که Chatbot Arena برای رتبه‌بندی بیش از 100 مدل از آن استفاده می‌کند
مدل زبانی در نقش داور (LLM-as-judge) «استفاده از هوش مصنوعی برای نمره دادن به هوش مصنوعی» یک مدل توانمند که خروجی‌های مدلی ضعیف‌تر را بر اساس یک شیوه‌نامه‌ی نمره‌دهی داوری می‌کند؛ این روش با هزینه‌ی حدود 0.01 دلار برای هر قضاوت، حدود 80% با داوران انسانی همبستگی دارد
آلودگی داده‌ها (Data contamination) «مدل سوالات امتحان را دیده» وجود سوالات بنچمارک در داده‌های آموزشی، که بدون بهبود مهارت‌های واقعی مدل، امتیازها را به‌طور کاذب بالا می‌برد
مجموعه‌ی ارزیابی (Eval suite) «یک مشت تست» مجموعه‌ای نسخه‌بندی‌شده از سه‌گانه‌های (ورودی، خروجی مورد انتظار، تابع امتیازدهی) که توانمندی مشخصی را اندازه می‌گیرند
نرخ قبولی (Pass rate) «چند درصد درست جواب داده» نسبتی از سناریوهای ارزیابی که امتیازی بالاتر از یک آستانه‌ی مشخص کسب می‌کنند؛ این معیار از میانگین نمرات کاربردی‌تر است زیرا قابلیت اطمینان سیستم را می‌سنجد
Chatbot Arena «سایت رده‌بندی مدل‌ها» پلتفرمی از LMSYS با بیش از 2 میلیون رأی ترجیح انسانی، که معتبرترین جدول رده‌بندی مدل‌های زبانی را با استفاده از رتبه‌بندی ELO تولید می‌کند

برای مطالعه‌ی بیشتر

سؤالات متداول

چرا نمرات بنچمارک‌هایی مثل MMLU دیگر بازتاب‌دهنده‌ی هوش واقعی مدل نیستند؟

به دلیل آلودگی داده‌های وب با سوالات بنچمارک، بهینه‌سازی هدفمند داده‌های آموزش برای فرمت تستی (Teaching to the test) و اشباع شدن سقف آزمون که باعث می‌شود اختلاف‌های اندک صرفاً ناشی از نویز آماری باشند.

روش LLM-as-judge چیست و چه چالش‌هایی دارد؟

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

حداقل تعداد سناریوی آزمون برای ساخت یک ارزیابی سفارشی چقدر است؟

برای یک نمونه‌ی اولیه (پروتوتایپ) حداقل 50 سناریوی آزمون و برای سامانه‌های آماده‌ی استقرار در محیط پروداکشن حداقل 200 سناریوی متنوع شامل حالت‌های مرزی و خطاساز نیاز است.

ما رو توی گوگل بیشتر ببین

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