Subbu1304 commited on
Commit
5ac6592
·
verified ·
1 Parent(s): 2e5aa0d

Create menu.py

Browse files
Files changed (1) hide show
  1. menu.py +264 -0
menu.py ADDED
@@ -0,0 +1,264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from simple_salesforce import Salesforce
2
+ import logging
3
+ from flask import Flask, render_template_string, request, jsonify
4
+ import speech_recognition as sr
5
+ from tempfile import NamedTemporaryFile
6
+ import os
7
+ import ffmpeg
8
+ from werkzeug.exceptions import BadRequest
9
+
10
+ app = Flask(__name__)
11
+ logging.basicConfig(level=logging.INFO)
12
+
13
+ # Salesforce connection setup
14
+ sf = Salesforce(
15
+ username='diggavalli98@gmail.com',
16
+ password='Sati@1020',
17
+ security_token='sSSjyhInIsUohKpG8sHzty2q',
18
+ consumer_key='3MVG9WVXk15qiz1JbtW1tT9a7Wnkos2RuGamw6p1lC5uPescT5NB2nPygpo6rQ87K1T.zBEn.wR.A6JdgHnIU',
19
+ consumer_secret='A75C6B7801D5D20BED0E46631CF58C4F7FF28E4DAF442FE667553D29C35C0451'
20
+ )
21
+
22
+ # Global variables
23
+ cart = [] # To store items, quantities, and prices
24
+ MENU = {}
25
+
26
+ current_category = None
27
+ current_item = None
28
+ awaiting_quantity = False
29
+
30
+ # Fetching menu items dynamically from Salesforce
31
+ def get_menu_items():
32
+ menu_items = {}
33
+ # Querying the Menu_Item__c object to fetch details
34
+ query = "SELECT Name, Category__c, Price__c, Ingredients__c FROM Menu_Item__c"
35
+ results = sf.query_all(query)
36
+
37
+ # Organizing the menu items by category
38
+ for record in results['records']:
39
+ category = record['Category__c']
40
+ item_name = record['Name']
41
+ price = record['Price__c']
42
+
43
+ if category not in menu_items:
44
+ menu_items[category] = {}
45
+ menu_items[category][item_name] = price
46
+
47
+ return menu_items
48
+
49
+ # Update global MENU variable
50
+ MENU = get_menu_items()
51
+
52
+ # Extract quantity from command (e.g., "two" -> 2, "three" -> 3, etc.)
53
+ def extract_quantity(command):
54
+ number_words = {
55
+ "one": 1, "two": 2, "three": 3, "four": 4, "five": 5,
56
+ "six": 6, "seven": 7, "eight": 8, "nine": 9, "ten": 10,
57
+ "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9, "10": 10
58
+ }
59
+
60
+ command_words = command.split()
61
+ for word in command_words:
62
+ if word in number_words:
63
+ return number_words[word]
64
+ return None
65
+
66
+ # HTML Template for Frontend
67
+ html_code = """
68
+ <!DOCTYPE html>
69
+ <html lang="en">
70
+ <head>
71
+ <meta charset="UTF-8">
72
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
73
+ <title>AI Dining Assistant</title>
74
+ <style>
75
+ body {
76
+ font-family: Arial, sans-serif;
77
+ text-align: center;
78
+ background-color: #f4f4f9;
79
+ }
80
+ h1 {
81
+ color: #333;
82
+ }
83
+ .status, .response {
84
+ margin-top: 20px;
85
+ }
86
+ </style>
87
+ </head>
88
+ <body>
89
+ <h1>AI Dining Assistant</h1>
90
+ <div class="status" id="status">Starting interaction...</div>
91
+ <div class="response" id="response" style="display: none;">Response will appear here...</div>
92
+ <script>
93
+ const status = document.getElementById('status');
94
+ const response = document.getElementById('response');
95
+ let isListening = false;
96
+ // Auto-trigger greeting and listening when the page loads
97
+ window.onload = function() {
98
+ greetUser();
99
+ };
100
+ function greetUser() {
101
+ const utterance = new SpeechSynthesisUtterance("Hi. Welcome to Biryani Hub. Can I show you the menu?");
102
+ speechSynthesis.speak(utterance);
103
+ utterance.onend = () => {
104
+ status.textContent = "Listening...";
105
+ startListening();
106
+ };
107
+ }
108
+ async function startListening() {
109
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
110
+ const mediaRecorder = new MediaRecorder(stream, { mimeType: "audio/webm;codecs=opus" });
111
+ const audioChunks = [];
112
+ mediaRecorder.ondataavailable = (event) => audioChunks.push(event.data);
113
+ mediaRecorder.onstop = async () => {
114
+ const audioBlob = new Blob(audioChunks, { type: "audio/webm" });
115
+ const formData = new FormData();
116
+ formData.append("audio", audioBlob);
117
+ status.textContent = "Processing...";
118
+ try {
119
+ const result = await fetch("/process-audio", { method: "POST", body: formData });
120
+ const data = await result.json();
121
+ response.textContent = data.response;
122
+ response.style.display = "block";
123
+ const utterance = new SpeechSynthesisUtterance(data.response);
124
+ speechSynthesis.speak(utterance);
125
+ utterance.onend = () => {
126
+ if (!data.response.includes("Goodbye") && !data.response.includes("final order")) {
127
+ startListening(); // Continue listening
128
+ } else {
129
+ status.textContent = "Conversation ended.";
130
+ isListening = false;
131
+ }
132
+ };
133
+ } catch (error) {
134
+ response.textContent = "Error processing your request. Please try again.";
135
+ status.textContent = "An error occurred. Restarting...";
136
+ isListening = false;
137
+ }
138
+ };
139
+ mediaRecorder.start();
140
+ setTimeout(() => mediaRecorder.stop(), 5000); // Stop recording after 5 seconds
141
+ }
142
+ </script>
143
+ </body>
144
+ </html>
145
+ """
146
+
147
+ @app.route("/")
148
+ def index():
149
+ return render_template_string(html_code)
150
+
151
+ @app.route("/process-audio", methods=["POST"])
152
+ def process_audio():
153
+ global current_category, current_item, awaiting_quantity
154
+ try:
155
+ audio_file = request.files.get("audio")
156
+ if not audio_file:
157
+ raise BadRequest("No audio file provided.")
158
+
159
+ temp_file = NamedTemporaryFile(delete=False, suffix=".webm")
160
+ audio_file.save(temp_file.name)
161
+
162
+ if os.path.getsize(temp_file.name) == 0:
163
+ raise BadRequest("Uploaded audio file is empty.")
164
+
165
+ converted_file = NamedTemporaryFile(delete=False, suffix=".wav")
166
+ ffmpeg.input(temp_file.name).output(
167
+ converted_file.name, acodec="pcm_s16le", ac=1, ar="16000"
168
+ ).run(overwrite_output=True)
169
+
170
+ recognizer = sr.Recognizer()
171
+ with sr.AudioFile(converted_file.name) as source:
172
+ audio_data = recognizer.record(source)
173
+ try:
174
+ command = recognizer.recognize_google(audio_data)
175
+ logging.info(f"Recognized command: {command}")
176
+ response = process_command(command)
177
+ except sr.UnknownValueError:
178
+ response = "Sorry, I couldn't understand your command. Could you please repeat?"
179
+ except sr.RequestError as e:
180
+ response = f"Error with the speech recognition service: {e}"
181
+
182
+ return jsonify({"response": response})
183
+
184
+ except BadRequest as br:
185
+ return jsonify({"response": f"Bad Request: {str(br)}"}), 400
186
+ except Exception as e:
187
+ return jsonify({"response": f"An error occurred: {str(e)}"}), 500
188
+ finally:
189
+ os.unlink(temp_file.name)
190
+ os.unlink(converted_file.name)
191
+
192
+ def process_command(command):
193
+ global cart, MENU, current_category, current_item, awaiting_quantity
194
+ command = command.lower()
195
+
196
+ # Handle quantity input
197
+ if awaiting_quantity:
198
+ quantity = extract_quantity(command)
199
+ if quantity:
200
+ cart.append((current_item, MENU[current_category][current_item], quantity))
201
+ awaiting_quantity = False
202
+ item = current_item
203
+ current_item = None
204
+ total = sum(i[1] * i[2] for i in cart)
205
+ cart_summary = ", ".join([f"{i[0]} x{i[2]} (₹{i[1] * i[2]})" for i in cart])
206
+ return f"Added {quantity} x {item} to your cart. Your current cart: {cart_summary}. Total: ₹{total}. Would you like to add more items?"
207
+ else:
208
+ return "Sorry, I couldn't understand the quantity. Please provide a valid quantity."
209
+
210
+ # Handle category selection
211
+ for category, items in MENU.items():
212
+ if category.lower() in command:
213
+ current_category = category
214
+ item_list = ", ".join([f"{item} (₹{price})" for item, price in items.items()])
215
+ return f"{category} menu: {item_list}. What would you like to order?"
216
+
217
+ # Handle item selection with dynamic matching
218
+ if current_category:
219
+ for item in MENU[current_category].keys():
220
+ if item.lower().startswith(command) or command in item.lower():
221
+ current_item = item
222
+ awaiting_quantity = True
223
+ return f"How many quantities of {current_item} would you like?"
224
+
225
+ # Handle item removal
226
+ if "remove" in command:
227
+ for item in cart:
228
+ if item[0].lower() in command:
229
+ cart.remove(item)
230
+ total = sum(i[1] * i[2] for i in cart)
231
+ cart_summary = ", ".join([f"{i[0]} x{i[2]} (₹{i[1] * i[2]})" for i in cart])
232
+ return f"Removed {item[0]} from your cart. Updated cart: {cart_summary}. Total: ₹{total}."
233
+ return "The item you are trying to remove is not in your cart."
234
+
235
+ # Handle final order
236
+ if "final order" in command or "submit" in command or "Proceed" in command or "place the order" in command:
237
+ if cart:
238
+ order_details = ", ".join([f"{item[0]} x{item[2]} (₹{item[1] * item[2]})" for item in cart])
239
+ total = sum(item[1] * item[2] for item in cart)
240
+ cart.clear()
241
+ return f"Your final order is: {order_details}. Total price: ₹{total}. Your order will arrive soon, Thank you for visiting Biryani Hub!"
242
+ else:
243
+ return "Your cart is empty. Please add items before placing the final order."
244
+
245
+ # Handle cart details
246
+ if "cart details" in command:
247
+ if cart:
248
+ cart_summary = "\n".join([f"{i[0]} x{i[2]} (₹{i[1] * i[2]})" for i in cart])
249
+ total = sum(i[1] * i[2] for i in cart)
250
+ return f"Your cart contains:\n{cart_summary}\nTotal: ₹{total}."
251
+ else:
252
+ return "Your cart is empty."
253
+
254
+ # Handle menu request
255
+ if "menu" in command or "yes" in command or "yeah" in command:
256
+ categories = ", ".join(MENU.keys())
257
+ return f"We have the following categories: {categories}. Please select a category to proceed."
258
+
259
+ # Default response
260
+ return "Sorry, I didn't understand that. Please try again."
261
+
262
+
263
+ if __name__ == "__main__":
264
+ app.run(host="0.0.0.0", port=7860)