Spaces:
Sleeping
Sleeping
import os | |
import re | |
import gradio as gr | |
from gtts import gTTS | |
from datetime import datetime | |
from openpyxl import Workbook, load_workbook | |
import google.generativeai as genai | |
# LangChain memory | |
from langchain_core.prompts import ChatPromptTemplate | |
from langchain_core.messages import HumanMessage, AIMessage | |
from langchain_google_genai import ChatGoogleGenerativeAI | |
from langchain.memory import ConversationBufferMemory | |
from langchain.chains import ConversationChain | |
# ========== SETUP ========== | |
genai.configure(api_key="AIzaSyBJFmohAmhmqXQlM3fVxj8MLegVb26kyJk") | |
llm = ChatGoogleGenerativeAI(model="gemini-1.5-flash", convert_system_message_to_human=True) | |
memory = ConversationBufferMemory(return_messages=True) | |
chain = ConversationChain(llm=llm, memory=memory, verbose=False) | |
# Menu & State | |
MENU = { | |
"Cheeseburger": 5.99, | |
"Fries": 2.99, | |
"Coke": 1.99, | |
"Pizza": 12.99, | |
"Chicken Wings": 7.99, | |
"Salad": 6.99 | |
} | |
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 | |
# Voice | |
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 | |
# Prompt Template | |
system_prompt = """ | |
You are a helpful restaurant assistant at 'Systaurant'. | |
Your job is to: | |
- Greet the user and ask their name if not known. | |
- Show the menu if requested. | |
- Extract food items and quantities from the customer's message. | |
- If the user says 'done', summarize the order and ask for confirmation. | |
- If confirmed, respond with a thank you and order ID. | |
- Keep the tone friendly and human. Do not prefix with "Bot:". | |
Menu: | |
{menu} | |
Customer name: {name} | |
Order so far: {summary} | |
""" | |
prompt = ChatPromptTemplate.from_messages([ | |
("system", system_prompt), | |
("human", "{input}") | |
]) | |
def generate_response(user_input): | |
global customer_name, order | |
# Track name | |
if "my name is" in user_input.lower(): | |
customer_name = user_input.split("my name is")[-1].strip().split()[0].title() | |
# Track items | |
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)) | |
# Confirmation | |
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) | |
memory.chat_memory.add_user_message(user_input) | |
memory.chat_memory.add_ai_message(f"β Your order ID is {order_id}. Thank you for ordering from Saad's Restaurant!") | |
return f"β Your order ID is {order_id}. Thank you for ordering from Saad's Restaurant!" | |
menu_text = "\n".join([f"{item}: ${price}" for item, price in MENU.items()]) | |
summary = ", ".join([f"{qty} x {item}" for item, qty in order]) if order else "No items yet" | |
filled_prompt = prompt.invoke({ | |
"input": user_input, | |
"menu": menu_text, | |
"name": customer_name or "Not provided", | |
"summary": summary | |
}) | |
return chain.invoke(filled_prompt.to_string()) | |
def handle_chat(user_input): | |
bot_reply = generate_response(user_input) | |
audio_file = speak(bot_reply) | |
return bot_reply, audio_file | |
# Gradio Interface | |
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="π SysTaurant Voice Bot with Memory", | |
description="Place your restaurant order through chat with memory.", | |
theme="soft" | |
).launch(share=True) | |