Ahmad-01 commited on
Commit
b86b079
·
verified ·
1 Parent(s): 81dfa34

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +69 -129
app.py CHANGED
@@ -1,140 +1,80 @@
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()
 
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
+ TEXT_FIELDS = ["restaurant_name", "cuisine_type", "rating", "cost_of_the_order"]
15
+
16
+ def create_text(row):
17
+ text = (
18
+ f"Restaurant: {row['restaurant_name']}. "
19
+ f"Cuisine: {row['cuisine_type']}. "
20
+ f"Rating: {row['rating']}. "
21
+ f"Cost: {row['cost_of_the_order']}."
22
+ )
23
+ return text
24
+
25
+ df["text"] = df.apply(create_text, axis=1)
26
+ corpus_embeddings = model.encode(df["text"].tolist(), normalize_embeddings=True)
27
+
28
+ # -----------------------------
29
+ # CHAT LOGIC
30
+ # -----------------------------
31
+ def bot_reply(user_query, history):
32
+ if not user_query.strip():
33
+ return history + [("","Please enter a valid question.")]
34
+
35
+ # Encode query
36
+ q_emb = model.encode([user_query], normalize_embeddings=True)
37
+ sims = cosine_similarity(q_emb, corpus_embeddings)[0]
38
+ idx = np.argmax(sims)
39
+ best_match = df.iloc[idx]
40
+
41
+ # Prepare clean response
42
+ response = (
43
+ f"🍽 **Recommended Restaurant**\n\n"
44
+ f"**Name:** {best_match['restaurant_name']}\n"
45
+ f"**Cuisine:** {best_match['cuisine_type']}\n"
46
+ f"**Rating:** ⭐ {best_match['rating']}\n"
47
+ f"**Avg Cost:** {best_match['cost_of_the_order']}\n\n"
48
+ f"Let me know if you want more options!"
49
+ )
50
+
51
+ # Update chat
52
+ history = history + [(user_query, response)]
53
+ return history
54
+
55
+
56
+ # -----------------------------
57
+ # GRADIO UI (MODERN + CLEAN)
58
+ # -----------------------------
59
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo")) as demo:
60
+
61
+ gr.Markdown(
62
+ """
63
+ # 🍴 Restaurant Guide Chatbot
64
+ Ask me for restaurant recommendations!
65
+ """
66
  )
67
 
68
+ chat = gr.Chatbot(label="Chat with Restaurant Guide", height=500)
69
+
70
+ with gr.Row():
71
+ user_in = gr.Textbox(
72
+ placeholder="Ask: Find me a Thai restaurant, show me cheap Italian...",
73
+ label="Your Question"
74
+ )
75
+ clear = gr.Button("Clear Chat")
76
+
77
+ user_in.submit(bot_reply, [user_in, chat], chat)
78
+ clear.click(lambda: [], None, chat)
79
+
80
  demo.launch()