vashu2425's picture
Update app.py
cbe2c52 verified
raw
history blame
5.56 kB
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
# 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 > 4 # 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.markdown(
"""
<style>
.main {
background-color: #f5f5f5;
font-family: Arial, sans-serif;
}
h1 {
color: #3c3c7b;
}
.sidebar .sidebar-content {
background-color: #eef2f3;
}
.stButton>button {
background-color: #3c3c7b;
color: white;
border-radius: 5px;
font-size: 16px;
}
.stButton>button:hover {
background-color: #2c2c5a;
}
.prediction-box {
background-color: #eaf6f6;
padding: 20px;
border-radius: 10px;
box-shadow: 2px 2px 10px #ccc;
}
.success {
color: green;
font-weight: bold;
}
.error {
color: red;
font-weight: bold;
}
</style>
""",
unsafe_allow_html=True,
)
st.title("๐ŸŒŸ Recipe Rating & Menu Optimization")
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)
st.markdown("<div class='prediction-box'>", unsafe_allow_html=True)
st.subheader("Prediction Results")
st.write(f"**๐Ÿด Food Name:** {result['FoodName']}")
st.write(f"**โญ Predicted Rating:** {result['PredictedRating']}")
st.write(
f"**๐Ÿฝ๏ธ Include on Menu:** "
f"<span class='{'success' if result['IncludeOnMenu'] else 'error'}'>"
f"{'Yes' if result['IncludeOnMenu'] else 'No'}</span>",
unsafe_allow_html=True,
)
st.markdown("</div>", unsafe_allow_html=True)