ADK-Bot / engine /flow_router.py
Mr-Help's picture
Upload 6 files
02fbdc7 verified
Raw
History Blame
15.4 kB
from engine.states import (
START,
WAITING_MAIN_MENU,
WAITING_USER_TYPE,
WAITING_AUDIENCE,
WAITING_PRIOR_STUDY,
WAITING_BEGINNER_SCHEDULE_CHOICE,
WAITING_PLACEMENT_TEST_CONFIRMATION,
WAITING_CURRENT_STUDENT_ACTION,
WAITING_SUPPORT_QUESTION,
WAITING_LEVEL_SELECTION,
WAITING_PAYMENT_METHOD,
WAITING_COMPLAINT_FORM,
HANDOFF_DONE,
)
from knowledge.replies import (
greeting_main_menu_reply,
ask_new_or_current_reply,
ask_audience_reply,
ask_prior_study_reply,
beginner_schedule_reply,
placement_test_reply,
current_student_menu_reply,
support_question_reply,
ask_level_selection_reply,
payment_methods_reply,
unknown_reply,
)
from handoff.sales import create_sales_handoff_result
from handoff.support import create_support_handoff_result
from handoff.complaints import create_complaint_flow_result
def normalize_text(text: str) -> str:
return (text or "").strip().lower()
def contains_any(text: str, keywords: list) -> bool:
return any(k in text for k in keywords)
def is_yes(text: str) -> bool:
t = normalize_text(text)
return t in [
"نعم", "اه", "أه", "ايوه", "أيوه", "yes", "y",
"درست", "اه درست", "أيوه درست"
]
def is_no(text: str) -> bool:
t = normalize_text(text)
return t in [
"لا", "لأ", "لاا", "no", "n",
"مدرستش", "ما درستش", "لا مدرستش"
]
def is_new_student(text: str) -> bool:
t = normalize_text(text)
return contains_any(t, [
"طالب جديد", "جديد", "عميل جديد", "اول مرة", "أول مرة",
"لسه جديد", "مشترك جديد"
])
def is_current_student(text: str) -> bool:
t = normalize_text(text)
return contains_any(t, [
"طالب حالي", "حالي", "عميل حالي", "مشترك", "مشترك حالي",
"أنا طالب", "انا طالب عندكم", "انا مشترك"
])
def is_adults(text: str) -> bool:
t = normalize_text(text)
return contains_any(t, [
"كبار", "adult", "adults", "الكبار"
])
def is_children(text: str) -> bool:
t = normalize_text(text)
return contains_any(t, [
"اطفال", "أطفال", "طفل", "children", "kids"
])
def is_support_request(text: str) -> bool:
t = normalize_text(text)
return contains_any(t, [
"استفسار", "سؤال", "عندي سؤال", "مشكلة", "مش فاهم",
"عايز اسأل", "عايزة اسأل", "محتاج مساعدة", "محتاجه مساعدة",
"support", "خدمة العملاء"
])
def is_next_level_booking(text: str) -> bool:
t = normalize_text(text)
return contains_any(t, [
"حجز", "احجز", "المستوى التالي", "مستوى تالي",
"next level", "احجز المستوى", "حجز مستوى"
])
def detect_level(text: str):
t = normalize_text(text)
if contains_any(t, ["1a", "a1", "a1.1", "1 a"]):
return "1A"
if contains_any(t, ["2a", "a2", "a1.2", "2 a"]):
return "2A"
if contains_any(t, ["1b", "b1", "b1.1", "1 b"]):
return "1B"
if contains_any(t, ["1c", "2b", "b2", "1c2/b", "1 c", "2 b"]):
return "1C2/B"
return None
def detect_payment_method(text: str):
t = normalize_text(text)
if contains_any(t, ["فرع", "فروع", "كاش", "cash"]):
return "branch_or_cash"
if contains_any(t, ["تحويل", "بنكي", "bank", "transfer"]):
return "bank_transfer"
if contains_any(t, ["فودافون", "vodafone", "vodafone cash"]):
return "vodafone_cash"
if contains_any(t, ["فيزا", "visa", "ماستر", "master", "credit card", "card"]):
return "card"
if contains_any(t, ["تقسيط", "value", "فاليو"]):
return "installments"
return None
def is_complaint(text: str) -> bool:
t = normalize_text(text)
return contains_any(t, [
"شكوى", "اشتكي", "اشتك", "مشكلة كبيرة", "complaint"
])
def wants_direct_support(text: str) -> bool:
t = normalize_text(text)
return contains_any(t, [
"تواصل", "اكلم", "عايز حد يكلمني", "عايزة حد يكلمني",
"عايز اكلم خدمة العملاء", "عايزة اكلم خدمة العملاء"
])
def wants_start(text: str) -> bool:
t = normalize_text(text)
return contains_any(t, [
"ابدأ", "ابدا", "مساعدة", "مساعده", "start", "menu", "القائمة"
])
def route_message(state: str, text: str, session: dict):
t = normalize_text(text)
flow_data = session.get("flow_data", {}) or {}
# =========================
# START
# =========================
if state == START:
return greeting_main_menu_reply(flow_data)
# =========================
# WAITING_MAIN_MENU
# =========================
if state == WAITING_MAIN_MENU:
if is_complaint(t):
return create_complaint_flow_result(flow_data)
if wants_direct_support(t):
return create_support_handoff_result(
flow_data=flow_data,
summary="طلب تواصل مباشر مع خدمة العملاء"
)
if wants_start(t):
return ask_new_or_current_reply(flow_data)
# لو العميل دخل مباشرة بنية واضحة
if is_new_student(t):
flow_data["customer_type"] = "new"
return ask_audience_reply(flow_data)
if is_current_student(t):
flow_data["customer_type"] = "current"
return current_student_menu_reply(flow_data)
return ask_new_or_current_reply(flow_data)
# =========================
# WAITING_USER_TYPE
# =========================
if state == WAITING_USER_TYPE:
if is_new_student(t):
flow_data["customer_type"] = "new"
return ask_audience_reply(flow_data)
if is_current_student(t):
flow_data["customer_type"] = "current"
return current_student_menu_reply(flow_data)
if is_complaint(t):
return create_complaint_flow_result(flow_data)
return {
"next_state": WAITING_USER_TYPE,
"flow_data": flow_data,
"reply": "تمام، محتاج أعرف الأول: إنت طالب جديد ولا طالب حالي؟"
}
# =========================
# WAITING_AUDIENCE
# =========================
if state == WAITING_AUDIENCE:
if is_adults(t):
flow_data["audience"] = "adults"
return ask_prior_study_reply(flow_data)
if is_children(t):
flow_data["audience"] = "children"
return ask_prior_study_reply(flow_data)
return {
"next_state": WAITING_AUDIENCE,
"flow_data": flow_data,
"reply": "تمام، الكورس للكبار ولا للأطفال؟"
}
# =========================
# WAITING_PRIOR_STUDY
# =========================
if state == WAITING_PRIOR_STUDY:
if is_no(t):
flow_data["prior_study"] = False
return beginner_schedule_reply(flow_data)
if is_yes(t):
flow_data["prior_study"] = True
return placement_test_reply(flow_data)
return {
"next_state": WAITING_PRIOR_STUDY,
"flow_data": flow_data,
"reply": "هل درست اللغة الألمانية قبل كده؟ رد بنعم أو لا."
}
# =========================
# WAITING_BEGINNER_SCHEDULE_CHOICE
# =========================
if state == WAITING_BEGINNER_SCHEDULE_CHOICE:
if contains_any(t, ["تم", "اخترت", "اختارت", "جاهز", "جاهزة"]):
return payment_methods_reply(flow_data)
if contains_any(t, ["عايز احجز", "عايزة احجز", "احجز", "حجز", "اشترك", "اشتراك"]):
return payment_methods_reply(flow_data)
if contains_any(t, ["محتاج مساعدة", "محتاجه مساعدة", "استفسار", "سؤال"]):
return create_support_handoff_result(
flow_data=flow_data,
summary="استفسار عن مواعيد كورسات المبتدئين"
)
return {
"next_state": WAITING_BEGINNER_SCHEDULE_CHOICE,
"flow_data": flow_data,
"reply": "بعد ما تختار المعاد المناسب، ابعتلي تم أو قولّي تحب نكمّل الحجز."
}
# =========================
# WAITING_PLACEMENT_TEST_CONFIRMATION
# =========================
if state == WAITING_PLACEMENT_TEST_CONFIRMATION:
if contains_any(t, ["تم", "اخترت", "اختارت", "جاهز", "جاهزة"]):
return create_sales_handoff_result(
flow_data=flow_data,
summary="عميل اختار أو مهتم باختبار تحديد مستوى"
)
if contains_any(t, ["تفاصيل", "اعرف اكتر", "محتاج مساعدة", "مساعدة", "استفسار"]):
return create_support_handoff_result(
flow_data=flow_data,
summary="استفسار عن اختبار تحديد المستوى"
)
return {
"next_state": WAITING_PLACEMENT_TEST_CONFIRMATION,
"flow_data": flow_data,
"reply": "بعد ما تراجع مواعيد اختبار تحديد المستوى، ابعتلي تم أو قولّي لو محتاج مساعدة."
}
# =========================
# WAITING_CURRENT_STUDENT_ACTION
# =========================
if state == WAITING_CURRENT_STUDENT_ACTION:
if is_support_request(t):
return support_question_reply(flow_data)
if is_next_level_booking(t):
return ask_level_selection_reply(flow_data)
if is_complaint(t):
return create_complaint_flow_result(flow_data)
return {
"next_state": WAITING_CURRENT_STUDENT_ACTION,
"flow_data": flow_data,
"reply": "تحب استفسار بخصوص الكورس ولا حجز المستوى التالي؟"
}
# =========================
# WAITING_SUPPORT_QUESTION
# =========================
if state == WAITING_SUPPORT_QUESTION:
flow_data["support_question"] = text
return create_support_handoff_result(
flow_data=flow_data,
summary=f"استفسار طالب حالي: {text}"
)
# =========================
# WAITING_LEVEL_SELECTION
# =========================
if state == WAITING_LEVEL_SELECTION:
level = detect_level(t)
if level:
flow_data["selected_level"] = level
return payment_methods_reply(flow_data)
if contains_any(t, ["مش عارف", "مش متأكد", "مش متاكدة", "محتاج مساعدة", "استفسار"]):
return create_support_handoff_result(
flow_data=flow_data,
summary="طالب حالي محتاج مساعدة في اختيار المستوى التالي"
)
return {
"next_state": WAITING_LEVEL_SELECTION,
"flow_data": flow_data,
"reply": "قولّي المستوى اللي تحب تحجزه: 1A أو 2A أو 1B أو 1C2/B."
}
# =========================
# WAITING_PAYMENT_METHOD
# =========================
if state == WAITING_PAYMENT_METHOD:
payment_method = detect_payment_method(t)
if payment_method:
flow_data["payment_method"] = payment_method
payment_summaries = {
"branch_or_cash": "عميل جاهز للحجز واختار الدفع كاش أو في الفرع",
"bank_transfer": "عميل جاهز للحجز واختار تحويل بنكي",
"vodafone_cash": "عميل جاهز للحجز واختار Vodafone Cash",
"card": "عميل جاهز للحجز واختار الدفع بالبطاقة",
"installments": "عميل مهتم بالتقسيط",
}
return create_sales_handoff_result(
flow_data=flow_data,
summary=payment_summaries[payment_method]
)
if contains_any(t, ["استفسار", "سؤال", "محتاج مساعدة", "محتاجه مساعدة"]):
return create_support_handoff_result(
flow_data=flow_data,
summary="استفسار عن طرق الدفع أو إتمام الحجز"
)
return {
"next_state": WAITING_PAYMENT_METHOD,
"flow_data": flow_data,
"reply": "اختار طريقة الدفع المناسبة: الفرع / تحويل بنكي / Vodafone Cash / Visa / تقسيط Value."
}
# =========================
# WAITING_COMPLAINT_FORM
# =========================
if state == WAITING_COMPLAINT_FORM:
if contains_any(t, ["تم", "خلصت", "سجلت", "قدمت", "بعت"]):
return {
"next_state": WAITING_COMPLAINT_FORM,
"flow_data": flow_data,
"reply": "تمام، بعد مراجعة الشكوى هيتم التواصل معاك. ولو حابب تكتب أي تفاصيل إضافية ابعتها هنا."
}
return {
"next_state": WAITING_COMPLAINT_FORM,
"flow_data": flow_data,
"reply": "سجّل الشكوى من الفورم أولًا، ولو احتجت مساعدة ابعتلي."
}
# =========================
# HANDOFF_DONE
# =========================
if state == HANDOFF_DONE:
if is_complaint(t):
return create_complaint_flow_result(flow_data)
if is_support_request(t):
return create_support_handoff_result(
flow_data=flow_data,
summary=f"استفسار إضافي بعد handoff: {text}"
)
if contains_any(t, ["شكرا", "متشكر", "تسلم", "ميرسي"]):
return {
"next_state": HANDOFF_DONE,
"flow_data": flow_data,
"reply": "العفو، تحت أمرك في أي وقت."
}
return {
"next_state": HANDOFF_DONE,
"flow_data": flow_data,
"reply": "تم تسجيل طلبك بالفعل، وفريقنا هيتواصل معاك قريب. لو عندك استفسار إضافي ابعته هنا."
}
return unknown_reply(flow_data)