Indonesian Customer Support Ticket Classifier
Route Indonesian customer-service tickets to billing, order, account, technical or inquiry teams with a small IndoBERT model that runs on a CPU.
Classifies Indonesian customer-service messages as billing, order, account, technical or product question, or none, offline on a CPU. It answers yes or no for each of the five categories, so a ticket that raises two problems reaches both teams and a greeting, thank-you or spam reaches none. It is built for how Indonesians write to customer service on WhatsApp, live chat, email, X and app-store reviews: casual Bahasa Indonesia, abbreviations (gk, blm, tlg), typos, Indonesian-English code-mix and regional phrasing. The model is IndoBERT (indobenchmark/indobert-base-p1) cut to 6 of its 12 layers and exported as an INT8 ONNX graph of about 67 MB, so it runs on a CPU or an edge device in a few milliseconds per message. Examples: "saldo kepotong tapi pesanan gagal" is billing_payment, "sudah bayar tapi paket belum sampai" is order_delivery, "akun diblokir, aktivitas mencurigakan" is account_access, and "halo min" is none.
What it answersEvery category whose score clears the threshold, with a score for each of the 5. An empty list means the message makes no request.
Also available inEnglish
Specs
Under the hood
| Indonesian | |
|---|---|
| Base model | indobenchmark/indobert-base-p1 |
| Parameters | 66.6M |
| Size | 67.2 MB |
| Format | ONNX INT8 |
| Max tokens | 256 |
Distilled from the base model by keeping fewer layers and trimming the vocabulary to the languages served, then quantised to INT8 so it fits a CPU, an edge device or embedded hardware.
Use cases
What you can do with it
Help-desk triage
Label every new message on arrival and assign it to payments, fulfilment, account security, technical support or the FAQ team — both teams when it raises two problems, nobody when it is a greeting or spam.
Deflecting questions
Answer `product_inquiry` tickets from your knowledge base or a chatbot, and keep agents for the four categories where something actually went wrong.
Volume reporting
Count tickets per category per day across WhatsApp, live chat, email and social media to see which team is under load.
Example results
Example results
Real outputs of this exact build on held-out rows — data it never saw in training. Each shows the input, what the model answered, and the reference label it was checked against. Nothing here is written by hand.
>>> classify("Selamat pagi Uda, mohon pesanan nomor PS-77310 dibatalkan karena denai salah memilih jenis meteran.")
{ "labels": [ "order_delivery" ], "scores": { "billing_payment": 0.004, "order_delivery": 0.9932, "account_access": 0.0092, "technical_issue": 0.002, "product_inquiry": 0.0034 } }# Reference: order_delivery ✗ Differs
>>> classify("NIK karyawan saya ditolak terus saat verifikasi")
{ "labels": [ "account_access" ], "scores": { "billing_payment": 0.0063, "order_delivery": 0.0051, "account_access": 0.9962, "technical_issue": 0.0042, "product_inquiry": 0.0066 } }# Reference: account_access ✗ Differs
>>> classify("Aplikasi ini sering banget force close sendiri, terutama pas saya mau pilih nominal top up. Sudah saya uninstall dan install ulang, tetap sama. Tolong diperbaiki, awak sudah tua susah kalau begini.")
{ "labels": [ "technical_issue" ], "scores": { "billing_payment": 0.0038, "order_delivery": 0.0049, "account_access": 0.0037, "technical_issue": 0.9974, "product_inquiry": 0.0145 } }# Reference: technical_issue ✗ Differs
>>> classify("gmn cara ganti nomor hp di akun? blm sy coba, tanya dulu")
{ "labels": [ "product_inquiry" ], "scores": { "billing_payment": 0.0038, "order_delivery": 0.0026, "account_access": 0.0074, "technical_issue": 0.0039, "product_inquiry": 0.9911 } }# Reference: product_inquiry ✗ Differs
>>> classify("kak akun gue kena blokir karena KTP gak cocok, dan gue mau tanya syarat ganti data KTP di aplikasi gimana. tolong dibantu dua-duanya.")
{ "labels": [ "account_access", "product_inquiry" ], "scores": { "billing_payment": 0.0925, "order_delivery": 0.0666, "account_access": 0.9945, "technical_issue": 0.0712, "product_inquiry": 0.9953 } }# Reference: account_access, product_inquiry ✗ Differs
Training data
Training data
Synthetic Indonesian customer-service messages generated across fourteen industries, nine channels, seven customer roles, nine writing styles and eight regional registers, labelled with one rubric; a quarter of every batch sits on the boundary between two categories, and the rest includes tickets with two problems and messages with none.
The classes this model learned to recognise:
| Label | Meaning |
|---|---|
billing_payment | Charges, failed or pending payments, refunds, top-ups, bills. |
order_delivery | An order, shipment, ride or booking already made: status, late, wrong, cancel, return. |
account_access | Login, PIN, OTP, blocked or hacked accounts, verification, changing account details. |
technical_issue | The app, website, network or device is not working: errors, crashes, outages, no signal. |
product_inquiry | A question with nothing gone wrong: prices, fees, promos, availability, how-to. |
The first five example rows, with the label each one carries:
| # | Text | Label |
|---|---|---|
| 0 | Selamat pagi Uda, mohon pesanan nomor PS-77310 dibatalkan karena denai salah memilih jenis meteran. | order_delivery |
| 1 | NIK karyawan saya ditolak terus saat verifikasi | account_access |
| 2 | Aplikasi ini sering banget force close sendiri, terutama pas saya mau pilih nominal top up. Sudah saya uninstall dan install ulang, tetap sama. Tolong diperbaiki, awak sudah tua susah kalau begini. | technical_issue |
| 3 | gmn cara ganti nomor hp di akun? blm sy coba, tanya dulu | product_inquiry |
| 4 | kak akun gue kena blokir karena KTP gak cocok, dan gue mau tanya syarat ganti data KTP di aplikasi gimana. tolong dibantu dua-duanya. | account_access, product_inquiry |
intura-ai script
Run it with the intura-ai SDK
- 1
Get it
Sign in on this site and press Get it. The model goes to your library with every version.
- 2
Create a download key
On your account page, create a download key and set it as INTURA_API_KEY. It only downloads what you own.
- 3
Install
pip install "intura-ai[local]" — the SDK plus the CPU runtime it uses to run a model on your machine.
- 4
Run it
Run the script. It downloads the build once and checks each file's SHA-256, then runs on your CPU, edge box or embedded Linux — no network call after the download.
# pip install "intura-ai>=3.0.0"
# export INTURA_API_KEY=... # a download key from your account
from intura_ai import Intura, LocalModel
client = Intura()
# Downloads once into ./chat-customer-support-ticket-id/v1.0; later runs reuse the files on disk.
model_dir = client.models.download("chat-customer-support-ticket-id", version="v1.0")
model = LocalModel.load(model_dir) # CPU, no network from here on
print(model.predict('Selamat pagi Uda, mohon pesanan nomor PS-77310 dibatalkan karena denai salah memilih jenis meteran.'))
# {"labels": [...], "scores": {...}}Pass the customer's first message as plain text. Order numbers, amounts and dates help: they are in the training data.
Want to see what it answers before you get it? Read the Example results
Versions
Versions
Every version stays downloadable once you own the model. A version id names exactly the bytes you download.
v1.0RecommendedONNX INT867.2 MBReleased Oct 16, 2026
Feedback
Need something changed in this model?
Ask for a new label or language, tell us where it misses on your data, get help running it, or report a bug. A person reads every message and replies by email.
Find the model for your task.
Search by what it has to do, read real example results, and download it to run on your own CPU — from $9 during early bird.