WorldTUI: من یک مدل 360M را آموزش دادم تا وانمود کنم که یک ترمینال است
آدرس مقاله: https://simedw.com/2026/10/21/world-model-terminal/ آدرس نظرات: https://news.ycombinator.com/item?id=50190363 امتیاز: 363 # نظرات: 114
TL;DR: من یک مدل زبان با پارامتر 360M را تنظیم کردم تا به عنوان ترمینال عمل کند. هیچ پوسته یا فایلی در پشت آن وجود ندارد: هر فشار کلید وارد میشود و مدل نحوه تغییر صفحه را پیشبینی میکند. میتواند فایلها را ایجاد کند، vim و tmux را اجرا کند، snake بازی کند، و معمولا چند دستور بعدا آنچه را که نوشتهاید به خاطر میآورد. بزرگترین دستاوردها آموزش تعمیر اشتباهات خود و رمزگشایی ردیفهای صفحه نمایش به صورت موازی بود. آن را در مرورگر خود امتحان کنید (208 مگابایت) و python را تایپ کنید تا ببینید که یک پوسته واقعی نیست.
نسخه ی نمایشی برای یک مرورگر دسکتاپ با WebGPU و صفحه کلید فیزیکی طراحی شده است. کروم یا اج بهترین مکان برای امتحان کردن آن است. باید روی یک تلفن مدرن کار کند، اما به آرامی.
وقتی برای اولین بار Genie 3 را در سال گذشته دیدم، شروع به تصور آینده ای کردم که در آن برنامه ها با کد نوشته نمی شوند بلکه یاد می گیرند. به جای اینکه یک موتور بازی صحنه را رندر کند، یک مدل فریم احتمالی بعدی را از ورودی های کاربر پیش بینی می کند.
طبیعتا می خواستم مدل دنیای خودم را آموزش دهم. اما من یک خوشه GPU عظیم یا انبوهی از داده های ویدیویی ندارم، بنابراین جاه طلبی خود را کاهش دادم: به جای دنیای بازی، یک ترمینال.
یک ترمینال مناسب بود. این فقط شبکهای از کاراکترها است تا پیکسلها، و من میتوانم با اجرای پوستههای واقعی، هر اندازه که میخواهم دادههای آموزشی کاملا برچسبگذاری شده تولید کنم. یک مدل زبانی از قبل آموزش دیده نیز از قبل ایده بسیار خوبی از آنچه ls یا cat باید چاپ کند دارد.
چیزی که من واقعا می خواستم بدانم این بود که آیا می تواند یک دنیای ثابت را حفظ کند یا فقط خروجی ترمینال قانع کننده ایجاد کند.
مدل نهایی مبتنی بر Qwen2.5-Coder-0.5B است که در جلسات ترمینال ضبط شده از برنامه های واقعی در حال اجرا در داکر به خوبی تنظیم شده است. به نمونه ویدیوها بروید
LLM های استاندارد یک اعلان می گیرند و سپس توکن ها را یکی یکی به انتها اضافه می کنند. این به خوبی به ترمینال نگاشت نمی شود. با فشار دادن یک کلید به تنهایی میتوان کاری انجام داد، مانند esc در vim، و خروجی همیشه به پایین نمیرود: clear صفحه را پاک میکند و مکاننما را به بالا میفرستد. بنابراین به جای پیش بینی جریان متن، باید تغییرات صفحه را پیش بینی کنم.
من ترمینال را بهعنوان شبکهای از نویسهها در نظر میگیرم، یکی در هر سلول. 1 مدل شبکه را مستقیما نمی بیند، بلکه دنباله ای از توکن ها را می بیند که محتویات آن و تغییرات ایجاد شده در آن را توصیف می کند.
هر جلسه با یک عکس فوری شروع می شود: اندازه صفحه، محتویات آن و مکان مکان نما.
اندازه بخشی از ورودی است، در 32×96 ثابت نیست. در نسخه ی نمایشی، می توانید ردیف ها و ستون ها را هنگام ایجاد یک صفحه شروع سفارشی تنظیم کنید.
این همچنین به من اجازه می دهد تا از طریق یک برنامه کاربردی شروع کنم. به آن یک فرمان bash، بافر vim یا یک بازی مار بدهید، و مدل سعی می کند از آنجا ادامه دهد. (از bash بهتر عمل می کند.)
پس از آن، هر فشار کلید به عنوان بایت های خامی که یک ترمینال واقعی ارسال می کند وارد می شود. حروف خودشان هستند، Enter \r است، Escape 0x1b و ← ESC [D و غیره است.
مدل پاسخ می دهد که با کدام ردیف ها بازنویسی شود و مکان نما به کجا ختم می شود:
به عبارت: در ردیف 0، که از ستون 17 شروع می شود، l را بنویسید، سپس مکان نما را به ردیف 0، ستون 18 منتقل کنید. 1 آخر به این معنی است که مکان نما قابل مشاهده است، زیرا برنامه های تمام صفحه گاهی اوقات آن را پنهان می کنند.
هیچ چیز اول پاک نمی شود شخصیت های جدید به سادگی بر روی شخصیت های قدیمی کشیده می شوند.
من به نشانه های جدید برای شخصیت ها نیاز نداشتم. Qwen در حال حاضر نشانه هایی برای تمام مقادیر 256 بایت دارد که من از آنها برای کاراکترها، مختصات و سایر اعداد کوچک دوباره استفاده می کنم. بنابراین مختصاتی مانند 17 یک نشانه می گیرد نه دو.
زمان نیز یک ورودی است. اگر چیزی فشار داده نشود، مدل به جای کلید، یک نشانه WAIT با مدت زمان دریافت می کند، به این ترتیب مار به تنهایی به حرکت خود ادامه می دهد.
وقتی به انتهای پنجره ترمینال رسیدید و enter را فشار دادید، هر خط باید یک بار به سمت بالا حرکت کند. من فقط میتوانم از مدل بخواهم که هر ردیف را دوباره در جای جدید خود خروجی بگیرد، اما این حدود 3000 توکن برای یک فشار کلید است.
هر عملیات یک ردیف را از صفحه قبلی کپی می کند. در این مثال، ردیف قدیمی 1 تبدیل به ردیف 0، ردیف 2 تبدیل به ردیف 1 و غیره می شود.
اکنون یک اسکرول به جای تقریبا 96، سه توکن در هر ردیف هزینه دارد.
همین ترفند پاک کردن صفحه، درج و حذف خطوط در vim و پیمایش در صفحات man را پوشش میدهد. همچنین می توانید یک ردیف را کپی کرده و سپس بخشی از آن را بازنویسی کنید.
در مجموع، این مدل از واژگان کوچکی از 333 توکن استفاده میکند: توکنهای 256 بایتی، 64 توکن ردیفی و تعدادی عملیات ویژه. رمزگشایی محدود به دستور زبان است، بنابراین هر پیشبینی بهروزرسانی معتبر صفحه نمایش است.
بعدا وقتی مدل را در مرورگر فشار میدهم، این واژگان کوچک برمیگردد.
من در ابتدا به دنبال مجموعه دادههای موجود از ضبطهای ترمینال، از جمله asciinema، بودم، اما نتوانستم مجموعهای را با تراز دقیق ضربهکلید به صفحه که نیاز داشتم، پیدا کنم.
ایده اصلی این بود که جلسات ترمینال قابل باوری را با اجرای دستورات واقعی در داخل کانتینرهای Docker، ضبط هر فشار کلید و صفحه نمایش پس از هر یک ایجاد کنیم.
اندازه ترمینال اکثرا 32×96 بود، با برخی 24×80 و 40×120، بنابراین مدل به یک سایز اضافه نمیشود.
با افزایش توانمندی مدل، مجموعه داده را گسترش دادم و در نهایت به 336 هزار قسمت رسیدم که تقریبا با 2 میلیارد توکن مطابقت دارد. برای مقایسه، مدل پایه در طول آموزش حدود 18 توکن را دید.
من از Qwen2.5-Coder-0.5B به عنوان نقطه شروع استفاده کردم. من به یک مدل کوچک نیاز داشتم تا به عملکرد بیدرنگ نزدیک شوم. به عنوان یک مدل کدنویسی، قبلا استفاده از CLI زیادی را نیز دیده بود.
من با انجام تنظیمات دقیق نظارت شده شروع کردم: تاریخچه صفحه نمایش و فشار دادن کلید، پیش بینی دلتای صفحه که توسط ترمینال واقعی تولید می شود.
تایپ معمولی به سرعت آموخته شد: یک حرف ظاهر می شود، بک اسپیس آن را حذف می کند، مکان نما حرکت می کند.
با این حال، در جلسات طولانی تر، خطاها شروع به ترکیب کردند: یک اشتباه در نام فایل که در بقیه جلسه منتشر شد.
برای پرداختن به این موضوع، صفحه ای از DAgger گرفتم، جایی که یک مدل به جای نمایش های ایده آل، از حالت هایی که بازدید می کند، یاد می گیرد. 2
دلتا صفحه نادرست مدل را به صفحه صحیح بعدی می برد. در اصل، یاد می گیرد که اشتباهات خود را "ترمیم" کند.
یک محدودیت مهم وجود دارد: مدل باید اطلاعات کافی برای استنباط اصلاح داشته باشد. هر کلمه ای که با یک تصحیح معرفی می شود باید در صفحه واقعی قبلی یا در تایپ کاربر ظاهر شده باشد، نه فقط در پیش بینی های خود مدل.
به عنوان مثال، اگر مدل نام فایلی را که قبلا ظاهر شده اشتباه نوشت، می توانم به آن آموزش دهم که آن را برطرف کند. اما اگر نام فایلی را لیست کند که هرگز ندیده است، نمی توانم انتظار داشته باشم که آن را به درستی دریافت کند.
آموزش در مورد آن نمونه ها در واقع به توهمات پاداش می دهد، که من واقعا به آنها نیازی ندارم.
حدود یک سوم از جلسات نمونه، نمونه های اصلاحی مفیدی را تولید کردند. من این کار را در سه دور تکرار کردم و هر بار اشتباهات را از آخرین مدل جمع آوری کردم.
خود اصلاحی یکی از موثرترین تغییرات آموزشی بود. همراه با برخی داده های آموزشی اضافی، PresetBench (تعریف شده در زیر) را از 24/47 به 38/47 در int4 بهبود بخشید.
در مجموع، آموزش مدل و اصلاحات بعدی آن تقریبا 75 ساعت GPU در RTX 4090 طول کشید.
من از سه تست استفاده می کنم. ShellBench دارای 106 فرمان در 24 جلسه bash دست نویس است که بر اساس خروجی دقیق امتیازدهی می شود. PresetBench دارای 47 مورد اسکریپت شده است که از شکست هایی که در نسخه ی نمایشی انجام دادم، گرفته شده است. هیچ یک از آزمون ها در داده های آموزشی ظاهر نمی شوند.
تست حافظه دارای 32 جهان است. هر کدام دو مقدار تصادفی را در دو فایل می نویسند، سپس آنها را در جلسات جداگانه می خوانند. یک دنیا تنها در صورتی می گذرد که هر دو بازخوانی دقیق باشند و در مجموع 64 بازخوانی ارائه می کنند. نام ها و ارزش ها هرگز در آموزش ظاهر نمی شوند. 3
بزرگترین تفاوت حافظه بود: WorldTUI 9/13 بازخوانی درستی داشت، در مقایسه با 2/13 و 3/13 برای مدل های درخواست شده.
هنوز تا یک سیستم فایل قابل اعتماد فاصله دارد. دستورات آشنا را به خوبی اجرا می کند، اما ترکیب آنها به روش های جدید می تواند به سرعت همه چیز را خراب کند. برای مثال، پس از رنگهای سبز پژواک >> رنگهای در حال اجرا اغلب خط الحاقی را نشان نمیدهند.
برای مدتی به طور کلی از مدل های اتورگرسیو دور ماندم. یک بازخرید کامل حدود 3000 توکن است، و تولید آنها در یک زمان برای چیزی که ظاهرا مانند یک ترمینال است، ناامید کننده به نظر می رسید.
اما آنها خیلی بهتر از گزینههایی که امتحان کردم، عمل کردند، بنابراین تسلیم شدم. با یک توکن در هر بار، تایپ کردن با سرعت ~38 میلیثانیه در هر کلید خوب بود، اما هر چیزی که کل صفحه را دوباره ترسیم کند (vim test.txt، man، شفاف) در RTX 4090 من تا 12 ثانیه طول میکشد، دقیقا همان طور که میترسم. زمان زیادی برای تجدید نظر در مورد اینکه آیا من به دفترچه راهنما نیاز دارم یا خیر. و من می خواستم این در مک من اجرا شود، تقریبا در زمان واقعی.
چیزی که من از دست داده بودم این بود که بیشتر ردیف های یک فریم به یکدیگر وابسته نیستند، بنابراین دلیلی وجود ندارد که آنها را یکی پس از دیگری ایجاد کنیم. من یک عنصر دسته ای را در هر ردیف اجرا می کنم. هر کدام همان تاریخچه قبلی (از جمله کش KV) را دریافت می کنند اما فقط به روز رسانی خود را تولید می کنند.
این هزینه رمزگشایی را از مجموع تمام ردیفها، تا 3000 قدم، به طول طولانیترین ردیف، تقریبا 100 مرحله، تغییر میدهد.
سپس مکان نما در پایان به مرحله خود تبدیل می شود که می تواند کل مجموعه به روز رسانی ردیف ها را ببیند.
این نیاز به یک ماسک توجه منطبق در طول تمرین داشت، اما بهبود سرعت ارزش آن را داشت. تاخیر p95 فریم بزرگ از 6.7 ثانیه به 0.87 ثانیه کاهش یافت.
این ممکن است بیش از حد خوب به نظر برسد که درست باشد، و همینطور هم شد. مسئله این است که از آنجایی که ردیف ها مستقل هستند، نمی توانند با هم هماهنگ شوند، که منجر به باز شدن vim در ردیف 3 به جای ردیف 0 یا چندین ردیف به اضافه کردن غذا برای مار در یک زمان شد.
معمولا رمزگشایی حدسی از یک مدل کوچک برای پیش نویسی توکن ها و یک مدل بزرگتر برای تأیید آنها استفاده می کند. به لطف توجه علی، چندین نشانه را می توان در یک پاس رو به جلو تأیید کرد.
در اینجا من از یک مدل برای هر دو استفاده میکنم: ردیفهای موازی یک پیشنویس تولید میکنند، که سپس مدل بهطور متوالی آن را تأیید میکند.
تایید کننده نشانه ها را تا اولین اختلاف نگه می دارد. از آنجا تصحیح خود را ایجاد می کند و پیش نویس باقیمانده را دوباره پیشنهاد می کند.
در مرورگر M4 Mac من، تایپ یک کاراکتر حدود 60 میلیثانیه طول میکشد. بهروزرسانی بزرگتر مانند تست مرد بهطور متوالی 2.5 ثانیه یا 0.9 ثانیه با پیشنویس و تأیید موازی طول میکشد. 5
من با Qwen2.5-Coder-0.5B شروع کردم که تقریبا 494M پارامتر دارد. من واقعا یک نسخه آزمایشی وب می خواستم، بنابراین باید آن را کوچک کنم. جدول جاسازی برای واژگان 151936 توکن آن 136 میلیون پارامتر است. من فقط به 333 توکن خود نیاز دارم، 6 تا بتوانم تقریبا همه آنها را رها کنم، که پارامترهای مدل را از 494M به حدود 360M می برد (990MB → 716MB).
سپس آن را به int4 کوانتیزه کردم، که آن را به 208 مگابایت رساند.
نسخه ی نمایشی مرورگر از پیاده سازی جاوا اسکریپت سفارشی رمزگشای Qwen استفاده می کند، با سایه بان های محاسباتی که در WGSL نوشته شده و از طریق WebGPU اجرا می شود. سایه زن ها وزن های 4 بیتی را در طول استنتاج باز می کنند. فعال سازی ها و حافظه نهان توجه از شناورهای 32 بیتی استفاده می کنند. همه استنتاج ها به صورت محلی در برگه اجرا می شوند.
تقطیر آن به لایه های کمتر چیزی به من آموخت که حافظه به کدام لایه ها بستگی دارد. معلم یک پست بازرسی قبلی بود که در ShellBench امتیاز 78/106 را کسب کرد. حذف فقط لایه 7 بدون آموزش مجدد به سختی باعث تغییر در دقت توکن بعدی شد: 99.3٪ به 98.9٪ کاهش یافت. اما بازخوانی دقیق حافظه از 64/64 به 0/64 کاهش یافت. این آزمایشها در تاریخ واقعی گنجانده شدهاند، بنابراین شکست ناشی از اشتباهات ترکیبی بر خروجی خود مدل نیست.
اولین دانش آموز مقطر من هر لایه زوج را نگه داشت، اما از لایه نهایی، 23، به جای 22 استفاده کرد. همچنان خروجی ترمینال قابل قبولی را می نوشت، اما تنها در 31/64 بازخوانی حافظه، مقدار مناسب را برمی گرداند. همیشه یکی از دو مقداری را که نوشته بود چاپ می کرد، اما تقریبا نیمی از دفعات را اشتباه انتخاب می کرد. این یک شانس است و پس از 480 میلیون توکن آموزشی بهبود نیافته بود.
آن دانش آموز لایه های 1، 7، 15 و 22 را رها کرده بود. دانش آموزی 16 لایه ای که آن چهار را نگه داشت، تمام 32 جهان آزمون حافظه را با 64/64 بازخوانی دقیق گذراند. هنوز هم تمام 32 جهان را در 4 بیت، در حدود 138 مگابایت پشت سر گذاشت. هر چند جای دیگری هزینه داشت: 65 فرمان ShellBench درست در برابر 78 معلم دریافت کرد. بنابراین یک دانش آموز می تواند خوب به نظر برسد و بی سر و صدا حافظه خود را از دست داده باشد.
این قسمتی بود که من بیشتر به آن علاقه داشتم. ایجاد یک فهرست دایرکتوری قانع کننده آسان است. چیزی که من می خواستم این بود که یک فایل ایجاد کنم، آن را ویرایش کنم، سرگردان شوم، و برگردم تا آن را بدون تغییر پیدا کنم.
اولین باری که tmux را شروع کردم، یک فایل را در vim باز کردم، آن را تغییر دادم، آن را ذخیره کردم و سپس در یک پنجره tmux دیگر محتوای به روز شده را با cat خواندم، احساس کردم دکتر فرانکنشتاین: زنده است!
برای من بسیار مهم بود که این کار فراتر از دستور bash عمل کند، بنابراین من روی vim، python، man pages، snake و حتی tmux آموزش دیدم.
در vim، سوئیچ حالت روی esc را کنترل می کند و به من اجازه می دهد ذخیره کنم، خارج شوم یا به حالت درج برگردم.
چیزی که واقعا ذهن من را به خود مشغول کرد tmux بود: می توانم چندین صفحه ایجاد کنم، در هر کدام کارهای مختلفی انجام دهم و بین آنها بپرم. این کامل نیست، اما یک مدل کوچک است.
حتی متغیرهای محیطی و بسط متغیر را مدیریت می کند.
از آنجایی که مدل پایه یک مدل کدنویسی است، کنجکاو بودم که چگونه Python REPL را مدیریت می کند. تلاش مناسبی انجام می دهد: اضافات کوچک معمولا درست هستند، و درک لیست یک لیست را باز می گرداند، هرچند اغلب با محتوای اشتباه. همچنین اشتباهات تایپی را تا حدودی می بخشد: پایتون پایتون را راه اندازی می کند، اما ython این کار را نمی کند.
من به کانتینرهای Docker اجازه دسترسی به اینترنت را ندادم، بنابراین ابزارهایی مانند سیاهگوش نسبتا خسته کننده هستند. پایتون میتواند عملیات بسیار سادهای را انجام دهد، اما هر چیزی سختتر پاسخهایی میدهد که مرا یاد توهمات دوران GPT-3 میاندازد.
گاهی اوقات، وقتی دایرکتوری های تودرتو ایجاد می کنم، گم می شود و ناگهان در مسیر دیگری قرار می گیرم. واضح است که فضای زیادی برای بهبود ثبات وجود دارد.
در آزمایش من، دمو در فایرفاکس 20× کندتر از کروم اجرا شد. از WebGPU در هر دو استفاده می کند. من موفق به ایجاد علت نشده ام.
مثل همیشه با پروژه هایی از این دست، سعی کردم ابتدا خودم آن را حل کنم و تنها سپس به نحوه برخورد دیگران با آن نگاه کردم.
در سال 2022، مردم قبلا ChatGPT را ترغیب می کردند که به عنوان یک ترمینال لینوکس عمل کند. اخیرا، GameNGen Doom را با استفاده از Diffusion شبیهسازی کرد و NeuralOS با رابط کاربری گرافیکی دسکتاپ مقابله کرد.
WorldTUI به ترفند اصلی ترمینال ChatGPT نزدیکتر است، با این تفاوت که به طور خاص روی فشار دادن کلیدها و به روز رسانی صفحه نمایش، از جمله برنامه های تمام صفحه مانند vim و tmux آموزش داده شده است.
من تا به حال انفجار ساختمان این. آیا مفید است؟ نه واقعا. اما برای یک مدل با پارامتر 360M که در تب مرورگر اجرا می شود، بسیار بهتر از آن چیزی است که انتظار داشتم.
چیزی که بیشتر از همه برایم جالب است این است که میتواند دنیایی تا حدودی ثابت را بدون اجرای هیچ یک از قوانین زیر آن حفظ کند.
بدیهی است که این یک مدل جهانی نسبتا ضعیف است، و من دوست دارم ببینم که این رویکرد تا کجا میتواند با سازگاری بهتر و روشی متفاوت برای ایجاد بهروزرسانیهای صفحه نمایش پیش برود، شاید با استفاده از انتشار به جای رمزگشایی اتورگرسیو.
یکی از آزمایشهایی که میخواهم بعدا امتحان کنم، آموزش روی هزاران برنامه کاربردی است که بهطور تصادفی تولید شدهاند، که هر کدام کنترلها و قوانین خاص خود را دارند. ایده این است که ببینیم آیا مدل میتواند رفتار برنامهای را که قبلا هرگز با آن مواجه نشده است، پیشبینی کند، با توجه به سرنخهای زمینهای کافی.
اینجا را امتحان کنید. این 208 مگابایت دانلود است، کاملا به صورت محلی اجرا میشود و در کروم بهترین عملکرد را دارد. سعی کنید آن را بشکنید و به من اطلاع دهید که چه چیزی پیدا می کنید.
به زودی وزن ها را می گذارم و لینک دانلود را اینجا می گذارم.
تک رنگ است: فقط کاراکترها، بدون رنگ یا سبک متن. کاراکترهای یونیکد، از جمله مرزهای طراحی جعبه tmux، قبل از رمزگذاری به ASCII نگاشت می شوند، بنابراین این مرزها به نشانه های کاراکتر چند بایتی نیاز ندارند. ↩
خیلی بی شباهت به نمونه برداری برنامه ریزی شده در پست midi من نیست. ↩
اینها تستهای فاصله کوتاه، با دستورات ۰–۱ مداخلهای هستند. ShellBench همچنین پایداری را در 18 دستور آزمایش می کند. ↩
هر دو مدل درخواست شده سه نمونه کار شده را دریافت کردند. آنها کل خروجی های فرمان را به جای به روز رسانی های جداگانه صفحه پیش بینی می کنند، بنابراین کار کاملا یکسان نیست. ↩
رمزگشایی حدسی سرعت بسیار بیشتری را در 4090 نسبت به M4 من می دهد. گمان من این است که گلوگاه بین پهنای باند محاسبه و حافظه جابجا می شود، اما من این موضوع را به درستی بررسی نکرده ام. ↩
سپس من می نویسم چه چیزی موثر بوده، چه چیزی شکست خورده است، و چه چیزی یاد گرفته ام. آزمایش بعدی را از طریق ایمیل دریافت کنید، چند پست در سال.
متن اصلی (انگلیسی)
WorldTUI: I trained a 360M model to pretend to be a terminal
Article URL: https://simedw.com/2026/10/21/world-model-terminal/ Comments URL: https://news.ycombinator.com/item?id=50190363 Points: 363 # Comments: 114