BF / smart_warehouse.py
SamiKoen's picture
Ürün tipi anlama - forma, tayt, içlik, yağmurluk vb. tanıma
03755da
raw
history blame
11.7 kB
"""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}"
}
payload = {
"model": "gpt-5-chat-latest",
"messages": [
{"role": "system", "content": "You are a product matcher. Find ALL matching products. Return only index numbers."},
{"role": "user", "content": smart_prompt}
],
"temperature": 0,
"max_tokens": 100
}
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()