| """Stage 1 of the Piper pipeline — normalize Indonesian/English code-mixed PO text.""" |
|
|
| import re |
|
|
| |
| SLANG_PATTERNS: list[tuple[str, str, str]] = [ |
| (r"\bmohon segera\b", "urgent ship request", "mohon segera"), |
| (r"\btolong kirim\b", "please ship", "tolong kirim"), |
| (r"\bkirim ya\b", "please ship", "kirim ya"), |
| (r"\brestock asap\b", "restock segera", "restock asap"), |
| (r"\bstok habis\b", "out of stock", "stok habis"), |
| (r"\blg diskon\b", "on sale", "lg diskon"), |
| (r"\blagi diskon\b", "on sale", "lagi diskon"), |
| (r"\bpesenan\b", "order", "pesanan"), |
| (r"\bpesan\b", "order", "pesan"), |
| (r"\bstiker\b", "sticker", "stiker"), |
| (r"\bstik(er)?\b", "sticker", "stiker"), |
| (r"\blembar\b", "pcs", "lembar"), |
| (r"\bbuah\b", "pcs", "buah"), |
| (r"\bunit\b", "pcs", "unit"), |
| (r"\bpcs\b", "pcs", "pcs"), |
| (r"\bpesanan bulan\b", "monthly order", "pesanan bulan"), |
| (r"\bmau order lagi\b", "reorder", "mau order lagi"), |
| (r"\bhai kak\b", "", "hai kak"), |
| (r"\bmakasih\b", "", "makasih"), |
| (r"\bthx\b", "", "thx"), |
| (r"\bthanks\b", "", "thanks"), |
| ] |
|
|
| |
| QTY_HINT = re.compile( |
| r"(\d+)\s*(?:pcs|pc|lembar|buah|unit)?", |
| re.I, |
| ) |
|
|
|
|
| def normalize_po_text(raw: str) -> tuple[str, list[str]]: |
| """ |
| Clean code-mixed PO text before the LLM sees it. |
| Returns (normalized_text, list of human-readable fixes applied). |
| """ |
| text = raw.strip() |
| fixes: list[str] = [] |
|
|
| for pattern, replacement, label in SLANG_PATTERNS: |
| if re.search(pattern, text, re.I): |
| text = re.sub(pattern, replacement, text, flags=re.I) |
| if label and label not in fixes: |
| fixes.append(label) |
|
|
| |
| text = re.sub(r"[ \t]+", " ", text) |
| text = re.sub(r"\n{3,}", "\n\n", text) |
| text = re.sub(r"^[,;\s]+", "", text) |
| text = re.sub(r"[,;\s]{2,}", ", ", text) |
|
|
| return text, fixes |
|
|