Đọc phần này trước khi dùng
Adapter đạt 0.995 trên tác vụ đích, nhưng nó trượt cổng hồi quy của lab và tôi
không khuyến nghị deploy nó như một model đa dụng. Lý do nằm ngay bên dưới, và nó là
kết quả đáng giá nhất của bài lab này chứ không phải một lời cảnh báo lấy lệ.
Table with columns: Nhóm, (a) base + prompt ngây thơ, (b) base + prompt tối ưu, (c) adapter này| Nhóm | (a) base + prompt ngây thơ | (b) base + prompt tối ưu | (c) adapter này |
|---|
| target (độ chính xác 4 trường) | 0.000 | 0.585 | 0.995 |
| regression (15 câu kiến thức phổ thông) | 0.644 | 0.644 | 0.067 |
| format (JSON hợp lệ, đủ 4 khoá) | 0.000 | 1.000 | 1.000 |
| latency (ms/mẫu, greedy) | 1759.8 | 488.2 | 804.7 |
target Δ = +0.410 so với baseline (b) · regression Δ = -0.578 (dung sai 0.020)
→ VERDICT: FAILED
Sau 58 optimizer step chỉ nhìn thấy khuôn ticket→JSON, model mất khả năng chọn định
dạng trả lời. Hỏi "Thủ đô của Việt Nam là thành phố nào?" nó đáp:
{"intent": "hoi_thong_tin", "urgency": "trung_binh", "product": "...", "sentiment": "..."}
14/15 câu regression sụp theo đúng kiểu đó — cú pháp hoàn hảo, nội dung vô nghĩa. Kiến
thức không mất (model vẫn viết đúng "product": "đại dương" khi được hỏi về đại dương);
cái mất là niềm tin rằng có tồn tại một định dạng khác. Đây là quên thảm hoạ dạng sụp
đổ định dạng, không phải suy giảm dần.
Dùng đúng cách: đặt sau một bộ định tuyến chỉ đẩy ticket thật vào. Coi nó là bộ phân
loại chuyên dụng, không phải trợ lý. Cách sửa gốc là trộn 1–5% dữ liệu replay phổ thông
vào tập huấn luyện rồi train lại — chưa làm trong bài nộp này.
Cách dùng
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
BASE = "Qwen/Qwen3.5-2B"
tok = AutoTokenizer.from_pretrained(BASE)
model = AutoModelForCausalLM.from_pretrained(BASE, dtype="bfloat16", device_map="auto")
model = PeftModel.from_pretrained(model, "Relieq/lab21-2A202601055-qwen35-triage-vi")
model.eval()
msgs = [
{"role": "system", "content": "Phân loại ticket sau."},
{"role": "user", "content": "Alo shop, mình đặt balo laptop mã đơn VN411453. "
"Cho tôi trả lại. Đã 3 ngày rồi."},
]
text = tok.apply_chat_template(msgs, tokenize=False, add_generation_prompt=True,
enable_thinking=False)
out = model.generate(**tok(text, return_tensors="pt").to(model.device),
max_new_tokens=160, do_sample=False)
print(tok.decode(out[0][len(tok(text).input_ids):], skip_special_tokens=True))
System prompt lúc suy luận là "Phân loại ticket sau." — đúng prompt đã dùng khi
huấn luyện. Không cần prompt mô tả schema dài dòng nữa: hành vi đã nằm trong trọng số.
Dùng sai prompt so với lúc train là cách nhanh nhất để nhận về điểm 0.000.
Giải mã greedy (do_sample=False) vì đây là tác vụ trích xuất có đáp án đúng.
Schema đầu ra
Table with columns: Trường, Giá trị| Trường | Giá trị |
|---|
intent | doi_tra · van_chuyen · hoan_tien · san_pham_loi · hoi_thong_tin |
urgency | cao · trung_binh · thap |
sentiment | · · |
Cấu hình huấn luyện
Table | |
|---|
| Base | Qwen/Qwen3.5-2B (tier LAPTOP của lab) |
| Dữ liệu | 250 ticket CSKH tiếng Việt → 225 train / 25 val, seed 42 |
| LoRA | r=16 · alpha=32 · dropout 0 · toàn bộ linear của text decoder (12 module) |
| Tham số huấn luyện | 16,819,200 |
| Learning rate | 1e-4 — thang LoRA, ~10× thang full-FT |
| Batch | per-device 1 × grad-accum 8 = 8 hiệu dụng |
| Steps | (2 epoch) · warmup 6 · cosine |
target_modules là linear của text decoder, không phải "all-linear": Qwen3.5 là
model đa phương thức, "all-linear" sẽ gắn adapter cả vào vision tower — to hơn, chậm
hơn, và sai khi merge.
Merge kiểm chứng không tụt điểm: target 0.995 trước merge → 0.995 sau merge (delta 0.000).
Ba cấu hình sai được đo đối chứng
Cả bốn run dùng cùng 58 step, cùng seed, cùng dataset đã token hoá sẵn. Mỗi run chỉ
đổi một biến.
Table with columns: Run, Biến đổi, train loss, target, VRAM| Run | Biến đổi | train loss | target | VRAM |
|---|
correct (adapter này) | — | 0.2951 | 0.995 | 6.75 GB |
attn_only | chỉ gắn q,v · r=322 (khớp ngân sách tham số, lệch 0.018%) | 0.3152 | 0.985 | 6.75 GB |
wrong_lr |
Hai điều đọc được từ bảng này:
- Xếp hạng theo train loss cho ra thứ tự KHÁC xếp hạng theo tác vụ.
correct có
loss thấp nhất nhưng qlora mới có target cao nhất. Chấm bằng chỉ số thay thế là cách
công bố một bảng xếp hạng mà chính số liệu của mình không ủng hộ.
- Sai learning rate một hệ số 10 tệ hơn là không fine-tune.
wrong_lr đạt 0.475,
thấp hơn baseline chỉ-dùng-prompt (0.585) — trong khi đường loss của nó trông hoàn
toàn khoẻ mạnh, chỉ dừng ở sai chỗ.
Còn attn_only (0.985) và qlora (1.000) nằm trong khoảng nhiễu quanh correct (0.995):
chênh lệch 0.005–0.010 tương đương nửa trường trên một ticket trong 50 ticket. Trên tác vụ
này, vị trí adapter và rank đều không phải đòn bẩy — tác vụ bão hoà ở trần trước khi
hai yếu tố đó kịp tạo khác biệt đo được.
Nội dung repo này
adapter_model.safetensors adapter LoRA (64 MB)
adapter_config.json cấu hình PEFT
tokenizer.json, ... tokenizer để load độc lập
results/ toàn bộ số liệu thô — verdict, autopsy, mask proof, runs.csv
submission/REPORT.md report đầy đủ 7 mục
Mọi con số trong model card này đối chiếu được với results/.
Giới hạn
- Corpus 250 mẫu tổng hợp, format hẹp; chưa kiểm chứng trên ticket thật.
- Không dùng cho mục đích đa dụng — xem phần cảnh báo hồi quy ở trên.
urgency là trường yếu nhất: nó là trường duy nhất không suy ra được từ từ khoá bề mặt,
và cũng là trường duy nhất adapter đoán sai trong 50 ticket đánh giá.