feat(script): one-time fix_existing personas' openers to natural Thai
Deterministic, conservative: only rewrites openers that lead with a casual interjection (เฮ้/เอ้/เอ่อ/เอ๊ะ/อืม/เออ/นี่ๆ/ว่าไง/hey/hi/hiya/yo) or a bare politeness word (ครับ/ค่ะ). Leaves natural Thai and English openers untouched. Prints before -> after. Run in the container console: cd /app/backend && python3 scripts/fix_openers.py
This commit is contained in:
86
backend/scripts/fix_openers.py
Normal file
86
backend/scripts/fix_openers.py
Normal file
@@ -0,0 +1,86 @@
|
||||
"""One-time data fix (run in the EasyPanel container console):
|
||||
Rewrite existing personas' openers (opener) to natural Thai.
|
||||
|
||||
Only rewords openers that OPEN with a casual interjection/filler
|
||||
(เฮ้ / เอ้ / เอ่อ / เอ๊ะ / อืม / เออ / นี่ๆ / ว่าไง / hey / hi / hiya / yo ...).
|
||||
Everyone else is left untouched (safe & reversible). Prints before -> after.
|
||||
|
||||
Usage:
|
||||
cd /app/backend
|
||||
python3 /path/to/fix_openers.py # or paste as a heredoc
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from app.config import Config
|
||||
from app.services.groups import GroupStore
|
||||
|
||||
# Leading casual interjections/filler that make a Thai opener sound unnatural.
|
||||
FILLER = re.compile(
|
||||
r"^(?:เฮ้|เอ้|เอ่อ|เอ๊ะ|อืม|เออ|นี่ๆ|นี่|ว่าไง|เฮย์|hey|hiya|hi|hello|yo)"
|
||||
r"[\s:,\-–—]*",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
BARE_POLITE = re.compile(r"^(ครับ|ค่ะ)(\s|$)")
|
||||
THAI_CHAR = re.compile(r"[\u0E00-\u0E7F]")
|
||||
|
||||
|
||||
def fix_opener(existing: str) -> str | None:
|
||||
"""Return the rewritten opener, or None when nothing needs changing."""
|
||||
if not isinstance(existing, str) or not existing.strip():
|
||||
return None
|
||||
s = existing.strip()
|
||||
# Only target Thai openers; leave English ones untouched.
|
||||
if not THAI_CHAR.search(s):
|
||||
return None
|
||||
|
||||
# 1) Strip leading casual fillers (เฮ้ / เอ้ / เอ่อ / hey / hi / ...).
|
||||
m = FILLER.match(s)
|
||||
grand_rest = s[m.end():].strip(" ,-–—:;") if m else s.strip()
|
||||
new = grand_rest
|
||||
|
||||
# 2) If it now (or originally) opens with a bare politeness word, prepend
|
||||
# the proper greeting: "ครับ สนใจ..." -> "สวัสดีครับ สนใจ..."
|
||||
bp = BARE_POLITE.match(new)
|
||||
if bp:
|
||||
polite = new[: len(bp.group(1))]
|
||||
new = new[len(polite):].strip(" ,-–—:;") or ""
|
||||
new = "สวัสดี" + polite + ((" " + new) if new else "")
|
||||
|
||||
cleaned = " ".join(new.split())
|
||||
if not cleaned or cleaned == s:
|
||||
return None # nothing meaningful changed (or was empty)
|
||||
return cleaned[:400]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
store = GroupStore(Config.DATA_DIR)
|
||||
groups = store.groups.all()
|
||||
fixed = skipped = 0
|
||||
seen: set[str] = set()
|
||||
for group in groups:
|
||||
gid = group.get("id") or group.get("_id")
|
||||
if not gid or gid in seen:
|
||||
continue
|
||||
seen.add(gid)
|
||||
raw = group.get("personas") or []
|
||||
personas = [p for p in raw if isinstance(p, dict) and p.get("id")]
|
||||
for p in personas:
|
||||
oid = p.get("id")
|
||||
old = p.get("opener") or ""
|
||||
new = fix_opener(old)
|
||||
if new is None:
|
||||
skipped += 1
|
||||
continue
|
||||
print(f"[{gid}] persona={oid!r}")
|
||||
print(f" before: {old!r}")
|
||||
print(f" after : {new!r}")
|
||||
store.update_persona(gid, oid, {"opener": new})
|
||||
fixed += 1
|
||||
print(f"\nDONE — fixed: {fixed}, left-as-is: {skipped}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user