DreamStream-1 commited on
Commit
1f2c15f
Β·
verified Β·
1 Parent(s): 81e978e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +467 -15
app.py CHANGED
@@ -147,11 +147,13 @@ MENU_CONFIG = {
147
  },
148
  'product_inquiry': {
149
  'name': 'Product Inquiry Menu',
150
- 'valid_options': ['1', '2', '3'],
151
  'option_descriptions': {
152
  '1': 'Talk to Veterinary Consultant',
153
  '2': 'Inquire about Product Availability',
154
- '3': 'Back to Main Menu'
 
 
155
  }
156
  },
157
  'ai_chat': {
@@ -2367,7 +2369,8 @@ async def handle_contact_request_response(from_number: str, response: str):
2367
  )
2368
  except Exception as e:
2369
  logger.error(f"[Contact] Error handling contact response: {e}")
2370
- # Instead of sending a generic error, return to main menu
 
2371
  welcome_msg = generate_veterinary_welcome_message(from_number, user_context)
2372
  send_whatsjet_message(from_number, welcome_msg)
2373
  context_manager.update_context(
@@ -2471,7 +2474,8 @@ async def handle_availability_request_response(from_number: str, response: str):
2471
  )
2472
  except Exception as e:
2473
  logger.error(f"[Availability] Error handling availability response: {e}")
2474
- # Instead of sending a generic error, return to main menu
 
2475
  welcome_msg = generate_veterinary_welcome_message(from_number, user_context)
2476
  send_whatsjet_message(from_number, welcome_msg)
2477
  context_manager.update_context(
@@ -2535,6 +2539,8 @@ def send_helpful_guidance(from_number: str, current_state: str):
2535
  )
2536
  except Exception as e:
2537
  logger.error(f"Error sending helpful guidance: {e}")
 
 
2538
  welcome_msg = generate_veterinary_welcome_message(from_number, user_context)
2539
  send_whatsjet_message(from_number, welcome_msg)
2540
  context_manager.update_context(
@@ -2847,7 +2853,6 @@ def generate_veterinary_welcome_message(phone_number=None, user_context=None):
2847
 
2848
  @app.get("/test-whatsjet")
2849
  async def test_whatsjet():
2850
- import requests
2851
  try:
2852
  resp = requests.get("https://api.whatsjet.com", timeout=5)
2853
  return {"status": resp.status_code, "text": resp.text[:200]}
@@ -2948,10 +2953,13 @@ async def handle_veterinary_product_followup(selection: str, from_number: str) -
2948
  user_context = context_manager.get_context(from_number)
2949
  current_product = user_context.get('current_product')
2950
 
 
 
 
 
2951
  if selection == '1':
2952
  # Talk to Veterinary Consultant
2953
- current_product = user_context.get('current_product')
2954
- product_name = current_product.get('Product Name', 'the selected product') if current_product else 'the selected product'
2955
  consultant_msg = (
2956
  f"πŸ“ž Contact Veterinary Consultant\n\n"
2957
  f"Product: {product_name}\n\n"
@@ -2962,10 +2970,44 @@ async def handle_veterinary_product_followup(selection: str, from_number: str) -
2962
  "Type main at any time to go to main menu."
2963
  )
2964
  send_whatsjet_message(from_number, consultant_msg)
 
 
 
 
 
 
 
2965
  elif selection == '2':
2966
  # Inquire about Product Availability
2967
  await handle_availability_inquiry(from_number, user_context)
 
2968
  elif selection == '3':
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2969
  # Back to Main Menu
2970
  welcome_msg = generate_veterinary_welcome_message(from_number, user_context)
2971
  send_whatsjet_message(from_number, welcome_msg)
@@ -2977,10 +3019,11 @@ async def handle_veterinary_product_followup(selection: str, from_number: str) -
2977
  )
2978
  return
2979
  else:
2980
- send_whatsjet_message(from_number, "❌ Invalid selection. Please choose 1, 2, or 3.")
2981
  return
2982
  except Exception as e:
2983
  logger.error(f"Error in product follow-up: {e}")
 
2984
  welcome_msg = generate_veterinary_welcome_message(from_number, user_context)
2985
  send_whatsjet_message(from_number, welcome_msg)
2986
  context_manager.update_context(
@@ -2993,7 +3036,7 @@ async def handle_veterinary_product_followup(selection: str, from_number: str) -
2993
  # Enhanced product inquiry handling
2994
  async def handle_veterinary_product_inquiry(product_name: str, from_number: str) -> None:
2995
  """
2996
- Handle product inquiry with enhanced veterinary domain support
2997
  """
2998
  try:
2999
  # Search for the product
@@ -3008,13 +3051,18 @@ async def handle_veterinary_product_inquiry(product_name: str, from_number: str)
3008
  current_menu='product_inquiry',
3009
  current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
3010
  )
 
3011
  # Get updated context with last message
3012
  context = context_manager.get_context(from_number)
3013
- response = generate_veterinary_product_response(selected_product, context)
3014
- send_whatsjet_message(from_number, response)
 
 
 
 
3015
 
3016
  # Add to conversation history
3017
- context_manager.add_to_history(from_number, product_name, response)
3018
 
3019
  else:
3020
  # Enhanced "not found" response with veterinary suggestions
@@ -3037,6 +3085,190 @@ async def handle_veterinary_product_inquiry(product_name: str, from_number: str)
3037
 
3038
  send_whatsjet_message(from_number, message)
3039
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3040
  except Exception as e:
3041
  logger.error(f"Error in product inquiry: {e}")
3042
  # Instead of sending a generic error, return to main menu
@@ -3095,7 +3327,8 @@ async def handle_category_selection(selection: str, from_number: str):
3095
 
3096
  except Exception as e:
3097
  logger.error(f"[Category] Error handling category selection: {e}")
3098
- # Instead of sending a generic error, return to main menu
 
3099
  welcome_msg = generate_veterinary_welcome_message(from_number, user_context)
3100
  send_whatsjet_message(from_number, welcome_msg)
3101
  context_manager.update_context(
@@ -3132,7 +3365,7 @@ def get_menu_validation_message(current_state: str, user_context: dict) -> str:
3132
  return "❌ No products available in this category. Please type 'main' to return to main menu."
3133
 
3134
  elif current_state == 'product_inquiry':
3135
- return "❌ Invalid selection for Product Options. Please choose:\n1️⃣ Talk to Veterinary Consultant\n2️⃣ Inquire about Product Availability\n3️⃣ Back to Main Menu"
3136
 
3137
  elif current_state == 'ai_chat_mode':
3138
  return "πŸ’¬ *You're in AI Chat mode. Ask me anything about veterinary care!*\n\nType 'main' to return to main menu."
@@ -3169,7 +3402,7 @@ def is_valid_menu_selection(selection: str, current_state: str, user_context: di
3169
  return 1 <= selection_num <= total_products
3170
 
3171
  elif current_state == 'product_inquiry':
3172
- return 1 <= selection_num <= 3
3173
 
3174
  elif current_state == 'ai_chat_mode':
3175
  return mapped_selection == 'main'
@@ -3179,6 +3412,225 @@ def is_valid_menu_selection(selection: str, current_state: str, user_context: di
3179
  # Load products on startup
3180
  load_products_data()
3181
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3182
  if __name__ == "__main__":
3183
  # Launch FastAPI app
3184
  import uvicorn
 
147
  },
148
  'product_inquiry': {
149
  'name': 'Product Inquiry Menu',
150
+ 'valid_options': ['1', '2', '3', '4', '5'],
151
  'option_descriptions': {
152
  '1': 'Talk to Veterinary Consultant',
153
  '2': 'Inquire about Product Availability',
154
+ '3': 'View Product Image',
155
+ '4': 'Download Detailed PDF',
156
+ '5': 'Back to Main Menu'
157
  }
158
  },
159
  'ai_chat': {
 
2369
  )
2370
  except Exception as e:
2371
  logger.error(f"[Contact] Error handling contact response: {e}")
2372
+ # Get user context before using it
2373
+ user_context = context_manager.get_context(from_number)
2374
  welcome_msg = generate_veterinary_welcome_message(from_number, user_context)
2375
  send_whatsjet_message(from_number, welcome_msg)
2376
  context_manager.update_context(
 
2474
  )
2475
  except Exception as e:
2476
  logger.error(f"[Availability] Error handling availability response: {e}")
2477
+ # Get user context before using it
2478
+ user_context = context_manager.get_context(from_number)
2479
  welcome_msg = generate_veterinary_welcome_message(from_number, user_context)
2480
  send_whatsjet_message(from_number, welcome_msg)
2481
  context_manager.update_context(
 
2539
  )
2540
  except Exception as e:
2541
  logger.error(f"Error sending helpful guidance: {e}")
2542
+ # Get user context before using it
2543
+ user_context = context_manager.get_context(from_number)
2544
  welcome_msg = generate_veterinary_welcome_message(from_number, user_context)
2545
  send_whatsjet_message(from_number, welcome_msg)
2546
  context_manager.update_context(
 
2853
 
2854
  @app.get("/test-whatsjet")
2855
  async def test_whatsjet():
 
2856
  try:
2857
  resp = requests.get("https://api.whatsjet.com", timeout=5)
2858
  return {"status": resp.status_code, "text": resp.text[:200]}
 
2953
  user_context = context_manager.get_context(from_number)
2954
  current_product = user_context.get('current_product')
2955
 
2956
+ if not current_product:
2957
+ send_whatsjet_message(from_number, "❌ No product selected. Please search for a product first.")
2958
+ return
2959
+
2960
  if selection == '1':
2961
  # Talk to Veterinary Consultant
2962
+ product_name = current_product.get('Product Name', 'the selected product')
 
2963
  consultant_msg = (
2964
  f"πŸ“ž Contact Veterinary Consultant\n\n"
2965
  f"Product: {product_name}\n\n"
 
2970
  "Type main at any time to go to main menu."
2971
  )
2972
  send_whatsjet_message(from_number, consultant_msg)
2973
+ context_manager.update_context(
2974
+ from_number,
2975
+ current_state='contact_request',
2976
+ current_menu='contact_request',
2977
+ current_menu_options=['Provide contact details']
2978
+ )
2979
+
2980
  elif selection == '2':
2981
  # Inquire about Product Availability
2982
  await handle_availability_inquiry(from_number, user_context)
2983
+
2984
  elif selection == '3':
2985
+ # View Product Image
2986
+ await send_product_with_image(from_number, current_product, user_context)
2987
+ # Return to product inquiry menu
2988
+ response_with_media = generate_veterinary_product_response_with_media(current_product, user_context)
2989
+ send_whatsjet_message(from_number, response_with_media['text'])
2990
+ context_manager.update_context(
2991
+ from_number,
2992
+ current_state='product_inquiry',
2993
+ current_menu='product_inquiry',
2994
+ current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
2995
+ )
2996
+
2997
+ elif selection == '4':
2998
+ # Download Detailed PDF
2999
+ await send_enhanced_pdf(from_number, current_product)
3000
+ # Return to product inquiry menu
3001
+ response_with_media = generate_veterinary_product_response_with_media(current_product, user_context)
3002
+ send_whatsjet_message(from_number, response_with_media['text'])
3003
+ context_manager.update_context(
3004
+ from_number,
3005
+ current_state='product_inquiry',
3006
+ current_menu='product_inquiry',
3007
+ current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
3008
+ )
3009
+
3010
+ elif selection == '5':
3011
  # Back to Main Menu
3012
  welcome_msg = generate_veterinary_welcome_message(from_number, user_context)
3013
  send_whatsjet_message(from_number, welcome_msg)
 
3019
  )
3020
  return
3021
  else:
3022
+ send_whatsjet_message(from_number, "❌ Invalid selection. Please choose 1, 2, 3, 4, or 5.")
3023
  return
3024
  except Exception as e:
3025
  logger.error(f"Error in product follow-up: {e}")
3026
+ user_context = context_manager.get_context(from_number)
3027
  welcome_msg = generate_veterinary_welcome_message(from_number, user_context)
3028
  send_whatsjet_message(from_number, welcome_msg)
3029
  context_manager.update_context(
 
3036
  # Enhanced product inquiry handling
3037
  async def handle_veterinary_product_inquiry(product_name: str, from_number: str) -> None:
3038
  """
3039
+ Handle product inquiry with enhanced veterinary domain support and media
3040
  """
3041
  try:
3042
  # Search for the product
 
3051
  current_menu='product_inquiry',
3052
  current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
3053
  )
3054
+
3055
  # Get updated context with last message
3056
  context = context_manager.get_context(from_number)
3057
+
3058
+ # Use enhanced response with media support
3059
+ response_with_media = generate_veterinary_product_response_with_media(selected_product, context)
3060
+
3061
+ # Send the response
3062
+ send_whatsjet_message(from_number, response_with_media['text'])
3063
 
3064
  # Add to conversation history
3065
+ context_manager.add_to_history(from_number, product_name, response_with_media['text'])
3066
 
3067
  else:
3068
  # Enhanced "not found" response with veterinary suggestions
 
3085
 
3086
  send_whatsjet_message(from_number, message)
3087
 
3088
+ except Exception as e:
3089
+ logger.error(f"Error in product inquiry: {e}")
3090
+ # Get user context before using it
3091
+ user_context = context_manager.get_context(from_number)
3092
+ welcome_msg = generate_veterinary_welcome_message(from_number, user_context)
3093
+ send_whatsjet_message(from_number, welcome_msg)
3094
+ context_manager.update_context(from_number, current_state='main_menu', current_menu='main_menu', current_menu_options=list(MENU_CONFIG['main_menu']['option_descriptions'].values()))
3095
+
3096
+ async def handle_intelligent_product_inquiry(from_number: str, query: str, user_context: dict, reply_language: str = 'en'):
3097
+ """Handle product inquiry with OpenAI intelligence and media support"""
3098
+ try:
3099
+ # First try direct product search
3100
+ products = get_veterinary_product_matches(query)
3101
+
3102
+ if products:
3103
+ # Check if this is a broad/category query (multiple products found)
3104
+ if len(products) > 1:
3105
+ # Use OpenAI to generate a professional summary and list all products
3106
+ if OPENAI_API_KEY:
3107
+ try:
3108
+ # Create a comprehensive prompt for multiple products
3109
+ products_info = []
3110
+ for i, product in enumerate(products, 1):
3111
+ product_name = product.get('Product Name', 'N/A')
3112
+ category = product.get('Category', 'N/A')
3113
+ target_species = product.get('Target Species', 'N/A')
3114
+ products_info.append(f"{i}. {product_name} - {category} ({target_species})")
3115
+
3116
+ products_text = "\n".join(products_info)
3117
+
3118
+ prompt = f"""
3119
+ You are a professional veterinary product assistant for Apex Biotical. The user asked about "{query}" and we found {len(products)} relevant products.
3120
+
3121
+ Available Products:
3122
+ {products_text}
3123
+
3124
+ Please provide:
3125
+ 1. A professional, welcoming response acknowledging their query
3126
+ 2. A brief summary of what these products are for (if it's a category like "poultry products", explain the category)
3127
+ 3. List all products with their numbers and brief descriptions
3128
+ 4. Clear instructions on how to proceed
3129
+
3130
+ Format your response professionally with emojis and clear structure. Keep it concise but informative.
3131
+ """
3132
+
3133
+ response = openai.ChatCompletion.create(
3134
+ model="gpt-4o",
3135
+ messages=[{"role": "user", "content": prompt}],
3136
+ temperature=0.7,
3137
+ max_tokens=400
3138
+ )
3139
+
3140
+ ai_response = response.choices[0].message['content'].strip()
3141
+
3142
+ # Add instructions for selection
3143
+ selection_instructions = (
3144
+ f"\n\nπŸ’¬ *To view detailed information about any product, reply with its number (1-{len(products)})*\n"
3145
+ "πŸ’¬ *Type 'main' to return to the main menu*"
3146
+ )
3147
+
3148
+ full_response = ai_response + selection_instructions
3149
+
3150
+ # Translate response if needed
3151
+ if reply_language == 'ur':
3152
+ try:
3153
+ translated_response = GoogleTranslator(source='auto', target='ur').translate(full_response)
3154
+ send_whatsjet_message(from_number, translated_response)
3155
+ except Exception as e:
3156
+ logger.error(f"[AI] Translation error: {e}")
3157
+ send_whatsjet_message(from_number, full_response)
3158
+ else:
3159
+ send_whatsjet_message(from_number, full_response)
3160
+
3161
+ # Store the product list in context for selection handling
3162
+ context_manager.update_context(
3163
+ from_number,
3164
+ current_state='intelligent_products_menu',
3165
+ current_menu='intelligent_products_menu',
3166
+ current_menu_options=[f"Product {i+1}" for i in range(len(products))],
3167
+ available_products=products,
3168
+ last_query=query
3169
+ )
3170
+
3171
+ # Add to conversation history
3172
+ context_manager.add_to_history(from_number, query, full_response)
3173
+ return
3174
+
3175
+ except Exception as e:
3176
+ logger.error(f"[AI] Error generating product summary: {e}")
3177
+ # Fall back to simple listing if AI fails
3178
+ pass
3179
+
3180
+ # Fallback: Simple listing without AI
3181
+ message = f"πŸ” *Found {len(products)} products matching '{query}':*\n\n"
3182
+
3183
+ for i, product in enumerate(products, 1):
3184
+ product_name = product.get('Product Name', 'N/A')
3185
+ category = product.get('Category', 'N/A')
3186
+ target_species = product.get('Target Species', 'N/A')
3187
+ message += f"{format_number_with_emoji(i)} {product_name}\n"
3188
+ message += f" πŸ“¦ {category} ({target_species})\n\n"
3189
+
3190
+ message += (
3191
+ f"πŸ’¬ *To view detailed information about any product, reply with its number (1-{len(products)})*\n"
3192
+ "πŸ’¬ *Type 'main' to return to the main menu*"
3193
+ )
3194
+
3195
+ # Translate response if needed
3196
+ if reply_language == 'ur':
3197
+ try:
3198
+ translated_message = GoogleTranslator(source='auto', target='ur').translate(message)
3199
+ send_whatsjet_message(from_number, translated_message)
3200
+ except Exception as e:
3201
+ logger.error(f"[AI] Translation error: {e}")
3202
+ send_whatsjet_message(from_number, message)
3203
+ else:
3204
+ send_whatsjet_message(from_number, message)
3205
+
3206
+ # Store the product list in context for selection handling
3207
+ context_manager.update_context(
3208
+ from_number,
3209
+ current_state='intelligent_products_menu',
3210
+ current_menu='intelligent_products_menu',
3211
+ current_menu_options=[f"Product {i+1}" for i in range(len(products))],
3212
+ available_products=products,
3213
+ last_query=query
3214
+ )
3215
+
3216
+ # Add to conversation history
3217
+ context_manager.add_to_history(from_number, query, message)
3218
+
3219
+ else:
3220
+ # Single product found - show detailed information with media support
3221
+ selected_product = products[0]
3222
+ context_manager.update_context(
3223
+ from_number,
3224
+ current_product=selected_product,
3225
+ current_state='product_inquiry',
3226
+ current_menu='product_inquiry',
3227
+ current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
3228
+ )
3229
+
3230
+ # Get updated context with last message
3231
+ context = context_manager.get_context(from_number)
3232
+
3233
+ # Use enhanced response with media support
3234
+ response_with_media = generate_veterinary_product_response_with_media(selected_product, context)
3235
+
3236
+ # Send the response
3237
+ send_whatsjet_message(from_number, response_with_media['text'])
3238
+
3239
+ # Add to conversation history
3240
+ context_manager.add_to_history(from_number, query, response_with_media['text'])
3241
+
3242
+ else:
3243
+ # Enhanced "not found" response with veterinary suggestions
3244
+ message = (
3245
+ "❌ *Product Not Found*\n\n"
3246
+ f"πŸ” *We couldn't find '{query}' in our veterinary database.*\n\n"
3247
+ "πŸ’‘ *Try these alternatives:*\n"
3248
+ "β€’ Check spelling (e.g., 'Hydropex' not 'Hydro pex')\n"
3249
+ "β€’ Search by symptoms (e.g., 'respiratory', 'liver support')\n"
3250
+ "β€’ Search by category (e.g., 'antibiotic', 'vitamin')\n"
3251
+ "β€’ Search by species (e.g., 'poultry', 'livestock')\n\n"
3252
+ "πŸ₯ *Popular Veterinary Products:*\n"
3253
+ "β€’ Hydropex (Electrolyte supplement)\n"
3254
+ "β€’ Heposel (Liver tonic)\n"
3255
+ "β€’ Bromacid (Respiratory support)\n"
3256
+ "β€’ Tribiotic (Antibiotic)\n"
3257
+ "β€’ Symodex (Multivitamin)\n\n"
3258
+ "πŸ’¬ *Type 'main' to return to main menu or try another search.*"
3259
+ )
3260
+
3261
+ # Translate response if needed
3262
+ if reply_language == 'ur':
3263
+ try:
3264
+ translated_message = GoogleTranslator(source='auto', target='ur').translate(message)
3265
+ send_whatsjet_message(from_number, translated_message)
3266
+ except Exception as e:
3267
+ logger.error(f"[AI] Translation error: {e}")
3268
+ send_whatsjet_message(from_number, message)
3269
+ else:
3270
+ send_whatsjet_message(from_number, message)
3271
+
3272
  except Exception as e:
3273
  logger.error(f"Error in product inquiry: {e}")
3274
  # Instead of sending a generic error, return to main menu
 
3327
 
3328
  except Exception as e:
3329
  logger.error(f"[Category] Error handling category selection: {e}")
3330
+ # Get user context before using it
3331
+ user_context = context_manager.get_context(from_number)
3332
  welcome_msg = generate_veterinary_welcome_message(from_number, user_context)
3333
  send_whatsjet_message(from_number, welcome_msg)
3334
  context_manager.update_context(
 
3365
  return "❌ No products available in this category. Please type 'main' to return to main menu."
3366
 
3367
  elif current_state == 'product_inquiry':
3368
+ return "❌ Invalid selection for Product Options. Please choose:\n1️⃣ Talk to Veterinary Consultant\n2️⃣ Inquire about Product Availability\n3️⃣ View Product Image\n4️⃣ Download Detailed PDF\n5️⃣ Back to Main Menu"
3369
 
3370
  elif current_state == 'ai_chat_mode':
3371
  return "πŸ’¬ *You're in AI Chat mode. Ask me anything about veterinary care!*\n\nType 'main' to return to main menu."
 
3402
  return 1 <= selection_num <= total_products
3403
 
3404
  elif current_state == 'product_inquiry':
3405
+ return 1 <= selection_num <= 5
3406
 
3407
  elif current_state == 'ai_chat_mode':
3408
  return mapped_selection == 'main'
 
3412
  # Load products on startup
3413
  load_products_data()
3414
 
3415
+ # Add these functions after the existing imports and before the main functions
3416
+
3417
+ def get_product_image_path(product_name: str) -> str:
3418
+ """
3419
+ Get the image path for a product
3420
+ Returns the path to the product image if it exists, otherwise None
3421
+ """
3422
+ try:
3423
+ # Create images directory if it doesn't exist
3424
+ images_dir = "static/images"
3425
+ os.makedirs(images_dir, exist_ok=True)
3426
+
3427
+ # Clean product name for filename
3428
+ safe_name = re.sub(r'[^\w\s-]', '', product_name).replace(' ', '_').lower()
3429
+
3430
+ # Check for common image extensions
3431
+ image_extensions = ['.jpg', '.jpeg', '.png', '.webp', '.gif']
3432
+
3433
+ for ext in image_extensions:
3434
+ image_path = os.path.join(images_dir, f"{safe_name}{ext}")
3435
+ if os.path.exists(image_path):
3436
+ logger.info(f"[Image] Found product image: {image_path}")
3437
+ return image_path
3438
+
3439
+ # If no specific product image found, check for a default image
3440
+ default_image_path = os.path.join(images_dir, "default_product.jpg")
3441
+ if os.path.exists(default_image_path):
3442
+ logger.info(f"[Image] Using default product image: {default_image_path}")
3443
+ return default_image_path
3444
+
3445
+ logger.warning(f"[Image] No image found for product: {product_name}")
3446
+ return None
3447
+
3448
+ except Exception as e:
3449
+ logger.error(f"[Image] Error getting product image path: {e}")
3450
+ return None
3451
+
3452
+ def get_product_image_media_type(image_path: str) -> str:
3453
+ """
3454
+ Determine the media type based on file extension
3455
+ """
3456
+ if not image_path:
3457
+ return None
3458
+
3459
+ ext = os.path.splitext(image_path)[1].lower()
3460
+
3461
+ media_type_map = {
3462
+ '.jpg': 'image/jpeg',
3463
+ '.jpeg': 'image/jpeg',
3464
+ '.png': 'image/png',
3465
+ '.webp': 'image/webp',
3466
+ '.gif': 'image/gif'
3467
+ }
3468
+
3469
+ return media_type_map.get(ext, 'image/jpeg')
3470
+
3471
+ async def send_product_with_image(from_number: str, product: Dict[str, Any], user_context: Dict[str, Any]):
3472
+ """
3473
+ Send product information with image if available
3474
+ """
3475
+ try:
3476
+ product_name = product.get('Product Name', 'Unknown Product')
3477
+
3478
+ # Generate product response
3479
+ response = generate_veterinary_product_response(product, user_context)
3480
+
3481
+ # Try to get product image
3482
+ image_path = get_product_image_path(product_name)
3483
+
3484
+ if image_path and os.path.exists(image_path):
3485
+ # Send product info with image
3486
+ media_type = get_product_image_media_type(image_path)
3487
+ filename = f"{product_name.replace(' ', '_')}.jpg"
3488
+
3489
+ success = send_whatsjet_message(
3490
+ from_number,
3491
+ response,
3492
+ media_type=media_type,
3493
+ media_path=image_path,
3494
+ filename=filename
3495
+ )
3496
+
3497
+ if success:
3498
+ logger.info(f"[Product] Successfully sent product with image: {product_name}")
3499
+ else:
3500
+ # Fallback to text-only if image send fails
3501
+ logger.warning(f"[Product] Failed to send image, sending text only: {product_name}")
3502
+ send_whatsjet_message(from_number, response)
3503
+ else:
3504
+ # Send text-only response
3505
+ send_whatsjet_message(from_number, response)
3506
+ logger.info(f"[Product] Sent product info without image: {product_name}")
3507
+
3508
+ except Exception as e:
3509
+ logger.error(f"[Product] Error sending product with image: {e}")
3510
+ # Fallback to text-only
3511
+ response = generate_veterinary_product_response(product, user_context)
3512
+ send_whatsjet_message(from_number, response)
3513
+
3514
+ async def send_enhanced_pdf(from_number: str, product: Dict[str, Any], pdf_content: bytes = None):
3515
+ """
3516
+ Send PDF with enhanced formatting and proper WhatsApp document sharing
3517
+ """
3518
+ try:
3519
+ product_name = product.get('Product Name', 'Unknown_Product')
3520
+ safe_name = re.sub(r'[^\w\s-]', '', product_name).replace(' ', '_')
3521
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
3522
+ filename = f"{safe_name}_Product_Info_{timestamp}.pdf"
3523
+
3524
+ # Generate PDF if not provided
3525
+ if pdf_content is None:
3526
+ pdf_content = generate_veterinary_pdf(product)
3527
+
3528
+ # Save PDF to uploads directory
3529
+ uploads_dir = "uploads"
3530
+ os.makedirs(uploads_dir, exist_ok=True)
3531
+ pdf_path = os.path.join(uploads_dir, filename)
3532
+
3533
+ with open(pdf_path, 'wb') as f:
3534
+ f.write(pdf_content)
3535
+
3536
+ # Send PDF as document via WhatsApp
3537
+ success = send_whatsjet_message(
3538
+ from_number,
3539
+ f"πŸ“„ *{product_name} - Detailed Product Information*\n\n"
3540
+ f"πŸ“Ž Here's the complete product information in PDF format.\n"
3541
+ f"πŸ“‹ Includes: Composition, Dosage, Precautions, Storage\n\n"
3542
+ f"πŸ’¬ Type 'main' to return to main menu.",
3543
+ media_type="application/pdf",
3544
+ media_path=pdf_path,
3545
+ filename=filename
3546
+ )
3547
+
3548
+ if success:
3549
+ logger.info(f"[PDF] Successfully sent PDF for product: {product_name}")
3550
+ else:
3551
+ # Fallback: Send download link
3552
+ server_url = os.getenv("SERVER_URL", "https://your-huggingface-space-url.hf.space")
3553
+ download_url = f"{server_url}/uploads/{filename}"
3554
+
3555
+ message = (
3556
+ f"πŸ“„ *{product_name} - Product Information*\n\n"
3557
+ f"πŸ“Ž [Download Product PDF]({download_url})\n\n"
3558
+ f"πŸ’¬ *Click the link above to download the detailed product information*\n"
3559
+ f"Type 'main' to return to main menu."
3560
+ )
3561
+ send_whatsjet_message(from_number, message)
3562
+ logger.info(f"[PDF] Sent PDF download link for product: {product_name}")
3563
+
3564
+ except Exception as e:
3565
+ logger.error(f"[PDF] Error sending enhanced PDF: {e}")
3566
+ # Fallback to basic text response
3567
+ response = generate_veterinary_product_response(product, {})
3568
+ send_whatsjet_message(from_number, response)
3569
+
3570
+ # Enhanced product response function with image support
3571
+ def generate_veterinary_product_response_with_media(product_info: Dict[str, Any], user_context: Dict[str, Any]) -> Dict[str, Any]:
3572
+ """
3573
+ Generate comprehensive veterinary product response with media information
3574
+ Returns a dictionary with text response and media info
3575
+ """
3576
+
3577
+ def clean_text(text):
3578
+ if pd.isna(text) or text is None:
3579
+ return "Not specified"
3580
+ return str(text).strip()
3581
+
3582
+ # Extract product details
3583
+ product_name = clean_text(product_info.get('Product Name', ''))
3584
+ product_type = clean_text(product_info.get('Type', ''))
3585
+ category = clean_text(product_info.get('Category', ''))
3586
+ indications = clean_text(product_info.get('Indications', ''))
3587
+
3588
+ # Check for PDF link in the CSV data
3589
+ pdf_link = ""
3590
+ try:
3591
+ # Load CSV data to check for PDF link
3592
+ csv_data = pd.read_csv('Veterinary.csv')
3593
+ product_row = csv_data[csv_data['Product Name'] == product_name]
3594
+ if not product_row.empty:
3595
+ brochure_link = product_row.iloc[0].get('Brochure (PDF)', '')
3596
+ if pd.notna(brochure_link) and brochure_link.strip():
3597
+ pdf_link = brochure_link.strip()
3598
+ except Exception as e:
3599
+ logger.warning(f"Error checking PDF link for {product_name}: {e}")
3600
+
3601
+ # Build the response
3602
+ response_text = f"""πŸ§ͺ *Name:* {product_name}
3603
+ πŸ“¦ *Type:* {product_type}
3604
+ πŸ₯ *Category:* {category}
3605
+ πŸ’Š *Used For:* {indications}"""
3606
+
3607
+ # Add PDF link if available
3608
+ if pdf_link:
3609
+ response_text += f"\n\nπŸ“„ Product Brochure Available\nπŸ”— {product_name} PDF:\n{pdf_link}"
3610
+
3611
+ # Add menu options
3612
+ response_text += f"""
3613
+
3614
+ πŸ’¬ *Available Actions:*
3615
+ 1️⃣ Talk to Veterinary Consultant
3616
+ 2️⃣ Inquire About Availability
3617
+ 3️⃣ View Product Image
3618
+ 4️⃣ Download Detailed PDF
3619
+ 5️⃣ Back to Main Menu
3620
+
3621
+ πŸ’¬ Select an option or ask about related products"""
3622
+
3623
+ # Check for product image
3624
+ image_path = get_product_image_path(product_name)
3625
+ has_image = image_path is not None and os.path.exists(image_path)
3626
+
3627
+ return {
3628
+ 'text': response_text,
3629
+ 'has_image': has_image,
3630
+ 'image_path': image_path,
3631
+ 'product_name': product_name
3632
+ }
3633
+
3634
  if __name__ == "__main__":
3635
  # Launch FastAPI app
3636
  import uvicorn