Spaces:
Sleeping
Sleeping
File size: 6,851 Bytes
ac5adde 432eed9 3c72163 87e39fc 3c72163 432eed9 ac5adde 432eed9 ac5adde c3ca079 432eed9 87e39fc 3c72163 ac5adde c3ca079 ac5adde 3c72163 ac5adde 3c72163 ac5adde 3c72163 ac5adde 20f50df ac5adde 432eed9 ac5adde 20f50df ac5adde 4956423 3c72163 ac5adde 3c72163 20f50df ac5adde 432eed9 4956423 20f50df 432eed9 ac5adde 432eed9 ac5adde 3c72163 432eed9 ac5adde 3c72163 ac5adde 20f50df ac5adde 432eed9 c3ca079 432eed9 3c72163 432eed9 3c72163 432eed9 20f50df 432eed9 3c72163 20f50df 3c72163 20f50df 3c72163 432eed9 c3ca079 20f50df c3ca079 20f50df 432eed9 3c72163 432eed9 20f50df 432eed9 20f50df 432eed9 3c72163 20f50df 3c72163 20f50df 3c72163 4956423 c3ca079 3c72163 ac5adde 9bd7e4f ac5adde 432eed9 20f50df 9bd7e4f 432eed9 c3ca079 cd55775 8ac57a8 432eed9 c3ca079 3c72163 c3ca079 432eed9 20f50df 432eed9 9bd7e4f ac5adde 9bd7e4f 432eed9 20f50df c3ca079 87e39fc c3ca079 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | 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)
# ==================================================
@st.cache_data
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)
|