# Mô hình AI dựng ra trông đúng hết: chỗ nó không cứu được mình là "có chế tạo được không"
Hôm nay có một bài test mình đọc tới hai lần. Người ta lấy mô hình 3D do LLM sinh ra, đưa vào đúng câu hỏi mà một xưởng sẽ hỏi: cái này làm được không?
Không phải "trông có giống không". Không phải "render có đẹp không". Mà là: cái thành mỏng kia máy có đúc nổi không, cái lỗ kia khoan tới đáy được không, cái mảng kia có chỗ nào để kẹp vào máy không.
Mình đọc xong thì thấy lạnh người, không phải vì kết quả, mà vì mình nhận ra mình đã tự hỏi y hệt câu đó hàng trăm lần — chỉ khác là vật liệu của mình là chữ, là mã, là quy trình, chứ không phải nhôm.
Thứ khác biệt lớn nhất: sửa code gần như miễn phí, sửa một miếng nhôm thì không
Có một điều mình không để ý suốt nhiều năm, vì nó quá hiển nhiên với dân làm phần mềm: vòng lặp sửa rẻ tới mức mình coi nó là miễn phí.
Viết sai một dòng. Chạy lại. Ba giây. Sửa cả một kiến trúc sai. Một buổi chiều. Xoá đi làm lại từ đầu. Thứ Hai khác.
Vì vòng lặp rẻ, mình vô thức xây thói quen: cứ ra bản nháp trước đã, sai thì sửa. Và thói quen đó đúng. Nó là lý do phần mềm tiến nhanh.
Nhưng cái thói quen đó được xây trên một giả định mình chưa bao giờ kiểm tra: được phép sửa lại, nhiều lần, gần như vô hạn.
Trong xưởng thì giả định đó chết ngay dòng đầu.
Một miếng nhôm đã phay rồi thì sai là sai. Không có bản nháp. Không có "chạy lại từ commit trước". Muốn sửa thì phải: nhận ra đã sai, gọi lại xưởng, xếp lịch máy, mua lại phôi, chờ. Khoảng thời gian đó tính bằng tuần, và mỗi tuần là tiền thuê, tiền máy, tiền người, cộng thêm phần đời mình bị đẩy lùi.
Nên khi một mô hình sinh ra thứ "trông đúng" trong môi trường mà sửa lại rẻ, sai 5% là chuyện nhỏ — mình sửa 5% đó trong bữa trưa. Còn trong môi trường mà sửa lại đắt, sai 5% không phải là 5% sai. Nó là một chu kỳ làm lại, và chu kỳ làm lại là toàn bộ chi phí đó nhân lên.
Đây là chỗ mình nghĩ AI đang bị hiểu sai nhiều nhất: người ta đo nó bằng tỷ lệ đúng, trong khi thứ quyết định giá trị là chi phí của lần sai.
Mô hình học "trông đúng", không học "làm được"
Mình không nghĩ đây là lỗi của mô hình. Mình nghĩ đây là chuyện nó được dạy cái gì.
Một mô hình sinh hình dạng học từ hàng triệu thứ đã tồn tại. Nó học được rằng cái giá đỡ thường có chân, cái vỏ thường có nắp, cái khớp thường có trục. Nó học phân bố của cái trông hợp lý.
Ràng buộc của xưởng thì không nằm trong phân bố đó.
Độ dày thành tối thiểu mà khuôn đúc nổi. Bán kính dao phay — mọi góc lõm đều phải rộng ít nhất bằng đầu dao, nếu không thì dao không vào được, và cái góc sắc trong bản vẽ sẽ biến thành một cục vật liệu thừa ngoài đời. Hướng rút khuôn: mọi mặt phải nghiêng đủ để khuôn tách ra, nếu không thì chi tiết dính trong khuôn. Mặt phẳng nằm ngang quá lớn khi in. Lỗ quá sâu so với đường kính. Dung sai cộng dồn qua nhiều chi tiết lắp.
Không có cái nào trong số đó hiện ra khi mình xoay mô hình trên màn hình. Tất cả đều chỉ hiện ra khi có một người đã từng đứng cạnh máy hỏi: "cái này mày định làm bằng gì?"
Mình gọi đây là khoảng trống chế tạo được. Mô hình trả lời đúng câu hỏi "cái này nên trông thế nào", và câu trả lời đó rất tốt. Nó chỉ không phải câu hỏi mà xưởng hỏi.
Ba tầng kiểm, và tầng nào thật sự đáng tiền
Ở chỗ mình, bài toán y hệt, chỉ là vật lý đổi thành logic. Đầu ra của một chuỗi tự động hoá cũng có "chế tạo được" của nó: nó có chạy nổi với dữ liệu thật, trong hệ thật, trước người thật không.
Và mình cũng học được rằng việc kiểm không phải một tầng, mà là ba tầng có giá khác nhau rất xa.
Tầng một — ràng buộc cứng, giá gần bằng không. Đây là những thứ kiểm được bằng luật, không cần gọi mô hình: trường bắt buộc có chưa, con số nằm trong khoảng cho phép không, tên có tồn tại trong danh sách không, tổng có khớp không, cái khoá ngoài có trỏ tới thứ thật không. Tầng này chạy trước khi gọi model, và nó chặn được phần lớn lỗi ngớ ngẩn mà mình hay đổ cho AI. Mỗi lần mình bỏ tầng này, mình đang trả tiền cho model để nó tự phát hiện một thứ mà một dòng if phát hiện miễn phí.
Tầng hai — thử trong môi trường gần thật. Không phải đọc rồi đoán, mà chạy thật: gọi thử cái endpoint, đẩy thử vào cái hàng đợi, render thử với dữ liệu méo. Đắt hơn tầng một, nhưng đây là tầng duy nhất trả lời được câu "có sống nổi không", vì nó là tầng duy nhất có phản hồi từ bên ngoài. Model tự nhìn lại output của chính nó thì không phải phản hồi, nó là một lần tự khen.
Tầng ba — người có chuyên môn ký. Đắt nhất, chậm nhất, và là tầng duy nhất không thể thay bằng gì khác ở những chỗ không hoàn tác được. Mình không dùng nó để kiểm mọi thứ. Mình dùng nó đúng ở chỗ mà nếu sai thì phải làm lại từ đầu.
Cái mình hay làm sai thời gian đầu: dùng tầng ba cho tất cả, vì "cho chắc". Kết quả là nghẽn ở người, và người mệt tới mức ký cho xong — tức là tầng ba biến thành con dấu, không còn là tầng kiểm. Ngược lại cũng sai: bỏ tầng một vì "AI giờ khá rồi", rồi để model gánh cả phần kiểm lẫn phần sinh, và mình mất luôn chỗ để biết nó sai từ bao giờ.
Một khung kiểm kiểu này, viết bằng pseudo-code cho dễ hình dung — không phải nguồn triển khai, chỉ là hình dạng của ý tưởng:
# pseudo-code minh hoạ, không phải code thật
def gate(ban_nhap):
# tầng 1: ràng buộc cứng, chạy trước khi tốn token
loi_cung = check_rules(ban_nhap) # schema, khoảng, danh sách, tổng
if loi_cung: return REJECT(loi_cung) # trả về lý do, không trả về "lỗi"
# tầng 2: thử trong môi trường thật, có phản hồi từ bên ngoài
ket_qua_thu = dry_run(ban_nhap)
if ket_qua_thu == FAIL: return REJECT(ket_qua_thu)
if ket_qua_thu == UNKNOWN: return ESCALATE("không xác định") # đừng đoán
# tầng 3: chỉ những thứ không hoàn tác được mới tới đây
if ban_nhap.khong_the_hoan_tac:
return WAIT_FOR_HUMAN(ban_nhap, ly_do="không có đường lùi")
return ACCEPT(ban_nhap, bang_chung=loi_cung + ket_qua_thu)Chú ý cái nhánh UNKNOWN. Đó là nhánh quan trọng nhất và là nhánh mình từng bỏ. Máy không biết thì hay có xu hướng chọn một câu trả lời nghe hợp lý, vì "trả lời" là việc nó giỏi. Nên phải có một cửa riêng để nó được phép không biết — nếu không, mọi lỗi "chưa xác định" sẽ bị bơm vào nhánh "đã xong", và mình chỉ phát hiện ở phía người nhận.
Vì sao chỗ này là chỗ ra tiền, và vì sao nó khó bán
Phần sinh đang thành hàng rẻ. Ai cũng dựng được một bản nháp trong buổi chiều. Điều đó tốt cho mình khi mình là người dùng, và tệ cho mình khi mình là người bán — vì thứ mình bán đang mất giá mỗi tháng.
Nhưng có một thứ không mất giá: cái làm cho bản nháp sống nổi. Trong sản xuất nó là kỹ sư hiểu chế tạo. Trong tự động hoá nó là người biết hệ này sẽ chết ở đâu khi gặp dữ liệu thật. Cả hai đều không phải là kỹ năng sinh ra nội dung, mà là kỹ năng từ chối nội dung — biết cái gì không được đi tiếp.
Và đây là chỗ nghịch lý: nó khó bán chính vì nó giỏi. Nếu nó chạy tốt, không có gì xảy ra. Không có sự cố, không có hoá đơn cứu hoả, không có câu chuyện để kể. Mình bán một thứ mà thành công của nó là sự vắng mặt.
Nên muốn bán được, mình phải bán bằng chứng chứ không bán cảm giác an tâm. Ba con số mình thấy đáng đo, và đều đo được mà không cần kể chuyện:
Một, tỷ lệ lần đầu ra là dùng được. Không phải tỷ lệ đúng của model — tỷ lệ đầu ra tới tay người nhận mà không ai phải sửa. Cái này thường thấp hơn nhiều so với con số mình tự hào trong demo.
Hai, số lần phải làm lại vì lỗi không hoàn tác. Đây là con số đau nhất và cũng là con số mình hay giấu nhất, vì nó không nằm trong log của máy — nó nằm trong lịch sử tin nhắn của người phải xin lỗi khách.
Ba, số lần "chưa xác định" bị đẩy thành "đã xong". Đo bằng cách đối chiếu định kỳ giữa trạng thái hệ báo và trạng thái thật. Cái này mình học được sau một lần log sạch hoàn toàn trong khi việc thật chưa hề xảy ra, và mình chỉ biết vì có người hỏi "sao chưa thấy gì".
Ba con số đó không hào nhoáng. Nhưng nó là thứ duy nhất khiến một khách hàng tin mình đã kiểm, thay vì tin mình đã hứa.
Ba cái bẫy mình đã sập, và vẫn thấy người khác sập
Bẫy một: tối ưu cho cái nhìn thấy được. Mô hình render đẹp, demo mượt, bản nháp long lanh — tất cả đều là phần nhìn thấy. Phần không nhìn thấy là ràng buộc, và mình có xu hướng đánh giá bằng phần nhìn thấy vì nó dễ chụp ảnh gửi sếp. Mình từng ship một thứ đẹp tới mức không ai buồn hỏi nó chạy bằng gì.
Bẫy hai: mua vòng lặp phản hồi mà không mua người đọc nó. Có phản hồi từ thế giới thật là điều kiện cần, không phải điều kiện đủ. Mình từng có cả một đống tín hiệu đúng — lỗi, cảnh báo, số liệu — và không ai đọc, vì đọc nó là một việc làm thêm không có trong lịch. Phản hồi không được thiết kế để có người đọc thì chỉ là tiếng ồn mình đã trả tiền để tạo ra.
Bẫy ba: tin vào "để nó tự sửa". Tự sửa chỉ hoạt động khi có phản hồi thật từ bên ngoài đóng vòng lại. Không có phản hồi thật, "tự sửa" là một vòng lặp tự khen: model đọc lại output của mình, thấy hợp lý, sửa thành một phiên bản hợp lý hơn, và mỗi vòng càng tự tin hơn trong khi khoảng cách với thực tế càng xa. Mình đã xem một chuỗi như vậy chạy ba vòng, mỗi vòng đều "cải thiện", và đầu ra cuối cùng tệ hơn đầu ra đầu tiên.
Kết
Cái làm mình nhớ bài test kia không phải chuyện AI có vẽ được CAD hay không. Mà là nó nhắc mình một câu hỏi mình nên hỏi mỗi ngày và hay quên:
Thứ này đúng, hay chỉ trông đúng?
Trong môi trường cho mình sửa, hai câu đó gần như giống nhau — và sự mơ hồ đó không sao, vì mình có thể trả giá bằng thời gian. Trong môi trường không cho sửa, hai câu đó cách nhau đúng một chu kỳ làm lại, và chu kỳ đó được tính bằng tiền thật, thời gian thật, và đôi khi bằng một cuộc xin lỗi.
Máy giỏi tạo ra thứ trông đúng. Điều đó có giá trị thật, chỉ là nó không phải toàn bộ giá trị. Phần còn lại — phần biết cái gì chế tạo được — vẫn đang nằm ở người, và mình nghĩ nó sẽ nằm ở đó lâu hơn mọi người dự đoán.
Anh em đang chạy chuỗi tự động hoá nào, thử nhớ lại lần gần nhất đầu ra "trông đúng hết" mà vẫn không dùng được — nó chết ở chỗ nào? Mình rất muốn nghe mấy cái chết đó, vì mấy cái đó mới là thứ đáng viết lại.