55 lines
1.7 KiB
Python
55 lines
1.7 KiB
Python
from __future__ import annotations
|
|
|
|
from app.normalization import normalize_text, tokenize
|
|
from app.typo import word_similarity
|
|
|
|
SERVICE_INTENTS = {
|
|
"opening_hours": [
|
|
("до", "скольки", "работаете"),
|
|
("режим", "работы"),
|
|
("график", "работы"),
|
|
],
|
|
"payment": [
|
|
("оплата", "картой"),
|
|
("оплатить", "картой"),
|
|
("наличными", "при", "получении"),
|
|
],
|
|
"location": [
|
|
("где", "магазин"),
|
|
("адрес", "магазина"),
|
|
("как", "доехать"),
|
|
],
|
|
"order_status": [
|
|
("статус", "заказа"),
|
|
("где", "мой", "заказ"),
|
|
],
|
|
"thanks": [
|
|
("спасибо", "заказ", "получил"),
|
|
("все", "отлично"),
|
|
],
|
|
}
|
|
|
|
|
|
def _token_present(expected: str, tokens: tuple[str, ...]) -> bool:
|
|
for token in tokens:
|
|
if token == expected:
|
|
return True
|
|
if min(len(token), len(expected)) >= 5 and word_similarity(token, expected) >= 0.72:
|
|
return True
|
|
return False
|
|
|
|
|
|
def detect_service_intent(text: str) -> str | None:
|
|
"""Detect a known non-product intent after product evidence has failed.
|
|
|
|
This is deliberately phrase/token based rather than a blacklist of words
|
|
such as ``подскажите``: those words are valid in product requests too.
|
|
"""
|
|
|
|
tokens = tokenize(normalize_text(text), already_normalized=True)
|
|
for intent, phrases in SERVICE_INTENTS.items():
|
|
for phrase in phrases:
|
|
if all(_token_present(expected, tokens) for expected in phrase):
|
|
return intent
|
|
return None
|