Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -4,23 +4,15 @@ import gradio as gr
|
|
4 |
from gtts import gTTS
|
5 |
from datetime import datetime
|
6 |
from openpyxl import Workbook, load_workbook
|
7 |
-
import google.generativeai as genai
|
8 |
-
|
9 |
-
# LangChain memory
|
10 |
-
from langchain_core.prompts import ChatPromptTemplate
|
11 |
-
from langchain_core.messages import HumanMessage, AIMessage
|
12 |
-
from langchain_google_genai import ChatGoogleGenerativeAI
|
13 |
from langchain.memory import ConversationBufferMemory
|
14 |
-
from langchain.chains import ConversationChain
|
15 |
|
16 |
-
#
|
17 |
-
genai
|
|
|
18 |
|
19 |
-
|
20 |
-
memory = ConversationBufferMemory(return_messages=True)
|
21 |
-
chain = ConversationChain(llm=llm, memory=memory, verbose=False)
|
22 |
|
23 |
-
#
|
24 |
MENU = {
|
25 |
"Cheeseburger": 5.99,
|
26 |
"Fries": 2.99,
|
@@ -29,10 +21,14 @@ MENU = {
|
|
29 |
"Chicken Wings": 7.99,
|
30 |
"Salad": 6.99
|
31 |
}
|
|
|
|
|
|
|
|
|
32 |
order = []
|
33 |
customer_name = ""
|
34 |
|
35 |
-
# Excel Setup
|
36 |
EXCEL_FILE = "orders.xlsx"
|
37 |
def setup_excel():
|
38 |
if not os.path.exists(EXCEL_FILE):
|
@@ -54,50 +50,66 @@ def save_to_excel(name, items):
|
|
54 |
wb.save(EXCEL_FILE)
|
55 |
return order_id
|
56 |
|
57 |
-
#
|
58 |
-
|
59 |
def clean_text(text):
|
60 |
-
text = re.sub(r"\*\*(.*?)\*\*", r"\1", text)
|
61 |
-
text = re.sub(r"Bot\s*:\s*", "", text, flags=re.IGNORECASE)
|
62 |
return text.strip()
|
63 |
|
64 |
def speak(text, filename="response.mp3"):
|
65 |
-
|
66 |
-
tts = gTTS(text=cleaned)
|
67 |
tts.save(filename)
|
68 |
return filename
|
69 |
|
70 |
-
#
|
71 |
-
|
72 |
-
|
|
|
|
|
|
|
73 |
|
74 |
-
|
75 |
-
|
76 |
-
- Show the menu if requested.
|
77 |
-
- Extract food items and quantities from the customer's message.
|
78 |
-
- If the user says 'done', summarize the order and ask for confirmation.
|
79 |
-
- If confirmed, respond with a thank you and order ID.
|
80 |
-
- Keep the tone friendly and human. Do not prefix with "Bot:".
|
81 |
|
82 |
Menu:
|
83 |
-
{
|
84 |
-
|
85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
"""
|
87 |
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
])
|
92 |
|
93 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
global customer_name, order
|
95 |
|
96 |
-
|
|
|
|
|
|
|
97 |
if "my name is" in user_input.lower():
|
98 |
customer_name = user_input.split("my name is")[-1].strip().split()[0].title()
|
99 |
|
100 |
-
# Track items
|
101 |
for item in MENU:
|
102 |
if item.lower() in user_input.lower():
|
103 |
qty = 1
|
@@ -107,40 +119,23 @@ def generate_response(user_input):
|
|
107 |
break
|
108 |
order.append((item, qty))
|
109 |
|
110 |
-
# Confirmation
|
111 |
if "confirm" in user_input.lower() or "yes" in user_input.lower():
|
112 |
if customer_name and order:
|
113 |
order_id = save_to_excel(customer_name, order)
|
114 |
-
|
115 |
-
memory.chat_memory.add_ai_message(f"β
Your order ID is {order_id}. Thank you for ordering from Saad's Restaurant!")
|
116 |
-
return f"β
Your order ID is {order_id}. Thank you for ordering from Saad's Restaurant!"
|
117 |
|
118 |
-
menu_text = "\n".join([f"{item}: ${price}" for item, price in MENU.items()])
|
119 |
-
summary = ", ".join([f"{qty} x {item}" for item, qty in order]) if order else "No items yet"
|
120 |
-
|
121 |
-
filled_prompt = prompt.invoke({
|
122 |
-
"input": user_input,
|
123 |
-
"menu": menu_text,
|
124 |
-
"name": customer_name or "Not provided",
|
125 |
-
"summary": summary
|
126 |
-
})
|
127 |
-
|
128 |
-
return chain.invoke(filled_prompt.to_string())
|
129 |
-
|
130 |
-
def handle_chat(user_input):
|
131 |
-
bot_reply = generate_response(user_input)
|
132 |
audio_file = speak(bot_reply)
|
133 |
return bot_reply, audio_file
|
134 |
|
135 |
-
# Gradio
|
136 |
gr.Interface(
|
137 |
fn=handle_chat,
|
138 |
-
inputs=gr.Textbox(label="π€ You", placeholder="Type your order..."),
|
139 |
outputs=[
|
140 |
gr.Textbox(label="π€ Bot Response"),
|
141 |
gr.Audio(label="π Speaking", autoplay=True)
|
142 |
],
|
143 |
-
title="π
|
144 |
-
description="
|
145 |
theme="soft"
|
146 |
).launch(share=True)
|
|
|
4 |
from gtts import gTTS
|
5 |
from datetime import datetime
|
6 |
from openpyxl import Workbook, load_workbook
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
from langchain.memory import ConversationBufferMemory
|
|
|
8 |
|
9 |
+
# --- Gemini setup ---
|
10 |
+
import google.generativeai as genai
|
11 |
+
genai.configure(api_key="AIzaSyBJFmohAmhmqXQlM3fVxj8MLegVb26kyJk")
|
12 |
|
13 |
+
model = genai.GenerativeModel("models/gemini-1.5-flash-latest")
|
|
|
|
|
14 |
|
15 |
+
# --- Restaurant menu ---
|
16 |
MENU = {
|
17 |
"Cheeseburger": 5.99,
|
18 |
"Fries": 2.99,
|
|
|
21 |
"Chicken Wings": 7.99,
|
22 |
"Salad": 6.99
|
23 |
}
|
24 |
+
|
25 |
+
# --- Memory with LangChain ---
|
26 |
+
memory = ConversationBufferMemory(return_messages=True)
|
27 |
+
chat_history = []
|
28 |
order = []
|
29 |
customer_name = ""
|
30 |
|
31 |
+
# --- Excel Setup ---
|
32 |
EXCEL_FILE = "orders.xlsx"
|
33 |
def setup_excel():
|
34 |
if not os.path.exists(EXCEL_FILE):
|
|
|
50 |
wb.save(EXCEL_FILE)
|
51 |
return order_id
|
52 |
|
53 |
+
# --- TTS ---
|
|
|
54 |
def clean_text(text):
|
55 |
+
text = re.sub(r"\*\*(.*?)\*\*", r"\1", text) # Remove bold
|
56 |
+
text = re.sub(r"Bot\s*:\s*", "", text, flags=re.IGNORECASE) # Remove "Bot:"
|
57 |
return text.strip()
|
58 |
|
59 |
def speak(text, filename="response.mp3"):
|
60 |
+
tts = gTTS(text=clean_text(text))
|
|
|
61 |
tts.save(filename)
|
62 |
return filename
|
63 |
|
64 |
+
# --- Generate Gemini response ---
|
65 |
+
def generate_response(user_input):
|
66 |
+
global order, customer_name
|
67 |
+
|
68 |
+
menu_str = "\n".join([f"{item}: ${price}" for item, price in MENU.items()])
|
69 |
+
order_summary = ", ".join([f"{qty} x {item}" for item, qty in order]) if order else "No items yet"
|
70 |
|
71 |
+
prompt = f"""
|
72 |
+
You are a friendly, intelligent restaurant assistant at 'Systaurant'.
|
|
|
|
|
|
|
|
|
|
|
73 |
|
74 |
Menu:
|
75 |
+
{menu_str}
|
76 |
+
|
77 |
+
Customer Name: {customer_name}
|
78 |
+
Current Order: {order_summary}
|
79 |
+
|
80 |
+
Instructions:
|
81 |
+
- Ask for name if not known
|
82 |
+
- Show menu if asked
|
83 |
+
- Extract food items and quantity
|
84 |
+
- Say "Order summary" and ask "Confirm?" when user is done
|
85 |
+
- Respond naturally, no "Bot:" prefix
|
86 |
+
|
87 |
+
Conversation so far:
|
88 |
"""
|
89 |
|
90 |
+
for m in memory.chat_memory.messages:
|
91 |
+
role = "Customer" if m.type == "human" else "Bot"
|
92 |
+
prompt += f"{role}: {m.content}\n"
|
|
|
93 |
|
94 |
+
prompt += f"Customer: {user_input}\nBot:"
|
95 |
+
|
96 |
+
try:
|
97 |
+
response = model.generate_content(prompt)
|
98 |
+
return response.text
|
99 |
+
except Exception as e:
|
100 |
+
return f"β Gemini Error: {e}"
|
101 |
+
|
102 |
+
# --- Chat handler ---
|
103 |
+
def handle_chat(user_input):
|
104 |
global customer_name, order
|
105 |
|
106 |
+
memory.chat_memory.add_user_message(user_input)
|
107 |
+
bot_reply = generate_response(user_input)
|
108 |
+
memory.chat_memory.add_ai_message(bot_reply)
|
109 |
+
|
110 |
if "my name is" in user_input.lower():
|
111 |
customer_name = user_input.split("my name is")[-1].strip().split()[0].title()
|
112 |
|
|
|
113 |
for item in MENU:
|
114 |
if item.lower() in user_input.lower():
|
115 |
qty = 1
|
|
|
119 |
break
|
120 |
order.append((item, qty))
|
121 |
|
|
|
122 |
if "confirm" in user_input.lower() or "yes" in user_input.lower():
|
123 |
if customer_name and order:
|
124 |
order_id = save_to_excel(customer_name, order)
|
125 |
+
bot_reply += f"\nβ
Your order ID is {order_id}. Thank you for ordering from Systaurant!"
|
|
|
|
|
126 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
audio_file = speak(bot_reply)
|
128 |
return bot_reply, audio_file
|
129 |
|
130 |
+
# --- Gradio UI ---
|
131 |
gr.Interface(
|
132 |
fn=handle_chat,
|
133 |
+
inputs=gr.Textbox(label="π€ You", placeholder="Type your order here..."),
|
134 |
outputs=[
|
135 |
gr.Textbox(label="π€ Bot Response"),
|
136 |
gr.Audio(label="π Speaking", autoplay=True)
|
137 |
],
|
138 |
+
title="π Systaurant Voice Bot",
|
139 |
+
description="A smart voice-enabled assistant to take food orders.",
|
140 |
theme="soft"
|
141 |
).launch(share=True)
|