Spaces:
Sleeping
Sleeping
| import random | |
| import uuid | |
| import logging | |
| from datetime import datetime, timedelta | |
| import streamlit as st | |
| from openai import OpenAI | |
| # ================================================== | |
| # LOGGING | |
| # ================================================== | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format="%(asctime)s | %(levelname)s | %(message)s" | |
| ) | |
| logger = logging.getLogger("AI-Agent") | |
| # ================================================== | |
| # RAW DATA (600+ ROWS WITH DATE) | |
| # ================================================== | |
| def generate_data(rows: int = 600): | |
| random.seed(42) | |
| today = datetime.today().date() | |
| data = [] | |
| for i in range(1, rows + 1): | |
| data.append({ | |
| "order_id": i, | |
| "order_date": today - timedelta(days=random.randint(0, 30)), | |
| "supplier": random.choice( | |
| ["Supplier A", "Supplier B", "Supplier C", "Supplier D"] | |
| ), | |
| "product": random.choice( | |
| ["Tomato", "Cheese", "Flour", "Oil", "Meat"] | |
| ), | |
| "quantity": random.randint(1, 100), | |
| "price": round(random.uniform(5, 50), 2), | |
| "delivery_days": random.randint(1, 14), | |
| "status": random.choice( | |
| ["Delivered", "Pending", "Delayed"] | |
| ) | |
| }) | |
| logger.info("Generated %d rows of data", len(data)) | |
| return data | |
| DATA = generate_data() | |
| # ================================================== | |
| # UTILS: FORMAT RESPONSE AS TEXT | |
| # ================================================== | |
| def format_rows_as_text(rows): | |
| lines = [] | |
| for r in rows: | |
| lines.append( | |
| f"π§Ύ Order #{r['order_id']} | {r['order_date']}\n" | |
| f" Product: {r['product']}\n" | |
| f" Supplier: {r['supplier']}\n" | |
| f" Qty: {r['quantity']} | Price: ${r['price']}\n" | |
| f" Delivery: {r['delivery_days']} days | Status: {r['status']}\n" | |
| ) | |
| return "\n".join(lines) | |
| # ================================================== | |
| # TOOLS | |
| # ================================================== | |
| def tool_get_stats(): | |
| prices = [x["price"] for x in DATA] | |
| days = [x["delivery_days"] for x in DATA] | |
| logger.info("Tool β get_stats") | |
| return { | |
| "rows": len(DATA), | |
| "avg_price": round(sum(prices) / len(prices), 2), | |
| "avg_delivery_days": round(sum(days) / len(days), 2), | |
| } | |
| def tool_query_product(product: str): | |
| logger.info("Tool β query_product(%s)", product) | |
| return [x for x in DATA if x["product"].lower() == product.lower()][:5] | |
| def tool_query_last_days(days: int): | |
| logger.info("Tool β query_last_days(%d)", days) | |
| cutoff = datetime.today().date() - timedelta(days=days) | |
| return [x for x in DATA if x["order_date"] >= cutoff][:5] | |
| def tool_create_support_ticket(text: str): | |
| ticket_id = str(uuid.uuid4())[:8] | |
| logger.info("Tool β create_support_ticket (%s)", ticket_id) | |
| return ticket_id | |
| # ================================================== | |
| # SAFETY | |
| # ================================================== | |
| def is_dangerous(text: str): | |
| blocked = ["delete", "drop", "truncate", "remove"] | |
| return any(b in text.lower() for b in blocked) | |
| # ================================================== | |
| # AGENT | |
| # ================================================== | |
| def agent(user_input: str, openai_client: OpenAI): | |
| logger.info("User input: %s", user_input) | |
| if is_dangerous(user_input): | |
| return "β Dangerous operations are not allowed." | |
| text = user_input.lower() | |
| # ---- STATS ---- | |
| if "stats" in text or "summary" in text: | |
| s = tool_get_stats() | |
| return ( | |
| "π Business Overview\n" | |
| f"- Total rows: {s['rows']}\n" | |
| f"- Average price: ${s['avg_price']}\n" | |
| f"- Average delivery days: {s['avg_delivery_days']}" | |
| ) | |
| # ---- LAST N DAYS ---- | |
| if "last" in text and "day" in text: | |
| try: | |
| days = int([x for x in text.split() if x.isdigit()][0]) | |
| except: | |
| days = 3 | |
| rows = tool_query_last_days(days) | |
| if not rows: | |
| return f"No data found for last {days} days." | |
| return f"π¦ Orders from last {days} days:\n\n" + format_rows_as_text(rows) | |
| # ---- PRODUCT ---- | |
| if text.startswith("show"): | |
| product = user_input.replace("show", "").strip() | |
| rows = tool_query_product(product) | |
| if not rows: | |
| return "No records found. Would you like me to create a support ticket?" | |
| return f"π¦ Showing orders for **{product}**:\n\n" + format_rows_as_text(rows) | |
| # ---- SUPPORT ---- | |
| if "support" in text or "ticket" in text: | |
| ticket_id = tool_create_support_ticket(user_input) | |
| return ( | |
| "π« Support Ticket Created\n" | |
| f"- Ticket ID: {ticket_id}\n" | |
| "- System: GitHub Issues (mock)" | |
| ) | |
| # ---- OPENAI FALLBACK ---- | |
| logger.info("LLM fallback via OpenAI") | |
| response = openai_client.chat.completions.create( | |
| model="gpt-4o-mini", | |
| messages=[ | |
| { | |
| "role": "system", | |
| "content": ( | |
| "You are an AI procurement assistant. " | |
| "You do NOT have access to raw data." | |
| ) | |
| }, | |
| {"role": "user", "content": user_input} | |
| ], | |
| max_tokens=150, | |
| temperature=0.3 | |
| ) | |
| return response.choices[0].message.content | |
| # ================================================== | |
| # STREAMLIT UI | |
| # ================================================== | |
| st.set_page_config(page_title="AI Procurement Agent", layout="wide") | |
| st.title("π€ AI Procurement Agent (OpenAI)") | |
| # ---- SIDEBAR ---- | |
| st.sidebar.header("π OpenAI Configuration") | |
| api_key = st.sidebar.text_input( | |
| "OpenAI API Key", | |
| type="password", | |
| help="Paste your OpenAI API key here" | |
| ) | |
| stats = tool_get_stats() | |
| st.sidebar.header("π Business Information") | |
| st.sidebar.metric("Rows", stats["rows"]) | |
| st.sidebar.metric("Avg Price", f"${stats['avg_price']}") | |
| st.sidebar.metric("Avg Delivery Days", stats["avg_delivery_days"]) | |
| st.sidebar.markdown("### Sample queries") | |
| st.sidebar.code( | |
| "show tomato\n" | |
| "last 3 days\n" | |
| "database stats\n" | |
| "create support ticket" | |
| ) | |
| if not api_key: | |
| st.warning("Please enter your OpenAI API key to continue.") | |
| st.stop() | |
| openai_client = OpenAI(api_key=api_key) | |
| # ---- CHAT ---- | |
| if "messages" not in st.session_state: | |
| st.session_state.messages = [] | |
| user_input = st.chat_input("Ask the procurement agent...") | |
| if user_input: | |
| st.session_state.messages.append(("user", user_input)) | |
| reply = agent(user_input, openai_client) | |
| st.session_state.messages.append(("assistant", reply)) | |
| for role, message in st.session_state.messages: | |
| st.chat_message(role).write(message) | |