Mục lục bài
Khi nào nên fine-tune, khi nào dùng RAG
LoRA huấn luyện một phần nhỏ trọng số bổ sung (adapter) thay vì toàn bộ mô hình. QLoRA nạp mô hình gốc ở dạng 4-bit để tiết kiệm VRAM, adapter vẫn huấn luyện ở độ chính xác cao hơn.
Các bước thực hiện
Tiến độ chỉ lưu trên trình duyệt này.
Bước 1: Chuẩn bị dữ liệu hội thoại dạng JSONL
Mỗi dòng là một hội thoại với trường
messages. Đây là định dạng TRL và nhiều công cụ khác đọc trực tiếp, và sẽ được áp chat template của mô hình khi huấn luyện.data/raw.jsonl (mỗi dòng một object) - Câu trả lời mẫu phải là câu trả lời bạn MUỐN mô hình học — dữ liệu kém chất lượng cho ra mô hình kém.
- Giữ system prompt thống nhất với lúc triển khai.
- Loại bỏ thông tin cá nhân, mật khẩu, số hợp đồng… trước khi đưa vào huấn luyện (xem bài bảo mật dữ liệu AI).
Bước 2: Làm sạch dữ liệu tiếng Việt và tách train/eval
Văn bản tiếng Việt chép từ nhiều nguồn hay lẫn hai kiểu mã hoá dấu (Unicode dựng sẵn NFC và tổ hợp NFD). Nhìn giống nhau nhưng tokenizer coi là khác nhau — chuẩn hoá về NFC trước tiên.
prepare_data.py Mẹo: Tỷ lệ tách eval 5% là điểm khởi đầu. Với dữ liệu ít, hãy tự chọn tay một bộ eval đại diện các loại câu hỏi quan trọng và không để trùng nội dung với tập train.
Bước 3: Viết script fine-tune QLoRA với TRL
Ví dụ dùng một mô hình instruct cỡ nhỏ-trung. Thay
MODEL_IDbằng mô hình bạn chọn (xem danh sách mô hình) và đọc giấy phép trên model card trước khi dùng thương mại.train_sft.py Cảnh báo: Tên tham số của TRL/transformers thay đổi giữa các bản (ví dụ
max_lengthtừng làmax_seq_length,dtypetừng làtorch_dtype;assistant_only_losscần chat template hỗ trợ). Nếu gặp lỗi tham số lạ, đối chiếu tài liệu đúng phiên bản bạn đang cài.Bước 4: Hiểu và chỉnh các tham số chính
Bước 5: Chạy huấn luyện và theo dõi loss
Bash Theo dõi
lossvàeval_losstrong log. Loss train giảm mà eval_loss tăng là quá khớp: giảm epoch, giảm learning rate hoặc bổ sung dữ liệu. Hết VRAM: giảmper_device_train_batch_size, giảmmax_length, bật gradient checkpointing.Bước 6: Đánh giá: so sánh với mô hình gốc
Eval loss chưa đủ để kết luận. Chuẩn bị bộ câu hỏi thật từ người dùng nghiệp vụ (không nằm trong tập train), sinh câu trả lời từ mô hình gốc và mô hình đã fine-tune, rồi cho người có chuyên môn chấm mù.
compare.py Muốn đo trên benchmark chuẩn, có thể dùng lm-evaluation-harness — nhưng benchmark chung không thay được bộ câu hỏi nghiệp vụ của chính bạn.
Bước 7: Merge adapter vào mô hình gốc
Adapter có thể phục vụ trực tiếp (vLLM hỗ trợ nạp LoRA). Khi cần một mô hình hoàn chỉnh — ví dụ để xuất GGUF — hãy merge trên mô hình gốc ở BF16/FP16, không merge trên bản 4-bit.
merge.py Bước 8: Xuất GGUF bằng llama.cpp
Bash File GGUF chạy được bằng llama.cpp hoặc Ollama (xem bài triển khai suy luận). Lượng tử hoá càng thấp thì file càng nhỏ nhưng chất lượng có thể giảm — đánh giá lại bằng bộ câu hỏi ở bước 6.
Bước 9: Ghi chú: Unsloth, LLaMA-Factory, Axolotl
Dữ liệu JSONL dạng
messagesở bước 1 dùng lại được cho cả ba công cụ (có thể cần khai báo ánh xạ trường trong cấu hình).
Kiểm tra thành công
- Thư mục
out/qwen7b-lora/finalcóadapter_config.jsonvàadapter_model.safetensors. eval_losskhông tăng liên tục ở cuối quá trình huấn luyện.- Trong
compare.jsonl, người chấm nghiệp vụ đánh giá bản fine-tune tốt hơn hoặc ngang bản gốc ở các câu quan trọng — và không làm hỏng các câu hỏi chung. - File GGUF chạy được bằng
llama-clivà trả lời đúng ngôn ngữ, đúng văn phong.
Lỗi thường gặp & cách sửa
CUDA out of memory ngay khi bắt đầu huấn luyện
Nguyên nhân thường gặp: Batch, max_length hoặc mô hình quá lớn so với VRAM.
Giảm per_device_train_batch_size về 1 và tăng gradient_accumulation_steps, giảm max_length, bật gradient_checkpointing, hoặc chọn mô hình nhỏ hơn. Ước lượng lại tại /ai/tinh-cau-hinh.
Mô hình sau fine-tune trả lời lặp, không dừng hoặc sai định dạng hội thoại
Nguyên nhân thường gặp: Chat template lúc huấn luyện và lúc suy luận không khớp, thiếu token kết thúc lượt.
Dùng cùng tokenizer/chat template ở mọi bước (huấn luyện, merge, xuất GGUF, phục vụ). Kiểm tra lại bằng tokenizer.apply_chat_template(..., tokenize=False) để xem chuỗi thực tế.
Loss về gần 0 rất nhanh, mô hình trả lời như chép dữ liệu
Nguyên nhân thường gặp: Dữ liệu ít, trùng lặp nhiều, huấn luyện quá nhiều epoch.
Loại trùng, giảm epoch và learning rate, mở rộng dữ liệu đa dạng hơn, theo dõi eval_loss.
Chữ tiếng Việt bị lỗi dấu trong câu trả lời
Nguyên nhân thường gặp: Dữ liệu lẫn NFC/NFD, hoặc file đọc/ghi không phải UTF-8.
Chuẩn hoá NFC như bước 2, luôn mở file với encoding="utf-8" và ghi JSON với ensure_ascii=False.
Bước tiếp theo
Khi mô hình hoặc dữ liệu vượt quá một GPU.
Nguồn chính chủ
Lệnh, tên gói và tham số thay đổi theo phiên bản. Trước khi chạy trên máy thật, hãy kiểm tra phiên bản mới nhất tại trang chính chủ:
- Hugging Face TRL — SFTTrainer
- Hugging Face PEFT — LoRA
- llama.cpp — GitHub
- Unsloth — Documentation
- LLaMA-Factory — GitHub
- Axolotl — Documentation
Giới hạn của bài
- Bài không khẳng định mô hình nào tốt nhất cho tiếng Việt và không đưa thời gian huấn luyện — phụ thuộc dữ liệu, GPU, tham số.
- Mô hình
Qwen/Qwen2.5-7B-Instructchỉ là ví dụ để script chạy được; giấy phép và sự phù hợp cần tự kiểm tra trên model card. - Bài không đề cập DPO/ORPO, fine-tune toàn phần hay huấn luyện tiếp (continued pre-training).
Kỹ sư HQG khảo sát, lên cấu hình, lắp đặt và bàn giao hạ tầng AI chạy được thật.