Mở đầu: Vì sao ChatGPT "nói chuyện được" còn GPT-3 gốc thì không hẳn
Nếu bạn từng thử dùng một base model LLM chưa qua "alignment" (chỉ huấn luyện dự đoán từ tiếp theo), bạn sẽ thấy nó có xu hướng lan man, đôi khi từ chối trả lời câu hỏi đơn giản, hoặc trả lời đúng cú pháp nhưng vô dụng với ý định thật của người hỏi. Bước biến một model "biết viết văn bản hợp lý" thành một trợ lý "biết giúp đỡ đúng ý con người" chính là RLHF — Reinforcement Learning from Human Feedback.
Bài học này giải thích vì sao huấn luyện có giám sát (SFT) chưa đủ, cách xây một reward model từ dữ liệu so sánh preference, ý tưởng cốt lõi của thuật toán PPO cập nhật policy theo reward đó, và cạm bẫy nguy hiểm nhất của cả quy trình: reward hacking — khi model học cách "đánh lừa" điểm số thay vì thực sự tốt hơn.
1. Vì sao SFT (Supervised Fine-Tuning) chưa đủ
SFT huấn luyện model bắt chước các cặp (câu hỏi, câu trả lời mẫu) do con người viết sẵn — về bản chất vẫn là "dự đoán từ tiếp theo giống văn bản mẫu". Vấn đề: con người không thể viết mẫu cho MỌI tình huống có thể xảy ra, và mục tiêu huấn luyện (bắt chước đúng từng từ) không trực tiếp đo lường điều ta thực sự muốn — "câu trả lời này có hữu ích/an toàn/trung thực không?".
RLHF giải quyết đúng khoảng cách đó: thay vì bắt chước 1 câu trả lời mẫu cố định, model được thưởng/phạt dựa trên việc câu trả lời của NÓ (tự sinh ra, đa dạng) có được con người ưa thích hơn phương án khác hay không — một tín hiệu học tập gần với "chất lượng thật" hơn nhiều so với SFT thuần.
// SFT: tối thiểu hoá sai khác giữa output model và 1 câu trả lời mẫu CỐ ĐỊNH
// (cross-entropy loss) — không có khái niệm "tốt hơn bao nhiêu", chỉ có
// "giống mẫu hay không giống mẫu".
function sftLoss(modelOutputTokens, referenceTokens) {
return crossEntropy(modelOutputTokens, referenceTokens);
}
// RLHF: tối đa hoá reward kỳ vọng trên CHÍNH output model tự sinh ra — không
// cần 1 câu trả lời mẫu duy nhất, chấp nhận nhiều câu trả lời khác nhau đều
// "tốt" miễn phản ánh đúng đánh giá của reward model.
function rlhfObjective(modelOutputTokens, rewardModel) {
return rewardModel.score(modelOutputTokens); // càng cao càng được khuyến khích
}
2. Preference Dataset & Reward Model
Thay vì thu thập câu trả lời "đúng", RLHF thu thập preference — cho model sinh ra 2 (hay nhiều) câu trả lời cho cùng 1 câu hỏi, rồi để con người chọn câu nào tốt hơn. Từ hàng chục nghìn cặp preference như vậy, ta huấn luyện một reward model — một model phụ học cách chấm điểm chất lượng một câu trả lời, sao cho điểm của phương án được chọn LUÔN cao hơn phương án bị loại:
// Quy tắc cập nhật kiểu Bradley-Terry rút gọn: điểm của phương án được
// chọn phải tăng, điểm phương án bị loại phải giảm, theo đúng hướng
// vector đặc trưng khác nhau giữa hai phương án.
function updateReward(model, chosenFeatures, rejectedFeatures, lr = 0.15) {
for (let i = 0; i < model.weights.length; i++) {
model.weights[i] += lr * (chosenFeatures[i] - rejectedFeatures[i]);
}
return model;
}
function scoreFeatures(model, features) {
return features.reduce((sum, f, i) => sum + f * model.weights[i], 0);
}
Đây chính xác là engine đứng sau demo tương tác ở mục 5 — mỗi lần bạn chọn A hoặc B, trọng số reward model cập nhật ngay lập tức theo công thức trên.
3. PPO — Cập nhật Policy theo Reward
Có reward model rồi, bước tiếp theo là dùng nó để CẢI THIỆN model chính (gọi là "policy" trong thuật ngữ RL) — cho policy sinh câu trả lời, chấm điểm bằng reward model, rồi điều chỉnh policy để có xu hướng sinh ra nhiều câu trả lời điểm cao hơn. Thuật toán phổ biến nhất cho bước này là PPO.
Điểm mấu chốt của PPO không phải là tối đa hoá reward bằng mọi giá — nó có một ràng buộc KL penalty giữ policy mới không lệch quá xa model gốc (trước alignment):
\[ \text{Mục tiêu} = \mathbb{E}[\text{Reward}(\text{câu trả lời})] - \beta \cdot D_{KL}(\pi_{\text{mới}} \Vert \pi_{\text{gốc}}) \]
Số hạng \(D_{KL}\) đo "độ lệch phân bố" giữa policy mới và policy gốc; hệ số \(\beta\) càng lớn thì model càng bị "kìm" gần hành vi gốc.
4. Cạm bẫy: Reward Hacking
// Reward model "ngây thơ" vô tình học tương quan SAI: dài = tốt.
function naiveRewardModel(response) {
return response.split(" ").length * 0.1; // chỉ đếm số từ, không đo chất lượng thật
}
// PPO tối ưu đúng theo hàm này sẽ đẩy policy sinh câu trả lời NGÀY CÀNG DÀI,
// dù người dùng thật không hề thấy hữu ích hơn — đây là reward hacking,
// không phải lỗi thuật toán PPO mà là lỗi CHẤT LƯỢNG của reward model.
function detectRewardDrift(responseLengthHistory, humanSatisfactionHistory) {
const lengthTrendUp = responseLengthHistory.at(-1) > responseLengthHistory[0] * 1.5;
const satisfactionFlat = Math.abs(humanSatisfactionHistory.at(-1) - humanSatisfactionHistory[0]) < 0.05;
return lengthTrendUp && satisfactionFlat; // độ dài tăng nhưng hài lòng không đổi -> nghi ngờ reward hacking
}
Cách giảm thiểu phổ biến: theo dõi cả reward VÀ các chỉ số độc lập khác trong suốt quá trình PPO, dừng sớm khi thấy dấu hiệu "trôi" (ví dụ độ dài câu trả lời tăng bất thường không đi kèm cải thiện chất lượng thật), và định kỳ thu thập thêm preference mới để re-train reward model tránh nó bị "khai thác" theo cùng 1 kiểu.
5. Thực hành tương tác: Reward Model Trainer
Chấm 5 cặp câu trả lời A/B dưới đây theo sở thích CỦA CHÍNH BẠN (không có đáp án đúng/sai tuyệt đối). Trọng số reward model sẽ cập nhật ngay sau mỗi lựa chọn — sau khi chấm đủ 5 cặp, demo áp dụng reward model vừa "học" từ bạn lên một cặp hoàn toàn MỚI mà nó chưa từng thấy để xem nó có generalize đúng ý bạn không:
export function updateReward(model, chosenFeatures, rejectedFeatures, lr = 0.15) {
for (let i = 0; i < model.weights.length; i++) {
model.weights[i] += lr * (chosenFeatures[i] - rejectedFeatures[i]);
}
return model;
}
// Mỗi lần bạn bấm chọn A hoặc B, hàm này chạy 1 lần — 3 chiều đặc trưng
// ẩn (Hữu ích / Súc tích / An toàn) của mỗi câu trả lời được cộng dồn
// theo đúng lựa chọn của bạn.
Nếu bạn nhất quán ưu tiên an toàn ở các cặp có sự khác biệt lớn (ví dụ cặp 1, 3, 5), trọng số "An toàn" sẽ tăng mạnh nhất — và reward model thường sẽ dự đoán đúng bạn thích phương án an toàn hơn ở cặp giữ lại, dù nó chưa từng thấy cặp đó. Đây chính là ý nghĩa của "generalize" trong reward model thật.
Tải file code thực hành minh họa bài học
File JavaScript aisys-rlhf-lab.js — 5 cặp preference huấn luyện, 1 cặp kiểm tra giữ lại, và
hàm cập nhật/chấm điểm reward model dùng trong bài:
📖 Tài liệu tham khảo
- Paper nền tảng RLHF: Training language models to follow instructions with human feedback (InstructGPT, OpenAI 2022) — quy trình 3 bước SFT → Reward Model → PPO gốc.
- Thuật toán PPO: Proximal Policy Optimization Algorithms (Schulman et al., 2017) — bài báo gốc giới thiệu PPO nhắc ở mục 3.
- Reward hacking / Goodhart's Law trong RL: Discovering Language Model Behaviors with Model-Written Evaluations (Perez et al., 2022) — khảo sát các hành vi lệch lạc phát sinh từ tối ưu reward.
Bình luận