Bỏ qua để đến nội dung

🎯 Fine-tuning

Fine-tuning là quá trình tinh chỉnh một pre-trained model trên dataset của riêng bạn để model hoạt động tốt hơn cho use case cụ thể.

📚 Bài viết liên quan:


Tình huống Ví dụ
Cần style/tone đặc biệt Chatbot với giọng điệu công ty
Domain knowledge chuyên sâu Medical, Legal, Financial
Task lặp lại nhiều lần Classify tickets, Extract data
Prompt Engineering không đủ Output vẫn không đúng format
Giảm latency/cost Dùng model nhỏ thay model lớn
Tình huống Lý do Thay thế
Cần cập nhật data thường xuyên Fine-tune tốn thời gian RAG
Muốn model biết thông tin mới Fine-tune không “dạy” facts RAG
Budget/thời gian hạn chế Fine-tune tốn resource Prompt Engineering
Chưa thử các phương pháp khác Có thể không cần fine-tune Few-shot prompting

flowchart TD
START["🤔 Cần customize model?"] --> PE
subgraph PE["1️⃣ Prompt Engineering"]
PE1["✅ Nhanh, dễ, không tốn chi phí<br/>Thử TRƯỚC KHI fine-tune"]
end
PE --> RAG
subgraph RAG["2️⃣ RAG"]
RAG1["✅ Kết hợp data riêng mà không cần train<br/>Dùng cho facts mới"]
end
RAG --> FT
subgraph FT["3️⃣ Fine-tuning"]
FT1["✅ Thay đổi behavior của model<br/>Dùng cho style, format, domain"]
end
style PE fill:#e8f5e9,stroke:#4caf50
style RAG fill:#fff3e0,stroke:#ff9800
style FT fill:#e3f2fd,stroke:#2196f3

Train lại toàn bộ parameters của model.

Pros:
✅ Kết quả tốt nhất
✅ Model adapt hoàn toàn
Cons:
❌ Cần GPU mạnh (nhiều VRAM)
❌ Dễ overfitting
❌ Tốn thời gian
❌ Chi phí cao

Train thêm các adapter layers nhỏ, giữ nguyên model gốc.

Pros:
✅ Tiết kiệm VRAM (giảm ~10x)
✅ Train nhanh hơn
✅ Có thể switch giữa nhiều adapters
✅ Ít overfitting hơn
Cons:
❌ Kết quả có thể kém hơn full fine-tune
❌ Cần tune hyperparameters

Cách hoạt động:

Original weights: W (frozen)
LoRA adapters: A, B (trainable)
Output = W·x + A·B·x
Chỉ train A và B (rất nhỏ so với W)

Kết hợp Quantization (giảm precision) + LoRA.

Pros:
✅ Cực kỳ tiết kiệm VRAM
✅ Fine-tune model 65B trên GPU 24GB
✅ Kết quả gần bằng full fine-tune
Cons:
❌ Chậm hơn 1 chút
❌ Setup phức tạp hơn

OpenAI cung cấp fine-tuning qua API, không cần GPU.

Model Use case Cost (training)
gpt-4o-mini-2024-07-18 Tốc độ, tiết kiệm $3.00/1M tokens
gpt-4o-2024-08-06 Hiệu năng cao $25.00/1M tokens
gpt-3.5-turbo Legacy $8.00/1M tokens

Format JSONL:

{"messages": [{"role": "system", "content": "Bạn là trợ lý lập trình Python."}, {"role": "user", "content": "Viết hàm tính giai thừa"}, {"role": "assistant", "content": "```python\ndef factorial(n: int) -> int:\n if n <= 1:\n return 1\n return n * factorial(n - 1)\n```"}]}
{"messages": [{"role": "system", "content": "Bạn là trợ lý lập trình Python."}, {"role": "user", "content": "Viết hàm tính Fibonacci"}, {"role": "assistant", "content": "```python\ndef fibonacci(n: int) -> int:\n if n <= 1:\n return n\n return fibonacci(n-1) + fibonacci(n-2)\n```"}]}
from openai import OpenAI
client = OpenAI()
# 1. Upload file
file = client.files.create(
file=open("training_data.jsonl", "rb"),
purpose="fine-tune"
)
# 2. Tạo fine-tuning job
job = client.fine_tuning.jobs.create(
training_file=file.id,
model="gpt-4o-mini-2024-07-18",
hyperparameters={
"n_epochs": 3
}
)
# 3. Kiểm tra status
status = client.fine_tuning.jobs.retrieve(job.id)
print(status.status) # "running" → "succeeded"
# 4. Sử dụng fine-tuned model
response = client.chat.completions.create(
model="ft:gpt-4o-mini-2024-07-18:your-org::job-id",
messages=[
{"role": "user", "content": "Viết hàm sort list"}
]
)
  1. Tối thiểu 50-100 examples cho mỗi use case
  2. Đa dạng examples - cover nhiều edge cases
  3. Quality > Quantity - data tốt quan trọng hơn nhiều data
  4. Consistent format - giữ format thống nhất
  5. Test trước với prompting - có thể không cần fine-tune

Dùng Hugging Face Transformers + PEFT (Parameter-Efficient Fine-Tuning).

Terminal window
pip install transformers peft datasets accelerate bitsandbytes
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training
import torch
# 1. Load model với quantization
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b-hf",
load_in_4bit=True,
device_map="auto"
)
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")
# 2. Cấu hình LoRA
lora_config = LoraConfig(
r=16, # Rank của adapter
lora_alpha=32, # Scaling factor
target_modules=["q_proj", "v_proj"], # Layers to adapt
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
# 3. Prepare model
model = prepare_model_for_kbit_training(model)
model = get_peft_model(model, lora_config)
# 4. Training (sử dụng Trainer hoặc custom loop)
# ...
from peft import PeftModel
# Load base model
base_model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b-hf",
load_in_4bit=True
)
# Load adapter
model = PeftModel.from_pretrained(base_model, "path/to/adapter")
# Inference
inputs = tokenizer("Hello, how are you?", return_tensors="pt")
outputs = model.generate(**inputs)
print(tokenizer.decode(outputs[0]))

Tinh chỉnh embedding model cho domain cụ thể.

from sentence_transformers import SentenceTransformer, InputExample, losses
from torch.utils.data import DataLoader
# 1. Load model
model = SentenceTransformer('all-MiniLM-L6-v2')
# 2. Prepare data
train_examples = [
InputExample(texts=["Python tutorial", "Learn Python programming"], label=0.9),
InputExample(texts=["Python tutorial", "Best restaurants nearby"], label=0.1),
]
train_dataloader = DataLoader(train_examples, shuffle=True, batch_size=16)
# 3. Loss function
train_loss = losses.CosineSimilarityLoss(model)
# 4. Training
model.fit(
train_objectives=[(train_dataloader, train_loss)],
epochs=3,
warmup_steps=100
)
# 5. Save
model.save("my-fine-tuned-model")

Task Metrics
Classification Accuracy, F1, Precision, Recall
Generation BLEU, ROUGE, Human eval
Embedding Hit Rate, MRR, NDCG
Chat Human preference, A/B testing
# Chia data: 80% train, 10% validation, 10% test
# KHÔNG dùng test set trong quá trình training
from sklearn.model_selection import train_test_split
train, temp = train_test_split(data, test_size=0.2)
val, test = train_test_split(temp, test_size=0.5)
50% users → Base model
50% users → Fine-tuned model
Đo: Response quality, User satisfaction, Task completion

Dataset: 1000 examples × ~500 tokens/example = 500K tokens
Epochs: 3
Total training tokens: 1.5M
Cost (gpt-4o-mini): 1.5M × $3/1M = $4.50
Cost (gpt-4o): 1.5M × $25/1M = $37.50
+ Inference cost (higher than base model)
GPU rental (A100 80GB): ~$2-3/hour
Training time: 4-8 hours
Total: $8-24
+ Infra costs (hosting, monitoring)

  1. Tạo 50-100 training examples (JSONL format)
  2. Upload và tạo fine-tuning job
  3. So sánh kết quả với base model
  1. Cài đặt environment với PEFT
  2. Fine-tune một small model (Phi-2, Gemma-2B…)
  3. Merge adapter và test inference
  1. Tạo training pairs (similar, dissimilar)
  2. Fine-tune all-MiniLM-L6-v2
  3. So sánh search quality trước/sau

Khái niệm Ý nghĩa
Fine-tuning Train thêm pre-trained model trên data riêng
Full Fine-tuning Train tất cả parameters
LoRA Train adapter nhỏ, giữ nguyên model
QLoRA LoRA + Quantization (tiết kiệm VRAM)
PEFT Thư viện Parameter-Efficient Fine-Tuning
flowchart TD
Q1{"🤔 Cần customize<br/>model behavior?"} -->|NO| PE["✅ Prompt Engineering / RAG"]
Q1 -->|YES| Q2{"💰 Có đủ budget & data?"}
Q2 -->|NO| FS["✅ Few-shot prompting"]
Q2 -->|YES| FT["🎯 Fine-tuning"]
FT --> Q3{"Chọn platform?"}
Q3 --> API["☁️ API (OpenAI)<br/>Không cần GPU"]
Q3 --> OS["🖥️ Open Source<br/>LoRA/QLoRA"]
style Q1 fill:#e3f2fd,stroke:#1976d2
style Q2 fill:#fff3e0,stroke:#ff9800
style FT fill:#f3e5f5,stroke:#9c27b0
style PE fill:#e8f5e9,stroke:#4caf50
style FS fill:#e8f5e9,stroke:#4caf50

Bài tiếp theo: Quay lại RAG để xem cách kết hợp các kỹ thuật.