Banking Intent Classification — Qwen3-8B (LoRA)
Fine-tuned Qwen3-8B (4-bit QLoRA via Unsloth) on the Banking77 dataset for customer intent classification across 77 banking categories.
Model Performance
Evaluated on the Banking77 test set (NVIDIA A100-SXM4-40GB):
| Mode | Dataset | Accuracy |
|---|---|---|
| Zero-Shot (base Qwen3-8B) | 200 stratified samples | 68.00% |
| Fine-Tuned (this model) | 200 stratified samples | 90.00% |
| Fine-Tuned (this model) | Full test set (3,080 samples) | 91.85% |
Macro F1: 0.9182 across all 77 intent classes.
Training Details
| Parameter | Value |
|---|---|
| Base model | unsloth/Qwen3-8B |
| Quantization | 4-bit (QLoRA) |
| Max sequence length | 2048 |
| LoRA rank (r) | 16 |
| LoRA alpha | 32 |
| LoRA dropout | 0.05 |
| Epochs | 1 |
| Batch size | 2 (grad accum 4 → effective 8) |
| Learning rate | 2e-4 |
| LR scheduler | cosine |
| Optimizer | adamw_8bit |
Usage
from unsloth import FastLanguageModel
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="minhthien/banking-intent-unsloth",
max_seq_length=2048,
load_in_4bit=True,
)
FastLanguageModel.for_inference(model)
INTENT_LABELS = [
"Refund_not_showing_up", "activate_my_card", "age_limit",
"apple_pay_or_google_pay", "atm_support", "automatic_top_up",
# ... (77 labels total, see Banking77 dataset)
]
SYSTEM_PROMPT = (
"You are a banking intent classifier. "
"Given a customer message, output exactly one intent label from the list below. "
"Output only the label, nothing else.\n\n"
"Labels:\n" + "\n".join(f"- {l}" for l in INTENT_LABELS)
)
def classify(text: str) -> str:
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": text},
]
input_ids = tokenizer.apply_chat_template(
messages, tokenize=True, add_generation_prompt=True, return_tensors="pt"
).to("cuda")
output = model.generate(input_ids=input_ids, max_new_tokens=32, do_sample=False)
decoded = tokenizer.decode(output[0][input_ids.shape[1]:], skip_special_tokens=True)
return decoded.strip()
print(classify("I lost my credit card, how do I order a replacement?"))
# → lost_or_stolen_card
Or use the full IntentClassification class from the project repo:
import sys
sys.path.insert(0, "scripts")
from inference import IntentClassification
clf = IntentClassification("configs/inference.yaml", mode="finetuned")
result = clf("I lost my credit card, how do I order a replacement?")
print(result) # → "lost_or_stolen_card"
Dataset
Banking77 — 13,083 customer service queries across 77 intent categories.
- Train: 10,003 samples
- Test: 3,080 samples (40 per intent)
Repo
Training code, evaluation scripts, and notebooks: nguyenvmthien/banking-intent-unsloth
- Downloads last month
- 122