Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -12,11 +12,11 @@ with open(r'vect_values.pickle', 'rb') as file:
|
|
| 12 |
|
| 13 |
df = pd.read_excel('perfume_database_cleaned.xlsx')
|
| 14 |
|
| 15 |
-
#
|
| 16 |
-
#
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
|
| 21 |
# Create brand and perfume options for the dropdowns
|
| 22 |
brand_options = sorted(df['brand'].unique())
|
|
@@ -28,7 +28,7 @@ perfume_options = sorted(df['perfume'].unique())
|
|
| 28 |
|
| 29 |
def perfume_change(brand):
|
| 30 |
"""
|
| 31 |
-
When user selects a brand, update the perfume dropdown
|
| 32 |
with only the perfumes from that brand.
|
| 33 |
"""
|
| 34 |
filtered_perfumes = df.loc[df['brand'] == brand, 'perfume'].unique()
|
|
@@ -36,48 +36,33 @@ def perfume_change(brand):
|
|
| 36 |
|
| 37 |
def filter_by_perfume(selected_brand, selected_perfume, top_n, note_search):
|
| 38 |
"""
|
| 39 |
-
1) Find the index of the chosen perfume in the
|
| 40 |
-
2) Retrieve the top_n most similar perfumes (based on vect_index and vect_values)
|
| 41 |
-
3) If note_search is
|
| 42 |
-
4) Return a subset of columns
|
| 43 |
"""
|
| 44 |
-
#
|
| 45 |
-
# 1) Locate chosen perfume in the DF
|
| 46 |
-
# ----------------------------------------------------------------
|
| 47 |
-
# We assume there's exactly one row that matches brand+perfume.
|
| 48 |
-
# If there's a possibility of duplicates, handle that carefully.
|
| 49 |
row_idx = df.query("brand == @selected_brand and perfume == @selected_perfume").index[0]
|
| 50 |
|
| 51 |
-
#
|
| 52 |
-
# 2) Retrieve top_n from vect_index, vect_values
|
| 53 |
-
# ----------------------------------------------------------------
|
| 54 |
recommended_indices = vect_index[row_idx][:top_n] # e.g. top_n indices
|
| 55 |
-
recommended_sims = vect_values[row_idx][:top_n]
|
| 56 |
|
| 57 |
-
# Build a
|
| 58 |
df_recs = df.iloc[recommended_indices].copy().reset_index(drop=True)
|
| 59 |
df_recs['similarity'] = recommended_sims
|
| 60 |
df_recs['similarity'] = df_recs['similarity'].map("{:.2%}".format)
|
| 61 |
|
| 62 |
-
# Clean up notes
|
| 63 |
df_recs['notes'] = df_recs['notes'].str.split(',').apply(lambda x: sorted(x))
|
| 64 |
df_recs['notes'] = df_recs['notes'].apply(lambda x: ', '.join([n.strip() for n in x]))
|
| 65 |
|
| 66 |
-
#
|
| 67 |
-
# 3) Optional note search (if user typed something in)
|
| 68 |
-
# ----------------------------------------------------------------
|
| 69 |
if note_search:
|
| 70 |
-
# For example, filter for rows that contain that note in the 'notes' column
|
| 71 |
-
# Convert both sides to lowercase for a case-insensitive match
|
| 72 |
note_search_lower = note_search.lower()
|
| 73 |
df_recs = df_recs[df_recs['notes'].str.lower().str.contains(note_search_lower)]
|
| 74 |
|
| 75 |
-
#
|
| 76 |
-
# 4) Return final DataFrame
|
| 77 |
-
# ----------------------------------------------------------------
|
| 78 |
-
# You can include any columns you want.
|
| 79 |
-
# Example columns: brand, perfume, similarity, notes
|
| 80 |
-
# If you have images, you could include them in a separate Gallery component, etc.
|
| 81 |
return df_recs[['brand', 'perfume', 'similarity', 'notes']]
|
| 82 |
|
| 83 |
# ----------------------------------------------------------------
|
|
@@ -121,7 +106,7 @@ button:hover {
|
|
| 121 |
font-size: 0.9rem !important;
|
| 122 |
}
|
| 123 |
|
| 124 |
-
/* Centered text for the top
|
| 125 |
#top-header {
|
| 126 |
text-align: center;
|
| 127 |
margin-bottom: 20px;
|
|
@@ -132,7 +117,7 @@ button:hover {
|
|
| 132 |
# BUILD THE GRADIO INTERFACE
|
| 133 |
# ----------------------------------------------------------------
|
| 134 |
with gr.Blocks(css=custom_css) as demo:
|
| 135 |
-
# Top header
|
| 136 |
gr.HTML("""
|
| 137 |
<div id="top-header">
|
| 138 |
<h1>🌸 Perfume Recommendation App 🌸</h1>
|
|
@@ -141,17 +126,17 @@ with gr.Blocks(css=custom_css) as demo:
|
|
| 141 |
""")
|
| 142 |
|
| 143 |
with gr.Row():
|
| 144 |
-
# Left column:
|
| 145 |
with gr.Column():
|
| 146 |
brand_dropdown = gr.Dropdown(
|
| 147 |
choices=brand_options,
|
| 148 |
label="Select Brand",
|
| 149 |
-
value=brand_options[0]
|
| 150 |
)
|
| 151 |
perfume_dropdown = gr.Dropdown(
|
| 152 |
choices=perfume_options,
|
| 153 |
label="Select Perfume",
|
| 154 |
-
value=perfume_options[0]
|
| 155 |
)
|
| 156 |
brand_dropdown.change(
|
| 157 |
fn=perfume_change,
|
|
@@ -159,12 +144,12 @@ with gr.Blocks(css=custom_css) as demo:
|
|
| 159 |
outputs=[perfume_dropdown]
|
| 160 |
)
|
| 161 |
|
| 162 |
-
#
|
| 163 |
note_search = gr.Textbox(
|
| 164 |
label="Optional: Search for a specific note (e.g., 'rose', 'vanilla')"
|
| 165 |
)
|
| 166 |
|
| 167 |
-
# Slider
|
| 168 |
top_n_slider = gr.Slider(
|
| 169 |
minimum=1,
|
| 170 |
maximum=10,
|
|
@@ -173,19 +158,18 @@ with gr.Blocks(css=custom_css) as demo:
|
|
| 173 |
label="Number of recommendations to show"
|
| 174 |
)
|
| 175 |
|
| 176 |
-
# Button to trigger the
|
| 177 |
btn_search = gr.Button("Recommend")
|
| 178 |
|
| 179 |
-
# Right column: results
|
| 180 |
with gr.Column():
|
| 181 |
-
# The results DataFrame
|
| 182 |
output_df = gr.Dataframe(
|
| 183 |
headers=["Brand", "Perfume", "Similarity", "Notes"],
|
| 184 |
label="Recommended Perfumes",
|
| 185 |
wrap=True
|
| 186 |
)
|
| 187 |
|
| 188 |
-
#
|
| 189 |
btn_search.click(
|
| 190 |
fn=filter_by_perfume,
|
| 191 |
inputs=[brand_dropdown, perfume_dropdown, top_n_slider, note_search],
|
|
|
|
| 12 |
|
| 13 |
df = pd.read_excel('perfume_database_cleaned.xlsx')
|
| 14 |
|
| 15 |
+
# Clean the DataFrame:
|
| 16 |
+
# Drop rows where 'perfume' is missing and convert both 'perfume' and 'brand' to strings
|
| 17 |
+
df.dropna(subset=['perfume'], inplace=True)
|
| 18 |
+
df['perfume'] = df['perfume'].astype(str)
|
| 19 |
+
df['brand'] = df['brand'].astype(str)
|
| 20 |
|
| 21 |
# Create brand and perfume options for the dropdowns
|
| 22 |
brand_options = sorted(df['brand'].unique())
|
|
|
|
| 28 |
|
| 29 |
def perfume_change(brand):
|
| 30 |
"""
|
| 31 |
+
When the user selects a brand, update the perfume dropdown
|
| 32 |
with only the perfumes from that brand.
|
| 33 |
"""
|
| 34 |
filtered_perfumes = df.loc[df['brand'] == brand, 'perfume'].unique()
|
|
|
|
| 36 |
|
| 37 |
def filter_by_perfume(selected_brand, selected_perfume, top_n, note_search):
|
| 38 |
"""
|
| 39 |
+
1) Find the index of the chosen perfume in the DataFrame.
|
| 40 |
+
2) Retrieve the top_n most similar perfumes (based on vect_index and vect_values).
|
| 41 |
+
3) If note_search is provided, filter recommendations by that note.
|
| 42 |
+
4) Return a subset of columns plus similarity.
|
| 43 |
"""
|
| 44 |
+
# Locate the chosen perfume in the DataFrame
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
row_idx = df.query("brand == @selected_brand and perfume == @selected_perfume").index[0]
|
| 46 |
|
| 47 |
+
# Retrieve top_n indices and similarity values
|
|
|
|
|
|
|
| 48 |
recommended_indices = vect_index[row_idx][:top_n] # e.g. top_n indices
|
| 49 |
+
recommended_sims = vect_values[row_idx][:top_n] # e.g. top_n similarity scores
|
| 50 |
|
| 51 |
+
# Build a DataFrame of the recommended items
|
| 52 |
df_recs = df.iloc[recommended_indices].copy().reset_index(drop=True)
|
| 53 |
df_recs['similarity'] = recommended_sims
|
| 54 |
df_recs['similarity'] = df_recs['similarity'].map("{:.2%}".format)
|
| 55 |
|
| 56 |
+
# Clean up the notes column: split, sort, and join
|
| 57 |
df_recs['notes'] = df_recs['notes'].str.split(',').apply(lambda x: sorted(x))
|
| 58 |
df_recs['notes'] = df_recs['notes'].apply(lambda x: ', '.join([n.strip() for n in x]))
|
| 59 |
|
| 60 |
+
# Optional filtering by a specific note if provided
|
|
|
|
|
|
|
| 61 |
if note_search:
|
|
|
|
|
|
|
| 62 |
note_search_lower = note_search.lower()
|
| 63 |
df_recs = df_recs[df_recs['notes'].str.lower().str.contains(note_search_lower)]
|
| 64 |
|
| 65 |
+
# Return the desired columns
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
return df_recs[['brand', 'perfume', 'similarity', 'notes']]
|
| 67 |
|
| 68 |
# ----------------------------------------------------------------
|
|
|
|
| 106 |
font-size: 0.9rem !important;
|
| 107 |
}
|
| 108 |
|
| 109 |
+
/* Centered text for the top header */
|
| 110 |
#top-header {
|
| 111 |
text-align: center;
|
| 112 |
margin-bottom: 20px;
|
|
|
|
| 117 |
# BUILD THE GRADIO INTERFACE
|
| 118 |
# ----------------------------------------------------------------
|
| 119 |
with gr.Blocks(css=custom_css) as demo:
|
| 120 |
+
# Top header with HTML content
|
| 121 |
gr.HTML("""
|
| 122 |
<div id="top-header">
|
| 123 |
<h1>🌸 Perfume Recommendation App 🌸</h1>
|
|
|
|
| 126 |
""")
|
| 127 |
|
| 128 |
with gr.Row():
|
| 129 |
+
# Left column: user inputs
|
| 130 |
with gr.Column():
|
| 131 |
brand_dropdown = gr.Dropdown(
|
| 132 |
choices=brand_options,
|
| 133 |
label="Select Brand",
|
| 134 |
+
value=brand_options[0]
|
| 135 |
)
|
| 136 |
perfume_dropdown = gr.Dropdown(
|
| 137 |
choices=perfume_options,
|
| 138 |
label="Select Perfume",
|
| 139 |
+
value=perfume_options[0]
|
| 140 |
)
|
| 141 |
brand_dropdown.change(
|
| 142 |
fn=perfume_change,
|
|
|
|
| 144 |
outputs=[perfume_dropdown]
|
| 145 |
)
|
| 146 |
|
| 147 |
+
# Optional textbox for note search
|
| 148 |
note_search = gr.Textbox(
|
| 149 |
label="Optional: Search for a specific note (e.g., 'rose', 'vanilla')"
|
| 150 |
)
|
| 151 |
|
| 152 |
+
# Slider to select the number of recommendations to show
|
| 153 |
top_n_slider = gr.Slider(
|
| 154 |
minimum=1,
|
| 155 |
maximum=10,
|
|
|
|
| 158 |
label="Number of recommendations to show"
|
| 159 |
)
|
| 160 |
|
| 161 |
+
# Button to trigger the recommendation
|
| 162 |
btn_search = gr.Button("Recommend")
|
| 163 |
|
| 164 |
+
# Right column: display results
|
| 165 |
with gr.Column():
|
|
|
|
| 166 |
output_df = gr.Dataframe(
|
| 167 |
headers=["Brand", "Perfume", "Similarity", "Notes"],
|
| 168 |
label="Recommended Perfumes",
|
| 169 |
wrap=True
|
| 170 |
)
|
| 171 |
|
| 172 |
+
# Link the Recommend button to our function
|
| 173 |
btn_search.click(
|
| 174 |
fn=filter_by_perfume,
|
| 175 |
inputs=[brand_dropdown, perfume_dropdown, top_n_slider, note_search],
|