Business Information Learning

  1. Trang chủ
  2. Lưu
  3. Thẻ
  4. Hỏi - Đáp

 
 
BIL'log, ⌚ 2022-03-27
***
☕ Nhàn đàm ICT: Machine Programming ░
Tác giả: Lê Văn Lợi
Bài đã đăng trên diễn đàn ICT_VN (ict_vn@googlegroups.com).
Ngày đăng: 27-03-2022.
-
Phác họa bài post:
⓪ Đề dẫn.
① OpenAI Codex.
② AlphaCode.
➡ Thể lệ thi.
➡ Cách tiếp cận.
➡ Máy đi thi.
Đọc thêm ⇛
➡ Code Generation.
➡ GitHub Copilot.

Để giúp anh/chị quyết định có đọc tiếp hay không, tôi xin phép cung cấp các thông tin liên quan đến bài post này như sau:

  • Chủ đề: Machine Learning.
  • Tính thời sự: Tháng 02/2022.
  • Thời gian đọc: Đọc hết: 7 phút, đọc lướt ý chính: 3 phút.

~

Hôm nay xin phép anh/chị chúng ta đàm luận về chủ đề “máy lập trình” (Machine Programming). Chủ đề này có vẻ quá khủng khiếp, đúng không ạ? Tôi tin là trên diễn đàn này nhiều anh/chị đã có trải nghiệm lập trình, thậm chí là tham gia nhiều cuộc thi lập trình. Để làm cho máy có thể lập trình được như người thì trước đây có thể nói là khoa học viễn tưởng. Ấy thế mà cách đây chừng hơn một tháng, báo chí ta và Tây đều rộ lên việc công ty DeepMind (một công ty con của Google) đã tạo ra một phần mềm có thể tham gia thi lập trình như người và điều gây ngạc nhiên hơn cả là “lập trình viên” này đạt trình độ “trung bình” so với tập hợp các thí sinh (người thật) tham gia! Thực hư thế nào, anh/chị có thể tham khảo bài báo của họ ở đây: Competition-Level Code Generation with AlphaCode. Nếu anh/chị đọc bài báo này rồi thì có thể bỏ qua phần tiếp theo bài post của tôi, vì tôi chỉ “diễn nôm” lại ý tưởng của họ. Nếu anh/chị chưa đọc thì tôi xin phép cung cấp thêm thông tin: bài báo của họ dài 74 trang, nội dung chính khoảng 31 trang, còn lại là tham chiếu và phụ lục.

Đề dẫn.

Đối với người “ngoại đạo” thì khái niệm “lập trình” nghe có vẻ bí hiểm và cao siêu, chứ đối với anh/chị trên diễn đàn này thì việc lập trình cũng “thường” thôi, đúng không ạ? 😊 Khi chúng ta học lập trình, thầy/cô dạy là phải xác định mục tiêu, chức năng của chương trình trước, rồi mới ngồi vào viết chương trình. Chúng ta cũng được khuyến nghị rằng một vấn đề lớn và khó thì trước hết cần chia vấn đề thành nhiều phần nhỏ, dễ hơn. Khi vấn đề không thể chia nhỏ hơn nữa (vấn đề “nguyên tử” - nhỏ nhất) thì cách thường được áp dụng là thiết kế thành các module, sub-routine hoặc function. Và khi viết phần mã lập trình (trong bất cứ ngôn ngữ lập trình nào), thói quen “chuẩn” mà chúng ta thường được khuyến nghị là viết thuyết minh trước, lập trình sau.

Ngẫm nghĩ một chút, chúng ta thấy lập trình từa tựa như viết bài post gửi lên diễn đàn này vậy. Chỉ có điều là chúng ta phải viết theo ngôn ngữ lập trình như C, C++, Python, Java, PHP, … chứ không phải viết tiếng Việt. Muốn máy compile/interpret (biên dịch/thông dịch) không phát sinh lỗi, chúng ta phải viết đúng chính tả, đúng ngữ pháp (cú pháp). Khi cho chương trình chạy (run) chúng ta lúc đó kiểm tra (test) xem chương trình đó có chạy “đúng” hay không? Và thông thường cũng phải xem xem có bao nhiêu trường hợp chạy đúng, bao nhiêu trường hợp chạy sai, … Đại ý thế.

Một cách nôm na ngắn gọn, theo các thông lệ thực tiễn tốt (good practices) về lập trình, chúng ta có thể hiểu giản lược như sau:

[Đề bài/thuyết minh] → [Đoạn mã chương trình] → [Kiểm tra kết quả]

OpenAI Codex.

Trước khi bàn đến cách tiếp cận của AlphaCode, mời anh/chị cùng xem qua cách OpenAI Codex tạo mã chương trình viết trong ngôn ngữ Python. Bài báo của họ tập trung vào cách tạo mã như sau:

[Docstring] → [Python function] → [Tests]

Trong đó:

  • Docstring: là thuyết minh (thường xuất hiện trước khi viết mã chương trình)
  • Python function: là mã của một hàm viết trong ngôn ngữ lập trình Python
  • Tests:  là phần kiểm tra xem phần mã vừa tạo ra chạy đúng ở mức độ nào.

Họ lấy mô hình gốc là GPT-3. Tôi đã giới thiệu mô hình GPT-3 trong bài post ngày 26-01-2022 với chủ đề là máy hiểu ngôn ngữ tự nhiên (Natural Language Understanding). Với khả năng của GPT-3, khi cho một chủ đề, GPT-3 có khả năng “viết” một “bản tin” không khác một nhà báo thực thụ là bao. Người ta tận dụng khả năng này của GPT-3. Nếu GPT-3 có khả năng viết một bản tin thì nó cũng có khả năng viết một đoạn mã chương trình khi cho một đầu vào thích hợp. Cái khác là GPT-3 chỉ được huấn luyện với dữ liệu ngôn ngữ tự nhiên – tức là đầu vào là ngôn ngữ tự nhiên và đầu ra cũng là ngôn ngữ tự nhiên thì Codex lấy đầu vào là ngôn ngữ tự nhiên (tiếng Anh) cho đầu ra là ngôn ngữ lập trình (Python). Tất nhiên, dữ liệu huấn luyện Fine-tuning phải tìm một nguồn thích hợp. Nguồn đó chính là GitHub (dung lượng 159 GB thu thập từ 54 triệu kho phần mềm công khai).

Vậy “trí tuệ” của Codex nằm ở đâu? Đó là câu hỏi “tò mò” chúng ta thường đặt ra, đúng không anh/chị?

Câu trả lời ngắn: lấy từ dữ liệu (kho dữ liệu khổng lồ).

Câu trả lời dài hơn: dữ liệu trên kho GitHub được dán nhãn như sau:

  • Với Docstring1 thì người lập trình viết đoạn mã Code1
  • Với Docstring2 thì người lập trình viết đoạn mã Code2
  • Với Docstring1000000 thì người lập trình viết đoạn mã Code1000000

Lưu ý: các Docstring1, Docstring2, …, Docstring1000000 là các thuyết minh bằng tiếng Anh.

Sau khi huấn luyện Fine-tuning với tập mẫu trên, khi cho một Docstring_mới thì máy sẽ biết cách tạo ra một Code_mới. Đơn giản là vậy. 😊

AlphaCode.

Cách đặt vấn đề của nhóm nghiên cứu thuộc công ty DeepMind hơi khác so với Codex: máy tham gia cuộc thi lập trình. Tất nhiên, máy cũng giống như người, phải tuân theo đúng quy định, thể lệ của cuộc thi.

Thể lệ thi.

Để hiểu máy thi lập trình như thế nào, mời anh chị cùng tìm hiểu qua hình thức thi trực tuyến. Cách tổ chức thi mỗi nơi một khác nhưng nhìn chung là thế này: người ta cho một đề thi, thường gồm 5-10 “vấn đề”, thời gian thi khoảng 3 tiếng đồng hồ. Người thi (hoặc nhóm thi) cần giải được càng nhiều “vấn đề” càng tốt. Đoạn mã chương trình, khi “nộp bài”, được gửi lên máy chủ (server). Tại đây, chương trình sẽ cho chạy thử hàng loạt test (các test này ẩn, thí sinh không biết). Thí sinh sẽ được thông báo là bài làm của họ có vượt qua được các test hay không (người ta không giải thích lý do vì sao được hay không được). Điểm chấm là tổ hợp của số kết quả đúng và thời gian chạy mỗi “vấn đề”. Mỗi một “vấn đề” gắn với một hệ số. Vấn đề càng khó thì hệ số càng cao. Ngôn ngữ lập trình thường dùng trong các cuộc thì là C++, Python.

Thế một “vấn đề” được người ta đặc tả như thế nào? Cấu trúc đặc tả chung như sau:

  • Mô tả vấn đề
  • Đặc tả dạng thức đầu vào (input), đầu ra (output)
  • Cho một số mẫu ví dụ về đầu vào (input), đầu ra (output).

Tôi có đính kèm một file là đặc tả đề thi có tên là “Backspace” – là một ví dụ về đề thi, để chúng ta dễ hình dung. (Ví dụ này tôi lấy từ bài báo AlphaCode.)

Ví dụ về đề thi có tên là "Backspace". Nguồn: AlphaCode.

-

Cách tiếp cận.

Nếu anh/chị bỏ chút thời gian đọc đề thi (như ví dụ đã dẫn), thì chúng ta sẽ có cảm giác là đến người có nhiều thời gian ngồi lập trình “mòn cả ghế” còn thấy khó thì máy làm sao mà làm được nhỉ? Tuy nhiên, nếu chúng ta nhớ lại cách tiếp cận của dịch máy: phiên dịch văn bản từ ngôn ngữ này sang ngôn ngữ khác bằng cách học theo các bài dịch do người thật dịch (cả hai phương pháp SMT (Statistical Machine Translation) và NMT (Neural Machine Translation) có cùng cách tiếp cận), thì chúng ta dễ dàng nhận thấy vấn đề này hoàn toàn tương tự như dịch máy. Nếu chúng ta coi “đề thi” được viết trong ngôn ngữ tự nhiên (tiếng Anh) thì bài toán trên trở thành: phiên dịch đoạn văn bản tiếng Anh (đề thi) ra đoạn văn bản được viết bằng ngôn ngữ lập trình (phần lập trình tham gia cuộc thì)!

Chúng ta có thể mô tả một cách giản lược như sau:

[Đề thi (tiếng Anh)] → [Đoạn mã lập trình (C++, Python, …)]

Trong dịch máy (Machine Translation) người ta tách đoạn văn bản gốc thành từng câu và máy dịch từng câu một. AlphaCode có cách tiếp cận tương tự: họ tách đề thi thành từng “vấn đề” và người ta phiên dịch từng “vấn đề” thành “giải pháp” – “giải pháp” chính là đoạn mã lập trình:

[Vấn đề] → [Giải pháp]

-

▓ Dữ liệu huấn luyện DeepMind lấy ở đâu? Đến đây, chắc hẳn anh/chị cũng đoán được rồi: họ lấy dữ liệu từ các cuộc thi. AlphaCode học theo cách tiếp cận của Codex, nhưng để mô hình có thể “thi” được, kiến trúc của AlphaCode có khác so với cách tiếp cận dịch máy thông thường. Một cách khái quát, kiến trúc này bao gồm 4 bước:

Bước 1:     Huấn luyện Pre-training (dữ liệu autoregressive: tự động tiếp diễn). Dữ liệu lấy từ GitHub – dữ liệu không dán nhãn. Mục tiêu của bước này là để mô hình “thông thạo” ngôn ngữ lập trình! Nếu anh/chị nhớ lại cách tiếp cận của GPT và BERT (bài tôi post lên diễn đàn này (ICT_VN) ngày 26-01-2022) thì đây là bước mà mô hình “nạp” tri thức – tức là hiểu biết về lập trình ở mức độ khái quát.

Bước 2:     Huấn luyện Fine-tuning. Dữ liệu lấy từ các cuộc thi và dán nhãn: “vấn đề” → “giải pháp” – “vấn đề” được viết bằng tiếng Anh, còn “giải pháp” được viết bằng ngôn ngữ lập trình (C++, Python). Anh/chị có thể hình dung tập mẫu dữ liệu một cách tượng trưng như sau:

[Vấn đề 1] → [Giải pháp 1]

[Vấn đề 2] → [Giải pháp 2]

[Vấn đề 1000000] → [Giải pháp 1000000]

Đến đây, khi chúng ta cấp đầu vào là “vấn đề” thì mô hình sẽ cho đầu ra “giải pháp”. “Giải pháp” là đoạn mã chương trình viết trong ngôn ngữ lập trình C++ hoặc Python.

Bước 3:     Tạo một lượng lớn “giải pháp” từ một “vấn đề”. Anh/chị có thể chất vấn: sao cần làm bước này làm gì? Trả lời: khi đi thi, từ một “vấn đề”, người thi có thể nộp nhiều “giải pháp”. Chú ý rằng, “giải pháp” có thể đúng, có thể sai. Vì vậy, khi nộp nhiều “giải pháp” thì xác suất có “giải pháp” đúng sẽ cao hơn. Từ một “vấn đề”, họ tạo ra hàng triệu “giải pháp” cho “vấn đề” đó. Khoảng một nửa số “giải pháp” được viết bằng ngôn ngữ C++, số còn lại được viết bằng Python.

Bước 4:     Đối với cuộc thi mà AlphaCode tham dự, với mỗi “vấn đề” họ chỉ được phép nộp tối đa là 10 “giải pháp”. Vì vậy, họ phải chọn 10 “giải pháp” tốt nhất để nộp bài. Đối với anh/chị tò mò về kỹ thuật thì cách họ làm có 2 bước: lọc (Filtering) và phân cụm (Clustering). Tôi xin phép không đi sâu vào chi tiết nhưng bản thân bài toán chọn ra 10 “giải pháp” tối ưu cũng đã là một câu chuyện thú vị.
-

Máy đi thi.

  • Địa điểm thi: Codeforces.
  • Thời gian thi: từ ngày 01/12/2021 đến ngày 28/12/2021.
  • Số lần tham gia thi: 10.
  • Số thí sinh tham gia: 5,000+.

Người ta xếp hạng các thí sinh theo thang 100. Thí sinh giỏi nhất đứng hạng 1 (thứ nhất) và thí sinh kém nhất đứng hạng 100. Thế máy AlphaCode đứng hạng bao nhiêu? Vì tham gia 10 cuộc thi nên họ phải tính thứ hạng chung cho cả 10 cuộc thi: thứ 54.3 – dưới trung bình một tý.

Nếu nộp nhiều hơn 10 “giải pháp” (chỉ để thử hệ thống của họ - khi thi thì không được phép), AlphaCode đạt được thứ hạng 48.8 – trên trung bình (50) hơn 1 điểm phần trăm.

⚠ Chú ý: khi đọc báo, chúng ta thấy các báo đưa tin máy đi thi đạt 54.3%. Con số 54.3% rất dễ gây hiểu nhầm: số % càng cao thì máy càng giỏi. Không phải vậy. Ngược lại mới đúng: số % càng thấp thì thứ hạng càng cao, máy càng giỏi.

:

Đến như một nghiên cứu khoa học, các nhà khoa học thời nay cũng biết cách “giật tít”, gây sốc cho người đọc! 😊

Đọc thêm

Bàn về ứng dụng các mô hình Codex và AlphaCode vào thực tế. Về cơ bản, tôi hy vọng là anh/chị đã biết được thực hư câu chuyện “máy thi lập trình” như thế nào rồi. Bài post của tôi đã kết thúc. Bây giờ tôi xin phép bàn thêm là liệu các mô hình Codex, AlphaCode có ứng dụng được vào việc gì không?

Code Generation.

Trước khi bàn đến ứng dụng, chúng ta hãy cùng rà soát lại cách Codex và AlphaCode “lập trình”. Về bản chất, các mô hình này “tạo mã lập trình” – trong tiếng Anh người ta gọi là Code Generation. Nếu anh/chị nhớ lại, Code Generation đã được nhiều công ty tìm cách tiếp cận từ khá sớm. Theo hiểu biết của tôi thì sớm nhất có lẽ là phần mềm của IBM có tên là Rational Rose. Rational Rose lấy đầu vào là UML (Unified Modeling Language) và đầu ra là một “khung phần mềm” gồm nhiều thứ, trong đó có các đoạn mã chương trình. Hay như Oracle, người lập trình có thể tạo mã phần mềm (chương trình được viết bằng ngôn ngữ Java) xuất phát từ cấu trúc của một bảng (table) trong một cơ sở dữ liệu (database). Phần mềm được tạo ra này có hàng loạt chức năng như thêm bớt, sửa đổi, liệt kê các bản ghi (record) của chính bảng đó. Chẳng hạn, nếu có thời gian và tò mò, anh/chị có thể tham khảo ở đây.

-

Quan sát hai giải pháp trên (Rational RoseOracle), chúng ta để ý thấy có một điểm khác so với cách tạo mã của Codex và AlphaCode:

Rational Rose:            [UML] → [Mã chương trình]

Oracle:                        [CSDL] → [Mã chương trình]

Nghĩa là khác nhau ở đầu vào. Rational RoseOracle cần người dùng phải có kiến thức về kỹ nghệ phần mềm (software engineering), cụ thể là phải biết ngôn ngữ UML hoặc phải có kiến thức về cơ sở dữ liệu. Còn Codex và AlphaCode chỉ cần người dùng biết viết tiếng Anh, mà cũng chỉ cần ở mức cơ bản thôi! (Trong tương lai tôi hy vọng có ai đó, hoặc nhóm nào đó, chuyển ngữ từ tiếng Việt sang tiếng Anh, tiếp theo dùng các mô hình như Codex/AlphaCode để chuyển ngữ từ tiếng Anh ra các đoạn mã lập trình. 😊)

Codex, AlphaCode:    [Ngôn ngữ tự nhiên] → [Mã chương trình]

-

GitHub Copilot.

Vào thời điểm hiện nay, đoạn mã lập trình do Codex hoặc AlphaCode tạo ra chưa chắc đã đúng cú pháp (nghĩa là chưa chắc đã compile). Và nếu đã đúng cú pháp rồi thì đoạn mã đó chưa chắc đã chạy đúng (đúng logic). Nghĩa là chẳng có gì đảm bảo để mã tạo ra “chạy” được cả. Tuy không chắc chắn đúng, nhưng rõ ràng là chúng có thể đưa ra gợi ý rất tốt cho người lập trình. Đó là ý tưởng mà Codex đã phối hợp với GitHub đưa ra một ứng dụng khá hấp dẫn: Your AI pair programmer (tạm dịch: AI song hành lập trình cùng bạn). Đại ý nó giống như autocomplete: khi soạn thảo chương trình, người lập trình gõ một đoạn văn bản khởi đầu, máy sẽ đoán ý người lập trình, rồi nó đưa ra gợi ý cho phần tiếp theo. Phần gợi ý của AI thường áp dụng cho hàm (function) – đầy đủ từ đầu đến cuối! Nó chỉ gợi ý thế thôi, còn đoạn mã mà nó gợi có đúng cú pháp hay không, đoạn đấy có chạy đúng hay không thì trách nhiệm thuộc về người lập trình. Tức là trách nhiệm chính là người lập trình còn bạn “AI song hành” kia chỉ đóng vai “nghe nhạc hiệu – đoán chương trình” (nhại một chương trình của VTV trước đây). Nhưng như thế cũng quý lắm rồi! 😊

 

GitHub Copilot đang ở giai đoạn technical preview. Nếu anh/chị muốn thử trải nghiệm thì anh/chị phải đăng ký (Sign Up). Tôi đã đăng ký và có một vài trải nghiệm tuy đơn giản nhưng cũng thú vị. Tôi xin kể ra đây quá trình đăng ký của tôi để anh/chị nếu hứng thú thì cùng thử cho vui:

  • Trước hết, anh/chị cần có một tài khoản trên GitHub (đăng ký miễn phí).
  • Phần cuối trang GitHub Copilot, anh/chị kích chuột vào đường link Sign up for the technical preview.
  • Tiếp theo là đợi … Tôi đợi khá lâu, hình như 10 ngày hay 2 tuần gì đó. Chắc người ta còn phải kiểm tra một số tiêu chí trước khi quyết định chấp nhận hay không.
  • Sau đó, họ gửi một thư phúc đáp vào địa chỉ email mà anh/chị đã đăng ký GitHub.
  • Trong thư phúc đáp, người ta có đầy đủ hướng dẫn cho anh/chị để trải nghiệm việc Codex hỗ trợ coding như thế nào.
  • Việc thử nghiệm chạy trong phần mềm Visual Studio Code (là phần mềm soạn thảo dành cho các ngôn ngữ lập trình).
  • Như tôi trải nghiệm thì GitHub Copilot gợi ý bằng hai cách: dựa trên tên hàm (function name) và dựa trên thuyết minh (comments). Tất nhiên, cả tên hàm và thuyết minh đều phải viết bằng tiếng Anh.

 

Anh/chị thế nào chả đặt câu hỏi: Liệu Code Generation, theo cách tiếp cận của Codex hoặc AlphaCode, đến một lúc nào đó tạo ra chương trình luôn luôn đúng cú pháp và chạy theo đúng ý muốn của người lập trình không? Trả lời: theo ý kiến của cá nhân tôi thì: “còn lâu nhé”! Vì sao vậy? Vì nếu chúng ta “soi kỹ” cách tiếp cận thì các mô hình loại này tích hợp tri thức từ các website lập trình công khai (như GitHub) hoặc các cuộc thi (như Codeforces). Có một thực tế: mã lập trình từ các nguồn này không phải đúng 100%. Vì là các website mở và công khai nên nguồn đầu vào không thể kiểm soát được các đoạn mã đó có lỗi hay không lỗi. Và có một điểm khó hơn nữa: không có cách gì để biết được, một cách tự động, đoạn mã đó có chạy đúng như ý muốn hay không.

 

Trong một buổi sáng bình yên, và đầy suy ngẫm, chú thỏ “ảo” thay tôi xin phép mời anh/chị một tách cà phê.

(_/)
( •_•)
/ >☕