Ahmad-01 commited on
Commit
4336e75
·
verified ·
1 Parent(s): ba0ca23

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +128 -0
app.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+ import pandas as pd
3
+ import gradio as gr
4
+ import re
5
+ from sentence_transformers import SentenceTransformer
6
+ from sklearn.neighbors import NearestNeighbors
7
+
8
+ # -------------------------------
9
+ # Load dataset
10
+ # -------------------------------
11
+ df = pd.read_csv("food_order_cleaned.csv")
12
+ df['rating'] = pd.to_numeric(df['rating'], errors='coerce')
13
+ df['search_text'] = df['restaurant_name'].astype(str) + " | " + df['cuisine_type'].astype(str) + " | " + df['rating'].astype(str)
14
+
15
+ # -------------------------------
16
+ # Rule-based functions
17
+ # -------------------------------
18
+ def find_by_cuisine(cuisine, limit=10):
19
+ mask = df['cuisine_type'].str.strip().str.lower() == cuisine.strip().lower()
20
+ cols = ['restaurant_name', 'cuisine_type', 'cost_of_the_order', 'rating']
21
+ return df.loc[mask, cols].head(limit)
22
+
23
+ def best_rated_by_cuisine(cuisine, top_n=10):
24
+ mask = df['cuisine_type'].str.strip().str.lower() == cuisine.strip().lower()
25
+ subset = df[mask].dropna(subset=['rating']).sort_values('rating', ascending=False)
26
+ cols = ['restaurant_name', 'cuisine_type', 'cost_of_the_order', 'rating']
27
+ return subset[cols].head(top_n)
28
+
29
+ def cheapest_high_rated(max_cost=None, min_rating=4.0, top_n=10):
30
+ subset = df.dropna(subset=['rating'])
31
+ subset = subset[subset['rating'] >= min_rating]
32
+ if max_cost is not None:
33
+ subset = subset[subset['cost_of_the_order'] <= max_cost]
34
+ subset = subset.sort_values('cost_of_the_order')
35
+ cols = ['restaurant_name', 'cuisine_type', 'cost_of_the_order', 'rating']
36
+ return subset[cols].head(top_n)
37
+
38
+ def personalized_recall(customer_id, day):
39
+ mask = (df['customer_id'].astype(str) == str(customer_id)) & \
40
+ (df['day_of_the_week'].str.strip().str.lower() == day.strip().lower())
41
+ cols = ['order_id', 'restaurant_name', 'cuisine_type', 'cost_of_the_order', 'rating', 'day_of_the_week']
42
+ return df.loc[mask, cols]
43
+
44
+ # -------------------------------
45
+ # Semantic Search
46
+ # -------------------------------
47
+ model = SentenceTransformer('all-MiniLM-L6-v2')
48
+ corpus = df['search_text'].tolist()
49
+ corpus_embeddings = model.encode(corpus, show_progress_bar=True)
50
+ nn = NearestNeighbors(n_neighbors=10, metric='cosine').fit(corpus_embeddings)
51
+
52
+ def semantic_search(query, k=5):
53
+ q_emb = model.encode([query])
54
+ dists, idxs = nn.kneighbors(q_emb, n_neighbors=k)
55
+ results = df.iloc[idxs[0]].copy()
56
+ results['score'] = 1 - dists[0]
57
+ cols = ['restaurant_name', 'cuisine_type', 'cost_of_the_order', 'rating', 'score']
58
+ return results[cols]
59
+
60
+ # -------------------------------
61
+ # Combined Chat Handler
62
+ # -------------------------------
63
+ def handle_query(message, customer_id="", history=[]):
64
+ text = message.strip().lower()
65
+
66
+ # Rule-Based: Specific Recommendation
67
+ if 'find' in text and 'restaurant' in text:
68
+ known = set(df['cuisine_type'].str.strip().str.lower().unique())
69
+ words = text.split()
70
+ found = [w for w in words if w in known]
71
+ if found:
72
+ res = find_by_cuisine(found[0])
73
+ return res.to_html(index=False)
74
+ else:
75
+ return semantic_search(message).to_html(index=False)
76
+
77
+ # Rule-Based: Best Rated
78
+ if 'best' in text and ('place' in text or 'best-rated' in text):
79
+ known = set(df['cuisine_type'].str.strip().str.lower().unique())
80
+ words = text.split()
81
+ found = [w for w in words if w in known]
82
+ if found:
83
+ res = best_rated_by_cuisine(found[0])
84
+ return res.to_html(index=False)
85
+ else:
86
+ return semantic_search(message).to_html(index=False)
87
+
88
+ # Rule-Based: Cheapest / Value Search
89
+ if 'cheapest' in text or 'cheap' in text or 'value' in text:
90
+ res = cheapest_high_rated(min_rating=4.0, top_n=10)
91
+ return res.to_html(index=False)
92
+
93
+ # Rule-Based: Personalized Recall
94
+ if 'what did i order' in text:
95
+ day_match = re.search(r'on (\w+)', text)
96
+ day = day_match.group(1) if day_match else ''
97
+ if customer_id == '':
98
+ return "Please enter your customer_id in the input box."
99
+ if day == '':
100
+ return "Please specify the day, e.g. 'on Weekend'."
101
+ res = personalized_recall(customer_id, day)
102
+ if res.empty:
103
+ return "No orders found for that customer/day."
104
+ return res.to_html(index=False)
105
+
106
+ # Fallback: Semantic Search
107
+ return semantic_search(message).to_html(index=False)
108
+
109
+ # -------------------------------
110
+ # Gradio Chatbot Interface
111
+ # -------------------------------
112
+ def chat_reply(history, message, customer_id):
113
+ reply = handle_query(message, customer_id)
114
+ history.append((message, reply))
115
+ return history, ""
116
+
117
+ with gr.Blocks(title="Restaurant Guide Chatbot") as demo:
118
+ gr.Markdown("## Restaurant Guide Chatbot\nAsk queries like:\n- Find me a Thai restaurant\n- What are the best Italian places?\n- Show me the cheapest highly-rated places\n- What did I order on Weekend? (enter customer_id)")
119
+
120
+ chatbot = gr.Chatbot()
121
+ with gr.Row():
122
+ user_msg = gr.Textbox(placeholder="Type your message here...")
123
+ cust_id = gr.Textbox(label="Customer ID (optional)")
124
+ send = gr.Button("Send")
125
+
126
+ send.click(chat_reply, inputs=[chatbot, user_msg, cust_id], outputs=[chatbot, user_msg])
127
+
128
+ demo.launch()