|
""" |
|
WhatsApp Improved Chatbot with Professional Product Search |
|
Optimized for mobile WhatsApp formatting |
|
""" |
|
|
|
from product_search import ProductSearchEngine |
|
import re |
|
from typing import List, Dict, Optional, Tuple |
|
|
|
class WhatsAppImprovedChatbot: |
|
"""Enhanced chatbot with intelligent product handling for WhatsApp""" |
|
|
|
def __init__(self, products: List[Tuple]): |
|
"""Initialize with product list""" |
|
self.search_engine = ProductSearchEngine(products) |
|
self.products = products |
|
|
|
def detect_product_query(self, message: str) -> bool: |
|
"""Detect if message is asking about products""" |
|
product_keywords = [ |
|
'bisiklet', 'bike', 'model', 'fiyat', 'price', 'stok', 'stock', |
|
'özellikleri', 'features', 'hangi', 'which', 'var mı', 'mevcut', |
|
'kaç', 'how much', 'ne kadar', 'kampanya', 'indirim', 'discount', |
|
'karşılaştır', 'compare', 'benzer', 'similar', 'alternatif', |
|
'öneri', 'recommend', 'tavsiye', 'suggest' |
|
] |
|
|
|
message_lower = message.lower() |
|
|
|
|
|
if any(keyword in message_lower for keyword in product_keywords): |
|
return True |
|
|
|
|
|
if re.search(r'\b\d+\.?\d*\b', message): |
|
return True |
|
|
|
|
|
categories = ['trek', 'marlin', 'fuel', 'slash', 'remedy', 'checkpoint', |
|
'domane', 'madone', 'emonda', 'fx', 'dual', 'wahoo', 'powerfly'] |
|
if any(cat in message_lower for cat in categories): |
|
return True |
|
|
|
return False |
|
|
|
def extract_query_intent(self, message: str) -> Dict: |
|
"""Extract the intent from user query""" |
|
intent = { |
|
'type': 'general', |
|
'action': None, |
|
'filters': {} |
|
} |
|
|
|
message_lower = message.lower() |
|
|
|
|
|
if any(word in message_lower for word in ['fiyat', 'price', 'kaç', 'ne kadar', 'how much']): |
|
intent['type'] = 'price' |
|
intent['action'] = 'get_price' |
|
|
|
|
|
elif any(word in message_lower for word in ['stok', 'stock', 'var mı', 'mevcut', 'available']): |
|
intent['type'] = 'stock' |
|
intent['action'] = 'check_stock' |
|
|
|
|
|
elif any(word in message_lower for word in ['karşılaştır', 'compare', 'fark', 'difference']): |
|
intent['type'] = 'comparison' |
|
intent['action'] = 'compare_products' |
|
|
|
|
|
elif any(word in message_lower for word in ['öneri', 'recommend', 'tavsiye', 'suggest', 'hangi']): |
|
intent['type'] = 'recommendation' |
|
intent['action'] = 'recommend' |
|
|
|
|
|
elif any(word in message_lower for word in ['özellik', 'feature', 'spec', 'detay', 'detail']): |
|
intent['type'] = 'features' |
|
intent['action'] = 'get_features' |
|
|
|
|
|
context = self.search_engine.extract_product_context(message) |
|
intent['filters'] = context |
|
|
|
return intent |
|
|
|
def format_product_info_whatsapp(self, product: Tuple, intent: Dict) -> str: |
|
"""Format product information for WhatsApp""" |
|
name = product[2] |
|
info = product[1] |
|
|
|
|
|
stock_status = info[0] if len(info) > 0 else "bilinmiyor" |
|
|
|
|
|
response_parts = [] |
|
|
|
|
|
if stock_status == "stokta": |
|
response_parts.append(f"🚴♂️ *{name}*") |
|
response_parts.append("✅ *Stokta mevcut*") |
|
else: |
|
response_parts.append(f"🚴♂️ *{name}*") |
|
response_parts.append("❌ *Stokta yok*") |
|
|
|
|
|
if intent['type'] in ['price', 'general'] and stock_status == "stokta" and len(info) > 1: |
|
price = info[1] |
|
response_parts.append(f"💰 *Fiyat:* {price} TL") |
|
|
|
|
|
if len(info) > 4 and info[4]: |
|
response_parts.append(f"🎯 *Kampanya:* {info[4]} TL") |
|
|
|
|
|
try: |
|
normal_price = float(info[1]) |
|
campaign_price = float(info[4]) |
|
discount = normal_price - campaign_price |
|
if discount > 0: |
|
response_parts.append(f"💸 *İndirim:* {discount:.0f} TL") |
|
except: |
|
pass |
|
|
|
|
|
elif len(info) > 3 and info[3]: |
|
response_parts.append(f"🏦 *Havale:* {info[3]} TL") |
|
|
|
|
|
if len(info) > 2 and info[2]: |
|
response_parts.append(f"🔗 Ürün sayfası: {info[2]}") |
|
|
|
return "\n".join(response_parts) |
|
|
|
def generate_product_response(self, message: str) -> str: |
|
"""Generate response for product queries optimized for WhatsApp""" |
|
intent = self.extract_query_intent(message) |
|
|
|
|
|
search_results = self.search_engine.search(message) |
|
|
|
if not search_results: |
|
|
|
response = self._handle_no_results_whatsapp(message) |
|
elif len(search_results) == 1: |
|
|
|
product = search_results[0][1] |
|
response = self.format_product_info_whatsapp(product, intent) |
|
elif search_results[0][0] > 0.9: |
|
|
|
product = search_results[0][1] |
|
response = self.format_product_info_whatsapp(product, intent) |
|
else: |
|
|
|
response = self._handle_multiple_results_whatsapp(search_results[:3], intent) |
|
|
|
return response |
|
|
|
def _handle_no_results_whatsapp(self, query: str) -> str: |
|
"""Handle case when no products are found - WhatsApp format""" |
|
response_parts = ["🤔 *Aradığınız ürünü bulamadım.*"] |
|
|
|
|
|
suggestions = self.search_engine.generate_suggestions(query) |
|
|
|
if suggestions: |
|
response_parts.append("\n💡 *Belki şunları arıyor olabilirsiniz:*") |
|
for i, suggestion in enumerate(suggestions[:2], 1): |
|
response_parts.append(f"{i}. {suggestion}") |
|
else: |
|
response_parts.append("\n📝 *Örnek aramalar:*") |
|
response_parts.append("• Marlin 5") |
|
response_parts.append("• FX 3 Disc") |
|
response_parts.append("• Checkpoint ALR 5") |
|
|
|
return "\n".join(response_parts) |
|
|
|
def _handle_multiple_results_whatsapp(self, results: List[Tuple[float, Tuple]], intent: Dict) -> str: |
|
"""Handle multiple product results - WhatsApp format""" |
|
response_parts = ["📋 *Birden fazla ürün buldum:*\n"] |
|
|
|
for i, (score, product) in enumerate(results, 1): |
|
name = product[2] |
|
stock = product[1][0] if len(product[1]) > 0 else "bilinmiyor" |
|
|
|
|
|
if stock == "stokta": |
|
status_emoji = "✅" |
|
response_parts.append(f"*{i}. {name}* {status_emoji}") |
|
|
|
|
|
if intent['type'] in ['price', 'general'] and len(product[1]) > 1: |
|
price = product[1][1] |
|
response_parts.append(f" 💰 {price} TL") |
|
|
|
|
|
if len(product[1]) > 4 and product[1][4]: |
|
response_parts.append(f" 🎯 Kampanya: {product[1][4]} TL") |
|
|
|
|
|
if len(product[1]) > 2 and product[1][2]: |
|
response_parts.append(f" 🔗 {product[1][2]}") |
|
else: |
|
status_emoji = "❌" |
|
response_parts.append(f"*{i}. {name}* {status_emoji}") |
|
|
|
response_parts.append("") |
|
|
|
response_parts.append("💡 _Daha detaylı bilgi için ürün adını yazın_") |
|
|
|
return "\n".join(response_parts) |
|
|
|
def handle_comparison_whatsapp(self, message: str) -> Optional[str]: |
|
"""Handle product comparison requests - WhatsApp format""" |
|
|
|
comparison_words = ['ile', 've', 'vs', 'versus', 'karşılaştır', 'arasında'] |
|
|
|
products_to_compare = [] |
|
|
|
|
|
for word in comparison_words: |
|
if word in message.lower(): |
|
parts = message.lower().split(word) |
|
if len(parts) >= 2: |
|
|
|
for part in parts[:2]: |
|
result = self.search_engine.find_best_match(part.strip()) |
|
if result: |
|
products_to_compare.append(result) |
|
|
|
if len(products_to_compare) < 2: |
|
|
|
search_results = self.search_engine.search(message) |
|
products_to_compare = [r[1] for r in search_results[:2] if r[0] > 0.6] |
|
|
|
if len(products_to_compare) >= 2: |
|
return self._format_comparison_whatsapp(products_to_compare[:2]) |
|
|
|
return None |
|
|
|
def _format_comparison_whatsapp(self, products: List[Tuple]) -> str: |
|
"""Format product comparison for WhatsApp""" |
|
response_parts = ["📊 *Ürün Karşılaştırması*\n"] |
|
|
|
for i, product in enumerate(products, 1): |
|
name = product[2] |
|
info = product[1] |
|
|
|
response_parts.append(f"*{i}. {name}*") |
|
|
|
|
|
stock = info[0] if len(info) > 0 else "bilinmiyor" |
|
if stock == "stokta": |
|
response_parts.append("✅ Stokta mevcut") |
|
else: |
|
response_parts.append("❌ Stokta yok") |
|
|
|
|
|
if stock == "stokta" and len(info) > 1: |
|
price = info[1] |
|
response_parts.append(f"💰 {price} TL") |
|
|
|
if len(info) > 4 and info[4]: |
|
response_parts.append(f"🎯 Kampanya: {info[4]} TL") |
|
|
|
response_parts.append("") |
|
|
|
return "\n".join(response_parts) |
|
|
|
def process_message(self, message: str) -> Dict: |
|
"""Process user message and return structured response optimized for WhatsApp""" |
|
result = { |
|
'is_product_query': False, |
|
'response': None, |
|
'products_found': [], |
|
'intent': None |
|
} |
|
|
|
|
|
if self.detect_product_query(message): |
|
result['is_product_query'] = True |
|
result['intent'] = self.extract_query_intent(message) |
|
|
|
|
|
if result['intent']['type'] == 'comparison': |
|
comparison_result = self.handle_comparison_whatsapp(message) |
|
if comparison_result: |
|
result['response'] = comparison_result |
|
return result |
|
|
|
|
|
result['response'] = self.generate_product_response(message) |
|
|
|
|
|
search_results = self.search_engine.search(message) |
|
result['products_found'] = [r[1] for r in search_results[:2] if r[0] > 0.6] |
|
|
|
return result |