| 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 |
|
|
| |
| nltk.download('stopwords') |
|
|
| |
| model = load_model("./best_model.keras") |
|
|
| |
| with open("./tokenizer.pkl", "rb") as f: |
| tokenizer = pickle.load(f) |
|
|
| |
| if not hasattr(tokenizer, 'texts_to_sequences'): |
| raise ValueError("Loaded tokenizer is not a valid Keras Tokenizer object.") |
|
|
| |
| MAX_SEQUENCE_LENGTH = 100 |
|
|
| |
| def simple_tokenizer(text): |
| text = text.lower() |
| text = re.sub(r'[^a-zA-Z\s]', '', text) |
| tokens = text.split() |
| return tokens |
|
|
| |
| 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 |
|
|
| |
| 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 |
|
|
| |
| def predict_menu_inclusion(food_name, review_text, cook_time, prep_time, total_time, protein, carbs, fat): |
| |
| processed_review = preprocess_input_review(review_text) |
| |
| |
| review_sequence = tokenizer.texts_to_sequences([processed_review]) |
| padded_review = pad_sequences(review_sequence, maxlen=MAX_SEQUENCE_LENGTH) |
| |
| |
| numerical_features = np.array([[time_to_minutes(cook_time), |
| time_to_minutes(prep_time), |
| time_to_minutes(total_time), |
| protein, carbs, fat]]) |
| |
| |
| scaler = StandardScaler() |
| numerical_features = scaler.fit_transform(numerical_features) |
| |
| |
| predicted_rating = model.predict([padded_review, numerical_features]).flatten()[0] |
| |
| |
| include_on_menu = predicted_rating > 4 |
| |
| return { |
| "FoodName": food_name, |
| "PredictedRating": round(predicted_rating, 2), |
| "IncludeOnMenu": include_on_menu |
| } |
|
|
| |
| 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) |
|
|