Upload 2 files
Browse files- app.py +65 -15
- enhanced_features.py +178 -7
app.py
CHANGED
@@ -6,6 +6,8 @@ import xml.etree.ElementTree as ET
|
|
6 |
import schedule
|
7 |
import time
|
8 |
import threading
|
|
|
|
|
9 |
from huggingface_hub import HfApi, create_repo, hf_hub_download
|
10 |
import warnings
|
11 |
import pandas as pd
|
@@ -25,7 +27,8 @@ from prompts import get_prompt_content_only
|
|
25 |
# Enhanced features import et
|
26 |
from enhanced_features import (
|
27 |
initialize_enhanced_features, process_image_message,
|
28 |
-
handle_comparison_request, get_user_recommendations, profile_manager
|
|
|
29 |
)
|
30 |
from image_renderer import extract_product_info_for_gallery, format_message_with_images
|
31 |
|
@@ -330,17 +333,17 @@ def chatbot_fn(user_message, history, image=None):
|
|
330 |
return
|
331 |
|
332 |
# Enhanced features - Kişisel öneriler
|
333 |
-
user_id =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
334 |
recommendation_result = get_user_recommendations(user_id, user_message)
|
335 |
if recommendation_result:
|
336 |
-
# Kullanıcı etkileşimini kaydet
|
337 |
-
try:
|
338 |
-
profile_manager.add_interaction(user_id, "recommendation_request", {
|
339 |
-
"message": user_message,
|
340 |
-
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
|
341 |
-
})
|
342 |
-
except Exception as e:
|
343 |
-
print(f"Profile save error: {e}")
|
344 |
yield recommendation_result
|
345 |
return
|
346 |
|
@@ -362,6 +365,30 @@ def chatbot_fn(user_message, history, image=None):
|
|
362 |
# Döküman verilerini sistem mesajlarına ekle
|
363 |
if document_content:
|
364 |
system_messages.append({"role": "system", "content": f"Dökümanlardan gelen bilgiler: {document_content}"})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
365 |
|
366 |
# Kullanıcı mesajında ürün ismi geçiyorsa ekle
|
367 |
input_words = user_message.lower().split()
|
@@ -805,10 +832,22 @@ with gr.Blocks(css=custom_css, theme="soft", title="Trek Asistanı") as demo:
|
|
805 |
elem_id="msg-input"
|
806 |
)
|
807 |
|
808 |
-
|
|
|
|
|
|
|
809 |
if not message.strip():
|
810 |
-
return "", chat_history
|
811 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
812 |
# Chat history'yi chatbot_fn için uygun formata çevir
|
813 |
formatted_history = []
|
814 |
if chat_history:
|
@@ -829,7 +868,18 @@ with gr.Blocks(css=custom_css, theme="soft", title="Trek Asistanı") as demo:
|
|
829 |
if chat_history is None:
|
830 |
chat_history = []
|
831 |
chat_history.append((message, response))
|
832 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
833 |
|
834 |
except Exception as e:
|
835 |
error_msg = f"Üzgünüm, bir hata oluştu: {str(e)}"
|
@@ -837,9 +887,9 @@ with gr.Blocks(css=custom_css, theme="soft", title="Trek Asistanı") as demo:
|
|
837 |
if chat_history is None:
|
838 |
chat_history = []
|
839 |
chat_history.append((message, error_msg))
|
840 |
-
return "", chat_history
|
841 |
|
842 |
-
msg.submit(respond, [msg, chatbot], [msg, chatbot])
|
843 |
|
844 |
if __name__ == "__main__":
|
845 |
demo.launch(debug=True)
|
|
|
6 |
import schedule
|
7 |
import time
|
8 |
import threading
|
9 |
+
import uuid
|
10 |
+
import hashlib
|
11 |
from huggingface_hub import HfApi, create_repo, hf_hub_download
|
12 |
import warnings
|
13 |
import pandas as pd
|
|
|
27 |
# Enhanced features import et
|
28 |
from enhanced_features import (
|
29 |
initialize_enhanced_features, process_image_message,
|
30 |
+
handle_comparison_request, get_user_recommendations, profile_manager,
|
31 |
+
get_user_profile_summary, get_user_chat_context
|
32 |
)
|
33 |
from image_renderer import extract_product_info_for_gallery, format_message_with_images
|
34 |
|
|
|
333 |
return
|
334 |
|
335 |
# Enhanced features - Kişisel öneriler
|
336 |
+
user_id = getattr(chatbot_fn, '_current_session_id', 'default_user')
|
337 |
+
|
338 |
+
# Profil sorguları kontrol et
|
339 |
+
if any(keyword in user_message.lower() for keyword in ["profil", "tercih", "geçmiş", "hatırla", "kaydet"]):
|
340 |
+
profile_summary = get_user_profile_summary(user_id)
|
341 |
+
yield profile_summary
|
342 |
+
return
|
343 |
+
|
344 |
recommendation_result = get_user_recommendations(user_id, user_message)
|
345 |
if recommendation_result:
|
346 |
+
# Kullanıcı etkileşimini kaydet (artık get_user_recommendations içinde)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
347 |
yield recommendation_result
|
348 |
return
|
349 |
|
|
|
365 |
# Döküman verilerini sistem mesajlarına ekle
|
366 |
if document_content:
|
367 |
system_messages.append({"role": "system", "content": f"Dökümanlardan gelen bilgiler: {document_content}"})
|
368 |
+
|
369 |
+
# Kullanıcı profil bilgilerini ve geçmiş kontekstini ekle
|
370 |
+
try:
|
371 |
+
user_id = getattr(chatbot_fn, '_current_session_id', 'default_user')
|
372 |
+
profile = profile_manager.get_or_create_profile(user_id)
|
373 |
+
preferences = profile.get("preferences", {})
|
374 |
+
|
375 |
+
# Kullanıcı tercihlerini sistem mesajı olarak ekle
|
376 |
+
if any(preferences.values()):
|
377 |
+
pref_info = []
|
378 |
+
if preferences.get("bike_category"):
|
379 |
+
pref_info.append(f"Kategori: {preferences['bike_category']}")
|
380 |
+
if preferences.get("budget_range"):
|
381 |
+
pref_info.append(f"Bütçe: {preferences['budget_range'][0]:,.0f}-{preferences['budget_range'][1]:,.0f} TL")
|
382 |
+
if preferences.get("usage_purpose"):
|
383 |
+
pref_info.append(f"Kullanım amacı: {preferences['usage_purpose']}")
|
384 |
+
|
385 |
+
if pref_info:
|
386 |
+
system_messages.append({
|
387 |
+
"role": "system",
|
388 |
+
"content": f"KULLANICI TERÇİHLERİ: {', '.join(pref_info)}. Bu bilgileri dikkate alarak daha kişiselleştirilmiş öneriler sun."
|
389 |
+
})
|
390 |
+
except Exception as e:
|
391 |
+
print(f"Profile context error: {e}")
|
392 |
|
393 |
# Kullanıcı mesajında ürün ismi geçiyorsa ekle
|
394 |
input_words = user_message.lower().split()
|
|
|
832 |
elem_id="msg-input"
|
833 |
)
|
834 |
|
835 |
+
# Session state için gizli bileşen
|
836 |
+
session_state = gr.State({})
|
837 |
+
|
838 |
+
def respond(message, chat_history, session_state):
|
839 |
if not message.strip():
|
840 |
+
return "", chat_history, session_state
|
841 |
|
842 |
+
# Session ID oluştur veya mevcut olanı kullan
|
843 |
+
if not session_state or 'session_id' not in session_state:
|
844 |
+
# Browser fingerprint benzeri benzersiz ID oluştur
|
845 |
+
session_id = str(uuid.uuid4())[:8] + hashlib.md5(str(time.time()).encode()).hexdigest()[:8]
|
846 |
+
session_state = {'session_id': session_id}
|
847 |
+
|
848 |
+
# Session ID'yi chatbot_fn'e geç
|
849 |
+
chatbot_fn._current_session_id = session_state['session_id']
|
850 |
+
|
851 |
# Chat history'yi chatbot_fn için uygun formata çevir
|
852 |
formatted_history = []
|
853 |
if chat_history:
|
|
|
868 |
if chat_history is None:
|
869 |
chat_history = []
|
870 |
chat_history.append((message, response))
|
871 |
+
|
872 |
+
# Kullanıcı profiline sohbet geçmişini kaydet
|
873 |
+
try:
|
874 |
+
profile_manager.add_interaction(session_state['session_id'], "chat_message", {
|
875 |
+
"user_message": message,
|
876 |
+
"bot_response": response,
|
877 |
+
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
|
878 |
+
})
|
879 |
+
except Exception as e:
|
880 |
+
print(f"Profile chat save error: {e}")
|
881 |
+
|
882 |
+
return "", chat_history, session_state
|
883 |
|
884 |
except Exception as e:
|
885 |
error_msg = f"Üzgünüm, bir hata oluştu: {str(e)}"
|
|
|
887 |
if chat_history is None:
|
888 |
chat_history = []
|
889 |
chat_history.append((message, error_msg))
|
890 |
+
return "", chat_history, session_state
|
891 |
|
892 |
+
msg.submit(respond, [msg, chatbot, session_state], [msg, chatbot, session_state])
|
893 |
|
894 |
if __name__ == "__main__":
|
895 |
demo.launch(debug=True)
|
enhanced_features.py
CHANGED
@@ -70,7 +70,76 @@ class UserProfileManager:
|
|
70 |
profile["interaction_history"].append(interaction)
|
71 |
# Son 50 etkileşimi tut
|
72 |
profile["interaction_history"] = profile["interaction_history"][-50:]
|
|
|
|
|
|
|
|
|
73 |
self.save_profiles()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
|
75 |
class VisualAI:
|
76 |
"""Görsel AI işlemleri"""
|
@@ -356,9 +425,79 @@ def handle_comparison_request(user_message):
|
|
356 |
print(f"Comparison error: {e}")
|
357 |
return None
|
358 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
359 |
def get_user_recommendations(user_id, user_message):
|
360 |
"""Kullanıcıya özel öneriler al"""
|
361 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
362 |
# Bütçe sorgusu varsa
|
363 |
if "bütçe" in user_message.lower() or "budget" in user_message.lower():
|
364 |
# Rakamları çıkarmaya çalış
|
@@ -376,15 +515,47 @@ def get_user_recommendations(user_id, user_message):
|
|
376 |
for product in recommendations[:3]:
|
377 |
rec_text += f"• {product[2]} - {product[1][1]} TL\n"
|
378 |
return rec_text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
379 |
|
380 |
-
#
|
381 |
if personalized_recommendations:
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
388 |
|
389 |
return None
|
390 |
except Exception as e:
|
|
|
70 |
profile["interaction_history"].append(interaction)
|
71 |
# Son 50 etkileşimi tut
|
72 |
profile["interaction_history"] = profile["interaction_history"][-50:]
|
73 |
+
|
74 |
+
# Otomatik tercih çıkarımı
|
75 |
+
self._extract_preferences_from_interaction(user_id, interaction_type, data)
|
76 |
+
|
77 |
self.save_profiles()
|
78 |
+
|
79 |
+
def _extract_preferences_from_interaction(self, user_id, interaction_type, data):
|
80 |
+
"""Etkileşimden otomatik tercih çıkarımı"""
|
81 |
+
profile = self.get_or_create_profile(user_id)
|
82 |
+
|
83 |
+
if interaction_type == "chat_message":
|
84 |
+
user_message = data.get("user_message", "").lower()
|
85 |
+
|
86 |
+
# Bütçe tespiti
|
87 |
+
import re
|
88 |
+
if "bütçe" in user_message or "budget" in user_message:
|
89 |
+
numbers = re.findall(r'\d+', user_message)
|
90 |
+
if len(numbers) >= 1:
|
91 |
+
try:
|
92 |
+
budget_value = int(numbers[0]) * 1000 # K TL formatı için
|
93 |
+
if budget_value > 10000: # Makul bütçe aralığı
|
94 |
+
current_budget = profile["preferences"].get("budget_range")
|
95 |
+
if not current_budget:
|
96 |
+
# Bütçe aralığını tahmin et
|
97 |
+
budget_max = budget_value * 1.5
|
98 |
+
profile["preferences"]["budget_range"] = [budget_value, budget_max]
|
99 |
+
except ValueError:
|
100 |
+
pass
|
101 |
+
|
102 |
+
# Bisiklet kategorisi tespiti
|
103 |
+
bike_categories = {
|
104 |
+
"dağ": "dağ bisikleti",
|
105 |
+
"mountain": "dağ bisikleti",
|
106 |
+
"mtb": "dağ bisikleti",
|
107 |
+
"yol": "yol bisikleti",
|
108 |
+
"road": "yol bisikleti",
|
109 |
+
"şehir": "şehir bisikleti",
|
110 |
+
"city": "şehir bisikleti",
|
111 |
+
"urban": "şehir bisikleti",
|
112 |
+
"elektrikli": "elektrikli bisiklet",
|
113 |
+
"electric": "elektrikli bisiklet",
|
114 |
+
"e-bike": "elektrikli bisiklet",
|
115 |
+
"gravel": "gravel bisiklet"
|
116 |
+
}
|
117 |
+
|
118 |
+
for keyword, category in bike_categories.items():
|
119 |
+
if keyword in user_message:
|
120 |
+
profile["preferences"]["bike_category"] = category
|
121 |
+
break
|
122 |
+
|
123 |
+
# Kullanım amacı tespiti
|
124 |
+
usage_purposes = {
|
125 |
+
"işe": "günlük ulaşım",
|
126 |
+
"work": "günlük ulaşım",
|
127 |
+
"spor": "spor ve egzersiz",
|
128 |
+
"sport": "spor ve egzersiz",
|
129 |
+
"egzersiz": "spor ve egzersiz",
|
130 |
+
"fitness": "spor ve egzersiz",
|
131 |
+
"tur": "tur ve gezi",
|
132 |
+
"tour": "tur ve gezi",
|
133 |
+
"gezi": "tur ve gezi",
|
134 |
+
"yarış": "yarış ve performans",
|
135 |
+
"race": "yarış ve performans",
|
136 |
+
"performance": "yarış ve performans"
|
137 |
+
}
|
138 |
+
|
139 |
+
for keyword, purpose in usage_purposes.items():
|
140 |
+
if keyword in user_message:
|
141 |
+
profile["preferences"]["usage_purpose"] = purpose
|
142 |
+
break
|
143 |
|
144 |
class VisualAI:
|
145 |
"""Görsel AI işlemleri"""
|
|
|
425 |
print(f"Comparison error: {e}")
|
426 |
return None
|
427 |
|
428 |
+
def get_user_chat_context(user_id, limit=5):
|
429 |
+
"""Son sohbet geçmişini kontekst için al"""
|
430 |
+
try:
|
431 |
+
profile = profile_manager.get_or_create_profile(user_id)
|
432 |
+
interactions = profile.get("interaction_history", [])
|
433 |
+
|
434 |
+
# Son chat mesajlarını al
|
435 |
+
chat_messages = []
|
436 |
+
for interaction in reversed(interactions):
|
437 |
+
if interaction['type'] == 'chat_message' and len(chat_messages) < limit:
|
438 |
+
data = interaction['data']
|
439 |
+
chat_messages.append({
|
440 |
+
"user": data.get('user_message', ''),
|
441 |
+
"assistant": data.get('bot_response', ''),
|
442 |
+
"timestamp": data.get('timestamp', '')
|
443 |
+
})
|
444 |
+
|
445 |
+
return list(reversed(chat_messages)) # Kronolojik sıra
|
446 |
+
|
447 |
+
except Exception as e:
|
448 |
+
print(f"Chat context error: {e}")
|
449 |
+
return []
|
450 |
+
|
451 |
+
def get_user_profile_summary(user_id):
|
452 |
+
"""Kullanıcı profil özetini döndür"""
|
453 |
+
try:
|
454 |
+
profile = profile_manager.get_or_create_profile(user_id)
|
455 |
+
preferences = profile.get("preferences", {})
|
456 |
+
|
457 |
+
if not any(preferences.values()):
|
458 |
+
return "Henüz tercihleriniz kaydedilmemiş. Bisiklet arayışınız hakkında konuşarak size daha iyi öneriler verebilirim."
|
459 |
+
|
460 |
+
summary = "🔄 **Kaydedilen Tercihleriniz:**\n\n"
|
461 |
+
|
462 |
+
if preferences.get("bike_category"):
|
463 |
+
summary += f"🚲 **Bisiklet Kategorisi:** {preferences['bike_category']}\n"
|
464 |
+
|
465 |
+
if preferences.get("budget_range"):
|
466 |
+
budget_min, budget_max = preferences['budget_range']
|
467 |
+
summary += f"💰 **Bütçe Aralığı:** {budget_min:,.0f} - {budget_max:,.0f} TL\n"
|
468 |
+
|
469 |
+
if preferences.get("usage_purpose"):
|
470 |
+
summary += f"🎯 **Kullanım Amacı:** {preferences['usage_purpose']}\n"
|
471 |
+
|
472 |
+
if preferences.get("size"):
|
473 |
+
summary += f"📏 **Boyut:** {preferences['size']}\n"
|
474 |
+
|
475 |
+
# Son etkileşimler
|
476 |
+
interactions = profile.get("interaction_history", [])
|
477 |
+
if interactions:
|
478 |
+
recent_chats = [i for i in interactions[-5:] if i['type'] == 'chat_message']
|
479 |
+
if recent_chats:
|
480 |
+
summary += f"\n📝 **Son {len(recent_chats)} Sohbet:**\n"
|
481 |
+
for chat in recent_chats:
|
482 |
+
timestamp = chat['data'].get('timestamp', 'Bilinmiyor')
|
483 |
+
summary += f"• {timestamp}: Sohbet\n"
|
484 |
+
|
485 |
+
summary += "\n*Bu tercihler sohbetlerimizden otomatik olarak çıkarıldı.*"
|
486 |
+
return summary
|
487 |
+
|
488 |
+
except Exception as e:
|
489 |
+
print(f"Profile summary error: {e}")
|
490 |
+
return "Profil bilgilerine şu anda erişilemiyor."
|
491 |
+
|
492 |
def get_user_recommendations(user_id, user_message):
|
493 |
"""Kullanıcıya özel öneriler al"""
|
494 |
try:
|
495 |
+
# Kullanıcı etkileşimini kaydet (tercih çıkarımı için)
|
496 |
+
profile_manager.add_interaction(user_id, "recommendation_query", {
|
497 |
+
"message": user_message,
|
498 |
+
"timestamp": datetime.now().isoformat()
|
499 |
+
})
|
500 |
+
|
501 |
# Bütçe sorgusu varsa
|
502 |
if "bütçe" in user_message.lower() or "budget" in user_message.lower():
|
503 |
# Rakamları çıkarmaya çalış
|
|
|
515 |
for product in recommendations[:3]:
|
516 |
rec_text += f"• {product[2]} - {product[1][1]} TL\n"
|
517 |
return rec_text
|
518 |
+
elif len(numbers) >= 1 and personalized_recommendations:
|
519 |
+
# Tek sayı varsa aralık oluştur
|
520 |
+
budget_center = int(numbers[0]) * 1000
|
521 |
+
budget_min = int(budget_center * 0.8)
|
522 |
+
budget_max = int(budget_center * 1.2)
|
523 |
+
recommendations = personalized_recommendations.get_budget_recommendations(
|
524 |
+
user_id, budget_min, budget_max
|
525 |
+
)
|
526 |
+
|
527 |
+
if recommendations:
|
528 |
+
rec_text = f"{numbers[0]}K TL bütçenize uygun öneriler:\n\n"
|
529 |
+
for product in recommendations[:3]:
|
530 |
+
rec_text += f"• {product[2]} - {product[1][1]} TL\n"
|
531 |
+
return rec_text
|
532 |
|
533 |
+
# Kullanıcı profili tercihleri varsa öneri ver
|
534 |
if personalized_recommendations:
|
535 |
+
profile = profile_manager.get_or_create_profile(user_id)
|
536 |
+
preferences = profile.get("preferences", {})
|
537 |
+
|
538 |
+
# Eğer kullanıcının kaydedilmiş tercihleri varsa
|
539 |
+
if any(preferences.values()):
|
540 |
+
suggestions = personalized_recommendations.get_personalized_suggestions(user_id)
|
541 |
+
if suggestions:
|
542 |
+
sug_text = "Tercihlerinize göre önerilerimiz:\n\n"
|
543 |
+
for product in suggestions[:3]:
|
544 |
+
sug_text += f"• {product[2]} - {product[1][1]} TL\n"
|
545 |
+
|
546 |
+
# Tercih özetini ekle
|
547 |
+
pref_summary = []
|
548 |
+
if preferences.get("bike_category"):
|
549 |
+
pref_summary.append(f"Kategori: {preferences['bike_category']}")
|
550 |
+
if preferences.get("budget_range"):
|
551 |
+
pref_summary.append(f"Bütçe: {preferences['budget_range'][0]:,.0f}-{preferences['budget_range'][1]:,.0f} TL")
|
552 |
+
if preferences.get("usage_purpose"):
|
553 |
+
pref_summary.append(f"Kullanım: {preferences['usage_purpose']}")
|
554 |
+
|
555 |
+
if pref_summary:
|
556 |
+
sug_text += f"\n*Kaydedilen tercihleriniz: {', '.join(pref_summary)}*"
|
557 |
+
|
558 |
+
return sug_text
|
559 |
|
560 |
return None
|
561 |
except Exception as e:
|