pleabargain commited on
Commit
6221bef
Β·
verified Β·
1 Parent(s): 2064073

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +250 -126
app.py CHANGED
@@ -1,11 +1,17 @@
1
  import gradio as gr
2
  import datetime
3
- from typing import Dict, List
4
  import random
5
  from huggingface_hub import InferenceClient
 
 
6
 
7
- # Initialize the Hugging Face client
8
- client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
 
 
 
 
9
 
10
  class TravelPlanner:
11
  def __init__(self):
@@ -31,6 +37,28 @@ class TravelPlanner:
31
  'street_food': (5, 10)
32
  }
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  def generate_itinerary(self,
35
  destination: str,
36
  num_days: int,
@@ -38,30 +66,35 @@ class TravelPlanner:
38
  """
39
  Generate a daily itinerary based on destination and budget level
40
  """
41
- itinerary = []
42
-
43
- activities = [
44
- 'Morning sightseeing',
45
- 'Museum visit',
46
- 'Local market tour',
47
- 'Cultural workshop',
48
- 'Historical site visit',
49
- 'Nature walk',
50
- 'Local neighborhood exploration',
51
- 'Evening entertainment'
52
- ]
53
-
54
- for day in range(1, num_days + 1):
55
- daily_schedule = {
56
- 'day': day,
57
- 'morning': random.choice(activities),
58
- 'afternoon': random.choice(activities),
59
- 'evening': random.choice(activities),
60
- 'accommodation': f"{budget_level} accommodation"
61
- }
62
- itinerary.append(daily_schedule)
63
 
64
- return itinerary
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
  def calculate_budget(self,
67
  num_days: int,
@@ -70,35 +103,39 @@ class TravelPlanner:
70
  """
71
  Calculate estimated budget based on duration and comfort level
72
  """
73
- accommodation_range = self.accommodation_types[budget_level]
74
- meal_range = self.meal_costs[budget_level]
75
-
76
- daily_accommodation = random.uniform(*accommodation_range)
77
- daily_meals = random.uniform(*meal_range) * 3 # 3 meals per day
78
- daily_activities = random.uniform(30, 100) # Average activity cost
79
- daily_transport = random.uniform(10, 50) # Local transport
80
-
81
- total_accommodation = daily_accommodation * num_days
82
- total_meals = daily_meals * num_days
83
- total_activities = daily_activities * num_days
84
- total_transport = daily_transport * num_days
85
-
86
- total_meals *= num_people
87
- total_activities *= num_people
88
- total_transport *= num_people
89
-
90
- buffer = (total_accommodation + total_meals + total_activities + total_transport) * 0.1
91
-
92
- total_cost = total_accommodation + total_meals + total_activities + total_transport + buffer
93
-
94
- return {
95
- 'accommodation': round(total_accommodation, 2),
96
- 'meals': round(total_meals, 2),
97
- 'activities': round(total_activities, 2),
98
- 'transport': round(total_transport, 2),
99
- 'buffer': round(buffer, 2),
100
- 'total': round(total_cost, 2)
101
- }
 
 
 
 
102
 
103
  def format_output(self,
104
  destination: str,
@@ -107,29 +144,67 @@ class TravelPlanner:
107
  """
108
  Format the itinerary and budget into a readable string
109
  """
110
- output = f"Travel Plan for {destination}\n\n"
111
- output += "=== ITINERARY ===\n\n"
112
-
113
- for day in itinerary:
114
- output += f"Day {day['day']}:\n"
115
- output += f"Morning: {day['morning']}\n"
116
- output += f"Afternoon: {day['afternoon']}\n"
117
- output += f"Evening: {day['evening']}\n"
118
- output += f"Accommodation: {day['accommodation']}\n\n"
119
-
120
- output += "=== BUDGET BREAKDOWN ===\n\n"
121
- output += f"Accommodation: ${budget['accommodation']}\n"
122
- output += f"Meals: ${budget['meals']}\n"
123
- output += f"Activities: ${budget['activities']}\n"
124
- output += f"Local Transport: ${budget['transport']}\n"
125
- output += f"Buffer (10%): ${budget['buffer']}\n"
126
- output += f"Total Estimated Cost: ${budget['total']}\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
- return output
 
 
 
 
 
 
 
 
129
 
130
  def respond(
131
  message: str,
132
- history: List[Dict[str, str]], # Updated to use dict format
133
  system_message: str,
134
  max_tokens: int,
135
  temperature: float,
@@ -138,64 +213,113 @@ def respond(
138
  """
139
  Process chat message and generate travel plan if requested
140
  """
141
- # Check if this is a travel planning request
142
- if "plan a trip" in message.lower():
143
- try:
144
- # Parse the message
145
- parts = message.lower().split()
146
- destination_idx = parts.index("to") + 1
147
- days_idx = parts.index("days") - 1
148
- budget_idx = parts.index("budget") - 1
149
- people_idx = parts.index("people") - 1
150
-
151
- destination = parts[destination_idx].capitalize()
152
- num_days = int(parts[days_idx])
153
- budget_level = parts[budget_idx]
154
- num_people = int(parts[people_idx])
155
-
156
- # Generate travel plan
157
  planner = TravelPlanner()
158
- itinerary = planner.generate_itinerary(destination, num_days, budget_level)
159
- budget = planner.calculate_budget(num_days, budget_level, num_people)
160
- return planner.format_output(destination, itinerary, budget)
161
-
162
- except (ValueError, IndexError):
163
- return "I couldn't understand your travel request. Please use the format: 'Plan a trip to [destination] for [X] days, [budget_level] budget, [X] people'"
164
-
165
- # If not a travel request, use the Hugging Face model
166
- messages = [{"role": "system", "content": system_message}]
167
-
168
- # Convert history to the correct format
169
- for msg in history:
170
- messages.append({"role": msg["role"], "content": msg["content"]})
171
-
172
- messages.append({"role": "user", "content": message})
173
-
174
- response = ""
175
- for token in client.chat_completion(
176
- messages,
177
- max_tokens=max_tokens,
178
- stream=True,
179
- temperature=temperature,
180
- top_p=top_p,
181
- ):
182
- response += token.choices[0].delta.content
183
- return response
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
 
185
- # Create the Gradio interface with updated message format
186
  demo = gr.ChatInterface(
187
  respond,
188
  additional_inputs=[
189
- gr.Textbox(value="You are a travel planning assistant who can also chat about other topics.",
190
- label="System message"),
191
- gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
192
- gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
193
- gr.Slider(minimum=0.1, maximum=1.0, value=0.95, step=0.05,
194
- label="Top-p (nucleus sampling)"),
195
- ],
196
- message_history=True, # Enable message history
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  )
198
 
199
  # Launch the application
200
  if __name__ == "__main__":
201
- demo.launch()
 
 
 
 
1
  import gradio as gr
2
  import datetime
3
+ from typing import Dict, List, Union, Optional
4
  import random
5
  from huggingface_hub import InferenceClient
6
+ import logging
7
+ import json
8
 
9
+ # Set up logging
10
+ logging.basicConfig(
11
+ level=logging.INFO,
12
+ format='%(asctime)s - %(levelname)s - %(message)s'
13
+ )
14
+ logger = logging.getLogger(__name__)
15
 
16
  class TravelPlanner:
17
  def __init__(self):
 
37
  'street_food': (5, 10)
38
  }
39
 
40
+ def validate_inputs(self,
41
+ destination: str,
42
+ num_days: int,
43
+ budget_level: str,
44
+ num_people: int) -> tuple[bool, str]:
45
+ """
46
+ Validate input parameters
47
+ """
48
+ if not destination or len(destination.strip()) == 0:
49
+ return False, "Destination cannot be empty"
50
+
51
+ if num_days < 1 or num_days > 30:
52
+ return False, "Number of days must be between 1 and 30"
53
+
54
+ if budget_level not in self.accommodation_types:
55
+ return False, f"Budget level must be one of: {', '.join(self.accommodation_types.keys())}"
56
+
57
+ if num_people < 1 or num_people > 10:
58
+ return False, "Number of people must be between 1 and 10"
59
+
60
+ return True, ""
61
+
62
  def generate_itinerary(self,
63
  destination: str,
64
  num_days: int,
 
66
  """
67
  Generate a daily itinerary based on destination and budget level
68
  """
69
+ try:
70
+ activities = [
71
+ 'Morning sightseeing',
72
+ 'Museum visit',
73
+ 'Local market tour',
74
+ 'Cultural workshop',
75
+ 'Historical site visit',
76
+ 'Nature walk',
77
+ 'Local neighborhood exploration',
78
+ 'Evening entertainment'
79
+ ]
 
 
 
 
 
 
 
 
 
 
 
80
 
81
+ itinerary = []
82
+ for day in range(1, num_days + 1):
83
+ # Ensure no duplicate activities in same day
84
+ day_activities = random.sample(activities, 3)
85
+ daily_schedule = {
86
+ 'day': day,
87
+ 'morning': day_activities[0],
88
+ 'afternoon': day_activities[1],
89
+ 'evening': day_activities[2],
90
+ 'accommodation': f"{budget_level} accommodation"
91
+ }
92
+ itinerary.append(daily_schedule)
93
+
94
+ return itinerary
95
+ except Exception as e:
96
+ logger.error(f"Error generating itinerary: {str(e)}")
97
+ raise
98
 
99
  def calculate_budget(self,
100
  num_days: int,
 
103
  """
104
  Calculate estimated budget based on duration and comfort level
105
  """
106
+ try:
107
+ accommodation_range = self.accommodation_types[budget_level]
108
+ meal_range = self.meal_costs[budget_level]
109
+
110
+ # Use median values for more stable estimates
111
+ daily_accommodation = sum(accommodation_range) / 2
112
+ daily_meals = (sum(meal_range) / 2) * 3 # 3 meals per day
113
+ daily_activities = 65 # Median activity cost
114
+ daily_transport = 30 # Median transport cost
115
+
116
+ total_accommodation = daily_accommodation * num_days
117
+ total_meals = daily_meals * num_days * num_people
118
+ total_activities = daily_activities * num_days * num_people
119
+ total_transport = daily_transport * num_days * num_people
120
+
121
+ # Add 15% buffer for unexpected expenses
122
+ subtotal = total_accommodation + total_meals + total_activities + total_transport
123
+ buffer = subtotal * 0.15
124
+
125
+ total_cost = subtotal + buffer
126
+
127
+ return {
128
+ 'accommodation': round(total_accommodation, 2),
129
+ 'meals': round(total_meals, 2),
130
+ 'activities': round(total_activities, 2),
131
+ 'transport': round(total_transport, 2),
132
+ 'buffer': round(buffer, 2),
133
+ 'total': round(total_cost, 2),
134
+ 'per_person': round(total_cost / num_people, 2)
135
+ }
136
+ except Exception as e:
137
+ logger.error(f"Error calculating budget: {str(e)}")
138
+ raise
139
 
140
  def format_output(self,
141
  destination: str,
 
144
  """
145
  Format the itinerary and budget into a readable string
146
  """
147
+ try:
148
+ output = [f"πŸ“ Travel Plan for {destination}", ""]
149
+ output.append("πŸ—“οΈ ITINERARY")
150
+ output.append("=" * 20)
151
+
152
+ for day in itinerary:
153
+ output.extend([
154
+ f"Day {day['day']}:",
155
+ f"πŸŒ… Morning: {day['morning']}",
156
+ f"β˜€οΈ Afternoon: {day['afternoon']}",
157
+ f"πŸŒ™ Evening: {day['evening']}",
158
+ f"🏠 Accommodation: {day['accommodation']}",
159
+ ""
160
+ ])
161
+
162
+ output.extend([
163
+ "πŸ’° BUDGET BREAKDOWN",
164
+ "=" * 20,
165
+ f"🏨 Accommodation: ${budget['accommodation']:,.2f}",
166
+ f"🍽️ Meals: ${budget['meals']:,.2f}",
167
+ f"🎫 Activities: ${budget['activities']:,.2f}",
168
+ f"🚌 Local Transport: ${budget['transport']:,.2f}",
169
+ f"⚠️ Buffer (15%): ${budget['buffer']:,.2f}",
170
+ "=" * 20,
171
+ f"πŸ’΅ Total Cost: ${budget['total']:,.2f}",
172
+ f"πŸ‘₯ Cost per person: ${budget['per_person']:,.2f}"
173
+ ])
174
+
175
+ return "\n".join(output)
176
+ except Exception as e:
177
+ logger.error(f"Error formatting output: {str(e)}")
178
+ return "Error formatting travel plan. Please try again."
179
+
180
+ def parse_travel_request(message: str) -> Optional[Dict]:
181
+ """
182
+ Parse travel request message and extract parameters
183
+ """
184
+ try:
185
+ message = message.lower()
186
+ if "plan a trip" not in message:
187
+ return None
188
+
189
+ parts = message.split()
190
+ destination_idx = parts.index("to") + 1
191
+ days_idx = parts.index("days") - 1
192
+ budget_idx = parts.index("budget") - 1
193
+ people_idx = parts.index("people") - 1
194
 
195
+ return {
196
+ "destination": parts[destination_idx].capitalize(),
197
+ "num_days": int(parts[days_idx]),
198
+ "budget_level": parts[budget_idx],
199
+ "num_people": int(parts[people_idx])
200
+ }
201
+ except (ValueError, IndexError) as e:
202
+ logger.warning(f"Error parsing travel request: {str(e)}")
203
+ return None
204
 
205
  def respond(
206
  message: str,
207
+ history: List[Dict[str, str]],
208
  system_message: str,
209
  max_tokens: int,
210
  temperature: float,
 
213
  """
214
  Process chat message and generate travel plan if requested
215
  """
216
+ try:
217
+ # Check if this is a travel planning request
218
+ travel_params = parse_travel_request(message)
219
+
220
+ if travel_params:
 
 
 
 
 
 
 
 
 
 
 
221
  planner = TravelPlanner()
222
+
223
+ # Validate inputs
224
+ is_valid, error_msg = planner.validate_inputs(
225
+ travel_params["destination"],
226
+ travel_params["num_days"],
227
+ travel_params["budget_level"],
228
+ travel_params["num_people"]
229
+ )
230
+
231
+ if not is_valid:
232
+ return f"Error: {error_msg}\n\nPlease use the format: 'Plan a trip to [destination] for [X] days, [budget_level] budget, [X] people'"
233
+
234
+ try:
235
+ # Generate travel plan
236
+ itinerary = planner.generate_itinerary(
237
+ travel_params["destination"],
238
+ travel_params["num_days"],
239
+ travel_params["budget_level"]
240
+ )
241
+
242
+ budget = planner.calculate_budget(
243
+ travel_params["num_days"],
244
+ travel_params["budget_level"],
245
+ travel_params["num_people"]
246
+ )
247
+
248
+ return planner.format_output(
249
+ travel_params["destination"],
250
+ itinerary,
251
+ budget
252
+ )
253
+ except Exception as e:
254
+ logger.error(f"Error generating travel plan: {str(e)}")
255
+ return "Sorry, there was an error generating your travel plan. Please try again."
256
+
257
+ # If not a travel request, use the Hugging Face model
258
+ try:
259
+ client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
260
+
261
+ messages = [{"role": "system", "content": system_message}]
262
+ for msg in history:
263
+ if isinstance(msg, dict) and "role" in msg and "content" in msg:
264
+ messages.append(msg)
265
+
266
+ messages.append({"role": "user", "content": message})
267
+
268
+ response = ""
269
+ for token in client.chat_completion(
270
+ messages,
271
+ max_tokens=max_tokens,
272
+ stream=True,
273
+ temperature=temperature,
274
+ top_p=top_p,
275
+ ):
276
+ if hasattr(token.choices[0].delta, 'content'):
277
+ response += token.choices[0].delta.content or ""
278
+ return response
279
+
280
+ except Exception as e:
281
+ logger.error(f"Error with chat model: {str(e)}")
282
+ return "I apologize, but I'm having trouble connecting to the chat service. You can still use me for travel planning by saying 'Plan a trip to [destination]...'"
283
+
284
+ except Exception as e:
285
+ logger.error(f"Unexpected error in respond function: {str(e)}")
286
+ return "An unexpected error occurred. Please try again."
287
 
288
+ # Create the Gradio interface
289
  demo = gr.ChatInterface(
290
  respond,
291
  additional_inputs=[
292
+ gr.Textbox(
293
+ value="You are a travel planning assistant who can also chat about other topics.",
294
+ label="System message"
295
+ ),
296
+ gr.Slider(
297
+ minimum=1,
298
+ maximum=2048,
299
+ value=512,
300
+ step=1,
301
+ label="Max new tokens"
302
+ ),
303
+ gr.Slider(
304
+ minimum=0.1,
305
+ maximum=4.0,
306
+ value=0.7,
307
+ step=0.1,
308
+ label="Temperature"
309
+ ),
310
+ gr.Slider(
311
+ minimum=0.1,
312
+ maximum=1.0,
313
+ value=0.95,
314
+ step=0.05,
315
+ label="Top-p (nucleus sampling)"
316
+ ),
317
+ ]
318
  )
319
 
320
  # Launch the application
321
  if __name__ == "__main__":
322
+ try:
323
+ demo.launch()
324
+ except Exception as e:
325
+ logger.error(f"Error launching Gradio interface: {str(e)}")