Vì sao ChatGPT hay sai khi tính toán
Hỏi ChatGPT tính 7583 × 2947, bạn nhận được một con số trông rất thuyết phục nhưng thường sai. Lỗi này có nguyên nhân cơ học: tokenizer cắt nhỏ chữ số, và model chỉ đoán chữ kế tiếp chứ không thực sự tính. Bài viết giải thích cơ chế, rồi chỉ ra cách chuyển việc tính cho đúng công cụ.
Bạn mở ChatGPT, nhập 7583 × 2947 rồi nhấn Enter. Một câu trả lời hiện ra gần như tức thì, chỉ sau khoảng một giây. Con số trả về trông rất thuyết phục: có đầy đủ chữ số, được đặt trong một câu gọn gàng, có khi còn kèm vài dòng diễn giải từng bước phép nhân ở dưới.
Bạn bấm thử lại trên máy tính điện thoại. Con số không khớp. Thử thêm một phép nhân khác, vẫn một câu trả lời trôi chảy, vẫn một kết quả sai. Hiện tượng này không phải bug, cũng không phải dấu hiệu model dở. Nó là hệ quả trực tiếp của cách một large language model (LLM) được dựng nên: một cỗ máy đoán chữ tiếp theo dựa trên ngữ cảnh, chứ không phải một chiếc máy tính.
Bài viết này giải thích chậm rãi vì sao ChatGPT, Claude, Gemini, và mọi chatbot dựa trên LLM đều yếu ở phép toán thuần, và làm cách nào để biến yếu điểm đó thành một bài toán giải quyết được bằng một vài thói quen rất đơn giản khi dùng chatbot hàng ngày.
Model không nhìn thấy chữ số
Trước khi đi vào phép nhân, cần nói một chút về cách model đọc văn bản đầu vào. Khi bạn gõ 7583 vào khung chat, phần tính toán bên trong không nhìn thấy bốn chữ số 7, 5, 8, 3. Nó nhìn thấy một chuỗi token: tức là các mảnh chữ đã được cắt sẵn từ lúc model được huấn luyện. Bộ cắt đó được gọi là tokenizer.
Một tokenizer kiểu byte-pair encoding, bộ cắt phổ biến nhất hiện nay, nhìn vào lịch sử văn bản khổng lồ trong dữ liệu huấn luyện rồi chọn ra các cụm chữ hay xuất hiện cùng nhau. Cụm càng thường gặp, khả năng được gom thành một token riêng càng cao. Kết quả: số 7583 có thể được cắt thành hai mảnh ["75", "83"], hoặc ba mảnh ["7", "58", "3"], tuỳ loại tokenizer. Từ góc nhìn của model, đó là hai hoặc ba từ rời cạnh nhau, không phải bốn chữ số liên tiếp.
Nhìn như vậy, phép nhân hàng dọc quen thuộc thời cấp hai bị đảo lộn hoàn toàn. Khi con người nhân 7583 × 2947, mắt đi theo từng vị trí: hàng đơn vị nhân với hàng đơn vị, rồi hàng chục, hàng trăm, có nhớ có mượn. Cơ chế đó hoạt động được vì bạn biết chữ số đang ở vị trí nào. Model không có cái biết đó. Mảnh "75" đứng cạnh mảnh "83" đối với model chỉ có nghĩa là hai từ liên tiếp, tương tự cách bạn thấy hai chữ “sáng” và “nay” đứng cạnh nhau.
Đoán token, không phải tính
Ngay cả khi tokenizer cắt từng chữ số ra riêng, model vẫn không biến thành máy tính. Lý do nằm ở nhiệm vụ gốc của nó. Một LLM được huấn luyện để làm đúng một việc: nhận vào một chuỗi token, đoán token tiếp theo có xác suất cao nhất. Toàn bộ phần cơ bắp bên trong, từ attention layer đến feed-forward layer, đều phục vụ mục tiêu đó.
Vậy khi bạn gõ 2 + 2 =, điều gì xảy ra? Model đã thấy cụm "2 + 2 = 4" hàng triệu lần trong dữ liệu huấn luyện, trên forum, trong sách giáo khoa, trên Wikipedia. Token "4"hiện ra với xác suất áp đảo, gần như bằng 1. Không có bước cộng nào thực sự diễn ra. Model chỉ lặp lại một mẫu đã thấy quá nhiều lần, giống cách bạn tự động nói tiếp “thì sáng” ngay khi nghe “gần đèn”.
Với 7583 × 2947thì khác. Cụm chữ cụ thể đó gần như không xuất hiện trong dữ liệu huấn luyện, vì có vô số cặp số bốn chữ số có thể ghép với nhau. Model rơi vào tình huống phải đoán một kết quả “nghe có vẻ đúng”: một con số bảy hay tám chữ số, bắt đầu bằng một chữ số có bậc phù hợp với ước lượng thô (7000 × 3000 cỡ 21 triệu), phân bố các chữ số còn lại trông tự nhiên. Nó thường đoán trúng vài chữ số đầu, trật vài chữ số giữa, rồi kết thúc bằng một cụm ba hay bốn chữ số hoàn toàn bịa. Kết quả nhìn như một phép nhân, nhưng không phải.
Nói cách khác, dự đoán token là một dạng suy luận mờ, không phải một phép tính chính xác. Model có thể làm tốt vô vàn công việc suy luận mờ: tóm tắt một bài báo, viết lại đoạn văn theo giọng khác, dịch, nghĩ ý tưởng, trả lời câu hỏi lịch sử. Nhưng một phép nhân bốn chữ số yêu cầu câu trả lời đúng đến từng chữ số cuối cùng. Ở địa hạt đó, suy luận mờ không cứu được.
Chọn token có xác suất cao nhất. Không có bước cộng thật, chỉ có thống kê ngữ cảnh.
Chạy thuật toán cộng trên byte. Kết quả xác định, không có xác suất nào ở đây.
Đưa phép tính cho đúng công cụ
Giải pháp hiệu quả nhất nghe có vẻ hiển nhiên một khi đã hiểu cơ chế: đừng bắt LLM tự tính. Thay vào đó, để nó viết một đoạn code ngắn, rồi chạy đoạn code đó trên một trình thông dịch Python thực. Tính năng này được gọi bằng nhiều tên: code interpreter, tool use, hoặc function calling. Bản chất giống nhau.
Khi bạn gõ 7583 × 2947 trên ChatGPT Plus với chế độ code interpreter đang bật, model sẽ không đoán con số. Nó viết ra đoạn code print(7583 * 2947), gửi sang một sandbox Python để chạy thật, rồi nhận lại con số chính xác 22347301, và chèn vào câu trả lời cho bạn. Từ đầu đến cuối, phép nhân do Python làm, còn LLM chỉ làm hai việc nó giỏi: hiểu yêu cầu bằng tiếng Việt, và trình bày kết quả lại thành câu đọc được. Đúng phân công.
Với các phép tính nhỏ và khi không có code interpreter, còn một kỹ thuật rẻ hơn là chain-of-thought. Bạn yêu cầu model “tính từng bước một” hoặc “hãy viết ra phép nhân hàng dọc”. Model sẽ trải phép nhân ra, viết từng bước, từng hàng có nhớ. Vì mỗi bước chỉ là nhân một chữ số với một chữ số (phép tính rất hay xuất hiện trong dữ liệu huấn luyện), xác suất đúng của từng bước cao hơn hẳn. Nhưng cách này có giới hạn rõ: nhân ba chữ số với ba chữ số tạm ổn, nhân sáu với sáu thì sai số tích luỹ sẽ phá vỡ kết quả. Khi phép tính đủ lớn, quay về tool use.
Cả hai cách đều đi theo một nguyên tắc chung: mỗi công cụ làm việc nó giỏi. LLM giỏi hiểu ngôn ngữ. Python giỏi tính. Cứ ghép chúng lại.
Tin vào cái gì, kiểm tra cái gì
Hiểu yếu điểm này không có nghĩa là tránh xa LLM khi gặp con số. Nó chỉ giúp bạn biết chỗ nào nên tin và chỗ nào nên kiểm. Một vài nguyên tắc thực tế để áp dụng ngay hôm nay.
Tin được. Bài toán có lời (word problem), giải thích công thức, biến đổi ký hiệu đại số, dịch một công đoạn tính thành mô tả, vẽ khung giải một bài toán từ đầu. Ở đây model đang làm đúng việc nó giỏi: liên kết ngôn ngữ với ý tưởng toán học. Con số cuối cùng nếu có thường vẫn nên kiểm, nhưng phần suy luận đa phần đúng hướng.
Không tin thẳng. Mọi phép toán nhiều chữ số, so sánh hai số thập phân gần bằng nhau, tính lãi suất, tính thuế, tổng hợp số liệu từ một bảng dài, cộng trừ tiền tệ. Luôn để tool use làm phần tính, rồi dùng model để diễn giải kết quả và trình bày.
Luôn kiểm chứng.Bất kỳ con số nào sẽ được dùng để ra quyết định. Bạn không cần tự bấm máy tính mỗi lần: chỉ cần bật code interpreter, hoặc yêu cầu model “chạy code để xác nhận”. Bước kiểm đó rẻ, và nó loại bỏ gần như toàn bộ rủi ro của phép toán sai trông như đúng.
Điểm cần nhớ cuối cùng: LLM không ngu về toán. Nó chỉ được thiết kế cho một việc khác. Hỏi một người đầu bếp cách sửa xe máy, câu trả lời vẫn sẽ trôi chảy và tự tin, nhưng đó không phải câu trả lời bạn nên làm theo. Với phép tính, hãy gọi đúng công cụ.