DreamStream-1 commited on
Commit
0c26c18
·
verified ·
1 Parent(s): caffcd1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +225 -97
app.py CHANGED
@@ -600,6 +600,19 @@ def get_veterinary_product_matches(query: str) -> List[Dict[str, Any]]:
600
  logger.info(f"[Veterinary Search] Skipping menu selection: '{normalized_query}'")
601
  return []
602
 
 
 
 
 
 
 
 
 
 
 
 
 
 
603
  scored_matches = []
604
 
605
  # Veterinary-specific query expansion
@@ -620,27 +633,29 @@ def get_veterinary_product_matches(query: str) -> List[Dict[str, Any]]:
620
  if category_key in normalized_query:
621
  expanded_queries.extend(categories)
622
 
623
- # Common veterinary product variations
624
  veterinary_variations = {
625
- 'hydropex': ['hydropex', 'hydro pex', 'electrolyte', 'dehydration', 'heat stress'],
626
- 'heposel': ['heposel', 'hepo sel', 'liver tonic', 'hepatoprotective'],
627
- 'bromacid': ['bromacid', 'brom acid', 'respiratory', 'mucolytic'],
628
- 'respira aid': ['respira aid', 'respira aid plus', 'respiratory support'],
629
- 'hexatox': ['hexatox', 'hexa tox', 'liver support', 'kidney support'],
630
- 'apma fort': ['apma fort', 'mycotoxin', 'liver support'],
631
- 'para c': ['para c', 'para c.e', 'heat stress', 'paracetamol'],
632
  'tribiotic': ['tribiotic', 'antibiotic', 'respiratory infection'],
633
- 'phyto-sal': ['phyto-sal', 'phytogenic', 'vitamin supplement'],
634
- 'mycopex': ['mycopex', 'mycotoxin binder', 'mold'],
635
- 'oftilex': ['oftilex', 'ofloxacin', 'antibiotic'],
636
- 'biscomin': ['biscomin', 'oxytetracycline', 'injectable'],
637
- 'apvita': ['apvita', 'vitamin b', 'amino acid'],
638
- 'bg aspro': ['bg aspro', 'aspirin', 'vitamin c'],
639
- 'ec-immune': ['ec-immune', 'immune', 'immunity'],
640
  'liverpex': ['liverpex', 'liver', 'metabolic'],
641
  'symodex': ['symodex', 'multivitamin', 'vitamin'],
642
- 'adek gold': ['adek gold', 'vitamin', 'multivitamin'],
643
- 'immuno dx': ['immuno dx', 'immune', 'antioxidant']
 
 
644
  }
645
 
646
  # Add veterinary variations
@@ -678,11 +693,11 @@ def get_veterinary_product_matches(query: str) -> List[Dict[str, Any]]:
678
  best_match_type = "exact"
679
  match_details = {"field": field_name, "query": expanded_query}
680
 
681
- # Fuzzy matching for close matches
682
  for expanded_query in expanded_queries:
683
  if len(expanded_query) > 3: # Only fuzzy match longer queries
684
  score = fuzz.partial_ratio(normalized_query, field_str) * weight
685
- if score > best_score and score > 70:
686
  best_score = score
687
  best_match_type = "fuzzy"
688
  match_details = {"field": field_name, "query": expanded_query}
@@ -1955,37 +1970,9 @@ async def process_incoming_message(from_number: str, msg: dict):
1955
  return
1956
 
1957
  else:
1958
- # Enhanced "not found" response with veterinary suggestions
1959
- message = (
1960
- "❌ *Product Not Found*\n\n"
1961
- f"🔍 *We couldn't find '{message_body}' in our veterinary database.*\n\n"
1962
- "💡 *Try these alternatives:*\n"
1963
- "• Check spelling (e.g., 'Hydropex' not 'Hydro pex')\n"
1964
- "• Search by symptoms (e.g., 'respiratory', 'liver support')\n"
1965
- "• Search by category (e.g., 'antibiotic', 'vitamin')\n"
1966
- "• Search by species (e.g., 'poultry', 'livestock')\n\n"
1967
- "🏥 *Popular Veterinary Products:*\n"
1968
- "• Hydropex (Electrolyte supplement)\n"
1969
- "• Heposel (Liver tonic)\n"
1970
- "• Bromacid (Respiratory support)\n"
1971
- "• Tribiotic (Antibiotic)\n"
1972
- "• Symodex (Multivitamin)\n\n"
1973
- "💬 *Type 'main' to return to main menu or try another search.*"
1974
- )
1975
-
1976
- # Translate response if needed
1977
- if reply_language == 'ur':
1978
- try:
1979
- translated_message = GoogleTranslator(source='auto', target='ur').translate(message)
1980
- send_whatsjet_message(from_number, translated_message)
1981
- except Exception as e:
1982
- logger.error(f"[AI] Translation error: {e}")
1983
- send_whatsjet_message(from_number, message)
1984
- else:
1985
- send_whatsjet_message(from_number, message)
1986
-
1987
- # 🎯 PRIORITY 5: Default: treat as general query with intelligent product inquiry
1988
- await handle_intelligent_product_inquiry(from_number, message_body, user_context, reply_language)
1989
 
1990
  except Exception as e:
1991
  logger.error(f"Error in process_incoming_message: {e}")
@@ -2001,20 +1988,50 @@ async def handle_general_query_with_ai(from_number: str, query: str, user_contex
2001
  logger.info(f"[AI General] Forcing reply_language to Urdu for Option 4.")
2002
 
2003
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2004
  if not OPENAI_API_KEY:
2005
- send_whatsjet_message(from_number,
2006
- "❌ AI assistance is not available. Please try searching for a specific product or type 'main' for the menu.")
 
 
 
 
2007
  return
2008
 
2009
  # Create context-aware prompt
2010
  current_state = user_context.get('current_state', 'main_menu')
2011
  current_product = user_context.get('current_product')
2012
 
2013
- # --- SYSTEM PROMPT FOR GENERAL/OUT-OF-MENU QUERIES ---
2014
- # This prompt ensures the assistant answers professionally, accurately, and helpfully.
2015
- # If the query is about products, list all relevant products (not just one) with brief details.
2016
- # If the query is general, provide a concise, expert veterinary answer.
2017
- # Clarify when a query is outside the menu system and offer to return to the main menu if needed.
 
 
 
 
 
 
 
 
 
 
2018
  prompt = f"""
2019
  You are a professional veterinary product assistant for Apex Biotical, helping users on WhatsApp.
2020
  Always answer in a clear, accurate, and helpful manner.
@@ -2023,21 +2040,40 @@ User Query: "{query}"
2023
  Current State: {current_state}
2024
  Current Product: {current_product.get('Product Name', 'None') if current_product else 'None'}
2025
 
2026
- If the user asks about products (e.g., 'poultry products', 'respiratory medicine'), list ALL relevant products from the database with a short description for each. If there are many, summarize or group them.
2027
- If the user asks a general veterinary question, provide a concise, expert answer.
2028
- If the query is outside the menu system, politely clarify and offer to return to the main menu (type 'main').
2029
- Always keep responses professional, concise, and user-friendly.
 
 
 
 
 
 
 
 
 
 
 
 
2030
  """
2031
 
2032
  response = openai.ChatCompletion.create(
2033
  model="gpt-4o",
2034
  messages=[{"role": "user", "content": prompt}],
2035
  temperature=0.7,
2036
- max_tokens=300
2037
  )
2038
 
2039
  ai_response = response.choices[0].message.content.strip()
2040
 
 
 
 
 
 
 
 
2041
  # Translate response if needed
2042
  if reply_language == 'ur':
2043
  try:
@@ -2054,9 +2090,13 @@ Always keep responses professional, concise, and user-friendly.
2054
 
2055
  except Exception as e:
2056
  logger.error(f"[AI] Error handling general query: {e}")
2057
- # Instead of sending a generic error, return to main menu
2058
- welcome_msg = generate_veterinary_welcome_message()
2059
- send_whatsjet_message(from_number, welcome_msg)
 
 
 
 
2060
  context_manager.update_context(
2061
  from_number,
2062
  current_state='main_menu',
@@ -3714,9 +3754,96 @@ async def test_send_product_image(phone: str, product_name: str = "Bromacid"):
3714
  async def handle_intelligent_product_inquiry(from_number: str, query: str, user_context: dict, reply_language: str = 'en'):
3715
  """Handle product inquiry with OpenAI intelligence and media support"""
3716
  try:
3717
- # First try direct product search
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3718
  products = get_veterinary_product_matches(query)
3719
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3720
  if products:
3721
  # Check if this is a broad/category query (multiple products found)
3722
  if len(products) > 1:
@@ -3845,47 +3972,48 @@ Format your response professionally with emojis and clear structure. Keep it con
3845
  current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
3846
  )
3847
 
3848
- # Send product image with caption using the new function
3849
- await send_product_image_with_caption(from_number, selected_product, user_context)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3850
 
3851
  # Add to conversation history
3852
  context_manager.add_to_history(from_number, query, f"Product inquiry for {selected_product.get('Product Name', 'Unknown')}")
3853
 
3854
  else:
3855
- # Enhanced "not found" response with veterinary suggestions
3856
- message = (
3857
- "❌ *Product Not Found*\n\n"
3858
- f"🔍 *We couldn't find '{query}' in our veterinary database.*\n\n"
3859
- "💡 *Try these alternatives:*\n"
3860
- "• Check spelling (e.g., 'Hydropex' not 'Hydro pex')\n"
3861
- "• Search by symptoms (e.g., 'respiratory', 'liver support')\n"
3862
- "• Search by category (e.g., 'antibiotic', 'vitamin')\n"
3863
- "• Search by species (e.g., 'poultry', 'livestock')\n\n"
3864
- "🏥 *Popular Veterinary Products:*\n"
3865
- "• Hydropex (Electrolyte supplement)\n"
3866
- "• Heposel (Liver tonic)\n"
3867
- "• Bromacid (Respiratory support)\n"
3868
- "• Tribiotic (Antibiotic)\n"
3869
- "• Symodex (Multivitamin)\n\n"
3870
- "💬 *Type 'main' to return to main menu or try another search.*"
3871
- )
3872
-
3873
- # Translate response if needed
3874
  if reply_language == 'ur':
3875
- try:
3876
- translated_message = GoogleTranslator(source='auto', target='ur').translate(message)
3877
- send_whatsjet_message(from_number, translated_message)
3878
- except Exception as e:
3879
- logger.error(f"[AI] Translation error: {e}")
3880
- send_whatsjet_message(from_number, message)
3881
  else:
3882
- send_whatsjet_message(from_number, message)
 
 
3883
 
3884
  except Exception as e:
3885
  logger.error(f"Error in product inquiry: {e}")
3886
- # Instead of sending a generic error, return to main menu
3887
- welcome_msg = generate_veterinary_welcome_message(from_number, user_context)
3888
- send_whatsjet_message(from_number, welcome_msg)
 
 
 
 
3889
  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()))
3890
 
3891
  async def handle_contact_request(from_number: str):
 
600
  logger.info(f"[Veterinary Search] Skipping menu selection: '{normalized_query}'")
601
  return []
602
 
603
+ # Check if this is a mode of action query
604
+ mode_of_action_keywords = ['mode of action', 'mechanism', 'how does it work', 'what does it do', 'how it works', 'mood of action']
605
+ is_mode_of_action_query = any(keyword in normalized_query for keyword in mode_of_action_keywords)
606
+
607
+ # Extract product name from mode of action query
608
+ if is_mode_of_action_query:
609
+ # Try to extract product name from the query
610
+ for _, row in products_df.iterrows():
611
+ product_name = str(row.get('Product Name', '')).lower()
612
+ if product_name in normalized_query:
613
+ logger.info(f"[Veterinary Search] Mode of action query for product: {product_name}")
614
+ return [row.to_dict()]
615
+
616
  scored_matches = []
617
 
618
  # Veterinary-specific query expansion
 
633
  if category_key in normalized_query:
634
  expanded_queries.extend(categories)
635
 
636
+ # Enhanced veterinary product variations with more variations
637
  veterinary_variations = {
638
+ 'hydropex': ['hydropex', 'hydro pex', 'hydropex', 'electrolyte', 'dehydration', 'heat stress'],
639
+ 'heposel': ['heposel', 'hepo sel', 'heposel', 'liver tonic', 'hepatoprotective'],
640
+ 'bromacid': ['bromacid', 'brom acid', 'bromacid', 'respiratory', 'mucolytic'],
641
+ 'respira aid': ['respira aid', 'respira aid plus', 'respiraaid', 'respiratory support'],
642
+ 'hexatox': ['hexatox', 'hexa tox', 'hexatox', 'liver support', 'kidney support'],
643
+ 'apma fort': ['apma fort', 'apmafort', 'mycotoxin', 'liver support'],
644
+ 'para c': ['para c', 'para c.e', 'parace', 'heat stress', 'paracetamol'],
645
  'tribiotic': ['tribiotic', 'antibiotic', 'respiratory infection'],
646
+ 'phyto-sal': ['phyto-sal', 'phytosal', 'phytogenic', 'vitamin supplement'],
647
+ 'mycopex': ['mycopex', 'mycopex super', 'mycotoxin binder', 'mold'],
648
+ 'oftilex': ['oftilex', 'oftilex ua-10', 'ofloxacin', 'antibiotic'],
649
+ 'biscomin': ['biscomin', 'biscomin 10', 'oxytetracycline', 'injectable'],
650
+ 'apvita': ['apvita', 'apvita plus', 'vitamin b', 'amino acid'],
651
+ 'bg aspro': ['bg aspro', 'b-g aspro-c', 'aspirin', 'vitamin c'],
652
+ 'ec-immune': ['ec-immune', 'ec immune', 'ecimmune', 'immune', 'immunity'],
653
  'liverpex': ['liverpex', 'liver', 'metabolic'],
654
  'symodex': ['symodex', 'multivitamin', 'vitamin'],
655
+ 'adek gold': ['adek gold', 'adekgold', 'vitamin', 'multivitamin'],
656
+ 'immuno dx': ['immuno dx', 'immunodx', 'immune', 'antioxidant'],
657
+ 'apex': ['apex', 'aapex', 'apex biotical'],
658
+ 'apex biotical': ['apex biotical', 'apex', 'aapex']
659
  }
660
 
661
  # Add veterinary variations
 
693
  best_match_type = "exact"
694
  match_details = {"field": field_name, "query": expanded_query}
695
 
696
+ # Fuzzy matching for close matches (improved threshold)
697
  for expanded_query in expanded_queries:
698
  if len(expanded_query) > 3: # Only fuzzy match longer queries
699
  score = fuzz.partial_ratio(normalized_query, field_str) * weight
700
+ if score > best_score and score > 75: # Increased threshold for better accuracy
701
  best_score = score
702
  best_match_type = "fuzzy"
703
  match_details = {"field": field_name, "query": expanded_query}
 
1970
  return
1971
 
1972
  else:
1973
+ # Use intelligent product inquiry for all non-found queries
1974
+ await handle_intelligent_product_inquiry(from_number, message_body, user_context, reply_language)
1975
+ return
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1976
 
1977
  except Exception as e:
1978
  logger.error(f"Error in process_incoming_message: {e}")
 
1988
  logger.info(f"[AI General] Forcing reply_language to Urdu for Option 4.")
1989
 
1990
  try:
1991
+ # Check if this is a non-product query that should get a simple response
1992
+ non_product_keywords = ['what is', 'who are', 'where is', 'when', 'why', 'how to', 'can you', 'do you', 'is this', 'are you']
1993
+ is_simple_query = any(keyword in query.lower() for keyword in non_product_keywords)
1994
+
1995
+ # Check for company-related queries
1996
+ company_queries = ['apex', 'aapex', 'apex biotical', 'company', 'about', 'who are you', 'what are you']
1997
+ is_company_query = any(keyword in query.lower() for keyword in company_queries)
1998
+
1999
+ if is_company_query:
2000
+ if reply_language == 'ur':
2001
+ response = "🏥 *Apex Biotical Solutions*\n\nہم ایک پیشہ ور ویٹرنری پروڈکٹس کمپنی ہیں۔\n\n💬 *براہ کرم 'main' لکھ کر مین مینو پر جائیں*"
2002
+ else:
2003
+ response = "🏥 *Apex Biotical Solutions*\n\nWe are a professional veterinary products company.\n\n💬 *Please type 'main' to go to main menu*"
2004
+ send_whatsjet_message(from_number, response)
2005
+ return
2006
+
2007
  if not OPENAI_API_KEY:
2008
+ if reply_language == 'ur':
2009
+ send_whatsjet_message(from_number,
2010
+ "❌ *AI assistance دستیاب نہیں ہے*\n\n💬 *براہ کرم 'main' لکھ کر مین مینو پر جائیں*")
2011
+ else:
2012
+ send_whatsjet_message(from_number,
2013
+ "❌ AI assistance is not available. Please type 'main' for the menu.")
2014
  return
2015
 
2016
  # Create context-aware prompt
2017
  current_state = user_context.get('current_state', 'main_menu')
2018
  current_product = user_context.get('current_product')
2019
 
2020
+ # Get all products data for context
2021
+ all_products = []
2022
+ if products_df is not None and not products_df.empty:
2023
+ all_products = products_df.to_dict('records')
2024
+
2025
+ # Create comprehensive context for AI
2026
+ products_context = ""
2027
+ if all_products:
2028
+ products_context = "Available Veterinary Products:\n"
2029
+ for i, product in enumerate(all_products[:30], 1): # Limit to first 30 products for context
2030
+ product_name = product.get('Product Name', 'N/A')
2031
+ category = product.get('Category', 'N/A')
2032
+ products_context += f"{i}. {product_name} - {category}\n"
2033
+
2034
+ # Enhanced prompt for better responses
2035
  prompt = f"""
2036
  You are a professional veterinary product assistant for Apex Biotical, helping users on WhatsApp.
2037
  Always answer in a clear, accurate, and helpful manner.
 
2040
  Current State: {current_state}
2041
  Current Product: {current_product.get('Product Name', 'None') if current_product else 'None'}
2042
 
2043
+ Available Products:
2044
+ {products_context}
2045
+
2046
+ IMPORTANT RULES:
2047
+ 1. If the user asks about products, list relevant products with brief descriptions
2048
+ 2. If the user asks general veterinary questions, provide concise, expert answers
2049
+ 3. If the query is unclear or not related to veterinary products, politely redirect to main menu
2050
+ 4. Keep responses professional, concise, and user-friendly
2051
+ 5. Always end with instructions to type 'main' to return to main menu
2052
+ 6. If the query seems like a test or unrelated question, provide a simple redirect response
2053
+
2054
+ Response Guidelines:
2055
+ - Be professional and helpful
2056
+ - Keep responses concise (max 3-4 sentences)
2057
+ - Always include menu navigation instructions
2058
+ - If unsure, redirect to main menu
2059
  """
2060
 
2061
  response = openai.ChatCompletion.create(
2062
  model="gpt-4o",
2063
  messages=[{"role": "user", "content": prompt}],
2064
  temperature=0.7,
2065
+ max_tokens=200 # Reduced for more concise responses
2066
  )
2067
 
2068
  ai_response = response.choices[0].message.content.strip()
2069
 
2070
+ # Ensure the response includes navigation instructions
2071
+ if 'main' not in ai_response.lower():
2072
+ if reply_language == 'ur':
2073
+ ai_response += "\n\n💬 *براہ کرم 'main' لکھ کر مین مینو پر جائیں*"
2074
+ else:
2075
+ ai_response += "\n\n💬 *Please type 'main' to go to main menu*"
2076
+
2077
  # Translate response if needed
2078
  if reply_language == 'ur':
2079
  try:
 
2090
 
2091
  except Exception as e:
2092
  logger.error(f"[AI] Error handling general query: {e}")
2093
+ # Professional error response
2094
+ if reply_language == 'ur':
2095
+ error_msg = "❌ *خطا آ گئی ہے*\n\n💬 *براہ کرم 'main' لکھ کر مین مینو پر جائیں*"
2096
+ else:
2097
+ error_msg = "❌ *An error occurred*\n\n💬 *Please type 'main' to go to main menu*"
2098
+
2099
+ send_whatsjet_message(from_number, error_msg)
2100
  context_manager.update_context(
2101
  from_number,
2102
  current_state='main_menu',
 
3754
  async def handle_intelligent_product_inquiry(from_number: str, query: str, user_context: dict, reply_language: str = 'en'):
3755
  """Handle product inquiry with OpenAI intelligence and media support"""
3756
  try:
3757
+ # Clean and normalize the query
3758
+ clean_query = query.strip().lower()
3759
+
3760
+ # Check for common misspellings and variations
3761
+ misspelling_corrections = {
3762
+ 'aapex': 'apex',
3763
+ 'apex': 'apex biotical',
3764
+ 'ec immune': 'ec-immune',
3765
+ 'ecimmune': 'ec-immune',
3766
+ 'hydro pex': 'hydropex',
3767
+ 'hydropex': 'hydropex',
3768
+ 'respira aid': 'respira aid plus',
3769
+ 'respiraaid': 'respira aid plus',
3770
+ 'hepo sel': 'heposel',
3771
+ 'heposel': 'heposel',
3772
+ 'brom acid': 'bromacid',
3773
+ 'bromacid': 'bromacid',
3774
+ 'hexa tox': 'hexatox',
3775
+ 'hexatox': 'hexatox',
3776
+ 'apma fort': 'apma fort',
3777
+ 'apmafort': 'apma fort',
3778
+ 'para c': 'para c.e',
3779
+ 'para ce': 'para c.e',
3780
+ 'parace': 'para c.e',
3781
+ 'tribiotic': 'tribiotic',
3782
+ 'phyto sal': 'phyto-sal',
3783
+ 'phytosal': 'phyto-sal',
3784
+ 'mycopex': 'mycopex super',
3785
+ 'mycopexsuper': 'mycopex super',
3786
+ 'eflin': 'eflin kt-20',
3787
+ 'eflinkt20': 'eflin kt-20',
3788
+ 'salcozine': 'salcozine st-30',
3789
+ 'salcozinest30': 'salcozine st-30',
3790
+ 'oftilex': 'oftilex ua-10',
3791
+ 'oftilexua10': 'oftilex ua-10',
3792
+ 'biscomin': 'biscomin 10',
3793
+ 'biscomin10': 'biscomin 10',
3794
+ 'apvita': 'apvita plus',
3795
+ 'apvitaplus': 'apvita plus',
3796
+ 'bg aspro': 'b-g aspro-c',
3797
+ 'bgaspro': 'b-g aspro-c',
3798
+ 'liverpex': 'liverpex',
3799
+ 'symodex': 'symodex',
3800
+ 'adek': 'adek gold',
3801
+ 'adekgold': 'adek gold',
3802
+ 'immuno': 'immuno dx',
3803
+ 'immunodx': 'immuno dx',
3804
+ 'mood of action': 'mode of action',
3805
+ 'mode of action': 'mode of action',
3806
+ 'mechanism of action': 'mode of action',
3807
+ 'how does it work': 'mode of action',
3808
+ 'what does it do': 'mode of action',
3809
+ 'how it works': 'mode of action'
3810
+ }
3811
+
3812
+ # Apply misspelling corrections
3813
+ corrected_query = clean_query
3814
+ for misspelling, correction in misspelling_corrections.items():
3815
+ if misspelling in clean_query:
3816
+ corrected_query = clean_query.replace(misspelling, correction)
3817
+ logger.info(f"[Query] Applied correction: '{misspelling}' -> '{correction}'")
3818
+ break
3819
+
3820
+ # Check if query is asking about mode of action or mechanism
3821
+ mode_of_action_keywords = ['mode of action', 'mechanism', 'how does it work', 'what does it do', 'how it works']
3822
+ is_mode_of_action_query = any(keyword in clean_query for keyword in mode_of_action_keywords)
3823
+
3824
+ # First try direct product search with original query
3825
  products = get_veterinary_product_matches(query)
3826
 
3827
+ # If no products found, try with corrected query
3828
+ if not products and corrected_query != clean_query:
3829
+ products = get_veterinary_product_matches(corrected_query)
3830
+ if products:
3831
+ logger.info(f"[Query] Found products using corrected query: '{corrected_query}'")
3832
+
3833
+ # If still no products, try fuzzy matching with product names
3834
+ if not products:
3835
+ if products_df is not None and not products_df.empty:
3836
+ all_product_names = [str(name).lower() for name in products_df['Product Name'].dropna()]
3837
+
3838
+ # Use fuzzy matching to find similar product names
3839
+ for product_name in all_product_names:
3840
+ similarity = fuzz.ratio(clean_query, product_name)
3841
+ if similarity >= 80: # 80% similarity threshold
3842
+ logger.info(f"[Query] Fuzzy match found: '{clean_query}' -> '{product_name}' (similarity: {similarity}%)")
3843
+ products = get_veterinary_product_matches(product_name)
3844
+ if products:
3845
+ break
3846
+
3847
  if products:
3848
  # Check if this is a broad/category query (multiple products found)
3849
  if len(products) > 1:
 
3972
  current_menu_options=list(MENU_CONFIG['product_inquiry']['option_descriptions'].values())
3973
  )
3974
 
3975
+ # If it's a mode of action query, provide detailed mechanism information
3976
+ if is_mode_of_action_query:
3977
+ product_name = selected_product.get('Product Name', 'Unknown')
3978
+ composition = selected_product.get('Composition', 'Not specified')
3979
+ indications = selected_product.get('Indications', 'Not specified')
3980
+
3981
+ mode_of_action_response = (
3982
+ f"🧪 *{product_name} - Mode of Action*\n\n"
3983
+ f"📋 *Composition:* {composition}\n\n"
3984
+ f"💊 *Mechanism:* {indications}\n\n"
3985
+ f"💬 *For complete product details, select an option below:*\n"
3986
+ f"1️⃣ Talk to Veterinary Consultant\n"
3987
+ f"2️⃣ Inquire About Availability\n"
3988
+ f"3️⃣ Back to Main Menu"
3989
+ )
3990
+
3991
+ send_whatsjet_message(from_number, mode_of_action_response)
3992
+ else:
3993
+ # Send product image with caption using the new function
3994
+ await send_product_image_with_caption(from_number, selected_product, user_context)
3995
 
3996
  # Add to conversation history
3997
  context_manager.add_to_history(from_number, query, f"Product inquiry for {selected_product.get('Product Name', 'Unknown')}")
3998
 
3999
  else:
4000
+ # Generic, professional "not found" response
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4001
  if reply_language == 'ur':
4002
+ message = "❌ *سوال درست نہیں ہے*\n\n💬 *براہ کرم اپنا سوال درست کریں یا 'main' لکھ کر مین مینو پر جائیں*"
 
 
 
 
 
4003
  else:
4004
+ message = "❌ *Please correct your question*\n\n💬 *Type 'main' to go to main menu*"
4005
+
4006
+ send_whatsjet_message(from_number, message)
4007
 
4008
  except Exception as e:
4009
  logger.error(f"Error in product inquiry: {e}")
4010
+ # Professional error response
4011
+ if reply_language == 'ur':
4012
+ error_msg = "❌ *خطا آ گئی ہے*\n\n💬 *براہ کرم 'main' لکھ کر مین مینو پر جائیں*"
4013
+ else:
4014
+ error_msg = "❌ *An error occurred*\n\n💬 *Please type 'main' to go to main menu*"
4015
+
4016
+ send_whatsjet_message(from_number, error_msg)
4017
  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()))
4018
 
4019
  async def handle_contact_request(from_number: str):