Reward function — chấm điểm để model tự khá lên

Thay vì dán nhãn hàng ngàn ví dụ, bạn viết hàm chấm điểm rồi để model tự tìm đường. Hướng dẫn triển khai reward function cho team Việt.

Tuần trước mình ngồi review pipeline fine-tune của một team ở Đà Nẵng. Họ đang dạy model phân loại ticket support tiếng Việt — đã dán nhãn 3.000 mẫu, accuracy kẹt ở tầm 78%. Anh tech lead hỏi: "Dán thêm 3.000 mẫu nữa thì có khá hơn không?" Câu trả lời ngắn gọn: có cách khác hiệu quả hơn — viết một hàm chấm điểm, rồi để model tự mò ra cách đạt điểm cao.

Cách đó gọi là Reinforcement Fine-Tuning (RFT), và thứ quyết định RFT thành hay bại chính là reward function.

SFT đã tốt, nhưng kẹt ở đâu?

Như mình đã chia sẻ trong các bài về fine-tuning trước đây, Supervised Fine-Tuning (SFT) là con đường quen thuộc: bạn cho model xem hàng ngàn cặp input-output mẫu, nó học theo. SFT hoạt động tốt khi task rõ ràng — phân loại, trích xuất entity, format lại văn bản.

Nhưng thực tế production phức tạp hơn vậy. Giả sử bạn cần model trả lời khách hàng vừa chính xác, vừa thân thiện, vừa ngắn gọn. Ba tiêu chí, ba chiều chất lượng. Để SFT xử lý được, bạn phải annotate reasoning path cho từng mẫu — tức là không chỉ gán nhãn đúng/sai mà còn chỉ ra tại sao đúng. Với team 5-7 người, việc này tốn vài tuần chỉ để có đủ data.

RFT đi đường khác: thay vì chỉ cho model đáp án, bạn cho nó biết đáp án đó được bao nhiêu điểm. Model tự thử nhiều cách, nhận phản hồi qua reward function, và dần tối ưu hành vi.

Cơ chế phía sau: chấm điểm thay vì cầm tay

Hiểu nôm na, reward function là một hàm nhận output của model, trả về một con số. Điểm cao nghĩa là output tốt, điểm thấp nghĩa là model cần thử cách khác.

Có hai hướng chính:

RLVR (Reinforcement Learning via Verifiable Rewards) — dùng khi kết quả kiểm chứng được bằng logic. Ví dụ: model sinh SQL, bạn chạy query đó trên database thật, khớp kết quả thì cho điểm cao. Không cần người ngồi chấm.

RLAIF (Reinforcement Learning via AI Feedback) — dùng khi tiêu chí mang tính chủ quan, như giọng văn hay mức độ thân thiện. Một model khác (thường lớn hơn) đóng vai "giám khảo" chấm điểm output.

Điểm hay: bạn có thể kết hợp cả hai trong một reward function đa chiều.

Hai team, hai bài toán

Team fintech tại TP.HCM đang xây text-to-SQL cho hệ thống nội bộ. Database của họ dùng SQL dialect riêng với hàm custom — model nào "out of the box" cũng sinh sai syntax. Thay vì dán nhãn hàng ngàn câu SQL, họ viết reward function theo kiểu RLVR:

def reward_fn(prompt, completion, expected):
    # Check syntax hop le
    if not is_valid_syntax(completion):
        return 0.0
    # Chay query, so ket qua
    actual = execute_query(completion)
    if actual == expected:
        return 1.0
    # Dung mot phan
    return partial_match_score(actual, expected)

Model học được dialect riêng mà team không phải ngồi viết reasoning path cho từng câu query. Chi phí inference trên serverless cũng nhẹ nhàng — nguồn tham khảo ghi nhận một workload mẫu chỉ tốn khoảng 0.80 USD/tháng với 22.000 query khi dùng pay-per-token thay vì host model riêng.

Team e-commerce tại Hà Nội cần chatbot CSKH cân bằng ba yếu tố: đúng thông tin, giọng thân thiện, và trả lời ngắn. Họ thiết kế reward function đa chiều kết hợp RLVR lẫn RLAIF:

def reward_fn(prompt, completion):
    accuracy = verify_facts(completion, knowledge_base)
    tone = judge_model.score_tone(completion)
    brevity = min(1.0, 100 / len(completion.split()))
    return accuracy * 0.5 + tone * 0.3 + brevity * 0.2

Khi muốn chỉnh ưu tiên — ví dụ mùa sale cần trả lời nhanh hơn — chỉ cần sửa trọng số, không cần dán nhãn lại dataset.

Cẩn thận: model biết "chơi gian"

Đây là phần mình muốn nhấn mạnh vì nhiều team vấp phải mà không hiểu tại sao.

Nếu reward function quá đơn giản — chẳng hạn chỉ chấm theo độ dài output — model sẽ học cách viết dài dằng dặc để ăn điểm. Giống như bón quá nhiều đạm cho cây: thân vống lên trông tươi tốt, nhưng không đậu trái gì.

Hiện tượng này gọi là reward hacking. Một ví dụ kinh điển: reward function đo keyword match, model học cách nhét keyword vào output dù câu trả lời vô nghĩa. Log thì thấy điểm cao ngất, deploy ra thì user phàn nàn.

Cách phòng:

Bốn bước thử ngay chiều nay

  1. Chọn một task có thể chấm tự động. Text-to-SQL, code generation, hay extraction với schema cố định là ứng viên lý tưởng vì output kiểm chứng được ngay.
  1. Viết reward function đơn giản trước. Bắt đầu với binary (0 hoặc 1), chạy thử, xem model phản ứng thế nào. Sau đó mới thêm chiều.
  1. Deploy reward function trên serverless. AWS Lambda là một lựa chọn, nhưng bạn dùng Google Cloud Functions hay bất kỳ platform nào cũng được. Quan trọng là reward function phải scale được — trong quá trình training, nó bị gọi hàng ngàn lần.
  1. Monitor reward distribution. Nếu điểm trung bình tăng đều mà variance giảm — tín hiệu tốt. Nếu điểm đột ngột nhảy lên gần tối đa cho mọi output — khả năng cao model đang hack reward.

Nếu bạn muốn self-host toàn bộ thay vì dùng managed service, TRL (Transformer Reinforcement Learning) của Hugging Face là framework mở hỗ trợ RLHF và reward modeling. Kết hợp với Ollama hoặc vLLM mà mình đã nhắc ở các bài trước, bạn có thể chạy pipeline RFT hoàn toàn trên infra nội bộ.

Gieo đúng hạt, model tự lớn

RFT không thay thế SFT — hai cách tiếp cận bổ trợ nhau. SFT dạy model nền tảng, RFT tinh chỉnh hành vi phức tạp. Nhưng điều mình thấy nhiều team Việt Nam đang thiếu là nhận ra rằng không phải lúc nào tốn công dán nhãn thêm cũng là lời giải. Đôi khi, việc bạn cần làm là gieo đúng hạt vào đúng mảnh đất, rồi để hệ thống tự tìm ra cách bén rễ hiệu quả nhất.

Nếu bài trước mình bàn về model tự tiến hóa thì reward function chính là cơ chế thực tế nhất để biến ý tưởng đó thành production code.

---

Bụi Wire — nghiện đọc release notes lúc 2 giờ sáng

Nguồn tham khảo