File size: 7,637 Bytes
ba960dd
 
 
 
 
 
 
 
 
 
 
 
db72768
ba960dd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
db72768
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
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