Các "gã khổng lồ" tự hồi quy (autoregressive) như GPT-4 và Claude tạo ra mã nguồn theo từng token, tiến dần từ trái sang phải trong một tệp. Chúng xử lý tốt các đoạn mã ngắn, nhưng lại gặp khó khăn khi lập trình viên muốn chỉnh sửa một dòng nằm sâu trong một kho mã nguồn (codebase) lớn. Mô hình phải đánh giá lại mọi token ở phía sau, và việc giữ cho toàn bộ tệp nhất quán trở thành một cơn ác mộng.
Các mô hình khuếch tán (diffusion models) bắt đầu từ một "đám mây" các token ngẫu nhiên và khử nhiễu lặp đi lặp lại cho đến khi một chương trình mạch lạc xuất hiện. Vì quá trình tinh chỉnh tác động lên toàn bộ chuỗi cùng một lúc, mô hình có thể chèn, xóa hoặc viết lại bất kỳ phần nào của mã nguồn mà không cần tính toán lại phần đuôi.
Tại sao mô hình hiện tại gặp khó khăn với kỹ thuật phần mềm
Tự hồi quy buộc mô hình phải coi mã nguồn như một luồng tuyến tính, điều này có nghĩa là nó:
- Chỉ nhìn về phía sau. Nó không bao giờ thấy được các token trong tương lai, vì vậy nó không thể dự đoán một thay đổi sẽ ảnh hưởng đến các dòng sau đó như thế nào.
- Tính toán lại văn bản phía sau. Một lần chỉnh sửa sẽ kích hoạt một chuỗi các dự đoán mới, làm tăng độ trễ khi tái cấu trúc (refactoring) hoặc sửa lỗi.
- Tích tụ các lỗi phạm vi dài. Những sai sót ban đầu sẽ tích tụ dần (hiệu ứng hòn tuyết lăn), khiến tệp cuối cùng bị lỗi cú pháp hoặc không nhất quán về mặt logic.
Khi bạn cần điền vào chỗ trống (infill)—chèn một thân hàm vào giữa tệp hoặc cập nhật một API signature—bản chất tuần tự của các mô hình tự hồi quy tạo cảm giác vụng về và dễ lỗi.
Giải pháp thay thế bằng khuếch tán: tinh chỉnh lặp lại, không phải dự đoán từng bước
Chúng ta coi một tệp mã nguồn như một tín hiệu nhiễu. Quá trình tạo mã diễn ra qua nhiều vòng:
- Khởi tạo với nhiễu thuần túy. Chúng ta cung cấp cho mô hình một chuỗi các token ngẫu nhiên, thường được đại diện bởi một trình giữ chỗ (placeholder) đặc biệt.
- Khử nhiễu dần dần. Ở mỗi bước, mô hình dự đoán một phiên bản sạch hơn một chút, thúc đẩy các token hướng tới mã nguồn hợp lý.
- Hội tụ thành một chương trình hoàn chỉnh. Sau một số bước cố định, nhiễu sẽ biến mất, để lại một đoạn mã hoàn chỉnh.
Vì mỗi bước đều xem xét lại toàn bộ chuỗi, mô hình có thể tinh chỉnh bất kỳ token nào ở bất kỳ giai đoạn nào. Góc nhìn tổng thể này cho phép nó thêm một lệnh import còn thiếu, đổi tên một biến, hoặc định dạng lại (re-indent) một khối mã mà không cần tạo lại tất cả những gì theo sau.
Xây dựng mô hình khuếch tán tập trung vào mã nguồn
Việc chuyển đổi mô hình khuếch tán từ hình ảnh sang văn bản không phải là một nhiệm vụ "cắm là chạy" (plug-and-play). Có ba sự thay đổi kỹ thuật quan trọng.
1. Khuếch tán rời rạc (Discrete diffusion)
Các pixel hình ảnh chấp nhận nhiễu phân số, nhưng một token mã nguồn là dạng phân loại (categorical)—nó có thể là một từ khóa, định danh (identifier) hoặc ký hiệu cụ thể. Do đó, chúng ta sử dụng một chuỗi Markov để thay thế lặp đi lặp lại các token bằng một trình giữ chỗ trung lập (thường là [MASK]) cho đến khi chuỗi đó thực sự ngẫu nhiên. Quá trình ngược lại sẽ học cách khôi phục các token ban đầu theo từng bước.
2. Nhận thức về cấu trúc (Structural awareness)
Các ngôn ngữ lập trình áp đặt các quy tắc cú pháp nghiêm ngặt: thụt lề xác định phạm vi (scope) trong Python, dấu ngoặc nhọn phân định các khối trong các ngôn ngữ kiểu C, và các biến phải được khai báo trước khi sử dụng. Một mô hình khuếch tán coi mã nguồn như văn bản thuần túy sẽ tạo ra đầu ra không hợp lệ về mặt cú pháp. Để ngăn chặn điều này, các nhà nghiên cứu thêm vào các mặt nạ chú ý nhận biết cú pháp (syntax-aware attention masks) nhằm giới hạn cách các token chú ý đến nhau, buộc mô hình phải tôn trọng thứ bậc, sự lồng nhau và các ràng buộc đặc thù của ngôn ngữ.
3. Tinh chỉnh phân cấp (Hierarchical refinement)
Các bước khuếch tán ban đầu phác thảo cấu trúc thô—chữ ký hàm (function signatures), định nghĩa lớp (class definitions), tổ chức module. Các bước sau đó sẽ trau chuốt các chi tiết nhỏ như dấu câu, khoảng trắng và quy ước đặt tên. Chiến lược "từ thô đến tinh" (coarse-to-fine) này mô phỏng cách con người lập dàn ý cho một chương trình trước khi hoàn thiện các chi tiết bên trong, đồng thời điều hướng tài nguyên tính toán vào những nơi quan trọng nhất ở mỗi giai đoạn.
So sánh song song: Tự hồi quy và Khuếch tán
| Khía cạnh | Tự hồi quy | Khuếch tán |
|---|---|---|
| Luồng tạo mã | Tuần tự, từ trái sang phải | Song song, khử nhiễu lặp lại |
| Tính nhất quán toàn cục | Dễ bị sai lệch trong các chuỗi dài | Cái nhìn tổng thể trên tất cả các token |
| Trường hợp sử dụng điển hình | Chat, giải thích, các đoạn mã ngắn | Tái cấu trúc, sửa lỗi, tổng hợp mã quy mô lớn |
Bảng trên cho thấy tại sao mỗi mô hình lại tỏa sáng trong các bối cảnh khác nhau. Các mô hình tự hồi quy chiếm ưu thế khi tốc độ và tương tác hội thoại là quan trọng. Các mô hình khuếch tán chiếm ưu thế khi sản phẩm cuối cùng phải đảm bảo tính đúng đắn về cú pháp và mạch lạc về cấu trúc, ngay cả khi chúng tiêu tốn thêm chu kỳ tính toán.
Những điều cần theo dõi tiếp theo
- Quy trình lai. Các hệ thống trong tương lai có thể cho phép một mô hình tự hồi quy phác thảo nhanh phiên bản đầu tiên, sau đó chuyển cho một mô hình khuếch tán để tinh chỉnh.
- Công cụ cho các mặt nạ cấu trúc. Các nhà nghiên cứu tiếp tục cải tiến các mặt nạ chú ý nhận biết cú pháp để giúp các mô hình khuếch tán tuân thủ các ràng buộc đặc thù của ngôn ngữ.
Điểm mấu chốt
Các mô hình khuếch tán thay đổi hoàn toàn cách tiếp cận tạo mã: thay vì tiến triển theo từng token, chúng điêu khắc cả một chương trình thông qua quá trình khử nhiễu lặp đi lặp lại. Cách tiếp cận này giải quyết điểm yếu cốt lõi của các hệ thống tự hồi quy—duy trì tính nhất quán toàn cục trong các kho mã nguồn lớn và có thể thay đổi. Mặc dù chậm hơn và tốn nhiều tài nguyên tính toán hơn, mô hình khuếch tán cung cấp một công cụ mạnh mẽ cho việc tái cấu trúc, sửa lỗi và bất kỳ kịch bản nào mà kết quả đầu ra sạch sẽ, đúng cú pháp quan trọng hơn tốc độ thuần túy. Hướng đi đầy triển vọng nhất có vẻ là một quy trình làm việc lai, kết hợp khả năng phác thảo nhanh của mô hình tự hồi quy với khả năng tinh chỉnh toàn diện của mô hình khuếch tán.
