Downloads · 30 days
0
anamolsitaula/llama3-ticket-classifier-lora
llama3-ticket-classifier-lora is a text classification model from anamolsitaula. Use it when you need a label for a piece of text. The card lists the license as llama3.1.
Downloads · 30 days
0
Access
Public
Updated Aug 12, 2026
Repo size
185 MB
Likes
0
Public
Click a slice to open those files.
.safetensors168 MB · 91%
From the Hugging Face model README
Task: Convert an unstructured customer support message into a structured JSON ticket with three fields: category, urgency, and summary.
Why fine-tuning (vs RAG or prompting): This is a behavior/format problem, not a knowledge problem — the model doesn't need new facts, it needs to consistently follow a fixed output schema and internalize a consistent labeling scheme across six categories. Fine-tuning is well-suited to this; RAG would add no value here since there's no external knowledge to retrieve.
Categories used: connectivity, billing, technical, security, account, feature_question
Urgency levels used: low, medium, high
train.json — 51 examplesval.json — 9 examples (held out, never seen during training){instruction, input, output}, one JSON object per line.| Setting | Value |
|---|---|
| Base model | Llama 3.1 8B (Unsloth 4-bit quantized) |
| Fine-tuning method | LoRA (via Unsloth) |
| Trainable parameters | 41,943,040 / 8,072,204,288 (0.52%) |
| LoRA target modules | Attention projection layers (q/k/v/o_proj) |
| Hardware | Google Colab, free-tier Tesla T4 GPU |
| Batch size (effective) | 8 (per-device 2 × grad accumulation 4) |
| Learning rate | 2e-4 |
| Epochs / steps | Two runs compared — see below |
Run 1 — max_steps = 60 (~9 epochs over 51 examples)
Run 2 — max_steps = 20 (~3 epochs over 51 examples)
Before comparing the two fine-tuning runs against each other, the untouched base model (Llama 3.1 8B, no LoRA adapter at all) was tested on the same 3 held-out complaints, to confirm fine-tuning was actually necessary rather than assumed:
| Test complaint | Base model output | Problem |
|---|---|---|
| "I'm unable to add new team members, the invite button just doesn't respond." | Echoed the input text back, then hallucinated fabricated new instruction/input/response blocks with entirely different complaints | No structure, no JSON, model just pattern-completed text rather than answering |
| "I can't reset my password, the reset link in the email isn't working at all." | {"category": "Authentication", "urgency": "High", "summary": "..."} | Produced valid JSON, but invented its own category (Authentication, not one of the 6 trained categories) and inconsistent casing (High vs high) |
| "Do you offer a student discount? Just curious before I renew." | Output as Python comments, not JSON: # Category: Renewal, # Urgency: Low, # Summary: Student discount | Wrong output format entirely (code comments instead of JSON), and invented a category (Renewal) not in the trained set |
Conclusion: the base model does not reliably follow the required JSON schema or fixed category/urgency vocabulary at all — it either fails to respond correctly, hallucinates unrelated content, or invents its own labels outside the trained vocabulary. This confirms fine-tuning was necessary for this task, not just a comparison between fine-tuning configurations.
Evaluated both runs on the same 3 held-out examples from val.json (never seen during training):
| Test complaint | Expected | Run 1 output | Run 2 output |
|---|---|---|---|
| "I'm unable to add new team members, the invite button just doesn't respond." | technical / medium | account ❌ / medium ✅ | technical ✅ / medium ✅ |
| "I can't reset my password, the reset link in the email isn't working at all." | account / high | security ❌ / medium ❌ | security ❌ / medium ❌ |
| "Do you offer a student discount? Just curious before I renew." | billing / low | billing ✅ / low ✅ | billing ✅ / low ✅ |
Accuracy summary:
| Metric | Base model | Run 1 (60 steps) | Run 2 (20 steps) |
|---|---|---|---|
| Follows JSON schema correctly | 1/3 (inconsistent) | 3/3 | 3/3 |
| Uses only the 6 trained categories | 0/3 | 3/3 | 3/3 |
| Category accuracy | N/A (no valid categories produced) | 1/3 | 2/3 |
| Urgency accuracy | N/A | 2/3 | 3/3 |
| Summary quality | N/A | Paraphrased, not verbatim, in both runs | Paraphrased, not verbatim, in both runs |
max_steps (e.g. 10, 20, 30, 40) with loss + validation accuracy logged at each, rather than comparing just two arbitrary points.The trained LoRA adapter is hosted on Hugging Face Hub: anamolsitaula/llama3-ticket-classifier-lora
The base model (unsloth/Meta-Llama-3.1-8B-bnb-4bit) and the adapter above are both downloaded automatically from Hugging Face — no local model files needed.
from unsloth import FastLanguageModel
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "anamolsitaula/llama3-ticket-classifier-lora",
max_seq_length = 2048,
load_in_4bit = True,
)
FastLanguageModel.for_inference(model)
alpaca_prompt = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
### Instruction:
{}
### Input:
{}
### Response:
{}"""
inputs = tokenizer(
[alpaca_prompt.format(
"Convert this customer message into a structured support ticket with category, urgency, and summary.",
"Your customer complaint here",
"",
)], return_tensors="pt"
).to("cuda")
outputs = model.generate(**inputs, max_new_tokens=128)
print(tokenizer.batch_decode(outputs))
To retrain from scratch instead of just running inference: open the Unsloth Colab notebook, upload train.json from this repo, and follow the same steps documented above (attach LoRA adapters, format with the Alpaca prompt template, train with SFTTrainer, max_steps = 20).