|
|
|
|
|
|
|
""" |
|
GPT-5 Powered Intent Analyzer |
|
Müşteri mesajlarından niyeti anlar ve aksiyonları belirler |
|
""" |
|
|
|
import os |
|
import json |
|
import requests |
|
import logging |
|
from typing import Dict, Optional, List, Tuple |
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") |
|
API_URL = "https://api.openai.com/v1/chat/completions" |
|
|
|
def analyze_customer_intent( |
|
message: str, |
|
context: Optional[Dict] = None |
|
) -> Dict: |
|
""" |
|
GPT-5 ile müşteri niyetini analiz et |
|
|
|
Args: |
|
message: Müşteri mesajı |
|
context: Sohbet bağlamı (varsa) |
|
|
|
Returns: |
|
{ |
|
"intents": ["reserve", "price", "stock", "info"], |
|
"product": "FX 2", |
|
"confidence": 0.95, |
|
"store": "caddebostan", # Eğer belirtildiyse |
|
"urgency": "high/medium/low", |
|
"customer_mood": "positive/neutral/negative", |
|
"suggested_action": "notify_store/answer_directly/both", |
|
"notification_message": "Özel mesaj" |
|
} |
|
""" |
|
|
|
if not OPENAI_API_KEY: |
|
logger.error("OpenAI API key missing") |
|
return {"intents": [], "confidence": 0} |
|
|
|
|
|
system_prompt = """Sen bir müşteri niyet analiz uzmanısın. Trek bisiklet mağazası için müşteri mesajlarını analiz ediyorsun. |
|
|
|
GÖREV: Müşteri mesajını analiz et ve JSON formatında döndür. |
|
|
|
NİYET TİPLERİ: |
|
- "reserve": Ürünü ayırtmak, rezerve etmek, tutmak istiyor |
|
- "price": Fiyat bilgisi istiyor |
|
- "stock": Stok durumu soruyor |
|
- "info": Genel bilgi istiyor |
|
- "complaint": Şikayet ediyor |
|
- "order": Sipariş vermek istiyor |
|
- "test_ride": Test sürüşü istiyor |
|
- "service": Servis/tamir istiyor |
|
- "none": Belirgin bir niyet yok |
|
|
|
ÖRNEK CÜMLELER: |
|
- "bu bisikleti ayırtabilir misiniz" → reserve |
|
- "yarın gelip alabilirim" → reserve |
|
- "benim için tutun" → reserve |
|
- "fiyatı nedir" → price |
|
- "kaç para" → price |
|
- "var mı" → stock |
|
- "stokta mı" → stock |
|
- "özellikleri nelerdir" → info |
|
- "test edebilir miyim" → test_ride |
|
|
|
ACİLİYET: |
|
- high: Hemen aksiyon gerekiyor (ayırtma, hemen alma isteği) |
|
- medium: Normal takip yeterli |
|
- low: Bilgi amaçlı |
|
|
|
JSON FORMATI: |
|
{ |
|
"intents": ["reserve", "price"], // Birden fazla olabilir |
|
"product": "FX 2", // Eğer üründen bahsediyorsa |
|
"confidence": 0.95, // 0-1 arası güven skoru |
|
"store": null, // Mağaza adı varsa |
|
"urgency": "high", |
|
"customer_mood": "positive", |
|
"suggested_action": "notify_store", // notify_store, answer_directly, both, none |
|
"notification_required": true, |
|
"notification_reason": "Müşteri FX 2'yi ayırtmak istiyor" |
|
}""" |
|
|
|
|
|
context_info = "" |
|
if context: |
|
if context.get("current_category"): |
|
context_info = f"\nSON KONUŞULAN ÜRÜN: {context['current_category']}" |
|
if context.get("messages"): |
|
last_msg = context["messages"][-1] if context["messages"] else None |
|
if last_msg: |
|
context_info += f"\nÖNCEKİ MESAJ: {last_msg.get('user', '')}" |
|
|
|
|
|
try: |
|
messages = [ |
|
{"role": "system", "content": system_prompt}, |
|
{"role": "user", "content": f"Müşteri mesajı: \"{message}\"{context_info}\n\nJSON formatında analiz et:"} |
|
] |
|
|
|
payload = { |
|
"model": "gpt-5-chat-latest", |
|
"messages": messages, |
|
"temperature": 0, |
|
"max_tokens": 300, |
|
"response_format": {"type": "json_object"} |
|
} |
|
|
|
headers = { |
|
"Content-Type": "application/json", |
|
"Authorization": f"Bearer {OPENAI_API_KEY}" |
|
} |
|
|
|
response = requests.post(API_URL, headers=headers, json=payload, timeout=10) |
|
|
|
if response.status_code == 200: |
|
result = response.json() |
|
analysis = json.loads(result['choices'][0]['message']['content']) |
|
|
|
logger.info(f"🧠 Intent Analysis: {analysis}") |
|
return analysis |
|
else: |
|
logger.error(f"GPT-5 API error: {response.status_code}") |
|
return {"intents": [], "confidence": 0} |
|
|
|
except Exception as e: |
|
logger.error(f"Intent analysis error: {e}") |
|
return {"intents": [], "confidence": 0} |
|
|
|
def should_notify_store(analysis: Dict) -> Tuple[bool, str]: |
|
""" |
|
Mağazaya bildirim gönderilmeli mi? |
|
|
|
Returns: |
|
(should_notify, reason) |
|
""" |
|
|
|
|
|
if "reserve" in analysis.get("intents", []) and analysis.get("confidence", 0) > 0.7: |
|
return True, "Müşteri ürünü ayırtmak istiyor" |
|
|
|
|
|
if "stock" in analysis.get("intents", []) and analysis.get("urgency") == "high": |
|
return True, "Müşteri acil stok bilgisi istiyor" |
|
|
|
|
|
if "test_ride" in analysis.get("intents", []): |
|
return True, "Müşteri test sürüşü talep ediyor" |
|
|
|
|
|
if "order" in analysis.get("intents", []) and analysis.get("confidence", 0) > 0.8: |
|
return True, "Müşteri sipariş vermek istiyor" |
|
|
|
|
|
if "complaint" in analysis.get("intents", []): |
|
return True, "Müşteri şikayette bulunuyor" |
|
|
|
|
|
if analysis.get("suggested_action") in ["notify_store", "both"]: |
|
return True, analysis.get("notification_reason", "GPT-5 bildirim öneriyor") |
|
|
|
return False, "" |
|
|
|
def get_smart_notification_message( |
|
analysis: Dict, |
|
customer_phone: str, |
|
original_message: str |
|
) -> str: |
|
""" |
|
Analiz sonucuna göre akıllı bildirim mesajı oluştur |
|
""" |
|
|
|
intents = analysis.get("intents", []) |
|
product = analysis.get("product", "Belirtilmemiş") |
|
urgency = analysis.get("urgency", "medium") |
|
mood = analysis.get("customer_mood", "neutral") |
|
|
|
|
|
if "reserve" in intents: |
|
emoji = "🔔" |
|
title = "AYIRTMA TALEBİ" |
|
elif "price" in intents: |
|
emoji = "💰" |
|
title = "FİYAT SORUSU" |
|
elif "stock" in intents: |
|
emoji = "📦" |
|
title = "STOK SORUSU" |
|
elif "test_ride" in intents: |
|
emoji = "🚴" |
|
title = "TEST SÜRÜŞÜ TALEBİ" |
|
elif "complaint" in intents: |
|
emoji = "⚠️" |
|
title = "ŞİKAYET" |
|
elif "order" in intents: |
|
emoji = "🛒" |
|
title = "SİPARİŞ TALEBİ" |
|
else: |
|
emoji = "ℹ️" |
|
title = "MÜŞTERİ TALEBİ" |
|
|
|
|
|
if urgency == "high": |
|
title = f"🚨 ACİL - {title}" |
|
|
|
|
|
from datetime import datetime |
|
now = datetime.now() |
|
date_str = now.strftime("%d.%m.%Y %H:%M") |
|
|
|
message_parts = [ |
|
f"{emoji} **{title}**", |
|
f"📅 {date_str}", |
|
"", |
|
f"👤 **Müşteri:** {customer_phone.replace('whatsapp:', '')}", |
|
f"🚲 **Ürün:** {product}", |
|
f"💬 **Mesaj:** \"{original_message}\"", |
|
"", |
|
"📊 **AI Analizi:**" |
|
] |
|
|
|
|
|
intent_map = { |
|
"reserve": "✓ Ayırtma isteği", |
|
"price": "✓ Fiyat bilgisi", |
|
"stock": "✓ Stok durumu", |
|
"test_ride": "✓ Test sürüşü", |
|
"order": "✓ Sipariş", |
|
"complaint": "✓ Şikayet", |
|
"info": "✓ Bilgi talebi" |
|
} |
|
|
|
for intent in intents: |
|
if intent in intent_map: |
|
message_parts.append(f" {intent_map[intent]}") |
|
|
|
|
|
mood_map = { |
|
"positive": "😊 Pozitif", |
|
"neutral": "😐 Nötr", |
|
"negative": "😟 Negatif" |
|
} |
|
message_parts.append(f" Müşteri Durumu: {mood_map.get(mood, mood)}") |
|
message_parts.append(f" Aciliyet: {'🔴 Yüksek' if urgency == 'high' else '🟡 Orta' if urgency == 'medium' else '🟢 Düşük'}") |
|
|
|
|
|
message_parts.extend([ |
|
"", |
|
"✅ **Önerilen Aksiyon:**" |
|
]) |
|
|
|
if "reserve" in intents: |
|
message_parts.extend([ |
|
"1. Stok kontrolü yapın", |
|
"2. Müşteriyi hemen arayın", |
|
"3. Ödeme ve teslimat planı belirleyin" |
|
]) |
|
elif "test_ride" in intents: |
|
message_parts.extend([ |
|
"1. Test bisikleti hazırlığı", |
|
"2. Randevu ayarlayın", |
|
"3. Kimlik ve güvenlik prosedürü" |
|
]) |
|
elif "complaint" in intents: |
|
message_parts.extend([ |
|
"1. Müşteriyi hemen arayın", |
|
"2. Sorunu dinleyin", |
|
"3. Çözüm önerisi sunun" |
|
]) |
|
else: |
|
message_parts.append("Müşteri ile iletişime geçin") |
|
|
|
message_parts.extend([ |
|
"", |
|
"---", |
|
"Trek AI Assistant" |
|
]) |
|
|
|
return "\n".join(message_parts) |
|
|
|
|
|
def test_intent_analysis(): |
|
"""Test senaryoları""" |
|
|
|
test_messages = [ |
|
"FX 2'yi ayırtabilir misiniz?", |
|
"Marlin 5'in fiyatı ne kadar?", |
|
"Stokta var mı?", |
|
"Yarın gelip alabilirim", |
|
"Test sürüşü yapabilir miyim?", |
|
"Bisikletim bozuldu", |
|
"Teşekkürler", |
|
"Merhaba", |
|
"Sipariş vermek istiyorum" |
|
] |
|
|
|
print("\n" + "="*60) |
|
print("INTENT ANALYSIS TEST") |
|
print("="*60) |
|
|
|
for msg in test_messages: |
|
print(f"\n📝 Mesaj: \"{msg}\"") |
|
analysis = analyze_customer_intent(msg) |
|
|
|
if analysis.get("intents"): |
|
print(f"🎯 Niyetler: {', '.join(analysis['intents'])}") |
|
print(f"📊 Güven: {analysis.get('confidence', 0):.2%}") |
|
print(f"🚨 Aciliyet: {analysis.get('urgency', 'unknown')}") |
|
|
|
should_notify, reason = should_notify_store(analysis) |
|
print(f"🔔 Bildirim: {'EVET' if should_notify else 'HAYIR'}") |
|
if reason: |
|
print(f" Sebep: {reason}") |
|
else: |
|
print("❌ Niyet tespit edilemedi") |
|
|
|
print("\n" + "="*60) |
|
|
|
if __name__ == "__main__": |
|
test_intent_analysis() |