Ahmad-01 commited on
Commit
1cf9263
·
verified ·
1 Parent(s): 9f2064a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +126 -64
app.py CHANGED
@@ -1,78 +1,140 @@
1
  import pandas as pd
2
- import numpy as np
3
  import gradio as gr
 
4
  from sentence_transformers import SentenceTransformer
5
- from sklearn.metrics.pairwise import cosine_similarity
6
 
7
- # -----------------------------
8
- # LOAD DATA & MODEL
9
- # -----------------------------
10
  df = pd.read_csv("food_order_cleaned.csv")
11
-
12
- model = SentenceTransformer("all-MiniLM-L6-v2")
13
-
14
- def create_text(row):
15
- return (
16
- f"Restaurant: {row['restaurant_name']}. "
17
- f"Cuisine: {row['cuisine_type']}. "
18
- f"Rating: {row['rating']}. "
19
- f"Cost: {row['cost_of_the_order']}."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  )
 
 
21
 
22
- df["text"] = df.apply(create_text, axis=1)
23
- corpus_embeddings = model.encode(df["text"].tolist(), normalize_embeddings=True)
24
-
25
- # -----------------------------
26
- # CHATBOT LOGIC
27
- # -----------------------------
28
- def chat_fn(message, history):
29
-
30
- user_msg = {"role": "user", "content": message}
31
-
32
- # Find best match
33
- q_emb = model.encode([message], normalize_embeddings=True)
34
- sims = cosine_similarity(q_emb, corpus_embeddings)[0]
35
- idx = int(np.argmax(sims))
36
- best = df.iloc[idx]
37
-
38
- bot_response = (
39
- f"🍽 **Recommended Restaurant**\n\n"
40
- f"**Name:** {best['restaurant_name']}\n"
41
- f"**Cuisine:** {best['cuisine_type']}\n"
42
- f"**Rating:** ⭐ {best['rating']}\n"
43
- f"**Avg Cost:** {best['cost_of_the_order']}\n\n"
44
- f"Ask me for more options anytime!"
45
- )
46
-
47
- bot_msg = {"role": "assistant", "content": bot_response}
48
-
49
- # Append messages to history
50
- history.append(user_msg)
51
- history.append(bot_msg)
52
-
53
- return history, history
54
-
55
-
56
- # -----------------------------
57
- # GRADIO UI (Gradio 4.x format)
58
- # -----------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  with gr.Blocks() as demo:
 
60
 
61
- gr.Markdown("## 🍴 Restaurant Guide Chatbot")
 
62
 
63
- chatbot = gr.Chatbot(
64
- label="Chat Window",
65
- type="messages"
66
- )
67
 
68
- user_input = gr.Textbox(
69
- placeholder="Ask: Find me a Thai restaurant...",
70
- label="Your Message"
 
71
  )
72
 
73
- clear = gr.Button("Clear Chat")
74
-
75
- user_input.submit(chat_fn, [user_input, chatbot], [chatbot, chatbot])
76
- clear.click(lambda: [], None, chatbot)
77
-
78
  demo.launch()
 
1
  import pandas as pd
 
2
  import gradio as gr
3
+ import re
4
  from sentence_transformers import SentenceTransformer
5
+ from sklearn.neighbors import NearestNeighbors
6
 
7
+ # -------------------------------
8
+ # Load dataset
9
+ # -------------------------------
10
  df = pd.read_csv("food_order_cleaned.csv")
11
+ df['rating'] = pd.to_numeric(df['rating'], errors='coerce')
12
+ df['search_text'] = (
13
+ df['restaurant_name'].astype(str) +
14
+ " | " + df['cuisine_type'].astype(str) +
15
+ " | " + df['rating'].astype(str)
16
+ )
17
+
18
+ # -------------------------------
19
+ # Rule-based functions
20
+ # -------------------------------
21
+ def find_by_cuisine(cuisine, limit=10):
22
+ mask = df['cuisine_type'].str.strip().str.lower() == cuisine.strip().lower()
23
+ cols = ['restaurant_name','cuisine_type','cost_of_the_order','rating']
24
+ return df.loc[mask, cols].head(limit)
25
+
26
+ def best_rated_by_cuisine(cuisine, top_n=10):
27
+ mask = df['cuisine_type'].str.strip().str.lower() == cuisine.strip().lower()
28
+ subset = df[mask].dropna(subset=['rating']).sort_values('rating', ascending=False)
29
+ cols = ['restaurant_name','cuisine_type','cost_of_the_order','rating']
30
+ return subset[cols].head(top_n)
31
+
32
+ def cheapest_high_rated(max_cost=None, min_rating=4.0, top_n=10):
33
+ subset = df.dropna(subset=['rating'])
34
+ subset = subset[subset['rating'] >= min_rating]
35
+ if max_cost:
36
+ subset = subset[subset['cost_of_the_order'] <= max_cost]
37
+ subset = subset.sort_values('cost_of_the_order')
38
+ cols = ['restaurant_name','cuisine_type','cost_of_the_order','rating']
39
+ return subset[cols].head(top_n)
40
+
41
+ def personalized_recall(customer_id, day):
42
+ mask = (
43
+ df['customer_id'].astype(str) == str(customer_id)
44
+ ) & (
45
+ df['day_of_the_week'].str.lower() == day.lower()
46
  )
47
+ cols = ['order_id','restaurant_name','cuisine_type','cost_of_the_order','rating','day_of_the_week']
48
+ return df.loc[mask, cols]
49
 
50
+ # -------------------------------
51
+ # Semantic Search
52
+ # -------------------------------
53
+ model = SentenceTransformer("all-MiniLM-L6-v2")
54
+ corpus_embeddings = model.encode(df["search_text"].tolist(), show_progress_bar=True)
55
+ nn = NearestNeighbors(n_neighbors=10, metric="cosine").fit(corpus_embeddings)
56
+
57
+ def semantic_search(query, k=5):
58
+ q_emb = model.encode([query])
59
+ dists, idxs = nn.kneighbors(q_emb, n_neighbors=k)
60
+ results = df.iloc[idxs[0]].copy()
61
+ results["score"] = 1 - dists[0]
62
+ cols = ['restaurant_name','cuisine_type','cost_of_the_order','rating','score']
63
+ return results[cols]
64
+
65
+ # -------------------------------
66
+ # Query Router
67
+ # -------------------------------
68
+ def handle_query(message, customer_id=""):
69
+ text = message.lower()
70
+
71
+ # 1. cuisine search
72
+ if "find" in text and "restaurant" in text:
73
+ for cuisine in df["cuisine_type"].str.lower().unique():
74
+ if cuisine in text:
75
+ return find_by_cuisine(cuisine).to_html(index=False)
76
+ return semantic_search(message).to_html(index=False)
77
+
78
+ # 2. best-rated query
79
+ if "best" in text:
80
+ for cuisine in df["cuisine_type"].str.lower().unique():
81
+ if cuisine in text:
82
+ return best_rated_by_cuisine(cuisine).to_html(index=False)
83
+ return semantic_search(message).to_html(index=False)
84
+
85
+ # 3. cheap places
86
+ if "cheap" in text or "value" in text:
87
+ return cheapest_high_rated().to_html(index=False)
88
+
89
+ # 4. personalized recall
90
+ if "what did i order" in text:
91
+ m = re.search(r"on (\w+)", text)
92
+ if not customer_id:
93
+ return "Please enter customer_id."
94
+ if not m:
95
+ return "Please specify the day (e.g., Tuesday)"
96
+ day = m.group(1)
97
+ r = personalized_recall(customer_id, day)
98
+ if r.empty:
99
+ return "No matching records."
100
+ return r.to_html(index=False)
101
+
102
+ return semantic_search(message).to_html(index=False)
103
+
104
+
105
+ # -------------------------------
106
+ # CHATBOT FUNCTION (DICTIONARY FORMAT)
107
+ # -------------------------------
108
+ def chatbot_fn(history, message, customer_id):
109
+ reply_html = handle_query(message, customer_id)
110
+
111
+ # append user message
112
+ history.append({"role": "user", "content": message})
113
+
114
+ # append assistant message
115
+ history.append({"role": "assistant", "content": "Here are the results 👇"})
116
+
117
+ return history, "", reply_html
118
+
119
+
120
+ # -------------------------------
121
+ # INTERFACE
122
+ # -------------------------------
123
  with gr.Blocks() as demo:
124
+ gr.Markdown("## 🍽️ Restaurant Guide Chatbot")
125
 
126
+ chat = gr.Chatbot(label="Chat History") # no type arg
127
+ html_out = gr.HTML(label="Search Results")
128
 
129
+ with gr.Row():
130
+ msg = gr.Textbox(placeholder="Ask me anything…")
131
+ cid = gr.Textbox(label="Customer ID (optional)")
132
+ btn = gr.Button("Send")
133
 
134
+ btn.click(
135
+ chatbot_fn,
136
+ inputs=[chat, msg, cid],
137
+ outputs=[chat, msg, html_out]
138
  )
139
 
 
 
 
 
 
140
  demo.launch()