NSamson1 commited on
Commit
6492bfc
ยท
verified ยท
1 Parent(s): 51b7c4e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +31 -35
app.py CHANGED
@@ -5,16 +5,19 @@ from datetime import datetime, timedelta
5
  from functools import lru_cache
6
  import gradio as gr
7
  import openai
8
- OPENAI_API_KEY
9
- # -------------------- CONFIGURATION --------------------
10
- # Use the provided OpenAI API key (lecturer paid for it)
11
- OPENAI_API_KEY = "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"
12
-
13
- # Optional: set OpenWeatherMap API key as environment variable (lecturer will provide)
14
- OPENWEATHER_API_KEY = os.getenv("OPENWEATHER_API_KEY", "") # Set this in Hugging Face Secrets
15
- SERP_API_KEY = os.getenv("SERPAPI_API_KEY", "") # Optional for realโ€‘time attractions
16
 
17
- client = openai.OpenAI(api_key=OPENAI_API_KEY)
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  # Local attractions database (can be expanded)
20
  try:
@@ -28,7 +31,7 @@ except FileNotFoundError:
28
  # -------------------- TOOL IMPLEMENTATIONS --------------------
29
  def get_weather(city: str) -> dict:
30
  """
31
- Return current weather for any city using lecturer's OpenWeatherMap API.
32
  Returns a dict with keys: city, temperature, condition, humidity, wind_speed, precipitation.
33
  On error, returns dict with 'error' key.
34
  """
@@ -56,7 +59,6 @@ def get_weather(city: str) -> dict:
56
  if response.status_code != 200:
57
  return {"error": f"Weather API error: {data.get('message', 'unknown')}"}
58
 
59
- # Extract relevant fields
60
  return {
61
  "city": city,
62
  "temperature": data['main']['temp'],
@@ -123,6 +125,13 @@ def fetch_attractions_via_serp(city: str) -> list:
123
 
124
  def fetch_attractions_via_openai(city: str) -> list:
125
  """Use OpenAI to generate a list of top attractions for any city."""
 
 
 
 
 
 
 
126
  try:
127
  prompt = f"""
128
  List the top 8 tourist attractions in {city}. For each, provide:
@@ -146,7 +155,6 @@ Do not include any other text.
146
  if isinstance(attractions, dict) and "attractions" in attractions:
147
  attractions = attractions["attractions"]
148
  elif not isinstance(attractions, list):
149
- # Try to extract list
150
  attractions = [attractions]
151
  # Normalize to our format
152
  result = []
@@ -160,7 +168,6 @@ Do not include any other text.
160
  return result
161
  except Exception as e:
162
  print(f"OpenAI attractions error: {e}")
163
- # Fallback to a simple generic list
164
  return [
165
  {"name": f"City center", "type": "landmark", "entry_fee": "free", "duration_hours": 2},
166
  {"name": f"Local museum", "type": "museum", "entry_fee": "varies", "duration_hours": 2},
@@ -180,9 +187,10 @@ def get_attractions(city: str) -> dict:
180
  if serp_attractions:
181
  return {"city": city, "attractions": serp_attractions, "source": "SerpAPI"}
182
 
183
- # 3. Fallback to OpenAI (always works, unless quota exceeded)
184
  openai_attractions = fetch_attractions_via_openai(city)
185
- return {"city": city, "attractions": openai_attractions, "source": "OpenAI (AIโ€‘generated)"}
 
186
 
187
  def get_tripadvisor_link(query):
188
  """Fetch a TripAdvisor link using SerpAPI (optional)."""
@@ -240,6 +248,10 @@ def generate_itinerary(destination, start_date, num_days, budget_type, departure
240
 
241
  # 5. Attempt to call OpenAI for itinerary
242
  try:
 
 
 
 
243
  prompt = f"""
244
  You are an expert travel planner. Create a detailed, day-wise travel itinerary based on the verified information below.
245
 
@@ -297,26 +309,10 @@ Follow these rules:
297
  break
298
  itinerary = "\n".join(enhanced)
299
 
300
- except openai.RateLimitError as e:
301
- # Quota exceeded โ€“ fallback to manual itinerary
302
- itinerary = f"""
303
- # ๐ŸŒ Manual Itinerary for {destination} (OpenAI quota exceeded)
304
-
305
- **Weather:** {weather_text}
306
- **Attractions available:**
307
- {attractions_list}
308
- {source_note}
309
- **Budget:** {budget_text if budget_text else 'Not specified'}
310
-
311
- *Since the AI service is temporarily unavailable (quota exceeded), please use the above information to plan your trip manually. You can search for opening hours, entry fees, and book activities online.*
312
-
313
- ๐Ÿ›๏ธ [Search Hotels on Booking.com](https://www.booking.com/searchresults.html?ss={destination.replace(' ', '+')})
314
- โœˆ๏ธ [Search Flights on Skyscanner](https://www.skyscanner.co.in/)
315
- """
316
  except Exception as e:
317
- # Other OpenAI errors
318
  itinerary = f"""
319
- # โš ๏ธ Itinerary generation failed (OpenAI error: {str(e)})
320
 
321
  **Weather:** {weather_text}
322
  **Attractions available:**
@@ -324,7 +320,7 @@ Follow these rules:
324
  {source_note}
325
  **Budget:** {budget_text if budget_text else 'Not specified'}
326
 
327
- Please try again later or use the above information to plan manually.
328
 
329
  ๐Ÿ›๏ธ [Search Hotels on Booking.com](https://www.booking.com/searchresults.html?ss={destination.replace(' ', '+')})
330
  โœˆ๏ธ [Search Flights on Skyscanner](https://www.skyscanner.co.in/)
@@ -353,7 +349,7 @@ with gr.Blocks(css=css) as demo:
353
  gr.Markdown("""
354
  # ๐ŸŒ TouristGuide AI Agent
355
  Your personal travel planner powered by real-time weather, attractions, and OpenAI.
356
- Works for **any city** โ€“ if no local data or SerpAPI, it uses OpenAI to suggest attractions.
357
  """)
358
  with gr.Row():
359
  destination = gr.Textbox(label="Destination (any city)", placeholder="e.g., Paris, Tokyo, New York", scale=2)
 
5
  from functools import lru_cache
6
  import gradio as gr
7
  import openai
 
 
 
 
 
 
 
 
8
 
9
+ # -------------------- CONFIGURATION --------------------
10
+ # Read API keys from environment variables (set in Hugging Face Secrets)
11
+ OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
12
+ OPENWEATHER_API_KEY = os.getenv("OPENWEATHER_API_KEY", "")
13
+ SERP_API_KEY = os.getenv("SERPAPI_API_KEY", "")
14
+
15
+ # Warn if OpenAI key is missing (but continue with fallbacks)
16
+ if not OPENAI_API_KEY:
17
+ print("โš ๏ธ OPENAI_API_KEY not set. AI itinerary generation will fall back to manual mode.")
18
+ client = None
19
+ else:
20
+ client = openai.OpenAI(api_key=OPENAI_API_KEY)
21
 
22
  # Local attractions database (can be expanded)
23
  try:
 
31
  # -------------------- TOOL IMPLEMENTATIONS --------------------
32
  def get_weather(city: str) -> dict:
33
  """
34
+ Return current weather for any city using OpenWeatherMap API (if key set).
35
  Returns a dict with keys: city, temperature, condition, humidity, wind_speed, precipitation.
36
  On error, returns dict with 'error' key.
37
  """
 
59
  if response.status_code != 200:
60
  return {"error": f"Weather API error: {data.get('message', 'unknown')}"}
61
 
 
62
  return {
63
  "city": city,
64
  "temperature": data['main']['temp'],
 
125
 
126
  def fetch_attractions_via_openai(city: str) -> list:
127
  """Use OpenAI to generate a list of top attractions for any city."""
128
+ if not client:
129
+ # If no OpenAI client, return generic list
130
+ return [
131
+ {"name": f"City center", "type": "landmark", "entry_fee": "free", "duration_hours": 2},
132
+ {"name": f"Local museum", "type": "museum", "entry_fee": "varies", "duration_hours": 2},
133
+ {"name": f"Popular park", "type": "nature", "entry_fee": "free", "duration_hours": 2}
134
+ ]
135
  try:
136
  prompt = f"""
137
  List the top 8 tourist attractions in {city}. For each, provide:
 
155
  if isinstance(attractions, dict) and "attractions" in attractions:
156
  attractions = attractions["attractions"]
157
  elif not isinstance(attractions, list):
 
158
  attractions = [attractions]
159
  # Normalize to our format
160
  result = []
 
168
  return result
169
  except Exception as e:
170
  print(f"OpenAI attractions error: {e}")
 
171
  return [
172
  {"name": f"City center", "type": "landmark", "entry_fee": "free", "duration_hours": 2},
173
  {"name": f"Local museum", "type": "museum", "entry_fee": "varies", "duration_hours": 2},
 
187
  if serp_attractions:
188
  return {"city": city, "attractions": serp_attractions, "source": "SerpAPI"}
189
 
190
+ # 3. Fallback to OpenAI (or generic if no key)
191
  openai_attractions = fetch_attractions_via_openai(city)
192
+ source = "OpenAI" if client else "generic fallback"
193
+ return {"city": city, "attractions": openai_attractions, "source": source}
194
 
195
  def get_tripadvisor_link(query):
196
  """Fetch a TripAdvisor link using SerpAPI (optional)."""
 
248
 
249
  # 5. Attempt to call OpenAI for itinerary
250
  try:
251
+ if not client:
252
+ # No OpenAI key โ€“ show manual plan
253
+ raise Exception("OpenAI client not available")
254
+
255
  prompt = f"""
256
  You are an expert travel planner. Create a detailed, day-wise travel itinerary based on the verified information below.
257
 
 
309
  break
310
  itinerary = "\n".join(enhanced)
311
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
  except Exception as e:
313
+ # Fallback to manual itinerary (no AI)
314
  itinerary = f"""
315
+ # ๐ŸŒ Manual Itinerary for {destination}
316
 
317
  **Weather:** {weather_text}
318
  **Attractions available:**
 
320
  {source_note}
321
  **Budget:** {budget_text if budget_text else 'Not specified'}
322
 
323
+ *Since the AI service is unavailable (API key missing or quota exceeded), please use the above information to plan your trip manually. You can search for opening hours, entry fees, and book activities online.*
324
 
325
  ๐Ÿ›๏ธ [Search Hotels on Booking.com](https://www.booking.com/searchresults.html?ss={destination.replace(' ', '+')})
326
  โœˆ๏ธ [Search Flights on Skyscanner](https://www.skyscanner.co.in/)
 
349
  gr.Markdown("""
350
  # ๐ŸŒ TouristGuide AI Agent
351
  Your personal travel planner powered by real-time weather, attractions, and OpenAI.
352
+ Works for **any city** โ€“ if no local data, it uses SerpAPI or OpenAI to suggest attractions.
353
  """)
354
  with gr.Row():
355
  destination = gr.Textbox(label="Destination (any city)", placeholder="e.g., Paris, Tokyo, New York", scale=2)