- Một lập trình viên đã đưa JavaScript đã rút gọn vào ChatGPT để hiểu cách triển khai component ASCII art nhìn thấy trên web, và ChatGPT đã tháo gỡ luồng bị làm rối thành một cấu trúc có thể đọc được
- Bản gốc là một component React tính toán số cột và hàng theo kích thước cửa sổ, rồi cập nhật lưới chuỗi bằng
setIntervalở 60fps - ChatGPT giải thích luồng chọn tập ký tự, tính toán ký tự dựa trên tọa độ và thời gian, cập nhật
div.textContent, rồi viết lại thành mã TypeScript/React tương đương - Ban đầu tưởng rằng các ký tự khối như
░▒▓█bị thiếu nên cách triển khai khác đi, nhưng khi kiểm tra lại script gốc thì hóa ra đó là vấn đề mã hóa khi sao chép-dán - Sau khi cập nhật với tập ký tự đúng, đầu ra trở nên giống component gốc, cho thấy có thể dùng ChatGPT một cách thực tiễn để hiểu và tái triển khai mã đã rút gọn
Tìm cách triển khai ASCII art trong JavaScript đã rút gọn
- Đã xem mã nguồn để kiểm tra khối ASCII art trên trang reactive.network hackathon được triển khai như thế nào
- Đoạn mã liên quan đã được rút gọn nên con người khó đọc ngay; thông thường sẽ phải tự giải mã hoặc tìm tệp
.mapđể khôi phục bản gốc - Lần này, toàn bộ mã đã rút gọn được dán vào ChatGPT và yêu cầu giải thích cách mã hoạt động
Cấu trúc lộ ra từ mã đã rút gọn
- Mã có cấu trúc tạo nội dung văn bản động bằng JavaScript và React
- Các yếu tố chính gồm:
- Dùng các bí danh ngắn cho những hàm toán học như
Math.floor,Math.abs,Math.min - Có một tập ký tự gồm
"reactive.network REACTIVE.NETWORK"cùng các ký tự đặc biệt và ký tự khối - Chọn tập ký tự sẽ dùng tùy theo kết quả của
Date.now() % 3 - Tính chỉ số ký tự sẽ hiển thị tại mỗi tọa độ dựa trên độ dài của tập ký tự đã chọn
- Dùng các bí danh ngắn cho những hàm toán học như
- Hàm cốt lõi
eTnhận tọa độ vị trí và giá trị thời gian, rồi trả về một ký tự để hiển thị- Giá trị thời gian được chuyển đổi bằng
t.time * 8e-5 - Tọa độ được hiệu chỉnh bằng giá trị nhỏ hơn giữa số cột và số hàng, cùng tỷ lệ màn hình
- Chỉ số ký tự được xác định bằng cách kết hợp kết quả tính
Math.cos(position.x * position.x - position.y * position.y)với giá trị thời gian
- Giá trị thời gian được chuyển đổi bằng
Cách render của component React
- Component tham chiếu tới
divsẽ chứa văn bản bằnguseRef, và lưu height cũng như width của cửa sổ bằnguseState useEffectđầu tiên thiết lập kích thước ban đầu bằngwindow.innerHeight,window.innerWidth, rồi cập nhật kích thước khi sự kiệnresizexảy rauseEffectthứ hai tính kích thước lưới ASCII dựa trên kích thước màn hìnhcolslàMath.floor(width / 12) * 1.6rowslàMath.floor(height / 12)aspectlàcols / rows
setIntervalchạy với khoảng cách1_000 / 60, tạo lại chuỗi theo 60fps- Ở mỗi frame, mã duyệt qua mọi hàng và cột để nối các ký tự đã tính, rồi đưa chuỗi cuối cùng vào
element.textContent
Viết lại thành mã dễ đọc bằng TypeScript
- Sau đó, lập trình viên yêu cầu triển khai mã tương đương bằng TypeScript nhưng dễ đọc hơn cho con người
- Mã do ChatGPT tạo ra diễn giải vai trò của mã đã rút gọn bằng các tên sau:
selectedCharacterSetcharacterSetLengthcalculateCharacter- Kiểu
Size - Component React
AsciiArtGenerator
- Các tên biến khó hiểu được đổi thành tên thể hiện ý định triển khai
calculateCharacternhận tọa độ, số cột/hàng, tỷ lệ màn hình và giá trị thời gian để tính ký tự cần hiển thịtextReftrỏ tớidivthực sự chứa văn bảnsizevàsetSizebiểu thị trạng thái kích thước cửa sổ
- Mã được viết lại dễ đọc hơn nhiều so với mã đã rút gọn ban đầu, và đủ tốt để học cách component này được triển khai
Hiểu nhầm về ký tự bị thiếu và vấn đề mã hóa
- Trong lần so sánh ban đầu, có vẻ như LLM đã bỏ sót một vài chi tiết triển khai
- Đặc biệt, người ta cho rằng các ký tự như
░▒▓█xuất hiện trong component gốc đã bị thiếu khỏi kết quả của ChatGPT - Sau đó, một người dùng trên diễn đàn HN chỉ ra khả năng đây là vấn đề sao chép-dán, và sau khi kiểm tra thêm thì phát hiện mã gốc chứa những ký tự khác với các ký tự đã dán vào ChatGPT
- Khi tải trực tiếp script xuống, các ký tự đúng đã được lấy về, và nguyên nhân được xác nhận là khác biệt về mã hóa
- Sau khi sửa lại tập ký tự, đầu ra trở nên giống hệt component gốc
1 bình luận
Các ý kiến trên Hacker News
Tôi là người tạo ra HumanifyJS, và đã làm riêng một công cụ dựa trên LLM cho mục đích này
Công cụ dùng LLM ở cấp AST để đảm bảo mã vẫn tiếp tục hoạt động sau khi gỡ rối mã: https://github.com/jehna/humanify
Ý tôi là một chức năng xóa toàn bộ các tên có ý nghĩa của người dùng trong mã thông thường, rồi chọn tên mới dựa trên thuật toán và các tên còn lại, chẳng hạn như tên built-in
Khi refactor, thỉnh thoảng tôi làm thủ công bằng LLM; việc này hữu ích để tìm những thuật ngữ chuẩn hơn như
antiparallel_linethay choparallel_line_opposite_direction, hoặc phát hiện các tên có thể khái quát hóa tốt hơn nhưfind_instance_in_listthay chofind_animal_instance_in_animalsNói thật là tôi vẫn đang chờ quản lý phiên bản ở cấp AST
Không biết bạn đưa cả hàm vào rồi lặp lại câu hỏi “cần đổi tên cái gì?” cho đến khi mọi thứ được đổi, hay yêu cầu xử lý toàn bộ một lần rồi parse đầu ra và kiểm tra xem AST có còn khớp hay không
Ý tôi là khoảng 50 nghìn dòng
Sửa: hiện tôi đang thử chạy chế độ openai trên một tệp JS chỉ khoảng 1,2 nghìn dòng, mà sau 20 phút mới xong 70%. Về lý thuyết dù nó chạy được với tệp 50 nghìn dòng thì có lẽ cũng không nên thử
Nén JS khá máy móc và đơn giản, nên việc đảo ngược cũng tương đối dễ
Tất nhiên nhìn chung thì vẫn đủ nhàm chán để con người không muốn tự làm, nhưng bản thân phép biến đổi khá hạn chế, nên chỉ cần có ghi chú theo dõi các định danh bị làm rối là có thể đọc được
Việc giải nén hoặc gỡ rối mã tổng quát hơn dường như vẫn là một bài toán mở. Trước đây tôi từng viết vài chương trình cố tình làm rối, và theo trải nghiệm của tôi ChatGPT không hiểu được ngay cả ở mức bề mặt
Ví dụ có một bình luận dùng GPT-4 để cố giải thích mã trong một gist về trình thông dịch Brainfuck viết bằng C chỉ 160 byte [1], nhưng “phiên bản đã làm rõ” đó hoàn toàn không giống mã gốc
[1] https://gist.github.com/lifthrasiir/596667#gistcomment-47512...
Ví dụ như nhân/phân tích thừa số nguyên tố, đạo hàm/tích phân, nhớ quá khứ/dự đoán tương lai
Gỡ rối mã rõ ràng là một trong những bài toán ngược khó như vậy, và có thể dễ dàng trở nên khó hơn vì bug, các routine không dùng hoặc không liên quan, hay các triển khai sai nhưng tình cờ cho kết quả đúng
Theo nghĩa đó, nếu ChatGPT cho kết quả ổn khi gỡ rối mã thì đó là điều đáng mừng, chứ không có kỳ vọng tiên nghiệm rằng nó phải làm được. Việc kiểm tra giới hạn của ChatGPT bằng một bài toán khó hơn là tốt, nhưng tôi cho rằng điều bạn tìm thấy chỉ là cận trên. Tôi không xem ví dụ trong bài gốc là tầm thường
let userSignedInTimestamp = new Date()thànhlet x = new Date()là chuyện tầm thường, nhưng để đi ngược lại thì nhiều khả năng phải đọc và hiểu mã xung quanh để xemxđược dùng trong ngữ cảnh nàoHơn nữa phần mã còn lại cũng đã bị nén nên càng khó hơn, và dù làm đúng hết thì rốt cuộc đây vẫn là một phép biến đổi mất mát, vì tên biến có thể đã chứa những đặc tính không được thể hiện rõ trong mã
Đó là vì dữ liệu đã biến mất trong quá trình này
Nén cũng hoạt động theo cách tương tự. Rất nhiều thông tin cần thiết để hiểu mã đã biến mất, và việc khôi phục thông tin đó có thể cực kỳ khó
timeFactorthànhingắn hơn nhiều có thể là máy móc và đơn giản, nhưng quá trình đó mang tính phá hủy, và việc đảo ngược thì tương đối không dễĐiều đó là bất khả thi nếu không hiểu khá tinh tế mã thực sự đang làm gì. Đó chính là phần LLM đã làm ở đây, và tuy không gây sốc nhưng rất ấn tượng. Thái độ vội vàng hạ thấp quá mức thì không hay lắm
Tôi không dùng PC nên chưa thử nghiệm được
Chẳng phải tiêu đề nên dùng ChatGPT hoặc tên mô hình GPT-4 thay vì OpenAI, vốn là tên công ty sao?
LLM rất giỏi biến đổi văn bản
Đây là thế mạnh cốt lõi, nhưng có vẻ chưa được tận dụng đủ
Những năng lực khác như suy luận hay lưu giữ tri thức chỉ là tác dụng phụ của khả năng siêu phàm trong việc tái tạo văn bản mà không “hiểu” ý nghĩa được chủ ý
Ví dụ, nó không sắp xếp được danh sách, nhưng có thể dịch ngôn ngữ. Vì một danh sách được sắp xếp gần đúng vẫn là sai, còn một bản dịch gần đúng thì chúng ta thường chấp nhận
Nếu một nhóm đang cân nhắc liệu có đáng chuyển một mảng lớn code Python sang Elixir hay không, họ không còn phải chỉ đoán mò nữa
Gần đây tôi đã thử dịch một script Python sang JavaScript, kết quả không có gì để chê, và có vẻ chỉ cần thêm một vài guardrail là có thể mở rộng quy mô
Chúng tôi chủ yếu dùng nó để trích xuất dữ liệu có cấu trúc từ các định dạng khác
Thêm nữa, bạn cũng phải thiếu kiến thức hoặc kỹ năng để xử lý nhanh hơn bằng awk, Python, Perl, v.v.
Một số lập trình viên từng dùng nén làm phương tiện làm rối mã chắc hẳn sẽ nổi giận
Tôi nhớ trong các phiên bản ColdFusion cũ từng có công cụ “mã hóa” code. Thuật toán rất yếu nên chẳng mất lâu để ai đó làm ra công cụ giải mã
Dù vậy, một số người không thích điều đó vì họ tin công cụ kia an toàn và đang dùng nó để bán code mà không công khai mã nguồn. Đó là chuyện cuối thập niên 90/đầu những năm 2000, trước khi mã nguồn mở trở thành mặc định áp đảo
Một website tổ chức cuộc thi dựa một phần vào mã phía client đã bị làm rối, và những người tham gia khôn khéo giờ có thể đưa nó vào ChatGPT để tăng tỷ lệ thắng
Đây mới chỉ là khởi đầu
Đây là một ví dụ về năng lực thực hiện trí tuệ vượt trội hơn con người
Không thể phủ nhận. Nhiệm vụ này mang tính trí tuệ và không liên quan đến ghi nhớ đơn thuần. Trên web cũng không có vô số cặp code đã nén/code giải nén để LLM học
LLM hiểu thứ mà nó đang giải nén, và riêng trong chủ đề cụ thể này thì nhìn chung vượt trội hơn con người
Có chắc là trên web không có nhiều cặp code nén và code chưa nén không? Có thể dễ dàng tạo chúng từ JS hiện có để dùng làm tập huấn luyện, và lượng JS chưa nén đã được dùng trong huấn luyện cũng cực kỳ lớn
Lý do con người khó hiểu code đã nén là vì tên biến mờ nghĩa, vòng lặp khó đọc, khoảng trắng bị tối giản, v.v. Máy tính không gặp khó với những thứ này, và đó cũng là lý do ban đầu chúng ta nén code. Kiến trúc attention nên làm tốt những việc như vậy
Tôi cũng cho rằng có rất nhiều code nén/chưa nén. Mục đích của file source map chính là như vậy. Nhìn vào việc OpenAI đầu tư vào duyệt web và phát triển phần mềm, sẽ không ngạc nhiên nếu họ đã đưa dữ liệu nén/chưa nén vào huấn luyện
Việc máy tính nhân tức thì các số 1000 chữ số là ví dụ con người đã tạo ra công cụ đó trước và thành công trong phép nhân. Ngoài điều đó ra thì còn thành công trí tuệ nào khác? Máy tính cũng đâu tự tạo ra chính nó
Nếu cắt ranh giới trí tuệ con người ở hộp sọ, và không tính các công cụ mà trí tuệ đó tạo ra và sử dụng như những bước trong quá trình giải quyết vấn đề, thì ta cũng phải chấp nhận rằng con người không đủ thông minh để bay vào vũ trụ, phẫu thuật hay nấu phần lớn bữa ăn
Việc nhận ra hình dạng trừu tượng của code khi thiếu tên biến, rồi ánh xạ nó sang tên biến con người đọc được từ các mẫu tương tự đã thấy trên Internet khổng lồ, nghe không hề vô lý
Thú vị, và có vẻ đã cải thiện rất nhiều
Hơn một năm trước một chút, tôi nhận được email nhờ giúp với một plugin tùy chỉnh trên một site WordPress bị hack, và đã thử dùng GPT để gỡ rối mã độc. Khi đó, tự mình lần theo code từng bước còn tiến triển tốt hơn nhiều
Đọc bài này xong tôi đã thử lại [0]. Nó đưa ra một số nội dung có thể hiểu được, nhưng code bị làm rối đến mức về cơ bản là eval các chuỗi không đọc được thông qua đối tượng Window, nên chỉ như vậy là chưa đủ
Một phần báo cáo tôi gửi khi đó có nội dung đại ý: tôi đã có thể đào sâu vào đoạn JavaScript bị làm rối nặng, phát hiện logic nhận biết việc tải trang, gọi một lớp vỏ tính toán về lý thuyết là hằng số, rồi chuyển hướng trang sang một site độc hại
[0] https://chatgpt.com/share/f51fbd50-8df0-49e9-86ef-fc972bca6b...
Có ai đang làm về LLM decompiler không?
Có vẻ như có thể biến mọi mã nguồn thành như mã nguồn mở
Trong trường hợp này, dữ liệu huấn luyện dễ tạo. Chỉ cần build hàng loạt mã GitHub miễn phí bằng nhiều compiler khác nhau, rồi huấn luyện để đảo ngược quá trình biên dịch. Đây là trường hợp dữ liệu huấn luyện tổng hợp phù hợp và có thể tạo khá dễ dàng
Decompiler chỉ cần được huấn luyện để đảo ngược việc biên dịch, còn các việc như thêm chú thích thì có thể dùng các code LLM lớn hơn hiện có
Không chỉ mở nguồn, mà còn có thể tưởng tượng cảnh dễ dàng decompile và sửa các ứng dụng độc quyền để vá lỗi hoặc thêm tính năng. Đặc biệt với những chương trình đã bị bỏ rơi từ lâu, đây có thể là một vùng giải phóng lớn
Vì lý do pháp lý, khả năng cao hành vi như vậy sẽ trở thành tính năng bị chặn trong các mô hình lớn
Những quyền đó chỉ tác giả mã mới có thể cấp
Nếu AI thật sự hiểu mã tốt, nó sẽ cứ tạo hoặc sửa binary
Tôi tin rằng khi lập trình viên AI thật sự xuất hiện, nó sẽ không bận tâm đến mã mà con người đọc được, mà sẽ code toàn bộ bằng mã máy. Nếu được giao nhiệm vụ bảo trì một hệ thống hiện có, nó sẽ hiểu trọn vẹn cả stack phần mềm lẫn phần cứng
Tương tự như các mô hình khuếch tán tạo ảnh không bận tâm học các kỹ thuật vẽ thực tế
Nó gần với việc đổi tên biến, tên hàm và thêm xuống dòng hơn
Rất giống cách tôi thường dùng LLM [0]
Khi buộc phải tự đọc mã, tôi dùng nó như bước đầu tiên để giải mã
Việc có thể đưa vào một đống mã spaghetti rối tung rồi nhờ nó làm cho dễ đọc hơn để bắt đầu từ đó thật sự rất giải phóng
Như tác giả cũng phát hiện, LLM đôi khi bỏ sót chi tiết, nhưng những phần đó thì tôi có thể tự bắt
Một cách dùng khác là khi tôi hiểu mã làm gì nhưng không thể nắm được vì sao nó lại được viết theo cách đó. Đặc biệt là khi người viết đoạn mã đó không còn ở công ty nữa. Khi đó tôi đưa method vào chat LLM, giải thích nó làm gì, rồi hỏi vì sao một số thứ có thể đã được làm theo cách cụ thể đó
Không phải lúc nào cũng hoàn hảo, nhưng khá thường xuyên nó đưa ra lời giải thích thật sự hợp lý, chịu được kiểm chứng và đem lại góc nhìn mới. Một hai lần nó còn giúp tôi tránh refactor theo cách mà về sau hẳn sẽ gây đau đầu
[0] Tôi dùng chatGPT và gần đây là openwebUI làm frontend cho nhiều mô hình khác nhau, chủ yếu là các biến thể Claude, để xem khác biệt. Cũng có thể tạo cấu hình thú vị cho các mô hình khác nhau kiểm tra câu trả lời của nhau
Nếu mã được unminify không khớp với mã đã minify, như phần cuối nói “phản hồi của LLM dường như bỏ lỡ vài chi tiết triển khai”, thì tính hữu ích giảm đi rất nhiều
Đặc biệt vì trong nhiều trường hợp ta không thể đơn giản chạy mã để kiểm tra khác biệt như trong bài viết
Sửa: xem thread bên dưới thì có vẻ đó là vấn đề encoding. Dù vậy tôi vẫn hơi lo về độ chính xác
Trong một số trường hợp, ngoài unminify, ChatGPT còn tự refactor
Mã gốc không gọi
handleResizengay mà inline nội dung của nó. Có lẽ minifier đã thực sự inline. Khác biệt thực tế duy nhất ở đây là thiếu điều kiệnif (typeof window < "u")Cụ thể là các ký tự khối, nhưng có vẻ HN không cho dán ký tự Unicode. Chúng xuất hiện trong bản gốc nhưng không thấy trong phiên bản ChatGPT tạo
Tuy nhiên cũng rất có thể là do tôi đã không đưa vào toàn bộ ngữ cảnh cần thiết
Hạ thấp toàn bộ đầu ra chỉ vì thiếu vài ký tự thì gần như là soi quá kỹ. Ngoài điểm đó ra, theo tôi thấy thì đầu ra giống nhau
Nếu chỉ bảo nó đổi tên biến và method thì có lẽ đã gần với bản gốc hơn