SamiKoen commited on
Commit
730bdef
·
verified ·
1 Parent(s): 19c2f41

Performance optimization: Add parallel API calls and caching for faster stock queries

Browse files
Files changed (1) hide show
  1. app.py +181 -5
app.py CHANGED
@@ -6,6 +6,7 @@ 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
@@ -32,6 +33,10 @@ from image_renderer import extract_product_info_for_gallery, format_message_with
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:
@@ -46,12 +51,183 @@ def normalize_turkish(text):
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 - endpoint parametresi eklendi
53
  warehouses_url = f"{STOCK_API_BASE}?action=warehouses&endpoint=warehouses"
54
- warehouses_response = requests.get(warehouses_url, timeout=5, verify=False)
55
 
56
  if warehouses_response.status_code != 200:
57
  print(f"Mağaza listesi alınamadı: {warehouses_response.status_code}")
@@ -84,7 +260,7 @@ def get_realtime_stock(product_name):
84
 
85
  # Mağaza stoklarını al - endpoint parametresi eklendi
86
  inventory_url = f"{STOCK_API_BASE}?action=inventory&warehouse={warehouse_id}&endpoint=inventory/{warehouse_id}"
87
- inventory_response = requests.get(inventory_url, timeout=5, verify=False)
88
 
89
  if inventory_response.status_code != 200:
90
  continue
@@ -507,7 +683,7 @@ def chatbot_fn(user_message, history, image=None):
507
  all_stock_info = []
508
 
509
  # Önce direkt API'de ara
510
- stock_info = get_realtime_stock(product_name)
511
  if stock_info:
512
  all_stock_info.append((product_name, stock_info))
513
 
@@ -515,12 +691,12 @@ def chatbot_fn(user_message, history, image=None):
515
  if len(product_words) <= 2 and 'fx' in product_name:
516
  # FX 3 varsa ara
517
  if '3' in product_name:
518
- fx3_info = get_realtime_stock('fx 3')
519
  if fx3_info:
520
  all_stock_info.append(('FX 3', fx3_info))
521
 
522
  # FX Sport AL 3 de ara
523
- fx_sport_info = get_realtime_stock('fx sport al 3')
524
  if fx_sport_info:
525
  all_stock_info.append(('FX Sport AL 3', fx_sport_info))
526
 
 
6
  import schedule
7
  import time
8
  import threading
9
+ from concurrent.futures import ThreadPoolExecutor, as_completed
10
  from huggingface_hub import HfApi, create_repo, hf_hub_download
11
  import warnings
12
  import pandas as pd
 
33
  # STOK API ENTEGRASYONU - YENİ EKLENEN KISIM
34
  STOCK_API_BASE = "https://video.trek-turkey.com/bizimhesap-proxy.php"
35
 
36
+ # Stock cache (5 dakikalık cache)
37
+ stock_cache = {}
38
+ CACHE_DURATION = 300 # 5 dakika (saniye cinsinden)
39
+
40
  def normalize_turkish(text):
41
  """Türkçe karakterleri normalize et"""
42
  if not text:
 
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:
57
+ warehouse_id = warehouse['id']
58
+ warehouse_name = warehouse['title']
59
+
60
+ # DSW'yi ayrı tut (gelecek stok için)
61
+ is_dsw = 'DSW' in warehouse_name or 'ÖN SİPARİŞ' in warehouse_name.upper()
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
69
+
70
+ inventory_data = inventory_response.json()
71
+
72
+ # API yanıtını kontrol et
73
+ if 'data' not in inventory_data or 'inventory' not in inventory_data['data']:
74
+ return None
75
+
76
+ products = inventory_data['data']['inventory']
77
+
78
+ # Ürünü ara
79
+ warehouse_variants = []
80
+ dsw_stock_count = 0
81
+
82
+ for product in products:
83
+ product_title = normalize_turkish(product.get('title', '')).lower()
84
+ original_title = product.get('title', '')
85
+
86
+ # Tüm arama terimlerinin ürün başlığında olup olmadığını kontrol et
87
+ if all(term in product_title for term in search_terms):
88
+ qty = int(product.get('qty', 0))
89
+ stock = int(product.get('stock', 0))
90
+ actual_stock = max(qty, stock)
91
+
92
+ if actual_stock > 0:
93
+ # DSW ise gelecek stok olarak say
94
+ if is_dsw:
95
+ dsw_stock_count += actual_stock
96
+ continue
97
+
98
+ # Normal mağaza stoğu - varyant detayını sakla
99
+ variant_info = original_title
100
+
101
+ # Ürün adını temizle
102
+ possible_names = [
103
+ product_name.upper(),
104
+ product_name.lower(),
105
+ product_name.title(),
106
+ product_name.upper().replace('I', 'İ'),
107
+ product_name.upper().replace('İ', 'I'),
108
+ ]
109
+
110
+ if 'fx sport' in product_name.lower():
111
+ possible_names.extend(['FX Sport AL 3', 'FX SPORT AL 3', 'Fx Sport Al 3'])
112
+
113
+ for possible_name in possible_names:
114
+ variant_info = variant_info.replace(possible_name, '').strip()
115
+
116
+ variant_info = ' '.join(variant_info.split())
117
+
118
+ if variant_info and variant_info != original_title:
119
+ warehouse_variants.append(f"{variant_info}: ✓ Stokta")
120
+ else:
121
+ warehouse_variants.append(f"{original_title}: ✓ Stokta")
122
+
123
+ # Sonuç döndür
124
+ if warehouse_variants and not is_dsw:
125
+ return {'warehouse': warehouse_name, 'variants': warehouse_variants, 'is_dsw': False}
126
+ elif dsw_stock_count > 0:
127
+ return {'dsw_stock': dsw_stock_count, 'is_dsw': True}
128
+
129
+ return None
130
+
131
+ except Exception:
132
+ return None
133
+
134
+ def get_realtime_stock_parallel(product_name):
135
+ """API'den gerçek zamanlı stok bilgisini çek - Paralel versiyon with cache"""
136
+ try:
137
+ # Cache kontrolü
138
+ cache_key = normalize_turkish(product_name).lower()
139
+ current_time = time.time()
140
+
141
+ if cache_key in stock_cache:
142
+ cached_data, cached_time = stock_cache[cache_key]
143
+ # Cache hala geçerli mi?
144
+ if current_time - cached_time < CACHE_DURATION:
145
+ print(f"Cache'den döndürülüyor: {product_name}")
146
+ return cached_data
147
+
148
+ # Önce mağaza listesini al
149
+ warehouses_url = f"{STOCK_API_BASE}?action=warehouses&endpoint=warehouses"
150
+ warehouses_response = requests.get(warehouses_url, timeout=3, verify=False)
151
+
152
+ if warehouses_response.status_code != 200:
153
+ print(f"Mağaza listesi alınamadı: {warehouses_response.status_code}")
154
+ return None
155
+
156
+ warehouses_data = warehouses_response.json()
157
+
158
+ # API yanıtını kontrol et
159
+ if 'data' not in warehouses_data or 'warehouses' not in warehouses_data['data']:
160
+ print("Mağaza verisi bulunamadı")
161
+ return None
162
+
163
+ warehouses = warehouses_data['data']['warehouses']
164
+
165
+ # Ürün adını normalize et
166
+ search_terms = normalize_turkish(product_name).lower().split()
167
+ print(f"Aranan ürün: {product_name} -> {search_terms}")
168
+
169
+ stock_info = {}
170
+ total_dsw_stock = 0
171
+ total_stock = 0
172
+
173
+ # Paralel olarak tüm mağazaları sorgula
174
+ with ThreadPoolExecutor(max_workers=10) as executor:
175
+ # Tüm mağazalar için görev oluştur
176
+ futures = {
177
+ executor.submit(fetch_warehouse_inventory, warehouse, product_name, search_terms): warehouse
178
+ for warehouse in warehouses
179
+ }
180
+
181
+ # Sonuçları topla
182
+ for future in as_completed(futures):
183
+ result = future.result()
184
+ if result:
185
+ if result.get('is_dsw'):
186
+ total_dsw_stock += result.get('dsw_stock', 0)
187
+ else:
188
+ warehouse_name = result['warehouse']
189
+ stock_info[warehouse_name] = result['variants']
190
+ total_stock += 1 # En az bir mağazada var
191
+
192
+ # Sonucu oluştur
193
+ if not stock_info:
194
+ # Mağazada yok ama DSW'de varsa
195
+ if total_dsw_stock > 0:
196
+ result = f"{product_name}: Şu anda mağazalarda stokta yok, ancak yakında gelecek. Ön sipariş verebilirsiniz."
197
+ else:
198
+ result = f"{product_name}: Şu anda hiçbir mağazada stokta bulunmuyor."
199
+ else:
200
+ # Minimal prompt oluştur - varyant detaylarıyla
201
+ prompt_lines = [f"{product_name} stok durumu:"]
202
+ for warehouse, variants in stock_info.items():
203
+ if isinstance(variants, list):
204
+ prompt_lines.append(f"- {warehouse}:")
205
+ for variant in variants:
206
+ prompt_lines.append(f" • {variant}")
207
+ else:
208
+ prompt_lines.append(f"- {warehouse}: {variants}")
209
+
210
+ # Güvenlik: Toplam adet bilgisi gösterme
211
+ if total_stock > 0:
212
+ prompt_lines.append(f"✓ Ürün stokta mevcut")
213
+
214
+ result = "\n".join(prompt_lines)
215
+
216
+ # Sonucu cache'e kaydet
217
+ stock_cache[cache_key] = (result, current_time)
218
+
219
+ return result
220
+
221
+ except Exception as e:
222
+ print(f"API hatası: {e}")
223
+ return None
224
+
225
  def get_realtime_stock(product_name):
226
  """API'den gerçek zamanlı stok bilgisini çek - Minimal versiyon"""
227
  try:
228
  # Önce mağaza listesini al - endpoint parametresi eklendi
229
  warehouses_url = f"{STOCK_API_BASE}?action=warehouses&endpoint=warehouses"
230
+ warehouses_response = requests.get(warehouses_url, timeout=3, verify=False) # Timeout 3 saniye
231
 
232
  if warehouses_response.status_code != 200:
233
  print(f"Mağaza listesi alınamadı: {warehouses_response.status_code}")
 
260
 
261
  # Mağaza stoklarını al - endpoint parametresi eklendi
262
  inventory_url = f"{STOCK_API_BASE}?action=inventory&warehouse={warehouse_id}&endpoint=inventory/{warehouse_id}"
263
+ inventory_response = requests.get(inventory_url, timeout=3, verify=False) # Timeout 3 saniye
264
 
265
  if inventory_response.status_code != 200:
266
  continue
 
683
  all_stock_info = []
684
 
685
  # Önce direkt API'de ara
686
+ stock_info = get_realtime_stock_parallel(product_name)
687
  if stock_info:
688
  all_stock_info.append((product_name, stock_info))
689
 
 
691
  if len(product_words) <= 2 and 'fx' in product_name:
692
  # FX 3 varsa ara
693
  if '3' in product_name:
694
+ fx3_info = get_realtime_stock_parallel('fx 3')
695
  if fx3_info:
696
  all_stock_info.append(('FX 3', fx3_info))
697
 
698
  # FX Sport AL 3 de ara
699
+ fx_sport_info = get_realtime_stock_parallel('fx sport al 3')
700
  if fx_sport_info:
701
  all_stock_info.append(('FX Sport AL 3', fx_sport_info))
702