Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -3816,9 +3816,13 @@ async def display_all_products(from_number: str):
|
|
| 3816 |
user_context = context_manager.get_context(from_number)
|
| 3817 |
current_state = user_context.get('current_state', 'main_menu')
|
| 3818 |
logger.info(f"[Display] display_all_products called for {from_number} in state: {current_state}")
|
|
|
|
|
|
|
|
|
|
| 3819 |
if products_df is None or products_df.empty:
|
| 3820 |
send_whatsjet_message(from_number, "β No products available at the moment.")
|
| 3821 |
return
|
|
|
|
| 3822 |
products = products_df.to_dict('records')
|
| 3823 |
context_manager.update_context(
|
| 3824 |
from_number,
|
|
@@ -3828,6 +3832,7 @@ async def display_all_products(from_number: str):
|
|
| 3828 |
available_products=products
|
| 3829 |
)
|
| 3830 |
logger.info(f"[Display] Set state to all_products_menu for {from_number}")
|
|
|
|
| 3831 |
chunk_size = 5
|
| 3832 |
for i in range(0, len(products), chunk_size):
|
| 3833 |
chunk = products[i:i + chunk_size]
|
|
@@ -3839,7 +3844,7 @@ async def display_all_products(from_number: str):
|
|
| 3839 |
message += "\n"
|
| 3840 |
send_whatsjet_message(from_number, message)
|
| 3841 |
send_whatsjet_message(from_number,
|
| 3842 |
-
"π¬ Type a product
|
| 3843 |
except Exception as e:
|
| 3844 |
logger.error(f"[Display] Error displaying products: {e}")
|
| 3845 |
send_whatsjet_message(from_number, "β Error displaying products. Please try again.")
|
|
@@ -3897,111 +3902,80 @@ async def handle_category_selection(selection: str, from_number: str):
|
|
| 3897 |
send_helpful_guidance(from_number, 'category_selection_menu')
|
| 3898 |
|
| 3899 |
def get_menu_validation_message(current_state: str, user_context: dict) -> str:
|
| 3900 |
-
"""Get
|
| 3901 |
if current_state == 'main_menu':
|
| 3902 |
return (
|
| 3903 |
-
"
|
| 3904 |
-
"Please
|
| 3905 |
-
"π *Available Options:*\n"
|
| 3906 |
"1οΈβ£ Search Veterinary Products\n"
|
| 3907 |
"2οΈβ£ Browse Categories\n"
|
| 3908 |
"3οΈβ£ Download Catalog\n"
|
| 3909 |
"4οΈβ£ Chat with Veterinary AI Assistant\n\n"
|
| 3910 |
-
"
|
| 3911 |
"β’ Type a product name (e.g., 'hydropex', 'respira aid plus')\n"
|
| 3912 |
-
"β’ Type 'main' to refresh the menu
|
| 3913 |
-
"β’ Ask about symptoms or categories"
|
| 3914 |
)
|
| 3915 |
elif current_state == 'all_products_menu':
|
| 3916 |
if products_df is not None and not products_df.empty:
|
| 3917 |
total_products = len(products_df)
|
| 3918 |
return (
|
| 3919 |
-
f"
|
| 3920 |
f"Please choose a product number between 1 and {total_products}.\n\n"
|
| 3921 |
-
"
|
| 3922 |
-
"β’ Type a
|
| 3923 |
-
"β’ Type 'main' to return to main menu
|
| 3924 |
-
"β’ Ask about product categories"
|
| 3925 |
)
|
| 3926 |
else:
|
| 3927 |
-
return
|
| 3928 |
-
"β οΈ *No Products Available*\n\n"
|
| 3929 |
-
"Currently no products are loaded in the system.\n\n"
|
| 3930 |
-
"π‘ *Please:*\n"
|
| 3931 |
-
"β’ Type 'main' to return to main menu\n"
|
| 3932 |
-
"β’ Contact support if this issue persists"
|
| 3933 |
-
)
|
| 3934 |
elif current_state == 'category_products_menu':
|
| 3935 |
available_products = user_context.get('available_products', [])
|
| 3936 |
if available_products:
|
| 3937 |
return (
|
| 3938 |
-
f"
|
| 3939 |
f"Please choose a product number between 1 and {len(available_products)}.\n\n"
|
| 3940 |
-
"
|
| 3941 |
-
"β’ Type a
|
| 3942 |
-
"β’ Type 'main' to return to main menu
|
| 3943 |
-
"β’ Browse other categories"
|
| 3944 |
)
|
| 3945 |
else:
|
| 3946 |
-
return
|
| 3947 |
-
"β οΈ *No Products in Category*\n\n"
|
| 3948 |
-
"This category currently has no available products.\n\n"
|
| 3949 |
-
"π‘ *Please:*\n"
|
| 3950 |
-
"β’ Type 'main' to return to main menu\n"
|
| 3951 |
-
"β’ Browse other categories\n"
|
| 3952 |
-
"β’ Ask about specific products"
|
| 3953 |
-
)
|
| 3954 |
elif current_state == 'category_selection_menu':
|
| 3955 |
available_categories = user_context.get('available_categories', [])
|
| 3956 |
if available_categories:
|
| 3957 |
return (
|
| 3958 |
-
f"
|
| 3959 |
f"Please choose a category number between 1 and {len(available_categories)}.\n\n"
|
| 3960 |
-
"
|
| 3961 |
-
"β’ Type a
|
| 3962 |
-
"β’ Type 'main' to return to main menu
|
| 3963 |
-
"β’ Ask about product types"
|
| 3964 |
)
|
| 3965 |
else:
|
| 3966 |
-
return
|
| 3967 |
-
"β οΈ *No Categories Available*\n\n"
|
| 3968 |
-
"Currently no product categories are available.\n\n"
|
| 3969 |
-
"π‘ *Please:*\n"
|
| 3970 |
-
"β’ Type 'main' to return to main menu\n"
|
| 3971 |
-
"β’ Ask about specific products\n"
|
| 3972 |
-
"β’ Contact support if needed"
|
| 3973 |
-
)
|
| 3974 |
elif current_state == 'product_inquiry':
|
| 3975 |
return (
|
| 3976 |
-
"
|
| 3977 |
-
"Please choose
|
| 3978 |
-
"π *Available Actions:*\n"
|
| 3979 |
"1οΈβ£ Talk to Veterinary Consultant\n"
|
| 3980 |
"2οΈβ£ Inquire About Availability\n"
|
| 3981 |
"3οΈβ£ Back to Main Menu\n\n"
|
| 3982 |
-
"
|
| 3983 |
-
"β’ Type
|
| 3984 |
-
"β’ Type 'main' to return to main menu
|
| 3985 |
-
"β’ Ask about related products"
|
| 3986 |
)
|
| 3987 |
elif current_state == 'intelligent_products_menu':
|
| 3988 |
-
available_products = user_context.get('available_products', [])
|
| 3989 |
return (
|
| 3990 |
-
|
| 3991 |
-
|
| 3992 |
-
"
|
| 3993 |
-
"β’ Type a
|
| 3994 |
-
"β’ Type 'main' to return to main menu
|
| 3995 |
-
"β’ Ask about different categories"
|
| 3996 |
)
|
| 3997 |
else:
|
| 3998 |
return (
|
| 3999 |
-
"
|
| 4000 |
"Please choose a valid option or type 'main' to return to main menu.\n\n"
|
| 4001 |
-
"
|
| 4002 |
-
"β’ Type a product name (e.g., 'hydropex', 'respira aid plus')
|
| 4003 |
-
"β’ Type 'main' to return to main menu\n"
|
| 4004 |
-
"β’ Ask about veterinary products or categories"
|
| 4005 |
)
|
| 4006 |
|
| 4007 |
def is_valid_menu_selection(selection: str, current_state: str, user_context: dict) -> bool:
|
|
@@ -4009,39 +3983,6 @@ def is_valid_menu_selection(selection: str, current_state: str, user_context: di
|
|
| 4009 |
is_valid, _ = validate_menu_selection(selection, current_state, user_context)
|
| 4010 |
return is_valid
|
| 4011 |
|
| 4012 |
-
def get_irrelevant_query_response(query: str, current_state: str, reply_language: str = 'en') -> str:
|
| 4013 |
-
"""Get professional response for irrelevant or unclear queries"""
|
| 4014 |
-
if reply_language == 'ur':
|
| 4015 |
-
return (
|
| 4016 |
-
"π€ *Apex Biotical Veterinary Assistant*\n\n"
|
| 4017 |
-
"Ψ’ΩΎ Ϊ©Ψ§ Ψ³ΩΨ§Ω ΩΨ§ΨΆΨ ΩΫΫΪΊ ΫΫ ΫΨ§ ΫΫ ΩΫΩΉΨ±ΩΨ±Ϋ Ω
Ψ΅ΩΩΨΉΨ§Ψͺ Ψ³Ϋ Ω
ΨͺΨΉΩΩ ΩΫΫΪΊ ΫΫΫ\n\n"
|
| 4018 |
-
"π‘ *Ω
ΫΪΊ Ψ’ΩΎ Ϊ©Ϋ Ω
Ψ―Ψ― Ϊ©Ψ± Ψ³Ϊ©ΨͺΨ§ ΫΩΪΊ:*\n"
|
| 4019 |
-
"β’ ΩΫΩΉΨ±ΩΨ±Ϋ Ω
Ψ΅ΩΩΨΉΨ§Ψͺ Ϊ©Ϋ Ψ¨Ψ§Ψ±Ϋ Ω
ΫΪΊ Ω
ΨΉΩΩΩ
Ψ§Ψͺ\n"
|
| 4020 |
-
"β’ Ω
Ψ΅ΩΩΨΉΨ§Ψͺ Ϊ©Ϋ ΨͺΩΨ§Ψ΄ Ψ§ΩΨ± Ψ¨Ψ±Ψ§Ψ€Ψ²\n"
|
| 4021 |
-
"β’ ΩΫΩΉΨ±ΩΨ±Ϋ Ω
Ψ΄ΩΨ±Ϋ Ψ§ΩΨ± Ψ±ΫΩΩ
Ψ§Ψ¦Ϋ\n"
|
| 4022 |
-
"β’ Ω
Ψ΅ΩΩΨΉΨ§Ψͺ Ϊ©Ϋ Ψ―Ψ³ΨͺΫΨ§Ψ¨Ϋ Ϊ©Ϋ Ψ¨Ψ§Ψ±Ϋ Ω
ΫΪΊ ΩΎΩΪΪΎΩΨ§\n\n"
|
| 4023 |
-
"π *Ω
Ψ«Ψ§Ω Ϊ©Ϋ Ψ·ΩΨ± ΩΎΨ±:*\n"
|
| 4024 |
-
"β’ 'hydropex Ϊ©Ϋ Ψ¨Ψ§Ψ±Ϋ Ω
ΫΪΊ Ψ¨ΨͺΨ§Ψ¦ΫΪΊ'\n"
|
| 4025 |
-
"β’ 'Ψ³Ψ§ΩΨ³ Ϊ©Ϋ Ω
Ψ΅ΩΩΨΉΨ§Ψͺ Ϊ©ΩΩ Ψ³Ϋ ΫΫΪΊΨ'\n"
|
| 4026 |
-
"β’ 'main' ΩΪ©ΪΎ Ϊ©Ψ± Ω
ΫΩ Ω
ΫΩΩ ΩΎΨ± Ψ¬Ψ§Ψ¦ΫΪΊ"
|
| 4027 |
-
)
|
| 4028 |
-
else:
|
| 4029 |
-
return (
|
| 4030 |
-
"π€ *Apex Biotical Veterinary Assistant*\n\n"
|
| 4031 |
-
"I'm here to help you with veterinary products and information. "
|
| 4032 |
-
"Your query doesn't seem to be related to our veterinary services.\n\n"
|
| 4033 |
-
"π‘ *I can help you with:*\n"
|
| 4034 |
-
"β’ Information about veterinary products\n"
|
| 4035 |
-
"β’ Product search and browsing\n"
|
| 4036 |
-
"β’ Veterinary advice and guidance\n"
|
| 4037 |
-
"β’ Product availability inquiries\n\n"
|
| 4038 |
-
"π *Examples of what you can ask:*\n"
|
| 4039 |
-
"β’ 'Tell me about hydropex'\n"
|
| 4040 |
-
"β’ 'What respiratory products do you have?'\n"
|
| 4041 |
-
"β’ 'Show me all antibiotics'\n"
|
| 4042 |
-
"β’ Type 'main' to return to main menu"
|
| 4043 |
-
)
|
| 4044 |
-
|
| 4045 |
def generate_veterinary_welcome_message(phone_number=None, user_context=None):
|
| 4046 |
"""Generate veterinary welcome message"""
|
| 4047 |
return (
|
|
@@ -4072,11 +4013,6 @@ async def handle_veterinary_product_followup(selection: str, from_number: str) -
|
|
| 4072 |
send_whatsjet_message(from_number, "β No product selected. Please search for a product first.")
|
| 4073 |
return
|
| 4074 |
|
| 4075 |
-
# Validate that the selection is a valid follow-up option (1, 2, or 3)
|
| 4076 |
-
if selection not in ['1', '2', '3']:
|
| 4077 |
-
send_whatsjet_message(from_number, "β Invalid selection. Please choose 1, 2, or 3.")
|
| 4078 |
-
return
|
| 4079 |
-
|
| 4080 |
if selection == '1':
|
| 4081 |
# Talk to Veterinary Consultant
|
| 4082 |
product_name = current_product.get('Product Name', 'the selected product')
|
|
@@ -4096,11 +4032,9 @@ async def handle_veterinary_product_followup(selection: str, from_number: str) -
|
|
| 4096 |
current_menu='contact_request',
|
| 4097 |
current_menu_options=['Provide contact details']
|
| 4098 |
)
|
| 4099 |
-
|
| 4100 |
elif selection == '2':
|
| 4101 |
# Inquire about Product Availability
|
| 4102 |
await handle_availability_inquiry(from_number, user_context)
|
| 4103 |
-
|
| 4104 |
elif selection == '3':
|
| 4105 |
welcome_msg = generate_veterinary_welcome_message(from_number, user_context)
|
| 4106 |
send_whatsjet_message(from_number, welcome_msg)
|
|
@@ -4111,6 +4045,9 @@ async def handle_veterinary_product_followup(selection: str, from_number: str) -
|
|
| 4111 |
current_menu_options=list(MENU_CONFIG['main_menu']['option_descriptions'].values())
|
| 4112 |
)
|
| 4113 |
return
|
|
|
|
|
|
|
|
|
|
| 4114 |
except Exception as e:
|
| 4115 |
logger.error(f"Error in product follow-up: {e}")
|
| 4116 |
user_context = context_manager.get_context(from_number)
|
|
|
|
| 3816 |
user_context = context_manager.get_context(from_number)
|
| 3817 |
current_state = user_context.get('current_state', 'main_menu')
|
| 3818 |
logger.info(f"[Display] display_all_products called for {from_number} in state: {current_state}")
|
| 3819 |
+
if current_state == 'all_products_menu':
|
| 3820 |
+
logger.warning(f"[Display] Already in all_products_menu state for {from_number}, skipping display")
|
| 3821 |
+
return
|
| 3822 |
if products_df is None or products_df.empty:
|
| 3823 |
send_whatsjet_message(from_number, "β No products available at the moment.")
|
| 3824 |
return
|
| 3825 |
+
# Set state to all_products_menu and store menu context
|
| 3826 |
products = products_df.to_dict('records')
|
| 3827 |
context_manager.update_context(
|
| 3828 |
from_number,
|
|
|
|
| 3832 |
available_products=products
|
| 3833 |
)
|
| 3834 |
logger.info(f"[Display] Set state to all_products_menu for {from_number}")
|
| 3835 |
+
# Send products in chunks
|
| 3836 |
chunk_size = 5
|
| 3837 |
for i in range(0, len(products), chunk_size):
|
| 3838 |
chunk = products[i:i + chunk_size]
|
|
|
|
| 3844 |
message += "\n"
|
| 3845 |
send_whatsjet_message(from_number, message)
|
| 3846 |
send_whatsjet_message(from_number,
|
| 3847 |
+
"π¬ Type a product name to get detailed information, or type 'main' to return to main menu.")
|
| 3848 |
except Exception as e:
|
| 3849 |
logger.error(f"[Display] Error displaying products: {e}")
|
| 3850 |
send_whatsjet_message(from_number, "β Error displaying products. Please try again.")
|
|
|
|
| 3902 |
send_helpful_guidance(from_number, 'category_selection_menu')
|
| 3903 |
|
| 3904 |
def get_menu_validation_message(current_state: str, user_context: dict) -> str:
|
| 3905 |
+
"""Get appropriate validation message for current menu state"""
|
| 3906 |
if current_state == 'main_menu':
|
| 3907 |
return (
|
| 3908 |
+
"β *Invalid Selection*\n\n"
|
| 3909 |
+
"Please choose from the main menu:\n"
|
|
|
|
| 3910 |
"1οΈβ£ Search Veterinary Products\n"
|
| 3911 |
"2οΈβ£ Browse Categories\n"
|
| 3912 |
"3οΈβ£ Download Catalog\n"
|
| 3913 |
"4οΈβ£ Chat with Veterinary AI Assistant\n\n"
|
| 3914 |
+
"π¬ *You can also:*\n"
|
| 3915 |
"β’ Type a product name (e.g., 'hydropex', 'respira aid plus')\n"
|
| 3916 |
+
"β’ Type 'main' to refresh the menu"
|
|
|
|
| 3917 |
)
|
| 3918 |
elif current_state == 'all_products_menu':
|
| 3919 |
if products_df is not None and not products_df.empty:
|
| 3920 |
total_products = len(products_df)
|
| 3921 |
return (
|
| 3922 |
+
f"β *Invalid Product Selection*\n\n"
|
| 3923 |
f"Please choose a product number between 1 and {total_products}.\n\n"
|
| 3924 |
+
"π¬ *You can also:*\n"
|
| 3925 |
+
"β’ Type a product name (e.g., 'hydropex', 'respira aid plus')\n"
|
| 3926 |
+
"β’ Type 'main' to return to main menu"
|
|
|
|
| 3927 |
)
|
| 3928 |
else:
|
| 3929 |
+
return "β No products available. Type 'main' to return to main menu."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3930 |
elif current_state == 'category_products_menu':
|
| 3931 |
available_products = user_context.get('available_products', [])
|
| 3932 |
if available_products:
|
| 3933 |
return (
|
| 3934 |
+
f"β *Invalid Product Selection*\n\n"
|
| 3935 |
f"Please choose a product number between 1 and {len(available_products)}.\n\n"
|
| 3936 |
+
"π¬ *You can also:*\n"
|
| 3937 |
+
"β’ Type a product name (e.g., 'hydropex', 'respira aid plus')\n"
|
| 3938 |
+
"β’ Type 'main' to return to main menu"
|
|
|
|
| 3939 |
)
|
| 3940 |
else:
|
| 3941 |
+
return "β No products available in this category. Type 'main' to return to main menu."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3942 |
elif current_state == 'category_selection_menu':
|
| 3943 |
available_categories = user_context.get('available_categories', [])
|
| 3944 |
if available_categories:
|
| 3945 |
return (
|
| 3946 |
+
f"β *Invalid Category Selection*\n\n"
|
| 3947 |
f"Please choose a category number between 1 and {len(available_categories)}.\n\n"
|
| 3948 |
+
"π¬ *You can also:*\n"
|
| 3949 |
+
"β’ Type a product name (e.g., 'hydropex', 'respira aid plus')\n"
|
| 3950 |
+
"β’ Type 'main' to return to main menu"
|
|
|
|
| 3951 |
)
|
| 3952 |
else:
|
| 3953 |
+
return "β No categories available. Type 'main' to return to main menu."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3954 |
elif current_state == 'product_inquiry':
|
| 3955 |
return (
|
| 3956 |
+
"β *Invalid Selection*\n\n"
|
| 3957 |
+
"Please choose an option:\n"
|
|
|
|
| 3958 |
"1οΈβ£ Talk to Veterinary Consultant\n"
|
| 3959 |
"2οΈβ£ Inquire About Availability\n"
|
| 3960 |
"3οΈβ£ Back to Main Menu\n\n"
|
| 3961 |
+
"π¬ *You can also:*\n"
|
| 3962 |
+
"β’ Type a product name (e.g., 'hydropex', 'respira aid plus')\n"
|
| 3963 |
+
"β’ Type 'main' to return to main menu"
|
|
|
|
| 3964 |
)
|
| 3965 |
elif current_state == 'intelligent_products_menu':
|
|
|
|
| 3966 |
return (
|
| 3967 |
+
"β *Invalid Selection*\n\n"
|
| 3968 |
+
"Please choose a product number between 1 and {len(available_products)}.\n\n"
|
| 3969 |
+
"π¬ *You can also:*\n"
|
| 3970 |
+
"β’ Type a product name (e.g., 'hydropex', 'respira aid plus')\n"
|
| 3971 |
+
"β’ Type 'main' to return to main menu"
|
|
|
|
| 3972 |
)
|
| 3973 |
else:
|
| 3974 |
return (
|
| 3975 |
+
"β *Invalid Selection*\n\n"
|
| 3976 |
"Please choose a valid option or type 'main' to return to main menu.\n\n"
|
| 3977 |
+
"π¬ *You can also:*\n"
|
| 3978 |
+
"β’ Type a product name (e.g., 'hydropex', 'respira aid plus')"
|
|
|
|
|
|
|
| 3979 |
)
|
| 3980 |
|
| 3981 |
def is_valid_menu_selection(selection: str, current_state: str, user_context: dict) -> bool:
|
|
|
|
| 3983 |
is_valid, _ = validate_menu_selection(selection, current_state, user_context)
|
| 3984 |
return is_valid
|
| 3985 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3986 |
def generate_veterinary_welcome_message(phone_number=None, user_context=None):
|
| 3987 |
"""Generate veterinary welcome message"""
|
| 3988 |
return (
|
|
|
|
| 4013 |
send_whatsjet_message(from_number, "β No product selected. Please search for a product first.")
|
| 4014 |
return
|
| 4015 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4016 |
if selection == '1':
|
| 4017 |
# Talk to Veterinary Consultant
|
| 4018 |
product_name = current_product.get('Product Name', 'the selected product')
|
|
|
|
| 4032 |
current_menu='contact_request',
|
| 4033 |
current_menu_options=['Provide contact details']
|
| 4034 |
)
|
|
|
|
| 4035 |
elif selection == '2':
|
| 4036 |
# Inquire about Product Availability
|
| 4037 |
await handle_availability_inquiry(from_number, user_context)
|
|
|
|
| 4038 |
elif selection == '3':
|
| 4039 |
welcome_msg = generate_veterinary_welcome_message(from_number, user_context)
|
| 4040 |
send_whatsjet_message(from_number, welcome_msg)
|
|
|
|
| 4045 |
current_menu_options=list(MENU_CONFIG['main_menu']['option_descriptions'].values())
|
| 4046 |
)
|
| 4047 |
return
|
| 4048 |
+
else:
|
| 4049 |
+
send_whatsjet_message(from_number, "β Invalid selection. Please choose 1, 2, or 3.")
|
| 4050 |
+
return
|
| 4051 |
except Exception as e:
|
| 4052 |
logger.error(f"Error in product follow-up: {e}")
|
| 4053 |
user_context = context_manager.get_context(from_number)
|