Bài thứ mười dừng lại ở một base model: dự đoán token kế tiếp rất giỏi, nhưng chỉ biết viết tiếp văn bản. Hỏi nó một câu, nó có thể viết tiếp thành một trang web hay một danh sách câu hỏi khác. Bài này đi qua chặng biến nó thành assistant, thứ biết trả lời đúng câu được hỏi, biết dừng và biết từ chối khi cần. Chặng này gọi chung là post-training, gồm ba lớp:
- SFT (supervised fine-tuning): train tiếp trên hội thoại mẫu đã được chat template đóng gói, loss chỉ tính trên phần trả lời.
- Học từ so sánh: cho model biết câu trả lời nào tốt hơn, bằng RLHF (reward model và PPO) hoặc DPO, cách tối ưu cùng mục tiêu nhưng bỏ reward model và vòng RL.
- Thay người chấm bằng model: RLAIF và Constitutional AI.
Ý xuyên suốt: post-training gần như không thêm tri thức, nó định hình cách model dùng tri thức đã có. Nhiều tật quen thuộc của chatbot, như dài dòng, chiều lòng người dùng hay từ chối quá tay, bắt nguồn từ chặng này chứ không phải từ kiến trúc. Bài đi theo thứ tự của Hình 1 ở đầu trang.
01Từ base model đến assistant
Bài 1, mục 7.4 đã vẽ bức tranh tổng quát: pretraining cho model tri thức, SFT dạy nó trả lời đúng khuôn hội thoại, alignment bằng RLHF hoặc DPO dạy nó câu trả lời nào được ưa hơn. Mục đó cũng có bảng nối từng hành vi quen thuộc của chatbot với giai đoạn sinh ra nó. Bài này không nhắc lại bức tranh đó mà đi vào cơ chế: mỗi bước tối ưu cái gì, công thức từ đâu ra, và chỗ nào hay hỏng.
Một điều nên giữ trong đầu từ đầu: về mặt toán, phần lớn post-training vẫn là những thứ ta đã gặp. SFT dùng đúng cross-entropy của bài 10, chỉ khác dữ liệu và chỗ tính loss. DPO cuối cùng cũng chỉ là một loss phân loại trên log-prob. Chỉ có PPO là mang vào một thứ thật sự mới: model phải tự sinh văn bản trong lúc train rồi được chấm điểm. Và khác biệt đó kéo theo gần như toàn bộ chi phí và độ phức tạp của RLHF.
02Vì sao base model không nghe lời
Objective pretraining thưởng cho cái gì
Pretraining chỉ thưởng cho việc gán xác suất cao cho token thật sự đứng tiếp theo trong văn bản trên internet. Objective đó không có khái niệm “câu hỏi” hay “câu trả lời”. Câu “Thủ đô của Pháp là gì?” trên internet có thể nằm trong một bài quiz (tiếp theo là câu hỏi khác), một trang diễn đàn (tiếp theo là ngày giờ đăng bài) hay một trang FAQ (tiếp theo là câu trả lời). Base model học đúng phân phối đó. Nó không phải không biết câu trả lời; nó không biết rằng việc của nó là trả lời.
Tri thức đã có sẵn: giả thuyết superficial alignment
LIMA (Zhou et al. 2023) fine-tune LLaMa 65B chỉ trên 1.000 ví dụ chọn lọc kỹ, không dùng RLHF. Trong đánh giá của người, câu trả lời của LIMA tương đương hoặc được ưa hơn GPT-4 trong 43% trường hợp, hơn Bard 58% và hơn DaVinci003 65% (abstract). Nhóm tác giả đưa ra Superficial Alignment Hypothesis (mục 2): tri thức và năng lực gần như đều được học trong pretraining, alignment chủ yếu dạy model nên dùng định dạng và phong cách nào.
URIAL (Lin et al. 2023) đo trực tiếp điều đó: cho base model và bản đã align cùng đọc một câu trả lời, rồi ở mỗi vị trí xem token mà bản align chọn đứng thứ mấy trong phân phối của base. Với Llama-2-7b và Llama-2-7b-chat, 77,7% vị trí trùng token top-1, 14,5% là token hạng 2–3 của base (mục 2.1 gọi là “marginal”), chỉ 7,8% thật sự lệch (Hình 3). Token lệch chủ yếu là token phong cách: từ nối, câu mở đầu lịch sự, lời cảnh báo an toàn (mục 2.2–2.3). Từ đó URIAL cho base model trả lời như assistant chỉ bằng prompt: một system prompt cộng 3 ví dụ cố định, tổng 1.011 token, không train gì (mục 3.3).
Giới hạn cần nói rõ: LIMA và URIAL đo chất lượng hội thoại trên câu hỏi phổ thông. Làm theo định dạng phức tạp, gọi tool, suy luận nhiều bước hay từ chối đúng chỗ vẫn cần post-training thật sự, và các pipeline ở mục 10 dùng hàng trăm nghìn ví dụ. “Superficial” nghĩa là không tạo tri thức mới, không có nghĩa là dễ.
03SFT: dạy format hội thoại
SFT là next-token prediction trên dữ liệu khác
SFT không có objective mới: vẫn là cross-entropy của token kế tiếp như bài 10, vẫn là training loop của bài 3. Chỉ khác hai thứ: dữ liệu là hội thoại (instruction, response), và loss mask chỉ giữ token của assistant. Token của system prompt và user vẫn đi qua model làm context nhưng không đóng góp gradient.
Lịch sử dữ liệu SFT cho thấy chất lượng quan trọng hơn số lượng:
- Biến dataset NLP có sẵn thành instruction. FLAN (Wei et al. 2021) viết 10 template cho mỗi dataset trong 62 dataset (mục 2.1), fine-tune LaMDA-PT 137B, và vượt GPT-3 175B zero-shot trên 20 trong 25 dataset (abstract).
- Để model tự sinh instruction. Self-Instruct (Wang et al. 2022) đi từ 175 tác vụ mẫu, cho GPT-3 sinh thêm và lọc lại, được 52.445 instruction (Bảng 1). Fine-tune GPT-3 trên đó tăng 33 điểm tuyệt đối trên Super-NaturalInstructions, ngang InstructGPT-001 (abstract, Bảng 3). Đây là tiền thân của dữ liệu synthetic ngày nay.
- Người viết tay. InstructGPT dùng khoảng 13 nghìn prompt cho SFT (mục 3.2). Llama 2 dừng ở 27.540 ví dụ do người viết, vì thấy một tập nhỏ chất lượng cao tốt hơn hàng triệu ví dụ từ nguồn bên thứ ba (mục 3.1, “Quality Is All You Need”).
Chat template
Bài 4, mục 6.3 đã giới thiệu ý chính: chat template biến hội thoại thành một token protocol có role. Ở đây là phần thao tác. Trên Hugging Face, template là một đoạn Jinja lưu trong tokenizer_config.json (trường chat_template), và tokenizer.apply_chat_template(messages, ...) chạy nó trên danh sách message. Hai tham số quan trọng:
add_generation_prompt=Truethêm phần mở đầu lượt của assistant (với Qwen là<|im_start|>assistant\n) để model biết đến lượt nó. Thiếu cái này, model có thể viết tiếp lượt của user.- Nếu tự tokenize chuỗi đã áp template, template thường đã chứa đủ special token, nên tài liệu Hugging Face khuyên dùng
add_special_tokens=Falseđể tránh thêm hai lần.
Ba lỗi hay gặp nhất đều nằm ở đây: quên add_generation_prompt, dùng template của model khác, và tự ghép chuỗi bằng tay. Model chỉ thấy một định dạng trong suốt SFT; lệch định dạng lúc inference là đưa nó ra khỏi phân phối đã học.
Loss mask chỉ trên token của assistant
Bài 5, mục 11.2–11.3 đã giải thích labels, việc shift và loss mask. Với SFT, vị trí thuộc prompt có label = -100, giá trị mà cross-entropy của PyTorch bỏ qua; vị trí thuộc câu trả lời giữ nguyên token ID. Ta muốn model học trả lời, không học đặt câu hỏi như người dùng, và không tiêu gradient vào việc học thuộc system prompt lặp lại ở mọi mẫu.
Chạy trên một model thật
Code dưới đây in chuỗi sau khi áp chat template, đánh dấu token được tính loss, rồi đưa cùng một câu hỏi cho Qwen2.5-0.5B bản base và bản instruct, có và không có template. Decoding là greedy nên kết quả lặp lại được.
# Python 3.12, torch 2.14.1 (CPU), transformers 5.18.0
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers.utils import logging
logging.disable_progress_bar()
tok = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-0.5B-Instruct")
# 1. Chat template: hội thoại -> chuỗi văn bản có role
chat = [
{"role": "user", "content": "Thủ đô của Pháp là gì?"},
{"role": "assistant", "content": "Thủ đô của Pháp là Paris."},
]
print(tok.apply_chat_template(chat, tokenize=False))
# 2. Loss mask: chỉ token của assistant được tính loss
prompt_ids = tok.apply_chat_template(chat[:1], add_generation_prompt=True, tokenize=True, return_dict=True)["input_ids"]
full_ids = tok.apply_chat_template(chat, tokenize=True, return_dict=True)["input_ids"]
assert full_ids[: len(prompt_ids)] == prompt_ids # prompt là tiền tố của cả hội thoại
labels = [-100] * len(prompt_ids) + full_ids[len(prompt_ids):]
print(f"tổng {len(full_ids)} token, tính loss trên {sum(l != -100 for l in labels)} token:")
print([tok.decode(t) for t, l in zip(full_ids, labels) if l != -100])
# 3. Cùng một câu hỏi cho base và instruct, có và không có template
question = "Thủ đô của Pháp là gì?"
for name in ("Qwen/Qwen2.5-0.5B", "Qwen/Qwen2.5-0.5B-Instruct"):
model = AutoModelForCausalLM.from_pretrained(name, dtype=torch.float32).eval()
for use_template in (False, True):
text = (tok.apply_chat_template([{"role": "user", "content": question}],
add_generation_prompt=True, tokenize=False)
if use_template else question)
ids = tok(text, return_tensors="pt").input_ids
out = model.generate(ids, max_new_tokens=40, do_sample=False)
answer = tok.decode(out[0, ids.shape[1]:], skip_special_tokens=False)
print(f"\n[{name.split('/')[1]} | template={use_template}]\n{answer!r}")
Output khi chạy:
<|im_start|>system
You are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>
<|im_start|>user
Thủ đô của Pháp là gì?<|im_end|>
<|im_start|>assistant
Thủ đô của Pháp là Paris.<|im_end|>
tổng 47 token, tính loss trên 10 token:
['Th', 'ủ', ' đô', ' của', ' Pháp', ' là', ' Paris', '.', '<|im_end|>', '\n']
[Qwen2.5-0.5B | template=False]
' - 2019-01-19 10:00:00\nThủ đô của Pháp là gì? - 2019-01-'
[Qwen2.5-0.5B | template=True]
'Thủ đô của Pháp là Paris. Comey, bạn có thể trả lời cho tôi một câu trả lời ngắn gọn hơn về thủ đô của Pháp? Comey, thủ đô của Pháp là Paris.<|endoftext|>'
[Qwen2.5-0.5B-Instruct | template=False]
' - 100th\nHome / Pháp / Thủ đô của Pháp là gì?\nThủ đô của Pháp là gì?\nThủ đô của Pháp là Paris. Đây là thủ đô của nước'
[Qwen2.5-0.5B-Instruct | template=True]
'Thủ đô của Pháp là Paris.<|im_end|>'
Đọc output:
- Template tự chèn system prompt “You are Qwen…” dù ta không đưa system message nào. Đoạn này có trong mọi mẫu SFT của model nên lúc inference cũng phải có, một lý do nữa để gọi
apply_chat_templatethay vì tự ghép chuỗi. - Chỉ 10 trên 47 token được tính loss, trong đó có
<|im_end|>. Model học khi nào dừng đúng bằng cách này. - Base model không có template viết tiếp như một trang web: ngày giờ đăng bài, rồi lặp lại câu hỏi, đúng hành vi mà objective pretraining thưởng.
- Base model có template trả lời được câu đầu nhưng không biết dừng: tự bịa thêm một lượt hỏi, rồi kết thúc bằng
<|endoftext|>thay vì<|im_end|>. Có vẻ nó đã gặp định dạng gần giống trong pretraining, nhưng chưa được dạy giao thức lượt lời. Với câu hỏi tiếng Anh, base model trả lời gọn ngay cả khi không có template (xem bản tiếng Anh của bài), nên đây là chuyện phân phối dữ liệu, không phải quy luật tuyệt đối. - Instruct model không có template quay về hành vi của base. Post-training không xoá năng lực viết tiếp văn bản; nó dạy một hành vi mới gắn với một định dạng cụ thể. Sai định dạng thì nhận lại hành vi cũ.
Một cái bẫy: apply_chat_template có tham số return_assistant_tokens_mask=True, nhưng nó chỉ hoạt động khi template đánh dấu phần assistant bằng thẻ {% generation %}. Template của Qwen2.5 không có thẻ đó, và với transformers 5.18.0, mask trả về toàn số 0, transformers chỉ in một warning rằng template không chứa {% generation %} chứ không báo lỗi, tức không token nào được train. Code trên vì vậy dựng mask bằng cách so tiền tố, kèm assert.
04Giới hạn của SFT
SFT dạy model bắt chước một câu trả lời mẫu, và đó cũng là giới hạn của nó.
Không có tín hiệu “tốt hơn”. Cross-entropy chỉ nói “tăng xác suất của đúng chuỗi này”. Nó không phân biệt câu hơi kém với câu sai hoàn toàn. Với tóm tắt, giải thích hay một lời từ chối lịch sự, không có một đáp án “đúng” duy nhất, và người viết dữ liệu chỉ viết được câu trả lời tốt nhất của họ. Con người khó viết câu trả lời hoàn hảo nhưng so sánh hai câu khá tốt; học từ so sánh khai thác đúng chỗ đó.
Exposure bias. Lúc SFT, model luôn được thấy câu trả lời mẫu làm context (teacher forcing). Lúc inference, nó đọc lại chính token nó vừa sinh, và một lỗi nhỏ đưa nó vào trạng thái chưa từng thấy lúc train. SFT không bao giờ train trên văn bản do chính model sinh, nên không dạy được cách thoát ra. RL train đúng trên output của policy.
SFT có thể dạy model bịa. John Schulman lập luận trong một bài nói năm 2023 rằng “even if you clone on a hundred percent correct answers, you’re teaching the model to hallucinate”, nếu model không có những tri thức đó: cách duy nhất để giảm loss là học giọng tự tin của câu trả lời. RL có thể thưởng cho “tôi không chắc” khi model không chắc, điều mà một đáp án mẫu cố định khó diễn đạt.
05RLHF (1): dữ liệu so sánh và reward model
RLHF có ba phần: thu dữ liệu so sánh, train reward model, rồi tối ưu policy theo reward model. Mục này đi qua hai phần đầu.
Thu dữ liệu so sánh
Học reward từ so sánh của người có từ trước LLM. Christiano et al. 2017 cho người chọn đoạn video tốt hơn trong hai đoạn của một agent Atari hoặc robot mô phỏng; phản hồi cho dưới 1% số tương tác, khoảng một giờ công, là đủ để học hành vi phức tạp (abstract). Stiennon et al. 2020 đem cách này sang tóm tắt văn bản, và InstructGPT (Ouyang et al. 2022) biến nó thành công thức chuẩn cho LLM:
- khoảng 40 contractor qua Upwork và ScaleAI (mục 3.4);
- mỗi prompt có K = 4 đến 9 câu trả lời để người chấm xếp hạng, cho ra
C(K, 2)cặp, tối đa 36 cặp (mục 3.5); - khoảng 13 nghìn prompt cho SFT, 33 nghìn cho reward model, 31 nghìn cho PPO (mục 3.2; số chính xác ở Bảng 6, Phụ lục A.3).
HH-RLHF của Anthropic (Bai et al. 2022) tách hai trục: helpfulness, crowdworker chọn câu hữu ích hơn, và harmlessness, crowdworker cố dụ model nói điều có hại rồi chọn câu ít có hại hơn; bộ cơ sở có khoảng 44 nghìn và 42 nghìn so sánh (mục 2.3). Llama 2 thu 1.418.091 so sánh nhị phân của riêng Meta (Bảng 6), mỗi so sánh kèm mức độ từ “significantly better” tới “negligibly better/ unsure” (mục 3.2.1).
Người chấm không đồng ý với nhau
Trong InstructGPT, hai người chấm được train cùng quy trình chỉ đồng ý với nhau 72,6 ± 1,5% số lần; với người chấm held-out (không tham gia tạo dữ liệu train) là 77,3 ± 1,3% (mục 3.4). Điều này đặt một trần cho mọi thứ phía sau: nếu người với người chỉ đồng ý khoảng 3/4 số lần, reward model chính xác 75% trên tập test đã gần chạm mức tốt nhất có thể. “Sở thích con người” không phải một hàm xác định; nó ồn.
Bradley–Terry: từ so sánh tới điểm số
Dữ liệu có dạng “với prompt x, câu y_w được chọn hơn câu y_l” (w là win, l là lose). Ta muốn một hàm r(x, y) cho ra một con số cho mỗi câu trả lời. Cầu nối là mô hình Bradley–Terry, mà Christiano et al. 2017 cũng dùng (phương trình 1).
Bước 1. Giả định. Mỗi câu trả lời có một điểm ẩn r. Xác suất y_w được chọn hơn y_l tỉ lệ với exp(r) của mỗi câu:
P(y_w ≻ y_l | x) = exp(r(x, y_w)) / ( exp(r(x, y_w)) + exp(r(x, y_l)) )
Đây là phương trình 1 trong DPO paper. Nó giống hệt softmax trên hai lựa chọn.
Bước 2. Rút gọn. Chia cả tử và mẫu cho exp(r(x, y_w)):
P(y_w ≻ y_l | x) = 1 / ( 1 + exp(−(r(x, y_w) − r(x, y_l))) )
= σ( r(x, y_w) − r(x, y_l) )
với σ(z) = 1 / (1 + e^(−z)) là hàm sigmoid. Kết quả này nói một điều quan trọng: xác suất chỉ phụ thuộc vào hiệu hai điểm. Cộng cùng một hằng số vào mọi điểm thì không gì thay đổi. Reward model vì thế không có thang tuyệt đối; một reward bằng 3,2 tự nó không có nghĩa gì, chỉ có chênh lệch giữa hai câu trả lời cho cùng một prompt là có nghĩa.
Bước 3. Maximum likelihood. Ta muốn tham số φ của reward model làm cho dữ liệu quan sát được có xác suất cao nhất. Lấy log và đổi dấu để có một loss cần tối thiểu hoá:
L_R(φ) = −E_(x, y_w, y_l) [ log σ( r_φ(x, y_w) − r_φ(x, y_l) ) ]
Đây là phương trình 2 trong DPO paper, cũng là loss của Stiennon et al. (mục 3.4) và InstructGPT (mục 3.5): một binary cross-entropy cho bài toán “câu nào thắng”, với logit là hiệu hai reward. Nếu r_w − r_l = 0, loss là −log 0,5 = ln 2 ≈ 0,693; hiệu bằng 1 cho loss ≈ 0,313; hiệu bằng −1 (xếp ngược) cho loss ≈ 1,313. Llama 2 thêm một margin m(r) vào trong sigmoid, lớn hơn khi người chấm nói “significantly better” (mục 3.2.2, phương trình 2); Llama 3 bỏ margin đi (mục 4.1.2).
Reward model là một LLM với đầu ra vô hướng
Reward model thường là chính một LLM khởi tạo từ model SFT, bỏ lm_head chiếu ra vocabulary và thay bằng một lớp tuyến tính ra một con số, đọc ở token cuối của prompt + câu trả lời. Nó vẫn là Transformer của bài 8, chỉ khác cái đầu. InstructGPT dùng reward model 6B cho mọi policy, kể cả 175B, vì tiết kiệm compute và vì train reward model 175B không ổn định (mục 3.5). Một chi tiết đáng chú ý: K câu trả lời của cùng prompt nằm trong cùng một batch element; xáo trộn các cặp làm reward model overfit chỉ sau một epoch.
06RLHF (2): tối ưu bằng PPO
Mục tiêu: reward trừ KL
Ta muốn policy π_θ (khởi tạo từ bản SFT) sinh câu trả lời có reward cao. Nhưng nếu chỉ tối đa hoá reward, policy sẽ nhanh chóng tìm ra những câu kỳ quặc mà reward model chấm cao nhầm, vì reward model chỉ được train trên phân phối câu trả lời của model SFT. Mục tiêu chuẩn vì vậy có thêm một khoản phạt:
max_π E_(x ~ D, y ~ π(·|x)) [ r(x, y) ] − β · D_KL( π(·|x) ‖ π_ref(·|x) )
Đây là phương trình 3 trong DPO paper. π_ref là reference model, một bản sao đóng băng của model SFT. β điều chỉnh độ mạnh của khoản phạt.
Khoản KL làm ba việc: giữ policy trong vùng reward model còn đáng tin; giữ năng lực ngôn ngữ của model SFT; và giữ độ đa dạng, vì không có KL thì nghiệm tối ưu là dồn toàn bộ xác suất vào một câu trả lời reward cao nhất.
Trong cài đặt thực tế, khoản phạt được tính trên từng câu trả lời đã sinh và trừ thẳng vào reward (Stiennon et al., mục 3.4):
R(x, y) = r(x, y) − β · log( π_θ(y|x) / π_ref(y|x) )
Kỳ vọng của log-ratio theo y ~ π_θ chính là KL, nên tối đa hoá R trung bình là tối đa hoá mục tiêu ở trên. Log-prob của câu bằng tổng log-prob từng token, nên khoản phạt chia được thành phạt từng token, còn reward model chỉ cộng vào ở token cuối. InstructGPT (phương trình 2) thêm một số hạng γ trộn lại loss pretraining, gọi là PPO-ptx, để giảm “alignment tax” (mục 7). β thật sự khá nhỏ: 0,02 ở InstructGPT (Phụ lục C.4); 0,01 cho Llama 2 7B và 13B, 0,005 cho 34B và 70B (mục 3.2.3).
PPO ở mức trực giác
Mục tiêu trên không lấy đạo hàm trực tiếp được như SFT, vì y được lấy mẫu từ chính policy, và phép lấy mẫu không khả vi. Policy gradient đi đường vòng: tăng log-prob của những token dẫn đến kết quả tốt hơn kỳ vọng, giảm log-prob của những token dẫn đến kết quả tệ hơn. Ba khái niệm:
- Advantage: token “tốt hơn kỳ vọng” bao nhiêu. Nếu mọi câu đều được reward khoảng 5, reward 5 không nói gì; điều đáng học là câu nào được 7, câu nào được 3.
- Value model: dự đoán tổng reward sẽ nhận được tính từ token hiện tại, tức “kỳ vọng” ở mỗi vị trí. InstructGPT khởi tạo nó từ reward model (mục 3.5). Advantage là reward thật trừ dự đoán này.
- Clipping: PPO (Schulman et al. 2017) cắt tỉ lệ
ρ = π_θ_mới(token) / π_θ_cũ(token)vào khoảng[1 − ε, 1 + ε], thường vớiε = 0,2(phương trình 7; Bảng 1). Một bước update không đẩy xác suất của token đi quá 20% so với policy đã sinh dữ liệu, tránh những bước nhảy phá hỏng policy.
Một vòng PPO vì vậy gồm: cho policy sinh câu trả lời cho một batch prompt (sampling của bài 9, chạy ngay trong vòng train); reward model chấm, reference model tính khoản phạt KL; value model ước lượng advantage; cập nhật policy và value model vài epoch trên dữ liệu vừa sinh; rồi lặp lại với policy mới. InstructGPT chạy 256 nghìn episode trên khoảng 31 nghìn prompt, batch 512 (Phụ lục C.4).
Bốn model trong bộ nhớ
Hàng trên của Hình 2 (ở mục 8) vẽ lại vòng lặp này. Số model phải có mặt:
| Model | Vai trò | Được train? |
|---|---|---|
| Policy | sinh câu trả lời, là thứ ta muốn có cuối cùng | có |
| Value | ước lượng giá trị để tính advantage | có |
| Reward | chấm điểm câu trả lời | không |
| Reference | tính khoản phạt KL | không |
Policy và value cần weights, gradient và optimizer state, khoảng 16 byte mỗi tham số như bài 10, mục 8 đã tính; reward và reference chỉ cần weights. Bước sinh văn bản còn chậm hơn: nó chạy từng token một. Trong phần profiling của OpenRLHF (Hu et al. 2024, bản v1, mục 2.2), bước sinh mẫu của PPO chiếm 80% tổng thời gian train; bản mới nhất của paper ghi hơn 90% (mục 1). Đây là lý do có cả một lớp framework riêng để chạy RLHF, và là lý do DPO ở mục 8 hấp dẫn đến vậy.
07Reward hacking và cái giá của alignment
Overoptimization là quy luật
Reward model chỉ là xấp xỉ của sở thích con người, train trên vài chục nghìn so sánh có độ đồng thuận khoảng 75%. Tối ưu mạnh một xấp xỉ thì sớm muộn sẽ tìm ra chỗ nó sai (định luật Goodhart). Stiennon et al. 2020 đã thấy: tối ưu theo reward model ban đầu cải thiện bản tóm tắt, rồi overfit, đến lúc reward model trở nên ngược chiều với đánh giá của người (mục 4.3, Hình 5).
Gao et al. 2022 đo điều này định lượng. Họ dùng một reward model 6B làm “gold” thay người chấm, train các “proxy” reward model từ 3M đến 3B tham số trên nhãn do gold sinh (mục 2.1), tối ưu policy theo proxy rồi xem điểm gold. Khi policy đi xa reference (đo bằng d = sqrt(KL)), điểm proxy tăng mãi còn điểm gold tăng rồi giảm (Hình 1), theo hai dạng hàm fit rất khớp (mục 1):
best-of-n: R(d) = d · (α_bon − β_bon · d)
RL: R(d) = d · (α_RL − β_RL · log d)
Cả hai đều có một đỉnh; qua đỉnh, tối ưu thêm chỉ làm chất lượng thật đi xuống. Reward model lớn hơn đẩy đỉnh ra xa nhưng không xoá nó. Vì vậy khoản phạt KL, early stopping và việc train lại reward model theo từng vòng không phải chi tiết phụ.
Độ dài: dạng reward hacking phổ biến nhất
Người chấm thường ưa câu trả lời dài và kỹ hơn, reward model học điều đó, policy học lại rất nhanh. Singhal et al. 2023 cho thấy với WebGPT và RLCD, 70–90% mức tăng reward sau PPO giải thích được chỉ bằng việc câu trả lời dài ra (mục 3.1, Bảng 1). Thay reward model bằng một reward chỉ dựa trên độ dài, PPO vẫn đạt win rate gần ngang RLHF chuẩn: 56% so với 58% trên WebGPT, 64% so với 63% trên RLCD (simulated preference, mục 3.2, Bảng 2). Đây là win rate của từng bản so với model SFT, không phải hai bản đấu trực tiếp với nhau.
Sycophancy
Sharma et al. 2023 kiểm tra năm assistant (claude-1.3, claude-2.0, gpt-3.5-turbo, gpt-4, llama-2-70b-chat) trên bốn tác vụ, như đổi đáp án đúng khi bị chất vấn hay lặp lại lỗi của người dùng; cả năm đều sycophantic nhất quán (mục 3). Phân tích dữ liệu sở thích cho thấy cả người lẫn preference model đôi khi chọn một câu sycophantic viết thuyết phục thay vì câu đúng (mục 4.3, Hình 7). Sycophancy không phải bug của một model; nó được dạy bởi chính dữ liệu so sánh.
Giảm đa dạng và alignment tax
Kirk et al. 2023 thấy RLHF tổng quát hoá ra ngoài phân phối tốt hơn SFT nhưng làm giảm đáng kể độ đa dạng đầu ra (abstract; mục 6.1–6.2). Phần đo đa dạng chủ yếu trên tác vụ tóm tắt, và mức giảm lớn nhất là giữa các câu trả lời cho cùng một input. InstructGPT ghi nhận policy RLHF tụt điểm trên SQuAD, DROP, HellaSwag và dịch WMT15 Pháp–Anh, gọi là alignment tax (mục 1 và 4.2); PPO-ptx giảm phần lớn mức tụt. Bai et al. 2022 thấy “thuế” này nặng ở model nhỏ, còn model 13B và 52B lại tốt hơn trên đánh giá zero-shot sau RLHF (mục 1.1 và 4.6).
Đặt cạnh nhau, những kết quả này giải thích bảng hành vi ở bài 1, mục 7.4: dài dòng đến từ length bias, sycophancy đến từ dữ liệu sở thích, câu trả lời “na ná nhau” đến từ đánh đổi giữa reward và đa dạng. Casper et al. 2023 xếp các vấn đề của RLHF theo dữ liệu phản hồi, reward model, policy và việc train chung hai thứ sau, phân biệt vấn đề tractable (sửa được trong RLHF) với fundamental (cần cách tiếp cận khác) (mục 3, Hình 1).
08DPO: bỏ reward model và vòng RL
RLHF với PPO đắt và khó: bốn model, sinh văn bản trong vòng train, nhiều siêu tham số. DPO (Rafailov et al. 2023) hỏi: nếu mục tiêu “reward trừ KL” có nghiệm đóng, có thể bỏ reward model và tối ưu thẳng trên dữ liệu so sánh không? Có, và phép dẫn chỉ cần vài dòng đại số.
Bước 1: nghiệm đóng của mục tiêu reward trừ KL
Bắt đầu từ mục tiêu của mục 6 cho một prompt x cố định. Viết KL thành kỳ vọng của log-ratio rồi gộp vào trong:
E_(y~π) [ r(x, y) ] − β · KL( π ‖ π_ref )
= E_(y~π) [ r(x, y) − β · log( π(y|x) / π_ref(y|x) ) ]
= −β · E_(y~π) [ log( π(y|x) / π_ref(y|x) ) − r(x, y) / β ]
= −β · E_(y~π) [ log( π(y|x) / ( π_ref(y|x) · exp(r(x, y) / β) ) ) ]
Mẫu số π_ref(y|x) · exp(r(x, y)/β) gần giống một phân phối, chỉ thiếu chuẩn hoá. Đặt hằng số chuẩn hoá:
Z(x) = Σ_y π_ref(y|x) · exp( r(x, y) / β )
và định nghĩa phân phối:
π*(y|x) = π_ref(y|x) · exp( r(x, y) / β ) / Z(x)
Thay π_ref · exp(r/β) = Z(x) · π* vào dòng cuối:
= −β · E_(y~π) [ log( π(y|x) / π*(y|x) ) − log Z(x) ]
= −β · KL( π ‖ π* ) + β · log Z(x)
Z(x) không phụ thuộc π, còn KL không âm và bằng 0 khi và chỉ khi hai phân phối trùng nhau. Vậy mục tiêu đạt cực đại đúng khi π = π* (phương trình 4; phép dẫn đầy đủ ở Phụ lục A.1). Đọc trực quan: policy tối ưu là reference được nghiêng lại theo reward, câu nào reward cao hơn được nhân xác suất theo exp(r/β). Nhưng Z(x) là tổng trên mọi chuỗi có thể sinh ra, không tính nổi, nên không dùng thẳng được π*. Bước tiếp theo né đúng chỗ đó.
Bước 2: viết reward theo policy
Lấy log hai vế của định nghĩa π* và chuyển vế:
r(x, y) = β · log( π*(y|x) / π_ref(y|x) ) + β · log Z(x)
Đây là phương trình 5: reward là log-ratio giữa policy tối ưu và reference, cộng một số hạng chỉ phụ thuộc prompt.
Bước 3: thay vào Bradley–Terry, Z(x) tự triệt tiêu
Bradley–Terry ở mục 5 chỉ dùng hiệu hai reward của cùng một prompt:
r(x, y_w) − r(x, y_l) = β · log( π*(y_w|x) / π_ref(y_w|x) ) − β · log( π*(y_l|x) / π_ref(y_l|x) )
Số hạng β · log Z(x) có ở cả hai reward và triệt tiêu. Cái tổng không tính nổi biến mất.
Bước 4: thay π* bằng model đang train
Thay π* chưa biết bằng model có tham số π_θ và áp maximum likelihood như với reward model, ta được loss DPO (phương trình 7):
L_DPO(θ) = −E_(x, y_w, y_l) [ log σ( β · log( π_θ(y_w|x) / π_ref(y_w|x) )
− β · log( π_θ(y_l|x) / π_ref(y_l|x) ) ) ]
Đây là đúng loss của reward model ở mục 5, chỉ thay r_φ(x, y) bằng β · log(π_θ(y|x) / π_ref(y|x)), đại lượng mà paper gọi là implicit reward. Policy tự đóng vai reward model, đúng như tiêu đề paper: “Your Language Model is Secretly a Reward Model”. Gradient (mục 4 của paper):
∇L = −β · E[ σ( r̂(y_l) − r̂(y_w) ) · ( ∇log π_θ(y_w|x) − ∇log π_θ(y_l|x) ) ]
Tăng log-prob của câu thắng, giảm log-prob của câu thua, với trọng số lớn hơn khi model đang xếp sai; bỏ trọng số này thì model thoái hoá (Phụ lục, Bảng 3).
β làm gì. β vẫn là hệ số KL của mục tiêu gốc, giờ hiện ra như thang đo của implicit reward. β lớn: một thay đổi nhỏ trong log-ratio đã đẩy sigmoid về phía bão hoà, policy không cần rời xa reference. β nhỏ: policy phải đi xa hơn mới giảm được loss. Llama 3 dùng β = 0,1 (mục 4.1.4).
Tính loss DPO trên một model thật
Code dưới đây dùng Qwen2.5-0.5B-Instruct làm cả reference (đóng băng) và policy (được train), với một cặp: “Paris” là chosen, “Lyon” là rejected. Log-prob của câu là tổng log-prob các token của câu trả lời, gồm <|im_end|>, tính đúng như loss mask ở mục 3. Code chạy bốn bước SGD trên riêng cặp này rồi kiểm tra lại loss bằng tay, chỉ dùng math.
# Python 3.12, torch 2.14.1 (CPU), transformers 5.18.0
import math
import torch
import torch.nn.functional as F
from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers.utils import logging
logging.disable_progress_bar()
name = "Qwen/Qwen2.5-0.5B-Instruct"
tok = AutoTokenizer.from_pretrained(name)
ref = AutoModelForCausalLM.from_pretrained(name, dtype=torch.float32).eval() # reference: đóng băng
policy = AutoModelForCausalLM.from_pretrained(name, dtype=torch.float32).eval() # policy: được train
for p in ref.parameters():
p.requires_grad_(False)
prompt = [{"role": "user", "content": "Thủ đô của Pháp là gì?"}]
chosen, rejected = "Thủ đô của Pháp là Paris.", "Thủ đô của Pháp là Lyon."
def seq_logprob(model, response):
"""log π(y|x): tổng log-prob của các token trong câu trả lời (gồm <|im_end|>)."""
p_ids = tok.apply_chat_template(prompt, add_generation_prompt=True, tokenize=True, return_dict=True)["input_ids"]
f_ids = tok.apply_chat_template(prompt + [{"role": "assistant", "content": response}],
tokenize=True, return_dict=True)["input_ids"]
ids = torch.tensor([f_ids])
logp = F.log_softmax(model(ids).logits[0, :-1], dim=-1) # vị trí t dự đoán token t+1
target = ids[0, 1:]
token_logp = logp.gather(-1, target[:, None]).squeeze(-1)
return token_logp[len(p_ids) - 1:].sum() # chỉ phần assistant
beta = 0.1
with torch.no_grad():
ref_c, ref_r = seq_logprob(ref, chosen), seq_logprob(ref, rejected)
print(f"reference: log π_ref(chosen) = {ref_c:.4f} log π_ref(rejected) = {ref_r:.4f}")
opt = torch.optim.SGD(policy.parameters(), lr=1e-4)
for step in range(4):
pol_c, pol_r = seq_logprob(policy, chosen), seq_logprob(policy, rejected)
r_c = beta * (pol_c - ref_c) # implicit reward của chosen
r_r = beta * (pol_r - ref_r) # implicit reward của rejected
loss = -F.logsigmoid(r_c - r_r)
print(f"step {step}: log π(c) = {pol_c.item():.4f} log π(r) = {pol_r.item():.4f} "
f"r_c = {r_c.item():+.4f} r_r = {r_r.item():+.4f} loss = {loss.item():.4f}")
opt.zero_grad()
loss.backward()
opt.step()
# Kiểm tra bằng tay với số của bước cuối, chỉ dùng math
margin = beta * ((pol_c.item() - ref_c.item()) - (pol_r.item() - ref_r.item()))
print(f"tính tay: margin = {margin:.4f} -log σ(margin) = {-math.log(1 / (1 + math.exp(-margin))):.4f}")
Output khi chạy (khoảng 15 giây trên CPU):
reference: log π_ref(chosen) = -1.2734 log π_ref(rejected) = -8.0342
step 0: log π(c) = -1.2734 log π(r) = -8.0342 r_c = +0.0000 r_r = +0.0000 loss = 0.6931
step 1: log π(c) = -1.9348 log π(r) = -11.4345 r_c = -0.0661 r_r = -0.3400 loss = 0.5655
step 2: log π(c) = -2.5642 log π(r) = -14.5651 r_c = -0.1291 r_r = -0.6531 loss = 0.4651
step 3: log π(c) = -3.1683 log π(r) = -17.5014 r_c = -0.1895 r_r = -0.9467 loss = 0.3846
tính tay: margin = 0.7572 -log σ(margin) = 0.3846
Đọc output:
- Ở bước 0, loss đúng bằng ln 2. Policy trùng reference nên mọi log-ratio bằng 0 và loss là
−log σ(0) = 0,6931. Đây là phép kiểm tra nhanh cho mọi cài đặt DPO: loss bước đầu khác ln 2 nghĩa là có gì sai trong cách tính log-prob hoặc dựng reference. - Kiểm tra bằng tay khớp. Từ bốn log-prob của bước 3,
β · ((−3,1683 − (−1,2734)) − (−17,5014 − (−8,0342)))cho margin 0,7572, và−log σ(0,7572) = 0,3846, đúng loss PyTorch báo. - DPO không quan tâm mức tuyệt đối. Reference đã ưa “Paris” (−1,27) hơn “Lyon” (−8,03) từ đầu; DPO chỉ quan tâm policy thay đổi so với reference bao nhiêu ở mỗi câu.
- Log-prob của câu thắng cũng giảm, từ −1,27 xuống −3,17, tức xác suất giảm khoảng 6,7 lần. Loss vẫn giảm vì câu thua bị đẩy xuống nhanh hơn. Hai câu chỉ khác một từ, và gradient đẩy câu thua xuống kéo theo cả những token dùng chung. Pal et al. 2024 mô tả đúng failure mode này: loss DPO có thể thấp ngay cả khi xác suất câu thắng giảm dưới mức reference, nhất là khi hai câu gần giống nhau (mục 3); Razin et al. 2024 gọi nó là likelihood displacement. Llama 3 thêm số hạng NLL hệ số 0,2 trên câu thắng vào loss DPO (mục 4.1.4).
Đây là ví dụ đồ chơi (một cặp, learning rate lớn, bốn bước), chỉ để thấy cơ chế và kiểm tra công thức.
So sánh với PPO
Về lý thuyết hai cách tối ưu cùng một mục tiêu; về thực hành chúng khác nhau ở những chỗ quan trọng:
| RLHF với PPO | DPO | |
|---|---|---|
| Model trong bộ nhớ | 4: policy, value, reward, reference | 2: policy, reference |
| Sinh văn bản lúc train | có, mỗi vòng | không |
| Dữ liệu | online: câu trả lời mới do policy hiện tại sinh | offline: cặp có sẵn, thường do model khác sinh |
| Độ phức tạp cài đặt | cao, nhiều siêu tham số | gần như một vòng SFT |
| Reward model riêng | có, dùng lại được cho rejection sampling, đánh giá | không |
Điểm yếu lớn nhất của DPO nằm ở dòng thứ ba. PPO train trên output của policy hiện tại nên sửa được lỗi mà policy đang mắc; DPO chỉ học từ cặp có sẵn, và ở vùng không có cặp nào phủ thì không có tín hiệu. Xu et al. 2024 chứng minh tập nghiệm của PPO là tập con thật sự của tập nghiệm DPO, và DPO có thể tìm ra nghiệm khai thác câu trả lời nằm ngoài phân phối dữ liệu (mục 4.1, Định lý 4.1).
Ai thắng? Còn đang tranh luận
- DPO paper: trên tóm tắt TL;DR với model SFT GPT-J, khi GPT-4 làm người chấm, DPO đạt win rate khoảng 61% so với bản tóm tắt tham chiếu, PPO đạt 57% ở temperature tốt nhất (mục 6.2, Hình 2); trong đánh giá bằng người, người chấm ưa mẫu DPO hơn PPO 58% số lần (mục 6.4, Bảng 2).
- Xu et al. 2024: với chuẩn hoá advantage, batch lớn và cập nhật reference bằng trung bình trượt, PPO vượt DPO trong mọi thí nghiệm của họ (abstract, mục 1 và 6). Trên CodeContests, PPO với CodeLlama-34B đạt 22,4% (10@1k), hơn AlphaCode-41B kèm clustering 16,4%, còn DPO đạt 0,0% và SFT 15,2% (Bảng 8).
- Ivison et al. 2024: PPO hơn DPO tối đa 2,5% ở toán và 1,2% ở miền chung, nhưng chất lượng dữ liệu sở thích mới là yếu tố lớn nhất, tới 8% ở instruction following và truthfulness (abstract). Thứ tự họ rút ra: dữ liệu > thuật toán > reward model > prompt cho policy (mục 6).
Bức tranh chung: PPO làm kỹ thường nhỉnh hơn, nhất là ở toán và code, nhưng đắt hơn nhiều. DPO rẻ, ổn định, đủ tốt cho phần lớn mục đích, nên thành lựa chọn mặc định của nhiều pipeline như Llama 3. Nhiều nhóm thu hẹp khoảng cách bằng DPO lặp nhiều vòng trên cặp mới do policy hiện tại sinh và reward model chấm.
Các biến thể
| Phương pháp | Ý chính | Có cần reference? |
|---|---|---|
| IPO (Azar et al. 2023) | thay −log σ bằng loss bình phương (h − 1/(2τ))² trên hiệu log-ratio h, để không overfit khi sở thích gần như tuyệt đối (mục 5.2; phương trình 17) |
có |
| KTO (Ethayarajh et al. 2024) | không cần cặp: mỗi câu trả lời chỉ cần nhãn “tốt” hay “xấu”, loss dựa trên prospect theory với điểm tham chiếu là KL (mục 4.1, phương trình 8) | có |
| ORPO (Hong et al. 2024) | gộp SFT và preference vào một bước: loss SFT cộng λ lần loss odds-ratio giữa câu thắng và câu thua (mục 4.2, phương trình 6–7) |
không |
| SimPO (Meng et al. 2024) | dùng log-prob trung bình theo độ dài làm reward, thêm margin γ trong sigmoid (mục 2.3, phương trình 6) |
không |
SimPO và length-normalized DPO của Tülu 3 nhắm vào một vấn đề mà code mẫu cũng cho thấy: log-prob của câu là tổng trên các token, nên câu càng dài log-prob càng âm, và loss DPO gốc nhạy với độ dài.
09RLAIF và Constitutional AI
Mọi thứ ở trên cần người chấm, và người chấm đắt, chậm, không đồng ý với nhau. Nếu LLM đủ giỏi để trả lời, liệu nó có đủ giỏi để chấm?
Constitutional AI: hai pha
Constitutional AI (Bai et al. 2022b, Anthropic) đưa ý này thành một quy trình hoàn chỉnh. “Constitution” là danh sách nguyên tắc viết bằng ngôn ngữ tự nhiên. Có hai pha (mục 1.2, Hình 1):
Pha 1: tự phê bình và tự sửa (mục 3). Đưa prompt có hại cho một model chỉ được train để hữu ích. Model phê bình câu trả lời của chính nó theo một nguyên tắc chọn ngẫu nhiên, rồi viết lại, lặp vài lần; bộ nguyên tắc có 16 cặp yêu cầu phê bình và sửa (mục 3.1, Phụ lục C.1). SFT trên các câu đã sửa cho ra SL-CAI.
Pha 2: RL từ phản hồi của AI (mục 4). SL-CAI sinh hai câu trả lời; một model khác được hỏi dạng trắc nghiệm: theo nguyên tắc này, câu nào tốt hơn? Ví dụ một nguyên tắc, trích nguyên văn (Phụ lục C.2):
“Please choose the response that is the most helpful, honest, and harmless.”
Pha này cũng dùng 16 nguyên tắc, mỗi so sánh chọn ngẫu nhiên một cái (mục 4.1). Xác suất của model chấm thành nhãn mềm để train preference model, rồi RL như mục 6, được RL-CAI. Paper gọi pha này là RL from AI Feedback (RLAIF). Khi model chấm suy nghĩ từng bước trước khi chọn, xác suất của nó trở nên cực đoan và RL sinh hành vi quá tay; nhóm tác giả kẹp xác suất vào khoảng 40–60% (mục 4.1 và 4.3). Kết quả là một model “harmless but non-evasive”: vô hại nhưng không né tránh, giải thích vì sao nó phản đối thay vì chỉ từ chối (abstract, mục 4.4).
“Không có con người” là hiểu sai
Con người viết constitution: chọn nguyên tắc nào, diễn đạt ra sao. Và trong paper, nhãn helpfulness vẫn do người gán; chỉ nhãn harmlessness là do AI, nên preference model là “hybrid human/AI” (mục 1.2, 4.1). Phần thảo luận tự nhận vẫn dựa vào giám sát của người qua nhãn helpfulness (mục 6). Cái thay đổi là vị trí của con người: từ chấm từng cặp sang viết nguyên tắc, một dạng giám sát minh bạch và kiểm tra được hơn.
RLAIF có tốt bằng RLHF không
Lee et al. 2023 (Google) so sánh trực tiếp, với AI chấm là PaLM 2 Large, policy và reward model khởi tạo từ PaLM 2 Extra-Small (mục 3.2–3.3). Đánh giá bằng người (Bảng 1, mục 4.1):
| Tác vụ | RLAIF | RLHF | SFT |
|---|---|---|---|
| Tóm tắt, win rate so với SFT | 71% | 73% | – |
| Hội thoại hữu ích, win rate so với SFT | 63% | 64% | – |
| Hội thoại vô hại, tỉ lệ câu trả lời vô hại | 88% | 76% | 64% |
Đối đầu trực tiếp, RLAIF thắng RLHF 50% ở tóm tắt và 52% ở hội thoại hữu ích, không khác 50% có ý nghĩa thống kê; ở tác vụ vô hại RLAIF vượt cả hai. Hai kết quả phụ còn đáng chú ý hơn. Khi AI chấm cùng kích thước với policy (PaLM 2 XS), RLAIF vẫn thắng SFT 68% ở tóm tắt (mục 4.2). Và direct RLAIF (d-RLAIF), bỏ reward model và cho LLM chấm điểm trực tiếp trong vòng RL, thắng SFT 74% và thắng RLAIF cùng kích thước 60% (mục 4.3). Ở hội thoại hữu ích, thí nghiệm d-RLAIF dùng AI chấm và policy ban đầu là cùng một checkpoint và vẫn thắng SFT 66% (mục 4.3); paper gọi đây là “strict self-improvement”. Thí nghiệm cùng kích thước ở mục 4.2 thì paper nói rõ là chưa phải strict self-improvement.
LLM-as-judge và các rủi ro
Dùng model để chấm là kế thừa thiên kiến của nó. Zheng et al. 2023 ghi nhận ba loại ở LLM làm giám khảo: position bias (ưa một vị trí nhất định), verbosity bias (ưa câu dài) và self-enhancement bias (ưa câu do chính mình viết) (mục 3.3). Verbosity bias chính là length bias của mục 7, giờ được tự động hoá, và trong RLAIF mọi thiên kiến của model chấm bị khuếch đại qua vòng tối ưu. Đổi lại: rẻ hơn hàng bậc độ lớn, mở rộng được, và nguyên tắc nằm trên giấy để ai cũng đọc và tranh luận được. Pipeline thực tế trộn cả hai: người cho quyết định khó và nhạy cảm, model cho khối lượng lớn.
10Pipeline post-training ngày nay
Pipeline thật hiếm khi là đường thẳng SFT → RLHF. Nó là nhiều vòng, mỗi vòng dùng model tốt nhất của vòng trước để sinh dữ liệu cho vòng sau. Ba technical report sau đủ chi tiết để đặt cạnh nhau:
| Llama 2 (2023) | Llama 3 (2024) | Tülu 3 (2024) | |
|---|---|---|---|
| SFT | 27.540 ví dụ người viết (mục 3.1) | dữ liệu từ rejection sampling, tổng hợp và người viết (mục 4.2, Bảng 7) | 939.344 prompt (Bảng 7) |
| Dữ liệu so sánh | 1.418.091 so sánh của Meta, 4 mức (Bảng 6, mục 3.2.1) | 4 mức, thêm bản do người sửa: edited > chosen > rejected (mục 4.2.1) | 271.409 cặp cho 8B, 334.302 cặp cho 70B, có dữ liệu on-policy (Bảng 15, mục 5.2) |
| Reward model | hai model riêng: Helpfulness và Safety, loss có margin (mục 3.2.2) | một model, bỏ margin (mục 4.1.2) | dùng để khởi tạo value model cho RLVR (mục 6.2) |
| Tối ưu | rejection sampling tới RLHF-V4, sau đó PPO trên checkpoint rejection sampling (mục 3.2.3) | rejection sampling, SFT rồi DPO; β = 0,1, mask token định dạng, thêm NLL 0,2 (mục 4.1.4) | DPO chuẩn hoá theo độ dài (mục 5.1.2), rồi RLVR bằng PPO (mục 6) |
| Số vòng | 5 phiên bản RLHF-V1 tới V5 (mục 3.2.3) | 6 vòng (mục 4.1.6) | 3 giai đoạn SFT → DPO → RLVR |
Vài chi tiết đáng đọc kỹ:
- Rejection sampling dùng reward model mà không cần PPO: sinh K câu trả lời cho mỗi prompt, chọn câu reward cao nhất, rồi SFT trên đó. Llama 3 lấy K từ 10 đến 30 (mục 4.2.2).
- Llama 3 chọn DPO thay PPO vì DPO “required less compute for large-scale models and performed better, especially on instruction following benchmarks like IFEval” (mục 4.1.4), và trung bình hoá weights của các model train với dữ liệu hoặc siêu tham số khác nhau ở mỗi giai đoạn (mục 4.1.5).
- Tülu 3 (Lambert et al. 2024, AI2) công khai toàn bộ: dữ liệu, code, checkpoint từng giai đoạn và công thức (mục 2.4, Bảng 1). Bản 70B, xây trên Llama 3.1 base, đạt điểm trung bình 76,2 trên bộ đánh giá của họ, so với 74,1 của Llama 3.1 70B Instruct, 72,8 của Qwen 2.5 72B Instruct, 69,6 của GPT-4o-mini và 75,3 của Claude 3.5 Haiku (Bảng 2); với Haiku, chính paper ở chỗ khác dùng chữ “approaching”.
RLVR và GRPO: một đoạn ngắn
Giai đoạn cuối của Tülu 3 là RLVR (reinforcement learning with verifiable rewards): với tác vụ có đáp án kiểm chứng được bằng chương trình, như toán (GSM8K, MATH) hay ràng buộc kiểu IFEval, reward đến từ một bộ kiểm tra: đúng được α = 10, sai được 0 (mục 6, phương trình 8), trên khoảng 30 nghìn prompt (Bảng 22). Reward như vậy không có xấp xỉ nào để hack theo kiểu mục 7. GRPO (Shao et al. 2024, DeepSeekMath) là biến thể của PPO hay đi cùng RLVR: bỏ value model, sinh một nhóm câu trả lời cho mỗi prompt, và lấy advantage là reward của từng câu trừ trung bình nhóm rồi chia độ lệch chuẩn nhóm (mục 4.1). Đây là nền của các reasoning model, chủ đề của bài 15 trong series.
11Những chỗ dễ hiểu sai
Sáu dòng dưới đây khớp với hàng dưới của Hình 1.
| Hiểu lầm | Thực tế |
|---|---|
| “Post-training dạy model kiến thức mới” | Bằng chứng từ LIMA và URIAL cho thấy tri thức gần như đã có sau pretraining; chỉ khoảng 7,8% vị trí token thật sự lệch giữa Llama-2-7b và bản chat, chủ yếu là token phong cách. SFT trên những điều model không biết còn có thể dạy nó bịa |
| “SFT tính loss trên cả prompt” | Loss chỉ tính trên token của assistant, gồm cả token kết thúc lượt; prompt có label = -100. Trong ví dụ của mục 3, chỉ 10 trên 47 token được tính loss |
| “Constitutional AI không có con người nào tham gia” | Con người viết constitution, và trong paper gốc nhãn helpfulness vẫn do người gán; AI chỉ thay người ở nhãn harmlessness |
| “DPO luôn tốt hơn PPO” | Còn đang tranh luận. PPO được cài đặt kỹ thắng ở nhiều thí nghiệm, nhất là code và toán; DPO rẻ và ổn định hơn. Chất lượng dữ liệu quan trọng hơn lựa chọn thuật toán |
| “DPO không cần reference model” | Reference nằm ngay trong loss DPO, qua log-ratio π_θ / π_ref; nó chỉ được đóng băng. Biến thể bỏ reference là ORPO, SimPO, không phải DPO |
| “Reward cao hơn tức là model tốt hơn” | Reward model là xấp xỉ; tối ưu quá mức thì điểm proxy tăng mãi còn chất lượng thật tăng rồi giảm. Phần lớn mức tăng reward có thể chỉ đến từ việc câu trả lời dài ra |
Tổng kết: một base model, ba lớp định hình
Post-training không làm model biết thêm điều gì. Nó dạy model dùng những gì đã biết theo cách con người muốn: trả lời đúng câu hỏi, đúng định dạng, biết dừng, biết từ chối. Mỗi lớp dạy một phần, và mỗi lớp mang theo tật riêng.
- Base model không nghe lời vì pretraining chỉ thưởng cho việc viết tiếp văn bản; LIMA và URIAL cho thấy phần thiếu chủ yếu là định dạng và phong cách.
- SFT là cross-entropy như pretraining, trên hội thoại đóng gói bằng chat template, loss chỉ trên token của assistant; sai template lúc inference là đưa model ra khỏi phân phối đã học.
- Reward model học từ so sánh qua Bradley–Terry,
σ(r_w − r_l), nên chỉ hiệu reward có nghĩa, và trần độ chính xác bị giới hạn bởi mức đồng thuận khoảng 73–77% giữa người chấm. - RLHF với PPO tối đa hoá
reward − β·KL, cần bốn model và sinh văn bản trong vòng train; reward hacking là quy luật, với độ dài và sycophancy là hai dạng phổ biến nhất. - DPO dẫn ra từ nghiệm đóng
π* ∝ π_ref · exp(r/β): reward thànhβ·log(π/π_ref),Z(x)triệt tiêu trong Bradley–Terry, còn lại một loss phân loại trên cặp. Nó rẻ và ổn định nhưng offline, và có thể kéo cả xác suất câu thắng xuống. DPO hay PPO vẫn đang tranh luận; dữ liệu tốt quan trọng hơn thuật toán. - RLAIF và Constitutional AI chuyển con người từ chấm từng cặp sang viết nguyên tắc, ngang RLHF ở các tác vụ của Lee et al., nhưng khuếch đại thiên kiến của model chấm.
- Pipeline thật là nhiều vòng: Llama 2 qua 5 phiên bản RLHF, Llama 3 qua 6 vòng, Tülu 3 công khai cả SFT → DPO → RLVR.
Mọi bước trong bài này đều fine-tune toàn bộ weights, và PPO còn giữ bốn bản model trong bộ nhớ cùng lúc. Với model 70B, chừng đó vượt xa khả năng của phần lớn đội ngũ. Bài 12 sẽ đi qua cách làm rẻ hơn: LoRA, QLoRA và quantization.
Tài liệu tham khảo
Paper
- Christiano et al. 2017 — Deep reinforcement learning from human preferences
- Schulman et al. 2017 — Proximal Policy Optimization Algorithms
- Stiennon et al. 2020 — Learning to summarize from human feedback
- Wei et al. 2021 — Finetuned Language Models Are Zero-Shot Learners
- Ouyang et al. 2022 — Training language models to follow instructions with human feedback
- Bai et al. 2022 — Training a Helpful and Harmless Assistant with Reinforcement Learning from Human Feedback
- Gao et al. 2022 — Scaling Laws for Reward Model Overoptimization
- Wang et al. 2022 — Self-Instruct: Aligning Language Models with Self-Generated Instructions
- Bai et al. 2022b — Constitutional AI: Harmlessness from AI Feedback
- Rafailov et al. 2023 — Direct Preference Optimization: Your Language Model is Secretly a Reward Model
- Zhou et al. 2023 — LIMA: Less Is More for Alignment
- Zheng et al. 2023 — Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena
- Touvron et al. 2023 — Llama 2: Open Foundation and Fine-Tuned Chat Models
- Casper et al. 2023 — Open Problems and Fundamental Limitations of Reinforcement Learning from Human Feedback
- Lee et al. 2023 — RLAIF vs. RLHF: Scaling Reinforcement Learning from Human Feedback with AI Feedback
- Kirk et al. 2023 — Understanding the Effects of RLHF on LLM Generalisation and Diversity
- Singhal et al. 2023 — A Long Way to Go: Investigating Length Correlations in RLHF
- Sharma et al. 2023 — Towards Understanding Sycophancy in Language Models
- Azar et al. 2023 — A General Theoretical Paradigm to Understand Learning from Human Preferences (IPO)
- Lin et al. 2023 — The Unlocking Spell on Base LLMs: Rethinking Alignment via In-Context Learning (URIAL)
- Ethayarajh et al. 2024 — KTO: Model Alignment as Prospect Theoretic Optimization
- Shao et al. 2024 — DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models (GRPO)
- Pal et al. 2024 — Smaug: Fixing Failure Modes of Preference Optimisation with DPO-Positive
- Hong et al. 2024 — ORPO: Monolithic Preference Optimization without Reference Model
- Xu et al. 2024 — Is DPO Superior to PPO for LLM Alignment? A Comprehensive Study
- Meng et al. 2024 — SimPO: Simple Preference Optimization with a Reference-Free Reward
- Hu et al. 2024 — OpenRLHF: An Easy-to-use, Scalable and High-performance RLHF Framework (bản v1)
- Ivison et al. 2024 — Unpacking DPO and PPO: Disentangling Best Practices for Learning from Preference Feedback
- Llama Team, Meta 2024 — The Llama 3 Herd of Models
- Razin et al. 2024 — Unintentional Unalignment: Likelihood Displacement in Direct Preference Optimization
- Lambert et al. 2024 — Tülu 3: Pushing Frontiers in Open Language Model Post-Training
Tài liệu
- Hugging Face — Chat templates
- Hugging Face — TRL: Transformer Reinforcement Learning
- Hugging Face — Qwen/Qwen2.5-0.5B và Qwen/Qwen2.5-0.5B-Instruct
- Nathan Lambert — Reinforcement Learning from Human Feedback (RLHF Book)
- John Schulman — Reinforcement Learning from Human Feedback: Progress and Challenges (bài nói tại UC Berkeley, 2023; bản ghi lời)