YenLai commited on
Commit
ca69d52
·
verified ·
1 Parent(s): 7199aa9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +254 -60
app.py CHANGED
@@ -10,18 +10,39 @@ from Gradio_UI import GradioUI
10
  # Below is an example of a tool that does nothing. Amaze us with your creativity !
11
  @tool
12
  def get_current_time_in_timezone(timezone: str) -> str:
13
- """A tool that fetches the current local time in a specified timezone.
14
  Args:
15
- timezone: A string representing a valid timezone (e.g., 'America/New_York').
16
  """
17
  try:
 
 
 
 
 
 
 
 
18
  # Create timezone object
19
  tz = pytz.timezone(timezone)
20
  # Get current time in that timezone
21
  local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
22
- return f"The current local time in {timezone} is: {local_time}"
 
 
 
 
 
 
 
 
 
23
  except Exception as e:
24
- return f"Error fetching time for timezone '{timezone}': {str(e)}"
 
 
 
 
25
 
26
  @tool
27
  def get_sunrise_time(location: str, date: str = "today") -> str:
@@ -31,57 +52,111 @@ def get_sunrise_time(location: str, date: str = "today") -> str:
31
  date: Date string (e.g., "2023-12-25" or "today" for current date)
32
  """
33
  try:
34
- # Use Sunrise-Sunset API to get sunrise data
35
- if date == "today":
36
- date_param = "" # API defaults to today
 
 
 
 
 
 
 
 
37
  else:
38
- date_param = f"&date={date}"
39
 
40
  # Check if location is in coordinate format
41
  if "," in location and all(part.replace('.', '', 1).replace('-', '', 1).isdigit() for part in location.split(',')):
42
  lat, lng = location.split(',')
 
43
  else:
44
  # Use Nominatim API for geocoding (convert location name to coordinates)
45
- geo_response = requests.get(f"https://nominatim.openstreetmap.org/search?q={location}&format=json&limit=1")
46
- geo_data = geo_response.json()
47
-
48
- if not geo_data:
49
- return f"Could not find location: {location}"
 
50
 
51
- lat = geo_data[0]['lat']
52
- lng = geo_data[0]['lon']
53
-
54
- # Use coordinates to get sunrise data
55
- response = requests.get(f"https://api.sunrise-sunset.org/json?lat={lat}&lng={lng}{date_param}&formatted=0")
56
- data = response.json()
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
- if data['status'] != 'OK':
59
- return f"Error getting sunrise data: {data['status']}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
  # Process sunrise times (convert from UTC to local time)
62
  sunrise_utc = datetime.datetime.fromisoformat(data['results']['sunrise'].replace('Z', '+00:00'))
63
  civil_twilight_utc = datetime.datetime.fromisoformat(data['results']['civil_twilight_begin'].replace('Z', '+00:00'))
64
 
65
  # Get timezone for the location (using timezonefinder library)
66
- from timezonefinder import TimezoneFinder
67
- tf = TimezoneFinder()
68
- timezone_str = tf.certain_timezone_at(lat=float(lat), lng=float(lng))
69
-
70
- if not timezone_str:
 
 
 
 
 
 
 
 
 
 
 
 
71
  timezone = pytz.UTC
72
  timezone_name = "UTC"
73
- else:
74
- timezone = pytz.timezone(timezone_str)
75
- timezone_name = timezone_str
76
 
77
  # Convert to local time
78
  sunrise_local = sunrise_utc.astimezone(timezone)
79
  civil_twilight_local = civil_twilight_utc.astimezone(timezone)
80
 
81
- # Calculate best shooting time (typically from civil twilight to sunrise)
82
- best_start = civil_twilight_local
83
- best_end = sunrise_local
84
-
85
  # Calculate golden hour (about 30 minutes after sunrise)
86
  golden_hour_end = sunrise_local + datetime.timedelta(minutes=30)
87
 
@@ -107,16 +182,22 @@ def get_sunrise_time(location: str, date: str = "today") -> str:
107
  else: # Winter
108
  season = "Winter"
109
  season_tip = "Winter sunrises come later with cooler light. Stay warm and bring extra batteries as cold temperatures drain them faster."
110
-
111
- # Generate photography tips
112
- photography_tips = [
113
- f"Best arrival time: {civil_twilight_time} (civil twilight begins)",
114
- f"Sunrise time: {sunrise_time}",
115
- f"Golden light ends: {golden_hour_end_time}",
116
- f"{season} photography tip: {season_tip}",
117
- "Recommended gear: Tripod (essential), Variable ND filter, Remote shutter, Extra batteries",
 
 
 
 
 
 
118
  "Composition tip: Look for interesting foreground elements, don't just focus on the sky",
119
- "For best exposure, use bracketing (HDR) or graduated filters"
120
  ]
121
 
122
  # Add a humorous tip
@@ -131,31 +212,138 @@ def get_sunrise_time(location: str, date: str = "today") -> str:
131
  "If your photos come out blurry, just tell everyone it's an 'artistic style'.",
132
  "The secret formula for the perfect sunrise shot: Weather forecast accuracy + Luck × Preparation ÷ Snooze button index"
133
  ]
134
- photography_tips.append(random.choice(humor_tips))
135
 
136
- # Return formatted results
137
  result = f"== Sunrise Photography Guide for {location} ==\n\n"
138
- result += "\n".join(photography_tips)
139
 
140
- return result
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
 
142
  except Exception as e:
143
- return f"Error getting sunrise information: {str(e)}"
 
 
 
 
144
 
145
- final_answer = FinalAnswerTool()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
- # If the agent does not answer, the model is overloaded, please use another model or the following Hugging Face Endpoint that also contains qwen2.5 coder:
148
- # model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
 
 
 
 
150
  model = HfApiModel(
151
- max_tokens=2096,
152
- temperature=0.5,
153
- model_id='Qwen/Qwen2.5-Coder-32B-Instruct',# it is possible that this model may be overloaded
154
- custom_role_conversions=None,
155
  )
156
 
157
-
158
- # Import tool from Hub
159
  image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
160
 
161
  with open("prompts.yaml", 'r') as stream:
@@ -163,15 +351,21 @@ with open("prompts.yaml", 'r') as stream:
163
 
164
  agent = CodeAgent(
165
  model=model,
166
- tools=[final_answer], ## add your tools here (don't remove final answer)
 
 
 
 
 
 
 
167
  max_steps=6,
168
  verbosity_level=1,
169
  grammar=None,
170
  planning_interval=None,
171
- name=None,
172
- description=None,
173
  prompt_templates=prompt_templates
174
  )
175
 
176
-
177
  GradioUI(agent).launch()
 
10
  # Below is an example of a tool that does nothing. Amaze us with your creativity !
11
  @tool
12
  def get_current_time_in_timezone(timezone: str) -> str:
13
+ """Get the current time in a specified timezone.
14
  Args:
15
+ timezone: A valid timezone string (e.g., 'America/New_York', 'Asia/Tokyo').
16
  """
17
  try:
18
+ # Validate timezone
19
+ if timezone not in pytz.all_timezones:
20
+ return json.dumps({
21
+ "status": "error",
22
+ "message": f"Invalid timezone: '{timezone}'. Please provide a valid timezone like 'America/New_York'.",
23
+ "data_source": "none"
24
+ })
25
+
26
  # Create timezone object
27
  tz = pytz.timezone(timezone)
28
  # Get current time in that timezone
29
  local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
30
+
31
+ return json.dumps({
32
+ "status": "success",
33
+ "message": f"The current time in {timezone} is: {local_time}",
34
+ "data": {
35
+ "timezone": timezone,
36
+ "current_time": local_time
37
+ },
38
+ "data_source": "system_time"
39
+ })
40
  except Exception as e:
41
+ return json.dumps({
42
+ "status": "error",
43
+ "message": f"Error fetching time for timezone '{timezone}': {str(e)}",
44
+ "data_source": "none"
45
+ })
46
 
47
  @tool
48
  def get_sunrise_time(location: str, date: str = "today") -> str:
 
52
  date: Date string (e.g., "2023-12-25" or "today" for current date)
53
  """
54
  try:
55
+ # Validate date format if not "today"
56
+ if date != "today":
57
+ try:
58
+ datetime.datetime.strptime(date, "%Y-%m-%d")
59
+ date_param = f"&date={date}"
60
+ except ValueError:
61
+ return json.dumps({
62
+ "status": "error",
63
+ "message": f"Invalid date format: '{date}'. Please use YYYY-MM-DD format or 'today'.",
64
+ "data_source": "none"
65
+ })
66
  else:
67
+ date_param = ""
68
 
69
  # Check if location is in coordinate format
70
  if "," in location and all(part.replace('.', '', 1).replace('-', '', 1).isdigit() for part in location.split(',')):
71
  lat, lng = location.split(',')
72
+ location_source = "user_coordinates"
73
  else:
74
  # Use Nominatim API for geocoding (convert location name to coordinates)
75
+ try:
76
+ geo_response = requests.get(
77
+ f"https://nominatim.openstreetmap.org/search?q={location}&format=json&limit=1",
78
+ headers={"User-Agent": "SunrisePhotographyAssistant/1.0"}
79
+ )
80
+ geo_data = geo_response.json()
81
 
82
+ if not geo_data:
83
+ return json.dumps({
84
+ "status": "error",
85
+ "message": f"Could not find location: {location}. Please try using coordinates or check the spelling.",
86
+ "data_source": "none"
87
+ })
88
+
89
+ lat = geo_data[0]['lat']
90
+ lng = geo_data[0]['lon']
91
+ location_source = "openstreetmap_geocoding"
92
+ # Get the properly formatted name from OSM
93
+ location_name = geo_data[0].get('display_name', location)
94
+ except Exception as e:
95
+ return json.dumps({
96
+ "status": "error",
97
+ "message": f"Error geocoding location '{location}': {str(e)}",
98
+ "data_source": "none"
99
+ })
100
 
101
+ # Use coordinates to get sunrise data
102
+ try:
103
+ response = requests.get(f"https://api.sunrise-sunset.org/json?lat={lat}&lng={lng}{date_param}&formatted=0")
104
+ data = response.json()
105
+
106
+ if data.get('status') != 'OK':
107
+ return json.dumps({
108
+ "status": "error",
109
+ "message": f"Error getting sunrise data: {data.get('status', 'Unknown error')}",
110
+ "data_source": "none"
111
+ })
112
+
113
+ # Validate required fields
114
+ required_fields = ['sunrise', 'civil_twilight_begin']
115
+ for field in required_fields:
116
+ if field not in data.get('results', {}):
117
+ return json.dumps({
118
+ "status": "error",
119
+ "message": f"Missing required data field: {field}",
120
+ "data_source": "none"
121
+ })
122
+ except Exception as e:
123
+ return json.dumps({
124
+ "status": "error",
125
+ "message": f"Error fetching sunrise data: {str(e)}",
126
+ "data_source": "none"
127
+ })
128
 
129
  # Process sunrise times (convert from UTC to local time)
130
  sunrise_utc = datetime.datetime.fromisoformat(data['results']['sunrise'].replace('Z', '+00:00'))
131
  civil_twilight_utc = datetime.datetime.fromisoformat(data['results']['civil_twilight_begin'].replace('Z', '+00:00'))
132
 
133
  # Get timezone for the location (using timezonefinder library)
134
+ try:
135
+ from timezonefinder import TimezoneFinder
136
+ tf = TimezoneFinder()
137
+ timezone_str = tf.certain_timezone_at(lat=float(lat), lng=float(lng))
138
+
139
+ if not timezone_str:
140
+ timezone = pytz.UTC
141
+ timezone_name = "UTC"
142
+ timezone_confidence = "low"
143
+ timezone_note = "(Note: Could not determine exact local timezone, using UTC instead)"
144
+ else:
145
+ timezone = pytz.timezone(timezone_str)
146
+ timezone_name = timezone_str
147
+ timezone_confidence = "high"
148
+ timezone_note = ""
149
+ except Exception as e:
150
+ # Fallback to UTC if timezone lookup fails
151
  timezone = pytz.UTC
152
  timezone_name = "UTC"
153
+ timezone_confidence = "fallback"
154
+ timezone_note = f"(Note: Error determining timezone: {str(e)}. Using UTC instead)"
 
155
 
156
  # Convert to local time
157
  sunrise_local = sunrise_utc.astimezone(timezone)
158
  civil_twilight_local = civil_twilight_utc.astimezone(timezone)
159
 
 
 
 
 
160
  # Calculate golden hour (about 30 minutes after sunrise)
161
  golden_hour_end = sunrise_local + datetime.timedelta(minutes=30)
162
 
 
182
  else: # Winter
183
  season = "Winter"
184
  season_tip = "Winter sunrises come later with cooler light. Stay warm and bring extra batteries as cold temperatures drain them faster."
185
+
186
+ # Generate factual data section
187
+ factual_data = [
188
+ f"Sunrise time: {sunrise_time} {timezone_note}",
189
+ f"Civil twilight begins: {civil_twilight_time}",
190
+ f"Golden light ends approximately: {golden_hour_end_time}",
191
+ f"Current season: {season}"
192
+ ]
193
+
194
+ # Generate photography recommendations
195
+ photography_recommendations = [
196
+ f"Recommended arrival time: Civil twilight ({civil_twilight_time})",
197
+ f"{season} photography consideration: {season_tip}",
198
+ "Suggested gear: Tripod (essential), Variable ND filter, Remote shutter, Extra batteries",
199
  "Composition tip: Look for interesting foreground elements, don't just focus on the sky",
200
+ "For best exposure, consider bracketing (HDR) or graduated filters"
201
  ]
202
 
203
  # Add a humorous tip
 
212
  "If your photos come out blurry, just tell everyone it's an 'artistic style'.",
213
  "The secret formula for the perfect sunrise shot: Weather forecast accuracy + Luck × Preparation ÷ Snooze button index"
214
  ]
 
215
 
216
+ # Build final output
217
  result = f"== Sunrise Photography Guide for {location} ==\n\n"
 
218
 
219
+ result += "FACTUAL DATA (from sunrise-sunset.org):\n"
220
+ result += "\n".join([f"• {item}" for item in factual_data])
221
+ result += "\n\n"
222
+
223
+ result += "PHOTOGRAPHY RECOMMENDATIONS:\n"
224
+ result += "\n".join([f"• {item}" for item in photography_recommendations])
225
+ result += "\n\n"
226
+
227
+ result += "HUMOR TIP:\n"
228
+ result += f"• {random.choice(humor_tips)}\n\n"
229
+
230
+ result += "NOTE: Weather conditions can significantly affect photography opportunities and are not predicted by this tool."
231
+
232
+ # Prepare data for structured output
233
+ output_data = {
234
+ "status": "success",
235
+ "message": result,
236
+ "data": {
237
+ "location": location,
238
+ "date": date if date != "today" else datetime.datetime.now().strftime("%Y-%m-%d"),
239
+ "sunrise_time": sunrise_time,
240
+ "civil_twilight_time": civil_twilight_time,
241
+ "golden_hour_end_time": golden_hour_end_time,
242
+ "timezone": timezone_name,
243
+ "season": season
244
+ },
245
+ "data_sources": {
246
+ "location": location_source,
247
+ "astronomy": "sunrise-sunset.org",
248
+ "timezone": f"timezonefinder ({timezone_confidence} confidence)"
249
+ }
250
+ }
251
+
252
+ return json.dumps(output_data)
253
 
254
  except Exception as e:
255
+ return json.dumps({
256
+ "status": "error",
257
+ "message": f"Error processing request: {str(e)}",
258
+ "data_source": "none"
259
+ })
260
 
261
+ @tool
262
+ def get_photography_tip() -> str:
263
+ """Get a random sunrise photography tip."""
264
+ tips = [
265
+ "Arrive 45 minutes before sunrise to set up your equipment and have time to adjust your composition.",
266
+ "Don't just shoot at the moment of sunrise - the light changes before and after are equally worth capturing.",
267
+ "Use a tripod and remote shutter for sharp photos in low light conditions.",
268
+ "Try using foreground elements (trees, rocks, lake reflections) to add depth to your photo.",
269
+ "Use smartphone apps to predict the sunrise direction at your location and plan your composition in advance.",
270
+ "Cloudy days can produce spectacular sunrise photos - don't abandon your shoot just because there's no clear sky.",
271
+ "Light changes rapidly during sunrise - use exposure bracketing (HDR) to ensure you capture enough dynamic range.",
272
+ "Consider using a telephoto lens for sunrise shots to magnify the sun and highlight atmospheric effects near the horizon.",
273
+ "Bring graduated ND filters to balance the bright sky with a darker foreground.",
274
+ "Research your location before traveling, understanding the sun's direction and terrain to find the best shooting spots.",
275
+ "Try shooting panoramas to capture the full range of colors in the sky during sunrise.",
276
+ "Shoot in RAW format to preserve more possibilities for post-processing.",
277
+ "When shooting sunrise at the beach, check tide schedules to plan your best shooting position.",
278
+ "Winter sunrises often have the most dramatic colors and longest golden hour periods.",
279
+ "City sunrises can be spectacular - look for elevated positions that show the city skyline.",
280
+ "In windy weather, add weight to your tripod to prevent camera shake during sunrise shoots.",
281
+ "Use interval shooting (time-lapse) to document the entire sunrise process.",
282
+ "Having the sky occupy 2/3 of your composition often creates more dramatic sunrise photos.",
283
+ "During sunrise, sunlight has a reddish-yellow tone. Try setting your white balance to 'cloudy' to preserve these colors.",
284
+ "If you want to capture star trails and sunrise in one composition, you'll need a star tracker and multiple exposure techniques."
285
+ ]
286
+
287
+ # Add some humorous "rescue" tips
288
+ rescue_tips = [
289
+ "If you overslept and missed the sunrise, don't worry! Claim you're practicing 'minimalist photography' - not shooting is the ultimate art form.",
290
+ "Lens fogged up? Tell everyone you invented the 'dream filter effect' - it might be trending next week.",
291
+ "If you took 100 photos and none are satisfactory, convert them to black and white - photographers call this 'artistic redemption'.",
292
+ "Forgot your memory card? Congratulations on experiencing 'mindful photography' - recording the moment with your eyes and heart.",
293
+ "Sun hiding behind clouds and not coming out? Claim you were actually there to shoot 'cloud portraits' all along.",
294
+ "Forgot to adjust ISO and got noisy photos? No problem, call it 'digital grain' and claim it's your signature style.",
295
+ "If your sunrise photos look bland, try this pro tip: Add filters until it looks like an alien sunset, then post on social media with #NoFilter.",
296
+ "Tripod collapsed? That's the universe telling you it's time to try 'stream of consciousness photography'."
297
+ ]
298
+
299
+ # 20% chance to return a "rescue" tip
300
+ if random.random() < 0.2:
301
+ tip = random.choice(rescue_tips)
302
+ tip_type = "humorous_rescue"
303
+ else:
304
+ tip = random.choice(tips)
305
+ tip_type = "practical"
306
+
307
+ return json.dumps({
308
+ "status": "success",
309
+ "message": tip,
310
+ "data": {
311
+ "tip": tip,
312
+ "tip_type": tip_type
313
+ },
314
+ "data_source": "curated_collection"
315
+ })
316
 
317
+ @tool
318
+ def parse_response(response_json: str) -> str:
319
+ """Helper tool to parse JSON responses and format them for user display.
320
+ Args:
321
+ response_json: JSON string from one of the other tools
322
+ """
323
+ try:
324
+ data = json.loads(response_json)
325
+
326
+ # Simply return the message for successful responses
327
+ if data.get("status") == "success":
328
+ return data.get("message", "Operation completed successfully, but no message was provided.")
329
+ else:
330
+ # For error responses, provide a clear error message
331
+ return f"ERROR: {data.get('message', 'An unknown error occurred.')}"
332
+
333
+ except Exception as e:
334
+ return f"Error parsing response: {str(e)}"
335
 
336
+ final_answer = FinalAnswerTool()
337
+
338
+ # Model setup
339
  model = HfApiModel(
340
+ max_tokens=2096,
341
+ temperature=0.5,
342
+ model_id='Qwen/Qwen2.5-Coder-32B-Instruct',
343
+ custom_role_conversions=None,
344
  )
345
 
346
+ # Import image generation tool from Hub
 
347
  image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
348
 
349
  with open("prompts.yaml", 'r') as stream:
 
351
 
352
  agent = CodeAgent(
353
  model=model,
354
+ tools=[
355
+ get_current_time_in_timezone,
356
+ get_sunrise_time,
357
+ get_photography_tip,
358
+ parse_response, # Add helper tool for parsing
359
+ image_generation_tool,
360
+ final_answer
361
+ ],
362
  max_steps=6,
363
  verbosity_level=1,
364
  grammar=None,
365
  planning_interval=None,
366
+ name="Sunrise Photography Assistant",
367
+ description="An intelligent assistant that helps photographers find the best times for sunrise photography and provides professional advice",
368
  prompt_templates=prompt_templates
369
  )
370
 
 
371
  GradioUI(agent).launch()