CoolFace
Modelpublic

hungarmen/lab21-2A202601523-qwen35-triage-vi

sourceHugging Faceapache-2.0updated 1mo agoView on Hugging Face
0likes78downloads
Model Card

lab21-2A202601523 — Qwen3.5-4B LoRA · phân loại ticket CSKH tiếng Việt

Adapter LoRA phân loại ticket chăm sóc khách hàng tiếng Việt thành JSON 4 trường. Bài nộp Lab 21 (AICB-P2T3 · Ngày 21 — Fine-tuning & An Toàn).

Họ tên: Nguyễn Quang Hưng · MSSV: 2A202601523 Repo bài nộp (code + report + results): https://github.com/hungdevcmc/Day21-Track3-Finetuning-Lab

Đọc phần "Phán quyết" trước khi dùng. Adapter này trượt cổng hồi quy của lab: nó thắng rõ trên tác vụ đích nhưng làm tụt năng lực phổ thông của model nền.

Tác vụ

Đầu vào: một ticket CSKH tiếng Việt. Đầu ra: đúng một JSON, đúng 4 khóa, không markdown.

json
{"intent": "doi_tra", "urgency": "trung_binh", "product": "balo laptop", "sentiment": "trung_tinh"}
TrườngTập giá trị
intentdoi_tra · van_chuyen · hoan_tien · san_pham_loi · hoi_thong_tin
urgencycao · trung_binh · thap
sentimenttieu_cuc · trung_tinh · tich_cuc
producttên sản phẩm xuất hiện trong ticket

Cấu hình huấn luyện

Base modelunsloth/Qwen3.5-4B
Phương phápLoRA (PEFT), base đóng băng
Vị trí gắntext-linear — toàn bộ 12 lớp linear của text decoder, không gắn vision tower
r / alpha16 / 32
Tham số huấn luyện32,464,896
Learning rate1e-4 (≈ 10× thang full fine-tune)
Batch hiệu dụng16 (1 × grad_accum 16)
Epochs / steps2 / 30 optimizer steps
max_length1024 (p95 đo được của corpus: 98 token)
Loss maskassistant-only — supervised_fraction = 0.4149, câu hỏi không vào loss
Precisionfp16 + GradScaler (T4 · sm_75 · không có bf16)
Dữ liệu225 train / 25 val, tách seed 42 từ 250 ticket tổng hợp
Phần cứngColab Free T4 · peak VRAM 12.01 GB · 991 s

Trọng số adapter được lưu ở fp32 (hệ quả của bước recast cho GradScaler trên fp16), nên file nặng ~124 MB thay vì ~62 MB.

Kết quả

Chấm trên 50 ticket giữ riêng (target), 15 câu kiến thức phổ thông (regression), greedy decoding.

Runtargetregressionformatlatency (ms)
(a) base + prompt ngây thơ0.0000.7580.0003303.3
(b) base + prompt tối ưu0.7650.7581.0001060.6
(c) adapter này0.9700.6561.0001493.4

Adapter được chấm với prompt một câu ("Phân loại ticket sau."), còn (b) dùng prompt schema đầy đủ — hành vi đã nằm trong trọng số, không phải trong prompt.

Phán quyết: FAILED

  • —target Δ = +0.205 so với baseline prompt tối ưu đã đóng băng trước khi train ✅
  • —regression Δ = -0.102 — gấp 5.1 lần ngưỡng dung sai 0.020 ❌
  • —valid_trace_rate = 0.00 — khả năng sinh khối <think> biến mất hoàn toàn

Đây là quên thảm hoạ (catastrophic forgetting): 225 mẫu, 2 epoch, 100% token được supervise đều là JSON 4 trường. Đừng deploy adapter này như trợ lý tổng quát. Dùng được nếu mount có điều kiện — chỉ bật cho route triage, mọi request khác đi thẳng vào base model.

6 lỗi còn lại có cấu trúc

Điểm 0.970 = sai 6/200 trường. Cả 6 đều là cùng một trường (urgency), cùng một chiều (thap → trung_binh), và cùng một cụm từ trong ticket: "Khi nào tiện." Hai cue thap khác thì đúng 100% ("Không vội" 7/7, "Hỏi cho biết thôi" 5/5), dù cụm "Khi nào tiện" xuất hiện tới 35 lần trong tập train và luôn gắn nhãn thap. Giả thuyết: base model đọc cụm đó như câu hỏi về thời điểm, và 30 step chưa đủ để lật một tiên nghiệm ngược chiều.

Đối chứng (cùng 30 step, mỗi run đổi đúng một biến)

RunBiến đổirtrainabletargetVRAM GB
correct (adapter này)—1632,464,8960.97012.01
attn_onlychỉ gắn q,v (rank khớp ngân sách)28332,456,7040.97012.02
wrong_lrLR 1e-5 (thang full-FT)1632,464,8960.00012.01
qlora4-bit1632,464,8960.9407.09

attn_only hoà, không thua — trên corpus này phép so vị trí-vs-rank đã bão hoà. Đáng chú ý: xếp theo train loss thì attn_only (0.536) "thắng" correct (0.626), tức thứ tự theo loss khác thứ tự theo năng lực thật.

Cách dùng

python
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel

BASE = "unsloth/Qwen3.5-4B"
tok = AutoTokenizer.from_pretrained(BASE)
model = AutoModelForCausalLM.from_pretrained(BASE, dtype="auto", device_map="auto")
model = PeftModel.from_pretrained(model, "hungarmen/lab21-2A202601523-qwen35-triage-vi")

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."},
]
ids = tok.apply_chat_template(msgs, add_generation_prompt=True, return_tensors="pt").to(model.device)
out = model.generate(ids, max_new_tokens=96, do_sample=False)
print(tok.decode(out[0][ids.shape[-1]:], skip_special_tokens=True))

Giới hạn

  • —Huấn luyện trên 250 ticket tổng hợp, không phải log CSKH thật — phân bố hẹp, câu chữ đều đặn hơn dữ liệu thực tế nhiều.
  • —Năng lực phổ thông đã tụt 0.102; không dùng cho hội thoại mở.
  • —product được chấm bằng so khớp sau khi bỏ dấu, nên tên sản phẩm lạ có thể lệch.
  • —Chỉ kiểm trên tiếng Việt.

Artefact kèm theo

  • —results/ — toàn bộ file chấm điểm: mask_proof.json, baselines_frozen.json, runs.csv, verdict.json, autopsy.json, qualitative.json, token_stats.json, template_check.json
  • —submission/REPORT.md — báo cáo đầy đủ 7 mục