Spaces:
Sleeping
Sleeping
import gradio as gr | |
import openai | |
import json | |
import os | |
import re | |
# Set your OpenAI API key | |
openai.api_key = os.getenv("OPENAI_API_KEY") | |
# OpenAI Assistant ID | |
ASSISTANT_ID = "asst_mDU549QCoU616nB69g5ZwI58" | |
# Load full product catalog | |
with open("cleaned_product_catalog.json", "r") as f: | |
PRODUCT_CATALOG = {item["ProductCode"]: item for item in json.load(f)} | |
# Global session state | |
cart = [] | |
thread_id = None | |
# 🧠 Smart JSON extractor that handles both ```json``` and loose JSON objects | |
def extract_cart_json_from_text(text): | |
blocks = [] | |
# 1. Try to find ```json ... ``` blocks | |
code_blocks = re.findall(r"```json(.*?)```", text, re.DOTALL) | |
for block in code_blocks: | |
try: | |
blocks.append(json.loads(block.strip())) | |
except Exception: | |
continue | |
# 2. Fall back to finding any JSON-like objects | |
if not blocks: | |
loose_jsons = re.findall(r"\{[\s\S]+?\}", text) | |
for snippet in loose_jsons: | |
try: | |
candidate = json.loads(snippet) | |
if "ProductCode" in candidate and "Description" in candidate: | |
blocks.append(candidate) | |
except Exception: | |
continue | |
return blocks | |
# 🔄 Communicate with OpenAI Assistant | |
def send_to_assistant(message): | |
global thread_id | |
if thread_id is None: | |
thread = openai.beta.threads.create() | |
thread_id = thread.id | |
openai.beta.threads.messages.create( | |
thread_id=thread_id, | |
role="user", | |
content=message | |
) | |
run = openai.beta.threads.runs.create( | |
thread_id=thread_id, | |
assistant_id=ASSISTANT_ID | |
) | |
while True: | |
run_status = openai.beta.threads.runs.retrieve( | |
thread_id=thread_id, | |
run_id=run.id | |
) | |
if run_status.status == "completed": | |
break | |
messages = openai.beta.threads.messages.list(thread_id=thread_id) | |
return messages.data[0].content[0].text.value | |
# 📦 Handle chat + add to cart | |
def assistant_response(message, chat_history): | |
global cart | |
response = send_to_assistant(message) | |
extracted_items = extract_cart_json_from_text(response) | |
if extracted_items: | |
for item in extracted_items: | |
cart.append(item) | |
chat_history.append((message, response)) | |
return "", chat_history, json.dumps(cart, indent=2) | |
# 🧼 Clear cart | |
def clear_cart(): | |
global cart | |
cart.clear() | |
return json.dumps(cart, indent=2) | |
# ✅ Finalise order | |
def submit_order(): | |
global cart | |
if not cart: | |
return "No items in cart, mate!" | |
customer = cart[0].get("Customer", {}) if cart else {} | |
discount_rate = customer.get("Discount", 0) | |
# Safe subtotal calc | |
subtotal = 0 | |
for item in cart: | |
try: | |
price = float(item["Price"]) | |
except: | |
price = 0.0 | |
subtotal += price * item.get("Quantity", 1) | |
discount_amt = round(subtotal * discount_rate, 2) | |
total = round(subtotal - discount_amt, 2) | |
# Save final order | |
order_summary = { | |
"Customer": customer, | |
"Products": [ | |
{k: v for k, v in item.items() if k != "Customer"} | |
for item in cart | |
], | |
"Totals": { | |
"Subtotal": round(subtotal, 2), | |
"DiscountRate": discount_rate, | |
"DiscountAmount": discount_amt, | |
"TotalAfterDiscount": total | |
} | |
} | |
with open("order_summary.json", "w") as f: | |
json.dump(order_summary, f, indent=2) | |
# Generate friendly summary | |
response_text = f"✅ Sweet as, {customer.get('Name', 'mate')} — your order’s locked in!\n\nHere’s what’s in the kit:\n\n" | |
for item in cart: | |
response_text += f"- {item['ProductCode']} — {item['Description']} — 💰 ${item['Price']}\n" | |
response_text += f"\n💲 **Subtotal:** ${subtotal:.2f}\n" | |
response_text += f"🎯 **Discount ({int(discount_rate*100)}%):** -${discount_amt:.2f}\n" | |
response_text += f"✅ **Total After Discount:** ${total:.2f}\n\n" | |
response_text += "We’ll get this sorted faster than a roo in a paddock. You’ll hear from us soon!" | |
cart.clear() | |
return response_text | |
# 🖼️ Gradio Interface | |
with gr.Blocks() as demo: | |
gr.Markdown("# 🧢 Westate Sales Assistant 🇦🇺\nTalk to your hose mate and build your order!") | |
with gr.Row(): | |
with gr.Column(scale=3): | |
chatbot = gr.Chatbot() | |
msg = gr.Textbox(label="Type your question here", placeholder="Ask Willy anything...") | |
send = gr.Button("Send") | |
with gr.Column(scale=2): | |
cart_display = gr.Textbox(label="🛒 Cart (Full JSON)", lines=20) | |
clear_btn = gr.Button("Clear Cart") | |
checkout_btn = gr.Button("Checkout") | |
send.click(assistant_response, inputs=[msg, chatbot], outputs=[msg, chatbot, cart_display]) | |
clear_btn.click(fn=clear_cart, outputs=cart_display) | |
checkout_btn.click(fn=submit_order, outputs=cart_display) | |
demo.launch() | |