Minimal stok API entegrasyonu eklendi
Browse files
app.py
CHANGED
@@ -29,6 +29,93 @@ from enhanced_features import (
|
|
29 |
)
|
30 |
from image_renderer import extract_product_info_for_gallery, format_message_with_images
|
31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
# Gradio uyarılarını bastır
|
33 |
warnings.filterwarnings("ignore", category=UserWarning, module="gradio.components.chatbot")
|
34 |
|
@@ -272,7 +359,7 @@ def run_scheduler(chat_history):
|
|
272 |
schedule.run_pending()
|
273 |
time.sleep(60)
|
274 |
|
275 |
-
# Chatbot fonksiyonu
|
276 |
def chatbot_fn(user_message, history, image=None):
|
277 |
if history is None:
|
278 |
history = []
|
@@ -288,12 +375,8 @@ def chatbot_fn(user_message, history, image=None):
|
|
288 |
yield comparison_result
|
289 |
return
|
290 |
|
291 |
-
# Enhanced features - Basit karşılaştırma ve görsel işleme
|
292 |
-
# Profil sistemi kaldırıldı - daha hızlı çalışma için
|
293 |
-
|
294 |
except Exception as e:
|
295 |
print(f"Enhanced features error: {e}")
|
296 |
-
# Enhanced features hata verirse normal chatbot'a devam et
|
297 |
|
298 |
# Log: Kullanıcı mesajını ekle
|
299 |
try:
|
@@ -308,39 +391,60 @@ def chatbot_fn(user_message, history, image=None):
|
|
308 |
|
309 |
# Döküman verilerini sistem mesajlarına ekle
|
310 |
if document_content:
|
311 |
-
system_messages.append({"role": "system", "content": f"Dökümanlardan gelen bilgiler: {document_content}"})
|
312 |
|
313 |
-
#
|
314 |
-
|
315 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
316 |
input_words = user_message.lower().split()
|
|
|
317 |
for word in input_words:
|
|
|
|
|
318 |
for product_info in products:
|
319 |
if word in product_info[0] or word in product_info[2].lower():
|
320 |
-
# Stokta olup olmadığını kontrol et
|
321 |
if product_info[1][0] == "stokta":
|
322 |
-
# Normal fiyat
|
323 |
normal_price = f"\\nFiyat: {product_info[1][1]} TL"
|
324 |
|
325 |
-
# Kampanyalı fiyat kontrolü
|
326 |
rebate_price = ""
|
327 |
discount_info = ""
|
328 |
eft_price = ""
|
329 |
rebate_money_order_price = ""
|
330 |
|
331 |
-
# Kampanyalı fiyat var mı kontrol et
|
332 |
if len(product_info[1]) > 4 and product_info[1][4] and product_info[1][4] != "":
|
333 |
rebate_price = f"\\nKampanyalı fiyat: {product_info[1][4]} TL"
|
334 |
|
335 |
-
# İndirim miktarını hesapla
|
336 |
try:
|
337 |
normal_price_float = float(product_info[1][1])
|
338 |
rebate_price_float = float(product_info[1][4])
|
339 |
discount_amount = normal_price_float - rebate_price_float
|
340 |
|
341 |
-
# İndirim miktarı 0'dan büyükse göster
|
342 |
if discount_amount > 0:
|
343 |
-
# İndirim miktarı için yuvarlama kurallarını uygula
|
344 |
if discount_amount > 200000:
|
345 |
discount_amount_rounded = round(discount_amount / 5000) * 5000
|
346 |
elif discount_amount > 30000:
|
@@ -350,35 +454,38 @@ def chatbot_fn(user_message, history, image=None):
|
|
350 |
else:
|
351 |
discount_amount_rounded = round(discount_amount / 10) * 10
|
352 |
|
353 |
-
# İndirim bilgisi
|
354 |
discount_info = f"\\nYapılan indirim: {discount_amount_rounded:.0f} TL"
|
355 |
except (ValueError, TypeError):
|
356 |
discount_info = ""
|
357 |
|
358 |
-
# Havale indirimli kampanyalı fiyat bilgisini gösterme
|
359 |
rebate_money_order_price = ""
|
360 |
else:
|
361 |
-
# Kampanyalı değilse, havale indirimli normal fiyatı göster
|
362 |
if product_info[1][3] and product_info[1][3] != "":
|
363 |
eft_price = f"\\nHavale indirimli fiyat: {product_info[1][3]} TL"
|
364 |
|
365 |
-
# Ürün linki ve resim
|
366 |
product_link = f"\\nÜrün linki: {product_info[1][2]}"
|
367 |
product_image = ""
|
368 |
-
if len(product_info[1]) > 6 and product_info[1][6]:
|
369 |
product_image = f"\\nÜrün resmi: {product_info[1][6]}"
|
370 |
|
371 |
-
# Tüm bilgileri birleştir
|
372 |
new_msg = f"{product_info[2]} {product_info[1][0]}\\n{normal_price}{rebate_price}{discount_info}{eft_price}{rebate_money_order_price}{product_link}{product_image}"
|
373 |
else:
|
374 |
-
# Ürün stokta yoksa sadece stok durumunu bildir
|
375 |
new_msg = f"{product_info[2]} {product_info[1][0]}"
|
376 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
377 |
|
378 |
messages = system_messages + history + [{"role": "user", "content": user_message}]
|
379 |
|
380 |
payload = {
|
381 |
-
"model": "gpt-
|
382 |
"messages": messages,
|
383 |
"temperature": 0.1,
|
384 |
"top_p": 0.9,
|
@@ -394,7 +501,8 @@ def chatbot_fn(user_message, history, image=None):
|
|
394 |
|
395 |
response = requests.post(API_URL, headers=headers, json=payload, stream=True, timeout=120)
|
396 |
if response.status_code != 200:
|
397 |
-
|
|
|
398 |
return
|
399 |
|
400 |
partial_response = ""
|
@@ -421,8 +529,6 @@ def chatbot_fn(user_message, history, image=None):
|
|
421 |
final_response = extract_product_info_for_gallery(partial_response)
|
422 |
yield final_response
|
423 |
|
424 |
-
# Profil kaydetme kaldırıldı - daha hızlı çalışma için
|
425 |
-
|
426 |
# Log: Asistan cevabını ekle
|
427 |
try:
|
428 |
with file_lock:
|
@@ -659,9 +765,7 @@ def enhanced_chatbot_fn(message, history, image):
|
|
659 |
# Demo arayüzü - Mobil responsive
|
660 |
with gr.Blocks(css=custom_css, theme="soft", title="Trek Asistanı", head=storage_js) as demo:
|
661 |
gr.Markdown("# 🚲 Trek Asistanı AI")
|
662 |
-
gr.Markdown("**Akıllı özellikler:**
|
663 |
-
|
664 |
-
# LocalStorage fonksiyonu kaldırıldı
|
665 |
|
666 |
chatbot = gr.Chatbot(height=600, elem_id="chatbot", show_label=False)
|
667 |
|
@@ -671,10 +775,6 @@ with gr.Blocks(css=custom_css, theme="soft", title="Trek Asistanı", head=storag
|
|
671 |
elem_id="msg-input"
|
672 |
)
|
673 |
|
674 |
-
# Restore button tamamen kaldırıldı
|
675 |
-
|
676 |
-
# Session ve profil sistemi tamamen kaldırıldı
|
677 |
-
|
678 |
def respond(message, chat_history):
|
679 |
if not message.strip():
|
680 |
return "", chat_history
|
@@ -707,8 +807,6 @@ with gr.Blocks(css=custom_css, theme="soft", title="Trek Asistanı", head=storag
|
|
707 |
chat_history[-1] = (message, response)
|
708 |
yield "", chat_history
|
709 |
|
710 |
-
# Chat kaydetme sistemi kaldırıldı
|
711 |
-
|
712 |
except Exception as e:
|
713 |
error_msg = f"Üzgünüm, bir hata oluştu: {str(e)}"
|
714 |
print(f"Chat error: {e}")
|
@@ -719,5 +817,4 @@ with gr.Blocks(css=custom_css, theme="soft", title="Trek Asistanı", head=storag
|
|
719 |
msg.submit(respond, [msg, chatbot], [msg, chatbot], show_progress=True)
|
720 |
|
721 |
if __name__ == "__main__":
|
722 |
-
demo.launch(debug=True)
|
723 |
-
|
|
|
29 |
)
|
30 |
from image_renderer import extract_product_info_for_gallery, format_message_with_images
|
31 |
|
32 |
+
# STOK API ENTEGRASYONU - YENİ EKLENEN KISIM
|
33 |
+
STOCK_API_BASE = "https://video.trek-turkey.com/bizimhesap-proxy.php"
|
34 |
+
|
35 |
+
def normalize_turkish(text):
|
36 |
+
"""Türkçe karakterleri normalize et"""
|
37 |
+
if not text:
|
38 |
+
return ""
|
39 |
+
replacements = {
|
40 |
+
'ı': 'i', 'İ': 'i', 'ş': 's', 'Ş': 's',
|
41 |
+
'ğ': 'g', 'Ğ': 'g', 'ü': 'u', 'Ü': 'u',
|
42 |
+
'ö': 'o', 'Ö': 'o', 'ç': 'c', 'Ç': 'c'
|
43 |
+
}
|
44 |
+
text = text.lower()
|
45 |
+
for tr_char, eng_char in replacements.items():
|
46 |
+
text = text.replace(tr_char, eng_char)
|
47 |
+
return text
|
48 |
+
|
49 |
+
def get_realtime_stock(product_name):
|
50 |
+
"""API'den gerçek zamanlı stok bilgisini çek - Minimal versiyon"""
|
51 |
+
try:
|
52 |
+
# Önce mağaza listesini al
|
53 |
+
warehouses_url = f"{STOCK_API_BASE}?action=warehouses"
|
54 |
+
warehouses_response = requests.get(warehouses_url, timeout=5, verify=False)
|
55 |
+
|
56 |
+
if warehouses_response.status_code != 200:
|
57 |
+
return None
|
58 |
+
|
59 |
+
warehouses = warehouses_response.json()
|
60 |
+
|
61 |
+
# Ürün adını normalize et
|
62 |
+
search_terms = normalize_turkish(product_name).lower().split()
|
63 |
+
|
64 |
+
# Her mağazanın stok bilgisini topla
|
65 |
+
stock_info = {}
|
66 |
+
total_stock = 0
|
67 |
+
|
68 |
+
for warehouse in warehouses:
|
69 |
+
warehouse_id = warehouse['id']
|
70 |
+
warehouse_name = warehouse['title']
|
71 |
+
|
72 |
+
# Mağaza stoklarını al
|
73 |
+
inventory_url = f"{STOCK_API_BASE}?action=inventory&warehouse={warehouse_id}"
|
74 |
+
inventory_response = requests.get(inventory_url, timeout=5, verify=False)
|
75 |
+
|
76 |
+
if inventory_response.status_code != 200:
|
77 |
+
continue
|
78 |
+
|
79 |
+
products = inventory_response.json()
|
80 |
+
|
81 |
+
# Ürünü ara
|
82 |
+
for product in products:
|
83 |
+
product_title = normalize_turkish(product.get('title', '')).lower()
|
84 |
+
|
85 |
+
# Tüm arama terimlerinin ürün başlığında olup olmadığını kontrol et
|
86 |
+
if all(term in product_title for term in search_terms):
|
87 |
+
stock = int(product.get('stock', 0))
|
88 |
+
if stock > 0:
|
89 |
+
stock_info[warehouse_name] = stock
|
90 |
+
total_stock += stock
|
91 |
+
break
|
92 |
+
|
93 |
+
if not stock_info:
|
94 |
+
return f"{product_name}: Şu anda hiçbir mağazada stokta bulunmuyor."
|
95 |
+
|
96 |
+
# Minimal prompt oluştur
|
97 |
+
prompt_lines = [f"{product_name} stok durumu:"]
|
98 |
+
for warehouse, stock in stock_info.items():
|
99 |
+
prompt_lines.append(f"- {warehouse}: {stock} adet")
|
100 |
+
prompt_lines.append(f"Toplam: {total_stock} adet")
|
101 |
+
|
102 |
+
return "\n".join(prompt_lines)
|
103 |
+
|
104 |
+
except Exception as e:
|
105 |
+
print(f"Stok API hatası: {e}")
|
106 |
+
return None
|
107 |
+
|
108 |
+
def is_stock_query(message):
|
109 |
+
"""Mesajın stok sorgusu olup olmadığını kontrol et"""
|
110 |
+
stock_keywords = [
|
111 |
+
'stok', 'stock', 'kaç adet', 'kaç tane', 'var mı',
|
112 |
+
'mevcut mu', 'bulunuyor mu', 'hangi mağaza', 'nerede var',
|
113 |
+
'stok durumu', 'stoklarda', 'stokta', 'adet', 'kaç tane var'
|
114 |
+
]
|
115 |
+
message_lower = message.lower()
|
116 |
+
return any(keyword in message_lower for keyword in stock_keywords)
|
117 |
+
# STOK API ENTEGRASYONU SONU
|
118 |
+
|
119 |
# Gradio uyarılarını bastır
|
120 |
warnings.filterwarnings("ignore", category=UserWarning, module="gradio.components.chatbot")
|
121 |
|
|
|
359 |
schedule.run_pending()
|
360 |
time.sleep(60)
|
361 |
|
362 |
+
# Chatbot fonksiyonu - STOK API ENTEGRASYONU EKLENDİ
|
363 |
def chatbot_fn(user_message, history, image=None):
|
364 |
if history is None:
|
365 |
history = []
|
|
|
375 |
yield comparison_result
|
376 |
return
|
377 |
|
|
|
|
|
|
|
378 |
except Exception as e:
|
379 |
print(f"Enhanced features error: {e}")
|
|
|
380 |
|
381 |
# Log: Kullanıcı mesajını ekle
|
382 |
try:
|
|
|
391 |
|
392 |
# Döküman verilerini sistem mesajlarına ekle
|
393 |
if document_content:
|
394 |
+
system_messages.append({"role": "system", "content": f"Dökümanlardan gelen bilgiler: {document_content[:3000]}"}) # Token limiti için kısalt
|
395 |
|
396 |
+
# STOK SORGUSU KONTROLÜ - YENİ EKLENEN KISIM
|
397 |
+
if is_stock_query(user_message):
|
398 |
+
print("Stok sorgusu algılandı, API'den veri çekiliyor...")
|
399 |
+
|
400 |
+
# Mesajdan ürün adını çıkarmaya çalış
|
401 |
+
# Basit bir yaklaşım: stok kelimelerini temizleyip kalan kelimeleri ürün adı olarak kullan
|
402 |
+
product_words = []
|
403 |
+
skip_words = ['stok', 'stock', 'kaç', 'adet', 'tane', 'var', 'mı', 'mi',
|
404 |
+
'mevcut', 'mu', 'bulunuyor', 'hangi', 'mağaza', 'nerede',
|
405 |
+
'durumu', 'stoklarda', 'stokta', 'için', 've', 'ile']
|
406 |
+
|
407 |
+
for word in user_message.lower().split():
|
408 |
+
if word not in skip_words:
|
409 |
+
product_words.append(word)
|
410 |
+
|
411 |
+
if product_words:
|
412 |
+
product_name = ' '.join(product_words)
|
413 |
+
stock_info = get_realtime_stock(product_name)
|
414 |
+
|
415 |
+
if stock_info:
|
416 |
+
# Stok bilgisini sistem mesajına ekle
|
417 |
+
system_messages.append({
|
418 |
+
"role": "system",
|
419 |
+
"content": f"GÜNCEL STOK BİLGİSİ (API'den alındı):\n{stock_info}"
|
420 |
+
})
|
421 |
+
print(f"Stok bilgisi eklendi: {stock_info}")
|
422 |
+
|
423 |
+
# ESKİ STOK SİSTEMİ - XML'den gelen bilgiler (yedek olarak kalacak)
|
424 |
input_words = user_message.lower().split()
|
425 |
+
added_products_count = 0
|
426 |
for word in input_words:
|
427 |
+
if added_products_count >= 5: # Token limiti için maksimum 5 ürün
|
428 |
+
break
|
429 |
for product_info in products:
|
430 |
if word in product_info[0] or word in product_info[2].lower():
|
|
|
431 |
if product_info[1][0] == "stokta":
|
|
|
432 |
normal_price = f"\\nFiyat: {product_info[1][1]} TL"
|
433 |
|
|
|
434 |
rebate_price = ""
|
435 |
discount_info = ""
|
436 |
eft_price = ""
|
437 |
rebate_money_order_price = ""
|
438 |
|
|
|
439 |
if len(product_info[1]) > 4 and product_info[1][4] and product_info[1][4] != "":
|
440 |
rebate_price = f"\\nKampanyalı fiyat: {product_info[1][4]} TL"
|
441 |
|
|
|
442 |
try:
|
443 |
normal_price_float = float(product_info[1][1])
|
444 |
rebate_price_float = float(product_info[1][4])
|
445 |
discount_amount = normal_price_float - rebate_price_float
|
446 |
|
|
|
447 |
if discount_amount > 0:
|
|
|
448 |
if discount_amount > 200000:
|
449 |
discount_amount_rounded = round(discount_amount / 5000) * 5000
|
450 |
elif discount_amount > 30000:
|
|
|
454 |
else:
|
455 |
discount_amount_rounded = round(discount_amount / 10) * 10
|
456 |
|
|
|
457 |
discount_info = f"\\nYapılan indirim: {discount_amount_rounded:.0f} TL"
|
458 |
except (ValueError, TypeError):
|
459 |
discount_info = ""
|
460 |
|
|
|
461 |
rebate_money_order_price = ""
|
462 |
else:
|
|
|
463 |
if product_info[1][3] and product_info[1][3] != "":
|
464 |
eft_price = f"\\nHavale indirimli fiyat: {product_info[1][3]} TL"
|
465 |
|
|
|
466 |
product_link = f"\\nÜrün linki: {product_info[1][2]}"
|
467 |
product_image = ""
|
468 |
+
if len(product_info[1]) > 6 and product_info[1][6]:
|
469 |
product_image = f"\\nÜrün resmi: {product_info[1][6]}"
|
470 |
|
|
|
471 |
new_msg = f"{product_info[2]} {product_info[1][0]}\\n{normal_price}{rebate_price}{discount_info}{eft_price}{rebate_money_order_price}{product_link}{product_image}"
|
472 |
else:
|
|
|
473 |
new_msg = f"{product_info[2]} {product_info[1][0]}"
|
474 |
+
|
475 |
+
# Token limiti için mesaj boyutunu kontrol et
|
476 |
+
if len(new_msg) < 5000: # Maksimum 5000 karakter
|
477 |
+
system_messages.append({"role": "system", "content": new_msg})
|
478 |
+
added_products_count += 1
|
479 |
+
break
|
480 |
+
|
481 |
+
# Son 10 mesajla sınırla (token limiti için)
|
482 |
+
if len(history) > 10:
|
483 |
+
history = history[-10:]
|
484 |
|
485 |
messages = system_messages + history + [{"role": "user", "content": user_message}]
|
486 |
|
487 |
payload = {
|
488 |
+
"model": "gpt-5-chat-latest",
|
489 |
"messages": messages,
|
490 |
"temperature": 0.1,
|
491 |
"top_p": 0.9,
|
|
|
501 |
|
502 |
response = requests.post(API_URL, headers=headers, json=payload, stream=True, timeout=120)
|
503 |
if response.status_code != 200:
|
504 |
+
print(f"API Hatası: {response.status_code} - {response.text}")
|
505 |
+
yield f"API Hatası ({response.status_code}): {response.text[:200]}"
|
506 |
return
|
507 |
|
508 |
partial_response = ""
|
|
|
529 |
final_response = extract_product_info_for_gallery(partial_response)
|
530 |
yield final_response
|
531 |
|
|
|
|
|
532 |
# Log: Asistan cevabını ekle
|
533 |
try:
|
534 |
with file_lock:
|
|
|
765 |
# Demo arayüzü - Mobil responsive
|
766 |
with gr.Blocks(css=custom_css, theme="soft", title="Trek Asistanı", head=storage_js) as demo:
|
767 |
gr.Markdown("# 🚲 Trek Asistanı AI")
|
768 |
+
gr.Markdown("**Akıllı özellikler:** Gerçek zamanlı stok bilgisi, ürün karşılaştırması ve detaylı ürün bilgileri sunuyorum.")
|
|
|
|
|
769 |
|
770 |
chatbot = gr.Chatbot(height=600, elem_id="chatbot", show_label=False)
|
771 |
|
|
|
775 |
elem_id="msg-input"
|
776 |
)
|
777 |
|
|
|
|
|
|
|
|
|
778 |
def respond(message, chat_history):
|
779 |
if not message.strip():
|
780 |
return "", chat_history
|
|
|
807 |
chat_history[-1] = (message, response)
|
808 |
yield "", chat_history
|
809 |
|
|
|
|
|
810 |
except Exception as e:
|
811 |
error_msg = f"Üzgünüm, bir hata oluştu: {str(e)}"
|
812 |
print(f"Chat error: {e}")
|
|
|
817 |
msg.submit(respond, [msg, chatbot], [msg, chatbot], show_progress=True)
|
818 |
|
819 |
if __name__ == "__main__":
|
820 |
+
demo.launch(debug=True)
|
|