Spaces:
Sleeping
Sleeping
File size: 4,703 Bytes
733fcd8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
from utils.layout import render_layout
import streamlit as st
import time
from model.recipe_search import load_search_system # assumed you modularized this logic
import streamlit.components.v1 as components
def recipe_search_page():
st.markdown("""
## π½οΈ Advanced Recipe Recommendation
<div class="about-box">
This module uses a custom-trained BERT model to semantically search recipes
based on your query, ingredients, and tags.
</div>
""", unsafe_allow_html=True)
if 'search_system' not in st.session_state:
with st.spinner("π Initializing recipe search system..."):
st.session_state.search_system = load_search_system()
search_system = st.session_state.search_system
if not search_system.is_ready:
st.error("β System not ready. Please check data files and try again.")
return
query = st.text_input(
"Search for recipes:",
placeholder="e.g., 'chicken pasta', 'vegetarian salad', 'chocolate dessert'"
)
col1, col2 = st.columns(2)
with col1:
num_results = st.slider("Number of results", 1, 15, 5)
with col2:
min_rating = st.slider("Minimum rating", 1.0, 5.0, 3.0, 0.1)
if st.button("π Search Recipes") and query:
with st.spinner(f"Searching for '{query}'..."):
start = time.time()
print(query, num_results, min_rating)
results = search_system.search_recipes(query, num_results, min_rating)
elapsed = time.time() - start
if results:
st.markdown(f"### π― Top {len(results)} recipe recommendations for: *'{query}'*")
st.markdown("<sub>π Sorted by best match using semantic search and popularity</sub>", unsafe_allow_html=True)
st.markdown("<hr>", unsafe_allow_html=True)
for i, recipe in enumerate(results, 1):
steps_html = "".join([f"<li>{step.strip().capitalize()}</li>" for step in recipe.get("steps", [])])
description = recipe.get("description", "").strip().capitalize()
html_code = f"""
<div style="margin-bottom: 24px; padding: 16px; border-radius: 12px; background-color: #fdfdfd; box-shadow: 0 2px 8px rgba(0,0,0,0.06); font-family: Arial, sans-serif;">
<div style="font-size: 18px; font-weight: bold; color: #333;">π {i}. {recipe['name']}</div>
<div style="margin: 4px 0 8px 0; font-size: 14px; color: #555;">
β±οΈ <b>{recipe['minutes']} min</b> | π₯ <b>{recipe['n_steps']} steps</b> | β <b>{recipe['avg_rating']:.1f}/5.0</b>
<span style="font-size: 12px; color: #999;">({recipe['num_ratings']} ratings)</span>
</div>
<div style="margin-bottom: 6px; font-size: 14px;">
<b>π Match Score:</b> <span style="color: #007acc; font-weight: bold;">{recipe['similarity_score']:.1%}</span>
<span style="font-size: 12px; color: #888;">(query match)</span><br>
<b>π Overall Score:</b> <span style="color: green; font-weight: bold;">{recipe['combined_score']:.1%}</span>
<span style="font-size: 12px; color: #888;">(match + popularity)</span>
</div>
<div style="margin-bottom: 6px;">
<b>π·οΈ Tags:</b><br>
{" ".join([f"<span style='background:#eee;padding:4px 8px;border-radius:6px;margin:2px;display:inline-block;font-size:12px'>{tag}</span>" for tag in recipe['tags']])}
</div>
<div style="margin-bottom: 6px;">
<b>π₯ Ingredients:</b><br>
<span style="font-size: 13px; color: #444;">{', '.join(recipe['ingredients'][:8])}
{'...' if len(recipe['ingredients']) > 8 else ''}</span>
</div>
{"<div style='margin-top: 10px; font-size: 13px; color: #333;'><b>π Description:</b><br>" + description + "</div>" if description else ""}
{"<div style='margin-top: 10px; font-size: 13px;'><b>π§βπ³ Steps:</b><ol style='margin: 6px 0 0 18px; padding: 0;'>" + steps_html + "</ol></div>" if steps_html else ""}
</div>
"""
components.html(html_code, height=360 + len(recipe.get("steps", [])) * 20)
else:
st.warning(f"π No recipes found for '{query}' with a minimum rating of {min_rating}/5.0.")
render_layout(recipe_search_page) |