Tôi muốn xem liệu việc chạy cùng một câu hỏi 51 lần có giúp câu trả lời trở nên đáng tin cậy hơn không. Tôi đã lấy một LLM chạy cục bộ, đưa cho nó một đoạn mã nguồn đang chạy (production code) và yêu cầu đánh giá. Sau đó tôi lặp lại việc này. Lại nữa. Tổng cộng 51 lần, sử dụng phương pháp bỏ phiếu đa số (majority voting) để chọn ra câu trả lời "tốt nhất". Ý tưởng rất đơn giản: nếu mô hình vấp lỗi trong một lần chạy, có lẽ "trí tuệ đám đông" từ 51 lần tạo ra sẽ triệt tiêu các nhiễu và làm nổi bật phân tích chính xác. Nhưng thực tế không phải vậy. Thí nghiệm cho thấy bỏ phiếu đa số không giúp chọn ra sự chính xác. Nó chỉ chọn ra bất cứ điều gì mà mô hình cố chấp nhất.

Sự phân biệt này rất quan trọng vì bỏ phiếu đa số đã trở thành một "mẹo" phổ biến trong các pipeline LLM. Quy trình rất đơn giản. Bạn chạy mô hình nhiều lần với cùng một prompt, thu thập các kết quả đầu ra và giữ lại câu trả lời xuất hiện thường xuyên nhất. Trong các lĩnh vực như chẩn đoán hình ảnh y tế hoặc phát hiện spam, các phương pháp ensemble (tập hợp) hoạt động hiệu quả vì các mô hình khác nhau, hoặc các góc nhìn khác nhau về dữ liệu, tạo ra các lỗi độc lập và thực sự có thể triệt tiêu lẫn nhau. Các mô hình ngôn ngữ lớn không phải là những cử tri độc lập. Chúng là một hệ thống duy nhất với một lịch sử huấn luyện, một bộ trọng số và một tập hợp các định kiến (biases) duy nhất. Khi bạn hỏi cùng một mô hình cùng một câu hỏi 51 lần, bạn không phải đang triệu tập một ủy ban. Bạn đang thực hiện một cuộc thăm dò ý kiến của cùng một người trả lời trong những tâm trạng hơi khác nhau một chút.

Vấn đề về sự cố chấp

Vấn đề cốt lõi là các lỗi của LLM hiếm khi là ngẫu nhiên. Chúng là những khuôn mẫu đã được khắc sâu vào dữ liệu huấn luyện và kiến trúc mô hình. Một mô hình đọc sai một Python decorator cụ thể trong một lần chạy có khả năng cao sẽ tiếp tục đọc sai nó trong lần chạy tiếp theo. Một mô hình "ảo giác" (hallucinate) về một lỗ hổng bảo mật vì tên biến trông giống mật khẩu có lẽ sẽ lại ảo giác về nó ở lần chạy thứ 47. Những nhiễu mà bạn đang cố gắng trung bình hóa thường chỉ là sự biến đổi bề mặt về cách dùng từ hoặc định dạng. Lập luận cốt lõi thường vẫn giữ nguyên không đổi.

Hãy xem xét một ví dụ cụ thể. Hãy tưởng tượng một hàm phân tích các tệp nhật ký (log files) bằng biểu thức chính quy (regular expression). Regex đó rất chặt chẽ và an toàn. Nhưng chuỗi r'...' chứa các ký tự mà trong một ngữ cảnh khác, có thể dẫn đến lỗi injection. Hãy yêu cầu một LLM đánh giá điều này. Nếu mô hình đã từng thấy hàng ngàn bài đăng trên Stack Overflow cảnh báo về regex injection trong các bộ phân tích log, nó có thể đánh dấu đoạn mã an toàn này là một rủi ro. Chạy một lần, bạn nhận được một kết quả dương tính giả (false positive). Chạy 51 lần, và có khả năng cao là bạn sẽ nhận được 51 kết quả dương tính giả, hoặc ít nhất là một đa số áp đảo. Lúc này, việc bỏ phiếu đa số sẽ củng cố thêm sự ảo giác đó. Mô hình có tính cố chấp, vì vậy "sự đồng thuận" cũng mang tính cố chấp tương tự.

Điều này xảy ra vì các thủ thuật về temperature và sampling không thay đổi những gì mô hình biết. Chúng chỉ sắp xếp lại cách nó diễn đạt. Temperature cao có thể khiến lời giải thích trở nên rông dài hoặc ngắn gọn. Nó có thể thay đổi các từ đồng nghĩa. Nó không đột nhiên dạy cho mô hình biết rằng regex đó thực sự vô hại. Những biến thể mà bạn đang bỏ phiếu chỉ là về mặt hình thức. Lỗi nằm ở cấu trúc.

51 lần chạy tiết lộ điều gì

Khi tôi trải 51 kết quả đầu ra đó ra bàn làm việc, khuôn mẫu hiện ra rất rõ ràng. Mô hình không khám phá 51 cách giải thích khác nhau về đoạn mã. Nó chỉ đang diễn lại cùng một cách giải thích bằng những giọng điệu hơi khác nhau một chút. Một vài lần chạy đi chệch khỏi kịch bản, gợi ý các bản sửa lỗi cho các trường hợp biên (edge-case) hoặc nhận thấy các vấn đề về phong cách không liên quan. Nhưng nhóm chiếm ưu thế, đa số rõ rệt, vẫn liên tục quay lại cùng một khẳng định sai lầm trung tâm. Khẳng định đó không đúng. Nó chỉ là thứ gì đó quen thuộc.

Toán học của việc bỏ phiếu đa số giả định các phép thử Bernoulli độc lập. Bạn cần các lỗi không liên quan để đa số có thể vượt trội hơn cá nhân. Trong thí nghiệm của tôi, các lỗi có liên quan sâu sắc với nhau. Chúng chia sẻ cùng một nguyên nhân gốc rễ: phân phối huấn luyện của mô hình coi trọng quá mức một số khuôn mẫu lập trình nhất định. Do đó, bỏ phiếu đa số không làm giảm lỗi. Nó khuếch đại định kiến của đa số. Nó tạo ra một cảm giác chắc chắn giả tạo cho một phân tích sai lầm.

Điều này đặc biệt nguy hiểm trong việc đánh giá mã nguồn vì các lập trình viên thường coi kết quả AI đồng nhất hoặc gần như đồng nhất là có thẩm quyền. Một gợi ý do dự duy nhất thì dễ dàng bị bác bỏ. Nhưng một khuyến nghị giữ nguyên qua 51 lần chạy sẽ tạo cảm giác như đó là sự thật khách quan (ground truth). Thực tế không phải vậy. Đó chỉ là một vòng lặp sai lầm (ground loop).

Nơi việc bỏ phiếu thực sự hiệu quả

Điều này không có nghĩa là bạn không bao giờ nên chạy một mô hình nhiều hơn một lần. Bỏ phiếu đa số có thể giúp ích trong những tình huống hẹp khi nhiệm vụ mang tính đơn giản và các lỗi thực sự là ngẫu nhiên. Yêu cầu một mô hình chọn giữa hai định dạng cú pháp, chọn một quy ước đặt tên biến, hoặc trích xuất một chuỗi ngày tháng từ một dòng log—những nhiệm vụ ít rủi ro này đôi khi sẽ có lợi từ việc lấy mẫu lặp lại. Sự biến thiên này là nhiễu thực sự, và một cuộc bỏ phiếu nhanh sẽ giúp loại bỏ nó.

Rắc rối bắt đầu khi nhiệm vụ yêu cầu suy luận về ý định. Liệu việc kiểm tra xác thực này có nên nằm ở đây không? Lời gọi bất đồng bộ này có an toàn không? Liệu sự xung đột khóa bộ nhớ đệm này có thực sự có thể khai thác được không? Những câu hỏi này đòi hỏi sự hiểu biết về ngữ cảnh, chứ không chỉ là khớp mẫu. Bộ khớp mẫu của một mô hình có tính xác định trong thiên kiến của nó. Nó sẽ tìm đến câu trả lời phổ biến nhất từ dữ liệu huấn luyện, chứ không phải câu trả lời chính xác nhất cho mã nguồn của bạn.

Cách sử dụng tài nguyên tính toán thông minh hơn

Việc chạy một mô hình cục bộ 51 lần sẽ tiêu tốn thời gian và điện năng thực tế. Có những cách tốt hơn để đầu tư tài nguyên tính toán đó. Nếu bạn muốn cải thiện độ tin cậy, sự đa dạng sẽ hiệu quả hơn số lượng. Hãy chạy hai mô hình khác nhau với