Update app.py
Browse files
app.py
CHANGED
|
@@ -18,6 +18,7 @@ from googleapiclient.http import MediaIoBaseDownload
|
|
| 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
|
|
@@ -622,6 +623,40 @@ if root is not None:
|
|
| 622 |
|
| 623 |
print(f"Toplam {len(products)} ürün yüklendi.")
|
| 624 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 625 |
# Initialize enhanced features
|
| 626 |
initialize_enhanced_features(OPENAI_API_KEY, products)
|
| 627 |
|
|
@@ -708,39 +743,54 @@ def run_scheduler(chat_history):
|
|
| 708 |
schedule.run_pending()
|
| 709 |
time.sleep(60)
|
| 710 |
|
| 711 |
-
# NEW: Stok sorularına deterministik, tamamen veri tabanlı yanıt
|
| 712 |
def answer_stock_grounded(user_message):
|
| 713 |
"""
|
| 714 |
Stok sorularına tamamen veri-tabanlı, deterministik yanıt üretir.
|
| 715 |
Yalnızca API + XML kullanır, LLM'ye gitmez.
|
|
|
|
| 716 |
"""
|
| 717 |
-
# 1) Ürün adı çıkarma
|
| 718 |
skip_words = ['stok','stock','kaç','adet','tane','var','mı','mi','mevcut','mu','bulunuyor',
|
| 719 |
'hangi','mağaza','nerede','durumu','stoklarda','stokta',
|
| 720 |
'için','ve','ile','toplam','toplamda','fiyat','fiyatı','ne','nedir','kadar',
|
| 721 |
'beden','bedeni','bedenli']
|
| 722 |
-
|
| 723 |
-
if not
|
| 724 |
return "Hangi ürün için stok bakmamı istersiniz?"
|
| 725 |
|
| 726 |
-
# Sadece beden mi sorulmuş?
|
| 727 |
size_terms = {'xs','s','m','ml','l','xl','xxl','2xl','3xl','small','medium','large',
|
| 728 |
'44','46','48','50','52','54','56','58','60'}
|
| 729 |
-
is_only_size = (len(
|
| 730 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 731 |
|
| 732 |
-
#
|
| 733 |
stock_text = get_realtime_stock_parallel(product_name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 734 |
if not stock_text:
|
| 735 |
return f"'{product_name}' için stok bilgisine şu an erişemedim."
|
| 736 |
|
| 737 |
-
#
|
| 738 |
norm_query = normalize_turkish(product_name).replace(" ", "")
|
| 739 |
extra_lines = []
|
| 740 |
added = 0
|
| 741 |
try:
|
| 742 |
for name, info, full_name in products:
|
| 743 |
-
if added >= 3:
|
| 744 |
break
|
| 745 |
norm_full = normalize_turkish(full_name).replace(" ", "")
|
| 746 |
if norm_query and norm_query in norm_full:
|
|
|
|
| 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
|
|
|
|
| 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 |
|
|
|
|
| 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:
|