قبل از اینکه چیزی بسازیم، باید بدانیم با چه چیزی طرفیم. این درس شما را از ساده‌ترین تعریف تا اصطلاح «مدل پایه» می‌برد — بدون هیچ پیش‌نیاز ریاضی. مدل زبانی یعنی چه؟ تعریف رسمی‌اش این است: مدل زبانی اطلاعات آماری یک یا چند زبان را در خود ذخیره می‌کند. ولی بیایید ساده‌تر بگوییم. یک دوست را تصور کنید که عادت دارد جمله‌های شما را تمام کند. می‌گویید «رنگ مورد علاقهٔ من ...» و او می‌گوید «آبی». چرا آبی گفت و نگفت «ماشین»؟ چون در تمام عمرش هزاران بار شنیده که بعد از این جمله یک رنگ می‌آید، نه یک وسیلهٔ نقلیه. او قاعدهٔ دستور زبان را حفظ نکرده — فقط آمار را از تجربه بلد است. یک LLM در اصل یک ماشین تکمیل جمله است. متنی به آن می‌دهید (به آن متن پرامپت می‌گویند) و او سعی می‌کند ادامه‌اش را بنویسد. همین. تمام کارهای خارق‌العاده‌ای که می‌بینید، از همین یک قابلیت ساده بیرون می‌آید. توکن: واحد شمارش دنیای مدل‌ها مدل با «کلمه» کار نمی‌کند و با «حرف» هم کار نمی‌کند. واحد کارش چیزی بین این دو است که به آن توکن می‌گویند. کار شکستن متن به توکن را توکن‌سازی (tokenization) می‌نامند، و مجموعهٔ همهٔ توکن‌هایی که یک مدل می‌شناسد واژگان (vocabulary) آن مدل است. با حدود ۳۲ هزار قطعهٔ لگو می‌توانید میلیون‌ها چیز بسازید. اگر واحد ساخت را «حرف» بگذاریم، قطعات خیلی ریزند و ساختن هر چیزی طول می‌کشد. اگر «کلمه» بگذاریم، باید برای هر کلمهٔ فارسی و انگلیسی و هر کلمهٔ تازه‌ساخته یک قطعهٔ جدا داشته باشیم — انبار بی‌نهایت می‌شود. توکن حد وسط است: مثلاً کلمهٔ cooking به دو قطعهٔ cook و ing شکسته می‌شود؛ هر دو قطعه معنی دارند و قابل استفادهٔ مجددند. همین ترفند باعث می‌شود مدل با کلمه‌ای که تا حالا ندیده هم کنار بیاید. کلمهٔ ساختگی chatgpting را می‌شکند به chatgpt و ing و حدس می‌زند که احتمالاً فعل است. برای متن انگلیسی، هر توکن به‌طور میانگین حدود سه‌چهارم یک کلمه است. یعنی ۱۰۰ توکن تقریباً برابر ۷۵ کلمه. این را یادتان باشد، چون بعداً هزینهٔ API و محدودیت طول متن، هر دو بر حسب توکن حساب می‌شوند نه کلمه. برای فارسی نسبت بدتر است: چون بیشتر مدل‌ها عمدتاً روی متن انگلیسی آموزش دیده‌اند، متن فارسی به توکن‌های بیشتری شکسته می‌شود — یعنی همان جمله برای شما گران‌تر تمام می‌شود. دو نوع مدل زبانی از این به بعد هرجا فقط بگوییم «مدل زبانی»، منظورمان نوع خودبازگشتی است — چون امروز تقریباً تمام کارهای تولید متن با همین نوع انجام می‌شود. چرا این یکی منفجر شد و بقیه نه؟ مدل زبانی فقط یکی از ده‌ها الگوریتم یادگیری ماشین است. مدل تشخیص چهره داریم، مدل پیش‌بینی آب‌وهوا داریم، مدل پیشنهاد فیلم داریم. پس چرا لحظهٔ انفجاری هوش مصنوعی با مدل زبانی رقم خورد؟ جواب در یک کلمه است: خودنظارتی (self-supervision). روش سنتی، نظارت‌شده (supervised) بود: باید هزاران نمونه را دستی برچسب می‌زدید تا مدل یاد بگیرد. می‌خواهید مدل تقلب بانکی را تشخیص دهد؟ باید روی هزاران تراکنش دستی بنویسید «تقلب» یا «سالم». فرض کنید برچسب زدن هر عکس ۵ سنت آب بخورد. برای یک میلیون عکس می‌شود ۵۰ هزار دلار. اگر بخواهید دو نفر مستقل هر عکس را برچسب بزنند تا کیفیت را چک کنید، دو برابر. و این برای «سگ» و «گربه» است که هر کسی بلد است. حالا تصور کنید بخواهید یک رادیولوژیست هزاران عکس سی‌تی‌اسکن را برچسب بزند — عملاً غیرممکن. خودنظارتی این گلوگاه را کنار می‌زند. ایدهٔ نابغه‌وارش این است: خود متن، برگهٔ پاسخ خودش است. هیچ انسانی لازم نیست چیزی برچسب بزند. یک جملهٔ ساده را ببینید. از همین یک جمله، مدل به‌طور خودکار چند نمونهٔ آموزشی می‌سازد: آن و دو توکن ویژه‌اند: BOS علامت شروع متن و EOS علامت پایان. دومی خیلی مهم‌تر از آن چیزی است که به‌نظر می‌رسد — همین توکن است که به مدل می‌گوید کِی حرفش را تمام کند. بدون آن، مدل تا ابد ادامه می‌دهد. متن همه‌جا هست: کتاب، ویکی‌پدیا، وبلاگ، کامنت اینترنتی. وقتی برای آموزش هیچ برچسب دستی لازم نباشد، حجم دادهٔ آموزشی عملاً بی‌نهایت می‌شود. و وقتی داده بی‌نهایت شد، می‌شود مدل را بزرگ و بزرگ‌تر کرد. این‌طور بود که «مدل زبانی» تبدیل شد به «مدل زبانی بزرگ». خودنظارتی با بدون‌نظارت (unsupervised) فرق دارد. در خودنظارتی برچسب وجود دارد، منتها از خود داده استخراج می‌شود. در بدون‌نظارت اصلاً برچسبی در کار نیست. چقدر بزرگ، بزرگ است؟ اندازهٔ مدل را با تعداد پارامترهایش می‌سنجند. پارامتر یعنی یک عدد داخل مدل که در جریان آموزش تنظیم می‌شود — مثل یک پیچ تنظیم روی یک دستگاه غول‌پیکر. هرچه پیچ بیشتر، ظرفیت یادگیری بیشتر (البته نه همیشه). معیار «بزرگ» مدام عوض می‌شود. در سال ۲۰۱۸ مدلی با ۱۱۷ میلیون پارامتر بزرگ حساب می‌شد؛ یک سال بعد همان عدد کوچک شد. امروز صد میلیارد پارامتر بزرگ است، و احتمالاً چند سال دیگر همین هم کوچک به‌نظر می‌رسد. مدل بزرگ‌تر ظرفیت یادگیری بیشتری دارد، پس برای اینکه آن ظرفیت هدر نرود به دادهٔ بیشتری نیاز دارد. می‌توانید مدل غول‌پیکری را روی دادهٔ کم آموزش دهید، ولی آن‌وقت پول و برق را دور ریخته‌اید — با مدل کوچک‌تر هم به همان نتیجه می‌رسیدید. قدم آخر: از LLM به مدل پایه مدل زبانی فقط متن می‌فهمد. ولی ما آدم‌ها دنیا را فقط با زبان درک نمی‌کنیم — می‌بینیم، می‌شنویم، لمس می‌کنیم. برای اینکه هوش مصنوعی در دنیای واقعی کار کند، باید فراتر از متن برود. مدلی که با بیش از یک نوع داده کار می‌کند چندوجهی (multimodal) نام دارد. اگر چندوجهی و مولد باشد، به آن LMM می‌گویند. وقتی این مدل‌ها هم بزرگ شدند و هم چندوجهی، اصطلاح LLM دیگر کافی نبود. اینجا بود که نام مدل پایه یا FM باب شد. مثل فونداسیون یک ساختمان. فونداسیون به‌تنهایی خانه نیست، ولی روی یک فونداسیون خوب می‌شود خانه، مغازه یا مدرسه ساخت. مدل پایه هم به‌تنهایی محصول نیست؛ زیرساختی است که ده‌ها محصول مختلف روی آن بنا می‌شود. این کلمه هر دو معنی را با هم می‌رساند: بنیادی بودن و قابل بنا شدن. سه راه برای رام کردن مدل مدل پایه از جعبه که بیرون می‌آید همه‌منظوره است. برای کار شما «خوب» است ولی «عالی» نیست. فرض کنید می‌خواهید برای یک فروشگاه، توضیح محصول بنویسد. مدل متن درستی تولید می‌کند، اما لحن برند شما را ندارد و پر از کلیشه‌های تبلیغاتی است. سه ابزار برای حل این مشکل دارید. کل باقی این دوره، شرح همین سه‌تاست: همیشه از ساده‌ترین شروع کنید. تطبیق دادن یک مدل آماده با کار شما معمولاً «ده نمونه و یک آخر هفته» وقت می‌برد، در حالی که ساختن مدل از صفر «یک میلیون نمونه و شش ماه» است. اکثر تیم‌ها مستقیم سراغ تنظیم دقیق می‌روند در حالی که یک پرامپت بهتر مشکلشان را حل می‌کرد. گلوگاه اصلی، داده بود نه الگوریتم. وقتی هر متن موجود در اینترنت بدون هیچ هزینه‌ای به دادهٔ آموزشی تبدیل شد، مقیاس‌دادن به مدل‌ها ممکن شد — و بقیهٔ ماجرا از همان مقیاس بیرون آمد. مدل خودبازگشتی فقط متن قبل را می‌بیند، پس نمی‌تواند از قرینهٔ بعد از جای خالی استفاده کند. مدل ماسک‌دار دقیقاً برای همین ساخته شده: دیدن دوطرفهٔ جمله. به همین دلیل برای دسته‌بندی و تحلیل احساسات هم بهتر است. دقیقاً برای همین است که یک متن انگلیسی و ترجمهٔ فارسی‌اش تعداد توکن متفاوتی دارند — و چون قیمت‌گذاری بر اساس توکن است، همین موضوع مستقیماً روی هزینهٔ محصول شما اثر می‌گذارد. قبل از اینکه چیزی بسازید، باید حس درستی از توانایی‌ها و ناتوانی‌های این ابزار داشته باشید. این درس نقشهٔ کاربردهاست. فهرست کردن تمام کاربردهای ممکن مدل‌های پایه عملاً شدنی نیست؛ هر روز چیز تازه‌ای اضافه می‌شود. ولی الگوها محدودند. اگر الگوها را بشناسید، می‌توانید فرصت‌های امروز را ببینید و حدس بزنید فردا چه می‌آید. هشت دستهٔ اصلی قاعدهٔ سرانگشتی: کجا خوب است، کجا نه یک پژوهش معروف، شغل‌ها را بر اساس «میزان در معرض بودن» نسبت به هوش مصنوعی رتبه‌بندی کرده است. تعریفشان دقیق است: یک کار در معرض است اگر هوش مصنوعی بتواند زمان انجامش را دست‌کم نصف کند. نتیجه، الگوی روشنی دارد. شغل‌هایی با بیشترین در معرض بودن: مترجم، پژوهشگر نظرسنجی، نویسنده، کارشناس روابط عمومی، حسابدار مالیاتی، طراح وب. شغل‌هایی با کمترین: آشپز، سنگ‌تراش، ورزشکار. هرجا کار اصلی جابه‌جا کردن نماد و متن باشد — کلمه، عدد، کد، قرارداد — هوش مصنوعی قوی است. هرجا کار اصلی دست بردن در دنیای فیزیکی باشد، تقریباً بی‌فایده است. این ساده‌ترین فیلتری است که می‌توانید روی هر ایده‌ای بگذارید. دو چیزی که باید حواستان باشد ساختن یک دموی چشم‌گیر با مدل‌های پایه آسان است. ساختن محصولی که واقعاً کار کند، سخت است. یک تیم بزرگ گزارش داده که یک ماه طول کشید تا به ۸۰٪ کیفیت مطلوب برسد — و چهار ماه دیگر تا از ۹۵٪ رد شود. به این پدیده چالش آخرین مایل می‌گویند: مسیر صفر تا شصت آسان است، شصت تا صد کمرشکن. ورود آسان یعنی خروج هم آسان است. اگر ساختنش برای شما راحت بود، برای رقیب هم راحت است. بدتر: اگر خودِ مدل‌های پایه قوی‌تر شوند، ممکن است لایه‌ای که شما ساخته‌اید کلاً بی‌معنی شود. اپلیکیشنی که فقط PDF را تحلیل می‌کند، با نسخهٔ بعدی مدل که خودش PDF می‌خواند، بی‌فایده می‌شود. در برابر این، سه نوع مزیت رقابتی وجود دارد: فناوری، داده و دسترسی به کاربر. با مدل‌های پایه، فناوری تقریباً برای همه یکسان شده. دسترسی به کاربر معمولاً دست شرکت‌های بزرگ است. پس چیزی که برای یک تیم کوچک واقعاً می‌ماند، داده است — به‌ویژه دادهٔ استفادهٔ کاربران واقعی شما. به همین دلیل است که در فصل ۱۰ یک فصل کامل روی جمع‌آوری بازخورد کار می‌کنیم. این دقیقاً جایی است که اکثر پروژه‌ها شکست می‌خورند: دمو در یک آخر هفته آماده می‌شود و تیم فکر می‌کند کار تمام است، در حالی که هشتاد درصد زمان واقعی پروژه هنوز شروع نشده. کار با نماد و متن، زمین بازی مدل‌های پایه است. سه گزینهٔ دیگر نیاز به حضور فیزیکی دارند — دقیقاً همان مرزی که در این درس دیدیم. وسوسه‌انگیز است که مستقیم بپرید سر کد. اگر برای یادگیری و تفریح است، حتماً بپرید. اگر قرار است محصول واقعی بسازید، این درس جلوی هدررفتن ماه‌ها وقتتان را می‌گیرد. سؤال اول: اصلاً چرا؟ ساختن یک اپلیکیشن هوش مصنوعی، مثل هر تصمیم کسب‌وکاری دیگر، پاسخی است به یک ریسک یا یک فرصت. سه سطح انگیزه وجود دارد، از پرفشارترین تا آرام‌ترین: بقا: اگر این کار را نکنم، رقیبی که هوش مصنوعی دارد مرا از دور خارج می‌کند. رایج در کارهای مبتنی بر پردازش سند و اطلاعات — تحلیل مالی، بیمه — و کارهای خلاقانه مثل تبلیغات و طراحی وب. سود و بهره‌وری: اگر این کار را نکنم، فرصت بهتر شدن را از دست می‌دهم. انگیزهٔ اکثر شرکت‌ها همین است. نترسیدن از جاماندن: هنوز نمی‌دانم کجای کارم به درد می‌خورد، ولی نمی‌خواهم عقب بمانم. اگر توانش را دارید، بد نیست — ولی بدانید که همین است. اگر هوش مصنوعی برای کسب‌وکارتان تهدید بقا است، احتمالاً باید خودتان بسازید — نه اینکه آن را به رقیب برون‌سپاری کنید. اما اگر فقط برای بهره‌وری است، گزینه‌های آمادهٔ زیادی هست که وقت و پول کمتری می‌برند و نتیجهٔ بهتری می‌دهند. نقش هوش مصنوعی در محصول را مشخص کنید سه محور وجود دارد که هر کدام مستقیماً روی سختی کار و سطح کیفیتی که لازم دارید اثر می‌گذارند: انسان کجای کار است؟ این سؤال را تیم‌ها معمولاً دیر از خودشان می‌پرسند. برای یک چت‌بات پشتیبانی، سه حالت کاملاً متفاوت وجود دارد: هوش مصنوعی چند پاسخ پیشنهاد می‌دهد و انسان انتخاب و ویرایش می‌کند. هوش مصنوعی فقط به سؤال‌های ساده جواب می‌دهد و بقیه را به انسان ارجاع می‌دهد. هوش مصنوعی مستقیماً به همه جواب می‌دهد بدون دخالت انسان. دخالت دادن انسان در تصمیم‌گیری هوش مصنوعی را انسان در حلقه (human-in-the-loop) می‌نامند. نکتهٔ مهم این است که این نقش قرار نیست ثابت بماند — قرار است به‌تدریج جلو برود. موفقیت را عددی تعریف کنید این مهم‌ترین قسمت این درس است. تا وقتی نتوانید بگویید «موفقیت یعنی این عدد به اینجا برسد»، نمی‌دانید کِی کار تمام شده و کِی باید بس کنید. دو دستهٔ متفاوت سنجه لازم دارید: سنجه‌های کسب‌وکار — چه درصدی از پیام‌ها خودکار شود؟ چقدر سریع‌تر پاسخ دهیم؟ چقدر نیروی انسانی صرفه‌جویی شود؟ آستانهٔ سودمندی — یعنی «چقدر خوب، یعنی به‌اندازهٔ کافی خوب برای اینکه جلوی کاربر بگذاریمش». آستانهٔ سودمندی معمولاً از چند گروه سنجه تشکیل می‌شود: کیفیت پاسخ‌ها، تأخیر (شامل TTFT و TPOT و زمان کل)، هزینهٔ هر درخواست، و گاهی مواردی مثل انصاف و تفسیرپذیری. اگر همین حالا همهٔ درخواست‌های مشتریان شما را آدم‌ها با میانگین یک ساعت جواب می‌دهند، هر چیزی سریع‌تر از یک ساعت پیشرفت است. اما اگر رقیبتان در دو ثانیه جواب می‌دهد، پنج ثانیه فاجعه است. تأخیر را همیشه نسبت به وضعیت فعلی بسنجید، نه نسبت به یک عدد آرمانی. برنامهٔ مرحله‌ای و نگهداری بعد از تعیین هدف، باید بدانید از کجا شروع می‌کنید. اول مدل‌های موجود را ارزیابی کنید. اگر هدفتان خودکارسازی ۶۰٪ تیکت‌هاست و مدل آماده همین حالا ۳۰٪ را می‌زند، مسیر شما خیلی کوتاه‌تر از حالتی است که از صفر شروع کند. بعد از ارزیابی ممکن است بفهمید منابعی که برای رسیدن به آستانهٔ سودمندی لازم است، از ارزشی که برمی‌گرداند بیشتر است. آن‌وقت تصمیم درست این است که پروژه را کنار بگذارید. این شکست نیست؛ این همان کاری است که ارزیابی برایش وجود دارد. و کار با رسیدن به هدف تمام نمی‌شود. این حوزه با سرعت عجیبی تغییر می‌کند و ساختن روی مدل‌های پایه یعنی سوار شدن بر همین قطار سریع. خیلی از تغییرات خوبند — طول متن قابل پردازش بیشتر می‌شود، کیفیت بالا می‌رود، قیمت‌ها پایین می‌آید. ولی حتی تغییر خوب هم اصطکاک ایجاد می‌کند: تصمیم می‌گیرید مدل را خودتان میزبانی کنید چون ارزان‌تر است؛ سه ماه بعد ارائه‌دهنده‌ها قیمتشان را نصف می‌کنند و انتخاب شما گران‌ترین گزینه می‌شود. روی یک راه‌حل شرکت ثالث سرمایه‌گذاری می‌کنید و زیرساختتان را دورش می‌چینید؛ آن شرکت سرمایه جذب نمی‌کند و تعطیل می‌شود. مدل جدیدی می‌آید که بهتر است، ولی پرامپت‌های شما با آن همان جواب را نمی‌دهند — و بدون زیرساخت نسخه‌بندی و ارزیابی، اصلاً نمی‌فهمید بهتر شده یا بدتر. همان جملهٔ آخر، دلیل وجود فصل‌های ۳ و ۴ این دوره است. زیرساخت ارزیابی و نسخه‌بندی، کاری نیست که «بعداً» انجام دهید. همان چیزی است که به شما اجازه می‌دهد بدون ترس، چیزها را عوض کنید. بدون این عدد، یا محصول نیم‌بند را زود بیرون می‌دهید و اعتماد کاربر را می‌سوزانید، یا تا ابد دنبال کمال می‌گردید و هیچ‌وقت منتشر نمی‌کنید. چون کاربر درخواستش نکرده، پیشنهاد بی‌کیفیت حس مزاحمت می‌دهد — پس سطح کیفیت باید بالاتر باشد. در عوض چون منتظر نیست، می‌شود از قبل محاسبه‌اش کرد و تأخیر مسئلهٔ اصلی نیست. هر روز ده ابزار تازه معرفی می‌شود و آدم حس می‌کند عقب مانده است. راه نجات این است که به‌جای دنبال کردن ابزارها، ساختار زیرینشان را بفهمید. هر اپلیکیشن هوش مصنوعی، هر قدر ساده یا پیچیده، از سه لایه ساخته شده است. معمولاً از بالا شروع می‌کنید و فقط در صورت نیاز پایین می‌روید. چه چیزی عوض شد، چه چیزی نه نکتهٔ جالب اینجاست: با آمدن مدل‌های پایه، لایهٔ بالا منفجر شد — تعداد ابزارهای توسعهٔ اپلیکیشن در یک سال چند برابر شد. اما لایهٔ زیرساخت تقریباً همان ماند. دلیلش روشن است: مدل‌ها و اپلیکیشن‌ها عوض شده‌اند، ولی نیاز به مدیریت منابع، سرویس‌دهی و پایش همان چیزی است که همیشه بوده. خیلی از اصول ساخت اپلیکیشن هوش مصنوعی عوض نشده‌اند. هنوز باید سنجهٔ کسب‌وکار را به سنجهٔ فنی ترجمه کنید. هنوز باید منظم آزمایش کنید. هنوز باید حلقهٔ بازخورد بسازید. یعنی یک دهه تجربهٔ جمعی مهندسان یادگیری ماشین هنوز به کار می‌آید — و شما لازم نیست همه‌چیز را از نو کشف کنید. مهندسی هوش مصنوعی در برابر مهندسی یادگیری ماشین سه تفاوت اصلی وجود دارد و هر سه مهم‌اند: مهندسی هوش مصنوعی کمتر دربارهٔ ساختن مدل است و بیشتر دربارهٔ تطبیق دادن و ارزیابی کردن آن. به همین دلیل است که از ده فصل این دوره، دو فصل کامل فقط به ارزیابی اختصاص دارد. تطبیق مدل: دو خانوادهٔ بزرگ همهٔ روش‌های تطبیق، بر اساس یک سؤال ساده به دو دسته تقسیم می‌شوند: آیا وزن‌های مدل را عوض می‌کنیم یا نه؟ چهار کلمه که مدام قاطی می‌شوند این چهار اصطلاح را همه‌جا می‌بینید و تفاوتشان اغلب توضیح داده نمی‌شود: آموزش همیشه وزن‌ها را عوض می‌کند — ولی هر تغییری در وزن‌ها آموزش نیست. کوانتیزیشن وزن‌ها را تغییر می‌دهد ولی چیزی یاد نمی‌گیرد؛ فقط همان دانش را در فضای کمتری می‌چپاند. و دقیقاً به همین دلیل، خروجی باز بودن مدل‌های امروز، ارزیابی را به بزرگ‌ترین چالش این حرفه تبدیل کرده است. سنجیدن «تقلب/سالم» آسان است؛ سنجیدن «این پاسخ خوب بود؟» نیست. این تمایز در فصل ۷ به‌کارتان می‌آید: کوانتیزیشن فقط بازنمایی عددی همان دانش را فشرده می‌کند. مثل ذخیره کردن یک عکس با کیفیت پایین‌تر — تصویر همان است، فقط جای کمتری می‌گیرد. وقت کد است. در این درس اسکلت محصولی را می‌سازیم که تا فصل ۱۰ همراهمان خواهد بود — و مهم‌ترین تصمیم معماری کل دوره را می‌گیریم. ذهن‌یار یک دستیار پرسش‌وپاسخ فارسی است که به سؤال‌های شما دربارهٔ همین دوره جواب می‌دهد. منبع دانشش، درس‌نامه‌های همین پنل است. یعنی هرچه بیشتر جلو بروید، دستیارتان هم باهوش‌تر می‌شود. در فصل ۱ فقط اسکلت را می‌سازیم: یک لایهٔ تمیز که با «مدل» حرف می‌زند. هنوز هیچ هوشی در کار نیست — و این عمدی است. کدمان هرگز مستقیماً با یک ارائه‌دهندهٔ خاص حرف نمی‌زند. بین کد ما و مدل، یک لایهٔ واسط به نام provider می‌گذاریم. امروز این لایه به یک مدل تقلبی و آفلاین وصل است؛ فردا با عوض کردن یک خط به Ollama یا OpenAI وصل می‌شود، بدون اینکه حتی یک خط از بقیهٔ پروژه عوض شود. مثل پریز برق خانه. لامپ، یخچال و شارژر همه یک شکل پریز دارند. اگر هر وسیله پریز خودش را می‌خواست، هر بار که وسیله‌ای عوض می‌کردید باید دیوار را می‌کندید. در درس قبل خواندیم که «مدل بهتر که می‌آید، پرامپت‌های شما با آن همان جواب را نمی‌دهند». لایهٔ provider همان پریز استاندارد است که جابه‌جایی را از فاجعه به یک خط تغییر تبدیل می‌کند. اگر تا حالا یک خط کد هم ننوشته‌اید، درست آمده‌اید. قدم‌به‌قدم می‌رویم: کدام برنامه‌ها را نصب کنید، کدام پوشه‌ها و فایل‌ها را بسازید، چه کدی را کجا بچسبانید، و بعد از هر فایل، تک‌تک خط‌هایش را به زبان ساده توضیح می‌دهیم. لازم نیست همه‌چیز را از همان بار اول کامل بفهمید؛ کافی است بدانید هر تکه چه کاری می‌کند. کار را از بالا به پایین و بدون جا انداختن هیچ قدمی انجام دهید. قدم ۰ — سه ابزاری که لازم دارید پایتون را نصب کنید از سایت python.org نسخهٔ ۳٫۱۲ را برای ویندوز دانلود و اجرا کنید. در اولین صفحهٔ نصب، تیک گزینهٔ Add python.exe to PATH را بزنید — این مهم‌ترین تیک کل نصب است. بدون آن، ویندوز دستور python را نمی‌شناسد. VS Code را نصب کنید از code.visualstudio.com دانلود و نصب کنید. بعد از باز کردنش، از نوار سمت چپ آیکون چهارمربعی (Extensions) را بزنید، کلمهٔ Python را جست‌وجو کنید و افزونهٔ Python ساخت Microsoft را نصب کنید. این افزونه کد پایتون را رنگی می‌کند و خطاها را زیرش خط قرمز می‌کشد. یک پوشهٔ خالی برای پروژه بسازید هر جای کامپیوترتان که دوست دارید — مثلاً داخل Documents — یک پوشهٔ خالی بسازید و اسمش را بگذارید zehnyar-project. اسم پوشه انگلیسی و بدون فاصله باشد تا بعداً در پاورشل دردسر نداشته باشید. تمام پروژهٔ این دوره، فصل به فصل، داخل همین یک پوشه ساخته می‌شود. پوشه را در VS Code باز کنید از منوی File گزینهٔ Open Folder... را بزنید و پوشهٔ zehnyar-project را انتخاب کنید. اگر پرسید «به نویسندگان این پوشه اعتماد دارید؟» گزینهٔ Yes را بزنید. ستون سمت چپ (Explorer) فعلاً خالی است — قرار است خودتان پرش کنید. پاورشل را داخل VS Code باز کنید از منوی Terminal گزینهٔ New Terminal را بزنید (یا کلید Ctrl را نگه دارید و کلید بالای Tab را بزنید). یک پنجرهٔ دستور پایین صفحه باز می‌شود که خودش در پوشهٔ پروژه است. همهٔ دستورهای این درس را همین‌جا تایپ می‌کنید و بعد از هر کدام Enter می‌زنید. قدم ۱ — محیط مجازی پایتون محیط مجازی یعنی یک جعبهٔ جدا داخل پوشهٔ پروژه که پایتون و کتابخانه‌های همین پروژه در آن قرار می‌گیرند و با بقیهٔ سیستم شما قاطی نمی‌شوند. اول مطمئن شوید پایتون درست نصب شده. در پاورشل بزنید: باید چیزی شبیه Python 3.12.10 ببینید. اگر پیغام «is not recognized» آمد، پایتون نصب نشده یا تیک Add python.exe to PATH را نزده‌اید: پایتون را دوباره نصب کنید و این بار آن تیک را بزنید، بعد VS Code را ببندید و دوباره باز کنید. حالا محیط مجازی را بسازید. این دستور چند ثانیه طول می‌کشد و بعدش پوشه‌ای به اسم .venv در Explorer ظاهر می‌شود (نقطهٔ اول اسم یعنی پوشهٔ «سیستمی»؛ لازم نیست داخلش کاری بکنید): حالا مطمئن شوید پایتونِ داخل محیط مجازی کار می‌کند: باید چیزی شبیه Python 3.12.10 ببینید. چون می‌خواهیم دقیقاً پایتونِ داخل جعبهٔ این پروژه اجرا شود، نه هر پایتون دیگری که روی سیستم است. این مسیر یعنی: «از پوشهٔ .venv برو داخل Scripts و برنامهٔ python.exe را اجرا کن». اگر خطای «is not recognized» دیدید، یعنی پاورشل در پوشهٔ پروژه نیست یا محیط مجازی ساخته نشده — قدم ۰ بند ۵ و قدم ۱ را دوباره انجام دهید. قدم ۲ — اسکلت پوشه‌ها و فایل‌ها پوشهٔ پروژهٔ شما در پایان این درس دقیقاً این شکل را دارد (به‌جز .venv که از قدم قبل دارید). هر خط یک فایل یا پوشه است؛ توضیح هر کدام جلویش آمده: پایتون پوشه‌ای را «بسته» (package) حساب می‌کند که داخلش فایلی به اسم __init__.py باشد — حتی اگر کاملاً خالی باشد. بدون این فایل، دستوری مثل from zehnyar.core.assistant import Zehnyar نمی‌تواند پوشه‌ها را پیدا کند و خطای ModuleNotFoundError می‌گیرید. دقت کنید: دو خط زیرین قبل و بعد از کلمهٔ init هست (__init__). همهٔ پوشه‌ها و فایل‌های خالی را با دو دستور زیر یک‌جا می‌سازید. هر دو را در پاورشل بزنید (اگر پیغام قرمز «already exists» دیدید نگران نشوید؛ یعنی آن فایل از قبل بوده و دست نخورده): برای هر فایلی که در قدم‌های بعد می‌بینید: در ستون Explorer سمت چپ VS Code روی پوشهٔ مقصد راست‌کلیک کنید و New File... را بزنید، اسم فایل را دقیقاً همان‌طور که بالای کادر کد نوشته شده تایپ کنید (مثلاً base.py) و Enter بزنید. بعد دکمهٔ «کپی» بالای کادر کد را بزنید، داخل فایل خالی Ctrl+V کنید و با Ctrl+S ذخیره کنید. اگر فایل از قبل هست، محتوایش را کامل با کد این صفحه عوض کنید (Ctrl+A بعد Ctrl+V). پایتون با تورفتگی (فاصلهٔ اول خط) می‌فهمد کدام خط‌ها مال کدام بخش‌اند. چهار فاصله یعنی «این خط داخل بخش بالایی است». اگر هنگام چسباندن، فاصله‌ها به هم بریزد، خطای IndentationError می‌گیرید. همیشه با دکمهٔ «کپی» کپی کنید، نه با انتخاب دستی متن. قدم ۳ — فارسی کردن پاورشل اولین فایل، کوچک‌ترین است. پاورشل ویندوز به‌طور پیش‌فرض حروف فارسی را نمی‌شناسد و اگر بخواهیم با print جملهٔ فارسی چاپ کنیم، برنامه با خطای UnicodeEncodeError می‌افتد. این فایل آن را درست می‌کند: قدم ۴ — قرارداد مشترک اول باید بگوییم «هر مدلی، هر که باشد، باید بتواند این کار را بکند». این همان قرارداد است. در پایتون به این کار کلاس پایه می‌گویند. دو مفهوم در این فایل هست که احتمالاً برایتان تازه است: @dataclass — یک میان‌بر پایتون برای ساختن کلاسی که فقط داده نگه می‌دارد. به‌جای نوشتن ده خط کد تکراری، فقط نام و نوع فیلدها را می‌نویسید. ABC و @abstractmethod — یعنی «این کلاس فقط یک قالب است، نمی‌شود مستقیم ازش نمونه ساخت؛ هر کس ارثش را می‌برد باید این متد را بنویسد». این همان چیزی است که قرارداد را الزام‌آور می‌کند. در تابع‌های داخل کلاس، اولین ورودی همیشه self است و یعنی «خودِ همین شیء». مثلاً self.model یعنی «مدلِ همین ارائه‌دهنده». لازم نیست موقع صدا زدن تابع، self را بدهید؛ پایتون خودش می‌گذارد. چون در درس قبل خواندیم که آستانهٔ سودمندی از کیفیت، تأخیر و هزینه تشکیل می‌شود. اگر از همین اولین روز این سه را اندازه نگیرید، در فصل ۴ که بخواهید مدل‌ها را مقایسه کنید دستتان خالی است. سنجه‌ها را از روز اول جمع کنید، حتی وقتی هنوز به دردتان نمی‌خورند. قدم ۵ — ارائه‌دهندهٔ آفلاین حالا اولین پیاده‌سازی واقعی. این یکی هیچ هوشی ندارد: بر اساس کلمات کلیدی جواب می‌دهد. ولی قطعی است (هر بار همان ورودی، همان خروجی) و همین آن را برای تست و یادگیری عالی می‌کند. قدم ۶ — تنظیمات و کارخانهٔ انتخاب این فایل کوچک، همان «پریز استاندارد» است. بقیهٔ پروژه فقط get_provider() را صدا می‌زند و اصلاً نمی‌داند پشتش چه خبر است. آن print("[هشدار] ...") و برگشتن به mock، عمدی است. اگر Ollama بالا نباشد، پروژه کرش نمی‌کند — با یک هشدار به حالت آفلاین برمی‌گردد. برای یک محیط آموزشی این حیاتی است: هیچ‌وقت نباید یادگیری شما به‌خاطر یک سرویس خاموش متوقف شود. در محصول واقعی اسم این الگو تنزل آرام (graceful degradation) است و در فصل ۱۰ جدی‌تر سراغش می‌رویم. قدم ۷ — دو ارائه‌دهندهٔ اختیاری کارخانهٔ قدم قبل به دو فایل دیگر هم اشاره می‌کند. تا وقتی mock کار می‌کند به آن‌ها نیازی نیست، ولی باید وجود داشته باشند — وگرنه در تمرین آخر همین درس که provider را عوض می‌کنید، به‌جای هشدار با خطای ModuleNotFoundError روبه‌رو می‌شوید. هر دو را بسازید: قدم ۸ — هستهٔ ذهن‌یار assistant.py فقط کلاس Zehnyar را تعریف می‌کند؛ مثل نقشهٔ یک ماشین است، نه خود ماشین در حال حرکت. برای اینکه واقعاً از آن سؤال بپرسیم، یک فایل جدا لازم داریم که ذهن‌یار را بسازد و صدا بزند: run.py در قدم بعد. قدم ۹ — فایل اجرایی: run.py این آخرین فایل است و همان فایلی است که اجرا می‌کنیم. چهار سؤال از ذهن‌یار می‌پرسد و جواب هر کدام را با سنجه‌هایش چاپ می‌کند. آن را در پوشهٔ projects/ch01_foundation بسازید: قدم ۱۰ — اجرا کنید حالا لحظهٔ حقیقت. این دستور را در پاورشل بزنید: باید خروجی‌ای شبیه این ببینید — پاسخ، به‌همراه سنجه‌های مهندسی: عددهای زمان روی سیستم شما کمی فرق می‌کند؛ این طبیعی است. اگر خطا دیدید می‌توانید همین‌جا هم امتحانش کنید. این آزمایشگاه یک نسخهٔ آماده از همین کد را اجرا می‌کند؛ جوابش را با خروجی پروژهٔ خودتان مقایسه کنید: چه چیزی ساختیم؟ یک قرارداد که هر مدلی باید رعایتش کند (Provider). یک پیاده‌سازی آفلاین و رایگان که همیشه کار می‌کند (MockProvider). یک کارخانه که مدل را بدون دست زدن به بقیهٔ کد عوض می‌کند (get_provider). اندازه‌گیری سنجه‌ها از روز اول: توکن، تأخیر، TTFT، هزینه. یک هسته که در نه فصل بعدی رویش بنا می‌کنیم. این دو کار را خودتان انجام دهید؛ هر دو کوچک‌اند ولی مفهوم را جا می‌اندازند: در zehnyar/providers/mock.py یک ردیف تازه به KNOWLEDGE اضافه کنید. یک خط زیر ردیف ("لایه", "stack", "پشته"): و جوابش، با همان چهار فاصلهٔ اول خط بنویسید: ("پرامپت", "prompt"): و در خط بعد با هشت فاصله، یک تعریف کوتاه داخل نقل‌قول و یک ویرگول در آخر. بعد در projects/ch01_foundation/run.py به فهرست QUESTIONS یک سؤال تازه اضافه کنید: "پرامپت چیست؟", (با ویرگول آخرش). هر دو فایل را ذخیره کنید و دستور قدم ۱۰ را دوباره بزنید. ذهن‌یار حالا جواب پرسش پنجم را بلد است. در zehnyar/config.py، در خط PROVIDER = os.getenv("ZEHNYAR_PROVIDER", "mock") کلمهٔ آخر یعنی "mock" را به "ollama" عوض کنید، ذخیره کنید و دستور قدم ۱۰ را دوباره بزنید. اگر Ollama نصب نکرده‌اید، باید هشدار «Ollama در دسترس نیست — به mock برگشتم» را ببینید و برنامه با mock ادامه بدهد — بدون کرش. این همان تنزل آرام است که ساختیم. بعد از امتحان، آن را به "mock" برگردانید. MockProvider ما احتمال و نمونه‌برداری ندارد — فقط جدول جست‌وجوست. در فصل ۲ یک مدل زبانی واقعی می‌سازیم که روی متن درس‌نامه‌های همین دوره آموزش می‌بیند، و با چشم خودتان می‌بینید که temperature و top-p چطور توزیع احتمال را عوض می‌کنند. در درس ۳ خواندیم که سرعت تغییرات این حوزه، تصمیم امروز را به اشتباه فردا تبدیل می‌کند. این لایه دقیقاً بیمه‌نامهٔ همان ریسک است. این یکی از تفاوت‌های مهندس تازه‌کار و باتجربه است: زیرساخت اندازه‌گیری را قبل از نیاز به آن می‌سازید، نه بعدش. وقتی نیاز پیدا کنید، دیگر دیر است — داده‌های گذشته را که نمی‌شود بازگرداند. یک مدل فقط به اندازهٔ داده‌ای که دیده خوب است. این درس توضیح می‌دهد چرا مدل‌ها در فارسی ضعیف‌ترند، چرا همان جمله برای ما گران‌تر تمام می‌شود، و کِی به یک مدل تخصصی نیاز دارید. قانون اول: آنچه ندیده، بلد نیست اگر در دادهٔ آموزشی یک مدل هیچ متن ویتنامی نباشد، آن مدل نمی‌تواند به ویتنامی ترجمه کند. اگر یک مدل تشخیص تصویر در تمام عمرش فقط عکس حیوان دیده باشد، جلوی عکس یک گلدان درمی‌ماند. این بدیهی به نظر می‌رسد، ولی پیامدش در عمل خیلی جدی است: برای فهمیدن توانایی‌ها و ضعف‌های یک مدل، اول باید بپرسید روی چه چیزی آموزش دیده است. آشپزی را تصور کنید که ده سال فقط در یک پیتزافروشی کار کرده. پیتزایش عالی است و پاستا را هم بد درست نمی‌کند، چون مواد اولیه‌اش شبیه است. ولی اگر از او قورمه‌سبزی بخواهید، یک چیز سبزرنگ تحویلتان می‌دهد که با اعتمادبه‌نفس کامل «قورمه‌سبزی» صدایش می‌کند. مدل‌ها هم همین‌طورند: در کاری که زیاد دیده‌اند درخشانند، در کار نزدیک به آن قابل‌قبول، و در کار ناآشنا — با همان لحن مطمئن — اشتباه. مشکل اینجاست که جمع‌کردن دادهٔ کافی برای یک مدل بزرگ گران است. برای همین سازندگان مدل معمولاً از هر داده‌ای که در دسترس است استفاده می‌کنند، حتی اگر دقیقاً همان چیزی نباشد که لازم دارند. رایج‌ترین منبع، Common Crawl است: یک سازمان غیرانتفاعی که گاه‌به‌گاه اینترنت را می‌خزد — در سال‌های ۲۰۲۲ و ۲۰۲۳ ماهی ۲ تا ۳ میلیارد صفحهٔ وب. گوگل نسخهٔ تمیزشده‌ای از آن به نام C4 ساخته است. کیفیت این داده‌ها؟ هرچه در اینترنت دیده‌اید و ندیده‌اید: خبر جعلی، کلیک‌بیت، تئوری توطئه، تبلیغات. با این حال تقریباً هر مدلی که منبع داده‌اش را اعلام کرده، از نسخه‌ای از همین استفاده کرده — از جمله GPT-3 و Gemini. این رویکرد به مدل‌هایی می‌رسد که در کارهای پرتکرار اینترنت عالی‌اند، ولی نه لزوماً در کاری که برای شما مهم است. اگر کار شما در اینترنت کم پیدا می‌شود — مثلاً قراردادهای حقوقی فارسی — نباید انتظار داشته باشید مدل عمومی در آن بدرخشد. این یکی از اولین چیزهایی است که در ارزیابی (فصل ۳ و ۴) باید بسنجید. چرا همهٔ داده‌ها را نریزیم داخل مدل تا همه‌چیز را بلد شود؟ چون دادهٔ بیشتر یعنی محاسبهٔ بیشتر، و همیشه هم به مدل بهتر نمی‌رسد. یک تیم پژوهشی فقط با ۷ میلیارد توکن کد باکیفیت مدلی با ۱٫۳ میلیارد پارامتر ساخت که در چند آزمون مهم برنامه‌نویسی از مدل‌های خیلی بزرگ‌تر جلو زد. فصل ۸ کاملاً به همین موضوع می‌پردازد. مدل‌ها انگلیسی فکر می‌کنند انگلیسی بر اینترنت حکومت می‌کند. تقریباً نیمی از Common Crawl (۴۵٫۸۸٪) انگلیسی است — هشت برابر زبان دوم، یعنی روسی. زبان‌هایی که سهم کمی از دادهٔ آموزشی دارند را کم‌منبع (low-resource) می‌نامند. یک راه ساده برای سنجیدن این بی‌عدالتی: سهم هر زبان از جمعیت جهان را بر سهمش از Common Crawl تقسیم کنید. در دنیای ایده‌آل این عدد ۱ است. هرچه بزرگ‌تر، آن زبان کم‌نماینده‌تر: نتیجه قابل پیش‌بینی است: مدل‌های عمومی در انگلیسی خیلی بهترند. در آزمون MMLU — چهارده هزار سؤال چهارگزینه‌ای در ۵۷ رشته — GPT-4 در انگلیسی بسیار بهتر از زبان‌های کم‌نماینده عمل کرد. و در یک آزمایش با شش مسئلهٔ ریاضی، GPT-4 مسئله‌ها را به انگلیسی بیش از سه برابر بیشتر از ارمنی یا فارسی حل کرد. وقتی محصولی فارسی می‌سازید، عددهایی که شرکت‌ها برای مدلشان منتشر می‌کنند تقریباً همیشه روی انگلیسی اندازه‌گیری شده‌اند. هرگز فرض نکنید آن کیفیت در فارسی هم تکرار می‌شود. باید خودتان با دادهٔ فارسی بسنجید — دقیقاً کاری که در فصل ۴ برای ذهن‌یار انجام می‌دهیم. کم بودن داده تنها دلیل نیست؛ ساختار یک زبان و فرهنگی که با خودش دارد هم می‌تواند یادگیری‌اش را سخت‌تر کند. رفتار مدل هم ممکن است بین زبان‌ها عوض شود: در یک آزمایش، ChatGPT در انگلیسی از نوشتن ۶ مقاله از ۷ مقالهٔ اطلاعات غلط سر باز زد، ولی همان درخواست‌ها را به چینی هر ۷ بار نوشت. چرا همه‌چیز را به انگلیسی ترجمه نکنیم؟ خیلی‌ها همین کار را می‌کنند: سؤال فارسی را به انگلیسی ترجمه می‌کنند، جواب انگلیسی می‌گیرند و برمی‌گردانند. ولی دو مشکل دارد. اول، برای ترجمهٔ خوب باید مدل همان زبان کم‌منبع را به‌قدر کافی بفهمد. دوم، ترجمه اطلاعات را می‌ریزد. در فارسی بین «تو» و «شما» فرق هست و همین فرق نشان می‌دهد گوینده با چه کسی و با چه نسبتی حرف می‌زند؛ در انگلیسی هر دو می‌شوند you. ترجمهٔ رفت‌وبرگشت، این ظرافت را دور می‌ریزد. همان جمله، قیمت متفاوت در فصل ۱ دیدیم که هزینه و سرعت مدل بر حسب توکن حساب می‌شود. حالا ببینید این برای زبان‌های غیرانگلیسی چه معنایی دارد. پژوهشی روی یک مجموعه‌داده با یک میلیون متن کوتاه که به ۵۲ زبان ترجمه شده بود نشان داد که برای رساندن یک معنای یکسان، میانهٔ طول متن انگلیسی ۷ توکن است، هندی ۳۲ توکن و برمه‌ای ۷۲ توکن. اگر تولید هر توکن در همهٔ زبان‌ها یک‌اندازه زمان ببرد، پاسخ برمه‌ای ده برابر کندتر از انگلیسی است. و چون APIها بر اساس توکن پول می‌گیرند، ده برابر گران‌تر هم هست. کاربر برمه‌ای برای همان خدمت، ده برابر پول می‌دهد و ده برابر منتظر می‌ماند. علت این است که توکنایزر هم مثل خود مدل روی همان دادهٔ عمدتاً انگلیسی ساخته می‌شود. تکه‌های پرتکرار انگلیسی هر کدام یک توکن می‌شوند؛ تکه‌های زبان‌های دیگر به قطعات ریزتر شکسته می‌شوند. این را با چشم خودتان ببینید. توکنایزر زیر را در درس ۷ همین فصل از صفر می‌سازیم. یک تفاوت مهم دارد: روی متن فارسی درس‌های همین دوره آموزش دیده — یعنی دقیقاً برعکس GPT. جملهٔ فارسی را با ترجمهٔ انگلیسی‌اش مقایسه کنید: همان جمله به انگلیسی به حدود سه برابر توکن شکسته می‌شود — بیشترش تقریباً حرف به حرف. چون توکنایزر ما انگلیسی کم دیده، تکه‌های انگلیسی را بلد نیست. این تصویر آینه‌ای همان چیزی است که هر روز برای متن فارسی در مدل‌های انگلیسی‌محور اتفاق می‌افتد. توکنایزر هم مثل مدل، همان است که خورده. برای حل این مشکل، مدل‌های زیادی روی زبان‌های غیرانگلیسی تمرکز کرده‌اند — از ChatGLM و YAYI برای چینی تا CroissantLLM برای فرانسوی، PhoGPT برای ویتنامی و Jais برای عربی. مدل‌های تخصصی مدل‌های همه‌منظوره در طیف عجیبی از حوزه‌ها خوب کار می‌کنند — برنامه‌نویسی، حقوق، علوم، ورزش — و دلیلش ساده است: این حوزه‌ها در دادهٔ آموزشی‌شان بوده‌اند. ولی بعضی کارها هرگز در اینترنت عمومی پیدا نمی‌شوند. کشف دارو با دادهٔ پروتئین، DNA و RNA کار می‌کند — قالب‌های خاص و گران که در وب عمومی نیستند. غربالگری سرطان به تصویر رادیولوژی و fMRI نیاز دارد که به‌خاطر حریم خصوصی به‌سختی به دست می‌آید. برای این کارها باید داده را دست‌چین کرد. مشهورترین نمونه AlphaFold از DeepMind است که روی توالی و ساختار سه‌بعدی حدود صد هزار پروتئین شناخته‌شده آموزش دید. BioNeMo از NVIDIA برای کشف دارو و Med-PaLM2 از گوگل برای پرسش‌های پزشکی، نمونه‌های دیگرند. مدلی که روی طرح‌های معماری آموزش دیده باشد، احتمالاً به معمارها خیلی بیشتر از یک مدل تصویرساز عمومی کمک می‌کند. مدلی که روی نقشه‌های کارخانه آموزش دیده باشد، برای فرایند تولید از ChatGPT بهتر است. هرجا دادهٔ خاصی دارید که در اینترنت نیست، فرصت یک مدل تخصصی هم هست. قانون اول این درس: مدل همان است که خورده. ساختار زبان هم بی‌اثر نیست، ولی کتاب کم‌نمایندگی در داده را دلیل بزرگ می‌داند — زبان‌هایی که در MMLU بدترین نتیجه را گرفتند، دقیقاً همان‌هایی بودند که کمترین سهم را در Common Crawl داشتند. مدل توکن به توکن تولید می‌کند و API بر حسب توکن پول می‌گیرد. پس تعداد توکن بیشتر یعنی هم کندتر، هم گران‌تر. معنی برای مدل مهم نیست؛ تعداد توکن مهم است. توکنایزر BPE تکه‌هایی را به یک توکن تبدیل می‌کند که در دادهٔ آموزشی‌اش زیاد دیده. داده فارسی بوده، پس تکه‌های فارسی ادغام شده‌اند و انگلیسی تکه‌تکه مانده — همان اتفاقی که برعکسش برای فارسی در GPT می‌افتد. لازم نیست ترنسفورمر بسازید، ولی باید بدانید چرا طول متن محدود است، چرا اولین کلمهٔ پاسخ دیرتر از بقیه می‌رسد، و «هفت میلیارد پارامتر» دقیقاً کجای مدل نشسته است. اگر جایی زیادی ریز شد، نگران نباشید و رد شوید. سه چیزی که حتماً باید با خودتان ببرید در کادرهای «نکتهٔ کلیدی» آمده‌اند. باقی را هر وقت لازم شد برگردید و بخوانید. مسئله‌ای که ترنسفورمر حلش کرد برای فهمیدن ترنسفورمر، باید ببینیم قبل از آن چه بود. در سال ۲۰۱۴ معماری‌ای به نام seq2seq معرفی شد که در ترجمهٔ ماشینی و خلاصه‌سازی جهش بزرگی ایجاد کرد. گوگل در ۲۰۱۶ آن را وارد Google Translate کرد و گفت «بزرگ‌ترین بهبود تاریخ ترجمهٔ ماشینی» بوده است. seq2seq دو بخش دارد: یک رمزگذار (encoder) که ورودی را می‌خواند و یک رمزگشا (decoder) که خروجی را می‌نویسد. هر دو از شبکه‌های RNN ساخته شده‌اند که متن را یکی‌یکی و به ترتیب پردازش می‌کنند. رمزگذار در پایان کار، کل ورودی را در یک بردار فشرده می‌کند و رمزگشا فقط همان بردار را می‌بیند. فرض کنید باید به سؤال‌هایی دربارهٔ یک کتاب جواب بدهید. seq2seq مثل کسی است که فقط خلاصهٔ کتاب را خوانده — هرچه در خلاصه نیامده، از دست رفته. ترنسفورمر مثل کسی است که کتاب را جلویش باز گذاشته و برای هر جمله‌ای که می‌نویسد، می‌تواند به هر صفحه‌ای برگردد و نگاه کند. پس seq2seq دو مشکل داشت: کیفیت (فقط خلاصه را می‌دید) و سرعت (اگر ورودی ۲۰۰ توکن بود، باید منتظر می‌ماند تا تک‌تک توکن‌ها به ترتیب پردازش شوند). ترنسفورمر در سال ۲۰۱۷ هر دو را با یک ایده حل کرد: سازوکار توجه (attention)، و کنار گذاشتن کامل RNN. سازوکار توجه را ترنسفورمر اختراع نکرد؛ سه سال قبل‌تر معرفی شده بود و گوگل هم در ۲۰۱۶ آن را کنار seq2seq استفاده می‌کرد. کار بزرگ مقالهٔ ترنسفورمر — با عنوان معروف «توجه، تمام چیزی است که نیاز دارید» — این بود که نشان داد بدون RNN هم می‌شود، و همین سرعت را آزاد کرد. دو مرحلهٔ هر پاسخ ترنسفورمر می‌تواند توکن‌های ورودی را موازی پردازش کند. اما خروجی هنوز توکن به توکن تولید می‌شود، چون هر توکن به توکن قبلی وابسته است. برای همین هر بار که از یک مدل زبانی سؤال می‌پرسید، دو مرحلهٔ کاملاً متفاوت اتفاق می‌افتد: یادتان هست در فصل ۱ دو سنجهٔ تأخیر را از روز اول ذخیره کردیم؟ حالا معنی‌شان روشن است. TTFT عمدتاً به مرحلهٔ پیش‌پردازش بستگی دارد: پرامپت طولانی‌تر یعنی اولین کلمه دیرتر. TPOT به مرحلهٔ رمزگشایی بستگی دارد: سرعت تایپ‌شدن بقیهٔ پاسخ. چون این دو مرحله ذاتاً فرق دارند، بهینه‌سازی‌شان هم فرق دارد — موضوع فصل ۹. سازوکار توجه با یک کتابخانه قلب ترنسفورمر سازوکار توجه است. پشت آن سه نوع بردار هست که با حروف Q و K و V نشانشان می‌دهند. همان تشبیه کتاب را ادامه بدهیم، این بار در یک کتابخانه: پرسش (Query یا Q): کسی که الان دنبال اطلاعات است — یعنی حالت فعلی مدل که می‌خواهد توکن بعدی را بسازد. کلید (Key یا K): برچسب روی هر قفسه. هر توکن قبلی یک کلید دارد. مقدار (Value یا V): خود کتاب داخل قفسه — محتوایی که مدل از آن توکن یاد گرفته است. مدل پرسش را با تک‌تک کلیدها مقایسه می‌کند (از نظر ریاضی با یک ضرب داخلی). هرچه شباهت بیشتر، امتیاز بالاتر. امتیازها با softmax به درصد تبدیل می‌شوند و خروجی، ترکیبی از مقدارهاست — هر کدام به اندازهٔ درصد خودش. لازم نیست این فرمول را حفظ کنید. فقط سه تکه‌اش را بشناسید: Q · Kᵀ همان «مقایسهٔ پرسش با همهٔ کلیدها» است، softmax امتیازها را درصد می‌کند (همان تابعی که در درس ۵ از نزدیک می‌بینیم)، و ضرب در V یعنی «به نسبت درصدها، از محتوای هر قفسه بردار». هر توکن قبلی یک کلید و یک مقدار دارد که باید حساب و در حافظه نگه داشته شود. متن دو برابر طولانی‌تر یعنی دو برابر کلید و مقدار — و چون هر توکن به همهٔ قبلی‌ها نگاه می‌کند، محاسبه حتی سریع‌تر از آن رشد می‌کند. این یکی از دلایل اصلی است که بزرگ‌کردن «پنجرهٔ متن» (context length) مدل‌ها این‌قدر سخت است. نگهداری هوشمندانهٔ این کلیدها و مقدارها (KV) در فصل‌های ۷ و ۹ برمی‌گردد. در عمل توجه همیشه چندسر (multi-head) است: مدل چند «نگاه» موازی دارد که هر کدام می‌تواند روی گروه متفاوتی از توکن‌ها تمرکز کند. مثلاً در Llama 2-7B بردارها ۴۰۹۶ بعدی‌اند و به ۳۲ سر تقسیم می‌شوند؛ هر سر بردارهایی ۱۲۸ بعدی دارد، چون ۴۰۹۶ تقسیم بر ۳۲ می‌شود ۱۲۸. آجرهای ساختمان: بلوک ترنسفورمر یک مدل ترنسفورمر از تعداد زیادی بلوک یکسان روی هم ساخته شده است. به تعداد این بلوک‌ها «تعداد لایه‌های» مدل می‌گویند. هر بلوک دو بخش دارد و کل پشته هم یک لایهٔ ورودی و یک لایهٔ خروجی: ماژول توجه: چهار ماتریس وزن — پرسش، کلید، مقدار و یک ماتریس خروجی. ماژول MLP: چند لایهٔ خطی که بینشان یک تابع فعال‌سازی غیرخطی نشسته. این توابع به‌طرز عجیبی ساده‌اند؛ مثلاً ReLU فقط اعداد منفی را صفر می‌کند: ReLU(x) = max(0, x). لایهٔ امبدینگ (قبل از بلوک‌ها): هر توکن و جایگاهش را به بردار تبدیل می‌کند. اگر مدل فقط ۲۰۴۸ جایگاه بشناسد، در ساده‌ترین حالت طول متنش هم ۲۰۴۸ توکن است. لایهٔ خروجی (بعد از بلوک‌ها): بردار نهایی را به یک لاجیت برای هر توکن واژگان تبدیل می‌کند. از این لاجیت‌ها، نمونه‌برداری توکن بعدی را انتخاب می‌کند — موضوع درس ۵. اندازهٔ مدل را ابعاد همین آجرها تعیین می‌کنند: تعداد بلوک‌ها، بُعد مدل، بُعد لایهٔ MLP و اندازهٔ واژگان. جدول زیر را ببینید: واژگان Llama 3 چهار برابر Llama 2 است. واژگان بزرگ‌تر یعنی تکه‌های بیشتری از زبان‌های مختلف یک توکن می‌شوند — همان مشکل درس قبل، از طرف سازندهٔ مدل. یک نکتهٔ دیگر: طول پنجرهٔ متن روی حافظهٔ مدل اثر دارد، ولی روی تعداد پارامترها نه. آیا ترنسفورمر ابدی است؟ از ۲۰۱۲ تا امروز معماری‌های زیادی آمدند و رفتند: seq2seq چهار سال (۲۰۱۴ تا ۲۰۱۸) بر صحنه بود و GANها کمی بیشتر. ترنسفورمر از ۲۰۱۷ مانده و «چسبنده» از آب درآمده. جایگزین کردنش سخت است، چون از ۲۰۱۷ تا حالا بی‌وقفه بهینه شده و هر رقیبی باید در مقیاسی که مردم برایشان مهم است و روی سخت‌افزاری که مردم دارند بهتر باشد. با این حال چند رقیب جدی پیدا شده‌اند: RWKV: یک مدل مبتنی بر RNN که برخلاف RNNهای قدیمی، آموزشش موازی می‌شود. در تئوری محدودیت طول متن ندارد — هرچند در عمل «بی‌محدودیت بودن» به معنی «خوب بودن در متن طولانی» نیست. SSMها (مدل‌های فضای حالت): خانواده‌ای که در حافظهٔ بلندمدت امیدوارکننده بوده‌اند. پله‌های تکاملشان: S4 (کارآمدتر)، H3 (سازوکاری شبیه توجه ولی ارزان‌تر)، و Mamba که محاسبه‌اش با طول متن خطی رشد می‌کند، نه مثل ترنسفورمر درجهٔ دو. Mamba-3B از ترنسفورمر هم‌اندازه بهتر بود و به ترنسفورمر دو برابر بزرگ‌تر رسید. Jamba: ترکیبی از لایه‌های ترنسفورمر و Mamba. نسخه‌ای با ۵۲ میلیارد پارامتر (که فقط ۱۲ میلیاردش هم‌زمان فعال است) در یک GPU هشتاد گیگابایتی جا می‌شود و تا ۲۵۶ هزار توکن متن را می‌خواند. اگر روزی معماری دیگری جای ترنسفورمر را بگیرد، بعضی ترفندهای این دوره عوض می‌شوند. اما همان‌طور که گذر از مهندسی یادگیری ماشین به مهندسی هوش مصنوعی خیلی از اصول را دست‌نخورده گذاشت، عوض شدن معماری هم رویکردهای بنیادی — ارزیابی، مهندسی پرامپت، بازیابی، حلقهٔ بازخورد — را عوض نمی‌کند. برای همین در این دوره روی همان‌ها سرمایه‌گذاری می‌کنیم. سازوکار توجه اجازه داد مدل هنگام تولید هر کلمه به همهٔ ورودی نگاه کند (کیفیت)، و حذف RNN اجازه داد ورودی موازی پردازش شود (سرعت). خروجی اما هنوز توکن به توکن است. موازی بودن پیش‌پردازش آن را سریع می‌کند ولی رایگانش نمی‌کند: ورودی ده برابر یعنی کار ده برابر قبل از اولین کلمه. به‌علاوه، هر توکن ورودی کلید و مقدار خودش را در حافظه می‌خواهد. پرسش (Q) با کلید (K) هر توکن قبلی مقایسه می‌شود تا معلوم شود چقدر به آن توجه شود؛ بعد از مقدار (V) همان توکن، به همان اندازه برداشته می‌شود. کلید یعنی «این قفسه دربارهٔ چیست». وقتی مدل تازه‌ای منتشر می‌شود، اولین سؤال همه این است: «چند میلیارد پارامتر؟» اینجا یاد می‌گیرید از همین یک عدد چه چیزهایی می‌شود فهمید، چه چیزهایی نمی‌شود، و چرا بزرگ‌تر همیشه بهتر نیست. پارامتر: ظرفیت یادگیری تعداد پارامتر معمولاً ته اسم مدل می‌آید: Llama-13B یعنی نسخه‌ای از خانوادهٔ Llama با ۱۳ میلیارد پارامتر. در یک خانوادهٔ یکسان، نسخهٔ بزرگ‌تر تقریباً همیشه بهتر است، چون ظرفیت یادگیری بیشتری دارد. سازندگان مدل هر سال بهتر یاد می‌گیرند که مدل‌ها را چطور آموزش دهند. نتیجه اینکه Llama 3-8B (سال ۲۰۲۴) در آزمون MMLU حتی از Llama 2-70B (سال ۲۰۲۳) بهتر است — مدلی تقریباً نُه برابر کوچک‌تر. «بزرگ‌تر» فقط در یک نسل معنی دارد. تعداد پارامتر کمک می‌کند منابع لازم را تخمین بزنید. اگر هر پارامتر با ۲ بایت (FP16) ذخیره شود، یک مدل ۷ میلیاردی دست‌کم ۱۴ گیگابایت حافظهٔ GPU فقط برای نگه داشتن وزن‌ها لازم دارد. حافظهٔ واقعی بیشتر است؛ حساب دقیقش در فصل ۷. اگر بدانید کتابخانه‌ای ۷ میلیون جلد کتاب دارد، بدون دیدنش می‌دانید چند قفسه و چند متر مربع جا لازم است. تعداد پارامتر همین کار را برای مدل می‌کند: پیش از دانلود می‌دانید روی لپ‌تاپتان جا می‌شود یا یک سرور ابری لازم دارید. مدل تُنُک و «ترکیب خبرگان» تعداد پارامتر گاهی گمراه‌کننده است. در یک مدل تُنُک (sparse) درصد زیادی از پارامترها صفرند؛ مدل ۷ میلیاردی‌ای که ۹۰٪ آن صفر باشد فقط ۷۰۰ میلیون پارامتر غیرصفر دارد و ارزان‌تر اجرا می‌شود. محبوب‌ترین نوع مدل تنک، ترکیب خبرگان یا MoE است. مدل به چند گروه پارامتر تقسیم می‌شود که هر کدام یک «خبره» است، و برای هر توکن فقط چند خبره فعال می‌شوند. بیمارستانی هشت پزشک متخصص دارد، ولی هر بیمار فقط پیش دو نفر می‌رود. حقوق بیمارستان را هشت نفر می‌گیرند، ولی زمان معطلی هر بیمار به اندازهٔ دو ویزیت است. مدل Mixtral 8x7B دقیقاً همین است: ۴۶٫۷ میلیارد پارامتر در کل (کمتر از ۸ × ۷ = ۵۶ چون بعضی پارامترها مشترک‌اند)، ولی برای هر توکن فقط دو خبره فعال‌اند — یعنی ۱۲٫۹ میلیارد پارامتر. هزینه و سرعتش مثل یک مدل ۱۲٫۹ میلیاردی است. داده را با توکن بشمارید، نه با نمونه مدل بزرگ با دادهٔ کم بی‌فایده است. یک مدل ۱۳ میلیاردی را تصور کنید که فقط روی یک جمله آموزش دیده: «من آناناس دوست دارم». هر مدل کوچکی که داده بیشتری دیده باشد از آن بهتر است. پس اندازهٔ مدل را همیشه کنار اندازهٔ داده‌اش بسنجید. برای مدل زبانی، یک «نمونهٔ آموزشی» می‌تواند یک جمله باشد یا یک کتاب کامل — که ارزششان اصلاً یکی نیست. برای همین داده را با تعداد توکن می‌شمارند. Meta برای هر نسل Llama دادهٔ بزرگ‌تری به کار برد: ۱٫۴ تریلیون توکن برای Llama 1، ۲ تریلیون برای Llama 2 و ۱۵ تریلیون برای Llama 3. مجموعه‌دادهٔ باز RedPajama-v2 سی تریلیون توکن دارد — معادل ۴۵۰ میلیون کتاب یا ۵۴۰۰ برابر کل ویکی‌پدیا. اگر مجموعه‌داده‌ای یک تریلیون توکن داشته باشد و مدل دو بار از اول تا آخرش را ببیند (دو دوره یا epoch)، تعداد توکن آموزشی می‌شود دو تریلیون. مدل‌های بزرگ امروزی معمولاً فقط یک دوره روی داده آموزش می‌بینند. FLOP: واحد هزینه آموزش مدل محاسبه می‌خواهد. شمردن تعداد GPU معیار خوبی نیست چون GPUها با هم خیلی فرق دارند. واحد استاندارد FLOP است: تعداد عملیات اعشاری لازم برای یک کار. مثلاً آموزش GPT-3 با ۱۷۵ میلیارد پارامتر حدود 3.14 × 10²³ FLOP خرج برداشت. FLOPs (با s کوچک، جمع FLOP) یعنی کل محاسبهٔ یک کار. FLOP/s یعنی محاسبه در هر ثانیه — توان یک دستگاه. مشکل اینجاست که FLOP/s را اغلب FLOPS می‌نویسند که تقریباً شبیه FLOPs است. اولی «حجم کار» است، دومی «سرعت کارگر». یک GPU از نوع H100 حداکثر حدود ۶۰ ترافلاپ بر ثانیه کار می‌کند، یعنی روزی حدود 5.2 × 10¹⁸ FLOP. با ۲۵۶ عدد H100 که با تمام ظرفیت و بدون هیچ اشتباهی کار کنند، آموزش GPT-3 حدود ۲۳۶ روز طول می‌کشد. ولی هیچ دستگاهی همیشه با تمام ظرفیت کار نمی‌کند. اگر به ۵۰٪ ظرفیت برسید کارتان خوب است؛ بالای ۷۰٪ عالی. با ۷۰٪ بهره‌وری و ساعتی ۲ دلار برای هر H100، هزینهٔ آموزش GPT-3 از ۴ میلیون دلار بیشتر می‌شود. تعداد پارامتر — نمایندهٔ ظرفیت یادگیری. تعداد توکن آموزشی — نمایندهٔ اینکه مدل واقعاً چقدر یاد گرفته. تعداد FLOP — نمایندهٔ هزینهٔ آموزش. قانون چین‌چیلا: بودجه را درست خرج کنید سه چیز تا اینجا روشن شد: کیفیت مدل به اندازهٔ مدل و داده بستگی دارد؛ هر دو محاسبه می‌خواهند؛ و محاسبه پول است. پس سؤال درست این نیست که «چه مدل بزرگی بسازیم؟» بلکه این است: «با این بودجه، بهترین مدل ممکن چیست؟» مدلی که با یک بودجهٔ ثابت بهترین نتیجه را بدهد، بهینهٔ محاسباتی (compute-optimal) نام دارد. پژوهشگران DeepMind در مقالهٔ معروف به چین‌چیلا بیش از ۴۰۰ مدل — از ۷۰ میلیون تا بیش از ۱۶ میلیارد پارامتر — را روی ۵ تا ۵۰۰ میلیارد توکن آموزش دادند و به یک قاعدهٔ ساده رسیدند: برای آموزش بهینه، تعداد توکن‌های آموزشی باید حدود ۲۰ برابر تعداد پارامترها باشد. مدل ۳ میلیاردی حدود ۶۰ میلیارد توکن می‌خواهد. و این دو باید با هم بزرگ شوند: مدل را دو برابر کردید، داده را هم دو برابر کنید. حالا جدول زیر معنی پیدا می‌کند. ستون آخر را ببینید — قبل از چین‌چیلا، مدل‌های غول‌پیکر با دادهٔ خیلی کمتر از لازم آموزش دیده بودند: با ماشین‌حساب زیر بازی کنید. ببینید با بزرگ‌تر شدن مدل، هر سه عدد مقیاس چطور با هم بالا می‌روند — و از کجا به بعد حتی اجرای مدل روی یک GPU ممکن نیست: قانون چین‌چیلا کیفیت را برای یک بودجهٔ آموزش بهینه می‌کند. ولی در محصول، هزینهٔ اجرا هم هست. سازندگان Llama می‌توانستند با بودجه‌شان مدل‌های بزرگ‌تر و بهتری بسازند، ولی عمداً مدل‌های کوچک‌تر را روی دادهٔ بیشتر آموزش دادند. مدل کوچک‌تر ارزان‌تر اجرا می‌شود و راحت‌تر کار با آن — و همین Llama را این‌قدر محبوب کرد. یک نکتهٔ دیگر هم هست: رسیدن به یک کیفیت ثابت هر سال ارزان‌تر می‌شود (هزینهٔ رسیدن به دقت ۹۳٪ در ImageNet از ۲۰۱۹ تا ۲۰۲۱ نصف شد)، ولی بهتر کردن کیفیت همچنان گران است. درست مثل چالش آخرین مایل فصل ۱: رفتن از ۹۰ به ۹۵ درصد از رفتن از ۸۵ به ۹۰ گران‌تر است. در مدل‌سازی زبان، یک بهبود ظاهراً کوچک در خطای مدل ممکن است ده برابر داده بخواهد — ولی همان بهبود کوچک در کیفیت محصول کاملاً حس می‌شود. پارامتر را مدل خودش در طول آموزش یاد می‌گیرد. ابرپارامتر (hyperparameter) را شما تنظیم می‌کنید: تعداد لایه‌ها، اندازهٔ واژگان، نرخ یادگیری و مانند این‌ها. در مدل‌های کوچک می‌شود ده بار با تنظیمات مختلف آموزش داد و بهترین را برداشت؛ در مدل‌های بزرگ فقط یک شانس دارید. برای همین پژوهشگران ابرپارامترها را روی مدل‌های کوچک می‌آزمایند و به مدل بزرگ برون‌یابی می‌کنند — یک بار از مدلی ۴۰ میلیونی به مدلی ۶٫۷ میلیاردی. سخت است، چون بعضی توانایی‌ها فقط در مقیاس بزرگ ظاهر می‌شوند و در مدل کوچک اصلاً دیده نمی‌شوند. دو دیوار پیش رو: داده و برق تا امروز هر ده برابر شدن اندازهٔ مدل، کیفیت را بالا برده است: GPT-2 ده برابر GPT-1 پارامتر داشت و GPT-3 صد برابر GPT-2. ولی این رشد تا کِی ادامه پیدا می‌کند؟ دو گلوگاه همین حالا دیده می‌شوند. گلوگاه اول: داده. دادهٔ آموزشی خیلی سریع‌تر از تولید دادهٔ تازه در اینترنت رشد می‌کند و نگرانی واقعی این است که ظرف چند سال دادهٔ اینترنتی تمام شود. هرچه تا حالا در اینترنت گذاشته‌اید، فرض کنید در دادهٔ آموزشی یک مدل هست یا خواهد بود — چه رضایت داده باشید چه نه. از آن طرف اینترنت با سرعت از متن‌های تولیدشده با هوش مصنوعی پر می‌شود؛ یک بار مدل Grok درخواستی را با این جمله رد کرد که «خلاف سیاست OpenAI است»، و توضیح سازنده‌اش این بود که «وب پر از خروجی ChatGPT است». در همین حال سایت‌هایی مثل Reddit و Stack Overflow دسترسی به داده‌شان را بستند؛ تا ۲۰۲۴ حدود ۴۵٪ از مجموعه‌دادهٔ C4 محدود شده بود. گلوگاه دوم: برق. مراکز داده امروز حدود ۱ تا ۲ درصد برق جهان را مصرف می‌کنند و تخمین زده می‌شود تا ۲۰۳۰ به ۴ تا ۲۰ درصد برسد. تا وقتی راهی برای تولید انرژی بیشتر پیدا نشود، مراکز داده حداکثر ۵۰ برابر می‌توانند بزرگ شوند — کمتر از دو مرتبهٔ بزرگی. وقتی دادهٔ عمومی تمام شود، دادهٔ اختصاصی — قرارداد، پروندهٔ پزشکی، کتاب، ترجمه، گفت‌وگوی واقعی کاربران — مزیت رقابتی می‌شود. برای همین OpenAI با ناشرانی مثل Associated Press قرارداد بست. این همان حرف درس ۲ فصل ۱ است: برای تیم کوچک، چیزی که واقعاً می‌ماند داده است. فصل ۸ و ۱۰ را برای همین داریم. ۱۳ میلیارد × ۲ بایت = ۲۶ میلیارد بایت ≈ ۲۶ گیگابایت. با FP32 می‌شد ۵۲ و با INT8 می‌شد ۱۳. این حساب ساده اولین فیلتر انتخاب مدل است: اگر حافظه‌اش را ندارید، باقی ویژگی‌هایش مهم نیست. در مدل ترکیب خبرگان، محاسبه فقط با خبره‌های فعال انجام می‌شود. ولی حواستان باشد: حافظه هنوز باید همهٔ ۴۶٫۷ میلیارد پارامتر را نگه دارد، چون معلوم نیست توکن بعدی سراغ کدام خبره‌ها برود. حدود ۲۰ توکن به ازای هر پارامتر: ۱۰ میلیارد × ۲۰ = ۲۰۰ میلیارد. اگر داده خیلی کمتر باشد، بخشی از ظرفیت مدل هدر رفته — همان اتفاقی که برای GPT-3 و Gopher افتاد. مدلی که فقط پیش‌آموزش دیده، باهوش ولی رام‌نشده است: به سؤال جواب نمی‌دهد، ادامه‌اش را می‌نویسد؛ و هرچه در اینترنت خوانده را بی‌پروا تکرار می‌کند. پس‌آموزش این دو مشکل را حل می‌کند. دو مشکل مدل خام در فصل ۱ دیدیم که پیش‌آموزش با خودنظارتی انجام می‌شود: مدل یاد می‌گیرد توکن بعدیِ متن‌های اینترنت را حدس بزند. نتیجه، مدلی است که دو مشکل دارد: برای تکمیل متن بهینه شده، نه برای گفت‌وگو. نمی‌داند که شما سؤال پرسیده‌اید و منتظر جوابید. اگر داده بی‌حساب‌وکتاب از اینترنت جمع شده باشد، خروجی‌اش هم می‌تواند نژادپرستانه، توهین‌آمیز یا صرفاً غلط باشد. به یک مدل خام بنویسید: «طرز تهیهٔ پیتزا». هر سه ادامهٔ زیر از نظر او کاملاً درست است: ۱. «… برای یک خانوادهٔ شش‌نفره؟» — سؤال را کامل‌تر کرد. ۲. «… چه موادی لازم دارم؟ چقدر طول می‌کشد؟» — چند سؤال دیگر پشتش نوشت. ۳. دستور پخت پیتزا. فقط سومی همان چیزی است که شما می‌خواستید. یکی از دوستان نویسندهٔ کتاب این را خوب گفته: مدل پیش‌آموزش‌دیده مثل یک صفحهٔ وب حرف می‌زند، نه مثل یک آدم. در درس ۷ همین رفتار را از نزدیک می‌بینید: مدل زبانی‌ای که می‌سازیم فقط پیش‌آموزش دیده، و اگر از آن سؤال بپرسید، به‌جای جواب، متنی شبیه درس‌نامه‌ها ادامه می‌دهد. نقشهٔ کلی: سه مرحله یک راه دیگر برای دیدن تفاوت: پیش‌آموزش کیفیت را در سطح توکن بهینه می‌کند — اینکه توکن بعدی درست حدس زده شود. ولی کاربر به کیفیت توکن اهمیتی نمی‌دهد؛ برایش کیفیت کل پاسخ مهم است. پس‌آموزش مدل را به سمت پاسخ‌هایی می‌برد که آدم‌ها ترجیح می‌دهند. بعضی این را این‌طور تشبیه می‌کنند: پیش‌آموزش یعنی خواندن برای کسب دانش، پس‌آموزش یعنی یاد گرفتن اینکه آن دانش را چطور به کار ببری. در مدل InstructGPT فقط ۲٪ کل محاسبات صرف پس‌آموزش شد و ۹۸٪ صرف پیش‌آموزش. پس پس‌آموزش توانایی تازه‌ای نمی‌سازد؛ توانایی‌هایی را آزاد می‌کند که از قبل در مدل بوده ولی کاربر نمی‌توانست فقط با پرامپت به آن‌ها برسد. بعضی‌ها «تنظیم دقیق دستوری» (instruction finetuning) را فقط به معنی SFT به کار می‌برند و بعضی به معنی SFT به‌علاوهٔ تنظیم ترجیحی. اگر در مقاله‌ای دیدیدش، از بافت بفهمید منظور کدام است. گام اول: تنظیم دقیق نظارت‌شده می‌دانیم مدل از دادهٔ آموزشی‌اش تقلید می‌کند. پس اگر می‌خواهیم پاسخ مناسب بدهد، باید نمونهٔ پاسخ مناسب نشانش بدهیم. این نمونه‌ها شکل (پرامپت، پاسخ) دارند و به آن‌ها دادهٔ نمایشی (demonstration data) می‌گویند. به همین دلیل گاهی به این مرحله شبیه‌سازی رفتار (behavior cloning) هم می‌گویند: شما رفتار را نشان می‌دهید و مدل آن را کپی می‌کند. اسم رسمی مرحله SFT است. چون درخواست‌های مختلف پاسخ‌های مختلفی می‌خواهند، دادهٔ نمایشی باید طیف کارهایی را که می‌خواهید مدل بلد باشد پوشش دهد: پرسش‌وپاسخ، خلاصه‌سازی، ترجمه، ایده‌پردازی و غیره. برخلاف برچسب زدن یک عکس که چند ثانیه طول می‌کشد، نوشتن یک جفت (پرامپت، پاسخ) خوب ممکن است تا ۳۰ دقیقه وقت بگیرد — مخصوصاً برای خلاصه‌سازی متن بلند. برای همین شرکت‌ها برچسب‌زن‌های تحصیل‌کرده استخدام می‌کنند: در InstructGPT حدود ۹۰٪ برچسب‌زن‌ها دست‌کم مدرک کارشناسی داشتند و بیش از یک‌سوم کارشناسی ارشد. اگر هر جفت ۱۰ دلار تمام شود، ۱۳ هزار جفتی که OpenAI برای InstructGPT استفاده کرد می‌شود ۱۳۰ هزار دلار — و این هنوز هزینهٔ طراحی داده، استخدام و کنترل کیفیت را ندارد. همه این بودجه را ندارند. سازمان غیرانتفاعی LAION سیزده هزار و پانصد داوطلب را از سراسر دنیا بسیج کرد که ده هزار گفت‌وگو در ۳۵ زبان نوشتند. ولی چون داوطلب بودند، کنترلی روی سوگیری نبود: در یک نظرسنجی، ۹۰٪ داوطلب‌ها خودشان را مرد معرفی کردند. اصولاً کسانی که «ترجیح انسانی» را به مدل یاد می‌دهند باید نمایندهٔ کل انسان‌ها باشند، و این‌جا نبودند. راه سوم، فیلتر کردن هوشمندانهٔ اینترنت است: DeepMind برای مدل Gopher متن‌هایی را برداشت که شکل گفت‌وگو داشتند ([A]: ... و [B]: ... پشت سر هم). و راه چهارم که این روزها رایج شده: تولید داده با خود هوش مصنوعی — موضوع فصل ۸. گام دوم: تنظیم ترجیحی دادهٔ نمایشی به مدل یاد می‌دهد چطور گفت‌وگو کند، ولی نه اینکه چه گفت‌وگویی کند. اگر کاربری بخواهد مدل دربارهٔ برتری یک نژاد مقاله بنویسد یا روش ربودن هواپیما را توضیح دهد، مدل باید همکاری کند؟ در این دو مثال جواب برای بیشتر مردم روشن است. ولی خیلی موقعیت‌ها این‌قدر روشن نیستند — آدم‌ها با پیشینه‌های فرهنگی، سیاسی و مذهبی مختلف مدام با هم اختلاف نظر دارند. اگر مدل دربارهٔ یک موضوع جنجالی جواب بدهد، هر جوابی که بدهد بخشی از کاربران را ناراحت می‌کند. اگر بیش از حد سانسور شود، کسل‌کننده می‌شود و کاربر را فراری می‌دهد. ترس از پاسخ نامناسب، گاهی شرکت‌ها را از انتشار محصولشان بازمی‌دارد. هدف تنظیم ترجیحی این است که مدل مطابق ترجیح انسانی رفتار کند — هدفی بلندپروازانه، اگر نگوییم ناممکن: هم فرض می‌کند «ترجیح انسانیِ جهانی» وجود دارد، هم فرض می‌کند می‌شود آن را در مدل جاسازی کرد. قدیمی‌ترین روش موفق که هنوز هم رایج است، RLHF است و دو بخش دارد: یک مدل پاداش آموزش بده که به پاسخ‌های مدل نمره بدهد. مدل اصلی را طوری آموزش بده که پاسخ‌هایی بسازد که بیشترین نمره را از مدل پاداش می‌گیرند. این کار معمولاً با الگوریتم PPO از خانوادهٔ RL انجام می‌شود. روش‌های تازه‌تری هم هستند. DPO ساده‌تر است و Meta برای Llama 3 از RLHF به آن کوچ کرد. RLAIF به‌جای بازخورد انسان از بازخورد خود هوش مصنوعی استفاده می‌کند. مدل پاداش: مقایسه از نمره دادن آسان‌تر است مدل پاداش یک جفت (پرامپت، پاسخ) می‌گیرد و یک نمره می‌دهد. مشکل اصلی، مثل SFT، داده است. اگر از برچسب‌زن‌ها بخواهیم به هر پاسخ مستقیم نمره بدهند، نمره‌ها پخش‌وپلا می‌شوند: یک نفر از ۱۰ می‌دهد ۵ و دیگری ۷؛ حتی یک نفر به یک پاسخ در دو نوبت دو نمرهٔ متفاوت می‌دهد. از یک داور بخواهید به یک بشقاب از ۱۰ نمره بدهد؛ مردد می‌ماند و فردا شاید عدد دیگری بگوید. ولی دو بشقاب را کنار هم بگذارید و بپرسید «کدام بهتر است؟»، جوابش سریع و پایدار است. برای همین دادهٔ مدل پاداش به شکل مقایسه جمع می‌شود: (پرامپت، پاسخ برنده، پاسخ بازنده). مقایسه هم رایگان نیست: هر مقایسه به‌طور میانگین ۳ تا ۵ دقیقه طول می‌کشد چون باید درستی هر دو پاسخ چک شود. یکی از نویسندگان Llama 2 گفته هر مقایسه برایشان ۳٫۵ دلار تمام شده — که هنوز خیلی ارزان‌تر از نوشتن یک پاسخ کامل (۲۵ دلار) است. توافق بین برچسب‌زن‌ها حدود ۷۳٪ بود: اگر ده نفر دو پاسخ را مقایسه کنند، حدود هفت نفرشان یک نظر دارند. ترفند سرعت: اگر برچسب‌زن سه پاسخ را رتبه‌بندی کند (الف > ب > ج)، یک‌جا سه مقایسه به دست می‌آید. ولی از دادهٔ «کدام بهتر است» چطور یک نمرهٔ عددی بیرون بیاید؟ با یک تابع هدف که تفاوت نمرهٔ برنده و بازنده را بزرگ کند. این فرمول InstructGPT است، به زبان پایتون: مدل پاداش را معمولاً روی قوی‌ترین مدلی که دارند تنظیم دقیق می‌کنند. بعضی معتقدند مدل پاداش باید دست‌کم به قوت مدل اصلی باشد تا بتواند داوری‌اش کند؛ ولی در فصل ۳ می‌بینیم که داوری کردن از تولید کردن آسان‌تر است و یک مدل ضعیف‌تر هم می‌تواند داور یک مدل قوی‌تر باشد. در عمل، هم RLHF و هم DPO کیفیت را نسبت به SFT تنها بهتر می‌کنند. ولی دربارهٔ اینکه چرا کار می‌کنند هنوز بحث است. و یک نکتهٔ جالب: هم SFT و هم تنظیم ترجیحی در اصل وصله‌ای برای کیفیت پایین دادهٔ پیش‌آموزش‌اند. اگر روزی دادهٔ پیش‌آموزش خیلی بهتر شود، شاید دیگر لازمشان نداشته باشیم. یک میان‌بر: بهترین از N بعضی شرکت‌ها اصلاً سراغ یادگیری تقویتی نمی‌روند. Stitch Fix و Grab فهمیدند که خود مدل پاداش برایشان کافی است: از مدل می‌خواهند چند پاسخ بسازد و پاسخی را برمی‌دارند که مدل پاداش بالاترین نمره را به آن داده. به این روش بهترین از N (best of N) می‌گویند. بهترین از N فقط وقتی کار می‌کند که مدل بتواند برای یک سؤال پاسخ‌های متفاوت بسازد. این تفاوت از کجا می‌آید؟ از نمونه‌برداری — موضوع درس بعد، که نویسندهٔ کتاب آن را کم‌قدرترین مفهوم پرتأثیر هوش مصنوعی می‌داند. مدل خام متن را ادامه می‌دهد و در اینترنت، بعد از چنین سؤالی بارها فهرستی از سؤال‌های مشابه آمده (مثلاً در برگهٔ امتحان). ممکن است «پاریس» هم بگوید، ولی هیچ تضمینی نیست. یاد دادن اینکه «این یک سؤال است و جواب می‌خواهد» کار SFT است. نمرهٔ مطلق بین آدم‌ها و حتی برای یک آدم در دو نوبت فرق می‌کند. «کدام بهتر است؟» سؤال ساده‌تری است. بعد با تابع هدفی که دیدید، از همین مقایسه‌ها نمرهٔ عددی ساخته می‌شود. پیش‌آموزش «خواندن» است و پس‌آموزش «یاد گرفتن به‌کار بستن آنچه خوانده‌ای». با یک بودجهٔ کوچک، رفتار مدل از «صفحهٔ وب» به «دستیار» تغییر می‌کند — ولی دانشی که در پیش‌آموزش نبوده، این‌جا هم ساخته نمی‌شود. مدل در هر قدم یک فهرست احتمال می‌سازد، نه یک جواب. اینکه از آن فهرست چه چیزی برداشته شود به چند پیچ ساده بستگی دارد که خودتان تنظیم می‌کنید — و همین پیچ‌ها خیلی از رفتارهای عجیب مدل را توضیح می‌دهند. از لاجیت تا احتمال یک مدل تشخیص هرزنامه را در نظر بگیرید. فقط دو جواب ممکن دارد: هرزنامه یا سالم. مدل احتمال هر کدام را حساب می‌کند — مثلاً ۹۰٪ هرزنامه و ۱۰٪ سالم — و شما تصمیم می‌گیرید: «هرچه بالای ۵۰٪ هرزنامه بود، هرزنامه است». مدل زبانی همین کار را می‌کند، فقط با تعداد بسیار بیشتری جواب ممکن: برای تولید توکن بعدی، برای تک‌تک توکن‌های واژگانش یک احتمال حساب می‌کند. اگر واژگان ۱۰۰ هزار توکن باشد، ۱۰۰ هزار احتمال. در واقع لایهٔ خروجی مدل (درس ۲) مستقیماً احتمال نمی‌دهد؛ برای هر توکن یک عدد خام به اسم لاجیت (logit) می‌دهد. لاجیت بزرگ‌تر یعنی احتمال بیشتر، ولی لاجیت‌ها احتمال نیستند: جمعشان ۱ نمی‌شود و حتی می‌توانند منفی باشند. تابعی به اسم softmax آن‌ها را به احتمال تبدیل می‌کند: حریصانه یا قرعه؟ ساده‌ترین روش: همیشه محتمل‌ترین گزینه را بردار. به این نمونه‌برداری حریصانه (greedy) می‌گویند. برای دسته‌بندی عالی است — اگر مدل فکر می‌کند ایمیل به احتمال بیشتر هرزنامه است، منطقی است هرزنامه علامتش بزنیم. ولی برای مدل زبانی خروجی کسل‌کننده می‌سازد: مدلی را تصور کنید که به هر سؤالی با رایج‌ترین کلمه‌ها جواب بدهد. راه دیگر، قرعه‌کشی بر اساس احتمال است. اگر بعد از «رنگ مورد علاقهٔ من» احتمال «قرمز» ۳۰٪ و «سبز» ۵۰٪ باشد، مدل ۳۰ درصد مواقع قرمز و ۵۰ درصد مواقع سبز می‌گوید. همین قرعه است که باعث می‌شود یک سؤال را دو بار بپرسید و دو جواب بگیرید. قرعه‌کشیِ ساده هم مشکل خودش را دارد: گزینه‌های رایج آن‌قدر محتمل‌ترند که جواب مدل شبیه جواب یک کودک پنج‌ساله می‌شود: «رنگ مورد علاقهٔ من سبز است». احتمال اینکه بگوید «رنگ مورد علاقهٔ من رنگ آسمانِ صبح بهار است» آن‌قدر کم است که عملاً هیچ‌وقت اتفاق نمی‌افتد. دما (temperature) این را تنظیم می‌کند. قبل از softmax، همهٔ لاجیت‌ها تقسیم بر دما می‌شوند. دمای بالا فاصلهٔ لاجیت‌ها را کم می‌کند و توزیع را پهن می‌کند: گزینه‌های نادر شانس بیشتری پیدا می‌کنند. دمای پایین فاصله‌ها را بزرگ می‌کند و توزیع را تیز می‌کند: محتمل‌ترین گزینه تقریباً همیشه برنده است. یک مثال عددی: مدلی فقط دو گزینه دارد، A با لاجیت ۱ و B با لاجیت ۲. از نظر ریاضی دما نمی‌تواند صفر باشد، چون تقسیم بر صفر ممکن نیست. وقتی دما را صفر می‌گذارید، مدل softmax را اصلاً حساب نمی‌کند و مستقیم بزرگ‌ترین لاجیت را برمی‌دارد — یعنی همان حریصانه. ارائه‌دهنده‌ها معمولاً دما را بین ۰ و ۲ محدود می‌کنند. عدد ۰٫۷ برای کارهای خلاقانه زیاد توصیه می‌شود، ولی بهترین عدد را باید خودتان با آزمایش پیدا کنید. در دمای صفر، همیشه همان غذای همیشگی را سفارش می‌دهید — بی‌خطر و قابل‌پیش‌بینی. در دمای متوسط، گاهی غذای دوم یا سوم محبوبتان. در دمای خیلی بالا، گاهی چیزی را سفارش می‌دهید که اسمش را هم نمی‌توانید بخوانید: شاید کشف بزرگ شب باشد، شاید پشیمانی. logprob: احتمال در مقیاس لگاریتمی خیلی از ارائه‌دهنده‌ها احتمال‌ها را به شکل logprob برمی‌گردانند: لگاریتم احتمال. دلیلش فنی است: با واژگان صد هزارتایی، احتمال بیشتر توکن‌ها آن‌قدر کوچک است که کامپیوتر نمی‌تواند نشانش بدهد و آن را صفر می‌کند. در مقیاس لگاریتمی این مشکل پیش نمی‌آید. اگر مدلی رفتار عجیبی دارد، به احتمال‌هایی که حساب کرده نگاه کنید. اگر احتمال‌ها تقریباً تصادفی و یکنواخت‌اند، مدل چیز زیادی یاد نگرفته. logprob در دسته‌بندی، ارزیابی (فصل ۳) و فهمیدن رفتار مدل خیلی به کار می‌آید. البته همهٔ ارائه‌دهنده‌ها آن را نمی‌دهند — تا زمان نوشتن کتاب، OpenAI فقط logprob بیست توکن محتمل‌تر را می‌داد و Anthropic اصلاً نمی‌داد — چون logprob کامل، کپی کردن مدل را آسان‌تر می‌کند. top-k و top-p: بریدن دُم top-k فقط k گزینهٔ محتمل‌تر را نگه می‌دارد و بقیه را حذف می‌کند. هدف اصلی‌اش کم کردن محاسبه بود (softmax روی صد هزار توکن گران است) و k معمولاً بین ۵۰ تا ۵۰۰ است. k کوچک‌تر یعنی متن قابل‌پیش‌بینی‌تر ولی کم‌روح‌تر. ولی یک عدد ثابت همیشه مناسب نیست. اگر بپرسید «موسیقی دوست داری؟ فقط بله یا نه بگو»، فقط دو گزینه معقول است. اگر بپرسید «معنای زندگی چیست؟»، صدها گزینه معقول است. top-p (یا nucleus sampling) این را حل می‌کند: گزینه‌ها را از محتمل‌ترین مرتب می‌کند و آن‌قدر برمی‌دارد تا جمع احتمالشان به p برسد. با top-p برابر ۰٫۹، کوچک‌ترین گروهی که روی هم ۹۰٪ احتمال را دارد می‌ماند. مقدارهای رایج ۰٫۹ تا ۰٫۹۵ است. فرض کنید احتمال‌ها این‌اند: «بله» ۶۰٪، «شاید» ۳۲٪، «نه» ۷٪، و بقیهٔ واژگان روی هم ۱٪. با top-p برابر ۰٫۹، فقط «بله» و «شاید» می‌مانند (جمعشان ۹۲٪). با top-p برابر ۰٫۹۹، «نه» هم اضافه می‌شود. اگر سؤال قبلی دربارهٔ معنای زندگی بود، همان ۰٫۹ شاید صدها گزینه را نگه می‌داشت — تعداد گزینه‌ها خودکار با موقعیت عوض می‌شود. یک روش خویشاوند هم هست به اسم min-p: هر گزینه‌ای که احتمالش کمتر از یک حد مشخص باشد حذف می‌شود. حالا خودتان امتحان کنید. سه پیچ را بچرخانید و نوارها را ببینید. مخصوصاً این سه آزمایش را انجام دهید: دما را به صفر ببرید؛ دما را به ۲ ببرید و بعد top-p را روی ۰٫۵ بگذارید؛ و top-k را روی ۲ بگذارید. دمای بالا گزینه‌های عجیبی مثل «ماشین» را هم وارد بازی می‌کند. top-p جلوی این را می‌گیرد: دم توزیع را می‌بُرد ولی تنوع بین گزینه‌های معقول را نگه می‌دارد. برای همین در عمل این دو را با هم استفاده می‌کنند: دما برای «چقدر جسور»، top-p برای «ولی نه بی‌معنی». مدل خودبازگشتی توکن پشت توکن تولید می‌کند. خروجی طولانی‌تر یعنی زمان بیشتر، هزینهٔ بیشتر، و گاهی کاربر کلافه. دو راه برای متوقف کردنش هست: حداکثر تعداد توکن: ساده است، ولی ممکن است جمله وسط کار قطع شود. توکن یا کلمهٔ توقف: مثلاً وقتی مدل توکن EOS را تولید کرد، بایست. یادتان هست در فصل ۱ گفتیم همین توکن است که به مدل می‌گوید کِی حرفش را تمام کند؟ اگر از مدل خروجی JSON خواسته‌اید و حداکثر توکن را کم گذاشته‌اید، ممکن است خروجی قبل از آکولاد بسته قطع شود و برنامهٔ شما نتواند آن را بخواند. در درس بعد راه‌حلش را می‌بینیم. یک جدول برای شروع این‌ها نقطهٔ شروعاند، نه قانون. همیشه با دادهٔ واقعی خودتان آزمایش کنید: تقسیم لاجیت‌ها بر عدد کوچک، فاصلهٔ آن‌ها را بزرگ می‌کند و بعد از softmax، بزرگ‌ترین لاجیت سهم خیلی بیشتری می‌گیرد. در حد صفر، همان نمونه‌برداری حریصانه است. top-k همیشه k گزینه نگه می‌دارد، حتی وقتی ۴۸تایشان بی‌معنی‌اند. top-p تا جایی جلو می‌رود که جمع احتمال به p برسد؛ وقتی دو گزینه تقریباً همهٔ احتمال را دارند، فقط همان دو می‌مانند. مدل برای همهٔ توکن‌های واژگان لاجیت می‌دهد. لاجیت بزرگ‌تر یعنی احتمال بیشتر، ولی فقط بعد از softmax به عددهایی بین صفر و یک با جمع یک تبدیل می‌شوند. همان قرعه‌ای که مدل را خلاق می‌کند، آن را غیرقابل‌اعتماد هم می‌کند: یک سؤال، دو جواب؛ قالبی که رعایت نمی‌شود؛ و حرفی که با اعتمادبه‌نفس کامل ساخته شده. این درس ابزارهای مهار این‌هاست. چند بار بپرسیم؟ محاسبه در زمان آزمون یک راه ساده برای بهتر کردن پاسخ: به‌جای یک پاسخ، چند پاسخ بسازید و بهترین را بردارید. به این محاسبه در زمان آزمون (test time compute) می‌گویند. «بهترین از N» که در درس ۴ دیدیم ساده‌ترین شکل آن است. شکل حساب‌شده‌ترش جست‌وجوی پرتو (beam search) است: در هر قدم تولید، فقط چند ادامهٔ امیدوارکننده نگه داشته می‌شوند. ولی «بهترین» را چطور انتخاب کنیم؟ چند راه: بیشترین احتمال: احتمال یک پاسخ، حاصل‌ضرب احتمال تک‌تک توکن‌هایش است. چون این ضرب برای پاسخ‌های بلند همیشه کوچک‌تر می‌شود، از میانگین logprob استفاده می‌کنند تا پاسخ کوتاه بی‌دلیل برنده نشود. مدل پاداش یا وارسی‌گر: هر پاسخ را به یک مدل داور بدهید. OpenAI نشان داد یک وارسی‌گر برای مسئله‌های ریاضی به اندازهٔ ۳۰ برابر کردن اندازهٔ مدل اثر دارد: مدلی ۱۰۰ میلیونی با وارسی‌گر، هم‌تراز مدلی ۳ میلیاردی بدون آن. قاعدهٔ خاص کار شما: اگر پاسخ کوتاه بهتر است، کوتاه‌ترین را بردارید. اگر متن را به SQL تبدیل می‌کنید، آن‌قدر تولید کنید تا یک SQL معتبر بیاید. اولین پاسخ آماده: یک تیم برای کم کردن تأخیر، چند پاسخ را هم‌زمان می‌سازد و اولین پاسخ کامل و معتبر را نشان می‌دهد. رأی اکثریت: برای سؤال‌هایی که جواب دقیق دارند، چند بار بپرسید و پرتکرارترین جواب را بردارید. گوگل برای ارزیابی Gemini روی MMLU برای هر سؤال ۳۲ نمونه گرفت. رأی اکثریت را در عمل ببینید. دقت یک‌بار پرسیدن را تغییر دهید و ببینید با چند بار پرسیدن، دقت چقدر بالا می‌رود — و هزینه چقدر: تولید دو پاسخ تقریباً دو برابر یک پاسخ هزینه دارد. در آزمایش OpenAI، نمونهٔ بیشتر تا ۴۰۰ نمونه کیفیت را بالا برد و بعد از آن پایین آورد — احتمالاً چون با نمونه‌های زیاد، شانس پیدا شدن پاسخی که وارسی‌گر را گول بزند هم بالا می‌رود. پژوهش دیگری تا ده هزار نمونه هم بهبود دید. ولی در محصول واقعی کسی برای هر سؤال ۴۰۰ پاسخ نمی‌سازد؛ هزینه نجومی می‌شود. یک نکتهٔ عملی: هرچه مدل کم‌ثبات‌تر باشد، از چند بار پرسیدن بیشتر سود می‌برد. نویسندهٔ کتاب در پروژه‌ای می‌خواست از عکس محصول اطلاعات بیرون بکشد. مدل فقط در نیمی از موارد موفق بود و در نیم دیگر می‌گفت «عکس تار است». با سه بار امتحان برای هر عکس، تقریباً همهٔ عکس‌ها درست خوانده شدند. خروجی ساختاریافته در محصول واقعی خیلی وقت‌ها خروجی مدل باید یک قالب مشخص داشته باشد. دو حالت اصلی هست: خود کار ساختاریافته است. مثلاً تبدیل زبان طبیعی به یک قالب ماشینی: «میانگین درآمد ماهانه در شش ماه گذشته چقدر بوده؟» ← یک دستور SQL معتبر. یا دسته‌بندی، که خروجی باید دقیقاً یکی از برچسب‌های مجاز باشد. خروجی را برنامهٔ دیگری می‌خواند. نوشتن ایمیل ذاتاً ساختار نمی‌خواهد، ولی اگر برنامهٔ شما ایمیل را به شکل {"title": ..., "body": ...} لازم دارد، خروجی باید همین شکل را داشته باشد. در ایجنت‌ها (فصل ۶) این حیاتی است، چون خروجی مدل مستقیم ورودی یک ابزار می‌شود. پنج جای مختلف در پشتهٔ هوش مصنوعی می‌شود قالب را تضمین کرد. سه‌تای اول بیشتر چسب زخماند و وقتی خوب کار می‌کنند که مدل خودش تقریباً بلد است؛ دو تای آخر درمان جدیاند: پرامپت خط اول دفاع است. بعضی برای بالا بردن درصد خروجی معتبر، از یک مدل دوم می‌خواهند خروجی را چک یا اصلاح کند — ولی این یعنی هر درخواست دست‌کم دو فراخوانی، و دو برابر هزینه. پس‌پردازش ساده و ارزان است و به‌طرز عجیبی خوب کار می‌کند. نویسندهٔ کتاب از تجربهٔ تدریسش می‌گوید دانشجوها اشتباه‌های خیلی شبیه به هم می‌کنند؛ مدل‌ها هم همین‌طور. اگر اشتباه رایج را پیدا کنید — مثلاً جا انداختن آکولاد بسته — یک اسکریپت کوچک درستش می‌کند. لینکدین با یک تجزیه‌گر دفاعی برای قالب YAML، درصد خروجی سالم را از ۹۰٪ به ۹۹٫۹۹٪ رساند. (آن‌ها YAML را به‌جای JSON انتخاب کردند چون کم‌حرف‌تر است و توکن کمتری مصرف می‌کند.) حالت JSON که ارائه‌دهنده‌ها دارند معمولاً فقط تضمین می‌کند که خروجی JSON معتبر باشد — نه اینکه کلیدهای درست را داشته باشد. و اگر تولید زود متوقف شود (مثلاً به حداکثر توکن برسد)، همان JSON هم نیمه‌کاره می‌ماند. حداکثر توکن را هم نمی‌شود خیلی بالا گذاشت، چون پاسخ کند و گران می‌شود. نمونه‌برداری محدودشده یادتان هست مدل برای هر توکن واژگان یک لاجیت می‌دهد؟ نمونه‌برداری محدودشده قبل از قرعه، لاجیت توکن‌هایی را که با قالب سازگار نیستند حذف می‌کند. مدل نه اینکه «قول بدهد» خارج از قالب حرف نزند — نمی‌تواند. در این مثال فیلتر کردن ساده است. ولی برای قالبی مثل JSON باید یک گرامر داشته باشید که بگوید در هر قدم چه چیزی مجاز است — مثلاً بعد از { آکولاد باز دیگری نمی‌تواند بیاید، مگر داخل یک رشته. ساختن این گرامر سخت است و برای هر قالب (JSON، YAML، CSV، عبارت منظم) جدا. بعضی معتقدند این زحمت بهتر است صرف آموزش مدل در پیروی از دستور شود. تنظیم دقیق روی نمونه‌هایی با قالب دلخواه، مؤثرترین و عمومی‌ترین راه است. برای بعضی کارها می‌شود حتی معماری مدل را عوض کرد: مثلاً برای دسته‌بندی، یک سر دسته‌بند (classifier head) به انتهای مدل می‌چسبانند که فقط و فقط یکی از برچسب‌های مشخص را خروجی می‌دهد. در فصل ۷ به آن برمی‌گردیم. ناسازگاری: یک سؤال، دو جواب از دوستتان بپرسید «بهترین غذای دنیا چیست؟» و یک دقیقه بعد دوباره بپرسید؛ دو بار یک جواب می‌شنوید. از یک مدل بپرسید و جوابش ممکن است عوض شود. اگر مدل فکر کند قورمه‌سبزی به احتمال ۷۰٪ بهترین غذای دنیاست و پیتزا ۳۰٪، هفتاد درصد مواقع می‌گوید قورمه‌سبزی و سی درصد پیتزا. نقطهٔ مقابل «احتمالی»، قطعی (deterministic) است: نتیجه بدون هیچ تصادفی معلوم است. مدل‌های پایه روی حجم عظیمی از داده آموزش دیده‌اند؛ چکیدهٔ نظر انبوه آدم‌ها هستند و به معنای واقعی کلمه دنیایی از احتمال‌ها را در خود دارند. هر چیزی که احتمالش صفر نباشد — هر قدر هم بعید یا غلط — ممکن است تولید شود. ناسازگاری دو شکل دارد: ورودی یکسان، خروجی متفاوت. نویسندهٔ کتاب از ChatGPT خواست به یک مقاله نمره بدهد. همان پرامپت را دو بار اجرا کرد و دو نمره گرفت: ۳ از ۵ و ۵ از ۵. ورودی کمی متفاوت، خروجی کاملاً متفاوت. مثلاً فقط به‌خاطر بزرگ نوشتن یک حرف. برای حالت اول چند راه هست: کش کردن پاسخ: سؤال تکراری، همان جواب قبلی را بگیرد (فصل ۹). ثابت کردن پیچ‌های نمونه‌برداری: دما، top-p و top-k. ثابت کردن بذر تصادفی (seed): نقطهٔ شروع مولد عدد تصادفی‌ای که قرعه با آن کشیده می‌شود. بذر یکسان، قرعهٔ یکسان. در درس ۷ این را با چشم خودتان می‌بینید. حتی با ثابت کردن همهٔ این‌ها، تضمین ۱۰۰٪ نیست: سخت‌افزاری که مدل روی آن اجرا می‌شود هم روی خروجی اثر دارد. اگر مدل را خودتان میزبانی کنید کنترلی دارید؛ اگر از API استفاده کنید، نه. نویسنده تشبیه جالبی دارد: معلمی را تصور کنید که فقط وقتی در یک کلاس خاص بنشیند نمره‌هایش ثابت است و در کلاس دیگر نمره‌هایش پرت می‌شود. ثابت کردن تنظیمات کار خوبی است، ولی اعتماد نمی‌سازد. حالت دوم سخت‌تر است. ثابت کردن تنظیمات کمکی نمی‌کند چون ورودی فرق دارد. پرامپت‌نویسی دقیق (فصل ۵) و یک سامانهٔ حافظه (فصل ۶) کمک می‌کنند. توهم: حرفی که از هیچ ساخته شده توهم (hallucination) یعنی پاسخی که بر واقعیت استوار نیست. برای کارهایی که به درستی وابسته‌اند، کشنده است. در ژوئن ۲۰۲۳ یک مؤسسهٔ حقوقی آمریکایی جریمه شد چون پژوهش حقوقی ساختگی به دادگاه داده بود — با ChatGPT تهیه‌اش کرده بودند و نمی‌دانستند ChatGPT توهم می‌زند. هنگام آماده کردن این درس، از یک مدل واقعی ۷ میلیاردی (qwen2.5:7b) که با Ollama روی همین کامپیوتر اجرا می‌شد پرسیدیم «مدل پایه چیست؟». جواب داد: «مدل پایه یا baseline model در مهندسی هوش مصنوعی، یک مدل ساده و سریع است که به عنوان یک مرجع استفاده می‌شود…». جمله روان و مطمئن است — و به سؤال ما بی‌ربط. منظور ما foundation model بود. مدل یک معنی محتمل‌تر از «مدل پایه» را برداشت و با اعتمادبه‌نفس کامل ادامه داد. درس ۱ را یادتان هست؟ مدلی که فارسی کم دیده، اصطلاح فنی فارسی را هم کمتر می‌شناسد. ناسازگاری از تصادفی بودن قرعه می‌آید؛ علت توهم پیچیده‌تر است. مدل از میان گزینه‌های محتمل انتخاب می‌کند، ولی چیزی که هرگز ندیده چطور محتمل می‌شود؟ دو فرضیهٔ اصلی وجود دارد: فرضیهٔ اول: خودفریبی مدل فرق بین داده‌ای که به او داده‌اند و داده‌ای که خودش ساخته را نمی‌فهمد. فرض کنید بپرسید «فلانی کیست؟» و اولین جملهٔ مدل این باشد: «فلانی یک معمار است». توکن بعدی بر اساس کل این متن ساخته می‌شود — و مدل جملهٔ «فلانی یک معمار است» را که خودش ساخته درست مثل یک واقعیتِ داده‌شده می‌بیند. از یک شروع کمی غلط، می‌تواند حقایق کاملاً ساختگی بسازد. پژوهشگران DeepMind اسمش را خودفریبی گذاشتند. دیگران به این توهم برفی می‌گویند: یک فرض غلط اول، مثل گلولهٔ برف بزرگ و بزرگ‌تر می‌شود چون مدل بقیهٔ پاسخ را برای توجیه آن می‌سازد. در یک نمونه، مدلی شیشهٔ شامپو را با شیر اشتباه گرفت و بعد «شیر» را در فهرست مواد تشکیل‌دهندهٔ برچسب نوشت. در نمونهٔ دیگر، یک فرض غلط اول باعث شد مدل ادعا کند ۹۶۷۷ بر ۱۳ بخش‌پذیر است — چیزی که در حالت عادی می‌دانست درست نیست. فرضیهٔ دوم: دانشی که مدل ندارد در SFT مدل یاد می‌گیرد از پاسخ‌های برچسب‌زن‌ها تقلید کند. اگر برچسب‌زن در پاسخش از دانشی استفاده کند که خودش دارد ولی مدل ندارد، در عمل داریم به مدل یاد می‌دهیم چیز بسازد. جان شولمن، از بنیان‌گذاران OpenAI، دو راه پیشنهاد کرد: یکی وارسی — از مدل بخواهید منبعی را که پاسخش بر آن استوار است بیاورد؛ دیگری یک تابع پاداش بهتر که برای ساختن حرف، جریمهٔ سنگین‌تری بدهد. شولمن گفته RLHF به کم کردن توهم کمک می‌کند. ولی مقالهٔ InstructGPT نشان داد RLHF توهم را بدتر کرده. با این حال برچسب‌زن‌ها در مجموع مدل RLHF را ترجیح دادند، چون در جنبه‌های دیگر بهتر بود. دو فرضیه مکمل هم‌اند: اولی می‌گوید خودنظارتی چطور توهم می‌سازد، دومی می‌گوید نظارت چطور. در پرامپت بنویسید «تا جایی که می‌شود صادقانه جواب بده و اگر مطمئن نیستی بگو نمی‌دانم». ذهن‌یار از فصل ۱ همین جمله را در SYSTEM_PROMPT دارد. از مدل پاسخ کوتاه بخواهید: توکن کمتر، فرصت کمتر برای ساختن. به مدل منبع بدهید تا از رو بخواند، نه از حافظه — این RAG است، فصل ۶. اگر نمی‌شود جلویش را گرفت، دست‌کم تشخیصش بدهید — فصل ۴. این‌ها مشکل کوچکی نیستند. نویسنده سه ماه درخواست‌های پشتیبانی یک شرکت هوش مصنوعی را بررسی کرد و دید یک‌پنجم سؤال‌ها دربارهٔ کنار آمدن با ناسازگاری مدل بود. و در یک پنل با مدیرعامل‌های Dropbox و LangChain، همه موافق بودند که توهم بزرگ‌ترین مانع استفاده از هوش مصنوعی در سازمان‌هاست. ثابت کردن دما و بذر خوب است ولی تضمین ۱۰۰٪ نمی‌دهد — سخت‌افزار هم اثر دارد. کش اصلاً مدل را دوباره صدا نمی‌زند، پس جواب حتماً یکی است (و ارزان‌تر هم هست). پرامپت فقط درخواست است. رأی اکثریت هم اگر بیشتر نمونه‌ها «عالی» باشند، «عالی» برمی‌گرداند. فقط وقتی توکن‌های غیرمجاز اصلاً شانس انتخاب نداشته باشند، خروجی تضمینی است. هر توکن جدید بر اساس کل متن قبلی ساخته می‌شود — از جمله جمله‌هایی که خود مدل ساخته. یک شروع کمی غلط، به‌عنوان «واقعیت» پذیرفته و بزرگ‌تر می‌شود: همان توهم برفی. در فصل ۱ ذهن‌یار فقط یک جدول جست‌وجو بود. حالا یک مدل زبانی واقعی برایش می‌سازیم — توکنایزر، شمارش احتمال، دما و top-p — همه از صفر، آفلاین و بدون نصب هیچ کتابخانهٔ اضافه‌ای. تا آخر این درس، ذهن‌یار یک مدل زبانی کوچک ولی واقعی دارد که روی متن درس‌نامه‌های همین دوره آموزش دیده است. این مدل ترنسفورمر نیست — یک مدل ساده‌تر به اسم n-gram است که با «شمردن» یاد می‌گیرد — ولی از بیرون دقیقاً همان کار GPT را می‌کند: برای همهٔ توکن‌های واژگان یک لاجیت می‌سازد و بعد با دما، top-k و top-p یکی را قرعه می‌کشد. پس هرچه در درس ۵ دیدید، این‌جا با کد خودتان اتفاق می‌افتد. در درس بعد (پروژه ۲) خروجی‌اش را مهار می‌کنیم و آن را به ذهن‌یار وصل می‌کنیم. این درس ادامهٔ درس ۵ فصل ۱ است. فرض می‌کنیم آن پروژه را ساخته‌اید و اجرا کرده‌اید. روش کار مثل همان‌جاست: VS Code را روی پوشهٔ پروژه باز کنید، از منوی Terminal یک پاورشل باز کنید، و هر فایل را با راست‌کلیک ← New File... بسازید، کد را با دکمهٔ «کپی» بردارید و با Ctrl+S ذخیره کنید. وقتی فایلی «تغییر» کرده، همهٔ محتوای قبلی‌اش را با کد تازه عوض کنید (Ctrl+A و بعد Ctrl+V). قدم ۱ — پوشه‌های تازه دو پوشهٔ تازه لازم است: یکی برای اسکریپت این فصل (با فایل خالی __init__.py داخلش — یادتان هست چرا؟ تا پایتون آن را «بسته» حساب کند)، و یکی به اسم corpus برای متن‌هایی که مدل از آن‌ها یاد می‌گیرد. این را در پاورشل بزنید: یک پوشهٔ دیگر هم به اسم data لازم می‌شود که توکنایزر حاصل آموزشش را آن‌جا ذخیره می‌کند. لازم نیست خودتان بسازیدش؛ کد خودش می‌سازد. قدم ۲ — پیکره: ذهن‌یار چه می‌خواند؟ هر مدل زبانی یک پیکره (corpus) لازم دارد: مجموعه متنی که از آن یاد می‌گیرد. ما متن درس‌های همین دوره را به ذهن‌یار می‌دهیم، تا وقتی با او حرف می‌زنید، به زبان همین درس‌ها جواب بدهد. متن درس‌ها را دانلود کنید روی این پیوند بزنید: دانلود متن درس‌ها (lessons.txt). یک فایل متنی ساده دانلود می‌شود که همهٔ پاراگراف‌های درس‌های تا اینجای دوره در آن است، هر پاراگراف جدا با یک خط خالی. فایل را در پوشهٔ corpus بگذارید فایل lessons.txt را از پوشهٔ Downloads به پوشهٔ corpus پروژه‌تان منتقل کنید (در VS Code می‌توانید آن را با موس روی پوشهٔ corpus در Explorer بکشید). در پایان باید این مسیر را داشته باشید: zehnyar-project/corpus/lessons.txt. (اختیاری) متن بیشتر اضافه کنید هر فایل .txt فارسی دیگری که در پوشهٔ corpus بگذارید هم خوانده می‌شود — مثلاً چند مقالهٔ ویکی‌پدیا که متنشان را کپی کرده‌اید. فقط فایل را با رمزگذاری UTF-8 ذخیره کنید (VS Code خودش همین کار را می‌کند) و پاراگراف‌ها را با یک خط خالی از هم جدا کنید. یادتان باشد: متن متفاوت یعنی خروجی‌های شما با خروجی‌های این صفحه فرق خواهد کرد. حالا کدی که این فایل‌ها را می‌خواند. در پوشهٔ zehnyar بسازیدش: مدل فقط متن می‌خواند؛ برای همین در فایل دانلودی، کد و جدول‌ها و نمودارهای درس‌ها کنار گذاشته شده‌اند، چون جملهٔ کامل فارسی ندارند. این همان «کیفیت از کمیت مهم‌تر است» درس ۱ است — در مقیاسی خیلی کوچک. و چون هر فایل تازه‌ای در corpus خودکار خوانده می‌شود، با هر فصل تازهٔ دوره می‌توانید متن جدید را دانلود کنید تا ذهن‌یار هم همراهتان جلو بیاید. قدم ۳ — توکنایزر BPE از صفر حالا توکنایزر. الگوریتمش BPE است — همان ایده‌ای که پشت توکنایزر GPT و Llama هم هست. اول ایده را بدون کد ببینید: از تک‌حرف‌ها شروع کن هر کلمه را به حروفش بشکن: «کتاب» ← ک ت ا ب. جفت‌های کنار هم را بشمار در کل متن، کدام دو تکهٔ کنار هم بیشتر از همه تکرار شده‌اند؟ پرتکرارترین جفت را بچسبان آن دو تکه از این به بعد یک توکن‌اند. مثلاً ک + ت ← کت. دوباره بشمار و دوباره بچسبان؛ ۸۰۰ بار. هر چسباندن یک توکن به واژگان اضافه می‌کند. این مثال واقعی است: همین الگوریتم را روی یک جملهٔ کوچک (چند بار تکرار «کتاب»، «کتاب‌ها»، «کتابخانه» و «کتابدار») فقط برای شش دور اجرا کردیم. ببینید چه جفت‌هایی به ترتیب چسبیدند: بعد از همین شش دور، کلمه‌ای که در متن آموزشی نبود — «کتابخانه‌ها» — این‌طور شکسته می‌شود: ▁کتاب · خ · ا · ن · ه · ‌ · ه · ا. علامت ▁ یعنی «اول کلمه»؛ این‌طوری بعداً می‌دانیم کجا فاصله بگذاریم. حالا کد کامل. طولانی‌ترین فایل این فصل است؛ عجله نکنید. جدول بعد از آن بخش‌به‌بخش توضیحش می‌دهد: حالا امتحانش کنید. این دستور توکنایزر را می‌سازد و یک جمله را با آن می‌شکند. -c یعنی «این متن کوتاه را به‌عنوان کد اجرا کن»: باید فهرستی از توکن‌ها ببینید و پوشهٔ data با فایل tokenizer.json ساخته شده باشد. آزمایشگاه درس ۱ هم نسخهٔ آمادهٔ همین کد بود. قدم ۴ — شمارش توکن واقعی در فصل ۱ قول فصل ۱ را عملی کنیم. در mock.py، تابع تخمینی count_tokens (که طول متن را تقسیم بر ۴ می‌کرد) حذف می‌شود و به‌جایش تابع واقعی توکنایزر آورده می‌شود. فایل را کامل با این عوض کنید: قدم ۵ — نمونه‌بردار این فایل خط لولهٔ درس ۵ است، کلمه به کلمه: لاجیت ← دما ← softmax ← top-k ← top-p ← قرعه. تفاوتش با کد کوچک درس ۵ این است که به‌جای فهرست، با دیکشنری «توکن ← لاجیت» کار می‌کند تا بدانیم هر احتمال مال کدام توکن است: قدم ۶ — مدل زبانی با شمارش حالا قلب پروژه. مدل n-gram احتمال را با شمردن می‌سازد: «بعد از این دو توکن، در متن درس‌ها هر توکن چند بار آمده؟». این جدول از خود پیکرهٔ واقعی ذهن‌یار گرفته شده: بعد از «مدل زبانی» (19 بار در کل درس‌ها) این توکن‌ها آمده‌اند: مشکل: اگر ترکیبی را هرگز ندیده باشد چه؟ آن‌وقت احتمال همه‌چیز صفر می‌شود و مدل گیر می‌کند. راه‌حل، درون‌یابی است: سه سطح را با هم ترکیب می‌کنیم. یعنی حتی برای ترکیبی که هرگز ندیده، سطح دوتایی یا یکتایی یک احتمال کوچک می‌دهد. و چون سطح یکتایی همهٔ واژگان را پوشش می‌دهد، مدل همیشه برای همهٔ توکن‌ها یک احتمال دارد — درست مثل GPT. چون همهٔ مدل‌های زبانی در اصل همین کار را می‌کنند: از روی داده، احتمال توکن بعدی را تخمین می‌زنند. فرق GPT با مدل ما در چطور تخمین زدن است: ما فقط دو توکن قبلی را می‌بینیم و دقیقاً همان ترکیب را باید قبلاً دیده باشیم؛ ترنسفورمر با سازوکار توجه (درس ۲) به هزاران توکن قبلی نگاه می‌کند و می‌تواند ترکیب‌هایی را که هرگز ندیده هم بفهمد. قدم ۷ — اجرا کنید حالا مدل را امتحان کنیم. این اسکریپت سه آزمایش را پشت هم اجرا می‌کند: توکنایزر، دما و بذر تصادفی. آن را در پوشهٔ projects/ch02_sampling بسازید: دستور اجرا، مثل فصل ۱ از پوشهٔ اصلی پروژه. بار اول چند ثانیه طول می‌کشد چون توکنایزر آموزش می‌بیند: باید خروجی‌ای شبیه این ببینید. این خروجی واقعی همین کد است: توکنایزر: جملهٔ انگلیسی حدود سه برابر جملهٔ فارسی توکن دارد — درس ۱، با کد خودتان. دما: در صفر، کوتاه و تکراری؛ در ۱٫۶، کلمه‌ها از وسط می‌شکنند — چون توکن‌ها تکه‌کلمه‌اند و دمای بالا تکه‌های بی‌ربط را کنار هم می‌گذارد. بذر: دو اجرا با بذر ۴۲ حرف به حرف یکی‌اند. ناسازگاری درس ۶ از قرعه می‌آید، و قرعه با بذر ثابت تکرارپذیر است. متن‌ها روان به نظر می‌رسند ولی معنای درستی ندارند — جمله‌های درس‌ها را تکه‌تکه به هم می‌دوزد. این دو درس این فصل است که جلوی چشمتان اتفاق می‌افتد: مدل فقط پیش‌آموزش دیده، پس متن را ادامه می‌دهد و جواب نمی‌دهد (پیتزای درس ۴)؛ و چون هر توکن را بر اساس توکن‌های قبلیِ خودش می‌سازد، با اعتمادبه‌نفس کامل حرف بی‌پایه می‌زند (خودفریبی درس ۶). همین مدل را در این آزمایشگاه هم امتحان کنید؛ نسخهٔ آمادهٔ همین کد را اجرا می‌کند. پیچ‌ها را بچرخانید و جدول قدم‌ها را ببینید: در هر قدم چند گزینه از فیلترها جان سالم به در برد (pool) و رقبای توکن برنده چه بودند: همان جدول خطاهای درس ۵ فصل ۱ این‌جا هم صادق است. سه خطای تازه: اگر FileNotFoundError: هیچ فایل متنی در ... پیدا نشد دیدید، فایل lessons.txt در پوشهٔ corpus نیست (قدم ۲). اگر ModuleNotFoundError: No module named 'zehnyar.tokenizer' دیدید، فایل tokenizer.py در پوشهٔ zehnyar نیست (نه در providers). اگر ImportError: cannot import name 'count_tokens' دیدید، tokenizer.py را کامل کپی نکرده‌اید. چه چیزی ساختیم؟ یک توکنایزر BPE از صفر که روی متن فارسی درس‌ها آموزش دیده (tokenizer.py). شمارش واقعی توکن در ذهن‌یار — جایگزین تخمین فصل ۱. یک مدل زبانی واقعی که برای همهٔ واژگان احتمال می‌سازد (lm.py). نمونه‌بردار کامل: دما، top-k، top-p و بذر تصادفی (sampling.py). در zehnyar/tokenizer.py مقدار NUM_MERGES = 800 را به 200 تغییر دهید، ذخیره کنید و پروژهٔ این فصل را دوباره اجرا کنید. توکنایزر خودکار دوباره آموزش می‌بیند (چون عدد در اثر انگشت هست). تعداد توکن جملهٔ فارسی چه شد؟ چرا؟ بعد به ۸۰۰ برگردانید. در zehnyar/lm.py مقدار LAMBDAS را به (1.0, 0.0, 0.0) تغییر دهید — یعنی فقط سطح سه‌تایی. دوباره اجرا کنید و خروجی دمای ۱ را ببینید. مدل چه می‌کند؟ (راهنمایی: جمله‌های درس‌ها را کلمه به کلمه کپی می‌کند. به این حفظ کردن می‌گویند و یکی از دلایلی است که مدل‌ها گاهی متن دادهٔ آموزشی‌شان را بیرون می‌دهند.) بعد مقدار اصلی را برگردانید. چالش: در zehnyar/sampling.py یک تابع min_p_filter(probs, m) بنویسید که هر توکنی با احتمال کمتر از m را حذف کند (درس ۵)، و آن را در choose بعد از top_p_filter صدا بزنید. از top_k_filter الگو بگیرید. خروجی مدل ما هر چیزی می‌تواند باشد. در درس بعد یاد می‌گیریم مجبورش کنیم فقط از یک فهرست مجاز انتخاب کند، JSON خراب را خودکار تعمیر کنیم، و مدل را پشت همان «پریز استاندارد» فصل ۱ به ذهن‌یار وصل کنیم. الگوریتم برای هر دو زبان یکی است؛ فرق در داده است. این همان دلیلی است که متن فارسی در توکنایزرهای انگلیسی‌محور گران‌تر تمام می‌شود. یک خط self.counts[order][ctx][ids[i]] += 1 کل آموزش است. احتمال از همین شمارش‌ها و درون‌یابی سه سطح ساخته می‌شود. مدل هنوز احتمالی است — با بذر ۴۳ خروجی دیگری می‌دهد. بذر فقط «قرعه‌ها» را تکرارپذیر می‌کند. در مدل‌های API، سخت‌افزار هم اثر دارد و این تکرارپذیری صددرصد نیست (درس ۶). مدل زبانی درس قبل هر چیزی می‌تواند بگوید. در این درس خروجی‌اش را مهار می‌کنیم — با فیلتر لاجیت و تعمیر خودکار JSON — و بعد آن را پشت همان «پریز استاندارد» فصل ۱ به ذهن‌یار وصل می‌کنیم. این درس ادامهٔ درس قبل است و در همان پوشهٔ zehnyar-project کار می‌کنیم. فرض می‌کنیم run.py درس قبل را اجرا کرده‌اید و کار کرده. روش کار مثل قبل: هر فایل را با راست‌کلیک ← New File... بسازید، کد را با دکمهٔ «کپی» بردارید و با Ctrl+S ذخیره کنید؛ و وقتی فایلی «تغییر» کرده، همهٔ محتوای قبلی‌اش را با کد تازه عوض کنید. قدم ۱ — خروجی محدودشده و تعمیر JSON دو ابزار از چهار ابزار درس ۶ را می‌سازیم. اولی نمونه‌برداری محدودشده: در هر قدم، فقط توکن‌هایی اجازه دارند که هنوز به یکی از گزینه‌های مجاز می‌رسند. دومی پس‌پردازش دفاعی: سه اشتباه رایج JSON را خودکار درست می‌کند. قدم ۲ — اجرا کنید این اسکریپت دو آزمایش دارد: یک پرامپت، یک بار آزاد و یک بار فقط بین سه گزینهٔ مجاز؛ و تعمیر یک JSON نیمه‌کاره و پرحرف. در پوشهٔ projects/ch02_sampling بسازیدش: باید خروجی‌ای شبیه این ببینید. این خروجی واقعی همین کد است: محدودشده: خروجی آزاد هر چیزی است؛ خروجی محدود همیشه یکی از سه گزینه. تعمیر: JSON قطع‌شده با حذف پرحرفی و بستن آکولادها خوانا شد — بدون هیچ فراخوانی دوباره از مدل. این دو آزمایشگاه نسخهٔ آمادهٔ همین کد را اجرا می‌کنند. گزینه‌های خودتان و JSONهای خراب خودتان را امتحان کنید: قدم ۳ — وصل کردن به ذهن‌یار آخرین کار: مدل تازه را پشت همان «پریز استاندارد» فصل ۱ بگذاریم تا ذهن‌یار هم بتواند از آن استفاده کند. اول یک ارائه‌دهندهٔ تازه: بعد، کارخانهٔ فصل ۱ باید اسم local را بشناسد. فایل را کامل با این عوض کنید — تنها تغییر، بلوک if name == "local": است: حالا تنظیمات پیش‌فرض نمونه‌برداری را در config.py تعریف می‌کنیم. یک بلوک SAMPLING اضافه شده؛ فایل را کامل عوض کنید: و آخر، هستهٔ ذهن‌یار باید این تنظیمات را به مدل برساند: حالا پروژهٔ فصل ۱ را با مدل تازه اجرا کنید. خط اول به پاورشل می‌گوید «تا این پنجره باز است، provider را local بگذار»: ذهن‌یار حالا با یک مدل زبانی واقعی کار می‌کند — و جواب‌هایش بی‌ربط است، چون فقط پیش‌آموزش دیده. برای برگشتن به mock، پاورشل را ببندید و دوباره باز کنید، یا بزنید: $env:ZEHNYAR_PROVIDER = "mock". اگر ModuleNotFoundError: No module named 'zehnyar.structured' دیدید، فایل structured.py در پوشهٔ zehnyar نیست. اگر با ZEHNYAR_PROVIDER = "local" خطای ModuleNotFoundError: ... local_lm آمد، فایل local_lm.py باید در پوشهٔ zehnyar/providers باشد. چه چیزی ساختیم؟ یک توکنایزر BPE از صفر که روی متن فارسی درس‌ها آموزش دیده (tokenizer.py). شمارش واقعی توکن در ذهن‌یار — جایگزین تخمین فصل ۱. یک مدل زبانی واقعی که برای همهٔ واژگان احتمال می‌سازد (lm.py). نمونه‌بردار کامل: دما، top-k، top-p و بذر تصادفی (sampling.py). نمونه‌برداری محدودشده و تعمیر JSON (structured.py). یک ارائه‌دهندهٔ تازه پشت همان پریز فصل ۱ — بدون تغییر حتی یک خط از run.py فصل ۱. در run_structured.py فهرست options را به سه واژهٔ دیگر از درس‌ها عوض کنید — مثلاً ["توکن", "مدل", "داده"] — و ببینید خروجی محدود همیشه یکی از آن‌هاست، حتی اگر خروجی آزاد چیز دیگری بگوید. در آزمایشگاه تعمیرکار بالا یک JSON بنویسید که دو اشتباه هم‌زمان دارد: هم حصار کد دورش است و هم آخرش قطع شده. تعمیرکار از پسش برمی‌آید؟ حالا یک JSON بنویسید که تعمیرکار نتواند درستش کند. این همان مرز پس‌پردازش است: فقط اشتباه‌های کوچک و قابل‌حدس. با $env:ZEHNYAR_PROVIDER = "local" پروژهٔ فصل ۱ را اجرا کنید و $env:ZEHNYAR_TEMPERATURE = "1.2" را هم امتحان کنید. پاسخ‌های ذهن‌یار چقدر عوض می‌شوند؟ مدل ما حالا برای هر متن یک احتمال دارد. این یعنی می‌توانیم بپرسیم «مدل چقدر از یک متن تازه غافلگیر می‌شود؟» — سنجه‌ای به اسم PPL که اولین ابزار ارزیابی فصل ۳ است. با آن، برای اولین بار به‌جای «به نظرم بهتر شد»، با عدد می‌گوییم ذهن‌یار بهتر شده یا نه. توکن غیرمجاز اصلاً به قرعه نمی‌رسد، پس مدل نمی‌تواند چیزی خارج از فهرست بگوید. گزینه‌های دیگر هم روش‌اند (پرامپت، محاسبه در زمان آزمون، پس‌پردازش)، ولی هیچ‌کدام تضمین نمی‌دهند. مدل ما SFT ندارد؛ نمی‌داند «سؤال» یعنی چه. این همان مثال پیتزای درس ۴ است — و دلیل اینکه پیش‌فرض ذهن‌یار هنوز mock است. هرچه از هوش مصنوعی بیشتر استفاده شود، فرصت شکست‌های فاجعه‌بار بیشتر می‌شود. بدون راهی برای کنترل کیفیت، خطر یک محصول هوش مصنوعی ممکن است از سودش بیشتر باشد. این درس می‌گوید چرا سنجیدن یک مدل پایه این‌قدر سخت است. وقتی کسی کیفیت را نمی‌سنجد در همین چند سال کوتاه، شکست‌های جدی کم نبوده‌اند: یک چت‌بات کاربری را به خودکشی تشویق کرد؛ وکیل‌هایی مدرک ساختگیِ تولیدشده با هوش مصنوعی به دادگاه دادند (همان توهم فصل ۲)؛ و شرکت هواپیمایی Air Canada محکوم به پرداخت خسارت شد، چون چت‌باتش اطلاعات غلط به یک مسافر داده بود. تیم‌هایی که با عجله سراغ هوش مصنوعی می‌روند، زود می‌فهمند که بزرگ‌ترین مانعِ رساندن محصول به دست کاربر ارزیابی است. در بعضی پروژه‌ها، ارزیابی بیشترِ وقت توسعه را می‌گیرد. برای همین این دوره دو فصل کامل به آن داده: این فصل روش‌ها را می‌گوید و فصل ۴ ساختن خط لولهٔ ارزیابی را. چون ارزیابی سخت است، خیلی‌ها به حرف دیگران («شنیدم مدل X خوب است») یا نگاه چشمی به چند خروجی بسنده می‌کنند — که در انگلیسی به آن «vibe check» می‌گویند. در یک نظرسنجی از ۷۰ مدیر تصمیم‌گیر، ۶ نفر مدل‌ها را فقط از روی حرف دیگران انتخاب کرده بودند. خیلی‌ها هم چند پرامپت محبوب خودشان را دارند که هر مدل تازه را با آن‌ها می‌سنجند — پرامپت‌هایی که از تجربهٔ شخصی آمده‌اند، نه از نیاز محصول. برای شروع شاید کافی باشد، ولی برای بهتر کردن مداوم محصول نه. یک نکتهٔ مهم پیش از هر روشی: ارزیابی باید در دلِ کل سامانه طراحی شود، نه جدا از آن. اول باید بدانید سامانه‌تان کجا ممکن است خراب شود، و ارزیابی را دور همان نقطه‌ها بچینید. گاهی لازم است سامانه را از نو طراحی کنید تا خرابی‌هایش دیده شوند. بدون این، هیچ سنجه و ابزاری سامانه را قابل‌اعتماد نمی‌کند. پنج دلیل سختی ارزیابی مدل‌های یادگیری ماشین همیشه سخت بوده، ولی با مدل‌های پایه سخت‌تر شده است: هرچه مدل باهوش‌تر، ارزیابی‌اش سخت‌تر. غلط بودن جواب ریاضی کلاس اول را همه می‌فهمند؛ غلط بودن اثبات یک مسئلهٔ دکترا را چند نفر؟ تشخیص خلاصهٔ بی‌معنی آسان است، ولی خلاصه‌ای که روان است را فقط کسی می‌تواند بسنجد که خود کتاب را خوانده باشد. پس دیگر نمی‌شود از روی «ظاهر» پاسخ قضاوت کرد؛ باید درستی‌اش را چک کرد، استدلال کرد و گاهی تخصص داشت. خروجی باز است. مدل دسته‌بندی سنتی فقط یکی از چند برچسب مشخص را می‌گوید و سنجیدنش ساده است: یا برچسب درست است یا نه. ولی برای یک سؤال باز، تعداد پاسخ‌های درست بی‌شمار است و نمی‌شود فهرست کاملشان را نوشت. جعبهٔ سیاه است. بیشتر مدل‌ها جزئیات معماری، دادهٔ آموزشی و روند آموزششان را منتشر نمی‌کنند — همان چیزهایی که در فصل ۲ دیدیم چقدر دربارهٔ نقاط قوت و ضعف مدل می‌گویند. پس فقط می‌شود از روی خروجی قضاوت کرد. آزمون‌های عمومی زود کهنه می‌شوند. وقتی مدلی در یک آزمون (benchmark) نمرهٔ کامل بگیرد، آن آزمون اشباع شده و دیگر چیزی نمی‌سنجد. آزمون GLUE در ۲۰۱۸ آمد و ظرف یک سال اشباع شد و SuperGLUE جایش را گرفت. MMLU که در فصل ۲ دیدیم (۲۰۲۰) هم تا ۲۰۲۴ عملاً جایش را به MMLU-Pro داد. دامنهٔ ارزیابی بزرگ شده. مدل تک‌کاره را فقط در همان یک کار می‌سنجیدند. مدل همه‌منظوره را باید بسنجیم تا بفهمیم چه کارهای تازه‌ای از دستش برمی‌آید — شاید حتی کارهایی فراتر از توان آدم‌ها. وقتی مدل o1 از OpenAI در ۲۰۲۴ آمد، ترنس تائو — ریاضی‌دان برندهٔ مدال فیلدز — کار با آن را به کار با «یک دانشجوی تحصیلات تکمیلی متوسط، ولی نه کاملاً بی‌عرضه» تشبیه کرد. خیلی‌ها شوخی کردند: اگر همین حالا برای ارزیابی هوش مصنوعی به باهوش‌ترین ریاضی‌دان‌های دنیا نیاز داریم، برای مدل‌های بعدی چه کسی می‌ماند؟ ارزیابی عقب مانده است خبر خوب: سختی‌های تازه، روش‌ها و آزمون‌های تازه هم آورده‌اند. تعداد مقاله‌های ارزیابی مدل‌های زبانی در نیمهٔ اول ۲۰۲۳ از ماهی ۲ مقاله به نزدیک ۳۵ مقاله رسید. در میان هزار مخزن پرطرفدار هوش مصنوعی در GitHub، بیش از ۵۰ مخزن فقط به ارزیابی اختصاص دارد. خبر بد: ارزیابی هنوز از بقیهٔ کارهای این حوزه عقب است. پژوهشگران DeepMind نوشته‌اند که «ساختن ارزیابی، در مقایسه با ساختن الگوریتم، توجه نظام‌مند کمی گرفته». Anthropic از سیاست‌گذاران خواسته بودجهٔ دولتی بیشتری برای روش‌های ارزیابی بگذارند. و تعداد ابزارهای متن‌باز ارزیابی در مقایسه با ابزارهای آموزش مدل یا هماهنگ‌سازی، خیلی کم است. سرمایه‌گذاری کم یعنی زیرساخت کم، و زیرساخت کم یعنی همان «نگاه چشمی». نقشهٔ این فصل روش‌های خودکار ارزیابی دو خانوادهٔ بزرگ دارند. ارزیابی دقیق نتیجه‌ای بی‌ابهام می‌دهد: اگر جواب سؤال چهارگزینه‌ای «الف» است و شما «ب» زده‌اید، غلط است و بحثی ندارد. ارزیابی ذهنی به داور بستگی دارد: نمرهٔ یک انشا به این بستگی دارد که چه کسی تصحیحش کند، و حتی یک معلم در دو نوبت ممکن است دو نمره بدهد. (با یک راهنمای نمره‌دهی روشن، انشا هم «دقیق‌تر» می‌شود — این نکته در درس ۵ مهم است.) «سنجه‌ها را از روز اول جمع کنید، حتی وقتی هنوز به کار نمی‌آیند.» این فصل همان روزی است که به کار می‌آیند. در پروژهٔ این فصل، برای اولین بار به‌جای «به نظرم بهتر شد»، با عدد می‌گوییم ذهن‌یار چقدر خوب جواب می‌دهد. مدل دسته‌بندی یکی از چند برچسب مشخص را می‌گوید و مقایسه با جواب درست ساده است. پاسخ باز را نمی‌شود با یک فهرست کامل از پاسخ‌های درست مقایسه کرد — و این ریشهٔ بیشتر روش‌های این فصل است. آزمونی که همه در آن نمرهٔ کامل می‌گیرند، دیگر چیزی دربارهٔ تفاوت مدل‌ها نمی‌گوید. GLUE فقط یک سال دوام آورد. پاسخ چهارگزینه‌ای یا درست است یا غلط. نمرهٔ انشا به تصحیح‌کننده بستگی دارد. هوش مصنوعی در نقش داور (درس ۵) ذهنی است، چون با عوض شدن مدل یا پرامپت داور، نمره عوض می‌شود. مدل‌های پایه از دل مدل‌های زبانی بیرون آمده‌اند و هنوز یک مدل زبانی در قلبشان دارند. سنجه‌های قدیمی مدل زبانی — آنتروپی، آنتروپی متقاطع و سرگشتگی — هنوز چیزهای زیادی دربارهٔ یک مدل می‌گویند. کارکرد بخش مدل زبانیِ یک مدل پایه، معمولاً با کارکرد کل مدل در کارهای واقعی همبستگی خوبی دارد. پس فهم سنجه‌های مدل زبانی، حتی اگر هیچ‌وقت مدلی آموزش ندهید، به انتخاب مدل کمک می‌کند. این سنجه‌ها از ۱۹۵۱ — مقالهٔ معروف کلود شانون دربارهٔ «پیش‌بینی و آنتروپی زبان انگلیسی» — تقریباً عوض نشده‌اند. چهار سنجه داریم که همه خویشاوندند: آنتروپی متقاطع، سرگشتگی (PPL)، بیت به‌ازای هر نویسه (BPC) و بیت به‌ازای هر بایت (BPB). اگر یکی را بدانید، با کمی اطلاعات اضافه بقیه را هم می‌توانید حساب کنید. اگر جایی گیج شدید، فرمول‌ها را رد کنید و روی تفسیر تمرکز کنید: اینکه هر عدد بالا یا پایین بودنش یعنی چه. آزمایشگاه پایین درس بدون هیچ فرمولی همه‌چیز را نشانتان می‌دهد. آنتروپی: هر توکن چقدر خبر می‌آورد آنتروپی می‌سنجد که هر توکن یک زبان، به‌طور میانگین چقدر اطلاعات دارد. هرچه آنتروپی بیشتر، هر توکن اطلاعات بیشتری می‌آورد و برای نشان دادنش بیت بیشتری لازم است. فرض کنید می‌خواهیم زبانی بسازیم که جای یک نقطه را در یک مربع بگوید. اگر زبان فقط دو توکن داشته باشد — «بالا» و «پایین» — یک بیت برای نشان دادنش کافی است (۰ یا ۱). آنتروپی این زبان ۱ است. اگر چهار توکن داشته باشد — بالا-چپ، بالا-راست، پایین-چپ، پایین-راست — هر توکن جای دقیق‌تری می‌گوید ولی دو بیت لازم دارد. آنتروپی این زبان ۲ است. دوست فصل ۱ را یادتان هست که جمله‌های شما را تمام می‌کرد؟ اگر او همیشه درست حدس بزند شما چه می‌خواهید بگویید، حرف شما برای او هیچ اطلاعات تازه‌ای ندارد — آنتروپی صفر. آنتروپی در واقع می‌سنجد پیش‌بینی ادامهٔ یک زبان چقدر سخت است: زبانی با آنتروپی کمتر، قابل‌پیش‌بینی‌تر است. آنتروپی متقاطع: مدل چقدر سخت حدس می‌زند وقتی یک مدل زبانی را روی داده‌ای آموزش می‌دهیم، می‌خواهیم توزیع آن داده را یاد بگیرد — یعنی بتواند حدس بزند در آن داده بعد از هر چیز چه می‌آید. آنتروپی متقاطع مدل روی یک داده می‌سنجد که این حدس زدن برای مدل چقدر سخت است. این عدد به دو چیز بستگی دارد: خود داده چقدر قابل‌پیش‌بینی است — یعنی آنتروپی داده. توزیعی که مدل یاد گرفته چقدر با توزیع واقعی داده فرق دارد — این فاصله را با معیاری به اسم «واگرایی KL» می‌سنجند. در این فرمول P توزیع واقعی داده است و Q توزیعی که مدل یاد گرفته. به زبان ساده: آنتروپی متقاطع = آنتروپی داده + فاصلهٔ مدل از داده. اگر مدل داده را کامل یاد بگیرد، واگرایی صفر می‌شود و آنتروپی متقاطعش دقیقاً برابر آنتروپی خود داده است. پس می‌شود آنتروپی متقاطع یک مدل را «تقریب مدل از آنتروپی داده» دانست. مدل‌های زبانی را دقیقاً با کمینه کردن همین عدد آموزش می‌دهند. بیت، BPC و BPB واحد آنتروپی بیت است. اگر آنتروپی متقاطع مدلی ۶ بیت باشد، یعنی برای نشان دادن هر توکن ۶ بیت لازم دارد. ولی توکن‌سازی مدل‌ها فرق دارد (فصل ۲)، پس «بیت به‌ازای هر توکن» بین مدل‌ها قابل‌مقایسه نیست. برای همین بعضی از بیت به‌ازای هر نویسه استفاده می‌کنند: اگر هر توکن به‌طور میانگین ۲ نویسه باشد، BPC می‌شود ۶ ÷ ۲ = ۳. ولی نویسه‌ها هم در رمزگذاری‌های مختلف اندازهٔ متفاوت دارند — یک حرف فارسی در UTF-8 دو بایت است و یک حرف انگلیسی یک بایت. استانداردترین واحد، بیت به‌ازای هر بایت است. یک نکتهٔ زیبا: BPB می‌گوید مدل چقدر خوب متن را فشرده می‌کند. اگر BPB مدلی ۳٫۴۳ باشد، هر بایت ۸ بیتی را با ۳٫۴۳ بیت نشان می‌دهد — یعنی متن را به کمتر از نصف حجمش فشرده می‌کند. سرگشتگی (perplexity) همان آنتروپی متقاطع است، فقط به شکل توان: ۲ به توان آنتروپی متقاطع. اگر آنتروپی متقاطع می‌سنجد حدس زدن توکن بعدی چقدر سخت است، سرگشتگی می‌سنجد مدل هنگام حدس زدن چقدر مردد است. سرگشتگی یعنی مدل انگار بین چند گزینهٔ هم‌احتمال مردد است. مدلی که زبان چهارتوکنی مربع را کامل یاد گرفته، آنتروپی متقاطعش ۲ بیت است و سرگشتگی‌اش ۲ به توان ۲ = ۴: هر بار بین ۴ گزینه مردد است. سرگشتگی ۳ یعنی انگار هر بار از بین ۳ گزینه یکی را حدس می‌زند — و با واژگانی از ده‌ها هزار توکن، این عدد شگفت‌انگیز است. یک دردسر واحد هم هست: کتابخانه‌هایی مثل PyTorch آنتروپی را به‌جای بیت با نَت (لگاریتم طبیعی) حساب می‌کنند؛ آن‌وقت سرگشتگی e به توان آنتروپی است. به همین خاطر خیلی‌ها برای گزارش، سرگشتگی را ترجیح می‌دهند — عددش به واحد بستگی ندارد. محاسبه‌اش ساده است. مدل به هر توکن واقعیِ متن یک احتمال داده؛ «غافلگیری» هر توکن منفی لگاریتم آن احتمال است: چه عددی خوب است؟ سرگشتگی خوب به خود داده و روش محاسبه بستگی دارد. سه قاعدهٔ کلی: دادهٔ ساختارمندتر، سرگشتگی کمتر. کد HTML از متن روزمره قابل‌پیش‌بینی‌تر است: اگر دیدید، می‌دانید همان نزدیکی‌هاست. واژگان بزرگ‌تر، سرگشتگی بیشتر. سرگشتگی یک مدل روی کتاب کودک احتمالاً کمتر از «جنگ و صلح» است. و روی یک متن، سرگشتگی حرف‌به‌حرف از سرگشتگی کلمه‌به‌کلمه کمتر است، چون تعداد حروف خیلی کمتر از تعداد کلمه‌هاست. زمینهٔ طولانی‌تر، سرگشتگی کمتر. هرچه مدل متن قبلی بیشتری ببیند، کمتر مردد است. شانون در ۱۹۵۱ تا ۱۰ توکن قبلی را می‌دید؛ امروز صدها تا ده‌ها هزار. سرگشتگی شاخص خوبی برای توانایی مدل است: مدلی که در حدس توکن بعدی بد است، احتمالاً در کارهای واقعی هم بد است. گزارش GPT-2 این را خوب نشان می‌داد — نسخه‌های بزرگ‌تر همیشه سرگشتگی کمتری داشتند: پس‌آموزش (فصل ۲) به مدل یاد می‌دهد کار انجام دهد، نه اینکه توکن بعدی متن را دقیق‌تر حدس بزند. برای همین سرگشتگی مدل معمولاً بعد از SFT و RLHF بالا می‌رود — بعضی می‌گویند پس‌آموزش آنتروپی را «فرو می‌ریزد». کوانتیزیشن هم ممکن است سرگشتگی را به شکل غیرمنتظره‌ای عوض کند. پس سرگشتگی برای مقایسهٔ مدل‌های خام خوب است، نه دستیارهای آماده. کاربردهای غیرمنتظره سرگشتگی مدل روی متنی که در دادهٔ آموزشی‌اش دیده و حفظ کرده کمترین است. این یک ابزار کارآگاهی می‌سازد: کشف آلودگی داده (data contamination): اگر سرگشتگی مدلی روی سؤال‌های یک آزمون عجیب پایین است، احتمالاً آن آزمون در دادهٔ آموزشی‌اش بوده — و نمرهٔ مدل در آن آزمون قابل‌اعتماد نیست. (فصل ۴ مفصل به این برمی‌گردد.) حذف دادهٔ تکراری: دادهٔ تازه را فقط وقتی به دادهٔ آموزشی اضافه کنید که سرگشتگی مدل رویش بالا باشد — یعنی چیز تازه‌ای دارد (فصل ۸). کشف متن غیرعادی: سرگشتگی روی متن‌های غیرقابل‌پیش‌بینی بالاترین است — چه ایده‌های عجیب («سگ من در وقت آزادش فیزیک کوانتوم درس می‌دهد») چه چرت‌وپرت («خانه گربه رفتن چشم»). این آزمایشگاه همان مدل زبانی فصل ۲ را به کار می‌گیرد که روی متن درس‌های همین دوره آموزش دیده. سه نمونه را امتحان کنید، بعد جمله‌های خودتان را بنویسید: جمله‌ای که عیناً در درس‌ها آمده، کمترین سرگشتگی را دارد: مدل آن را «حفظ» کرده — این دقیقاً همان سازوکار کشف آلودگی داده است. جملهٔ عادی ولی تازه، سرگشتگی خیلی بیشتری دارد، چون مدل کوچک ما فقط همین درس‌ها را خوانده. و چرت‌وپرت از همه بالاتر است. توکن‌های قرمز همان جاهایی‌اند که مدل غافلگیر شده. برای حساب کردن سرگشتگی باید به احتمال‌هایی که مدل به هر توکن داده دسترسی داشته باشید — همان logprob فصل ۲. خیلی از ارائه‌دهنده‌های تجاری آن را نمی‌دهند یا محدود می‌دهند. مدل ما چون مال خودمان است، همه را دارد. سرگشتگی = ۲ به توان آنتروپی متقاطع. آنتروپی متقاطع ۲ بیت یعنی سرگشتگی ۴ — مثل زبان چهارتوکنی مربع که مدل باید هر بار بین چهار جا یکی را حدس بزند. سرگشتگی روی متنی که مدل دیده و حفظ کرده کمترین است. پس نمرهٔ خوب این مدل در آن آزمون شاید از «حفظ کردن» آمده باشد، نه «فهمیدن». پس‌آموزش مدل را برای انجام کار بهینه می‌کند و معمولاً سرگشتگی را بالا می‌برد، حتی وقتی مدل برای کاربر خیلی بهتر شده. پس سرگشتگی بالاتر این‌جا به معنی مدل بدتر نیست. بهترین ارزیابی، ارزیابی‌ای است که جای بحث نگذارد. این درس دو راه برای آن نشان می‌دهد: اجرا کردن خروجی و دیدن اینکه کار می‌کند یا نه، و مقایسهٔ خروجی با یک پاسخ مرجع. این درس روی ارزیابی پاسخ‌های باز تمرکز دارد. دلیلش این نیست که مدل‌های پایه برای کارهای بسته (مثل دسته‌بندی) استفاده نمی‌شوند — خیلی از سامانه‌ها دست‌کم یک بخش دسته‌بندی دارند. فقط ارزیابی کارهای بسته از قبل خوب شناخته شده است. درستی عملکرد: کار می‌کند یا نه؟ درستی عملکرد (functional correctness) یعنی بسنجید سامانه همان کاری را که باید، انجام می‌دهد یا نه. اگر از مدل خواستید وب‌سایتی بسازد، سایت ساخته‌شده نیازهای شما را برآورده می‌کند؟ اگر خواستید در رستورانی میز رزرو کند، رزرو انجام شد؟ این نهایی‌ترین سنجه است، چون مستقیم می‌پرسد محصول کارش را می‌کند یا نه. مشکل اینجاست که همیشه نمی‌شود آن را خودکار سنجید. تولید کد نمونه‌ای است که می‌شود. فرض کنید از مدل خواسته‌اید تابع پایتونی بنویسد که بزرگ‌ترین مقسوم‌علیه مشترک (ب.م.م) دو عدد را حساب کند. کافی است کد را اجرا کنید و ببینید برای ۱۵ و ۲۰ عدد ۵ را برمی‌گرداند یا نه: این کار تازه نیست: مهندسی نرم‌افزار سال‌هاست کد را با آزمون واحد (unit test) می‌سنجد، و سایت‌هایی مثل LeetCode راه‌حل‌ها را دقیقاً همین‌طور تصحیح می‌کنند. آزمون‌های معروف تولید کد مثل HumanEval از OpenAI و MBPP از گوگل، و آزمون‌های تبدیل متن به SQL مثل Spider و BIRD-SQL، همه با درستی عملکرد نمره می‌دهند. در این آزمون‌ها معمولاً برای هر مسئله k نمونه کد تولید می‌شود. اگر هر کدام از k نمونه همهٔ تست‌ها را رد کند، مسئله حل‌شده حساب می‌شود. نسبت مسئله‌های حل‌شده، نمرهٔ pass@k است. اگر از ۱۰ مسئله، مدل با k = ۳ پنج تا را حل کند، pass@3 آن ۵۰٪ است. طبیعتاً pass@1 از pass@3 و pass@3 از pass@10 کمتر است — همان «چند بار بپرسیم؟» درس ۶ فصل ۲. کارهای دیگری هم هدف قابل‌اندازه‌گیری دارند: ربات بازی تتریس را با امتیازش می‌سنجید؛ هوش مصنوعی‌ای که زمان‌بندی کارها را برای صرفه‌جویی انرژی می‌چیند، با مقدار انرژی صرفه‌جویی‌شده. شباهت با دادهٔ مرجع اگر نمی‌شود خروجی را «اجرا» کرد، رایج‌ترین راه مقایسه با دادهٔ مرجع است. هر نمونهٔ این داده شکل (ورودی، پاسخ‌های مرجع) دارد — مثلاً یک جملهٔ فرانسوی و چند ترجمهٔ درست انگلیسی‌اش. به پاسخ مرجع «حقیقت زمینه» (ground truth) هم می‌گویند. سنجه‌هایی که مرجع لازم دارند مرجع‌محوراند و آن‌هایی که ندارند بی‌مرجع. گلوگاه این روش، ساختن خود دادهٔ مرجع است. اگر آدم‌ها آن را بنویسند، یعنی کارکرد انسان را «استاندارد طلایی» گرفته‌ایم — ولی گران و کند است. برای همین خیلی‌ها دادهٔ مرجع را با هوش مصنوعی می‌سازند و فقط بازبینی‌اش را به انسان می‌سپارند، که خیلی کم‌زحمت‌تر از نوشتن از صفر است. شباهت دو متن باز را چهار جور می‌شود سنجید: (۱) از یک داور — انسان یا هوش مصنوعی — بپرسید، (۲) تطابق دقیق، (۳) شباهت واژگانی، (۴) شباهت معنایی. اولی موضوع درس ۵ است؛ سه تای بعدی را یکی‌یکی می‌بینیم. همین سنجه‌ها برای جست‌وجو (پیدا کردن چیزهای شبیه یک پرسش)، رتبه‌بندی، خوشه‌بندی، کشف ناهنجاری (چیزی که به هیچ‌چیز شبیه نیست) و حذف تکراری‌ها هم به کار می‌روند. در فصل ۶ (RAG) و فصل ۸ (داده) دوباره سراغشان می‌آییم. پاسخ دقیقاً برابر یکی از پاسخ‌های مرجع است؟ این برای کارهایی با جواب کوتاه و قطعی خوب کار می‌کند: «۲ به‌علاوهٔ ۳ چند می‌شود؟»، «موجودی حسابم چقدر است؟»، «پاریس برای فرانسه مثل ___ برای انگلستان». یک نسخهٔ آسان‌گیرتر: هر پاسخی که پاسخ مرجع را در خودش داشته باشد قبول است. اگر مرجع «۵» باشد، «جواب ۵ است» هم قبول می‌شود. ولی این دام دارد: آنه فرانک در ۱۲ ژوئن ۱۹۲۹ به دنیا آمد و جواب درستِ «چه سالی؟» می‌شود ۱۹۲۹. اگر مدل بگوید «۱۲ سپتامبر ۱۹۲۹»، سالِ درست داخل جوابش هست — ولی جوابش غلط است. برای کارهای پیچیده‌تر تطابق دقیق تقریباً هیچ‌وقت کار نمی‌کند. «حالت چطوره؟» را می‌شود به «چطوری؟»، «احوالت چطوره؟»، «حال شما خوبه؟» و ده‌ها شکل دیگر گفت. هر شکلی که در فهرست مرجع نباشد، غلط حساب می‌شود. پیش از هر مقایسه‌ای در فارسی باید متن را یکسان‌سازی کنید، وگرنه دو متنِ «یکسان» برابر حساب نمی‌شوند: «ي» و «ك» عربی با «ی» و «ک» فارسی برای کامپیوتر دو حرف متفاوت‌اند؛ «می‌کند» را بعضی با نیم‌فاصله می‌نویسند و بعضی با فاصله؛ «۵» فارسی با «5» انگلیسی فرق دارد. در پروژهٔ این فصل تابع normalize همین کار را می‌کند. شباهت واژگانی شباهت واژگانی می‌سنجد دو متن چقدر هم‌پوشانی دارند. ساده‌ترین شکلش: چه کسری از واژه‌های مرجع در پاسخ هم آمده؟ اگر مرجع «گربه‌های من موش‌ها را می‌ترسانند» باشد، پاسخ «گربه‌های من موش‌ها را می‌خورند» بیشتر واژه‌ها را دارد و پاسخ «گربه‌ها و موش‌ها همیشه دعوا می‌کنند» کمتر. پس اولی «شبیه‌تر» است. راه دیگر فاصلهٔ ویرایشی است: کمترین تعداد ویرایش برای تبدیل یک متن به دیگری. سه نوع ویرایش داریم: حذف («کتابها» ← «کتاب»)، درج («کار» ← «کارت») و جایگزینی («کتاب» ← «کباب»). مثلاً bad با یک ویرایش به bard می‌رسد و با سه ویرایش به cash؛ پس به اولی شبیه‌تر است. به این روش «تطبیق تقریبی» یا fuzzy matching هم می‌گویند. راه سوم هم‌پوشانی n-gram است: به‌جای تک‌واژه، دنباله‌های چندواژه‌ای را مقایسه کنید. «گربه‌های من موش‌ها را» دوتایی‌هایی مثل «گربه‌های من»، «من موش‌ها» و «موش‌ها را» دارد. سنجه‌های معروف این خانواده — BLEU، ROUGE، METEOR++، TER و CIDEr — فقط در جزئیات شمارش با هم فرق دارند. پیش از مدل‌های پایه این‌ها برای ترجمه خیلی رایج بودند؛ امروز کمتر. مرجع ناقص: پاسخ خوبی که شکلش در فهرست مرجع نیست، نمرهٔ کم می‌گیرد. شرکت Adept دید مدلش در بعضی آزمون‌ها بد نمره گرفته، نه چون غلط گفته، بلکه چون جواب درستش در مرجع نبود. مرجع غلط: برگزارکنندگان یک مسابقهٔ معتبر ترجمهٔ ماشینی در ۲۰۲۳ گفتند در دادهٔ خودشان ترجمه‌های مرجع بد زیادی پیدا کرده‌اند. شباهت بیشتر ≠ پاسخ بهتر: OpenAI دید نمرهٔ BLEU برای کدهای درست و غلط در HumanEval تقریباً یکی است. بهینه کردن BLEU، بهینه کردن درستی نیست. در این آزمایشگاه شش سنجه را روی یک جفت پاسخ ببینید. سه نمونهٔ آماده را امتحان کنید — مخصوصاً «دام شامل بودن» و «ي و ك عربی»: SQL را می‌شود اجرا کرد و دید جواب درست برمی‌گرداند یا نه — بی‌ابهام. سه گزینهٔ دیگر جواب درستِ یکتا ندارند. «۱۹۲۹» داخل پاسخ هست، پس شامل بودن قبولش می‌کند. ولی روز و ماه غلط است — همان دامی که سنجه‌های آسان‌گیر برایتان پهن می‌کنند. این سنجه‌ها فقط هم‌پوشانی ظاهری را می‌شمارند. پاسخ درستی که با کلمه‌های دیگری گفته شده، نمرهٔ کمی می‌گیرد — مشکلی که درس بعد سراغ حلش می‌رود. دو جمله می‌توانند هیچ کلمهٔ مشترکی نداشته باشند و یک معنا بدهند — یا همهٔ کلمه‌هایشان یکی باشد و دو معنای متضاد. برای سنجیدن «معنا» باید متن را به عدد تبدیل کنیم. به این عددها امبدینگ می‌گویند. ظاهر یا معنا؟ شباهت واژگانی می‌سنجد دو متن چقدر شبیه به نظر می‌رسند، نه اینکه چقدر یک معنا دارند. «چه خبر؟» و «حالت چطوره؟» تقریباً هیچ کلمهٔ مشترکی ندارند، ولی معنایشان نزدیک است. برعکسش هم هست. جملهٔ معروف «بخشش لازم نیست، اعدامش کنید» و «بخشش، لازم نیست اعدامش کنید» دقیقاً همان کلمه‌ها را دارند و فقط جای یک ویرگول فرق کرده — ولی سرنوشت یک آدم را عوض می‌کند. هر سنجهٔ واژگانی این دو را «تقریباً یکسان» می‌بیند. شباهت معنایی می‌خواهد خود معنا را مقایسه کند. برای این کار اول هر متن را به یک نمایش عددی تبدیل می‌کند که به آن امبدینگ (embedding) می‌گویند. برای همین به شباهت معنایی «شباهت امبدینگ» هم می‌گویند. امبدینگ چیست؟ کامپیوترها با عدد کار می‌کنند. امبدینگ یک نمایش عددی است که تلاش می‌کند معنای داده را نگه دارد. امبدینگ یک بردار است — یعنی فهرستی از عددها. مثلاً جملهٔ «گربه روی فرش نشسته» ممکن است این‌طور نمایش داده شود: [0.11, 0.02, 0.54]. در واقعیت این فهرست بین صد تا ده هزار عدد دارد. یادتان هست در درس ۲ فصل ۲، اولین لایهٔ ترنسفورمر «لایهٔ امبدینگ» بود؟ هر مدل زبانی هم در درونش امبدینگ می‌سازد و اگر به لایه‌های میانی‌اش دسترسی داشته باشید می‌توانید از آن‌ها امبدینگ بیرون بکشید. ولی معمولاً امبدینگ مدل‌هایی که مخصوص همین کار آموزش دیده‌اند بهتر است. شباهت کسینوسی حالا دو متن را چطور مقایسه کنیم؟ امبدینگ هر دو را حساب کنید و زاویهٔ بین دو بردار را بسنجید. سنجهٔ رایج شباهت کسینوسی است: دو بردار کاملاً هم‌جهت نمرهٔ ۱ می‌گیرند، دو بردار بی‌ربط حدود ۰، و دو بردار کاملاً مخالف ۱-. سنجه‌های معروف این خانواده BERTScore و MoverScore‌اند. شباهت معنایی به فهرست کامل پاسخ‌های مرجع نیاز ندارد، چون پاسخ هم‌معنی با کلمه‌های دیگر هم نمرهٔ بالا می‌گیرد. کتاب شباهت معنایی را در خانوادهٔ «دقیق» گذاشته، چون وقتی دو امبدینگ را داشته باشید، کسینوسشان دقیقاً حساب می‌شود. ولی خود امبدینگ را یک مدل ساخته، و مدل‌های مختلف امبدینگ‌های مختلف می‌سازند. اگر امبدینگ بد باشد، دو متن هم‌معنی هم نمرهٔ پایین می‌گیرند. و ساختن امبدینگ با مدل‌های بزرگ، خودش محاسبه و زمان می‌خواهد. امبدینگ خوب چیست؟ بردار [0.11, 0.02, 0.54] هیچ شباهتی به جملهٔ «گربه روی فرش نشسته» ندارد. پس از کجا بفهمیم امبدینگی خوب است؟ قاعدهٔ کلی: متن‌های شبیه‌تر باید امبدینگ‌های نزدیک‌تری داشته باشند. امبدینگ «گربه روی فرش نشسته» باید به «سگ روی چمن بازی می‌کند» نزدیک‌تر باشد تا به «پژوهش هوش مصنوعی خیلی جذاب است». راه دوم، سنجیدن فایدهاش در کار شماست: دسته‌بندی، پیشنهاد، جست‌وجو یا RAG. آزمون MTEB کیفیت امبدینگ‌ها را در ده‌ها کار مختلف می‌سنجد. امبدینگ فقط مال متن نیست. فروشگاه‌های اینترنتی برای محصول‌ها امبدینگ دارند و Pinterest برای تصویر، جست‌وجو و حتی کاربر. مرز تازه، امبدینگ مشترک برای چند نوع داده است: CLIP تصویر و متن را در یک فضا می‌گذارد، طوری که امبدینگ عکس یک ماهیگیر به امبدینگ متن «ماهیگیر» نزدیک باشد تا به «نمایش مد». همین امکان «جست‌وجوی عکس با متن» را می‌دهد. ImageBind این کار را برای شش نوع داده — از جمله صدا — انجام می‌دهد. امبدینگ کوچک ذهن‌یار در درس ۷ یک امبدینگ ساده از صفر می‌سازیم، بر پایهٔ یک ایدهٔ قدیمی زبان‌شناسی: «معنای هر واژه را از همسایه‌هایش بشناس.» اگر «دما» و «top-p» در درس‌ها مدام کنار واژه‌های مشترکی مثل «احتمال» و «نمونه‌برداری» بیایند، بردارشان هم شبیه می‌شود — بی‌آنکه کسی به مدل گفته باشد این دو به هم ربط دارند. مدل‌های امبدینگ واقعی همین ایده را روی میلیاردها جمله و با شبکه‌های عصبی پیاده می‌کنند. آزمایشگاه درس قبل را این بار با نمونه‌های معنایی امتحان کنید و به نوار آخر — شباهت معنایی — نگاه کنید: جفت هم‌معنی با کلمه‌های متفاوت، شباهت معنایی بیشتری از جفت بی‌ربط دارد — حتی با امبدینگ کوچک ما. ولی جفت سوم را ببینید: «بخشش لازم نیست، اعدامش کنید» در برابر «بخشش، لازم نیست اعدامش کنید». همهٔ سنجه‌ها، از تطابق دقیق تا شباهت معنایی، این دو را یکسان می‌بینند؛ چون یکسان‌سازی علامت‌ها را دور می‌ریزد و امبدینگ ما هم ویرگول را نمی‌بیند. هیچ سنجهٔ خودکاری بی‌عیب نیست — برای همین در درس بعد سراغ داوری می‌رویم که دست‌کم «می‌خواند». این دو تقریباً هیچ کلمهٔ مشترکی ندارند، پس هم‌پوشانی واژگانی‌شان نزدیک صفر است؛ ولی معنایشان نزدیک است و یک امبدینگ خوب بردارهای نزدیکی برایشان می‌سازد. ۱ یعنی هم‌جهت، حدود ۰ یعنی بی‌ربط (عمود)، و ۱- یعنی مخالف. در عمل امبدینگ متن‌ها کمتر به ۱- می‌رسد؛ بیشتر بین ۰ و ۱ می‌مانند. طول بیشتر لزوماً بهتر نیست. معیار، نزدیکی متن‌های هم‌معنی و فایده در کار واقعی است — همان چیزی که MTEB می‌سنجد. اگر هوش مصنوعی این‌همه کار سخت را خودکار کرده، چرا خود ارزیابی را نکند؟ این ایده — که به آن «هوش مصنوعی در نقش داور» می‌گویند — امروز شاید رایج‌ترین روش ارزیابی در محصول‌های واقعی باشد. و پرمناقشه‌ترین. چرا یک داور هوشمند؟ ایدهٔ ارزیابی هوش مصنوعی با هوش مصنوعی قدیمی است، ولی حدود ۲۰۲۰ و با GPT-3 عملی شد. گزارش LangChain در ۲۰۲۳ نشان داد ۵۸٪ ارزیابی‌های انجام‌شده روی پلتفرمشان با داورهای هوش مصنوعی بوده است. سریع، ساده و نسبتاً ارزان، در مقایسه با داور انسانی. بدون دادهٔ مرجع هم کار می‌کند؛ یعنی در محیط واقعی، جایی که برای سؤال کاربر هیچ «پاسخ درستی» از قبل ندارید، هم قابل‌استفاده است. هر معیاری را می‌شود از او خواست: درستی، تکرار، لحن توهین‌آمیز، توهم، و هر چیز دیگر. دلیلش را هم توضیح می‌دهد، که برای بازبینی نتایج خیلی به کار می‌آید. پژوهش‌ها نشان داده‌اند بعضی داورهای هوش مصنوعی همبستگی بالایی با داوران انسانی دارند. در آزمون MT-Bench، توافق GPT-4 با انسان‌ها به ۸۵٪ رسید — حتی بیشتر از توافق خود انسان‌ها با هم (۸۱٪). سه راه اصلی برای داوری هست. این‌ها نسخه‌های ساده‌شده‌اند: شکل سوم برای ساختن دادهٔ ترجیحی پس‌آموزش (فصل ۲)، انتخاب بهترین از N، و رتبه‌بندی مدل‌ها (درس بعد) به کار می‌آید. ابزارهای ارزیابی معیارهای آماده‌ای هم دارند: معیارهای داور استاندارد نیستند. «ربط» در Azure ممکن است با «ربط» در MLflow خیلی فرق داشته باشد، چون نمره به مدل و پرامپت داور بستگی دارد. پرامپت داور خوب پرامپت داور مثل هر پرامپت دیگری است (فصل ۵)، ولی باید سه چیز را روشن بگوید: وظیفه: مثلاً «ربط پاسخ با سؤال را بسنج». معیار: هرچه دقیق‌تر بهتر. مثلاً «تمرکز اصلی‌ات این باشد که پاسخ، با توجه به پاسخ مرجع، اطلاعات کافی برای جواب دادن به سؤال دارد یا نه». سیستم نمره‌دهی: دسته‌بندی (خوب/بد)، عدد گسسته (۱ تا ۵)، یا عدد پیوسته (بین ۰ و ۱). مدل‌های زبانی با کلمه بهترند تا عدد. داورها با دسته‌بندی بهتر کار می‌کنند تا با نمرهٔ عددی. اگر عدد می‌خواهید، گسسته از پیوسته بهتر است، و بازهٔ کوچک از بازهٔ بزرگ. رایج‌ترین بازه ۱ تا ۵ است. مثال بدهید: یک نمونه برای هر نمره، و اگر بشود، دلیل آن نمره. پرامپت معیار «ربط» در Azure AI Studio همهٔ این‌ها را دارد: وظیفه، معیار، بازهٔ ۱ تا ۵، و یک مثال با دلیل — سؤال «آسمان آبی است؟» با پاسخ مرجع «بله» و پاسخ تولیدشدهٔ «نه، آبی نیست» که به‌خاطر تناقض نمرهٔ ۱ تا ۲ می‌گیرد. داور پروژهٔ ما (درس ۸) دقیقاً همین ساختار و همین مثال را دارد. با همهٔ این مزیت‌ها، خیلی تیم‌ها به داور هوش مصنوعی شک دارند. «ارزیابی هوش مصنوعی با هوش مصنوعی» به نظر دوری می‌آید، و احتمالی بودن مدل‌ها آن را غیرقابل‌اعتماد نشان می‌دهد. نگرانی‌ها بی‌پایه نیستند: داور هم مثل هر مدلی احتمالی است: همان داور روی همان ورودی ممکن است دو نمرهٔ متفاوت بدهد. ثابت کردن دما کمک می‌کند (فصل ۲). یک پژوهش نشان داد گذاشتن مثال در پرامپت، ثبات GPT-4 را از ۶۵٪ به ۷۷٫۵٪ رساند — ولی هزینه‌اش را چهار برابر کرد، چون پرامپت بلندتر شد. و ثبات بالا یعنی دقت بالا نیست: داور ممکن است همیشه همان اشتباه را بکند. ابزارهای MLflow، Ragas و LlamaIndex هر سه معیار «وفاداری به متن» دارند، ولی اولی از ۱ تا ۵ نمره می‌دهد، دومی ۰ یا ۱، و سومی «بله» یا «نه». اگر برای یک پاسخ اولی بگوید ۳، دومی ۱ و سومی «نه»، کدام را باور کنید؟ از آن بدتر: محصول شما مدام عوض می‌شود، ولی ارزیابی‌اش باید ثابت بماند تا بتوانید تغییرات را بسنجید. فرض کنید نمرهٔ «انسجام» محصولتان ماه پیش ۹۰٪ بود و این ماه ۹۲٪ است. محصول بهتر شده؟ شاید. یا شاید همکارتان یک غلط تایپی را در پرامپت داور درست کرده و داور مهربان‌تر شده. به هیچ داوری که مدل و پرامپتش را نمی‌بینید اعتماد نکنید. داور پروژهٔ ما برای همین مدل، پرامپت و دمایش را همیشه چاپ می‌کند. هزینه و تأخیر اگر با GPT-4 هم پاسخ بسازید و هم داوری کنید، تعداد فراخوانی‌ها دو برابر می‌شود. سه معیار جدا یعنی چهار برابر. دو راه کم کردن هزینه: داور ارزان‌تر، یا نمونه‌گیری — فقط درصدی از پاسخ‌ها را داوری کنید. هرچه درصد بیشتر، اطمینان بیشتر ولی هزینه بیشتر (فصل ۴). اگر داوری را پیش از نشان دادن پاسخ به کاربر انجام دهید، تأخیر هم اضافه می‌شود. با همهٔ این‌ها، داور هوش مصنوعی خیلی ارزان‌تر از انسان است. سوگیری خودی: داور پاسخ‌های خودش را ترجیح می‌دهد. GPT-4 حدود ۱۰٪ و Claude-v1 حدود ۲۵٪ بیشتر به نفع خودشان رأی دادند. سوگیری جایگاه اول: داور پاسخی را که اول آمده ترجیح می‌دهد. جالب اینکه آدم‌ها برعکس‌اند و پاسخ آخر را ترجیح می‌دهند. راه‌حل: همان مقایسه را با جای عوض‌شده تکرار کنید. سوگیری پرحرفی: داور پاسخ بلندتر را ترجیح می‌دهد. یک پژوهش دید GPT-4 و Claude-1 پاسخ‌های حدوداً ۱۰۰ کلمه‌ای پر از اشتباه را به پاسخ‌های ۵۰ کلمه‌ای درست ترجیح دادند. خبر خوب: مدل‌های قوی‌تر کمتر این‌طورند. و همهٔ مشکل‌های عادی هوش مصنوعی، مثل حریم خصوصی: اگر داورتان یک API تجاری است، داده‌تان را برای آن می‌فرستید. چه مدلی داور باشد؟ داور می‌تواند قوی‌تر، ضعیف‌تر یا همان مدلی باشد که داوری می‌شود. هر حالت دلیل خودش را دارد: داور قوی‌تر: منطقی به نظر می‌رسد — تصحیح‌کننده باید از امتحان‌دهنده بیشتر بداند. ولی اگر مدل قوی‌تر را دارید، چرا با آن پاسخ نمی‌سازید؟ به‌خاطر هزینه و سرعت: با یک مدل ارزان پاسخ بسازید و با GPT-4 فقط ۱٪ پاسخ‌ها را داوری کنید. مشکل: قوی‌ترین مدل داوری ندارد. خود مدل (خودارزیابی): به نظر تقلب است، ولی برای «بررسی عقلانی» عالی است. اگر مدل خودش فکر کند جوابش غلط است، احتمالاً به آن مدل نمی‌شود تکیه کرد. پرسیدن «این جواب درست است؟» حتی می‌تواند مدل را به اصلاح جوابش هل بدهد: مدل گفته ۱۰ + ۳ = ۳۰؛ از خودش می‌پرسد درست است؟ و جواب می‌دهد «نه، ۱۳ است». داور ضعیف‌تر: بعضی می‌گویند داوری از تولید آسان‌تر است — هر کسی می‌تواند بگوید آهنگی خوب است یا نه، ولی همه نمی‌توانند آهنگ بسازند. پژوهش‌ها نشان داده مدل‌های قوی‌تر با نظر انسان هماهنگ‌ترند، ولی این برای داورهای همه‌منظوره است. یک جهت هیجان‌انگیز، داورهای کوچک تخصصی‌اند که برای یک داوری خاص با معیار و نمره‌دهی مشخص آموزش دیده‌اند و می‌توانند از داورهای بزرگ همه‌منظوره قابل‌اعتمادتر باشند: هنگام ساختن پروژهٔ این فصل، داور ما را با مدل qwen2.5:7b روی Ollama اجرا کردیم. سؤال «توکن چیست؟» بود. به پاسخ درست «توکن واحد کار مدل است؛ چیزی بین حرف و کلمه» نمرهٔ ۳ از ۵ داد و نوشت «توضیح بیشتری نیاز دارد». به پاسخ کاملاً غلط «توکن یعنی رمز عبور سایت» نمرهٔ ۲ داد — نه ۱، با اینکه راهنمای نمره‌دهی صریحاً می‌گوید پاسخ غلط ۱ می‌گیرد. داور سخت‌گیر است و فاصلهٔ درست و غلط را کم نشان می‌دهد. این همان چیزی است که قبل از اعتماد به هر داوری باید بسنجید: داور را هم باید ارزیابی کرد. در این آزمایشگاه پرامپتی را که داور پروژه می‌سازد ببینید. اگر Ollama و یک مدل روی کامپیوترتان دارید (درس ۸)، نمره و دلیل هم برمی‌گردد: با همهٔ محدودیت‌ها، استفاده از داور هوش مصنوعی رو به رشد است — و خیلی از کسانی که اول بدبین بودند حالا در محصول به آن تکیه می‌کنند. ولی داور هوش مصنوعی باید کنار ارزیابی دقیق و/یا ارزیابی انسانی بیاید، نه به‌جایشان. داور هم یک اپلیکیشن هوش مصنوعی است و ممکن است عوض شده باشد. اگر پرامپت داور تغییر کرده، دو عدد قابل‌مقایسه نیستند. اگر داور واقعاً یک پاسخ را ترجیح می‌داد، با عوض شدن جا، حرف هم باید عوض می‌شد. رأی ثابت به A یعنی رأی به جایگاه. سه داور قوی هزینه را چند برابر می‌کند. دو گزینهٔ اول هزینه را کم می‌کنند و گزینهٔ آخر تأخیر را. خیلی وقت‌ها نمرهٔ یک مدل برایتان مهم نیست؛ می‌خواهید بدانید کدام مدل برای شما بهتر است. برای رتبه‌بندی، گاهی مقایسهٔ دوبه‌دو از نمره دادن جداگانه بهتر کار می‌کند. نمره یا مقایسه؟ دو راه برای رتبه‌بندی مدل‌ها هست. در ارزیابی نقطه‌ای (pointwise) هر مدل را جداگانه نمره می‌دهید و به ترتیب نمره مرتب می‌کنید — مثل مسابقهٔ رقصی که داورها به هر رقصنده جدا نمره بدهند. در ارزیابی مقایسه‌ای مدل‌ها را کنار هم می‌گذارید و می‌پرسید کدام بهتر است — مثل اینکه رقصنده‌ها کنار هم برقصند و داورها بگویند کدام را بیشتر پسندیدند. برای کیفیت‌های سلیقه‌ای، مقایسه معمولاً آسان‌تر است: گفتن اینکه از دو آهنگ کدام بهتر است، از نمره دادن به هر کدام آسان‌تر است (همان دلیلی که در فصل ۲ دادهٔ مدل پاداش را به شکل مقایسه جمع می‌کردند). در هوش مصنوعی، Anthropic در ۲۰۲۱ اولین بار از ارزیابی مقایسه‌ای برای رتبه‌بندی مدل‌ها استفاده کرد. امروز جدول معروف Chatbot Arena از LMSYS با همین روش کار می‌کند: هر کسی پرامپتی می‌نویسد، دو پاسخ از دو مدل ناشناس می‌گیرد، به بهتری رأی می‌دهد، و فقط بعد از رأی اسم مدل‌ها را می‌بیند. ChatGPT هم گاهی دو پاسخ را کنار هم نشان می‌دهد و می‌پرسد کدام را ترجیح می‌دهید. خیلی از سؤال‌ها را باید با درستی سنجید، نه ترجیح. تصور کنید بپرسید «آیا امواج تلفن همراه با تومور مغزی ربط دارد؟» و مدل دو گزینهٔ «بله» و «نه» جلویتان بگذارد تا یکی را ترجیح دهید. رأی سلیقه‌ای این‌جا سیگنال غلط می‌سازد، و اگر با آن مدل را آموزش دهید، رفتارش خراب می‌شود. یا سؤال ریاضی‌ای که جوابش را نمی‌دانید بپرسید و مدل دو جواب بدهد و بپرسد کدام را ترجیح می‌دهید — اگر می‌دانستید، نمی‌پرسیدید! رأی ترجیحی فقط وقتی کار می‌کند که رأی‌دهنده در آن موضوع وارد باشد: وقتی هوش مصنوعی دستیار کاری است که خودتان بلدید. ارزیابی مقایسه‌ای را با آزمون A/B اشتباه نگیرید: در آزمون A/B هر کاربر فقط خروجی یکی از مدل‌ها را می‌بیند؛ در ارزیابی مقایسه‌ای، خروجی چند مدل را هم‌زمان. از مسابقه‌ها به رتبه هر مقایسه یک مسابقه است. از مجموع مسابقه‌های دو مدل الف و ب، درصد برد الف بر ب به دست می‌آید. با دو مدل، رتبه‌بندی ساده است. ولی با پنج مدل و این درصدها، رتبه‌بندی دیگر بدیهی نیست: برای تبدیل مسابقه‌ها به رتبه، از الگوریتم‌های امتیازدهی ورزش و بازی استفاده می‌شود — Elo (معروف از شطرنج)، Bradley–Terry و TrueSkill. Chatbot Arena اول از Elo استفاده می‌کرد ولی بعد به Bradley–Terry رفت، چون دید Elo به ترتیب رأی‌ها و پرامپت‌ها حساس است. این را خودتان ببینید: Elo بعد از هر مسابقه امتیازها را کمی جابه‌جا می‌کند، پس مسابقه‌های آخر اثر بیشتری دارند. وقتی مسابقه‌ها جفت‌به‌جفت و پشت سر هم وارد می‌شوند، Elo حتی ترتیب رتبه‌ها را به هم می‌ریزد. با ترتیب درهم به Bradley–Terry نزدیک می‌شود، ولی با هر ترتیب تازه کمی فرق می‌کند. Bradley–Terry همهٔ مسابقه‌ها را یک‌جا می‌بیند و برای همان مسابقه‌ها، همیشه همان رتبه را می‌دهد. رتبه‌بندی در واقع یک پیش‌بینی است: از مسابقه‌های گذشته رتبه می‌سازیم تا نتیجهٔ مسابقه‌های آینده را حدس بزنیم. رتبه‌بندی «درست» است اگر برای هر جفت، مدلِ بالاتر در بیش از نیمی از مسابقه‌ها برنده شود. هیچ جواب قطعی‌ای برای «رتبهٔ واقعی» نیست؛ کیفیت رتبه‌بندی را با دقت پیش‌بینی‌اش می‌سنجند. تعداد جفت‌ها با مربع تعداد مدل‌ها رشد می‌کند. LMSYS در ژانویهٔ ۲۰۲۴، ۵۷ مدل را با ۲۴۴ هزار مقایسه سنجید — که به‌نظر زیاد است، ولی ۵۷ مدل یعنی ۱۵۹۶ جفت، یعنی به‌طور میانگین فقط ۱۵۳ مقایسه برای هر جفت. خوشبختانه لازم نیست همهٔ جفت‌ها مستقیم مقایسه شوند: اگر الف از ب بهتر است و ب از ج، می‌شود نتیجه گرفت الف از ج بهتر است. به این ترایایی (transitivity) می‌گویند — ولی معلوم نیست ترجیح انسان واقعاً ترایا باشد. مدل تازه هم دردسر است: باید با مدل‌های موجود مقایسه شود و ممکن است رتبهٔ آن‌ها را هم عوض کند. اگر مدل اختصاصی خودتان را دارید، برای مقایسه با مدل‌های عمومی باید جدول خودتان را بسازید. یک راه کم کردن هزینه: جفت‌هایی که نتیجه‌شان دیگر روشن است را کمتر مقایسه کنید. ۲. استاندارد و کنترل کیفیت رأی‌گیری عمومی تنوع زیادی می‌آورد و تقلب در آن سخت است، ولی کنترل کیفیتش هم سخت است. داوطلب‌ها درستی پاسخ‌ها را چک نمی‌کنند و ممکن است پاسخ غلطِ خوش‌ظاهر را ترجیح دهند. بعضی پاسخ مؤدبانه می‌خواهند و بعضی بی‌پرده؛ اگر مدلی از گفتن یک جوک نامناسب سر باز بزند، ممکن است رأی منفی بگیرد — در حالی که شما به‌عنوان سازندهٔ محصول دقیقاً همین رفتار را می‌خواهید. پرامپت‌ها هم واقعی نیستند: از ۳۳ هزار پرامپت منتشرشده از Chatbot Arena در ۲۰۲۳، ۱۸۰ تا فقط «hello» یا «hi» بود. یک معمای منطقی ۴۴ بار پرسیده شده بود. پرامپت ساده را همه خوب جواب می‌دهند و بین مدل‌ها فرقی نمی‌گذارد. LMSYS برای حل این، پرامپت‌های سخت را جدا می‌کند و رتبه را فقط با آن‌ها می‌سازد. راه دیگر، داورهای آموزش‌دیده است — که گران است — یا گذاشتن مقایسه در خود محصول، که کاربر ممکن است بی‌دقت روی یکی کلیک کند. ۳. از «بهتر» تا «کافی» مقایسه می‌گوید کدام مدل بهتر است، نه اینکه چقدر خوب است یا برای شما کافی است یا نه. فرض کنید مدل الف ۷۰٪ تیکت‌های پشتیبانی را حل می‌کند و مدل ب در ۵۱٪ مقایسه‌ها از الف می‌برد. این ۵۱٪ به چند درصد تیکت حل‌شده تبدیل می‌شود؟ معلوم نیست. و اگر ب دو برابر گران‌تر باشد، بدون این عدد نمی‌شود حساب سود و هزینه کرد (آستانهٔ سودمندی فصل ۱). آیندهٔ ارزیابی مقایسه‌ای وقتی مدل‌ها از ما جلو بزنند، شاید نتوانیم به پاسخشان نمره بدهیم، ولی هنوز می‌توانیم بگوییم کدام بهتر است. مقالهٔ Llama 2 می‌گوید حتی وقتی نوشتهٔ مدل از توان بهترین برچسب‌زن‌ها فراتر می‌رود، آن‌ها هنوز در مقایسهٔ دو پاسخ بازخورد مفید می‌دهند. هرگز اشباع نمی‌شود: تا مدل تازه می‌آید، مقایسه معنی دارد — برخلاف آزمون‌هایی که درس ۱ دیدیم. تقلب در آن سخت است: نمی‌شود مدل را روی «جواب‌ها» آموزش داد. برای همین خیلی‌ها به جدول‌های مقایسه‌ای عمومی بیشتر از بقیه اعتماد دارند. مکمل است: در ارزیابی آفلاین کنار آزمون‌ها، و در محصول کنار آزمون A/B. این سؤال جواب درست دارد و کاربر آن را نمی‌داند — اگر می‌دانست نمی‌پرسید. رأی سلیقه‌ای این‌جا سیگنال خطرناک می‌سازد. بقیهٔ گزینه‌ها کارهایی‌اند که خود کاربر داور خوبی برایشان است. Elo امتیاز را بعد از هر مسابقه به‌روز می‌کند، پس ترتیب مسابقه‌ها روی نتیجه اثر دارد. Bradley–Terry همهٔ مسابقه‌ها را یک‌جا در نظر می‌گیرد. مقایسه فقط ترتیب را می‌گوید. اینکه این برتری کوچک در محصول شما به چه بهبودی تبدیل می‌شود، ارزیابی دیگری می‌خواهد. تا اینجا فقط «حس» می‌کردیم ذهن‌یار خوب جواب می‌دهد یا نه. در این درس برایش خط‌کش می‌سازیم: سرگشتگی، شش سنجهٔ شباهت، یک امبدینگ از صفر، و یک دادهٔ مرجع کوچک — و برای اولین بار ذهن‌یار را با عدد می‌سنجیم. این درس ادامهٔ پروژهٔ فصل ۲ است و در همان پوشهٔ zehnyar-project کار می‌کنیم. روش کار مثل قبل: VS Code را روی پوشهٔ پروژه باز کنید، از منوی Terminal پاورشل را باز کنید، هر فایل را با راست‌کلیک ← New File... بسازید، کد را با دکمهٔ «کپی» بردارید و با Ctrl+S ذخیره کنید. هیچ کتابخانهٔ تازه‌ای نصب نمی‌کنیم. قدم ۱ — پوشه‌های تازه یک پوشه برای دادهٔ مرجع (evals) و یک پوشه برای اسکریپت‌های این فصل لازم داریم: قدم ۲ — متن تازهٔ درس‌ها فصل ۳ متن تازه‌ای به دوره اضافه کرده. نسخهٔ تازه را دانلود کنید: دانلود متن درس‌ها تا فصل ۳ (lessons.txt). بعد آن را در پوشهٔ corpus بگذارید و وقتی پرسید، جایگزین فایل قبلی کنید. یادتان هست در فصل ۲ برای توکنایزر «اثر انگشت» ساختیم؟ همین که متن پیکره عوض شد، اثر انگشت عوض می‌شود و دفعهٔ بعد توکنایزر خودکار دوباره آموزش می‌بیند. یعنی خروجی‌های پروژهٔ فصل ۲ هم کمی عوض می‌شوند — کاملاً طبیعی است؛ مدل حالا متن بیشتری خوانده. قدم ۳ — خط‌کش‌ها: metrics.py همهٔ سنجه‌های درس‌های ۲ تا ۴ در یک فایل. طولانی است ولی هر بخشش ساده است؛ جدول‌های بعد از کد، بخش‌به‌بخش توضیحش می‌دهند. در پوشهٔ zehnyar بسازیدش: بخش ۱: سرگشتگی بخش ۲ و ۳: یکسان‌سازی و تطابق دقیق بخش ۴: شباهت واژگانی بخش ۵: کسینوس و همه با هم قدم ۴ — امبدینگ از صفر: embedding.py حالا امبدینگ، با همان ایدهٔ درس ۴: «معنای هر واژه را از همسایه‌هایش بشناس». سه قدم دارد که در توضیح بالای فایل آمده. در پوشهٔ zehnyar بسازیدش: این امبدینگ روی چند صد پاراگراف آموزش دیده و فقط واژه‌هایی را می‌شناسد که دست‌کم دو بار در درس‌ها آمده‌اند. همسایه‌های بعضی واژه‌ها منطقی‌اند و بعضی نه. مدل‌های امبدینگ واقعی روی میلیاردها جمله آموزش می‌بینند. ولی ایده دقیقاً همین است — و برای اولین بار عددی داریم که به معنا حساس است، نه فقط به ظاهر. قدم ۵ — دادهٔ مرجع: evals/qa.json حالا چند سؤال با پاسخ درستشان. قالب فایل JSON است: یک فهرست (کروشه) از چند شیء (آکولاد)، که هر کدام یک question و یک فهرست references دارد. در پوشهٔ evals بسازیدش: قدم ۶ — اجرا کنید آخرین فایل: اسکریپتی که چهار آزمایش را پشت هم انجام می‌دهد. در پوشهٔ projects/ch03_evaluation بسازیدش: دستور اجرا، از پوشهٔ اصلی پروژه: بار اول چند ثانیه طول می‌کشد، چون توکنایزر با متن تازه دوباره آموزش می‌بیند. باید خروجی‌ای شبیه این ببینید — این خروجی واقعی همین کد است: سرگشتگی: جمله‌ای که عیناً در درس‌ها آمده کمترین عدد را دارد؛ چرت‌وپرت بیشترین. همان «کشف آلودگی» درس ۲. تطابق دقیق: برای هیچ سؤالی برقرار نیست، حتی وقتی پاسخ ذهن‌یار کاملاً درست است. پاسخ باز تقریباً هیچ‌وقت عیناً مثل مرجع نیست. سؤال لایه‌ها: «شامل بودن» و هم‌پوشانی واژه‌ها کامل‌اند، ولی شباهت ویرایشی خیلی پایین است، چون پاسخ خیلی بلندتر از مرجع کوتاه «سه» است؛ شباهت معنایی هم متوسط است، چون مرجع فقط یکی دو کلمه است. هر سنجه یک چیز متفاوت می‌بیند. سؤال پرامپت: ذهن‌یار جواب را بلد نیست. شباهت معنایی تقریباً صفر است — امبدینگ درست فهمیده که این پاسخ ربطی به مرجع ندارد — ولی هم‌پوشانی واژه‌ها هنوز صفر نیست، چون چند واژهٔ عمومی مشترک‌اند. میانگین‌ها: هر سنجه عدد متفاوتی دربارهٔ همان پاسخ‌ها می‌گوید. پس همیشه بگویید با چه سنجه‌ای سنجیده‌اید. همین سنجه‌ها را در آزمایشگاه درس‌های ۳ و ۴ هم دیدید؛ آن‌ها نسخهٔ آمادهٔ همین کد را اجرا می‌کنند. چه چیزی ساختیم؟ سرگشتگی مدل زبانی ذهن‌یار روی هر متن، به‌همراه غافلگیری تک‌تک توکن‌ها. یکسان‌سازی متن فارسی — پیش‌نیاز هر مقایسه‌ای. پنج سنجهٔ دقیق: تطابق دقیق، شامل بودن، هم‌پوشانی واژه، شباهت ویرایشی، هم‌پوشانی دوتایی. یک امبدینگ از صفر و شباهت معنایی با کسینوس. اولین دادهٔ مرجع و اولین کارنامهٔ عددی ذهن‌یار. یک سؤال تازه به evals/qa.json اضافه کنید — مثلاً «خودنظارتی یعنی چه؟» با یک پاسخ مرجع از درس‌ها. حواستان به ویرگول‌ها باشد. دوباره اجرا کنید و نمره‌هایش را ببینید. به سؤال اول یک پاسخ مرجع دوم اضافه کنید که عیناً همان پاسخ ذهن‌یار باشد. کدام سنجه‌ها ۱ می‌شوند؟ (این یک تقلب است — ولی نشان می‌دهد چرا کیفیت دادهٔ مرجع این‌قدر مهم است.) در zehnyar/embedding.py مقدار WINDOW را از ۴ به ۲ و بعد به ۸ تغییر دهید و همسایه‌های «دما» را مقایسه کنید. بعد به ۴ برگردانید. سنجه‌های این درس همه دقیق‌اند ولی هیچ‌کدام نمی‌خوانند. در درس بعد یک داور می‌سازیم که پاسخ را می‌خواند و با یک راهنمای نمره‌دهی مشخص، از ۱ تا ۵ نمره می‌دهد. برای کامپیوتر «ي» و «ی» دو حرف کاملاً متفاوت‌اند. بدون یکسان‌سازی، دو متن یکسان «نابرابر» به نظر می‌رسند و همهٔ سنجه‌ها غلط می‌شوند. این همان ایدهٔ «معنا از همسایه‌ها» است. بردار هر واژه جمع وزن‌دار بردار همسایه‌هایش است؛ همسایه‌های مشترک، بردار شبیه می‌سازند. سنجه‌های درس قبل دقیق‌اند ولی پاسخ را نمی‌خوانند. حالا یک داور می‌سازیم که می‌خواند: با یک مدل واقعی، یک راهنمای نمره‌دهی روشن، و دو آزمون برای سنجیدن خودِ داور — ثبات و سوگیری جایگاه. مدل mock فصل ۱ فقط جدول جست‌وجوست و مدل فصل ۲ متن را ادامه می‌دهد؛ هیچ‌کدام نمی‌توانند داوری کنند. پس داور ما با Ollama کار می‌کند — یک برنامهٔ رایگان که مدل‌های واقعی را روی کامپیوتر خودتان اجرا می‌کند. اگر Ollama ندارید، کد را بسازید و اجرا کنید: داور صادقانه می‌گوید در دسترس نیست و پرامپتی را که می‌فرستاد نشانتان می‌دهد. نصب Ollama در قدم ۴ آمده و اختیاری است. قدم ۱ — انتخاب مدل داور در config.py یک تنظیم تازه اضافه می‌کنیم: داور از کدام ارائه‌دهنده استفاده کند. این جدا از ارائه‌دهندهٔ خود ذهن‌یار است — یادتان هست در درس ۵ دیدیم داور می‌تواند مدلی متفاوت با مدلِ داوری‌شده باشد؟ فایل را کامل با این عوض کنید: قدم ۲ — داور: judge.py قلب این درس. سه بخش اصلی درس ۵ — راهنمای نمره، پرامپت و تنظیمات — هر کدام یک متغیر جدا در بالای فایل است تا همیشه ببینید داورتان دقیقاً چیست. در پوشهٔ zehnyar بسازیدش: قدم ۳ — اجرا کنید اسکریپت این درس سه آزمایش دارد: نمره دادن به پاسخ‌های ذهن‌یار، آزمون ثبات (یک داوری، دو بار) و مقایسهٔ یک پاسخ کوتاهِ درست با یک پاسخ بلندِ غلط (هم سوگیری پرحرفی را می‌سنجد هم سوگیری جایگاه). در پوشهٔ projects/ch03_evaluation بسازیدش: اگر Ollama ندارید، این را می‌بینید — داور در دسترس نیست و پرامپتی را که می‌فرستاد نشان می‌دهد: قدم ۴ (اختیاری) — Ollama و یک داور واقعی Ollama برنامه‌ای رایگان است که مدل‌های زبانی باز را روی کامپیوتر خودتان اجرا می‌کند؛ بدون اینترنت (بعد از دانلود مدل) و بدون هزینه. مدل qwen2.5:7b حدود ۴٫۷ گیگابایت جا می‌گیرد و دست‌کم ۸ گیگابایت حافظهٔ رم لازم دارد. اگر کامپیوترتان ضعیف‌تر است، qwen2.5:3b (حدود ۲ گیگابایت) را امتحان کنید — داور ضعیف‌تری است، ولی خودش یک آزمایش جالب است. Ollama را نصب کنید از سایت ollama.com نسخهٔ ویندوز را دانلود و نصب کنید. بعد از نصب، Ollama در پس‌زمینه اجرا می‌شود (آیکونش کنار ساعت ویندوز). یک مدل دانلود کنید در پاورشل بزنید: ollama pull qwen2.5:7b — بسته به سرعت اینترنت چند دقیقه طول می‌کشد. به ذهن‌یار بگویید از کدام مدل استفاده کند کد فصل ۱ به‌طور پیش‌فرض دنبال مدل llama3.2:3b می‌گردد. در همان پاورشلی که پروژه را اجرا می‌کنید بزنید: $env:OLLAMA_MODEL = "qwen2.5:7b". این تنظیم تا وقتی آن پنجره باز است می‌ماند. دوباره اجرا کنید دستور قدم ۳ را دوباره بزنید. هر داوری با مدل محلی بین چند تا چهل ثانیه طول می‌کشد؛ کل اسکریپت چند دقیقه. این خروجی واقعی همین اسکریپت با qwen2.5:7b روی یک کامپیوتر خانگی است. خروجی شما ممکن است فرق کند — داور هم احتمالی است: داور را هم باید ارزیابی کرد. نمره‌ها را با درستی واقعی پاسخ‌ها مقایسه کنید: داور با پاسخ درست و غلط چطور رفتار کرده؟ اگر فاصلهٔ نمرهٔ درست و غلط کم است، داور برای تشخیص کیفیت حساس نیست. ثبات: با دمای صفر، دو داوری یکسان انتظار می‌رود — ولی این را باید دید، نه فرض کرد. مقایسهٔ کوتاه و بلند: اگر داور در هر دو دور پاسخ کوتاهِ درست را برگزیده، نه به طول رأی داده نه به جایگاه. اگر نتیجه «مساوی» شد، داور به جایگاه حساس بوده. یک داور = مدل + پرامپت + تنظیمات. خط اول خروجی هر سه را می‌گوید. هر عددی که از داور گزارش می‌کنید، باید همین خط را کنارش داشته باشد. اگر هشدار «Ollama بالاست ولی مدل … را ندارد» دیدید، یا مدل را با ollama pull نگرفته‌اید یا $env:OLLAMA_MODEL را در همین پنجرهٔ پاورشل تنظیم نکرده‌اید. اگر «Ollama در دسترس نیست» دیدید، برنامهٔ Ollama اجرا نیست؛ از منوی استارت بازش کنید. اگر خطای TimeoutError آمد، مدل برای کامپیوترتان سنگین است؛ مدل کوچک‌تر را امتحان کنید. چه چیزی ساختیم؟ سنجه‌های مدل زبانی: سرگشتگی، آنتروپی متقاطع، BPC و BPB. سنجه‌های دقیق: یکسان‌سازی فارسی، تطابق دقیق و شامل بودن، هم‌پوشانی واژه و n-gram، فاصلهٔ ویرایشی. یک امبدینگ از صفر و شباهت معنایی. یک دادهٔ مرجع کوچک و اولین کارنامهٔ عددی ذهن‌یار. یک داور خودکار با راهنمای نمره‌دهی، خواندن مقاوم نمره، آزمون ثبات و آزمون جابه‌جایی جایگاه — که وقتی مدل واقعی ندارد، صادقانه می‌گوید. در zehnyar/judge.py جملهٔ معیار را عوض کنید — مثلاً «معیار: فقط درستی معنا مهم است» را به «معیار: پاسخ باید کامل و مفصل باشد» — و دوباره اجرا کنید. نمره‌ها چه شدند؟ این همان «ابهام معیار» درس ۵ است: یک جمله، داوری دیگر. بعد به حالت قبل برگردانید. در SETTINGS دما را به 0.8 ببرید و آزمون ثبات را چند بار اجرا کنید. دو نمره چقدر از هم فاصله می‌گیرند؟ اگر Ollama دارید، qwen2.5:3b را هم بگیرید و با همان اسکریپت مقایسه کنید: داور ضعیف‌تر همان نمره‌ها را می‌دهد؟ حالا ابزار سنجیدن داریم. فصل ۴ از این ابزارها یک خط لولهٔ ارزیابی کامل می‌سازد: یک دادهٔ طلایی بزرگ‌تر و حساب‌شده‌تر، اجرای خودکار همهٔ سنجه‌ها، و داشبوردی برای مقایسهٔ مدل‌ها — تا بتوانیم بگوییم کدام مدل برای ذهن‌یار مناسب است. یک ارزیابی دروغین از نبود ارزیابی خطرناک‌تر است، چون به آن اعتماد می‌کنید. همان اصلی که در فصل ۱ با «تنزل آرام» دیدیم: کرش نکن، ولی وانمود هم نکن. داورها سوگیری جایگاه اول دارند. اگر برنده با عوض شدن جا عوض شود، رأی داور به محتوا نبوده. قیمتش؟ دو برابر فراخوانی — تصمیمی که هر تیم باید با بودجه‌اش بگیرد.