Để nhận được lời giải thích code hữu ích từ AI, hãy nói rõ bạn đã biết bao nhiêu, yêu cầu giải thích từng dòng, và yêu cầu một bảng trace: bảng các giá trị mà mỗi biến giữ khi code chạy. Một câu "giải thích đoạn code này" trống trơn sẽ nhận về bản tóm tắt viết cho một người đọc trung bình tưởng tượng, thường hoặc quá cơ bản, hoặc quá nhanh với bạn.
Từng dòng một, kèm bảng trace giá trị
Hai tab hỏi về cùng một hàm ngắn. Hãy so sánh xem mỗi câu trả lời cho phép bạn kiểm tra những gì.
def running_max(nums):
result = []
best = None
for n in nums:
if best is None or n > best:
best = n
result.append(best)
return result
print(running_max([3, 1, 4, 1, 5]))Hàm này tính giá trị lớn nhất tích lũy (running maximum) của một danh sách. Nó lặp qua các số, lưu giá trị lớn nhất gặp được tới lúc đó trong best, và thêm giá trị đó vào result ở mỗi bước. Phép kiểm tra best is None xử lý phần tử đầu tiên. Lời gọi hàm in ra [3, 3, 4, 4, 5].
Hàm chạy với độ phức tạp thời gian O(n), vì nó duyệt qua mỗi phần tử một lần.
Câu trả lời đầu tiên chính xác, nhưng chỉ hữu ích nếu bạn đã biết giá trị lớn nhất tích lũy là gì. Nó còn thêm một ghi chú về độ phức tạp thời gian mà không ai hỏi, kiểu nội dung thừa bạn nhận được khi model không biết ai đang đọc. Câu trả lời thứ hai gắn mỗi câu với một dòng bạn có thể chỉ vào, và bảng làm cụ thể điều mà bản tóm tắt chỉ nói lướt qua: result.append(best) chạy ở mọi lần lặp, kể cả những lần best không đổi. Đó là lý do 3 xuất hiện hai lần, và bạn thấy được điều đó ở hàng 2 thay vì phải suy ra từ cụm "ở mỗi bước".
Bảng trace cũng là một cách kiểm tra chính lời giải thích. Bạn có thể xác minh từng hàng bằng cách chạy code với print(n, best, result) bên trong vòng lặp. Nếu một hàng không khớp với đầu ra thật, lời giải thích đã sai ở đâu đó, và giờ bạn biết là ở đâu.
Giải thích đúng trình độ của bạn
Dòng hữu ích nhất trong một prompt giải thích là những gì bạn đã biết. Nó cho model biết nên lướt qua dòng nào và nên chậm lại ở dòng nào. Một câu về vai trò cũng có thể giúp ích ("Bạn là gia sư cho những người mới học lập trình được một tháng"), nhưng nó hoạt động theo cùng cơ chế: cho model biết người đọc là ai. Role prompting trình bày một vai trò thay đổi được gì và không thay đổi được gì.
Khối dưới đây là phiên bản dùng lại được. Đổi trình độ, phần gây bối rối hoặc đoạn code, và lời giải thích sẽ thay đổi theo.
text = "the cat and the hat"
counts = {}
for word in text.split():
counts[word] = counts.get(word, 0) + 1
top = sorted(counts.items(), key=lambda kv: kv[1], reverse=True)[:2]
print(top)Vòng lặp đếm từng từ: cuối cùng counts là {'the': 2, 'cat': 1, 'and': 1, 'hat': 1}.
Giờ đến hai dòng cuối, từ trong ra ngoài:
counts.items()cho ra các cặp('the', 2),('cat', 1),('and', 1),('hat', 1).lambda kv: kv[1]là một hàm nhỏ không có tên. Nó nhận một cặp và trả về phần tử thứ hai, tức số lần đếm. Với('the', 2)nó trả về2.sorted(..., key=...)sắp xếp các cặp theo giá trị mà hàm đó trả về, tức là theo số lần đếm.reverse=Trueđưa số lớn nhất lên đầu. Các từ có số lần đếm bằng nhau giữ nguyên thứ tự ban đầu.[:2]giữ lại hai cặp đầu tiên.
Vậy top là [('the', 2), ('cat', 1)], và đó là thứ được in ra.
"Số lần đếm bằng nhau giữ nguyên thứ tự ban đầu" là chi tiết mà một lời giải thích vội vàng bỏ qua, và đó là lý do cat giành vị trí thứ hai chứ không phải and hay hat. sorted của Python là sắp xếp ổn định (stable), và reverse=True vẫn giữ tính ổn định đó. Bạn sẽ không nghĩ ra để hỏi về nó, và chính yêu cầu "giá trị mà mỗi mảnh tạo ra với đầu vào này" đã làm nó lộ ra.
Hỏi về một phần, không phải cả tệp
Dán một tệp 500 dòng rồi hỏi "cái này làm gì" sẽ nhận về một chuyến tham quan cấu trúc của tệp. Khi bạn bị kẹt ở một hàm, hãy dán hàm đó và những dòng gọi tới nó, rồi hỏi thẳng: "Vì sao hàm này return sớm khi list rỗng?" hoặc "yield ở dòng 12 làm gì, và điều gì sẽ thay đổi nếu nó là return?" Một câu hỏi hẹp nhận về câu trả lời về code của bạn; một câu hỏi rộng nhận về câu trả lời về code giống code của bạn.
Với một codebase lớn và xa lạ, hãy làm ngược lại: yêu cầu một bản đồ trước ("liệt kê các module chính và trách nhiệm của từng module, mỗi module một dòng"), rồi hỏi về module bạn cần. Đây là một chuỗi prompt nhỏ, và mỗi bước giữ câu trả lời của model đủ ngắn để kiểm tra.
Giải thích qua một ngôn ngữ bạn đã biết
Code viết bằng một ngôn ngữ xa lạ sẽ dễ đọc hơn khi lời giải thích được neo vào một ngôn ngữ bạn đã biết. Hãy nói rõ trong prompt: "Tôi biết Python. Hãy giải thích hàm Go này và chỉ ra mọi chỗ nó hoạt động khác với điều một lập trình viên Python sẽ mong đợi." Những điểm khác biệt chính là nơi hiểu lầm nảy sinh: phép chia số nguyên, giá trị zero thay vì None, một slice dùng chung bộ nhớ với mảng mà nó được tạo ra từ đó. Một lời giải thích thông thường về đoạn code Go sẽ mô tả đúng những dòng đó mà không bao giờ cho bạn biết trực giác của bạn về chúng là sai.
Kiểm tra xem bạn đã hiểu chưa
Một lời giải thích bạn đọc và đồng ý vẫn có thể khiến bạn không tự viết được đoạn code đó. Hai prompt giúp lấp khoảng trống này:
- Đoán trước. Trước khi chạy code hoặc nhờ giải thích, hãy viết ra bạn nghĩ nó sẽ in ra gì. Sau đó nhờ model chỉ giải thích những dòng mà bạn đoán sai.
- Tự giải thích lại. Viết lời giải thích của riêng bạn và nhờ model chỉ ra chỗ nào sai hoặc còn thiếu, mà không viết lại nó.
def running_max(nums):
result = []
best = None
for n in nums:
if best is None or n > best:
best = n
result.append(best)
return result
Hỏi tôi 3 câu để kiểm tra xem tôi đã thực sự hiểu nó chưa, từng câu một. Có một câu mà tôi phải đoán đầu ra cho một đầu vào mới. Chờ tôi trả lời rồi mới hỏi câu tiếp theo, và cho tôi biết câu trả lời của tôi đúng hay sai và vì sao.Câu 1/3: running_max([2, 7, 5, 9]) trả về gì? Hãy tự tính ra trước khi chạy thử.
Cách tiếp cận này cũng dùng được khi một chương trình chạy sai, nhưng khi đó bạn cần nguyên nhân chứ không phải một bài học: xem prompt để gỡ lỗi. Khi đoạn code trước mặt bạn do AI viết, giải thích từng dòng là cách nhanh để review nó trước khi giữ lại; prompt để viết code liệt kê các bước kiểm tra khác nên làm.
Câu hỏi thường gặp
Làm sao nhờ ChatGPT hoặc Claude giải thích code?
Dán code vào và nói ba điều: bạn đã biết gì, phần nào khiến bạn bối rối, và bạn muốn lời giải thích có dạng thế nào. "Giải thích mỗi dòng trong một câu, rồi cho xem bảng các biến sau mỗi lần lặp" nhận về câu trả lời hữu ích hơn nhiều so với "giải thích đoạn code này".
Bảng trace (trace table) là gì?
Bảng trace theo dõi một chương trình khi nó chạy: mỗi hàng là một bước (thường là một lần lặp), mỗi cột là một biến, và mỗi ô là giá trị của biến đó tại thời điểm ấy. Yêu cầu một bảng như vậy biến một mô tả trừu tượng thành những giá trị cụ thể bạn có thể đối chiếu với code. Đó là bản ghi trên giấy của những gì debugger cho bạn thấy khi chạy từng bước qua chương trình.
AI có thể giải thích code viết bằng ngôn ngữ tôi chưa biết không?
Có, và đó là một trong những việc hữu ích nhất để nhờ. Hãy nêu một ngôn ngữ bạn đã biết và yêu cầu model so sánh: "Tôi biết Python; hãy giải thích đoạn code Rust này và chỉ ra những chỗ nó hoạt động khác với Python." Hãy kiểm tra các khẳng định về cách ngôn ngữ hoạt động bằng cách chạy những ví dụ nhỏ, vì lời giải thích có thể sai một cách đầy tự tin ở các chi tiết.
Dùng AI để giải thích code có hại cho việc học không?
Còn tùy vào việc bạn làm gì tiếp theo. Đọc một lời giải thích rồi bỏ qua thì học được rất ít. Đoán trước đầu ra trước khi chạy code, nhờ model đố bạn, hoặc tự giải thích lại code rồi hỏi mình sai ở đâu đều buộc bạn phải tự suy nghĩ, và đó là lúc việc học diễn ra.