BMS-AI-BOT / app /intent_parser.py
BMS Deployer
Remove header and fix inventory
9916f7c
raw
history blame
3.88 kB
import re
from app.data_loader import loader
class IntentParser:
def __init__(self):
pass
def parse(self, text):
text = text.lower()
response = {
"intent": "general_chat", # Default to LLM
"item_code": None,
"location": None,
"horizon_days": None,
"extra": {}
}
# 1. Detect Intent (order matters - more specific checks first)
if any(x in text for x in ["list items", "show catalog", "what items", "available items", "list available", "show items"]):
response["intent"] = "list_items"
elif any(x in text for x in ["forecast", "demand", "predict", "future", "sales"]):
response["intent"] = "demand_forecast"
elif any(x in text for x in ["details", "info", "about", "price", "description"]):
response["intent"] = "item_details"
elif any(x in text for x in ["inventory", "stock", "how many", "available", "on hand"]):
response["intent"] = "check_inventory"
elif any(x in text for x in ["supplier", "vendor", "who supplies", "lead time"]):
response["intent"] = "supplier_info"
elif any(x in text for x in ["buy", "order", "purchase", "requisition"]):
response["intent"] = "create_requisition"
elif any(x in text for x in ["status", "alerts", "dashboard", "overview"]):
response["intent"] = "system_status"
elif any(x in text for x in ["pdf", "download", "report", "file"]):
response["intent"] = "generate_report"
# 2. Extract Item Code
# Look for patterns like FS1234, BMS0001, etc. (2-3 letters + 4 digits)
item_match = re.search(r'\b([a-z]{2,3}\d{4})\b', text)
if item_match:
response["item_code"] = item_match.group(1).upper()
else:
# Fallback: check against known items in DB
if loader.items_df is not None:
known_items = loader.items_df['item_code'].tolist()
for item in known_items:
if item.lower() in text:
response["item_code"] = item
break
# 2.5 Extract Quantity (for orders)
qty_match = re.search(r'\b(\d+)\s*(?:units|pcs|pieces)?\b', text)
if qty_match:
# Avoid confusing horizon days with quantity if possible
# If "days" is not next to it, assume qty
if "day" not in text[qty_match.end():qty_match.end()+5]:
response["extra"]["qty"] = int(qty_match.group(1))
# 3. Extract Location
if re.search(r'\b(na|north america|usa|us)\b', text):
response["location"] = "NA"
elif re.search(r'\b(eu|europe|uk|germany)\b', text):
response["location"] = "EU"
elif re.search(r'\b(apac|asia|china|india)\b', text):
response["location"] = "APAC"
# 4. Extract Horizon
response["horizon_days"] = self._parse_horizon(text)
return response
def _parse_horizon(self, text):
days = None
# Explicit days
days_match = re.search(r'(\d+)\s*days?', text)
if days_match:
return int(days_match.group(1))
# Weeks
weeks_match = re.search(r'(\d+)\s*weeks?', text)
if weeks_match:
return int(weeks_match.group(1)) * 7
# Months
months_match = re.search(r'(\d+)\s*months?', text)
if months_match:
return int(months_match.group(1)) * 30
# Keywords
if "next week" in text:
return 7
if "next month" in text:
return 30
if "next year" in text:
return 365
if "tomorrow" in text:
return 1
return days
parser = IntentParser()