vashu2425's picture
Update app.py
456e90c verified
import pickle
import streamlit as st
import numpy as np
import pandas as pd
import re
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.sequence import pad_sequences
from nltk.corpus import stopwords
from sklearn.preprocessing import StandardScaler
import nltk
import time
# Download required NLTK data (for stopwords only)
nltk.download('stopwords')
# Load the trained model
model = load_model("./best_model.keras")
# Load the tokenizer
with open("./tokenizer.pkl", "rb") as f:
tokenizer = pickle.load(f)
# Ensure the tokenizer is valid
if not hasattr(tokenizer, 'texts_to_sequences'):
raise ValueError("Loaded tokenizer is not a valid Keras Tokenizer object.")
# Define constants
MAX_SEQUENCE_LENGTH = 100
# Simple tokenizer function
def simple_tokenizer(text):
text = text.lower()
text = re.sub(r'[^a-zA-Z\s]', '', text)
tokens = text.split() # Split by whitespace
return tokens
# Preprocessing function for input review
def preprocess_input_review(review_text):
tokens = simple_tokenizer(review_text)
stop_words = set(stopwords.words('english'))
tokens = [word for word in tokens if word not in stop_words]
processed_review = ' '.join(tokens)
return processed_review
# Convert simplified time strings (e.g., 2H30M or 15M) to minutes
def time_to_minutes(time_str):
if not time_str or pd.isna(time_str):
return 0
hours, minutes = 0, 0
if 'H' in time_str:
parts = time_str.split('H')
hours = int(parts[0]) if parts[0].isdigit() else 0
time_str = parts[1] if len(parts) > 1 else ''
if 'M' in time_str and time_str.split('M')[0].isdigit():
minutes = int(time_str.split('M')[0])
return hours * 60 + minutes
# Prediction function
def predict_menu_inclusion(food_name, review_text, cook_time, prep_time, total_time, protein, carbs, fat):
# Preprocess the review
processed_review = preprocess_input_review(review_text)
# Tokenize and pad the review
review_sequence = tokenizer.texts_to_sequences([processed_review])
padded_review = pad_sequences(review_sequence, maxlen=MAX_SEQUENCE_LENGTH)
# Prepare numerical features
numerical_features = np.array([[time_to_minutes(cook_time),
time_to_minutes(prep_time),
time_to_minutes(total_time),
protein, carbs, fat]])
# Normalize numerical features
scaler = StandardScaler()
numerical_features = scaler.fit_transform(numerical_features)
# Predict the rating
predicted_rating = model.predict([padded_review, numerical_features]).flatten()[0]
# Decide whether to include the item on the menu
include_on_menu = predicted_rating > 3.5 # Threshold for inclusion
return {
"FoodName": food_name,
"PredictedRating": round(predicted_rating, 2),
"IncludeOnMenu": include_on_menu
}
# Streamlit app with enhanced UI
st.set_page_config(page_title="Recipe Rating & Menu Optimization", layout="wide")
st.title("๐Ÿฒ๐ŸŒŸ Recipe Rating & Menu Optimization ๐Ÿš€")
st.markdown(
"""
Welcome to the **Recipe Rating & Menu Optimization** app! ๐ŸŽ‰
This tool uses cutting-edge **AI and machine learning** ๐Ÿง  to help chefs, restaurateurs, and food enthusiasts ๐Ÿฝ๏ธ predict recipe ratings and decide if a dish deserves a place on the menu. ๐Ÿ†
Let's get started and create culinary magic! โœจ
"""
)
st.sidebar.header("๐Ÿ“‹ Enter Recipe Details")
food_name = st.sidebar.text_input("๐Ÿด Food Name", value="Paneer Butter Masala")
review_text = st.sidebar.text_area("๐Ÿ“ Review Text", value="This dish is delicious, rich in flavor, and a favorite among customers!")
cook_time = st.sidebar.text_input("โณ Cooking Time (e.g., 15M or 2H30M)", value="30M")
prep_time = st.sidebar.text_input("๐Ÿ•’ Preparation Time (e.g., 15M or 1H15M)", value="15M")
total_time = st.sidebar.text_input("๐Ÿ“… Total Time (e.g., 45M or 1H45M)", value="45M")
protein = st.sidebar.number_input("๐Ÿ’ช Protein (grams)", min_value=0.0, step=1.0, value=20.0)
carbs = st.sidebar.number_input("๐Ÿž Carbohydrates (grams)", min_value=0.0, step=1.0, value=10.0)
fat = st.sidebar.number_input("๐ŸŸ Fat (grams)", min_value=0.0, step=1.0, value=15.0)
if st.sidebar.button("๐Ÿ”ฎ Predict"):
result = predict_menu_inclusion(food_name, review_text, cook_time, prep_time, total_time, protein, carbs, fat)
predicted_rating = result["PredictedRating"]
include_on_menu = result["IncludeOnMenu"]
# Custom progress bar with color based on inclusion
bar_color = "green" if include_on_menu else "red"
progress_percentage = int(predicted_rating * 20) # Convert rating (0-5) to percentage (0-100)
# Display animated progress bar
st.markdown(
f"""
<div style="
width: 100%;
background-color: #ddd;
border-radius: 10px;
margin-bottom: 15px;
">
<div style="
width: {progress_percentage}%;
height: 25px;
background-color: {bar_color};
border-radius: 10px;
text-align: center;
color: white;
line-height: 25px;
font-weight: bold;
animation: growBar 2s;
">
{progress_percentage}%
</div>
</div>
<style>
@keyframes growBar {{
from {{ width: 0%; }}
to {{ width: {progress_percentage}%; }}
}}
</style>
""",
unsafe_allow_html=True,
)
# Display prediction results
st.subheader("Prediction Results")
st.markdown(f"**๐Ÿด Food Name:** {result['FoodName']}")
st.markdown(f"**โญ Predicted Rating:** {result['PredictedRating']:.1f}")
st.markdown(
f"**๐Ÿฝ๏ธ Include on Menu:** "
f"<span style='color: {'green' if include_on_menu else 'red'}; font-weight: bold;'>"
f"{'Yes' if include_on_menu else 'No'}</span>",
unsafe_allow_html=True,
)