-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathconversational.py
More file actions
99 lines (85 loc) · 4.38 KB
/
Copy pathconversational.py
File metadata and controls
99 lines (85 loc) · 4.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
"""Grounded handling for conversational / meta questions.
These answers describe the assistant and its corpus only — they never invent
policy content — so they are safe under the strict-grounded policy. Substantive
questions still flow to retrieval / metadata / RAG.
"""
from __future__ import annotations
import re
import unicodedata
from catalog_service import load_document_catalog
_GREETING_WORDS = {"hi", "hello", "hey", "helo", "hallo", "chao", "alo", "yo"}
_GREETING_PHRASES = {"hi", "hello", "hey", "chao", "xin chao", "chao ban", "alo", "hallo"}
# Short acknowledgements / fillers that carry no question — answering them with
# retrieved document content looks broken, so nudge instead.
_ACK = {
"ok", "oke", "okay", "oki", "okê", "k", "kk", "done", "end", "fine",
"thanks", "thank", "tks", "ty", "cam on", "uh", "um", "hmm", "hm",
"vang", "u", "uhm", "roger", "noted",
}
_IDENTITY = (
"ban la ai", "ban la gi", "ban ten gi", "ban ten la gi", "ai vay",
"gioi thieu ve ban", "gioi thieu ban", "who are you", "what are you",
)
_CAPABILITIES = (
"ban lam duoc gi", "ban lam duoc nhung gi", "lam duoc nhung gi", "lam duoc gi",
"ban giup duoc gi", "ban giup gi", "giup duoc gi", "ban co the lam gi",
"huong dan su dung", "cach su dung", "what can you do", "ban biet gi", "ban ho tro gi",
)
def _fold(text: str) -> str:
folded = unicodedata.normalize("NFC", str(text or "")).lower().replace("đ", "d")
folded = " ".join(folded.split())
decomposed = unicodedata.normalize("NFD", folded)
return "".join(char for char in decomposed if unicodedata.category(char) != "Mn")
def _collapse_repeats(text: str) -> str:
"""hiii -> hi, alooo -> alo, okkk -> ok (collapse runs of 3+ identical chars)."""
return re.sub(r"(.)\1{2,}", r"\1", text)
def detect_meta_intent(question: str) -> str | None:
"""Return "greeting" | "ack" | "identity" | "capabilities", or None.
Greetings/acks only match very short messages so a real question that merely
opens with "chào" or ends with "ok" still goes to retrieval.
"""
folded = _fold(question)
if not folded:
return None
collapsed = _collapse_repeats(folded)
words = collapsed.split()
if collapsed in _GREETING_PHRASES or (len(words) <= 2 and words[0] in _GREETING_WORDS):
return "greeting"
# Whole short message is just fillers/acks (e.g. "ok", "end", "thanks", "uh").
if len(words) <= 3 and words and all(word in _ACK for word in words):
return "ack"
if collapsed in _ACK:
return "ack"
if any(phrase in folded for phrase in _IDENTITY):
return "identity"
if any(phrase in folded for phrase in _CAPABILITIES):
return "capabilities"
return None
def meta_answer(intent: str) -> str:
total = len(load_document_catalog())
if intent == "greeting":
return (
"Chào bạn 👋 Mình là **GRC Assistant** — trợ lý tra cứu tài liệu ISMS, bảo mật "
"và tuân thủ của ZaloPay. Bạn cần tra cứu chính sách, quy trình hay tiêu chuẩn "
"nào? Ví dụ: \"quy trình cấp quyền truy cập\", \"ZION-QT-04 có mấy phiên bản\"."
)
if intent == "ack":
return (
"Mình sẵn sàng 👍 Bạn cứ hỏi về chính sách, quy trình hay tiêu chuẩn ISMS nhé. "
"Ví dụ: \"quy trình cấp quyền truy cập\", \"ZION-QT-04 có mấy phiên bản\"."
)
if intent == "identity":
return (
f"Mình là **GRC Assistant**, trợ lý tri thức GRC của ZaloPay (team GRC thuộc "
f"Compliance). Mình trả lời dựa trên {total} tài liệu ISMS đã được lập chỉ mục — "
"chỉ dùng nội dung trong tài liệu, không suy đoán bên ngoài."
)
return (
"Mình có thể giúp bạn:\n\n"
"* Tra cứu nội dung **chính sách / quy trình / tiêu chuẩn** bảo mật & tuân thủ\n"
"* Gợi ý **nên xem tài liệu nào** cho một chủ đề\n"
"* **Liệt kê phiên bản / tác giả / phạm vi** của một tài liệu\n"
"* Cho biết **tổng số và danh sách** tài liệu\n\n"
f"Hiện có {total} tài liệu trong cơ sở tri thức. Ví dụ: \"tài liệu nào về quản lý "
"tài khoản\", \"ZION-TC-13 có những phiên bản nào\", \"có bao nhiêu tài liệu\"."
)