Journi-09032025 / tools /get_weather_forecast.py
PLBot's picture
Update tools/get_weather_forecast.py
db72768 verified
raw
history blame contribute delete
7.64 kB
from typing import Any, Optional
from smolagents.tools import Tool
import datetime
import random
import os
import requests
class GetWeatherForecastTool(Tool):
name = "get_weather_forecast"
description = "Gets the weather forecast for a travel destination."
inputs = {
'destination': {'type': 'string', 'description': 'City or location name'},
'days': {'type': 'integer', 'description': 'Number of days to forecast (default: 3)', 'nullable': True}
}
output_type = "string"
def __init__(self, api_key=None):
super().__init__()
# You can set an API key for a real weather service like OpenWeatherMap
self.api_key = api_key or os.environ.get("WEATHER_API_KEY")
# Weather conditions for demo/fallback
self.weather_conditions = [
"Sunny", "Partly Cloudy", "Cloudy", "Light Rain",
"Heavy Rain", "Thunderstorms", "Windy", "Foggy", "Snow", "Clear"
]
def forward(self, destination: str, days: int = 3) -> str:
try:
# Try to use a real weather API if the API key is available
if self.api_key:
try:
url = f"http://api.openweathermap.org/data/2.5/forecast?q={destination}&appid={self.api_key}&units=metric"
response = requests.get(url)
data = response.json()
if response.status_code != 200:
# Fall back to demo method if API call fails
return self._generate_demo_forecast(destination, days)
# Process and format forecast data
forecast_text = f"🌦️ Weather forecast for {destination}:\n\n"
# Group forecasts by day
forecasts_by_day = {}
for item in data['list'][:days * 8]: # API returns data in 3-hour intervals
date = item['dt_txt'].split(' ')[0]
if date not in forecasts_by_day:
forecasts_by_day[date] = []
forecasts_by_day[date].append(item)
# Format each day's forecast
for date, items in list(forecasts_by_day.items())[:days]:
day_name = datetime.datetime.strptime(date, "%Y-%m-%d").strftime("%A")
temps = [item['main']['temp'] for item in items]
avg_temp = sum(temps) / len(temps)
conditions = [item['weather'][0]['main'] for item in items]
most_common = max(set(conditions), key=conditions.count)
precipitation = any('Rain' in item['weather'][0]['main'] or 'Snow' in item['weather'][0]['main'] for item in items)
precipitation_chance = "60%" if precipitation else "0%"
forecast_text += f"• {day_name}, {date}: {most_common}, {min(temps):.1f}°C to {max(temps):.1f}°C"
if precipitation:
forecast_text += f", {precipitation_chance} chance of precipitation"
forecast_text += "\n"
# Add packing recommendations
forecast_text += self._generate_packing_tips(forecasts_by_day)
return forecast_text
except Exception:
# Fall back to demo method if any error occurs
return self._generate_demo_forecast(destination, days)
# If no API key is available, use the demo method
return self._generate_demo_forecast(destination, days)
except Exception as e:
return f"Error retrieving weather data for {destination}: {str(e)}"
def _generate_demo_forecast(self, destination: str, days: int) -> str:
# Create a deterministic but seemingly random forecast based on destination name
seed = sum(ord(c) for c in destination)
random.seed(seed)
# Generate forecast data
forecast_text = f"🌦️ Weather forecast for {destination}:\n\n"
today = datetime.datetime.now()
temp_base = random.randint(10, 25) # Base temperature varies by destination
for i in range(days):
day = today + datetime.timedelta(days=i)
day_name = day.strftime("%A")
date = day.strftime("%b %d")
# "Random" but deterministic weather for the demo
condition = self.weather_conditions[random.randint(0, len(self.weather_conditions)-1)]
temp_high = temp_base + random.randint(0, 10) # Celsius
temp_low = temp_high - random.randint(5, 15)
precipitation = random.randint(0, 100) if "Rain" in condition or "Snow" in condition or "Thunder" in condition else 0
forecast_text += f"• {day_name}, {date}: {condition}, {temp_low}°C to {temp_high}°C"
if precipitation > 0:
forecast_text += f", {precipitation}% chance of precipitation"
forecast_text += "\n"
# Add packing recommendations
cold_days = sum(1 for i in range(days) if temp_base + 5 < 15)
rainy_days = sum(1 for i in range(days) if "Rain" in self.weather_conditions[random.randint(0, len(self.weather_conditions)-1)])
hot_days = sum(1 for i in range(days) if temp_base + 5 > 25)
forecast_text += "\n🧳 Packing tips: "
if cold_days > days/2:
forecast_text += "Bring warm layers and a jacket. "
elif cold_days > 0:
forecast_text += "Pack a light jacket for cooler periods. "
if rainy_days > 0:
forecast_text += "Don't forget an umbrella or rain gear. "
if hot_days > days/2:
forecast_text += "Bring sunscreen, sunglasses, and light clothing. "
return forecast_text
def _generate_packing_tips(self, forecasts_by_day):
# Extract temperature ranges across all days
all_temps = []
has_rain = False
has_snow = False
for day_items in forecasts_by_day.values():
for item in day_items:
all_temps.append(item['main']['temp'])
if 'Rain' in item['weather'][0]['main']:
has_rain = True
if 'Snow' in item['weather'][0]['main']:
has_snow = True
min_temp = min(all_temps) if all_temps else 0
max_temp = max(all_temps) if all_temps else 30
# Generate packing tips based on conditions
tips = "\n🧳 Packing tips: "
if min_temp < 5:
tips += "Bring a heavy winter coat, gloves, and hat. "
elif min_temp < 15:
tips += "Pack a warm jacket and layers. "
elif min_temp < 20:
tips += "Bring a light jacket for evenings. "
if max_temp > 25:
tips += "Pack light, breathable clothing for warm days. "
if has_rain:
tips += "Don't forget an umbrella and waterproof footwear. "
if has_snow:
tips += "Bring waterproof boots and warm socks. "
if max_temp > 22:
tips += "Sunscreen and sunglasses are recommended. "
return tips