Spaces:
Running
Running
| import gradio as gr | |
| import pandas as pd | |
| import numpy as np | |
| import folium | |
| import sys | |
| import os | |
| # Add utils to path | |
| sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), 'utils')) | |
| from clean_text import clean_text | |
| from semantic_similarity import Encoder | |
| from main import get_recommendations | |
| print("Loading restaurant data...") | |
| data = pd.read_csv("data/toy_data_aggregated_embeddings.csv") | |
| print(f"Loaded {len(data)} restaurants") | |
| # Initialize semantic encoder | |
| print("Loading semantic encoder model...") | |
| try: | |
| encoder = Encoder() | |
| print("Semantic encoder loaded") | |
| except Exception as e: | |
| print(f"Warning: Could not load semantic encoder: {e}") | |
| print("Falling back to keyword-only search") | |
| def create_paris_map(results_df): | |
| """Create interactive map of Paris restaurants""" | |
| paris_center = [48.8566, 2.3522] | |
| m = folium.Map(location=paris_center, zoom_start=12, tiles='OpenStreetMap') | |
| for idx, row in results_df.iterrows(): | |
| lat_offset = np.random.uniform(-0.05, 0.05) | |
| lng_offset = np.random.uniform(-0.07, 0.07) | |
| coords = [48.8566 + lat_offset, 2.3522 + lng_offset] | |
| rating = float(row.get('overall_rating', 0)) | |
| color = 'green' if rating >= 4.5 else 'blue' if rating >= 4.0 else 'orange' if rating >= 3.5 else 'red' | |
| popup_html = f""" | |
| <div style="width:250px"> | |
| <h4><b>{row['name']}</b></h4> | |
| <p>Rating: {row.get('overall_rating', 'N/A')}</p> | |
| <p>Reviews: {row.get('review_count', 'N/A')}</p> | |
| <p>Popularity Score: {row.get('pop_score', 'N/A'):.2f}</p> | |
| </div> | |
| """ | |
| folium.Marker( | |
| location=coords, | |
| popup=folium.Popup(popup_html, max_width=300), | |
| icon=folium.Icon(color=color, icon='cutlery', prefix='fa') | |
| ).add_to(m) | |
| return m._repr_html_() | |
| def search_restaurants(query_input, data_source, num_results): | |
| n_candidates = 2000 | |
| query_clean = clean_text(query_input) | |
| restaurant_ids = get_recommendations(query_clean, n_candidates, num_results, data_source) | |
| # Subset data for recommendedations | |
| results = data[data["id"].isin(restaurant_ids)] | |
| map_html = create_paris_map(results) | |
| output = f"Found {len(results)} restaurants for '{query_input}'\n" | |
| output += f"Data Source: {data_source}\n" | |
| for idx, (_, row) in enumerate(results.iterrows(), 1): | |
| name = row.get('name', 'Unknown') | |
| rating = row.get('overall_rating', 'N/A') | |
| reviews = row.get('review_count', 'N/A') | |
| output += f"{idx}. **{name}**\n" | |
| output += f" Rating: {rating} | Reviews: {reviews}\n" | |
| output += "\n" | |
| if 'address' in row and pd.notna(row['address']): | |
| addr = str(row['address'])[:100] | |
| output += f" Address: {addr}\n" | |
| output += "\n" | |
| return output, map_html | |
| # Create Gradio interface | |
| with gr.Blocks( | |
| title="Restaurant Finder", | |
| # theme=gr.themes.Soft() | |
| ) as app: | |
| gr.Markdown(""" | |
| # Advanced Restaurant Recommendation System | |
| ### Search Through 5,000+ Restaurants with AI-Powered Semantic Search | |
| Find restaurants using semantic understanding and popularity ranking! | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=3): | |
| query_input = gr.Textbox( | |
| label="Search Query", | |
| placeholder="e.g., Italian pasta, best sushi, romantic dinner, family-friendly pizza", | |
| lines=2 | |
| ) | |
| with gr.Column(scale=2): | |
| data_source = gr.Dropdown( | |
| choices=["Michelin Guide", "Google", "Yelp"], | |
| value="Yelp", | |
| multiselect=True, | |
| label="Data Source", | |
| info="Select restaurant data source" | |
| ) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| num_results = gr.Slider( | |
| minimum=5, | |
| maximum=30, | |
| value=10, | |
| step=5, | |
| label="Results" | |
| ) | |
| search_btn = gr.Button("Search Restaurants", variant="primary", size="lg") | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| results_output = gr.Textbox( | |
| label="Restaurant Results", | |
| lines=20, | |
| max_lines=30 | |
| ) | |
| with gr.Column(scale=1): | |
| map_output = gr.HTML( | |
| label="Paris Map" | |
| ) | |
| gr.Markdown("### Try These Examples:") | |
| examples = [ | |
| ["Italian pasta", "Yelp", 10], | |
| ["sushi", "Michelin Guide", 10], | |
| ["romantic dinner", "Google", 8], | |
| ["family-friendly pizza", "Yelp", 10], | |
| ["best seafood", "Michelin Guide", 10], | |
| ["cheap burger", "Google", 10] | |
| ] | |
| gr.Examples( | |
| examples=examples, | |
| inputs=[query_input, data_source, num_results] | |
| ) | |
| search_btn.click( | |
| fn=search_restaurants, | |
| inputs=[query_input, data_source, num_results], | |
| outputs=[results_output, map_output] | |
| ) | |
| query_input.submit( | |
| fn=search_restaurants, | |
| inputs=[query_input, data_source, num_results], | |
| outputs=[results_output, map_output] | |
| ) | |
| if __name__ == "__main__": | |
| print("\nStarting Advanced Restaurant Finder...") | |
| print(f"{len(data)} restaurants ready to search") | |
| print("Opening at http://127.0.0.1:7860\n") | |
| # # if run locally | |
| # app.launch(share=False, server_name="127.0.0.1", server_port=7860, inbrowser=True) | |
| # if run on HF Space | |
| app.launch(ssr_mode=False) |