Relieq/lab21-2A202601055-qwen35-triage-vi
lab21-2A202601055 — Qwen3.5-2B LoRA, phân loại ticket CSKH tiếng Việt
Adapter LoRA cho `Qwen/Qwen3.5-2B`, huấn luyện để chuyển ticket chăm sóc khách hàng tiếng Việt thành JSON triage 4 trường: intent, urgency, product, sentiment.
Đây là bài nộp Lab 21 — Fine-tuning LLMs (Track 3), AICB-P2T3 Ngày 21. Hoàng Văn Nhân · MSSV 2A202601055.
Report đầy đủ + toàn bộ artefact: https://github.com/HVNhan-Relieq/lab21-2A202601055 Trong repo này, bản report nằm ở submission/REPORT.md và số liệu thô ở results/.
Đọ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ệ.
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))
# {"intent": "doi_tra", "urgency": "trung_binh", "product": "balo laptop", "sentiment": "trung_tinh"}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
Cấu hình huấn luyện
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.
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ụ.
correctcó loss thấp nhất nhưngqloramớ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ụcMọ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.
urgencylà 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á.
