Spaces:
Runtime error
Runtime error
| import pandas as pd | |
| import gradio as gr | |
| import re | |
| from sentence_transformers import SentenceTransformer | |
| from sklearn.neighbors import NearestNeighbors | |
| # ------------------------------- | |
| # Load dataset | |
| # ------------------------------- | |
| df = pd.read_csv("food_order_cleaned.csv") | |
| df['rating'] = pd.to_numeric(df['rating'], errors='coerce') | |
| df['search_text'] = ( | |
| df['restaurant_name'].astype(str) + | |
| " | " + df['cuisine_type'].astype(str) + | |
| " | " + df['rating'].astype(str) | |
| ) | |
| # ------------------------------- | |
| # Rule-based functions | |
| # ------------------------------- | |
| def find_by_cuisine(cuisine, limit=10): | |
| mask = df['cuisine_type'].str.strip().str.lower() == cuisine.strip().lower() | |
| cols = ['restaurant_name','cuisine_type','cost_of_the_order','rating'] | |
| return df.loc[mask, cols].head(limit) | |
| def best_rated_by_cuisine(cuisine, top_n=10): | |
| mask = df['cuisine_type'].str.strip().str.lower() == cuisine.strip().lower() | |
| subset = df[mask].dropna(subset=['rating']).sort_values('rating', ascending=False) | |
| cols = ['restaurant_name','cuisine_type','cost_of_the_order','rating'] | |
| return subset[cols].head(top_n) | |
| def cheapest_high_rated(max_cost=None, min_rating=4.0, top_n=10): | |
| subset = df.dropna(subset=['rating']) | |
| subset = subset[subset['rating'] >= min_rating] | |
| if max_cost: | |
| subset = subset[subset['cost_of_the_order'] <= max_cost] | |
| subset = subset.sort_values('cost_of_the_order') | |
| cols = ['restaurant_name','cuisine_type','cost_of_the_order','rating'] | |
| return subset[cols].head(top_n) | |
| def personalized_recall(customer_id, day): | |
| mask = ( | |
| df['customer_id'].astype(str) == str(customer_id) | |
| ) & ( | |
| df['day_of_the_week'].str.lower() == day.lower() | |
| ) | |
| cols = ['order_id','restaurant_name','cuisine_type','cost_of_the_order','rating','day_of_the_week'] | |
| return df.loc[mask, cols] | |
| # ------------------------------- | |
| # Semantic Search | |
| # ------------------------------- | |
| model = SentenceTransformer("all-MiniLM-L6-v2") | |
| corpus_embeddings = model.encode(df["search_text"].tolist(), show_progress_bar=True) | |
| nn = NearestNeighbors(n_neighbors=10, metric="cosine").fit(corpus_embeddings) | |
| def semantic_search(query, k=5): | |
| q_emb = model.encode([query]) | |
| dists, idxs = nn.kneighbors(q_emb, n_neighbors=k) | |
| results = df.iloc[idxs[0]].copy() | |
| results["score"] = 1 - dists[0] | |
| cols = ['restaurant_name','cuisine_type','cost_of_the_order','rating','score'] | |
| return results[cols] | |
| # ------------------------------- | |
| # Query Router | |
| # ------------------------------- | |
| def handle_query(message, customer_id=""): | |
| text = message.lower() | |
| # 1. cuisine search | |
| if "find" in text and "restaurant" in text: | |
| for cuisine in df["cuisine_type"].str.lower().unique(): | |
| if cuisine in text: | |
| return find_by_cuisine(cuisine).to_html(index=False) | |
| return semantic_search(message).to_html(index=False) | |
| # 2. best-rated query | |
| if "best" in text: | |
| for cuisine in df["cuisine_type"].str.lower().unique(): | |
| if cuisine in text: | |
| return best_rated_by_cuisine(cuisine).to_html(index=False) | |
| return semantic_search(message).to_html(index=False) | |
| # 3. cheap places | |
| if "cheap" in text or "value" in text: | |
| return cheapest_high_rated().to_html(index=False) | |
| # 4. personalized recall | |
| if "what did i order" in text: | |
| m = re.search(r"on (\w+)", text) | |
| if not customer_id: | |
| return "Please enter customer_id." | |
| if not m: | |
| return "Please specify the day (e.g., Tuesday)" | |
| day = m.group(1) | |
| r = personalized_recall(customer_id, day) | |
| if r.empty: | |
| return "No matching records." | |
| return r.to_html(index=False) | |
| return semantic_search(message).to_html(index=False) | |
| # ------------------------------- | |
| # CHATBOT FUNCTION (DICTIONARY FORMAT) | |
| # ------------------------------- | |
| def chatbot_fn(history, message, customer_id): | |
| reply_html = handle_query(message, customer_id) | |
| # append user message | |
| history.append({"role": "user", "content": message}) | |
| # append assistant message | |
| history.append({"role": "assistant", "content": "Here are the results 👇"}) | |
| return history, "", reply_html | |
| # ------------------------------- | |
| # INTERFACE | |
| # ------------------------------- | |
| with gr.Blocks() as demo: | |
| gr.Markdown("## 🍽️ Restaurant Guide Chatbot") | |
| chat = gr.Chatbot(label="Chat History") # no type arg | |
| html_out = gr.HTML(label="Search Results") | |
| with gr.Row(): | |
| msg = gr.Textbox(placeholder="Ask me anything…") | |
| cid = gr.Textbox(label="Customer ID (optional)") | |
| btn = gr.Button("Send") | |
| btn.click( | |
| chatbot_fn, | |
| inputs=[chat, msg, cid], | |
| outputs=[chat, msg, html_out] | |
| ) | |
| demo.launch() | |