Voice2Policy Text Router v0.1
๐ฐ๐ท Korean card: MODEL_CARD.ko.md
A small character n-gram TF-IDF + logistic regression classifier that reads a Korean business voice command (an ASR transcript) and predicts its command frame โ intent, action, and the kind of pending item โ plus whether a booking time/date or phone number was mentioned. It is the routing step of ThakiCloud's Voice2Policy pipeline (ASR โ this router โ entity resolver โ tool-schema check โ policy engine).
It is a trained machine-learning model, but not a neural network, an LLM, a Transformer, or a speech model. It does not hear audio, does not resolve names, and does not execute anything.
Use
pip install numpy safetensors huggingface_hub
from huggingface_hub import snapshot_download
import sys
d = snapshot_download("ThakiCloud/Voice2Policy-Text-Router-v0.1")
sys.path.insert(0, d)
from predict import TextRouter
r = TextRouter(d)
print(r.predict("๋ด์ผ ์คํ ์ธ ์์ ์ค์ผ์ผ๋ง ์์ฝํด ์ฃผ์ธ์"))
# {'intent': 'tool', 'action': 'book', 'kind': None, 'frame_score': 0.9991, ..., 'slot_mentioned': True, 'slot_score': ..., 'tool_hint': 'update_slots'}
Command line: python predict.py "์ฝ๋๋ธ๋ฃจ ๋ผ๋ผ ๋ ์ ์ฃผ์ธ์" --json. No pickle and no scikit-learn are needed: weights are in model.safetensors, the n-gram vocabulary in vocab.json, settings and labels in config.json.
Output
| field | meaning |
|---|---|
intent |
tool (business tool request), no_command (question, narration, refusal), delegate (hand off to staff: refund, complaint, discount, medical, asking for the owner) |
action |
book, order, confirm, decline (only when intent=tool) |
kind |
booking / order when the utterance says which pending item to confirm or cancel, else null |
frame_score, frame_scores |
softmax probability of the chosen frame and of all 10 frames |
slot_mentioned, slot_score |
a booking time/date or phone number was mentioned (sigmoid โฅ 0.5) |
tool_hint |
default tool family for the frame (update_slots, update_basket, confirm_*, decline_*, handoff) |
From frame to tool. The final decision needs things this model does not see: the workspace's registered service/menu names, what is pending, and the tool's required arguments. In Voice2Policy that is done after the router (entity resolver, schema check, policy engine). Do not execute tool_hint directly.
Model
| Features | scikit-learn TfidfVectorizer(analyzer="char_wb", ngram_range=(1,4), min_df=2, sublinear_tf=True, norm="l2") re-implemented in numpy โ 8,716 character n-grams |
| Frame head | multinomial logistic regression, 10 classes (C = 10) |
| Slot head | binary logistic regression |
| Parameters | 104,603 (coefficients + intercepts + IDF) |
| Files | model.safetensors 0.84 MB, vocab.json 0.15 MB |
| Inference | CPU, ~0.7 ms per utterance (measured inside the pipeline on one B200 host's CPU) |
| Training | 10,682 sentences, 11 s on CPU |
equivalence.json: the exported model reproduces the original scikit-learn model on 5,613 sentences โ identical frame and slot decisions; probabilities differ only by the 4-decimal rounding of the output.
Training data
10,682 synthetic Korean business commands (booking / ordering / confirm / cancel / FAQ / narration / negation / hand-off) for 11 small-business types (clinic, cafe, restaurant, nail shop, โฆ). The sentences were written by an LLM from typed command representations, and the labels come from deterministic rules on those representations, not from the LLM. No customer data, no recordings, and no personal information. The dataset is not released.
Evaluation (development comparison, single training run)
| input | frame accuracy | intent+action | slot mentioned |
|---|---|---|---|
| held-out synthetic sentences (biz_test, 3,081) | 0.998 | 0.998 | 0.999 |
| ASR transcripts of the same test set read by TTS voices (18,879 clips; Qwen3-ASR-1.7B with registered names as context) | 0.997 | 0.997 | 0.998 |
| 81 hand-written sentences in other wording | 0.827 | 0.889 | 0.975 |
The held-out test shares the generator's style with training, so the first two rows are optimistic. On hand-written wording the router drops to 0.83. Typical misses: a refund request with no "staff" word is read as no_command; negated requests ("์์ฝ ์ทจ์ํ์ง ๋ง์ ์ฃผ์ธ์" โ don't cancel) are read as the action; demonstratives alone ("๊ทธ๊ฑฐ ํด ์ฃผ์ธ์" โ do that) are guessed as a cancel. In Voice2Policy these are caught by the policy engine (negation on the tool verb, required action evidence for confirm/cancel, policy hand-off cues); with that layer the same 81 sentences give 76/81 correct decisions and no unsafe execution.
Limitations
- Korean only; vocabulary of small-business booking/ordering. Other domains need retraining.
- Synthetic training text only; real users' phrasing is not measured.
- A bag of character n-grams has no notion of scope: negation and reference need the downstream policy checks.
- Scores are not calibrated probabilities of being correct.
License
Apache-2.0 (weights, config and code in this repository).
- Downloads last month
- 21