SparkMartAI / app.py
akankshar639's picture
Update app.py
5067fe8 verified
import gradio as gr
from supervisor_agent import supervisor_agent
from database import engine
from sqlalchemy import text
import uuid
import pandas as pd
import os
from supabase import create_client
from dotenv import load_dotenv
load_dotenv()
supabase = create_client(os.getenv("SUPABASE_URL"), os.getenv("SUPABASE_KEY"))
def upload_file_to_supabase_gradio(file_path: str, order_id: str):
"""
Uploads a file to Supabase storage from a file path (Gradio format)
Returns the public URL or None if upload fails
"""
if not file_path:
return None
try:
with open(file_path, 'rb') as f:
file_bytes = f.read()
file_ext = os.path.splitext(file_path)[1].lstrip('.')
if not file_ext:
file_ext = 'bin'
timestamp = str(uuid.uuid4().hex)
storage_path = f"{order_id}_{timestamp}.{file_ext}"
res = supabase.storage.from_("complaints").upload(storage_path, file_bytes)
if isinstance(res, dict) and res.get("error"):
print(f"Supabase upload error: {res.get('error')}")
return None
public_url = supabase.storage.from_("complaints").get_public_url(storage_path)
print(f"File uploaded successfully: {public_url}")
return public_url
except Exception as e:
print(f"Error uploading file to Supabase: {e}")
import traceback
traceback.print_exc()
return None
def chat_with_agent(message, file, session_id):
"""Main chat function"""
if not session_id:
session_id = int(uuid.uuid4().int % 1000000)
session_id = int(session_id)
file_url = None
if file is not None:
print(f" File received: {file}")
print(f" File type: {type(file)}")
file_url = upload_file_to_supabase_gradio(file, order_id=str(session_id))
if file_url:
print(f" File uploaded: {file_url}")
else:
print(" File upload failed, continuing without file")
supervisor_input = f"Session ID: {session_id} | User Query: {message}"
if file_url:
supervisor_input += f" | FileURL: {file_url}"
print(f"\n Sending to supervisor: {supervisor_input}\n")
try:
result = supervisor_agent.invoke(
{"messages": [{"role": "user", "content": supervisor_input}]},
{"configurable": {"thread_id": str(session_id)}},
)
return result["messages"][-1].content, session_id
except Exception as e:
print(f" Error in chat_with_agent: {e}")
import traceback
traceback.print_exc()
return f"I apologize, but I encountered an error: {str(e)}", session_id
def view_orders(user_id):
"""View all orders for a user"""
try:
if not user_id:
return pd.DataFrame({"Message": ["Please enter a valid User ID"]})
with engine.connect() as conn:
result = conn.execute(
text(
"SELECT order_id, product_name, created_at FROM orders WHERE user_id = :user_id ORDER BY created_at DESC"),
{"user_id": int(user_id)}
)
rows = result.fetchall()
if not rows:
return pd.DataFrame({"Message": ["No orders found for this User ID"]})
df = pd.DataFrame(rows, columns=["Order ID", "Product Name", "Order Date"])
return df
except Exception as e:
return pd.DataFrame({"Error": [str(e)]})
def check_complaints(user_id):
"""View all complaints for a user"""
try:
if not user_id:
return pd.DataFrame({"Message": ["Please enter a valid User ID"]})
with engine.connect() as conn:
result = conn.execute(
text("""
SELECT order_id, product_name, complaint_text, complaint_file_url, created_at
FROM orders
WHERE user_id = :user_id AND is_complaint = 1
ORDER BY created_at DESC
"""),
{"user_id": int(user_id)}
)
rows = result.fetchall()
if not rows:
return pd.DataFrame({"Message": ["No complaints found for this User ID"]})
df = pd.DataFrame(rows, columns=["Order ID", "Product", "Complaint", "Evidence", "Date"])
return df
except Exception as e:
return pd.DataFrame({"Error": [str(e)]})
def upload_catalog(file, table_name):
"""Upload CSV/Excel to database"""
if not file:
return " Please select a file to upload"
try:
file_path = file if isinstance(file, str) else file.name
if file_path.endswith('.csv'):
df = pd.read_csv(file_path)
elif file_path.endswith(('.xlsx', '.xls')):
df = pd.read_excel(file_path)
else:
return " Please upload a CSV or Excel file"
df.to_sql(table_name, con=engine, if_exists="replace", index=False)
return f" Successfully uploaded {len(df)} rows to table '{table_name}'"
except Exception as e:
return f" Error: {str(e)}"
custom_css = """
#title-box {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 30px;
border-radius: 12px;
margin-bottom: 25px;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
text-align: center;
width: 100%;
}
#title-box h1 {
color: white !important;
margin: 0 !important;
font-size: 2.2em !important;
text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
text-align: center !important;
}
/* Target all buttons with variant="primary" */
button[variant="primary"] {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
border: none !important;
color: white !important;
font-weight: 600 !important;
border-radius: 8px !important;
transition: all 0.3s ease !important;
}
button[variant="primary"]:hover {
background: linear-gradient(135deg, #764ba2 0%, #667eea 100%) !important;
transform: translateY(-2px) !important;
box-shadow: 0 5px 20px rgba(102, 126, 234, 0.5) !important;
}
/* Backup selectors for buttons */
.primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
border: none !important;
color: white !important;
}
.primary:hover {
background: linear-gradient(135deg, #764ba2 0%, #667eea 100%) !important;
}
"""
with gr.Blocks() as demo:
gr.HTML("""
<div id="title-box">
<h1>🛍️ E-commerce Customer Support System</h1>
</div>
""")
session_state = gr.State(value=int(uuid.uuid4().int % 1000000))
with gr.Tabs():
with gr.Tab("💬 Chat with Support"):
gr.Markdown("### Talk to our AI support agent")
with gr.Row():
with gr.Column(scale=3):
chatbot = gr.Chatbot(height=400)
msg_input = gr.Textbox(
placeholder="Type your message here...",
label="Your Message",
lines=2
)
with gr.Row():
file_input = gr.File(
label="Attach file (for complaints)",
file_types=["image", "video", ".jpg", ".jpeg", ".png", ".mp4", ".mov"],
scale=2
)
with gr.Column(scale=1):
send_btn = gr.Button("Send", variant="primary", size="lg")
clear_btn = gr.Button("Clear Chat", variant="secondary", size="lg")
with gr.Column(scale=1):
session_display = gr.Textbox(
label="Your Session ID",
value=session_state.value,
interactive=False,
lines=2
)
gr.Markdown("""
**Tips:**
- Ask about products
- Place orders
- File complaints
- Upload evidence for complaints
**File Upload:**
- Click "Attach file" button
- Select image or video
- Then send your message
""")
def respond(message, chat_history, file_path, session_id):
"""Handle user message and bot response"""
if not message.strip():
return chat_history, session_id, None
try:
bot_response, updated_session = chat_with_agent(message, file_path, session_id)
chat_history.append({"role": "user", "content": message})
chat_history.append({"role": "assistant", "content": bot_response})
return chat_history, updated_session, None
except Exception as e:
print(f"Error in respond function: {e}")
import traceback
traceback.print_exc()
error_msg = f"I apologize, but I encountered an error: {str(e)}"
chat_history.append({"role": "user", "content": message})
chat_history.append({"role": "assistant", "content": error_msg})
return chat_history, session_id, None
send_btn.click(
respond,
inputs=[msg_input, chatbot, file_input, session_state],
outputs=[chatbot, session_state, file_input]
).then(
lambda: "",
outputs=[msg_input]
)
msg_input.submit(
respond,
inputs=[msg_input, chatbot, file_input, session_state],
outputs=[chatbot, session_state, file_input]
).then(
lambda: "",
outputs=[msg_input]
)
clear_btn.click(
lambda: ([], int(uuid.uuid4().int % 1000000)),
outputs=[chatbot, session_state]
)
with gr.Tab("📦 My Orders"):
gr.Markdown("### View all your orders")
user_id_orders = gr.Number(
label="Enter Your User ID",
precision=0
)
check_orders_btn = gr.Button("View My Orders", variant="primary")
orders_output = gr.Dataframe(
label="Your Orders",
headers=["Order ID", "Product Name", "Order Date"]
)
check_orders_btn.click(
view_orders,
inputs=[user_id_orders],
outputs=[orders_output]
)
with gr.Tab("⚠️ My Complaints"):
gr.Markdown("### Track your complaint status")
user_id_complaints = gr.Number(
label="Enter Your User ID",
precision=0
)
check_complaints_btn = gr.Button("View My Complaints", variant="primary")
complaints_output = gr.Dataframe(
label="Your Complaints",
headers=["Order ID", "Product", "Complaint", "Evidence Files", "Date"]
)
check_complaints_btn.click(
check_complaints,
inputs=[user_id_complaints],
outputs=[complaints_output]
)
with gr.Tab("📊 Upload Products (Admin)"):
gr.Markdown("### Upload product catalog to database")
gr.Markdown("⚠️ *Admin only - uploads CSV/Excel to database*")
catalog_file = gr.File(label="Upload CSV or Excel")
table_name_input = gr.Textbox(
label="Table Name",
value="Ecommerce_Data"
)
upload_btn = gr.Button("Upload to Database", variant="primary")
upload_status = gr.Textbox(label="Status")
upload_btn.click(
upload_catalog,
inputs=[catalog_file, table_name_input],
outputs=[upload_status]
)
gr.Markdown("""
---
### How to Use:
1. **Chat**: Talk to AI for product recommendations, place orders, or file complaints
2. **My Orders**: Check your order history using your User ID
3. **My Complaints**: Track complaint status and view evidence
4. **Upload Products** *(Admin)*: Add new products to the catalog
### Troubleshooting:
- If file upload fails, check console logs for errors
- Make sure SUPABASE_URL and SUPABASE_KEY are set in .env
- Supported file types: JPG, PNG, MP4, MOV
""")
if __name__ == "__main__":
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
debug=True,
css=custom_css
)