Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -2166,11 +2166,93 @@ async def process_incoming_message(from_number: str, msg: dict):
|
|
2166 |
|
2167 |
async def handle_general_query_with_ai(from_number: str, query: str, user_context: dict, reply_language: str = 'en'):
|
2168 |
"""Handle general queries with OpenAI intelligence"""
|
2169 |
-
|
2170 |
-
reply_language = 'ur'
|
2171 |
-
logger.info(f"[AI General] Forcing reply_language to Urdu for Option 4.")
|
2172 |
|
2173 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2174 |
# Check if this is a non-product query that should get a simple response
|
2175 |
non_product_keywords = ['what is', 'who are', 'where is', 'when', 'why', 'how to', 'can you', 'do you', 'is this', 'are you']
|
2176 |
is_simple_query = any(keyword in query.lower() for keyword in non_product_keywords)
|
@@ -2179,6 +2261,15 @@ async def handle_general_query_with_ai(from_number: str, query: str, user_contex
|
|
2179 |
company_queries = ['apex', 'aapex', 'apex biotical', 'company', 'about', 'who are you', 'what are you']
|
2180 |
is_company_query = any(keyword in query.lower() for keyword in company_queries)
|
2181 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2182 |
if is_company_query:
|
2183 |
if reply_language == 'ur':
|
2184 |
response = (
|
@@ -2266,6 +2357,7 @@ Response Guidelines:
|
|
2266 |
- Keep responses concise (max 3-4 sentences)
|
2267 |
- Always include menu navigation instructions
|
2268 |
- If unsure, redirect to main menu
|
|
|
2269 |
"""
|
2270 |
|
2271 |
response = openai.ChatCompletion.create(
|
@@ -3495,80 +3587,111 @@ async def handle_category_selection(selection: str, from_number: str):
|
|
3495 |
send_helpful_guidance(from_number, 'category_selection_menu')
|
3496 |
|
3497 |
def get_menu_validation_message(current_state: str, user_context: dict) -> str:
|
3498 |
-
"""Get
|
3499 |
if current_state == 'main_menu':
|
3500 |
return (
|
3501 |
-
"
|
3502 |
-
"Please
|
|
|
3503 |
"1️⃣ Search Veterinary Products\n"
|
3504 |
"2️⃣ Browse Categories\n"
|
3505 |
"3️⃣ Download Catalog\n"
|
3506 |
"4️⃣ Chat with Veterinary AI Assistant\n\n"
|
3507 |
-
"
|
3508 |
"• Type a product name (e.g., 'hydropex', 'respira aid plus')\n"
|
3509 |
-
"• Type 'main' to refresh the menu"
|
|
|
3510 |
)
|
3511 |
elif current_state == 'all_products_menu':
|
3512 |
if products_df is not None and not products_df.empty:
|
3513 |
total_products = len(products_df)
|
3514 |
return (
|
3515 |
-
f"
|
3516 |
f"Please choose a product number between 1 and {total_products}.\n\n"
|
3517 |
-
"
|
3518 |
-
"• Type a product name (e.g., 'hydropex'
|
3519 |
-
"• Type 'main' to return to main menu"
|
|
|
3520 |
)
|
3521 |
else:
|
3522 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
3523 |
elif current_state == 'category_products_menu':
|
3524 |
available_products = user_context.get('available_products', [])
|
3525 |
if available_products:
|
3526 |
return (
|
3527 |
-
f"
|
3528 |
f"Please choose a product number between 1 and {len(available_products)}.\n\n"
|
3529 |
-
"
|
3530 |
-
"• Type a product name
|
3531 |
-
"• Type 'main' to return to main menu"
|
|
|
3532 |
)
|
3533 |
else:
|
3534 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3535 |
elif current_state == 'category_selection_menu':
|
3536 |
available_categories = user_context.get('available_categories', [])
|
3537 |
if available_categories:
|
3538 |
return (
|
3539 |
-
f"
|
3540 |
f"Please choose a category number between 1 and {len(available_categories)}.\n\n"
|
3541 |
-
"
|
3542 |
-
"• Type a product name
|
3543 |
-
"• Type 'main' to return to main menu"
|
|
|
3544 |
)
|
3545 |
else:
|
3546 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3547 |
elif current_state == 'product_inquiry':
|
3548 |
return (
|
3549 |
-
"
|
3550 |
-
"Please choose
|
|
|
3551 |
"1️⃣ Talk to Veterinary Consultant\n"
|
3552 |
"2️⃣ Inquire About Availability\n"
|
3553 |
"3️⃣ Back to Main Menu\n\n"
|
3554 |
-
"
|
3555 |
-
"• Type
|
3556 |
-
"• Type 'main' to return to main menu"
|
|
|
3557 |
)
|
3558 |
elif current_state == 'intelligent_products_menu':
|
|
|
3559 |
return (
|
3560 |
-
"
|
3561 |
-
"Please choose a product number between 1 and {len(available_products)}.\n\n"
|
3562 |
-
"
|
3563 |
-
"• Type a product name
|
3564 |
-
"• Type 'main' to return to main menu"
|
|
|
3565 |
)
|
3566 |
else:
|
3567 |
return (
|
3568 |
-
"
|
3569 |
"Please choose a valid option or type 'main' to return to main menu.\n\n"
|
3570 |
-
"
|
3571 |
-
"• Type a product name (e.g., 'hydropex', 'respira aid plus')"
|
|
|
|
|
3572 |
)
|
3573 |
|
3574 |
def is_valid_menu_selection(selection: str, current_state: str, user_context: dict) -> bool:
|
@@ -3576,6 +3699,39 @@ def is_valid_menu_selection(selection: str, current_state: str, user_context: di
|
|
3576 |
is_valid, _ = validate_menu_selection(selection, current_state, user_context)
|
3577 |
return is_valid
|
3578 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3579 |
def generate_veterinary_welcome_message(phone_number=None, user_context=None):
|
3580 |
"""Generate veterinary welcome message"""
|
3581 |
return (
|
@@ -4037,6 +4193,196 @@ async def test_send_product_image(phone: str, product_name: str = "Bromacid"):
|
|
4037 |
async def handle_intelligent_product_inquiry(from_number: str, query: str, user_context: dict, reply_language: str = 'en'):
|
4038 |
"""Handle product inquiry with OpenAI intelligence and media support"""
|
4039 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4040 |
# Clean and normalize the query
|
4041 |
clean_query = query.strip().lower()
|
4042 |
|
|
|
2166 |
|
2167 |
async def handle_general_query_with_ai(from_number: str, query: str, user_context: dict, reply_language: str = 'en'):
|
2168 |
"""Handle general queries with OpenAI intelligence"""
|
2169 |
+
logger.info(f"[AI General] Processing query: '{query}' with language: {reply_language}")
|
|
|
|
|
2170 |
|
2171 |
try:
|
2172 |
+
# Let OpenAI handle all queries intelligently first
|
2173 |
+
if OPENAI_API_KEY and products_df is not None and not products_df.empty:
|
2174 |
+
try:
|
2175 |
+
# Get all products data for context
|
2176 |
+
all_products = products_df.to_dict('records')
|
2177 |
+
|
2178 |
+
# Create comprehensive context for AI
|
2179 |
+
products_context = ""
|
2180 |
+
if all_products:
|
2181 |
+
products_context = "Available Veterinary Products:\n"
|
2182 |
+
for i, product in enumerate(all_products[:50], 1): # Limit to first 50 products for context
|
2183 |
+
product_name = product.get('Product Name', 'N/A')
|
2184 |
+
category = product.get('Category', 'N/A')
|
2185 |
+
target_species = product.get('Target Species', 'N/A')
|
2186 |
+
products_context += f"{i}. {product_name} - {category} ({target_species})\n"
|
2187 |
+
|
2188 |
+
# Enhanced AI prompt for intelligent query understanding
|
2189 |
+
prompt = f"""
|
2190 |
+
You are a professional veterinary product assistant for Apex Biotical, helping users on WhatsApp.
|
2191 |
+
|
2192 |
+
User Query: "{query}"
|
2193 |
+
|
2194 |
+
Available Products Database:
|
2195 |
+
{products_context}
|
2196 |
+
|
2197 |
+
IMPORTANT INSTRUCTIONS:
|
2198 |
+
1. FIRST, analyze if this is a COUNT query (asking for numbers, quantities, how many, etc.)
|
2199 |
+
2. If it's a COUNT query:
|
2200 |
+
- Determine if asking for TOTAL products or SPECIFIC category/products
|
2201 |
+
- If TOTAL: Provide total count of all products and categories
|
2202 |
+
- If SPECIFIC: Search the database for matching products and provide count with breakdown
|
2203 |
+
- Always provide accurate numbers from the database
|
2204 |
+
3. If it's NOT a count query:
|
2205 |
+
- Handle as a general product inquiry
|
2206 |
+
- List relevant products with descriptions
|
2207 |
+
- Provide helpful veterinary advice
|
2208 |
+
|
2209 |
+
RESPONSE FORMAT:
|
2210 |
+
- Be professional, concise, and helpful
|
2211 |
+
- Use emojis for better readability
|
2212 |
+
- Always include navigation instructions
|
2213 |
+
- If count query: Show numbers clearly with category breakdown
|
2214 |
+
- If product query: List products with brief descriptions
|
2215 |
+
|
2216 |
+
IMPORTANT: Always respond in a way that shows you understand the user's intent and provide accurate information from the database.
|
2217 |
+
"""
|
2218 |
+
|
2219 |
+
response = openai.ChatCompletion.create(
|
2220 |
+
model="gpt-4o",
|
2221 |
+
messages=[{"role": "user", "content": prompt}],
|
2222 |
+
temperature=0.7,
|
2223 |
+
max_tokens=500
|
2224 |
+
)
|
2225 |
+
|
2226 |
+
ai_response = response.choices[0].message.content.strip()
|
2227 |
+
|
2228 |
+
# Ensure the response includes navigation instructions
|
2229 |
+
if 'main' not in ai_response.lower():
|
2230 |
+
if reply_language == 'ur':
|
2231 |
+
ai_response += "\n\n💬 *براہ کرم 'main' لکھ کر مین مینو پر جائیں*"
|
2232 |
+
else:
|
2233 |
+
ai_response += "\n\n💬 *Please type 'main' to go to main menu*"
|
2234 |
+
|
2235 |
+
# Translate response if needed (ENGLISH/URDU ONLY)
|
2236 |
+
if reply_language == 'ur':
|
2237 |
+
try:
|
2238 |
+
# Only translate from English to Urdu - no other languages
|
2239 |
+
translated_response = GoogleTranslator(source='en', target='ur').translate(ai_response)
|
2240 |
+
send_whatsjet_message(from_number, translated_response)
|
2241 |
+
except Exception as e:
|
2242 |
+
logger.error(f"[AI] Translation error: {e}")
|
2243 |
+
send_whatsjet_message(from_number, ai_response)
|
2244 |
+
else:
|
2245 |
+
send_whatsjet_message(from_number, ai_response)
|
2246 |
+
|
2247 |
+
# Add to conversation history
|
2248 |
+
context_manager.add_to_history(from_number, query, ai_response)
|
2249 |
+
return
|
2250 |
+
|
2251 |
+
except Exception as e:
|
2252 |
+
logger.error(f"[AI] Error handling query with OpenAI: {e}")
|
2253 |
+
# Fall back to existing logic if OpenAI fails
|
2254 |
+
pass
|
2255 |
+
|
2256 |
# Check if this is a non-product query that should get a simple response
|
2257 |
non_product_keywords = ['what is', 'who are', 'where is', 'when', 'why', 'how to', 'can you', 'do you', 'is this', 'are you']
|
2258 |
is_simple_query = any(keyword in query.lower() for keyword in non_product_keywords)
|
|
|
2261 |
company_queries = ['apex', 'aapex', 'apex biotical', 'company', 'about', 'who are you', 'what are you']
|
2262 |
is_company_query = any(keyword in query.lower() for keyword in company_queries)
|
2263 |
|
2264 |
+
# Check for irrelevant or unclear queries
|
2265 |
+
irrelevant_keywords = ['weather', 'football', 'cricket', 'movie', 'music', 'food', 'restaurant', 'hotel', 'travel', 'shopping', 'fashion', 'beauty', 'sports', 'game', 'entertainment']
|
2266 |
+
is_irrelevant_query = any(keyword in query.lower() for keyword in irrelevant_keywords)
|
2267 |
+
|
2268 |
+
if is_irrelevant_query:
|
2269 |
+
response = get_irrelevant_query_response(query, user_context.get('current_state', 'main_menu'), reply_language)
|
2270 |
+
send_whatsjet_message(from_number, response)
|
2271 |
+
return
|
2272 |
+
|
2273 |
if is_company_query:
|
2274 |
if reply_language == 'ur':
|
2275 |
response = (
|
|
|
2357 |
- Keep responses concise (max 3-4 sentences)
|
2358 |
- Always include menu navigation instructions
|
2359 |
- If unsure, redirect to main menu
|
2360 |
+
- Focus on veterinary products and services only
|
2361 |
"""
|
2362 |
|
2363 |
response = openai.ChatCompletion.create(
|
|
|
3587 |
send_helpful_guidance(from_number, 'category_selection_menu')
|
3588 |
|
3589 |
def get_menu_validation_message(current_state: str, user_context: dict) -> str:
|
3590 |
+
"""Get professional validation message for current menu state"""
|
3591 |
if current_state == 'main_menu':
|
3592 |
return (
|
3593 |
+
"⚠️ *Invalid Selection*\n\n"
|
3594 |
+
"Please select a valid option from the main menu:\n\n"
|
3595 |
+
"📋 *Available Options:*\n"
|
3596 |
"1️⃣ Search Veterinary Products\n"
|
3597 |
"2️⃣ Browse Categories\n"
|
3598 |
"3️⃣ Download Catalog\n"
|
3599 |
"4️⃣ Chat with Veterinary AI Assistant\n\n"
|
3600 |
+
"💡 *Quick Actions:*\n"
|
3601 |
"• Type a product name (e.g., 'hydropex', 'respira aid plus')\n"
|
3602 |
+
"• Type 'main' to refresh the menu\n"
|
3603 |
+
"• Ask about symptoms or categories"
|
3604 |
)
|
3605 |
elif current_state == 'all_products_menu':
|
3606 |
if products_df is not None and not products_df.empty:
|
3607 |
total_products = len(products_df)
|
3608 |
return (
|
3609 |
+
f"⚠️ *Invalid Product Selection*\n\n"
|
3610 |
f"Please choose a product number between 1 and {total_products}.\n\n"
|
3611 |
+
"💡 *Alternative Options:*\n"
|
3612 |
+
"• Type a specific product name (e.g., 'hydropex')\n"
|
3613 |
+
"• Type 'main' to return to main menu\n"
|
3614 |
+
"• Ask about product categories"
|
3615 |
)
|
3616 |
else:
|
3617 |
+
return (
|
3618 |
+
"⚠️ *No Products Available*\n\n"
|
3619 |
+
"Currently no products are loaded in the system.\n\n"
|
3620 |
+
"💡 *Please:*\n"
|
3621 |
+
"• Type 'main' to return to main menu\n"
|
3622 |
+
"• Contact support if this issue persists"
|
3623 |
+
)
|
3624 |
elif current_state == 'category_products_menu':
|
3625 |
available_products = user_context.get('available_products', [])
|
3626 |
if available_products:
|
3627 |
return (
|
3628 |
+
f"⚠️ *Invalid Product Selection*\n\n"
|
3629 |
f"Please choose a product number between 1 and {len(available_products)}.\n\n"
|
3630 |
+
"💡 *Alternative Options:*\n"
|
3631 |
+
"• Type a specific product name\n"
|
3632 |
+
"• Type 'main' to return to main menu\n"
|
3633 |
+
"• Browse other categories"
|
3634 |
)
|
3635 |
else:
|
3636 |
+
return (
|
3637 |
+
"⚠️ *No Products in Category*\n\n"
|
3638 |
+
"This category currently has no available products.\n\n"
|
3639 |
+
"💡 *Please:*\n"
|
3640 |
+
"• Type 'main' to return to main menu\n"
|
3641 |
+
"• Browse other categories\n"
|
3642 |
+
"• Ask about specific products"
|
3643 |
+
)
|
3644 |
elif current_state == 'category_selection_menu':
|
3645 |
available_categories = user_context.get('available_categories', [])
|
3646 |
if available_categories:
|
3647 |
return (
|
3648 |
+
f"⚠️ *Invalid Category Selection*\n\n"
|
3649 |
f"Please choose a category number between 1 and {len(available_categories)}.\n\n"
|
3650 |
+
"💡 *Alternative Options:*\n"
|
3651 |
+
"• Type a specific product name\n"
|
3652 |
+
"• Type 'main' to return to main menu\n"
|
3653 |
+
"• Ask about product types"
|
3654 |
)
|
3655 |
else:
|
3656 |
+
return (
|
3657 |
+
"⚠️ *No Categories Available*\n\n"
|
3658 |
+
"Currently no product categories are available.\n\n"
|
3659 |
+
"💡 *Please:*\n"
|
3660 |
+
"• Type 'main' to return to main menu\n"
|
3661 |
+
"• Ask about specific products\n"
|
3662 |
+
"• Contact support if needed"
|
3663 |
+
)
|
3664 |
elif current_state == 'product_inquiry':
|
3665 |
return (
|
3666 |
+
"⚠️ *Invalid Selection*\n\n"
|
3667 |
+
"Please choose a valid option for this product:\n\n"
|
3668 |
+
"📋 *Available Actions:*\n"
|
3669 |
"1️⃣ Talk to Veterinary Consultant\n"
|
3670 |
"2️⃣ Inquire About Availability\n"
|
3671 |
"3️⃣ Back to Main Menu\n\n"
|
3672 |
+
"💡 *Alternative Options:*\n"
|
3673 |
+
"• Type another product name\n"
|
3674 |
+
"• Type 'main' to return to main menu\n"
|
3675 |
+
"• Ask about related products"
|
3676 |
)
|
3677 |
elif current_state == 'intelligent_products_menu':
|
3678 |
+
available_products = user_context.get('available_products', [])
|
3679 |
return (
|
3680 |
+
f"⚠️ *Invalid Product Selection*\n\n"
|
3681 |
+
f"Please choose a product number between 1 and {len(available_products)}.\n\n"
|
3682 |
+
"💡 *Alternative Options:*\n"
|
3683 |
+
"• Type a specific product name\n"
|
3684 |
+
"• Type 'main' to return to main menu\n"
|
3685 |
+
"• Ask about different categories"
|
3686 |
)
|
3687 |
else:
|
3688 |
return (
|
3689 |
+
"⚠️ *Invalid Selection*\n\n"
|
3690 |
"Please choose a valid option or type 'main' to return to main menu.\n\n"
|
3691 |
+
"💡 *Helpful Options:*\n"
|
3692 |
+
"• Type a product name (e.g., 'hydropex', 'respira aid plus')\n"
|
3693 |
+
"• Type 'main' to return to main menu\n"
|
3694 |
+
"• Ask about veterinary products or categories"
|
3695 |
)
|
3696 |
|
3697 |
def is_valid_menu_selection(selection: str, current_state: str, user_context: dict) -> bool:
|
|
|
3699 |
is_valid, _ = validate_menu_selection(selection, current_state, user_context)
|
3700 |
return is_valid
|
3701 |
|
3702 |
+
def get_irrelevant_query_response(query: str, current_state: str, reply_language: str = 'en') -> str:
|
3703 |
+
"""Get professional response for irrelevant or unclear queries"""
|
3704 |
+
if reply_language == 'ur':
|
3705 |
+
return (
|
3706 |
+
"🤖 *Apex Biotical Veterinary Assistant*\n\n"
|
3707 |
+
"آپ کا سوال واضح نہیں ہے یا یہ ویٹرنری مصنوعات سے متعلق نہیں ہے۔\n\n"
|
3708 |
+
"💡 *میں آپ کی مدد کر سکتا ہوں:*\n"
|
3709 |
+
"• ویٹرنری مصنوعات کے بارے میں معلومات\n"
|
3710 |
+
"• مصنوعات کی تلاش اور براؤز\n"
|
3711 |
+
"• ویٹرنری مشورے اور رہنمائی\n"
|
3712 |
+
"• مصنوعات کی دستیابی کے بارے میں پوچھنا\n\n"
|
3713 |
+
"📋 *مثال کے طور پر:*\n"
|
3714 |
+
"• 'hydropex کے بارے میں بتائیں'\n"
|
3715 |
+
"• 'سانس کی مصنوعات کون سی ہیں؟'\n"
|
3716 |
+
"• 'main' لکھ کر مین مینو پر جائیں"
|
3717 |
+
)
|
3718 |
+
else:
|
3719 |
+
return (
|
3720 |
+
"🤖 *Apex Biotical Veterinary Assistant*\n\n"
|
3721 |
+
"I'm here to help you with veterinary products and information. "
|
3722 |
+
"Your query doesn't seem to be related to our veterinary services.\n\n"
|
3723 |
+
"💡 *I can help you with:*\n"
|
3724 |
+
"• Information about veterinary products\n"
|
3725 |
+
"• Product search and browsing\n"
|
3726 |
+
"• Veterinary advice and guidance\n"
|
3727 |
+
"• Product availability inquiries\n\n"
|
3728 |
+
"📋 *Examples of what you can ask:*\n"
|
3729 |
+
"• 'Tell me about hydropex'\n"
|
3730 |
+
"• 'What respiratory products do you have?'\n"
|
3731 |
+
"• 'Show me all antibiotics'\n"
|
3732 |
+
"• Type 'main' to return to main menu"
|
3733 |
+
)
|
3734 |
+
|
3735 |
def generate_veterinary_welcome_message(phone_number=None, user_context=None):
|
3736 |
"""Generate veterinary welcome message"""
|
3737 |
return (
|
|
|
4193 |
async def handle_intelligent_product_inquiry(from_number: str, query: str, user_context: dict, reply_language: str = 'en'):
|
4194 |
"""Handle product inquiry with OpenAI intelligence and media support"""
|
4195 |
try:
|
4196 |
+
# Check for intelligent product count queries
|
4197 |
+
count_keywords = ['how many', 'count', 'number of', 'total', 'quantity', 'amount']
|
4198 |
+
is_count_query = any(keyword in query.lower() for keyword in count_keywords)
|
4199 |
+
|
4200 |
+
if is_count_query and products_df is not None and not products_df.empty:
|
4201 |
+
# Intelligent count analysis
|
4202 |
+
query_lower = query.lower()
|
4203 |
+
|
4204 |
+
# Check if it's asking for total products
|
4205 |
+
total_indicators = ['total products', 'all products', 'products you have', 'products in total', 'total medicines', 'all medicines']
|
4206 |
+
is_total_query = any(indicator in query_lower for indicator in total_indicators)
|
4207 |
+
|
4208 |
+
if is_total_query:
|
4209 |
+
# Total products count
|
4210 |
+
total_products = len(products_df)
|
4211 |
+
categories = products_df['Category'].dropna().unique()
|
4212 |
+
total_categories = len(categories)
|
4213 |
+
|
4214 |
+
if reply_language == 'ur':
|
4215 |
+
response = (
|
4216 |
+
f"📊 *کل مصنوعات کی تعداد*\n\n"
|
4217 |
+
f"ہمارے پاس کل **{total_products}** ویٹرنری مصنوعات ہیں۔\n\n"
|
4218 |
+
f"📂 *زمرے:* {total_categories}\n"
|
4219 |
+
f"📦 *مصنوعات:* {total_products}\n\n"
|
4220 |
+
"💡 *مثال کے طور پر:*\n"
|
4221 |
+
"• 'سانس کی مصنوعات دکھائیں'\n"
|
4222 |
+
"• 'hydropex کے بارے میں بتائیں'\n"
|
4223 |
+
"• 'main' لکھ کر مین مینو پر جائیں"
|
4224 |
+
)
|
4225 |
+
else:
|
4226 |
+
response = (
|
4227 |
+
f"📊 *Total Product Count*\n\n"
|
4228 |
+
f"We have a total of **{total_products}** veterinary products.\n\n"
|
4229 |
+
f"📂 *Categories:* {total_categories}\n"
|
4230 |
+
f"📦 *Products:* {total_products}\n\n"
|
4231 |
+
"💡 *Examples:*\n"
|
4232 |
+
"• 'Show me respiratory products'\n"
|
4233 |
+
"• 'Tell me about hydropex'\n"
|
4234 |
+
"• Type 'main' to return to main menu"
|
4235 |
+
)
|
4236 |
+
|
4237 |
+
send_whatsjet_message(from_number, response)
|
4238 |
+
return
|
4239 |
+
else:
|
4240 |
+
# Specific category/product type count
|
4241 |
+
# Extract search terms from the query
|
4242 |
+
search_terms = []
|
4243 |
+
|
4244 |
+
# Common veterinary categories and terms
|
4245 |
+
category_mappings = {
|
4246 |
+
'respiratory': ['respiratory', 'breathing', 'lung', 'bronchi', 'respira'],
|
4247 |
+
'liver': ['liver', 'hepatic', 'hepat', 'hepo'],
|
4248 |
+
'antibiotic': ['antibiotic', 'anti-biotic', 'biotic', 'tribiotic'],
|
4249 |
+
'vitamin': ['vitamin', 'vit', 'multivitamin', 'symodex', 'adek'],
|
4250 |
+
'electrolyte': ['electrolyte', 'hydropex', 'rehydration'],
|
4251 |
+
'poultry': ['poultry', 'chicken', 'bird', 'avian'],
|
4252 |
+
'livestock': ['livestock', 'cattle', 'cow', 'buffalo', 'animal'],
|
4253 |
+
'immune': ['immune', 'immunity', 'immuno', 'ec-immune'],
|
4254 |
+
'parasite': ['parasite', 'parasitic', 'para'],
|
4255 |
+
'antifungal': ['antifungal', 'fungal', 'myco'],
|
4256 |
+
'pain': ['pain', 'analgesic', 'painkiller'],
|
4257 |
+
'fever': ['fever', 'pyrexia', 'temperature']
|
4258 |
+
}
|
4259 |
+
|
4260 |
+
# Find matching categories
|
4261 |
+
matched_categories = []
|
4262 |
+
for category, terms in category_mappings.items():
|
4263 |
+
if any(term in query_lower for term in terms):
|
4264 |
+
matched_categories.append(category)
|
4265 |
+
|
4266 |
+
# Search in CSV for matching products
|
4267 |
+
matching_products = []
|
4268 |
+
if matched_categories:
|
4269 |
+
for category in matched_categories:
|
4270 |
+
# Search by category name
|
4271 |
+
category_products = products_df[
|
4272 |
+
products_df['Category'].str.lower().str.contains(category, na=False) |
|
4273 |
+
products_df['Product Name'].str.lower().str.contains(category, na=False) |
|
4274 |
+
products_df['Target Species'].str.lower().str.contains(category, na=False) |
|
4275 |
+
products_df['Mode of Action'].str.lower().str.contains(category, na=False)
|
4276 |
+
]
|
4277 |
+
matching_products.extend(category_products.to_dict('records'))
|
4278 |
+
|
4279 |
+
# Remove duplicates
|
4280 |
+
seen_names = set()
|
4281 |
+
unique_products = []
|
4282 |
+
for product in matching_products:
|
4283 |
+
name = product.get('Product Name', '')
|
4284 |
+
if name not in seen_names:
|
4285 |
+
seen_names.add(name)
|
4286 |
+
unique_products.append(product)
|
4287 |
+
|
4288 |
+
matching_products = unique_products
|
4289 |
+
else:
|
4290 |
+
# If no specific category found, search for any terms in the query
|
4291 |
+
query_words = query_lower.split()
|
4292 |
+
for word in query_words:
|
4293 |
+
if len(word) > 3: # Only search for meaningful words
|
4294 |
+
word_products = products_df[
|
4295 |
+
products_df['Category'].str.lower().str.contains(word, na=False) |
|
4296 |
+
products_df['Product Name'].str.lower().str.contains(word, na=False) |
|
4297 |
+
products_df['Target Species'].str.lower().str.contains(word, na=False) |
|
4298 |
+
products_df['Mode of Action'].str.lower().str.contains(word, na=False)
|
4299 |
+
]
|
4300 |
+
matching_products.extend(word_products.to_dict('records'))
|
4301 |
+
|
4302 |
+
# Remove duplicates
|
4303 |
+
seen_names = set()
|
4304 |
+
unique_products = []
|
4305 |
+
for product in matching_products:
|
4306 |
+
name = product.get('Product Name', '')
|
4307 |
+
if name not in seen_names:
|
4308 |
+
seen_names.add(name)
|
4309 |
+
unique_products.append(product)
|
4310 |
+
|
4311 |
+
matching_products = unique_products
|
4312 |
+
|
4313 |
+
# Generate response based on results
|
4314 |
+
if matching_products:
|
4315 |
+
count = len(matching_products)
|
4316 |
+
|
4317 |
+
# Get category breakdown
|
4318 |
+
categories_found = {}
|
4319 |
+
for product in matching_products:
|
4320 |
+
category = product.get('Category', 'Unknown')
|
4321 |
+
categories_found[category] = categories_found.get(category, 0) + 1
|
4322 |
+
|
4323 |
+
if reply_language == 'ur':
|
4324 |
+
response = (
|
4325 |
+
f"📊 *{query}*\n\n"
|
4326 |
+
f"ہمارے پاس **{count}** مصنوعات ملی ہیں۔\n\n"
|
4327 |
+
)
|
4328 |
+
|
4329 |
+
if len(categories_found) > 1:
|
4330 |
+
response += "📂 *زمرے کے مطابق:*\n"
|
4331 |
+
for category, cat_count in categories_found.items():
|
4332 |
+
response += f"• {category}: {cat_count}\n"
|
4333 |
+
response += "\n"
|
4334 |
+
|
4335 |
+
response += (
|
4336 |
+
"💡 *مثال کے طور پر:*\n"
|
4337 |
+
"• 'سانس کی مصنوعات دکھائیں'\n"
|
4338 |
+
"• 'hydropex کے بارے میں بتائیں'\n"
|
4339 |
+
"• 'main' لکھ کر مین مینو پر جائیں"
|
4340 |
+
)
|
4341 |
+
else:
|
4342 |
+
response = (
|
4343 |
+
f"📊 *{query}*\n\n"
|
4344 |
+
f"We found **{count}** products.\n\n"
|
4345 |
+
)
|
4346 |
+
|
4347 |
+
if len(categories_found) > 1:
|
4348 |
+
response += "📂 *By Category:*\n"
|
4349 |
+
for category, cat_count in categories_found.items():
|
4350 |
+
response += f"• {category}: {cat_count}\n"
|
4351 |
+
response += "\n"
|
4352 |
+
|
4353 |
+
response += (
|
4354 |
+
"💡 *Examples:*\n"
|
4355 |
+
"• 'Show me respiratory products'\n"
|
4356 |
+
"• 'Tell me about hydropex'\n"
|
4357 |
+
"• Type 'main' to return to main menu"
|
4358 |
+
)
|
4359 |
+
|
4360 |
+
send_whatsjet_message(from_number, response)
|
4361 |
+
return
|
4362 |
+
else:
|
4363 |
+
# No matching products found
|
4364 |
+
if reply_language == 'ur':
|
4365 |
+
response = (
|
4366 |
+
f"❌ *{query}*\n\n"
|
4367 |
+
"ہمیں کوئی مصنوعات نہیں ملی۔\n\n"
|
4368 |
+
"💡 *مثال کے طور پر:*\n"
|
4369 |
+
"• 'سانس کی مصنوعات'\n"
|
4370 |
+
"• 'جگر کی مصنوعات'\n"
|
4371 |
+
"• 'main' لکھ کر مین مینو پر جائیں"
|
4372 |
+
)
|
4373 |
+
else:
|
4374 |
+
response = (
|
4375 |
+
f"❌ *{query}*\n\n"
|
4376 |
+
"No products found matching your query.\n\n"
|
4377 |
+
"💡 *Try:*\n"
|
4378 |
+
"• 'respiratory products'\n"
|
4379 |
+
"• 'liver products'\n"
|
4380 |
+
"• Type 'main' to return to main menu"
|
4381 |
+
)
|
4382 |
+
|
4383 |
+
send_whatsjet_message(from_number, response)
|
4384 |
+
return
|
4385 |
+
|
4386 |
# Clean and normalize the query
|
4387 |
clean_query = query.strip().lower()
|
4388 |
|