from flask import Flask, render_template_string, request, jsonify import speech_recognition as sr from tempfile import NamedTemporaryFile import os import ffmpeg import logging from werkzeug.exceptions import BadRequest from fuzzywuzzy import process app = Flask(__name__) logging.basicConfig(level=logging.INFO) # Global variables cart = [] menu_preferences = "all" prices = { "samosa": 9, "onion pakoda": 10, "chilli gobi": 12, "chicken biryani": 14, "mutton biryani": 16, "veg biryani": 12, "panner butter": 10, "fish curry": 12, "chicken manchurian": 14, "veg manchurian": 12, "chilli chicken": 14, "panner biryani": 13, "chicken curry": 14 } menus = { "all": list(prices.keys()), "vegetarian": [ "samosa", "onion pakoda", "chilli gobi", "veg biryani", "panner butter", "veg manchurian", "panner biryani" ], "non-vegetarian": [ "chicken biryani", "mutton biryani", "fish curry", "chicken manchurian", "chilli chicken", "chicken curry" ], "guilt-free": ["samosa", "onion pakoda"] } html_code = """ AI Dining Assistant

AI Dining Assistant

Press the mic button to start...
Response will appear here...
""" @app.route('/') def index(): return render_template_string(html_code) @app.route('/reset-cart', methods=['GET']) def reset_cart(): global cart global menu_preferences cart = [] menu_preferences = "all" return "Cart reset successfully." @app.route('/process-audio', methods=['POST']) def process_audio(): try: audio_file = request.files.get('audio') if not audio_file: raise BadRequest("No audio file provided.") temp_file = NamedTemporaryFile(delete=False, suffix=".webm") audio_file.save(temp_file.name) if os.path.getsize(temp_file.name) == 0: raise BadRequest("Uploaded audio file is empty.") converted_file = NamedTemporaryFile(delete=False, suffix=".wav") ffmpeg.input(temp_file.name).output( converted_file.name, acodec='pcm_s16le', ac=1, ar='16000' ).run(overwrite_output=True) recognizer = sr.Recognizer() recognizer.dynamic_energy_threshold = True # Enable dynamic threshold recognizer.energy_threshold = 100 # Lower threshold for better sensitivity with sr.AudioFile(converted_file.name) as source: audio_data = recognizer.record(source) try: command = recognizer.recognize_google(audio_data, show_all=True) if "alternative" in command: best_match = command["alternative"][0] if best_match.get("confidence", 0) > 0.6: # Confidence threshold command_text = best_match["transcript"].lower() response = process_command(command_text) else: response = "I couldn't confidently understand that. Please repeat." else: response = "Sorry, I couldn't understand. Please try again." except sr.UnknownValueError: response = "Sorry, I couldn't understand. Please try again." return jsonify({"response": response}) except BadRequest as br: return jsonify({"response": f"Bad Request: {str(br)}"}), 400 except Exception as e: return jsonify({"response": f"An error occurred: {str(e)}"}), 500 finally: os.unlink(temp_file.name) os.unlink(converted_file.name) def process_command(command): global cart, menu_preferences command = command.lower() # Recognize menu preferences if menu_preferences == "all": if "vegetarian" in command and "non-vegetarian" not in command: menu_preferences = "vegetarian" return "You have chosen the Vegetarian menu. To view menu say menu" elif "non-vegetarian" in command: menu_preferences = "non-vegetarian" return "You have chosen the Non-Vegetarian menu. To view menu say menu" elif "guilt-free" in command: menu_preferences = "guilt-free" return "You have chosen the Guilt-Free menu. To view menu say menu" elif "all" in command: menu_preferences = "all" return "You have chosen the complete menu. To view menu say menu" # Filtered menu based on preference menu = menus.get(menu_preferences, menus["all"]) if "menu" in command: return f"Here is your menu: {', '.join(menu)}. To select an item say item name." elif "price of" in command: item = command.replace("price of", "").strip() closest_match = process.extractOne(item, prices.keys()) if closest_match and closest_match[1] > 80: # Match threshold matched_item = closest_match[0] return f"The price of {matched_item} is ${prices[matched_item]}." return "Sorry, I couldn't find that item in the menu." elif "remove" in command: item = command.replace("remove", "").strip() closest_match = process.extractOne(item, cart) if closest_match and closest_match[1] > 80: matched_item = closest_match[0] cart.remove(matched_item) return f"{matched_item.capitalize()} has been removed from your cart." return "Sorry, that item is not in your cart." elif any(item in command for item in menu): closest_match = process.extractOne(command, menu) if closest_match and closest_match[1] > 80: # Fuzzy match threshold matched_item = closest_match[0] cart.append(matched_item) 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." return "Sorry, I couldn't recognize the item. Could you try again?" elif "final order" in command: if cart: total = sum(prices[item] for item in cart if item in prices) response = f"Your final order is: {', '.join(cart)}. Your total bill is ${total}. Thank you for ordering!" cart.clear() return response return "Your cart is empty. Please add items to your cart first." elif "no" in command or "nothing" in command or "goodbye" in command: cart.clear() menu_preferences = "all" return "Goodbye! Thank you for using AI Dining Assistant." return "Sorry, I couldn't understand that. Please try again." if __name__ == "__main__": app.run(host="0.0.0.0", port=7860)