SamiKoen commited on
Commit
73cc2c5
·
verified ·
1 Parent(s): 911a3b8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +53 -171
app.py CHANGED
@@ -18,7 +18,6 @@ from googleapiclient.http import MediaIoBaseDownload
18
  import io
19
  import warnings
20
  from requests.packages.urllib3.exceptions import InsecureRequestWarning
21
- import re # NEW: yıl tespiti için
22
  warnings.simplefilter('ignore', InsecureRequestWarning)
23
 
24
  # Prompt dosyasını import et
@@ -52,17 +51,6 @@ def normalize_turkish(text):
52
  text = text.replace(tr_char, eng_char)
53
  return text
54
 
55
- # NEW: Basit retry/backoff'lu güvenli GET wrapper
56
- def safe_get(url, timeout=5, retries=2, verify=False, **kwargs):
57
- last_exc = None
58
- for i in range(retries + 1):
59
- try:
60
- return requests.get(url, timeout=timeout, verify=verify, **kwargs)
61
- except requests.RequestException as e:
62
- last_exc = e
63
- time.sleep(0.3 * (2 ** i))
64
- raise last_exc
65
-
66
  def fetch_warehouse_inventory(warehouse, product_name, search_terms):
67
  """Tek bir mağazanın stok bilgisini al"""
68
  try:
@@ -74,8 +62,7 @@ def fetch_warehouse_inventory(warehouse, product_name, search_terms):
74
 
75
  # Mağaza stoklarını al
76
  inventory_url = f"{STOCK_API_BASE}?action=inventory&warehouse={warehouse_id}&endpoint=inventory/{warehouse_id}"
77
- # CHANGED: requests.get -> safe_get
78
- inventory_response = safe_get(inventory_url, timeout=5, verify=False)
79
 
80
  if inventory_response.status_code != 200:
81
  return None
@@ -115,6 +102,7 @@ def fetch_warehouse_inventory(warehouse, product_name, search_terms):
115
  # Eğer sadece beden sorgusu ise
116
  if is_only_size_query:
117
  # Beden terimini ürün başlığında ara (parantez içinde veya dışında)
 
118
  if size_query in product_title.split() or f'({size_query})' in product_title or f' {size_query} ' in product_title or product_title.endswith(f' {size_query}'):
119
  qty = int(product.get('qty', 0))
120
  stock = int(product.get('stock', 0))
@@ -229,8 +217,7 @@ def get_realtime_stock_parallel(product_name):
229
 
230
  # Önce mağaza listesini al
231
  warehouses_url = f"{STOCK_API_BASE}?action=warehouses&endpoint=warehouses"
232
- # CHANGED: requests.get -> safe_get
233
- warehouses_response = safe_get(warehouses_url, timeout=5, verify=False)
234
 
235
  if warehouses_response.status_code != 200:
236
  print(f"Mağaza listesi alınamadı: {warehouses_response.status_code}")
@@ -310,8 +297,7 @@ def get_realtime_stock(product_name):
310
  try:
311
  # Önce mağaza listesini al - endpoint parametresi eklendi
312
  warehouses_url = f"{STOCK_API_BASE}?action=warehouses&endpoint=warehouses"
313
- # CHANGED: requests.get -> safe_get
314
- warehouses_response = safe_get(warehouses_url, timeout=5, verify=False) # Timeout 5 saniye
315
 
316
  if warehouses_response.status_code != 200:
317
  print(f"Mağaza listesi alınamadı: {warehouses_response.status_code}")
@@ -344,8 +330,7 @@ def get_realtime_stock(product_name):
344
 
345
  # Mağaza stoklarını al - endpoint parametresi eklendi
346
  inventory_url = f"{STOCK_API_BASE}?action=inventory&warehouse={warehouse_id}&endpoint=inventory/{warehouse_id}"
347
- # CHANGED: requests.get -> safe_get
348
- inventory_response = safe_get(inventory_url, timeout=5, verify=False) # Timeout 5 saniye
349
 
350
  if inventory_response.status_code != 200:
351
  continue
@@ -468,21 +453,13 @@ OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
468
  if not OPENAI_API_KEY:
469
  print("Hata: OPENAI_API_KEY çevre değişkeni ayarlanmamış!")
470
 
471
- # NEW: V1 bayrağı (stok sorularında LLM bypass)
472
- GROUND_STOCK_ONLY = os.getenv("GROUND_STOCK_ONLY", "1") == "1"
473
-
474
  # Trek bisiklet ürünlerini çekme
475
  url = 'https://www.trekbisiklet.com.tr/output/8582384479'
476
- # CHANGED: requests.get -> safe_get
477
- try:
478
- response = safe_get(url, verify=False, timeout=60)
479
- if response.status_code == 200 and response.content:
480
- root = ET.fromstring(response.content)
481
- else:
482
- print(f"HTTP hatası: {response.status_code}")
483
- root = None
484
- except Exception as e:
485
- print(f"XML çekme hatası: {e}")
486
  root = None
487
 
488
  products = []
@@ -499,15 +476,9 @@ if root is not None:
499
  name = name_words[0]
500
  full_name = ' '.join(name_words)
501
 
502
- # CHANGED: stok kontrolü int'e çevrildi
503
- try:
504
- stock_val = int((stock_elem.text or "0").strip())
505
- except (ValueError, TypeError):
506
- stock_val = 0
507
- stock_amount = "stokta" if stock_val > 0 else "stokta değil"
508
 
509
- # Stokta olmayan ürünler için fiyat/link bilgisi yine saklanıyor (aşağıda)
510
- # Stokta olanlar için detaylar
511
  if stock_amount == "stokta":
512
  # Normal fiyat bilgisini al - Güvenli versiyon
513
  price_elem = item.find('priceTaxWithCur')
@@ -521,34 +492,42 @@ if root is not None:
521
  price_rebate_elem = item.find('priceRebateWithTax')
522
  price_rebate_str = price_rebate_elem.text if price_rebate_elem is not None and price_rebate_elem.text else ""
523
 
524
- # Havale indirimli kampanyalı fiyatı - Güvenli versiyon
525
  price_rebate_money_order_elem = item.find('priceRebateWithMoneyOrderWithTax')
526
  price_rebate_money_order_str = price_rebate_money_order_elem.text if price_rebate_money_order_elem is not None and price_rebate_money_order_elem.text else ""
527
 
528
  # Normal fiyatı yuvarla
529
  try:
530
  price_float = float(price_str)
 
531
  if price_float > 200000:
532
- price = str(round(price_float / 5000) * 5000)
 
533
  elif price_float > 30000:
534
- price = str(round(price_float / 1000) * 1000)
 
535
  elif price_float > 10000:
536
- price = str(round(price_float / 100) * 100)
 
537
  else:
538
- price = str(round(price_float / 10) * 10)
539
  except (ValueError, TypeError):
540
- price = price_str
541
 
542
  # Havale indirimli orijinal fiyatı yuvarla (varsa)
543
  if price_eft_str:
544
  try:
545
  price_eft_float = float(price_eft_str)
 
546
  if price_eft_float > 200000:
547
  price_eft = str(round(price_eft_float / 5000) * 5000)
 
548
  elif price_eft_float > 30000:
549
  price_eft = str(round(price_eft_float / 1000) * 1000)
 
550
  elif price_eft_float > 10000:
551
  price_eft = str(round(price_eft_float / 100) * 100)
 
552
  else:
553
  price_eft = str(round(price_eft_float / 10) * 10)
554
  except (ValueError, TypeError):
@@ -560,12 +539,16 @@ if root is not None:
560
  if price_rebate_str:
561
  try:
562
  price_rebate_float = float(price_rebate_str)
 
563
  if price_rebate_float > 200000:
564
  price_rebate = str(round(price_rebate_float / 5000) * 5000)
 
565
  elif price_rebate_float > 30000:
566
  price_rebate = str(round(price_rebate_float / 1000) * 1000)
 
567
  elif price_rebate_float > 10000:
568
  price_rebate = str(round(price_rebate_float / 100) * 100)
 
569
  else:
570
  price_rebate = str(round(price_rebate_float / 10) * 10)
571
  except (ValueError, TypeError):
@@ -573,16 +556,20 @@ if root is not None:
573
  else:
574
  price_rebate = ""
575
 
576
- # Havale indirimli kampanyalı fiyatı (varsa)
577
  if price_rebate_money_order_str:
578
  try:
579
  price_rebate_money_order_float = float(price_rebate_money_order_str)
 
580
  if price_rebate_money_order_float > 200000:
581
  price_rebate_money_order = str(round(price_rebate_money_order_float / 5000) * 5000)
 
582
  elif price_rebate_money_order_float > 30000:
583
  price_rebate_money_order = str(round(price_rebate_money_order_float / 1000) * 1000)
 
584
  elif price_rebate_money_order_float > 10000:
585
  price_rebate_money_order = str(round(price_rebate_money_order_float / 100) * 100)
 
586
  else:
587
  price_rebate_money_order = str(round(price_rebate_money_order_float / 10) * 10)
588
  except (ValueError, TypeError):
@@ -623,40 +610,6 @@ if root is not None:
623
 
624
  print(f"Toplam {len(products)} ürün yüklendi.")
625
 
626
- # NEW: Ürün adlarındaki yılları topla (yıl doğrulama/tolerans için)
627
- PRODUCT_YEARS = set()
628
- year_pat = re.compile(r'(?:19|20)\d{2}')
629
- for _, _, full_name in products:
630
- for y in year_pat.findall(full_name or ""):
631
- PRODUCT_YEARS.add(y)
632
- print(f"Yıl seti (ürün adlarından): {sorted(PRODUCT_YEARS)}")
633
-
634
- # NEW: Yıl toleransı yardımcıları
635
- def strip_unseen_years(q: str):
636
- """Sorgudan, ürünlerde hiç bulunmayan yıl(lar)ı temizle."""
637
- if not q:
638
- return q, []
639
- years = re.findall(r'(?:19|20)\d{2}', q)
640
- removed = []
641
- new_q = q
642
- for y in years:
643
- if y not in PRODUCT_YEARS:
644
- new_q = re.sub(r'\b' + re.escape(y) + r'\b', '', new_q)
645
- removed.append(y)
646
- new_q = ' '.join(new_q.split())
647
- return new_q, removed
648
-
649
- def remove_all_years(q: str):
650
- """Sorgudaki tüm yıl ifadelerini (19xx/20xx) sil."""
651
- if not q:
652
- return q
653
- new_q = re.sub(r'\b(?:19|20)\d{2}\b', '', q)
654
- return ' '.join(new_q.split())
655
-
656
- def is_no_stock_text(text: str):
657
- """'stokta bulunmuyor' ifadesini içeriyor mu?"""
658
- return bool(text) and ("stokta bulunmuyor" in text)
659
-
660
  # Initialize enhanced features
661
  initialize_enhanced_features(OPENAI_API_KEY, products)
662
 
@@ -707,14 +660,14 @@ def download_documents_from_drive():
707
  file_io.seek(0)
708
  doc = Document(file_io)
709
 
710
- content = f"\n=== {file['name']} ===\n"
711
  for paragraph in doc.paragraphs:
712
  if paragraph.text.strip():
713
- content += paragraph.text + "\n"
714
 
715
  all_content.append(content)
716
 
717
- document_content = "\n".join(all_content)
718
  print(f"Toplam {len(files)} döküman yüklendi.")
719
 
720
  except Exception as e:
@@ -730,7 +683,7 @@ def clear_log_file():
730
  if os.path.exists(LOG_FILE):
731
  with file_lock:
732
  with open(LOG_FILE, 'w', encoding='utf-8') as f:
733
- f.write("Log dosyası temizlendi.\n")
734
  print("Log dosyası temizlendi.")
735
  except Exception as e:
736
  print(f"Log dosyası temizleme hatası: {e}")
@@ -743,83 +696,11 @@ def run_scheduler(chat_history):
743
  schedule.run_pending()
744
  time.sleep(60)
745
 
746
- # NEW: Stok sorularına deterministik, tamamen veri tabanlı yanıt (YIL TOLERANSI ENTEGRE)
747
- def answer_stock_grounded(user_message):
748
- """
749
- Stok sorularına tamamen veri-tabanlı, deterministik yanıt üretir.
750
- Yalnızca API + XML kullanır, LLM'ye gitmez.
751
- YIL TOLERANSI: XML'de hiç olmayan yıl(lar)ı sorgudan otomatik çıkarır.
752
- """
753
- # 1) Ürün adı çıkarma
754
- skip_words = ['stok','stock','kaç','adet','tane','var','mı','mi','mevcut','mu','bulunuyor',
755
- 'hangi','mağaza','nerede','durumu','stoklarda','stokta',
756
- 'için','ve','ile','toplam','toplamda','fiyat','fiyatı','ne','nedir','kadar',
757
- 'beden','bedeni','bedenli']
758
- tokens = [w for w in user_message.lower().split() if w not in skip_words]
759
- if not tokens:
760
- return "Hangi ürün için stok bakmamı istersiniz?"
761
-
762
- size_terms = {'xs','s','m','ml','l','xl','xxl','2xl','3xl','small','medium','large',
763
- '44','46','48','50','52','54','56','58','60'}
764
- is_only_size = (len(tokens) == 1 and tokens[0] in size_terms)
765
- raw_name = tokens[0] if is_only_size else ' '.join(tokens)
766
-
767
- # 2) Sorgudan, XML'de hiç bulunmayan yıl(lar)ı çıkar
768
- refined_name, removed_years = strip_unseen_years(raw_name)
769
- product_name = refined_name or raw_name # emniyet
770
-
771
- # 3) İlk deneme (refined query ile)
772
- stock_text = get_realtime_stock_parallel(product_name)
773
-
774
- # 4) Hâlâ "stokta yok" ve sorguda YIL vardıysa: tüm yılları silip bir kez daha dene
775
- had_any_year = bool(re.search(r'(?:19|20)\d{2}', raw_name))
776
- if (not stock_text or is_no_stock_text(stock_text)) and had_any_year:
777
- name_wo_years = remove_all_years(raw_name)
778
- if name_wo_years and name_wo_years != product_name:
779
- retry_text = get_realtime_stock_parallel(name_wo_years)
780
- if retry_text and not is_no_stock_text(retry_text):
781
- stock_text = retry_text
782
- product_name = name_wo_years # raporlamada bu adı kullan
783
-
784
- if not stock_text:
785
- return f"'{product_name}' için stok bilgisine şu an erişemedim."
786
-
787
- # 5) XML’den (varsa) fiyat/link/resim ekle (sadece veride olanı)
788
- norm_query = normalize_turkish(product_name).replace(" ", "")
789
- extra_lines = []
790
- added = 0
791
- try:
792
- for name, info, full_name in products:
793
- if added >= 3:
794
- break
795
- norm_full = normalize_turkish(full_name).replace(" ", "")
796
- if norm_query and norm_query in norm_full:
797
- normal_price = f"\nFiyat: {info[1]} TL" if len(info) > 1 and info[1] else ""
798
- product_link = f"\nÜrün linki: {info[2]}" if len(info) > 2 and info[2] else ""
799
- product_image = f"\nÜrün resmi: {info[6]}" if len(info) > 6 and info[6] else ""
800
- eft = f"\nHavale indirimi: {info[3]} TL" if len(info) > 3 and info[3] else ""
801
- rebate = f"\nKampanyalı fiyat: {info[4]} TL" if len(info) > 4 and info[4] else ""
802
- rebate_mo = f"\nHavale kampanyalı: {info[5]} TL" if len(info) > 5 and info[5] else ""
803
- extra_lines.append(f"{full_name} (veriden):{normal_price}{rebate}{eft}{rebate_mo}{product_link}{product_image}")
804
- added += 1
805
- except Exception:
806
- pass
807
-
808
- extra_block = ("\n\n" + "\n---\n".join(extra_lines)) if extra_lines else ""
809
- return f"{stock_text}{extra_block}"
810
-
811
  # Chatbot fonksiyonu - STOK API ENTEGRASYONU EKLENDİ
812
  def chatbot_fn(user_message, history, image=None):
813
  if history is None:
814
  history = []
815
 
816
- # NEW: Grounded stock only — stok sorgusuysa LLM'yi tamamen bypass
817
- if is_stock_query(user_message) and GROUND_STOCK_ONLY:
818
- print("Grounded stok modu: LLM devre dışı, veri tabanlı yanıt oluşturuluyor...")
819
- deterministic_answer = answer_stock_grounded(user_message)
820
- yield deterministic_answer
821
- return
822
-
823
  try:
824
  # Enhanced features - Görsel işleme
825
  if image is not None:
@@ -838,7 +719,7 @@ def chatbot_fn(user_message, history, image=None):
838
  try:
839
  with file_lock:
840
  with open(LOG_FILE, 'a', encoding='utf-8') as f:
841
- f.write(f"User: {user_message}\n")
842
  except Exception as e:
843
  print(f"Dosya yazma hatası (Kullanıcı): {e}")
844
 
@@ -849,11 +730,12 @@ def chatbot_fn(user_message, history, image=None):
849
  if document_content:
850
  system_messages.append({"role": "system", "content": f"Dökümanlardan gelen bilgiler: {document_content[:3000]}"}) # Token limiti için kısalt
851
 
852
- # STOK SORGUSU KONTROLÜ - (Eski yol) sadece GROUND_STOCK_ONLY kapalıysa
853
- if is_stock_query(user_message) and not GROUND_STOCK_ONLY:
854
  print("Stok sorgusu algılandı, API'den veri çekiliyor...")
855
 
856
  # Mesajdan ürün adını çıkarmaya çalış
 
857
  product_words = []
858
  skip_words = ['stok', 'stock', 'kaç', 'adet', 'tane', 'var', 'mı', 'mi',
859
  'mevcut', 'mu', 'bulunuyor', 'hangi', 'mağaza', 'nerede',
@@ -963,7 +845,7 @@ def chatbot_fn(user_message, history, image=None):
963
 
964
  # Fiyat bilgisi varsa al
965
  if len(product_info[1]) > 1 and product_info[1][1]:
966
- normal_price = f"\nFiyat: {product_info[1][1]} TL"
967
  print(f"Fiyat bulundu: {product_info[1][1]}")
968
  else:
969
  normal_price = ""
@@ -975,7 +857,7 @@ def chatbot_fn(user_message, history, image=None):
975
  rebate_money_order_price = ""
976
 
977
  if len(product_info[1]) > 4 and product_info[1][4] and product_info[1][4] != "":
978
- rebate_price = f"\nKampanyalı fiyat: {product_info[1][4]} TL"
979
 
980
  try:
981
  normal_price_float = float(product_info[1][1])
@@ -992,26 +874,26 @@ def chatbot_fn(user_message, history, image=None):
992
  else:
993
  discount_amount_rounded = round(discount_amount / 10) * 10
994
 
995
- discount_info = f"\nYapılan indirim: {discount_amount_rounded:.0f} TL"
996
  except (ValueError, TypeError):
997
  discount_info = ""
998
 
999
  rebate_money_order_price = ""
1000
  else:
1001
  if product_info[1][3] and product_info[1][3] != "":
1002
- eft_price = f"\nHavale indirimli fiyat: {product_info[1][3]} TL"
1003
 
1004
- product_link = f"\nÜrün linki: {product_info[1][2]}"
1005
  product_image = ""
1006
  if len(product_info[1]) > 6 and product_info[1][6]:
1007
- product_image = f"\nÜrün resmi: {product_info[1][6]}"
1008
 
1009
  # API'den stok alındıysa sadece fiyat/görsel/link ekle
1010
  if has_stock_from_api:
1011
- new_msg = f"ÜRÜN BİLGİLERİ (Fiyat/Link):\n{normal_price}{rebate_price}{discount_info}{eft_price}{rebate_money_order_price}{product_link}{product_image}"
1012
  else:
1013
  # API'den stok alınmadıysa hem stok hem fiyat bilgisi ekle
1014
- 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}"
1015
  else:
1016
  # Stokta değilse
1017
  if has_stock_from_api:
@@ -1081,7 +963,7 @@ def chatbot_fn(user_message, history, image=None):
1081
  try:
1082
  with file_lock:
1083
  with open(LOG_FILE, 'a', encoding='utf-8') as f:
1084
- f.write(f"Bot: {partial_response}\n")
1085
  except Exception as e:
1086
  print(f"Dosya yazma hatası (Bot): {e}")
1087
 
@@ -1365,4 +1247,4 @@ with gr.Blocks(css=custom_css, theme="soft", title="Trek Asistanı", head=storag
1365
  msg.submit(respond, [msg, chatbot], [msg, chatbot], show_progress=True)
1366
 
1367
  if __name__ == "__main__":
1368
- demo.launch(debug=True)
 
18
  import io
19
  import warnings
20
  from requests.packages.urllib3.exceptions import InsecureRequestWarning
 
21
  warnings.simplefilter('ignore', InsecureRequestWarning)
22
 
23
  # Prompt dosyasını import et
 
51
  text = text.replace(tr_char, eng_char)
52
  return text
53
 
 
 
 
 
 
 
 
 
 
 
 
54
  def fetch_warehouse_inventory(warehouse, product_name, search_terms):
55
  """Tek bir mağazanın stok bilgisini al"""
56
  try:
 
62
 
63
  # Mağaza stoklarını al
64
  inventory_url = f"{STOCK_API_BASE}?action=inventory&warehouse={warehouse_id}&endpoint=inventory/{warehouse_id}"
65
+ inventory_response = requests.get(inventory_url, timeout=3, verify=False)
 
66
 
67
  if inventory_response.status_code != 200:
68
  return None
 
102
  # Eğer sadece beden sorgusu ise
103
  if is_only_size_query:
104
  # Beden terimini ürün başlığında ara (parantez içinde veya dışında)
105
+ # Örnek: "Marlin 5 (M)" veya "Marlin 5 M" veya "Marlin 5 - M"
106
  if size_query in product_title.split() or f'({size_query})' in product_title or f' {size_query} ' in product_title or product_title.endswith(f' {size_query}'):
107
  qty = int(product.get('qty', 0))
108
  stock = int(product.get('stock', 0))
 
217
 
218
  # Önce mağaza listesini al
219
  warehouses_url = f"{STOCK_API_BASE}?action=warehouses&endpoint=warehouses"
220
+ warehouses_response = requests.get(warehouses_url, timeout=3, verify=False)
 
221
 
222
  if warehouses_response.status_code != 200:
223
  print(f"Mağaza listesi alınamadı: {warehouses_response.status_code}")
 
297
  try:
298
  # Önce mağaza listesini al - endpoint parametresi eklendi
299
  warehouses_url = f"{STOCK_API_BASE}?action=warehouses&endpoint=warehouses"
300
+ warehouses_response = requests.get(warehouses_url, timeout=3, verify=False) # Timeout 3 saniye
 
301
 
302
  if warehouses_response.status_code != 200:
303
  print(f"Mağaza listesi alınamadı: {warehouses_response.status_code}")
 
330
 
331
  # Mağaza stoklarını al - endpoint parametresi eklendi
332
  inventory_url = f"{STOCK_API_BASE}?action=inventory&warehouse={warehouse_id}&endpoint=inventory/{warehouse_id}"
333
+ inventory_response = requests.get(inventory_url, timeout=3, verify=False) # Timeout 3 saniye
 
334
 
335
  if inventory_response.status_code != 200:
336
  continue
 
453
  if not OPENAI_API_KEY:
454
  print("Hata: OPENAI_API_KEY çevre değişkeni ayarlanmamış!")
455
 
 
 
 
456
  # Trek bisiklet ürünlerini çekme
457
  url = 'https://www.trekbisiklet.com.tr/output/8582384479'
458
+ response = requests.get(url, verify=False, timeout=60)
459
+ if response.status_code == 200 and response.content:
460
+ root = ET.fromstring(response.content)
461
+ else:
462
+ print(f"HTTP hatası: {response.status_code}")
 
 
 
 
 
463
  root = None
464
 
465
  products = []
 
476
  name = name_words[0]
477
  full_name = ' '.join(name_words)
478
 
479
+ stock_amount = "stokta" if stock_elem.text and stock_elem.text > '0' else "stokta değil"
 
 
 
 
 
480
 
481
+ # Stokta olmayan ürünler için fiyat/link bilgisi eklemiyoruz
 
482
  if stock_amount == "stokta":
483
  # Normal fiyat bilgisini al - Güvenli versiyon
484
  price_elem = item.find('priceTaxWithCur')
 
492
  price_rebate_elem = item.find('priceRebateWithTax')
493
  price_rebate_str = price_rebate_elem.text if price_rebate_elem is not None and price_rebate_elem.text else ""
494
 
495
+ # Havale indirimi fiyatını al (havale indirimli kampanyalı fiyat) - Güvenli versiyon
496
  price_rebate_money_order_elem = item.find('priceRebateWithMoneyOrderWithTax')
497
  price_rebate_money_order_str = price_rebate_money_order_elem.text if price_rebate_money_order_elem is not None and price_rebate_money_order_elem.text else ""
498
 
499
  # Normal fiyatı yuvarla
500
  try:
501
  price_float = float(price_str)
502
+ # Fiyat 200000 üzerindeyse en yakın 5000'lik basamağa yuvarla
503
  if price_float > 200000:
504
+ price = str(round(price_float / 5000) * 5000) # En yakın 5000'e yuvarla
505
+ # Fiyat 30000 üzerindeyse en yakın 1000'lik basamağa yuvarla
506
  elif price_float > 30000:
507
+ price = str(round(price_float / 1000) * 1000) # En yakın 1000'e yuvarla
508
+ # Fiyat 10000 üzerindeyse en yakın 100'lük basamağa yuvarla
509
  elif price_float > 10000:
510
+ price = str(round(price_float / 100) * 100) # En yakın 100'e yuvarla
511
+ # Diğer durumlarda en yakın 10'luk basamağa yuvarla
512
  else:
513
+ price = str(round(price_float / 10) * 10) # En yakın 10'a yuvarla
514
  except (ValueError, TypeError):
515
+ price = price_str # Sayıya dönüştürülemezse olduğu gibi bırak
516
 
517
  # Havale indirimli orijinal fiyatı yuvarla (varsa)
518
  if price_eft_str:
519
  try:
520
  price_eft_float = float(price_eft_str)
521
+ # Fiyat 200000 üzerindeyse en yakın 5000'lik basamağa yuvarla
522
  if price_eft_float > 200000:
523
  price_eft = str(round(price_eft_float / 5000) * 5000)
524
+ # Fiyat 30000 üzerindeyse en yakın 1000'lik basamağa yuvarla
525
  elif price_eft_float > 30000:
526
  price_eft = str(round(price_eft_float / 1000) * 1000)
527
+ # Fiyat 10000 üzerindeyse en yakın 100'lük basamağa yuvarla
528
  elif price_eft_float > 10000:
529
  price_eft = str(round(price_eft_float / 100) * 100)
530
+ # Diğer durumlarda en yakın 10'luk basamağa yuvarla
531
  else:
532
  price_eft = str(round(price_eft_float / 10) * 10)
533
  except (ValueError, TypeError):
 
539
  if price_rebate_str:
540
  try:
541
  price_rebate_float = float(price_rebate_str)
542
+ # Fiyat 200000 üzerindeyse en yakın 5000'lik basamağa yuvarla
543
  if price_rebate_float > 200000:
544
  price_rebate = str(round(price_rebate_float / 5000) * 5000)
545
+ # Fiyat 30000 üzerindeyse en yakın 1000'lik basamağa yuvarla
546
  elif price_rebate_float > 30000:
547
  price_rebate = str(round(price_rebate_float / 1000) * 1000)
548
+ # Fiyat 10000 üzerindeyse en yakın 100'lük basamağa yuvarla
549
  elif price_rebate_float > 10000:
550
  price_rebate = str(round(price_rebate_float / 100) * 100)
551
+ # Diğer durumlarda en yakın 10'luk basamağa yuvarla
552
  else:
553
  price_rebate = str(round(price_rebate_float / 10) * 10)
554
  except (ValueError, TypeError):
 
556
  else:
557
  price_rebate = ""
558
 
559
+ # Havale indirimli kampanyalı fiyatı yuvarla (varsa)
560
  if price_rebate_money_order_str:
561
  try:
562
  price_rebate_money_order_float = float(price_rebate_money_order_str)
563
+ # Fiyat 200000 üzerindeyse en yakın 5000'lik basamağa yuvarla
564
  if price_rebate_money_order_float > 200000:
565
  price_rebate_money_order = str(round(price_rebate_money_order_float / 5000) * 5000)
566
+ # Fiyat 30000 üzerindeyse en yakın 1000'lik basamağa yuvarla
567
  elif price_rebate_money_order_float > 30000:
568
  price_rebate_money_order = str(round(price_rebate_money_order_float / 1000) * 1000)
569
+ # Fiyat 10000 üzerindeyse en yakın 100'lük basamağa yuvarla
570
  elif price_rebate_money_order_float > 10000:
571
  price_rebate_money_order = str(round(price_rebate_money_order_float / 100) * 100)
572
+ # Diğer durumlarda en yakın 10'luk basamağa yuvarla
573
  else:
574
  price_rebate_money_order = str(round(price_rebate_money_order_float / 10) * 10)
575
  except (ValueError, TypeError):
 
610
 
611
  print(f"Toplam {len(products)} ürün yüklendi.")
612
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
613
  # Initialize enhanced features
614
  initialize_enhanced_features(OPENAI_API_KEY, products)
615
 
 
660
  file_io.seek(0)
661
  doc = Document(file_io)
662
 
663
+ content = f"\\n=== {file['name']} ===\\n"
664
  for paragraph in doc.paragraphs:
665
  if paragraph.text.strip():
666
+ content += paragraph.text + "\\n"
667
 
668
  all_content.append(content)
669
 
670
+ document_content = "\\n".join(all_content)
671
  print(f"Toplam {len(files)} döküman yüklendi.")
672
 
673
  except Exception as e:
 
683
  if os.path.exists(LOG_FILE):
684
  with file_lock:
685
  with open(LOG_FILE, 'w', encoding='utf-8') as f:
686
+ f.write("Log dosyası temizlendi.\\n")
687
  print("Log dosyası temizlendi.")
688
  except Exception as e:
689
  print(f"Log dosyası temizleme hatası: {e}")
 
696
  schedule.run_pending()
697
  time.sleep(60)
698
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
699
  # Chatbot fonksiyonu - STOK API ENTEGRASYONU EKLENDİ
700
  def chatbot_fn(user_message, history, image=None):
701
  if history is None:
702
  history = []
703
 
 
 
 
 
 
 
 
704
  try:
705
  # Enhanced features - Görsel işleme
706
  if image is not None:
 
719
  try:
720
  with file_lock:
721
  with open(LOG_FILE, 'a', encoding='utf-8') as f:
722
+ f.write(f"User: {user_message}\\n")
723
  except Exception as e:
724
  print(f"Dosya yazma hatası (Kullanıcı): {e}")
725
 
 
730
  if document_content:
731
  system_messages.append({"role": "system", "content": f"Dökümanlardan gelen bilgiler: {document_content[:3000]}"}) # Token limiti için kısalt
732
 
733
+ # STOK SORGUSU KONTROLÜ - YENİ EKLENEN KISIM
734
+ if is_stock_query(user_message):
735
  print("Stok sorgusu algılandı, API'den veri çekiliyor...")
736
 
737
  # Mesajdan ürün adını çıkarmaya çalış
738
+ # Basit bir yaklaşım: stok kelimelerini temizleyip kalan kelimeleri ürün adı olarak kullan
739
  product_words = []
740
  skip_words = ['stok', 'stock', 'kaç', 'adet', 'tane', 'var', 'mı', 'mi',
741
  'mevcut', 'mu', 'bulunuyor', 'hangi', 'mağaza', 'nerede',
 
845
 
846
  # Fiyat bilgisi varsa al
847
  if len(product_info[1]) > 1 and product_info[1][1]:
848
+ normal_price = f"\\nFiyat: {product_info[1][1]} TL"
849
  print(f"Fiyat bulundu: {product_info[1][1]}")
850
  else:
851
  normal_price = ""
 
857
  rebate_money_order_price = ""
858
 
859
  if len(product_info[1]) > 4 and product_info[1][4] and product_info[1][4] != "":
860
+ rebate_price = f"\\nKampanyalı fiyat: {product_info[1][4]} TL"
861
 
862
  try:
863
  normal_price_float = float(product_info[1][1])
 
874
  else:
875
  discount_amount_rounded = round(discount_amount / 10) * 10
876
 
877
+ discount_info = f"\\nYapılan indirim: {discount_amount_rounded:.0f} TL"
878
  except (ValueError, TypeError):
879
  discount_info = ""
880
 
881
  rebate_money_order_price = ""
882
  else:
883
  if product_info[1][3] and product_info[1][3] != "":
884
+ eft_price = f"\\nHavale indirimli fiyat: {product_info[1][3]} TL"
885
 
886
+ product_link = f"\\nÜrün linki: {product_info[1][2]}"
887
  product_image = ""
888
  if len(product_info[1]) > 6 and product_info[1][6]:
889
+ product_image = f"\\nÜrün resmi: {product_info[1][6]}"
890
 
891
  # API'den stok alındıysa sadece fiyat/görsel/link ekle
892
  if has_stock_from_api:
893
+ new_msg = f"ÜRÜN BİLGİLERİ (Fiyat/Link):\\n{normal_price}{rebate_price}{discount_info}{eft_price}{rebate_money_order_price}{product_link}{product_image}"
894
  else:
895
  # API'den stok alınmadıysa hem stok hem fiyat bilgisi ekle
896
+ 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}"
897
  else:
898
  # Stokta değilse
899
  if has_stock_from_api:
 
963
  try:
964
  with file_lock:
965
  with open(LOG_FILE, 'a', encoding='utf-8') as f:
966
+ f.write(f"Bot: {partial_response}\\n")
967
  except Exception as e:
968
  print(f"Dosya yazma hatası (Bot): {e}")
969
 
 
1247
  msg.submit(respond, [msg, chatbot], [msg, chatbot], show_progress=True)
1248
 
1249
  if __name__ == "__main__":
1250
+ demo.launch(debug=True)