Spaces:
Sleeping
Sleeping
| import os | |
| import requests | |
| import gradio as gr | |
| from gtts import gTTS | |
| from datetime import datetime | |
| from openpyxl import Workbook, load_workbook | |
| import re | |
| from langchain.memory import ConversationBufferMemory | |
| # ========== CONFIGURATION ========== | |
| API_KEY = "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" | |
| MODEL = "google/gemma-3n-e2b-it:free" | |
| MENU = { | |
| "Cheeseburger": 5.99, | |
| "Fries": 2.99, | |
| "Coke": 1.99, | |
| "Pizza": 12.99, | |
| "Chicken Wings": 7.99, | |
| "Salad": 6.99 | |
| } | |
| memory = ConversationBufferMemory(return_messages=True) | |
| order = [] | |
| customer_name = "" | |
| # ========== Excel Setup ========== | |
| EXCEL_FILE = "orders.xlsx" | |
| def setup_excel(): | |
| if not os.path.exists(EXCEL_FILE): | |
| wb = Workbook() | |
| ws = wb.active | |
| ws.title = "Orders" | |
| ws.append(["Order ID", "Date", "Customer", "Items", "Total", "Time"]) | |
| wb.save(EXCEL_FILE) | |
| setup_excel() | |
| def save_to_excel(name, items): | |
| wb = load_workbook(EXCEL_FILE) | |
| ws = wb.active | |
| order_id = f"ORD{ws.max_row:04d}" | |
| now = datetime.now() | |
| total = sum(qty * MENU[item] for item, qty in items) | |
| items_str = ", ".join(f"{qty} x {item}" for item, qty in items) | |
| ws.append([order_id, now.strftime("%Y-%m-%d"), name, items_str, f"${total:.2f}", now.strftime("%H:%M:%S")]) | |
| wb.save(EXCEL_FILE) | |
| return order_id | |
| # ========== Text-to-Speech ========== | |
| def clean_text(text): | |
| text = re.sub(r"\*\*(.*?)\*\*", r"\1", text) | |
| text = re.sub(r"Bot\s*:\s*", "", text, flags=re.IGNORECASE) | |
| return text.strip() | |
| def speak(text, filename="response.mp3"): | |
| cleaned = clean_text(text) | |
| tts = gTTS(text=cleaned) | |
| tts.save(filename) | |
| return filename | |
| # ========== OpenRouter API ========== | |
| def generate_response(user_input): | |
| global customer_name, order | |
| memory.chat_memory.add_user_message(user_input) | |
| menu_description = "\n".join([f"{item}: ${price}" for item, price in MENU.items()]) | |
| order_summary = ", ".join([f"{qty} x {item}" for item, qty in order]) if order else "No items yet" | |
| context = f""" | |
| You are a helpful, kind restaurant assistant at 'PandaAI'. | |
| MENU: | |
| {menu_description} | |
| Customer name: {customer_name} | |
| Current order: {order_summary} | |
| Instructions: | |
| - Ask for name if not known. | |
| - Show menu if requested. | |
| - Extract item names and quantities from messages. | |
| - Say 'Order summary' and ask 'Confirm?' when user is done. | |
| - Respond only as the bot, no need to prefix with \"Bot:\". | |
| - Keep tone human, natural, and friendly. | |
| Conversation: | |
| """ | |
| for msg in memory.chat_memory.messages: | |
| if msg.type == "human": | |
| context += f"\nCustomer: {msg.content}" | |
| else: | |
| context += f"\nBot: {msg.content}" | |
| context += f"\nCustomer: {user_input}\nBot:" | |
| headers = { | |
| "Authorization": f"Bearer {API_KEY}", | |
| "Content-Type": "application/json" | |
| } | |
| payload = { | |
| "model": MODEL, | |
| "messages": [{"role": "user", "content": context}], | |
| } | |
| try: | |
| response = requests.post("https://openrouter.ai/api/v1/chat/completions", headers=headers, json=payload) | |
| response.raise_for_status() | |
| reply = response.json()["choices"][0]["message"]["content"] | |
| memory.chat_memory.add_ai_message(reply) | |
| return reply | |
| except Exception as e: | |
| return f"β OpenRouter Error: {str(e)}" | |
| # ========== Chat Logic ========== | |
| def handle_chat(user_input): | |
| global customer_name, order | |
| bot_reply = generate_response(user_input) | |
| if "my name is" in user_input.lower(): | |
| customer_name = user_input.split("my name is")[-1].strip().split()[0].title() | |
| for item in MENU: | |
| if item.lower() in user_input.lower(): | |
| qty = 1 | |
| for word in user_input.lower().split(): | |
| if word.isdigit(): | |
| qty = int(word) | |
| break | |
| order.append((item, qty)) | |
| if "confirm" in user_input.lower() or "yes" in user_input.lower(): | |
| if customer_name and order: | |
| order_id = save_to_excel(customer_name, order) | |
| bot_reply += f"\nβ Your order ID is {order_id}. Thank you for ordering from Saad's Restaurant!" | |
| audio_file = speak(bot_reply) | |
| return bot_reply, audio_file | |
| # ========== Gradio UI ========== | |
| gr.Interface( | |
| fn=handle_chat, | |
| inputs=gr.Textbox(label="π€ You", placeholder="Type your order..."), | |
| outputs=[ | |
| gr.Textbox(label="π€ Bot Response"), | |
| gr.Audio(label="π Speaking", autoplay=True) | |
| ], | |
| title="π PandaAI", | |
| description="Smart restaurant assistant powered by LangChain memory and OpenRouter API.", | |
| theme="soft" | |
| ).launch(share=True) | |