vovarbv's picture
Update app.py
3525044 verified
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
@tool
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"
@tool
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()