DreamStream-1 commited on
Commit
7915a03
·
verified ·
1 Parent(s): 3ea2f6c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +363 -14
app.py CHANGED
@@ -752,20 +752,59 @@ def get_veterinary_product_matches(query: str) -> List[Dict[str, Any]]:
752
  return unique_matches
753
 
754
  def normalize(text: str) -> str:
755
- """Normalize text for search"""
756
- if not text:
757
- return ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
758
 
759
- # Convert to lowercase and remove extra whitespace
760
- normalized = text.lower().strip()
761
 
762
- # Remove special characters but keep spaces
763
- normalized = re.sub(r'[^\w\s]', '', normalized)
 
764
 
765
- # Replace multiple spaces with single space
766
- normalized = re.sub(r'\s+', ' ', normalized)
 
 
767
 
768
- return normalized
 
769
 
770
  # Enhanced context management with veterinary domain awareness
771
  class VeterinaryContextManager:
@@ -1837,9 +1876,73 @@ async def process_incoming_message(from_number: str, msg: dict):
1837
  logger.warning(f"[Process] Language detection failed: {e}, defaulting to English")
1838
  reply_language = 'en'
1839
 
1840
- # Only use keyword logic for strict menu navigation
1841
- menu_commands = ['main', 'menu', 'start', 'home', 'back', '1', '2', '3', '4', '5']
1842
- if message_body.lower().strip() in menu_commands:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1843
  if reply_language == 'ur':
1844
  welcome_msg = (
1845
  "🤖 ویٹرنری ورچوئل اسسٹنٹ\n\n"
@@ -1852,6 +1955,7 @@ async def process_incoming_message(from_number: str, msg: dict):
1852
  )
1853
  else:
1854
  welcome_msg = generate_veterinary_welcome_message()
 
1855
  send_whatsjet_message(from_number, welcome_msg)
1856
  context_manager.update_context(
1857
  from_number,
@@ -1861,7 +1965,252 @@ async def process_incoming_message(from_number: str, msg: dict):
1861
  reply_language=reply_language
1862
  )
1863
  return
1864
- # All other queries: always use OpenAI/gpt-4o for intelligent response
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1865
  await handle_general_query_with_ai(from_number, message_body, user_context, reply_language)
1866
  return
1867
 
 
752
  return unique_matches
753
 
754
  def normalize(text: str) -> str:
755
+ """Normalize text for better matching"""
756
+ return re.sub(r'[^\w\s\u0600-\u06FF]', '', text).lower().strip()
757
+
758
+ def apply_intelligent_corrections(query: str) -> str:
759
+ """Apply intelligent corrections to common misspellings and variations"""
760
+ corrections = {
761
+ # Common misspellings
762
+ 'hydropex': 'hydropex',
763
+ 'respira': 'respira aid plus',
764
+ 'bromacid': 'bromacid',
765
+ 'heposel': 'heposel',
766
+ 'tribiotic': 'tribiotic',
767
+ 'para ce': 'para c.e',
768
+ 'phytosal': 'phyto-sal',
769
+ 'mycopex': 'mycopex super',
770
+ 'eflin': 'eflin kt-20',
771
+ 'salcozine': 'salcozine st-30',
772
+ 'oftilex': 'oftilex ua-10',
773
+ 'biscomin': 'biscomin 10',
774
+ 'apvita': 'apvita plus',
775
+ 'b gaspro': 'b-g aspro-c',
776
+ 'ec immune': 'ec-immune',
777
+ 'liverpex': 'liverpex',
778
+ 'symodex': 'symodex',
779
+ 'adek': 'adek gold',
780
+ 'immuno dx': 'immuno dx',
781
+
782
+ # Category corrections
783
+ 'respiratory': 'respiratory',
784
+ 'liver': 'liver health',
785
+ 'antibiotic': 'antibiotics',
786
+ 'vitamin': 'vitamins',
787
+ 'supplement': 'supplements',
788
+ 'immune': 'immune system',
789
+
790
+ # Common variations
791
+ 'apex': 'apex biotical',
792
+ 'aapex': 'apex biotical',
793
+ }
794
 
795
+ normalized_query = query.lower().strip()
 
796
 
797
+ # Check for exact matches first
798
+ if normalized_query in corrections:
799
+ return corrections[normalized_query]
800
 
801
+ # Check for partial matches
802
+ for wrong, correct in corrections.items():
803
+ if wrong in normalized_query:
804
+ return normalized_query.replace(wrong, correct)
805
 
806
+ # If no corrections found, return original
807
+ return query
808
 
809
  # Enhanced context management with veterinary domain awareness
810
  class VeterinaryContextManager:
 
1876
  logger.warning(f"[Process] Language detection failed: {e}, defaulting to English")
1877
  reply_language = 'en'
1878
 
1879
+ # Check for greetings with multilingual support
1880
+ if is_greeting(message_body):
1881
+ # Check if user is currently in AI chat mode - if so, don't trigger menu mode
1882
+ if current_state == 'ai_chat_mode':
1883
+ logger.info(f"[Process] Greeting detected in AI chat mode, treating as AI query: {message_body}")
1884
+ # Treat greeting as a general query in AI chat mode
1885
+ await handle_general_query_with_ai(from_number, message_body, user_context, reply_language)
1886
+ return
1887
+ else:
1888
+ # Only trigger menu mode if not in AI chat mode
1889
+ # Generate welcome message in detected language
1890
+ if reply_language == 'ur':
1891
+ welcome_msg = (
1892
+ "🤖 ویٹرنری ورچوئل اسسٹنٹ\n\n"
1893
+ "آپ مجھ سے پوچھ سکتے ہیں:\n"
1894
+ "* ویٹرنری سوالات\n"
1895
+ "* پروڈکٹ کی سفارشات\n"
1896
+ "* علاج کے مشورے\n"
1897
+ "* عمومی معلومات\n\n"
1898
+ "💬 'main' لکھ کر مین مینو پر واپس جائیں۔"
1899
+ )
1900
+ else:
1901
+ welcome_msg = generate_veterinary_welcome_message()
1902
+
1903
+ send_whatsjet_message(from_number, welcome_msg)
1904
+ context_manager.update_context(
1905
+ from_number,
1906
+ current_state='main_menu',
1907
+ current_menu='main_menu',
1908
+ current_menu_options=list(MENU_CONFIG['main_menu']['option_descriptions'].values()),
1909
+ reply_language=reply_language
1910
+ )
1911
+ return
1912
+
1913
+ # 🎯 PRIORITY 1: Navigation commands - work from ANY state
1914
+ # Check for "main" command - now works for both text and voice
1915
+ if current_state != 'main_menu' and current_state != 'ai_chat_mode': # Only check for main if not already in main menu and not in AI chat mode
1916
+ mapped_navigation = process_intelligent_voice_command(message_body, current_state, user_context)
1917
+ if mapped_navigation == 'main':
1918
+ logger.info(f"[Process] Navigation command detected: '{message_body}' -> 'main'")
1919
+ # Generate welcome message in detected language
1920
+ if reply_language == 'ur':
1921
+ welcome_msg = (
1922
+ "🤖 ویٹرنری ورچوئل اسسٹنٹ\n\n"
1923
+ "آپ مجھ سے پوچھ سکتے ہیں:\n"
1924
+ "* ویٹرنری سوالات\n"
1925
+ "* پروڈکٹ کی سفارشات\n"
1926
+ "* علاج کے مشورے\n"
1927
+ "* عمومی معلومات\n\n"
1928
+ "💬 'main' لکھ کر مین مینو پر واپس جائیں۔"
1929
+ )
1930
+ else:
1931
+ welcome_msg = generate_veterinary_welcome_message()
1932
+
1933
+ send_whatsjet_message(from_number, welcome_msg)
1934
+ context_manager.update_context(
1935
+ from_number,
1936
+ current_state='main_menu',
1937
+ current_menu='main_menu',
1938
+ current_menu_options=list(MENU_CONFIG['main_menu']['option_descriptions'].values()),
1939
+ reply_language=reply_language
1940
+ )
1941
+ return
1942
+
1943
+ # Also check for text-based navigation commands
1944
+ if message_body.lower() in ['main', 'menu', 'start', 'home', 'back']:
1945
+ # Generate welcome message in detected language
1946
  if reply_language == 'ur':
1947
  welcome_msg = (
1948
  "🤖 ویٹرنری ورچوئل اسسٹنٹ\n\n"
 
1955
  )
1956
  else:
1957
  welcome_msg = generate_veterinary_welcome_message()
1958
+
1959
  send_whatsjet_message(from_number, welcome_msg)
1960
  context_manager.update_context(
1961
  from_number,
 
1965
  reply_language=reply_language
1966
  )
1967
  return
1968
+
1969
+ # 🎯 PRIORITY 2: State-specific handling (contact_request, availability_request, ai_chat_mode, clarification)
1970
+ if current_state == 'contact_request':
1971
+ await handle_contact_request_response(from_number, message_body)
1972
+ return
1973
+ elif current_state == 'availability_request':
1974
+ await handle_availability_request_response(from_number, message_body)
1975
+ return
1976
+ elif current_state == 'ai_chat_mode':
1977
+ await handle_ai_chat_mode(from_number, message_body, reply_language)
1978
+ return
1979
+ elif user_context.get('awaiting_clarification', False):
1980
+ # Handle clarification responses
1981
+ await handle_clarification_response(from_number, message_body, user_context)
1982
+ return
1983
+
1984
+ # 🎯 PRIORITY 3: Menu selection validation and handling
1985
+ if current_state == 'main_menu':
1986
+ # Validate menu selection
1987
+ is_valid, validation_message = validate_menu_selection(message_body, current_state, user_context)
1988
+
1989
+ if not is_valid:
1990
+ send_whatsjet_message(from_number, validation_message)
1991
+ return
1992
+
1993
+ # Handle valid menu selection
1994
+ if message_body == '1':
1995
+ # Product Search
1996
+ context_manager.update_context(
1997
+ from_number,
1998
+ current_state='product_inquiry',
1999
+ current_menu='product_inquiry',
2000
+ current_menu_options=['main'],
2001
+ reply_language=reply_language
2002
+ )
2003
+ if reply_language == 'ur':
2004
+ message = (
2005
+ "🔍 *پروڈکٹ سرچ*\n\n"
2006
+ "براہ کرم پروڈکٹ کا نام، زمرہ، یا علامات لکھیں:\n\n"
2007
+ "📝 *مثال:*\n"
2008
+ "• Hydropex\n"
2009
+ "• سانس کی بیماری\n"
2010
+ "• جگر کی صحت\n"
2011
+ "• اینٹی بائیوٹکس\n\n"
2012
+ "💬 'main' لکھ کر مین مینو پر واپس جائیں۔"
2013
+ )
2014
+ else:
2015
+ message = (
2016
+ "🔍 *Product Search*\n\n"
2017
+ "Please enter a product name, category, or symptoms:\n\n"
2018
+ "📝 *Examples:*\n"
2019
+ "• Hydropex\n"
2020
+ "• Respiratory disease\n"
2021
+ "• Liver health\n"
2022
+ "• Antibiotics\n\n"
2023
+ "💬 Type 'main' to return to main menu"
2024
+ )
2025
+ send_whatsjet_message(from_number, message)
2026
+ return
2027
+
2028
+ elif message_body == '2':
2029
+ # Category Browse
2030
+ categories = get_all_categories()
2031
+ if reply_language == 'ur':
2032
+ message = "📂 *زمرے براؤز کریں:*\n\n"
2033
+ for i, category in enumerate(categories, 1):
2034
+ message += f"{format_number_with_emoji(i)} {category}\n"
2035
+ message += "\n💬 اپنا انتخاب لکھیں یا 'main' لکھ کر مین مینو پر واپس جائیں۔"
2036
+ else:
2037
+ message = "📂 *Browse Categories:*\n\n"
2038
+ for i, category in enumerate(categories, 1):
2039
+ message += f"{format_number_with_emoji(i)} {category}\n"
2040
+ message += "\n💬 Type your choice or 'main' to return to main menu"
2041
+
2042
+ send_whatsjet_message(from_number, message)
2043
+ context_manager.update_context(
2044
+ from_number,
2045
+ current_state='category_selection',
2046
+ current_menu='category_selection',
2047
+ current_menu_options=categories,
2048
+ reply_language=reply_language
2049
+ )
2050
+ return
2051
+
2052
+ elif message_body == '3':
2053
+ # Catalog Download
2054
+ await send_catalog_pdf(from_number)
2055
+ return
2056
+
2057
+ elif message_body == '4':
2058
+ # AI Chat Mode
2059
+ context_manager.update_context(
2060
+ from_number,
2061
+ current_state='ai_chat_mode',
2062
+ current_menu='ai_chat_mode',
2063
+ current_menu_options=['main'],
2064
+ reply_language='ur'
2065
+ )
2066
+ if reply_language == 'ur':
2067
+ message = (
2068
+ "🤖 ویٹرنری ورچوئل اسسٹنٹ\n\n"
2069
+ "آپ مجھ سے پوچھ سکتے ہیں:\n"
2070
+ "* ویٹرنری سوالات\n"
2071
+ "* پروڈکٹ کی سفارشات\n"
2072
+ "* علاج کے مشورے\n"
2073
+ "* عمومی معلومات\n\n"
2074
+ "💬 'main' لکھ کر مین مینو پر واپس جائیں۔"
2075
+ )
2076
+ else:
2077
+ message = (
2078
+ "🤖 Veterinary Virtual Assistant\n\n"
2079
+ "You can ask me about:\n"
2080
+ "* Veterinary questions\n"
2081
+ "* Product recommendations\n"
2082
+ "* Treatment advice\n"
2083
+ "* General information\n\n"
2084
+ "💬 Type 'main' to return to main menu"
2085
+ )
2086
+ send_whatsjet_message(from_number, message)
2087
+ return
2088
+
2089
+ # 🎯 PRIORITY 4: Category selection handling
2090
+ elif current_state == 'category_selection':
2091
+ await handle_category_selection(message_body, from_number)
2092
+ return
2093
+
2094
+ # 🎯 PRIORITY 5: Product inquiry handling
2095
+ elif current_state == 'product_inquiry':
2096
+ # Check for voice commands first
2097
+ mapped_command = process_intelligent_voice_command(message_body, current_state, user_context)
2098
+ if mapped_command != message_body:
2099
+ logger.info(f"[Voice Command] Processing: '{message_body}' in state: {current_state}")
2100
+ message_body = mapped_command
2101
+ logger.info(f"[Voice Command] Mapped to: '{message_body}'")
2102
+
2103
+ # Search for products
2104
+ matches = get_veterinary_product_matches(message_body)
2105
+
2106
+ if matches:
2107
+ logger.info(f"[Process] Product query detected from menu state '{current_state}': '{message_body}' -> Found {len(matches)} products")
2108
+
2109
+ # Apply intelligent corrections
2110
+ corrected_query = apply_intelligent_corrections(message_body)
2111
+ if corrected_query != message_body:
2112
+ logger.info(f"[Query] Applied correction: '{message_body}' -> '{corrected_query}'")
2113
+ matches = get_veterinary_product_matches(corrected_query)
2114
+
2115
+ # Handle product matches
2116
+ if len(matches) == 1:
2117
+ # Single product match - show detailed info
2118
+ product = matches[0]
2119
+ context_manager.update_context(from_number, current_product=product)
2120
+ await send_product_with_image(from_number, product, user_context)
2121
+
2122
+ # Send follow-up options
2123
+ await handle_veterinary_product_followup(message_body, from_number)
2124
+
2125
+ elif len(matches) <= 5:
2126
+ # Multiple products - show list
2127
+ if reply_language == 'ur':
2128
+ response = f"🔍 *{len(matches)} پروڈکٹ ملے:*\n\n"
2129
+ else:
2130
+ response = f"🔍 *Found {len(matches)} products:*\n\n"
2131
+
2132
+ for i, product in enumerate(matches, 1):
2133
+ product_name = product.get('Product Name', 'N/A')
2134
+ category = product.get('Category', 'N/A')
2135
+ if reply_language == 'ur':
2136
+ response += f"{format_number_with_emoji(i)} {product_name} ({category})\n"
2137
+ else:
2138
+ response += f"{format_number_with_emoji(i)} {product_name} ({category})\n"
2139
+
2140
+ if reply_language == 'ur':
2141
+ response += "\n💬 اپنا انتخاب لکھیں یا 'main' لکھ کر مین مینو پر واپس جائیں۔"
2142
+ else:
2143
+ response += "\n💬 Type your choice or 'main' to return to main menu"
2144
+
2145
+ send_whatsjet_message(from_number, response)
2146
+ context_manager.update_context(
2147
+ from_number,
2148
+ current_state='product_selection',
2149
+ current_menu='product_selection',
2150
+ current_menu_options=[p.get('Product Name', 'N/A') for p in matches],
2151
+ reply_language=reply_language
2152
+ )
2153
+
2154
+ else:
2155
+ # Too many matches - ask for clarification
2156
+ if reply_language == 'ur':
2157
+ response = f"🔍 *{len(matches)} سے زیادہ پروڈکٹ ملے۔ براہ کرم مزید تفصیل دیں:*\n\n"
2158
+ else:
2159
+ response = f"🔍 *Found {len(matches)}+ products. Please be more specific:*\n\n"
2160
+
2161
+ # Show first 10 matches as examples
2162
+ for i, product in enumerate(matches[:10], 1):
2163
+ product_name = product.get('Product Name', 'N/A')
2164
+ category = product.get('Category', 'N/A')
2165
+ if reply_language == 'ur':
2166
+ response += f"{format_number_with_emoji(i)} {product_name} ({category})\n"
2167
+ else:
2168
+ response += f"{format_number_with_emoji(i)} {product_name} ({category})\n"
2169
+
2170
+ if reply_language == 'ur':
2171
+ response += "\n💬 براہ کرم مزید تفصیل دیں یا 'main' لکھ کر مین مینو پر واپس جائیں۔"
2172
+ else:
2173
+ response += "\n💬 Please provide more details or type 'main' to return to main menu"
2174
+
2175
+ send_whatsjet_message(from_number, response)
2176
+ context_manager.update_context(from_number, awaiting_clarification=True)
2177
+
2178
+ else:
2179
+ # No matches found - use OpenAI for intelligent response
2180
+ await handle_general_query_with_ai(from_number, message_body, user_context, reply_language)
2181
+ return
2182
+
2183
+ # 🎯 PRIORITY 6: Product selection handling
2184
+ elif current_state == 'product_selection':
2185
+ # Handle product selection from list
2186
+ try:
2187
+ selection_index = int(message_body) - 1
2188
+ menu_options = user_context.get('current_menu_options', [])
2189
+
2190
+ if 0 <= selection_index < len(menu_options):
2191
+ selected_product_name = menu_options[selection_index]
2192
+ # Find the product in the database
2193
+ if products_df is not None and not products_df.empty:
2194
+ product_match = products_df[products_df['Product Name'].str.contains(selected_product_name, case=False, na=False)]
2195
+ if not product_match.empty:
2196
+ product = product_match.iloc[0].to_dict()
2197
+ context_manager.update_context(from_number, current_product=product)
2198
+ await send_product_with_image(from_number, product, user_context)
2199
+ await handle_veterinary_product_followup(selected_product_name, from_number)
2200
+ return
2201
+
2202
+ # Invalid selection
2203
+ if reply_language == 'ur':
2204
+ send_whatsjet_message(from_number, "❌ *غلط انتخاب۔ براہ کرم دوبارہ کوشش کریں یا 'main' لکھ کر مین مینو پر واپس جائیں۔*")
2205
+ else:
2206
+ send_whatsjet_message(from_number, "❌ *Invalid selection. Please try again or type 'main' to return to main menu.*")
2207
+
2208
+ except ValueError:
2209
+ # Not a number - treat as general query
2210
+ await handle_general_query_with_ai(from_number, message_body, user_context, reply_language)
2211
+ return
2212
+
2213
+ # 🎯 PRIORITY 7: All other queries - use OpenAI for intelligent response
2214
  await handle_general_query_with_ai(from_number, message_body, user_context, reply_language)
2215
  return
2216