galcomis commited on
Commit
fef3901
·
verified ·
1 Parent(s): 351d269

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +124 -0
app.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import numpy as np
4
+ import os
5
+ from sentence_transformers import SentenceTransformer
6
+ from sklearn.metrics.pairwise import cosine_similarity
7
+
8
+ # --- Configuration & Model ---
9
+ model = SentenceTransformer('all-MiniLM-L6-v2')
10
+ MAIN_DATASET = 'bitewise_clean_dataset.csv'
11
+ DISH_EMBEDDINGS = 'BiteWise_Dish_Embeddings.npy'
12
+ USER_REVIEWS_DB = 'BiteWise_User_Reviews.csv'
13
+
14
+ df_main = pd.read_csv(MAIN_DATASET)
15
+ dish_embeddings = np.load(DISH_EMBEDDINGS)
16
+
17
+ # --- Custom CSS for Styling ---
18
+ custom_css = """
19
+ #main-container {background-color: #fcfcfc;}
20
+ .gradio-container {max-width: 900px !important; margin: auto;}
21
+ .primary-btn {
22
+ background: linear-gradient(90deg, #ff5f6d 0%, #ffc371 100%) !important;
23
+ border: none !important;
24
+ color: white !important;
25
+ font-weight: bold !important;
26
+ border-radius: 50px !important;
27
+ }
28
+ .primary-btn:hover {transform: scale(1.02); transition: 0.3s;}
29
+ .dish-card {
30
+ background: white;
31
+ border-radius: 15px;
32
+ padding: 20px;
33
+ margin-bottom: 15px;
34
+ box-shadow: 0 4px 15px rgba(0,0,0,0.05);
35
+ border-left: 6px solid #ff5f6d;
36
+ }
37
+ .status-msg {
38
+ padding: 10px;
39
+ border-radius: 8px;
40
+ font-weight: 500;
41
+ }
42
+ """
43
+
44
+ def execute_search(query):
45
+ current_df = pd.concat([df_main, pd.read_csv(USER_REVIEWS_DB)] if os.path.exists(USER_REVIEWS_DB) else [df_main], ignore_index=True)
46
+ query_vec = model.encode([query])
47
+ sim_scores = cosine_similarity(query_vec, dish_embeddings).flatten()
48
+ current_df['score'] = sim_scores
49
+ results = current_df.sort_values(by='score', ascending=False).head(3)
50
+
51
+ html = "<div style='margin-top: 20px;'>"
52
+ for _, row in results.iterrows():
53
+ confidence = int(min(99, 85 + (row['score'] * 15)))
54
+ html += f"""
55
+ <div class="dish-card">
56
+ <div style="display: flex; justify-content: space-between; align-items: center;">
57
+ <h3 style="margin: 0; color: #2D3436;">🍴 {row['dish_name']}</h3>
58
+ <span style="background: #FFF0F0; color: #FF5F6D; padding: 4px 12px; border-radius: 20px; font-size: 0.8em; font-weight: bold;">{confidence}% Match</span>
59
+ </div>
60
+ <p style="margin: 5px 0; color: #636E72;">📍 <b>{row['restaurant_name']}</b></p>
61
+ <p style="margin: 10px 0; font-style: italic; color: #2D3436; line-height: 1.4;">"{row['taste_review']}"</p>
62
+ <div style="display: flex; gap: 10px; font-size: 0.85em; color: #B2BEC3;">
63
+ <span>⭐ {row['rating']}</span> | <span>📷 {row.get('visual_description', 'No photo desc')}</span>
64
+ </div>
65
+ </div>
66
+ """
67
+ html += "</div>"
68
+ return html
69
+
70
+ def save_and_reset(dish, rest, rate, taste, visual, user):
71
+ if not dish or not rest:
72
+ return "⚠️ Please fill in the dish and restaurant name.", dish, rest, rate, taste, visual, user
73
+
74
+ new_entry = {'dish_name': dish, 'restaurant_name': rest, 'rating': rate, 'taste_review': taste, 'visual_description': visual, 'user_name': user}
75
+ new_df = pd.DataFrame([new_entry])
76
+
77
+ if os.path.exists(USER_REVIEWS_DB):
78
+ existing = pd.read_csv(USER_REVIEWS_DB)
79
+ pd.concat([existing, new_df], ignore_index=True).to_csv(USER_REVIEWS_DB, index=False)
80
+ else:
81
+ new_df.to_csv(USER_REVIEWS_DB, index=False)
82
+
83
+ global dish_embeddings
84
+ dish_embeddings = np.vstack([dish_embeddings, model.encode([f"{dish} {taste}"])])
85
+
86
+ return f"✨ <b>Amazing!</b> {user}, '{dish}' has been added to our flavor map.", "", "", 4.5, "", "", ""
87
+
88
+ # --- UI Layout ---
89
+ with gr.Blocks(css=custom_css, theme=gr.themes.Default(primary_hue="orange", secondary_hue="gray")) as demo:
90
+ with gr.Column(elem_id="main-container"):
91
+ gr.HTML("""
92
+ <div style="text-align: center; padding: 20px 0;">
93
+ <h1 style="font-size: 2.5em; color: #2D3436; margin-bottom: 0;">BiteWise <span style="color: #ff5f6d;">AI</span></h1>
94
+ <p style="color: #636E72; font-size: 1.1em;">The Intelligence Behind Your Next Craving</p>
95
+ </div>
96
+ """)
97
+
98
+ with gr.Tabs():
99
+ with gr.Tab("🔍 DISCOVER"):
100
+ query_input = gr.Textbox(label="What are you craving?", placeholder="e.g., A rich, creamy pasta with lots of cheese", lines=1)
101
+ search_btn = gr.Button("Find My Flavor", variant="primary", elem_classes="primary-btn")
102
+ gr.Examples(examples=["Crispy chicken burger with spicy aioli", "Fresh summer salad with mango", "Deep dish pizza with pepperoni"], inputs=query_input)
103
+ output_area = gr.HTML()
104
+ search_btn.click(execute_search, query_input, output_area)
105
+
106
+ with gr.Tab("✨ CONTRIBUTE"):
107
+ gr.Markdown("### Share your latest culinary find")
108
+ with gr.Row():
109
+ user_in = gr.Textbox(label="Your Name", placeholder="Chef...")
110
+ dish_in = gr.Textbox(label="Dish Name", placeholder="The star of the show")
111
+ rest_in = gr.Textbox(label="Restaurant", placeholder="Where was it?")
112
+ with gr.Row():
113
+ rate_in = gr.Slider(1, 5, value=4.5, step=0.1, label="Rating")
114
+ taste_in = gr.Textbox(label="Taste Notes", placeholder="Describe the flavors...")
115
+ visual_in = gr.Textbox(label="Visual Plating", placeholder="How did it look?")
116
+
117
+ save_btn = gr.Button("Sync Review", variant="primary", elem_classes="primary-btn")
118
+ status_out = gr.HTML(elem_classes="status-msg")
119
+
120
+ save_btn.click(save_and_reset,
121
+ inputs=[dish_in, rest_in, rate_in, taste_in, visual_in, user_in],
122
+ outputs=[status_out, dish_in, rest_in, rate_in, taste_in, visual_in, user_in])
123
+
124
+ demo.launch()