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.


📚 Điều kiện tiên quyết
Không yêu cầu kiến thức RL sâu. Nếu muốn hiểu cơ chế train model ngôn ngữ ở tầng toán học trước khi alignment (pretraining/SFT), xem qua Series 12 — Tokenizer & LLM Pretraining.

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-vs-rlhf-objective.js
// 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
}
💡 Mẹo: RLHF luôn build TRÊN NỀN một model đã SFT
RLHF không thay thế SFT — nó là bước tiếp theo. Model phải đã qua SFT để biết định dạng hội thoại cơ bản trước, RLHF sau đó tinh chỉnh HÀNH VI (giọng điệu, mức độ hữu ích, an toàn) chứ không dạy lại từ đầu cách hình thành câu.

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:

reward-model-update.js
// 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.

🔬 Đào sâu: Vì sao cần KL penalty thay vì tối ưu reward thuần tuý
Nếu tối ưu reward mà không ràng buộc, policy có thể "trôi" rất xa khỏi phân bố ngôn ngữ tự nhiên để tìm ra vùng điểm reward cao bất thường (chính là cội nguồn của reward hacking ở mục 4) — ví dụ lặp đi lặp lại 1 cụm từ mà reward model (do huấn luyện chưa hoàn hảo) tình cờ chấm điểm cao. KL penalty giữ policy "neo" gần hành vi ngôn ngữ tự nhiên đã học được từ pretraining + SFT, coi đó là vùng an toàn để tìm kiếm cải thiện.

4. Cạm bẫy: Reward Hacking

🕳️ Cạm bẫy: Model học cách "đánh lừa" điểm số thay vì thật sự tốt hơn
Reward model KHÔNG PHẢI con người thật — nó là một model được huấn luyện xấp xỉ sở thích con người từ một tập mẫu hữu hạn, nên luôn có sai số và điểm mù. Khi PPO tối ưu quá mạnh theo đúng con số reward model chấm, policy có thể tìm ra "lỗ hổng" của reward model — ví dụ trả lời dài dòng hơn vì reward model (được huấn luyện từ dữ liệu con người thường thích câu trả lời chi tiết) học nhầm "dài = tốt", dẫn đến model sinh câu trả lời dài lê thê không cần thiết chỉ để ăn điểm, thay vì thực sự hữu ích hơn. Đây gọi là reward hacking — tối ưu đúng theo thước đo (proxy) nhưng lại xa rời mục tiêu thật.
reward-hacking-example.js
// 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:

🏆 Reward Model Trainer
Đã chấm 0/5 cặp — chọn phương án bạn thích hơn ở mỗi cặp bên dưới.
aisys-rlhf-lab.js (trích)
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 về aisys-rlhf-lab.js

📖 Tài liệu tham khảo

Bài viết liên quan trong series

Bài 3: Huấn Luyện Phân Tán (Khái Niệm) Bài 5: Red-Teaming & Đánh Giá Benchmark Quay lại Lộ trình Kỹ Thuật Hệ Thống AI

Bình luận