غول‌های خودبازگشت (Autoregressive) مانند GPT-4 و Claude، کد را توکن‌به‌توکن و با حرکت از چپ به راست در یک فایل تولید می‌کنند. آن‌ها قطعه‌کدهای کوتاه را به خوبی مدیریت می‌کنند، اما زمانی که یک توسعه‌دهنده بخواهد خطی را که در اعماق یک مجموعه کد بزرگ قرار دارد ویرایش کند، دچار مشکل می‌شوند. مدل باید تمام توکن‌های پایین‌دست را دوباره ارزیابی کند و حفظ یکپارچگی کل فایل به یک کابوس تبدیل می‌شود.

مدل‌های انتشار (Diffusion) از ابری از توکن‌های تصادفی شروع می‌کنند و به‌صورت تکرارشونده آن را نویززدایی می‌کنند تا زمانی که یک برنامه منسجم ظاهر شود. از آنجایی که فرآیند اصلاح، تمام توالی را به‌طور هم‌زمان تحت تأثیر قرار می‌دهد، مدل می‌تواند هر بخشی از کد را بدون نیاز به محاسبه مجدد بخش‌های انتهایی، درج، حذف یا بازنویسی کند.

چرا پارادایم فعلی در مهندسی نرم‌افزار با چالش روبروست

خودبازگشت مدل را مجبور می‌کند تا با کد مانند یک جریان خطی برخورد کند، که به این معناست که:

  • فقط به گذشته نگاه می‌کند. مدل هرگز توکن‌های آینده را نمی‌بیند، بنابراین نمی‌تواند پیش‌بینی کند که یک تغییر چگونه بر خطوط بعدی تأثیر می‌گذارد.
  • متن‌های پایین‌دست را دوباره محاسبه می‌کند. یک ویرایش باعث ایجاد زنجیره‌ای از پیش‌بینی‌های جدید می‌شود که منجر به افزایش تأخیر (latency) در بازنویسی کد (refactoring) یا رفع باگ می‌شود.
  • خطاهای بلندمدت را انباشته می‌کند. عدم تطابق‌های اولیه مانند گلوله برفی بزرگ می‌شوند و باعث می‌شوند فایل نهایی از نظر نحو (syntax) خراب یا از نظر منطقی ناسازگار باشد.

وقتی نیاز به پر کردن جاهای خالی (infill) دارید — مثلاً درج بدنه یک تابع در میان یک فایل یا به‌روزرسانی امضای یک API — ماهیت متوالی مدل‌های خودبازگشت، کند و خطاپذیر به نظر می‌رسد.

جایگزین انتشار: اصلاح تکرارشونده، نه پیش‌بینی گام‌به‌گام

ما با یک فایل کد مانند یک سیگنال نویزی برخورد می‌کنیم. فرآیند تولید در چندین مرحله انجام می‌شود:

  1. مقداردهی اولیه با نویز خالص. ما یک توالی از توکن‌های تصادفی را به مدل می‌دهیم که اغلب با یک جای‌گذار (placeholder) خاص نشان داده می‌شود.
  2. نویززدایی تدریجی. در هر مرحله، مدل نسخه کمی تمیزتر را پیش‌بینی می‌کند و توکن‌ها را به سمت یک کد معقول سوق می‌دهد.
  3. همگرایی به یک برنامه نهایی. پس از تعداد مشخصی مرحله، نویز از بین می‌رود و یک قطعه‌کد کاملاً شکل‌گرفته باقی می‌ماند.

از آنجایی که در هر مرحله کل توالی دوباره بررسی می‌شود، مدل می‌تواند هر توکنی را در هر مرحله‌ای تغییر دهد. این دیدگاه کلی به مدل اجازه می‌دهد تا یک import فراموش‌شده را اضافه کند، یک متغیر را تغییر نام دهد یا تورفتگی (indentation) یک بلوک را بدون نیاز به تولید مجدد تمام موارد بعدی، اصلاح کند.

مهندسی یک مدل انتشار متمرکز بر کد

انتقال مدل‌های انتشار از تصاویر به متن، یک کار ساده و آماده (plug-and-play) نیست. سه تغییر فنی در این زمینه اهمیت دارند.

۱. انتشار گسسته (Discrete diffusion)

پیکسل‌های تصویر نویز کسری را می‌پذیرند، اما یک توکن کد، دسته‌ای (categorical) است؛ یعنی یا یک کلمه کلیدی خاص است، یا یک شناسه (identifier) و یا یک نماد. بنابراین، ما از یک زنجیره مارکوف استفاده می‌کنیم که به‌طور مکرر توکن‌ها را با یک جای‌گذار خنثی (اغلب [MASK]) جایگزین می‌کند تا زمانی که توالی عملاً تصادفی شود. فرآیند معکوس یاد می‌گیرد که چگونه توکن‌های اصلی را مرحله‌به‌مرحله بازیابی کند.

۲. آگاهی ساختاری (Structural awareness)

زبان‌های برنامه‌نویسی قوانین نحوی (syntactic) سخت‌گیرانه‌ای را اعمال می‌کنند: تورفتگی (indentation) در پایتون محدوده (scope) را تعیین می‌کند، آکولادها در زبان‌های سبک C بلوک‌ها را مشخص می‌کنند و متغیرها باید قبل از استفاده تعریف شوند. یک مدل انتشار که با کد مانند متن ساده برخورد کند، خروجی‌های از نظر نحوی نامعتبر تولید خواهد کرد. برای جلوگیری از این امر، محققان از ماسک‌های توجه آگاه از نحو (syntax-aware attention masks) استفاده می‌کنند که نحوه توجه توکن‌ها به یکدیگر را محدود کرده و مدل را مجبور می‌کنند تا به سلسله‌مراتب، تو در تو بودن (nesting) و محدودیت‌های خاص هر زبان احترام بگذارد.

۳. اصلاح سلسله‌مراتبی (Hierarchical refinement)

مراحل اولیه انتشار، ساختار کلی را ترسیم می‌کنند — امضای توابع، تعاریف کلاس‌ها و سازماندهی ماژول‌ها. مراحل بعدی جزئیات ظریف مانند علائم نگارشی، فضاها (whitespace) و قراردادهای نام‌گذاری را صیقل می‌دهند. این استراتژی «از کلی به جزئی» (coarse-to-fine) مشابه روشی است که انسان‌ها پیش از پرداختن به جزئیات داخلی، طرح کلی یک برنامه را ترسیم می‌کنند، و باعث می‌شود محاسبات در هر مرحله به جایی که بیشترین اهمیت را دارد، هدایت شود.

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

جنبه خودبازگشت (Autoregressive) انتشار (Diffusion)
جریان تولید متوالی، از چپ به راست موازی، نویززدایی تکرارشونده
یکپارچگی کلی مستعد انحراف در اجراهای طولانی دید کل‌نگر نسبت به تمام توکن‌ها
موارد استفاده معمول چت، توضیح، قطعه‌کدهای سریع بازنویسی کد (refactoring)، رفع باگ، سنتز کد در مقیاس بزرگ

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

آنچه در ادامه باید دنبال کنید

  • خط‌لوله‌های ترکیبی. سیستم‌های آینده ممکن است به یک مدل خودبازگشت اجازه دهند نسخه اول را به سرعت پیش‌نویس کند، و سپس آن را برای صیقل دادن به یک مدل انتشار بسپارد.
  • ابزارسازی برای ماسک‌های ساختاری. پژوهشگران به اصلاح ماسک‌های توجه آگاه از نحو ادامه می‌دهند تا به مدل‌های انتشار کمک کنند محدودیت‌های خاص هر زبان را رعایت کنند.

نکته کلیدی

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