nagasurendra commited on
Commit
4038fb7
·
verified ·
1 Parent(s): 3690a94

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +233 -12
app.py CHANGED
@@ -1,9 +1,233 @@
 
 
 
 
 
 
 
1
  from fuzzywuzzy import process
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  def process_command(command):
4
  global cart, menu_preferences
5
  command = command.lower()
6
-
7
  # Recognize menu preferences first
8
  if menu_preferences == "all":
9
  if "vegetarian" in command and "non-vegetarian" not in command:
@@ -19,12 +243,12 @@ def process_command(command):
19
  menu_preferences = "all"
20
  return "You have chosen the complete menu. To view menu say menu"
21
 
 
22
  # Use filtered menu based on preference
23
  menu = menus.get(menu_preferences, menus["all"])
24
 
25
  if "menu" in command:
26
  return f"Here is your menu: {', '.join(menu)}. To select an item say item name"
27
-
28
  elif "price of" in command:
29
  item = command.replace("price of", "").strip()
30
  closest_match = process.extractOne(item, prices.keys())
@@ -32,7 +256,6 @@ def process_command(command):
32
  matched_item = closest_match[0]
33
  return f"The price of {matched_item} is ${prices[matched_item]}."
34
  return "Sorry, I couldn't find that item in the menu."
35
-
36
  elif "remove" in command:
37
  item = command.replace("remove", "").strip()
38
  closest_match = process.extractOne(item, cart)
@@ -41,16 +264,13 @@ def process_command(command):
41
  cart.remove(matched_item)
42
  return f"{matched_item.capitalize()} has been removed from your cart."
43
  return "Sorry, that item is not in your cart."
44
-
45
  elif any(item in command for item in menu):
46
- # Fuzzy match for menu items
47
- matched_item = process.extractOne(command, menu)
48
- if matched_item and matched_item[1] > 80: # Match threshold
49
- cart.append(matched_item[0])
50
- return f"{matched_item[0].capitalize()} added to your cart. Your cart now has: {', '.join(cart)}. To add another item say item name. To submit your order say final order. To know the price of an item say price of item name. To remove an item say remove item name."
51
  else:
52
  return "Sorry, I couldn't recognize the item. Could you try again?"
53
-
54
  elif "final order" in command or "submit" in command:
55
  if cart:
56
  total = sum(prices[item] for item in cart if item in prices)
@@ -59,10 +279,11 @@ def process_command(command):
59
  return response
60
  else:
61
  return "Your cart is empty. Please add items to your cart first."
62
-
63
  elif "no" in command or "nothing" in command or "goodbye" in command:
64
  cart.clear() # Clear cart on exit
65
  menu_preferences = "all"
66
  return "Goodbye! Thank you for using AI Dining Assistant."
67
-
68
  return "Sorry, I couldn't understand that. Please try again."
 
 
 
 
1
+ from flask import Flask, render_template_string, request, jsonify
2
+ import speech_recognition as sr
3
+ from tempfile import NamedTemporaryFile
4
+ import os
5
+ import ffmpeg
6
+ import logging
7
+ from werkzeug.exceptions import BadRequest
8
  from fuzzywuzzy import process
9
 
10
+ app = Flask(__name__)
11
+ logging.basicConfig(level=logging.INFO)
12
+
13
+ # Global variables
14
+ cart = []
15
+ menu_preferences = "all"
16
+ prices = {
17
+ "samosa": 9,
18
+ "onion pakoda": 10,
19
+ "chilli gobi": 12,
20
+ "chicken biryani": 14,
21
+ "mutton biryani": 16,
22
+ "veg biryani": 12,
23
+ "panner butter": 10,
24
+ "fish curry": 12,
25
+ "chicken manchurian": 14,
26
+ "veg manchurian": 12,
27
+ "chilli chicken": 14,
28
+ "panner biryani": 13,
29
+ "chicken curry": 14
30
+ }
31
+ menus = {
32
+ "all": list(prices.keys()),
33
+ "vegetarian": [
34
+ "samosa", "onion pakoda", "chilli gobi", "veg biryani", "panner butter", "veg manchurian", "panner biryani"
35
+ ],
36
+ "non-vegetarian": [
37
+ "chicken biryani", "mutton biryani", "fish curry", "chicken manchurian", "chilli chicken", "chicken curry"
38
+ ],
39
+ "guilt-free": ["samosa", "onion pakoda"]
40
+ }
41
+
42
+ html_code = """
43
+ <!DOCTYPE html>
44
+ <html lang="en">
45
+ <head>
46
+ <meta charset="UTF-8">
47
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
48
+ <title>AI Dining Assistant</title>
49
+ <style>
50
+ body {
51
+ display: flex;
52
+ flex-direction: column;
53
+ align-items: center;
54
+ justify-content: center;
55
+ min-height: 100vh;
56
+ margin: 0;
57
+ font-family: Arial, sans-serif;
58
+ background-color: #f4f4f9;
59
+ }
60
+ h1 {
61
+ color: #333;
62
+ }
63
+ .mic-button {
64
+ font-size: 2rem;
65
+ padding: 1rem 2rem;
66
+ color: white;
67
+ background-color: #007bff;
68
+ border: none;
69
+ border-radius: 50px;
70
+ cursor: pointer;
71
+ transition: background-color 0.3s;
72
+ }
73
+ .mic-button:hover {
74
+ background-color: #0056b3;
75
+ }
76
+ .status, .response {
77
+ margin-top: 1rem;
78
+ text-align: center;
79
+ color: #555;
80
+ font-size: 1.2rem;
81
+ }
82
+ .response {
83
+ background-color: #e8e8ff;
84
+ padding: 1rem;
85
+ border-radius: 10px;
86
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
87
+ display: none;
88
+ }
89
+ </style>
90
+ </head>
91
+ <body>
92
+ <h1>AI Dining Assistant</h1>
93
+ <button class="mic-button" id="mic-button">🎤</button>
94
+ <div class="status" id="status">Press the mic button to start...</div>
95
+ <div class="response" id="response">Response will appear here...</div>
96
+ <script>
97
+ const micButton = document.getElementById('mic-button');
98
+ const status = document.getElementById('status');
99
+ const response = document.getElementById('response');
100
+ let mediaRecorder;
101
+ let audioChunks = [];
102
+ let isConversationActive = false;
103
+ micButton.addEventListener('click', () => {
104
+ if (!isConversationActive) {
105
+ isConversationActive = true;
106
+ startConversation();
107
+ }
108
+ });
109
+ function startConversation() {
110
+ const utterance = new SpeechSynthesisUtterance('Please choose your preference: All, Vegetarian, Non-Vegetarian, or Guilt-Free.');
111
+ speechSynthesis.speak(utterance);
112
+ utterance.onend = () => {
113
+ status.textContent = 'Listening...';
114
+ startListening();
115
+ };
116
+ }
117
+ function startListening() {
118
+ navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
119
+ mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm;codecs=opus' });
120
+ mediaRecorder.start();
121
+ audioChunks = [];
122
+ mediaRecorder.ondataavailable = event => audioChunks.push(event.data);
123
+ mediaRecorder.onstop = async () => {
124
+ const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });
125
+ const formData = new FormData();
126
+ formData.append('audio', audioBlob);
127
+ status.textContent = 'Processing...';
128
+ try {
129
+ const result = await fetch('/process-audio', { method: 'POST', body: formData });
130
+ const data = await result.json();
131
+ response.textContent = data.response;
132
+ response.style.display = 'block';
133
+ const utterance = new SpeechSynthesisUtterance(data.response);
134
+ speechSynthesis.speak(utterance);
135
+ utterance.onend = () => {
136
+ console.log("Speech synthesis completed.");
137
+ if (data.response.includes("Goodbye")) {
138
+ status.textContent = 'Conversation ended. Press the mic button to start again.';
139
+ isConversationActive = false;
140
+ fetch('/reset-cart'); // Reset the cart dynamically on end
141
+ } else if (data.response.includes("Your order is complete")) {
142
+ status.textContent = 'Order complete. Thank you for using AI Dining Assistant.';
143
+ isConversationActive = false;
144
+ fetch('/reset-cart'); // Reset the cart after final order
145
+ } else {
146
+ status.textContent = 'Listening...';
147
+ setTimeout(() => {
148
+ startListening();
149
+ }, 500);
150
+ }
151
+ };
152
+ utterance.onerror = (e) => {
153
+ console.error("Speech synthesis error:", e.error);
154
+ status.textContent = 'Error with speech output.';
155
+ isConversationActive = false;
156
+ };
157
+ } catch (error) {
158
+ response.textContent = 'Sorry, I could not understand. Please try again.';
159
+ response.style.display = 'block';
160
+ status.textContent = 'Press the mic button to restart the conversation.';
161
+ isConversationActive = false;
162
+ }
163
+ };
164
+ setTimeout(() => mediaRecorder.stop(), 5000);
165
+ }).catch(() => {
166
+ status.textContent = 'Microphone access denied.';
167
+ isConversationActive = false;
168
+ });
169
+ }
170
+ </script>
171
+ </body>
172
+ </html>
173
+ """
174
+
175
+ @app.route('/')
176
+ def index():
177
+ return render_template_string(html_code)
178
+
179
+ @app.route('/reset-cart', methods=['GET'])
180
+ def reset_cart():
181
+ global cart
182
+ global menu_preferences
183
+ cart = []
184
+ menu_preferences = "all"
185
+ return "Cart reset successfully."
186
+
187
+ @app.route('/process-audio', methods=['POST'])
188
+ def process_audio():
189
+ try:
190
+ audio_file = request.files.get('audio')
191
+ if not audio_file:
192
+ raise BadRequest("No audio file provided.")
193
+
194
+ temp_file = NamedTemporaryFile(delete=False, suffix=".webm")
195
+ audio_file.save(temp_file.name)
196
+
197
+ if os.path.getsize(temp_file.name) == 0:
198
+ raise BadRequest("Uploaded audio file is empty.")
199
+
200
+ converted_file = NamedTemporaryFile(delete=False, suffix=".wav")
201
+ ffmpeg.input(temp_file.name).output(
202
+ converted_file.name, acodec='pcm_s16le', ac=1, ar='16000'
203
+ ).run(overwrite_output=True)
204
+
205
+ recognizer = sr.Recognizer()
206
+ recognizer.energy_threshold = 300 # Adjust for low-volume recognition
207
+ with sr.AudioFile(converted_file.name) as source:
208
+ audio_data = recognizer.record(source)
209
+ try:
210
+ command = recognizer.recognize_google(audio_data)
211
+ response = process_command(command)
212
+ except sr.UnknownValueError:
213
+ response = "Sorry, I could not understand. Please try again."
214
+
215
+ return jsonify({"response": response})
216
+
217
+ except BadRequest as br:
218
+ return jsonify({"response": f"Bad Request: {str(br)}"}), 400
219
+ except Exception as e:
220
+ return jsonify({"response": f"An error occurred: {str(e)}"}), 500
221
+ finally:
222
+ os.unlink(temp_file.name)
223
+ os.unlink(converted_file.name)
224
+
225
+ # Add this to the imports
226
+
227
  def process_command(command):
228
  global cart, menu_preferences
229
  command = command.lower()
230
+
231
  # Recognize menu preferences first
232
  if menu_preferences == "all":
233
  if "vegetarian" in command and "non-vegetarian" not in command:
 
243
  menu_preferences = "all"
244
  return "You have chosen the complete menu. To view menu say menu"
245
 
246
+
247
  # Use filtered menu based on preference
248
  menu = menus.get(menu_preferences, menus["all"])
249
 
250
  if "menu" in command:
251
  return f"Here is your menu: {', '.join(menu)}. To select an item say item name"
 
252
  elif "price of" in command:
253
  item = command.replace("price of", "").strip()
254
  closest_match = process.extractOne(item, prices.keys())
 
256
  matched_item = closest_match[0]
257
  return f"The price of {matched_item} is ${prices[matched_item]}."
258
  return "Sorry, I couldn't find that item in the menu."
 
259
  elif "remove" in command:
260
  item = command.replace("remove", "").strip()
261
  closest_match = process.extractOne(item, cart)
 
264
  cart.remove(matched_item)
265
  return f"{matched_item.capitalize()} has been removed from your cart."
266
  return "Sorry, that item is not in your cart."
 
267
  elif any(item in command for item in menu):
268
+ matched_item = next((item for item in menu if item in command), None)
269
+ if matched_item:
270
+ cart.append(matched_item)
271
+ return f"{matched_item.capitalize()} added to your cart. Your cart now has: {', '.join(cart)}. To add another item say item name. To submit your order say final order. To know the price of an item say price of item name. To remove an item say remove item name."
 
272
  else:
273
  return "Sorry, I couldn't recognize the item. Could you try again?"
 
274
  elif "final order" in command or "submit" in command:
275
  if cart:
276
  total = sum(prices[item] for item in cart if item in prices)
 
279
  return response
280
  else:
281
  return "Your cart is empty. Please add items to your cart first."
 
282
  elif "no" in command or "nothing" in command or "goodbye" in command:
283
  cart.clear() # Clear cart on exit
284
  menu_preferences = "all"
285
  return "Goodbye! Thank you for using AI Dining Assistant."
 
286
  return "Sorry, I couldn't understand that. Please try again."
287
+
288
+ if __name__ == "__main__":
289
+ app.run(host="0.0.0.0", port=7860)