SamiKoen
Model adi gpt-5.5 olarak duzeltildi (chat-latest suffix'i kaldirildi); smart_warehouse.py'den temperature/max_tokens kaldirildi
cc9cc9e | """Smart warehouse stock finder using GPT-5's intelligence""" | |
| import requests | |
| import re | |
| import os | |
| import json | |
| def get_warehouse_stock_smart(user_message, previous_result=None): | |
| """Let GPT-5 intelligently find products or filter by warehouse""" | |
| OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") | |
| # Check if user is asking about specific warehouse | |
| warehouse_keywords = { | |
| 'caddebostan': 'Caddebostan', | |
| 'ortaköy': 'Ortaköy', | |
| 'ortakoy': 'Ortaköy', | |
| 'alsancak': 'Alsancak', | |
| 'izmir': 'Alsancak', | |
| 'bahçeköy': 'Bahçeköy', | |
| 'bahcekoy': 'Bahçeköy' | |
| } | |
| user_lower = user_message.lower() | |
| asked_warehouse = None | |
| for keyword, warehouse in warehouse_keywords.items(): | |
| if keyword in user_lower: | |
| asked_warehouse = warehouse | |
| break | |
| # Get XML data with retry | |
| xml_text = None | |
| for attempt in range(3): # Try 3 times | |
| try: | |
| url = 'https://video.trek-turkey.com/bizimhesap-warehouse-xml-b2b-api-v2.php' | |
| timeout_val = 10 + (attempt * 5) # Increase timeout on each retry: 10, 15, 20 | |
| response = requests.get(url, verify=False, timeout=timeout_val) | |
| xml_text = response.text | |
| print(f"DEBUG - XML fetched: {len(xml_text)} characters (attempt {attempt+1})") | |
| break | |
| except requests.exceptions.Timeout: | |
| print(f"XML fetch timeout (attempt {attempt+1}/3, timeout={timeout_val}s)") | |
| if attempt == 2: | |
| print("All attempts failed - timeout") | |
| return None | |
| except Exception as e: | |
| print(f"XML fetch error: {e}") | |
| return None | |
| # Extract just product blocks to reduce token usage | |
| product_pattern = r'<Product>(.*?)</Product>' | |
| all_products = re.findall(product_pattern, xml_text, re.DOTALL) | |
| # Create a simplified product list for GPT | |
| products_summary = [] | |
| for i, product_block in enumerate(all_products): | |
| name_match = re.search(r'<ProductName><!\[CDATA\[(.*?)\]\]></ProductName>', product_block) | |
| variant_match = re.search(r'<ProductVariant><!\[CDATA\[(.*?)\]\]></ProductVariant>', product_block) | |
| if name_match: | |
| # Check warehouse stock for this product | |
| warehouses_with_stock = [] | |
| warehouse_regex = r'<Warehouse>.*?<Name><!\[CDATA\[(.*?)\]\]></Name>.*?<Stock>(.*?)</Stock>.*?</Warehouse>' | |
| warehouses = re.findall(warehouse_regex, product_block, re.DOTALL) | |
| for wh_name, wh_stock in warehouses: | |
| try: | |
| if int(wh_stock.strip()) > 0: | |
| warehouses_with_stock.append(wh_name) | |
| except: | |
| pass | |
| product_info = { | |
| "index": i, | |
| "name": name_match.group(1), | |
| "variant": variant_match.group(1) if variant_match else "", | |
| "warehouses": warehouses_with_stock | |
| } | |
| products_summary.append(product_info) | |
| # If user is asking about specific warehouse, include that in prompt | |
| warehouse_filter = "" | |
| if asked_warehouse: | |
| warehouse_filter = f"\nIMPORTANT: User is asking specifically about {asked_warehouse} warehouse. Only return products available in that warehouse." | |
| # Let GPT-5 find ALL matching products | |
| smart_prompt = f"""User is asking: "{user_message}" | |
| Find ALL products that match this query from the list below. | |
| If user asks about specific size (S, M, L, XL, XXL, SMALL, MEDIUM, LARGE, X-LARGE), return only that size. | |
| If user asks generally (without size), return ALL variants of the product. | |
| {warehouse_filter} | |
| IMPORTANT BRAND AND PRODUCT TYPE RULES: | |
| - GOBIK: Spanish textile brand we import. When user asks about "gobik", return ALL products with "GOBIK" in the name. | |
| - Product names contain type information: FORMA (jersey/cycling shirt), TAYT (tights), İÇLİK (base layer), YAĞMURLUK (raincoat), etc. | |
| - Understand Turkish/English terms: | |
| * "erkek forma" / "men's jersey" -> Find products with FORMA in name | |
| * "tayt" / "tights" -> Find products with TAYT in name | |
| * "içlik" / "base layer" -> Find products with İÇLİK in name | |
| * "yağmurluk" / "raincoat" -> Find products with YAĞMURLUK in name | |
| - Gender: UNISEX means for both men and women. If no gender specified, it's typically men's. | |
| - Be smart: "erkek forma" should find all FORMA products (excluding women-specific if any) | |
| Products list (with warehouse availability): | |
| {json.dumps(products_summary, ensure_ascii=False, indent=2)} | |
| Return index numbers of ALL matching products as comma-separated list (e.g., "5,8,12,15"). | |
| If no products found, return: -1 | |
| Examples: | |
| - "madone sl 6 var mı" -> Return ALL Madone SL 6 variants | |
| - "erkek forma" -> Return all products with FORMA in name | |
| - "gobik tayt" -> Return all GOBIK products with TAYT in name | |
| - "içlik var mı" -> Return all products with İÇLİK in name | |
| - "gobik erkek forma" -> Return all GOBIK products with FORMA in name | |
| - "yağmurluk medium" -> Return all YAĞMURLUK products in MEDIUM size""" | |
| headers = { | |
| "Content-Type": "application/json", | |
| "Authorization": f"Bearer {OPENAI_API_KEY}" | |
| } | |
| # GPT-5.5 modeli temperature ve max_tokens desteklemiyor | |
| payload = { | |
| "model": "gpt-5.5", | |
| "messages": [ | |
| {"role": "system", "content": "You are a product matcher. Find ALL matching products. Return only index numbers."}, | |
| {"role": "user", "content": smart_prompt} | |
| ] | |
| } | |
| try: | |
| response = requests.post( | |
| "https://api.openai.com/v1/chat/completions", | |
| headers=headers, | |
| json=payload, | |
| timeout=10 | |
| ) | |
| if response.status_code == 200: | |
| result = response.json() | |
| indices_str = result['choices'][0]['message']['content'].strip() | |
| if indices_str == "-1": | |
| return ["Ürün bulunamadı"] | |
| try: | |
| # Parse multiple indices | |
| indices = [int(idx.strip()) for idx in indices_str.split(',')] | |
| # Collect all matching products | |
| all_variants = [] | |
| warehouse_stock = {} | |
| for idx in indices: | |
| if 0 <= idx < len(all_products): | |
| product_block = all_products[idx] | |
| # Get product name and variant | |
| name_match = re.search(r'<ProductName><!\[CDATA\[(.*?)\]\]></ProductName>', product_block) | |
| variant_match = re.search(r'<ProductVariant><!\[CDATA\[(.*?)\]\]></ProductVariant>', product_block) | |
| if name_match: | |
| product_name = name_match.group(1) | |
| variant = variant_match.group(1) if variant_match else "" | |
| # Track this variant | |
| variant_info = { | |
| 'name': product_name, | |
| 'variant': variant, | |
| 'warehouses': [] | |
| } | |
| # Get warehouse stock | |
| warehouse_regex = r'<Warehouse>.*?<Name><!\[CDATA\[(.*?)\]\]></Name>.*?<Stock>(.*?)</Stock>.*?</Warehouse>' | |
| warehouses = re.findall(warehouse_regex, product_block, re.DOTALL) | |
| for wh_name, wh_stock in warehouses: | |
| try: | |
| stock = int(wh_stock.strip()) | |
| if stock > 0: | |
| display_name = format_warehouse_name(wh_name) | |
| variant_info['warehouses'].append({ | |
| 'name': display_name, | |
| 'stock': stock | |
| }) | |
| # Track total stock per warehouse | |
| if display_name not in warehouse_stock: | |
| warehouse_stock[display_name] = 0 | |
| warehouse_stock[display_name] += stock | |
| except: | |
| pass | |
| if variant_info['warehouses']: # Only add if has stock | |
| all_variants.append(variant_info) | |
| # Format result | |
| result = [] | |
| if asked_warehouse: | |
| # Filter for specific warehouse | |
| warehouse_variants = [] | |
| for variant in all_variants: | |
| for wh in variant['warehouses']: | |
| if asked_warehouse in wh['name']: | |
| warehouse_variants.append({ | |
| 'name': variant['name'], | |
| 'variant': variant['variant'], | |
| 'stock': wh['stock'] | |
| }) | |
| if warehouse_variants: | |
| result.append(f"{format_warehouse_name(asked_warehouse)} mağazasında mevcut:") | |
| for v in warehouse_variants: | |
| result.append(f"• {v['name']} ({v['variant']})") | |
| else: | |
| result.append(f"{format_warehouse_name(asked_warehouse)} mağazasında bu ürün mevcut değil") | |
| else: | |
| # Show all variants and warehouses | |
| if all_variants: | |
| result.append(f"Bulunan {len(all_variants)} varyant:") | |
| # Show ALL variants (not just first 5) | |
| for variant in all_variants: | |
| variant_text = f" ({variant['variant']})" if variant['variant'] else "" | |
| result.append(f"• {variant['name']}{variant_text}") | |
| result.append("") | |
| result.append("Mağaza stok durumu:") | |
| for warehouse, total_stock in sorted(warehouse_stock.items()): | |
| result.append(f"• {warehouse}: Mevcut") | |
| else: | |
| result.append("Hiçbir mağazada stok yok") | |
| return result | |
| except (ValueError, IndexError) as e: | |
| print(f"DEBUG - Error parsing indices: {e}") | |
| return None | |
| else: | |
| print(f"GPT API error: {response.status_code}") | |
| return None | |
| except Exception as e: | |
| print(f"Error calling GPT: {e}") | |
| return None | |
| def format_warehouse_name(wh_name): | |
| """Format warehouse name nicely""" | |
| if "CADDEBOSTAN" in wh_name: | |
| return "Caddebostan mağazası" | |
| elif "ORTAKÖY" in wh_name: | |
| return "Ortaköy mağazası" | |
| elif "ALSANCAK" in wh_name: | |
| return "İzmir Alsancak mağazası" | |
| elif "BAHCEKOY" in wh_name or "BAHÇEKÖY" in wh_name: | |
| return "Bahçeköy mağazası" | |
| else: | |
| return wh_name.replace("MAGAZA DEPO", "").strip() |