Spaces:
Sleeping
Sleeping
| from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel, load_tool, tool | |
| import datetime | |
| import time | |
| import requests | |
| import pytz | |
| import yaml | |
| import random | |
| from tools.final_answer import FinalAnswerTool | |
| from Gradio_UI import GradioUI | |
| import os | |
| # Global cache for forecasts per city to avoid refetching within a certain duration (10 minutes) | |
| cached_forecasts = {} # Dictionary mapping city name -> { "data": str, "timestamp": int } | |
| CACHE_DURATION_MS = 10 * 60 * 1000 # 10 minutes in milliseconds | |
| def get_current_time_in_timezone(timezone: str = "UTC") -> str: | |
| """ | |
| A tool to get the current time in a specific timezone. | |
| Args: | |
| timezone (str): The timezone string. E.g., 'America/New_York' | |
| Returns: | |
| str: The local time in the specified timezone. | |
| """ | |
| try: | |
| tz = pytz.timezone(timezone) | |
| now = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S") | |
| return f"Local time in {timezone}: {now}" | |
| except Exception: | |
| return "Invalid timezone" | |
| def get_weather_forecast(city: str = "New York", days: int = 7) -> str: | |
| """ | |
| A tool to fetch a weekly weather forecast for a specified city. | |
| This function first checks for a cached forecast for the given city. If the cached | |
| data is older than 10 minutes, it attempts to fetch new data from OpenWeatherMap. | |
| If a valid API key is not provided or an error occurs during the API call, | |
| a mock forecast is generated. | |
| Args: | |
| city (str): The city name for which to get the weather. | |
| days (int): Number of days to forecast (maximum of 7). | |
| Returns: | |
| str: A formatted summary forecast with daily averages. | |
| """ | |
| global cached_forecasts | |
| now_ms = int(time.time() * 1000) | |
| # Check for a valid cache | |
| if city in cached_forecasts and now_ms - cached_forecasts[city]["timestamp"] < CACHE_DURATION_MS: | |
| return cached_forecasts[city]["data"] | |
| # Use a real API key in production | |
| api_key = os.environ.get("OPENWEATHER_API", None) # This should be defined/assigned earlier | |
| # For debugging: print the API key value (remove or secure in production) | |
| print("DEBUG: API key used =", api_key) | |
| # Validate API key before proceeding | |
| if not api_key: | |
| return "Error: Invalid or missing OpenWeather API key. Please configure a valid API key." | |
| url = f"http://api.openweathermap.org/data/2.5/forecast?q={city}&appid={api_key}&units=metric" | |
| try: | |
| response = requests.get(url) | |
| data = response.json() | |
| if data.get("cod") != "200": | |
| raise ValueError(data.get("message", "Error fetching weather data")) | |
| # Process and group forecast items by day (format: YYYY-MM-DD) | |
| forecast_by_day = {} | |
| for item in data.get("list", []): | |
| dt = datetime.datetime.utcfromtimestamp(item["dt"]) | |
| day_str = dt.strftime("%Y-%m-%d") | |
| forecast_by_day.setdefault(day_str, []).append(item) | |
| # Build forecast for up to 'days' days | |
| sorted_days = sorted(forecast_by_day.keys())[:min(days, 7)] | |
| daily_forecasts = [] | |
| for day_str in sorted_days: | |
| day_items = forecast_by_day[day_str] | |
| date_obj = datetime.datetime.strptime(day_str, "%Y-%m-%d") | |
| day_name = date_obj.strftime("%A") | |
| date_display = date_obj.strftime("%b %d") | |
| total_temp = total_humidity = total_pressure = total_wind = 0 | |
| condition_counts = {} | |
| for item in day_items: | |
| total_temp += item["main"]["temp"] | |
| total_humidity += item["main"]["humidity"] | |
| total_pressure += item["main"]["pressure"] | |
| total_wind += item["wind"]["speed"] | |
| condition = item["weather"][0]["description"] | |
| condition_counts[condition] = condition_counts.get(condition, 0) + 1 | |
| count = len(day_items) | |
| avg_temp = round(total_temp / count) | |
| avg_humidity = round(total_humidity / count) | |
| avg_pressure = round(total_pressure / count) | |
| avg_wind = round((total_wind / count) * 3.6) # Convert m/s to km/h | |
| most_common_condition = max(condition_counts.items(), key=lambda x: x[1])[0] | |
| daily_forecasts.append( | |
| f"{day_name}, {date_display}: {avg_temp}°C, {most_common_condition} | Humidity: {avg_humidity}% | Pressure: {avg_pressure} hPa | Wind: {avg_wind} km/h" | |
| ) | |
| forecast_data = "\n".join(daily_forecasts) | |
| except Exception as error: | |
| # Log the error and return an error message | |
| print("Error fetching forecast from API:", error) | |
| return f"Error: Unable to fetch weather data. Reason: {error}" | |
| # Cache the forecast data | |
| cached_forecasts[city] = { | |
| "data": forecast_data, | |
| "timestamp": now_ms | |
| } | |
| return forecast_data | |
| final_answer = FinalAnswerTool() | |
| model = HfApiModel( | |
| max_tokens=2096, | |
| temperature=0.5, | |
| model_id='Qwen/Qwen2.5-Coder-32B-Instruct', | |
| custom_role_conversions=None, | |
| ) | |
| # Import a text-to-image tool from the hub, if desired. | |
| image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True) | |
| with open("prompts.yaml", 'r') as stream: | |
| prompt_templates = yaml.safe_load(stream) | |
| agent = CodeAgent( | |
| model=model, | |
| tools=[final_answer, get_current_time_in_timezone, get_weather_forecast], | |
| max_steps=6, | |
| verbosity_level=1, | |
| grammar=None, | |
| planning_interval=None, | |
| name=None, | |
| description=None, | |
| prompt_templates=prompt_templates | |
| ) | |
| GradioUI(agent).launch() |