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("============================================") # ========================= # Global topic switches # ========================= 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) # ========================= # START # ========================= if state == START: return greeting_main_menu_reply(flow_data) # ========================= # WAITING_MAIN_MENU # ========================= if state == WAITING_MAIN_MENU: return ask_new_or_current_reply(flow_data) # ========================= # WAITING_USER_TYPE # ========================= 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": "تمام، محتاج أعرف الأول: إنت طالب جديد ولا طالب حالي؟" } # ========================= # WAITING_AUDIENCE # ========================= 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": "تمام، الكورس للكبار ولا للأطفال؟" } # ========================= # WAITING_PRIOR_STUDY # ========================= 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": "هل درست اللغة الألمانية قبل كده؟ رد بنعم أو لا." } # ========================= # WAITING_BEGINNER_SCHEDULE_CHOICE # ========================= 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": "تقصد تكمل الحجز، ولا بتسأل عن حالة لو كنت درست ألماني قبل كده؟" } # ========================= # WAITING_PDF_102_CONFIRMATION # ========================= 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": "بعد ما تطلع على الملف، ابعتلي تم عشان أكمل معاك إجراءات الدفع والحجز." } # ========================= # WAITING_PLACEMENT_TEST_CONFIRMATION # ========================= 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": "بعد ما تراجع مواعيد اختبار تحديد المستوى، ابعتلي تم أو قولّي لو محتاج مساعدة." } # ========================= # WAITING_CURRENT_STUDENT_ACTION # ========================= 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": "تحب استفسار بخصوص الكورس ولا حجز المستوى التالي؟" } # ========================= # WAITING_SUPPORT_QUESTION # ========================= 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": "اكتبلي استفسارك بالتفصيل، وأنا هرفعه لفريق خدمة العملاء." } # ========================= # WAITING_LEVEL_SELECTION # ========================= 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." } # ========================= # WAITING_PAYMENT_METHOD # ========================= 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." } # ========================= # WAITING_COMPLAINT_FORM # ========================= 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": "سجّل الشكوى من الفورم أولًا، ولو احتجت مساعدة ابعتلي." } # ========================= # HANDOFF_DONE # ========================= 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)