| from engine.states import ( |
| START, |
| WAITING_MAIN_MENU, |
| WAITING_USER_TYPE, |
| WAITING_AUDIENCE, |
| WAITING_PRIOR_STUDY, |
| WAITING_BEGINNER_SCHEDULE_CHOICE, |
| WAITING_PDF_102_CONFIRMATION, |
| 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, |
| pdf_102_reply, |
| placement_test_reply, |
| current_student_menu_reply, |
| support_question_reply, |
| ask_level_selection_reply, |
| payment_methods_reply, |
| unknown_reply, |
| ) |
|
|
| from knowledge.message_understanding import classify_message |
| 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 route_message(state: str, text: str, session: dict): |
| flow_data = session.get("flow_data", {}) or {} |
| parsed = classify_message(state, text, flow_data) |
|
|
| kind = parsed["kind"] |
| value = parsed["value"] |
| entities = parsed.get("entities", {}) or {} |
|
|
| print("========== MESSAGE CLASSIFICATION ==========") |
| print(f"state: {state}") |
| print(f"text: {text}") |
| print(f"kind: {kind}") |
| print(f"value: {value}") |
| print(f"entities: {entities}") |
| print(f"source: {parsed.get('source')}") |
| if parsed.get("raw_model_output") is not None: |
| print(f"raw_model_output: {parsed.get('raw_model_output')}") |
| print("============================================") |
|
|
| |
| |
| |
| if kind == "topic_switch": |
| if value in ["restart", "new_topic", "courses_info"]: |
| return { |
| "next_state": WAITING_MAIN_MENU, |
| "flow_data": {}, |
| "reply": "تمام، نبدأ من جديد. إنت طالب جديد ولا طالب حالي؟" |
| } |
|
|
| if value == "complaint": |
| return create_complaint_flow_result(flow_data) |
|
|
| if value == "direct_support": |
| return create_support_handoff_result( |
| flow_data=flow_data, |
| summary=f"طلب تواصل مباشر أثناء المحادثة: {text}" |
| ) |
|
|
| if value == "children_courses": |
| new_flow = dict(flow_data) |
| new_flow["customer_type"] = "new" |
| new_flow["audience"] = "children" |
| return ask_prior_study_reply(new_flow) |
|
|
| if value == "adults_courses": |
| new_flow = dict(flow_data) |
| new_flow["customer_type"] = "new" |
| new_flow["audience"] = "adults" |
| return ask_prior_study_reply(new_flow) |
|
|
| if value == "new_student": |
| new_flow = dict(flow_data) |
| new_flow["customer_type"] = "new" |
| return ask_audience_reply(new_flow) |
|
|
| if value == "current_student": |
| new_flow = dict(flow_data) |
| new_flow["customer_type"] = "current" |
| return current_student_menu_reply(new_flow) |
|
|
| |
| |
| |
| if state == START: |
| return greeting_main_menu_reply(flow_data) |
|
|
| |
| |
| |
| if state == WAITING_MAIN_MENU: |
| return ask_new_or_current_reply(flow_data) |
|
|
| |
| |
| |
| if state == WAITING_USER_TYPE: |
| if kind == "direct_answer" and value == "new_student": |
| flow_data.update(entities) |
| return ask_audience_reply(flow_data) |
|
|
| if kind == "direct_answer" and value == "current_student": |
| flow_data.update(entities) |
| return current_student_menu_reply(flow_data) |
|
|
| return { |
| "next_state": WAITING_USER_TYPE, |
| "flow_data": flow_data, |
| "reply": "تمام، محتاج أعرف الأول: إنت طالب جديد ولا طالب حالي؟" |
| } |
|
|
| |
| |
| |
| if state == WAITING_AUDIENCE: |
| if kind == "direct_answer" and value == "adults": |
| flow_data.update(entities) |
| return ask_prior_study_reply(flow_data) |
|
|
| if kind == "direct_answer" and value == "children": |
| flow_data.update(entities) |
| return ask_prior_study_reply(flow_data) |
|
|
| return { |
| "next_state": WAITING_AUDIENCE, |
| "flow_data": flow_data, |
| "reply": "تمام، الكورس للكبار ولا للأطفال؟" |
| } |
|
|
| |
| |
| |
| if state == WAITING_PRIOR_STUDY: |
| if kind == "direct_answer" and value == "prior_study_no": |
| flow_data.update(entities) |
| return beginner_schedule_reply(flow_data) |
|
|
| if kind == "direct_answer" and value == "prior_study_yes": |
| flow_data.update(entities) |
| return placement_test_reply(flow_data) |
|
|
| return { |
| "next_state": WAITING_PRIOR_STUDY, |
| "flow_data": flow_data, |
| "reply": "هل درست اللغة الألمانية قبل كده؟ رد بنعم أو لا." |
| } |
|
|
| |
| |
| |
| if state == WAITING_BEGINNER_SCHEDULE_CHOICE: |
| if kind == "state_switch" and value == "switch_to_prior_study_true": |
| new_flow = dict(flow_data) |
| new_flow.update(entities) |
| return placement_test_reply(new_flow) |
|
|
| if kind == "state_switch" and value == "switch_to_prior_study_false": |
| new_flow = dict(flow_data) |
| new_flow.update(entities) |
| return beginner_schedule_reply(new_flow) |
|
|
| if kind == "state_switch" and value == "support_needed": |
| return create_support_handoff_result( |
| flow_data=flow_data, |
| summary="استفسار عن مواعيد كورسات المبتدئين" |
| ) |
|
|
| if kind == "direct_answer" and value in ["confirm_schedule_reviewed", "proceed_booking"]: |
| return pdf_102_reply(flow_data) |
|
|
| if kind == "unclear": |
| return { |
| "next_state": WAITING_BEGINNER_SCHEDULE_CHOICE, |
| "flow_data": flow_data, |
| "reply": "تقصد تكمل الحجز، ولا بتسأل عن حالة لو كنت درست ألماني قبل كده؟" |
| } |
|
|
| |
| |
| |
| if state == WAITING_PDF_102_CONFIRMATION: |
| if kind == "state_switch" and value == "switch_to_prior_study_true": |
| new_flow = dict(flow_data) |
| new_flow.update(entities) |
| return placement_test_reply(new_flow) |
|
|
| if kind == "state_switch" and value == "switch_to_prior_study_false": |
| new_flow = dict(flow_data) |
| new_flow.update(entities) |
| return beginner_schedule_reply(new_flow) |
|
|
| if kind == "state_switch" and value == "support_needed": |
| return create_support_handoff_result( |
| flow_data=flow_data, |
| summary="استفسار بعد إرسال ملف 102" |
| ) |
|
|
| if kind == "direct_answer" and value == "confirm_pdf_reviewed": |
| return payment_methods_reply(flow_data) |
|
|
| return { |
| "next_state": WAITING_PDF_102_CONFIRMATION, |
| "flow_data": flow_data, |
| "reply": "بعد ما تطلع على الملف، ابعتلي تم عشان أكمل معاك إجراءات الدفع والحجز." |
| } |
|
|
| |
| |
| |
| if state == WAITING_PLACEMENT_TEST_CONFIRMATION: |
| if kind == "state_switch" and value == "switch_to_prior_study_false": |
| new_flow = dict(flow_data) |
| new_flow.update(entities) |
| return beginner_schedule_reply(new_flow) |
|
|
| if kind == "state_switch" and value == "switch_to_prior_study_true": |
| new_flow = dict(flow_data) |
| new_flow.update(entities) |
| return placement_test_reply(new_flow) |
|
|
| if kind == "state_switch" and value == "support_needed": |
| return create_support_handoff_result( |
| flow_data=flow_data, |
| summary="استفسار عن اختبار تحديد المستوى" |
| ) |
|
|
| if kind == "direct_answer" and value == "confirm_placement_test_reviewed": |
| return create_sales_handoff_result( |
| flow_data=flow_data, |
| summary="عميل اختار أو مهتم باختبار تحديد مستوى" |
| ) |
|
|
| return { |
| "next_state": WAITING_PLACEMENT_TEST_CONFIRMATION, |
| "flow_data": flow_data, |
| "reply": "بعد ما تراجع مواعيد اختبار تحديد المستوى، ابعتلي تم أو قولّي لو محتاج مساعدة." |
| } |
|
|
| |
| |
| |
| if state == WAITING_CURRENT_STUDENT_ACTION: |
| if kind == "direct_answer" and value == "current_student_support": |
| return support_question_reply(flow_data) |
|
|
| if kind == "direct_answer" and value == "current_student_next_level": |
| return ask_level_selection_reply(flow_data) |
|
|
| return { |
| "next_state": WAITING_CURRENT_STUDENT_ACTION, |
| "flow_data": flow_data, |
| "reply": "تحب استفسار بخصوص الكورس ولا حجز المستوى التالي؟" |
| } |
|
|
| |
| |
| |
| if state == WAITING_SUPPORT_QUESTION: |
| if kind == "direct_answer" and value == "support_question_text": |
| flow_data.update(entities) |
| return create_support_handoff_result( |
| flow_data=flow_data, |
| summary=f"استفسار طالب حالي: {text}" |
| ) |
|
|
| return { |
| "next_state": WAITING_SUPPORT_QUESTION, |
| "flow_data": flow_data, |
| "reply": "اكتبلي استفسارك بالتفصيل، وأنا هرفعه لفريق خدمة العملاء." |
| } |
|
|
| |
| |
| |
| if state == WAITING_LEVEL_SELECTION: |
| if kind == "direct_answer" and value == "level_selected": |
| flow_data.update(entities) |
| return payment_methods_reply(flow_data) |
|
|
| if kind == "state_switch" and value == "support_needed": |
| 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." |
| } |
|
|
| |
| |
| |
| if state == WAITING_PAYMENT_METHOD: |
| if kind == "direct_answer" and value == "payment_method_selected": |
| flow_data.update(entities) |
|
|
| payment_method = flow_data.get("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 kind == "state_switch" and value == "support_needed": |
| 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." |
| } |
|
|
| |
| |
| |
| if state == WAITING_COMPLAINT_FORM: |
| if kind == "direct_answer" and value == "complaint_form_submitted": |
| return { |
| "next_state": WAITING_COMPLAINT_FORM, |
| "flow_data": flow_data, |
| "reply": "تمام، بعد مراجعة الشكوى هيتم التواصل معاك. ولو حابب تكتب أي تفاصيل إضافية ابعتها هنا." |
| } |
|
|
| return { |
| "next_state": WAITING_COMPLAINT_FORM, |
| "flow_data": flow_data, |
| "reply": "سجّل الشكوى من الفورم أولًا، ولو احتجت مساعدة ابعتلي." |
| } |
|
|
| |
| |
| |
| if state == HANDOFF_DONE: |
| if kind == "direct_answer" and value == "thanks": |
| return { |
| "next_state": HANDOFF_DONE, |
| "flow_data": flow_data, |
| "reply": "العفو، تحت أمرك في أي وقت." |
| } |
|
|
| if kind == "topic_switch": |
| if value in ["restart", "new_topic", "courses_info"]: |
| return { |
| "next_state": WAITING_MAIN_MENU, |
| "flow_data": {}, |
| "reply": "تمام، نبدأ من جديد. إنت طالب جديد ولا طالب حالي؟" |
| } |
|
|
| if value == "children_courses": |
| new_flow = {} |
| new_flow["customer_type"] = "new" |
| new_flow["audience"] = "children" |
| return ask_prior_study_reply(new_flow) |
|
|
| if value == "adults_courses": |
| new_flow = {} |
| new_flow["customer_type"] = "new" |
| new_flow["audience"] = "adults" |
| return ask_prior_study_reply(new_flow) |
|
|
| if value == "new_student": |
| new_flow = {} |
| new_flow["customer_type"] = "new" |
| return ask_audience_reply(new_flow) |
|
|
| if value == "current_student": |
| new_flow = {} |
| new_flow["customer_type"] = "current" |
| return current_student_menu_reply(new_flow) |
|
|
| if value == "direct_support": |
| return create_support_handoff_result( |
| flow_data=flow_data, |
| summary=f"استفسار إضافي بعد handoff: {text}" |
| ) |
|
|
| if value == "complaint": |
| return create_complaint_flow_result(flow_data) |
|
|
| return { |
| "next_state": HANDOFF_DONE, |
| "flow_data": flow_data, |
| "reply": ( |
| "تم تسجيل طلبك بالفعل، وفريقنا هيتواصل معاك قريب.\n" |
| "ولو تحب تبدأ استفسار جديد، اكتب: ابدأ من جديد." |
| ) |
| } |
|
|
| return unknown_reply(flow_data) |