galcomis commited on
Commit
a82a092
·
verified ·
1 Parent(s): 7dbeb05

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +123 -91
app.py CHANGED
@@ -5,127 +5,159 @@ import os
5
  from sentence_transformers import SentenceTransformer
6
  from sklearn.metrics.pairwise import cosine_similarity
7
 
8
- # --- Loading Assets (Exact logic from Colab) ---
 
9
  model = SentenceTransformer('all-MiniLM-L6-v2')
10
 
11
- # Database and Embeddings
12
- main_df = pd.read_csv('bitewise_clean_dataset.csv')
13
- dish_embeddings = np.load('BiteWise_Dish_Embeddings.npy')
 
 
14
 
15
- # User Reviews Database
16
- USER_REVIEWS_FILE = "BiteWise_User_Reviews.csv"
 
17
 
18
- # --- Styling (Light Brown / Beige) ---
19
  custom_css = """
20
- .gradio-container { background-color: #F5F5DC; }
21
- .action-btn {
22
- background-color: #8B4513 !important;
23
- color: white !important;
24
- border-radius: 8px !important;
25
- }
26
- .main-header {
27
- color: #5D4037;
28
- text-align: center;
29
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
 
30
  }
 
 
31
  """
32
 
33
- # --- Step 1: User Profile Context ---
34
- def create_user_profile(user_name, user_preferences):
35
- if not user_name:
36
- return "Please enter your name."
37
- # exact phrasing from Part 4
38
- return f"User Profile Created: Welcome {user_name}! We'll tailor your experience based on your preferences: '{user_preferences}'"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
- # --- Step 2: Search Engine (The Engine) ---
41
- def search_engine(query):
42
  try:
43
- # Step 2 logic: Encode and compare
44
  query_embedding = model.encode([query])
45
- similarities = cosine_similarity(query_embedding, dish_embeddings).flatten()
46
 
47
- main_df['match_score'] = similarities
48
- top_results = main_df.sort_values(by='match_score', ascending=False).head(3)
 
 
49
 
50
- # Displaying the results in the exact format we built
51
- results_text = "### Top 3 Recommended Dishes:\n"
52
- for _, row in top_results.iterrows():
53
- results_text += f"**Dish Name:** {row['dish_name']}\n"
54
- results_text += f"**Restaurant:** {row['restaurant_name']}\n"
55
- results_text += f"**Rating:** {row['rating']} ⭐\n"
56
- results_text += f"**Taste Review:** {row['taste_review']}\n\n"
57
- results_text += "---\n\n"
58
- return results_text
59
  except Exception as e:
60
  return f"Error: {e}"
61
 
62
- # --- Step 3: Upload Review ---
63
- def upload_review(dish_name, restaurant_name, rating, taste_review, visual_description, user_name):
64
- if not dish_name or not restaurant_name:
65
- return "⚠️ Dish and Restaurant names are required.", dish_name, restaurant_name, rating, taste_review, visual_description, user_name
66
-
67
- new_review = {
68
- 'dish_name': dish_name,
69
- 'restaurant_name': restaurant_name,
70
- 'rating': rating,
71
- 'taste_review': taste_review,
72
- 'visual_description': visual_description,
73
- 'user_name': user_name
74
- }
75
 
76
- new_df = pd.DataFrame([new_review])
 
 
 
77
 
78
- if os.path.exists(USER_REVIEWS_FILE):
79
- pd.concat([pd.read_csv(USER_REVIEWS_FILE), new_df], ignore_index=True).to_csv(USER_REVIEWS_FILE, index=False)
 
80
  else:
81
- new_df.to_csv(USER_REVIEWS_FILE, index=False)
 
 
82
 
83
- # Success message and Resetting fields
84
- success_msg = f"Review for '{dish_name}' by {user_name} uploaded successfully!"
85
- return success_msg, "", "", 4.5, "", "", ""
86
 
87
- # --- UI Layout (Exact sequence from Part 4) ---
88
- with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
89
- gr.HTML("<h1 class='main-header'>BiteWise AI Engine</h1>")
90
 
91
  with gr.Tabs():
92
- # PART 4 - STEP 1
93
- with gr.Tab("1. Create User Profile"):
94
- gr.Markdown("### User Profile Context")
 
 
 
95
  with gr.Row():
96
- u_name = gr.Textbox(label="User Name", placeholder="Enter your name")
97
- u_pref = gr.Textbox(label="User Preferences", placeholder="e.g., Spicy, Vegan, Sweet")
98
- btn_profile = gr.Button("Create Profile", elem_classes="action-btn")
99
- out_profile = gr.Markdown()
100
- btn_profile.click(create_user_profile, inputs=[u_name, u_pref], outputs=out_profile)
 
 
 
 
 
 
 
 
 
 
101
 
102
- # PART 4 - STEP 2
103
- with gr.Tab("2. Search Engine"):
104
- gr.Markdown("### Dish Search Engine")
105
- s_query = gr.Textbox(label="Enter your craving", placeholder="e.g., I want a juicy burger")
106
- btn_search = gr.Button("Find My Dish", variant="primary", elem_classes="action-btn")
107
- out_search = gr.Markdown()
108
- btn_search.click(search_engine, inputs=s_query, outputs=out_search)
109
 
110
- # PART 4 - STEP 3
111
  with gr.Tab("3. Upload Review"):
112
- gr.Markdown("### Contribute Your Review")
113
  with gr.Row():
114
- in_user = gr.Textbox(label="Reviewer Name")
115
- in_dish = gr.Textbox(label="Dish Name")
116
- in_rest = gr.Textbox(label="Restaurant Name")
117
  with gr.Row():
118
  in_rate = gr.Slider(1, 5, value=4.5, step=0.1, label="Rating")
119
- in_taste = gr.Textbox(label="Taste Review")
120
- in_visual = gr.Textbox(label="Visual Description")
121
-
122
- btn_upload = gr.Button("Upload Review", elem_classes="action-btn")
123
- out_status = gr.Markdown()
124
 
125
- btn_upload.click(
126
- upload_review,
127
- inputs=[in_dish, in_rest, in_rate, in_taste, in_visual, in_user],
128
- outputs=[out_status, in_dish, in_rest, in_rate, in_taste, in_visual, in_user]
129
- )
130
 
131
  demo.launch()
 
5
  from sentence_transformers import SentenceTransformer
6
  from sklearn.metrics.pairwise import cosine_similarity
7
 
8
+ # --- 1. SETTINGS & MODEL ---
9
+ # Using the exact SBERT model from our pipeline
10
  model = SentenceTransformer('all-MiniLM-L6-v2')
11
 
12
+ # File configurations
13
+ MAIN_DB = 'bitewise_clean_dataset.csv'
14
+ DISH_VECTORS = 'BiteWise_Dish_Embeddings.npy'
15
+ USER_DB_PATH = 'BiteWise_User_Database.csv'
16
+ REVIEWS_DB_PATH = 'BiteWise_User_Reviews.csv'
17
 
18
+ # Pre-loading static assets
19
+ df_main = pd.read_csv(MAIN_DB)
20
+ dish_embeddings = np.load(DISH_VECTORS)
21
 
22
+ # --- 2. THE STYLING (Bespoke Light Brown/Beige Theme) ---
23
  custom_css = """
24
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600&display=swap');
25
+ * { font-family: 'Inter', sans-serif !important; }
26
+ .gradio-container { background-color: #F8F5F2 !important; }
27
+ .main-header { color: #3D2B1F; text-align: center; font-weight: 600; font-size: 2.5em; margin-bottom: 5px; }
28
+ .action-btn {
29
+ background: #5D4037 !important;
30
+ color: white !important;
31
+ border: none !important;
32
+ border-radius: 8px !important;
33
+ font-weight: 600 !important;
34
+ padding: 10px 20px !important;
35
  }
36
+ .action-btn:hover { background: #3D2B1F !important; }
37
+ input, textarea, .dropdown, .slider { border-radius: 8px !important; border: 1px solid #D7CCC8 !important; }
38
  """
39
 
40
+ # --- 3. CORE LOGIC (Part 4 Pipeline) ---
41
+
42
+ def create_user_persona(name, age, cuisine, spice, adventure, diet, fav_dish, drink, frequency):
43
+ """Step 1: Building the user database record."""
44
+ if not name:
45
+ return "⚠️ Error: Full Name is required."
46
+
47
+ user_data = {
48
+ 'full_name': name, 'age_group': age, 'fav_cuisine': cuisine,
49
+ 'spice_level': spice, 'adventure_level': adventure, 'dietary_restrictions': diet,
50
+ 'favorite_dish': fav_dish, 'preferred_drink': drink, 'dining_frequency': frequency
51
+ }
52
+
53
+ # Save to persistent user storage
54
+ u_df = pd.DataFrame([user_data])
55
+ if os.path.exists(USER_DB_PATH):
56
+ pd.concat([pd.read_csv(USER_DB_PATH), u_df], ignore_index=True).to_csv(USER_DB_PATH, index=False)
57
+ else:
58
+ u_df.to_csv(USER_DB_PATH, index=False)
59
+
60
+ # Return exactly as phrased in Colab
61
+ return f"""### 👤 Profile Created Successfully!
62
+ **Welcome, {name}!**
63
+
64
+ **Your Culinary Context:**
65
+ * **Preferences:** {cuisine} | **Spice:** {spice}/5 | **Adventure:** {adventure}/5
66
+ * **Details:** {diet} | **Favorite:** {fav_dish} | **Vibe:** {drink}
67
+
68
+ We have updated our records. You can now use the search engine to find dishes tailored to your taste."""
69
 
70
+ def run_search_engine(query):
71
+ """Step 2: Semantic search logic."""
72
  try:
 
73
  query_embedding = model.encode([query])
74
+ sims = cosine_similarity(query_embedding, dish_embeddings).flatten()
75
 
76
+ # Temporary view for results
77
+ search_df = df_main.copy()
78
+ search_df['match_score'] = sims
79
+ top_3 = search_df.sort_values(by='match_score', ascending=False).head(3)
80
 
81
+ output = "### 🍴 Top Matches Found:\n\n"
82
+ for _, row in top_3.iterrows():
83
+ output += f"**{row['dish_name']}** at **{row['restaurant_name']}**\n"
84
+ output += f"Rating: {row['rating']} ⭐ | Review: {row['taste_review']}\n\n"
85
+ output += "---\n"
86
+ return output
 
 
 
87
  except Exception as e:
88
  return f"Error: {e}"
89
 
90
+ def submit_review(dish, rest, rate, taste, visual, user):
91
+ """Step 3: Contributing a new review."""
92
+ if not dish or not rest:
93
+ return "⚠️ Dish and Restaurant names are required.", dish, rest, rate, taste, visual, user
 
 
 
 
 
 
 
 
 
94
 
95
+ review_data = {
96
+ 'dish_name': dish, 'restaurant_name': rest, 'rating': rate,
97
+ 'taste_review': taste, 'visual_description': visual, 'user_name': user
98
+ }
99
 
100
+ r_df = pd.DataFrame([review_data])
101
+ if os.path.exists(REVIEWS_DB_PATH):
102
+ pd.concat([pd.read_csv(REVIEWS_DB_PATH), r_df], ignore_index=True).to_csv(REVIEWS_DB_PATH, index=False)
103
  else:
104
+ r_df.to_csv(REVIEWS_DB_PATH, index=False)
105
+
106
+ return f"✨ Thank you {user}! Your review for '{dish}' has been synced.", "", "", 4.5, "", "", ""
107
 
108
+ # --- 4. USER INTERFACE (Gradio) ---
 
 
109
 
110
+ with gr.Blocks(css=custom_css) as demo:
111
+ gr.HTML("<h1 class='main-header'>BiteWise</h1>")
 
112
 
113
  with gr.Tabs():
114
+ # STEP 1: PERSONA
115
+ with gr.Tab("1. User Profile Setup"):
116
+ gr.Markdown("### 📋 Create your culinary DNA")
117
+ with gr.Row():
118
+ u_name = gr.Textbox(label="Full Name")
119
+ u_age = gr.Dropdown(choices=["Under 18", "18-25", "26-40", "41-60", "60+"], label="Age Group")
120
  with gr.Row():
121
+ u_cuisine = gr.Textbox(label="Favorite Cuisine Type", placeholder="e.g., Asian, Italian")
122
+ u_diet = gr.Textbox(label="Dietary Restrictions", placeholder="None, Vegan, etc.")
123
+ with gr.Row():
124
+ u_dish = gr.Textbox(label="One dish you love", placeholder="e.g., Truffle Pasta")
125
+ u_drink = gr.Textbox(label="Preferred Drink", placeholder="e.g., Matcha, Wine")
126
+ with gr.Row():
127
+ u_freq = gr.Dropdown(choices=["Daily", "Weekly", "Rarely"], label="Dining Frequency")
128
+ u_spice = gr.Slider(1, 5, step=1, label="Spice Tolerance")
129
+ u_adv = gr.Slider(1, 5, step=1, label="Adventurousness")
130
+
131
+ btn_p = gr.Button("Create Profile", elem_classes="action-btn")
132
+ out_p = gr.Markdown()
133
+ btn_p.click(create_user_persona,
134
+ inputs=[u_name, u_age, u_cuisine, u_spice, u_adv, u_diet, u_dish, u_drink, u_freq],
135
+ outputs=out_p)
136
 
137
+ # STEP 2: SEARCH
138
+ with gr.Tab("2. Dish Search"):
139
+ gr.Markdown("### 🔍 Find your next flavor")
140
+ s_q = gr.Textbox(label="Describe your craving", placeholder="e.g., Something spicy and crunchy")
141
+ btn_s = gr.Button("Search Engine", elem_classes="action-btn")
142
+ out_s = gr.Markdown()
143
+ btn_s.click(run_search_engine, inputs=s_q, outputs=out_s)
144
 
145
+ # STEP 3: CONTRIBUTION
146
  with gr.Tab("3. Upload Review"):
147
+ gr.Markdown("### ✍️ Share your experience")
148
  with gr.Row():
149
+ in_u = gr.Textbox(label="Reviewer Name")
150
+ in_d = gr.Textbox(label="Dish Name")
151
+ in_r = gr.Textbox(label="Restaurant")
152
  with gr.Row():
153
  in_rate = gr.Slider(1, 5, value=4.5, step=0.1, label="Rating")
154
+ in_t = gr.Textbox(label="Taste Notes")
155
+ in_v = gr.Textbox(label="Visual Description")
 
 
 
156
 
157
+ btn_r = gr.Button("Upload Review", elem_classes="action-btn")
158
+ out_r = gr.Markdown()
159
+ btn_r.click(submit_review,
160
+ inputs=[in_d, in_r, in_rate, in_t, in_v, in_u],
161
+ outputs=[out_r, in_d, in_r, in_rate, in_t, in_v, in_u])
162
 
163
  demo.launch()