ArslanFOX commited on
Commit
ac57ee0
·
verified ·
1 Parent(s): 61093db

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +108 -137
app.py CHANGED
@@ -6,22 +6,17 @@ import gradio as gr
6
  from geopy.geocoders import Nominatim
7
  from timezonefinder import TimezoneFinder
8
  import requests
 
9
 
10
  @tool
11
  def get_timezone_by_city(city: str) -> str:
12
- """Tool to fetch the timezone for a given city using geolocation.
13
- Args:
14
- city: A string representing the city name, optionally with region or country (e.g., 'Бураево', 'Осиновка, Бирский район', 'Идиофа, Африка').
15
- Returns:
16
- A string with the timezone (e.g., 'Europe/Samara') or an error message.
17
- """
18
  if not isinstance(city, str):
19
  return f"Error: Expected a string for city, got: {type(city)}"
20
  try:
21
  geolocator = Nominatim(user_agent="smolagents_bot")
22
  location = geolocator.geocode(city, language="en")
23
  if not location:
24
- city_name = city.split(",")[0].strip()
25
  location = geolocator.geocode(city_name, language="en")
26
  if not location:
27
  return f"Error: City '{city}' not found. Try a different spelling or provide more context."
@@ -35,34 +30,24 @@ def get_timezone_by_city(city: str) -> str:
35
 
36
  @tool
37
  def get_current_time_in_timezone(timezone: str) -> str:
38
- """Tool to fetch the current local time in a specified timezone.
39
- Args:
40
- timezone: A string representing a valid timezone (e.g., 'Europe/Moscow').
41
- """
42
  if not isinstance(timezone, str):
43
  return f"Error: Expected a string for timezone, got: {type(timezone)}"
44
  try:
45
  tz = pytz.timezone(timezone)
46
  local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
47
- return f"Current time in {timezone}: {local_time}"
48
  except Exception as e:
49
  return f"Error fetching time for timezone '{timezone}': {str(e)}"
50
 
51
  @tool
52
- def get_air_quality(city: str) -> str:
53
- """Tool to fetch air quality data for a given city using OpenWeatherMap API.
54
- Args:
55
- city: A string representing the city name (e.g., 'Бирск', 'New York').
56
- Returns:
57
- A string with air quality index (AQI) and pollutant levels or an error message.
58
- """
59
  if not isinstance(city, str):
60
  return f"Error: Expected a string for city, got: {type(city)}"
61
  try:
62
  geolocator = Nominatim(user_agent="smolagents_bot")
63
  location = geolocator.geocode(city, language="en")
64
  if not location:
65
- city_name = city.split(",")[0].strip()
66
  location = geolocator.geocode(city_name, language="en")
67
  if not location:
68
  return f"Error: City '{city}' not found for air quality data."
@@ -76,22 +61,110 @@ def get_air_quality(city: str) -> str:
76
  data = response.json()
77
  aqi = data["list"][0]["main"]["aqi"]
78
  components = data["list"][0]["components"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
- aqi_description = {1: "Good", 2: "Fair", 3: "Moderate", 4: "Poor", 5: "Very Poor"}
81
  return (
82
- f"Air quality in {city}: AQI {aqi} ({aqi_description.get(aqi, 'Unknown')})\n"
83
- f"PM2.5: {components['pm2_5']} µg/m³, PM10: {components['pm10']} µg/m³\n"
84
- f"CO: {components['co']} µg/m³, NO2: {components['no2']} µg/m³, SO2: {components['so2']} µg/m³, O3: {components['o3']} µg/m³"
 
 
 
 
85
  )
86
  except Exception as e:
87
  return f"Error fetching air quality for '{city}': {str(e)}"
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  @tool
90
  def final_answer(answer: str) -> str:
91
- """Returns the final answer.
92
- Args:
93
- answer: The final answer as a string.
94
- """
95
  return answer
96
 
97
  try:
@@ -106,115 +179,13 @@ except Exception as e:
106
  prompt_templates = {
107
  "system_prompt": (
108
  "You are a helpful assistant that responds in the same language as the user's query. "
109
- "Detect the language and return only the result, without explanations, images, or repeating instructions. "
110
- "If the query contains a city name (e.g., 'Бураево', 'Осиновка', 'Fosnavåg', 'न्यू यॉर्क') or phrases like 'сколько времени', 'what time', 'quelle heure', "
111
- "or if a city is mentioned in any context (e.g., 'Что там в Бирске?'), treat it as a request for the current time and air quality in that city. "
112
- "Use `get_timezone_by_city` to find the timezone, `get_current_time_in_timezone` for the time, and `get_air_quality` for air quality data. "
113
- "Combine results in a single response. "
114
- "Always return the response via `final_answer()` in a code block like this:\n"
115
  "```py\n"
116
  "final_answer('YOUR ANSWER HERE')\n"
117
  "```\n"
118
- "Execute tools in sequence: first call get_timezone_by_city(city), then get_current_time_in_timezone(timezone), then get_air_quality(city). "
119
- "Do NOT include tool calls, formatting like 'Current time in X: ', or invalid dates (e.g., '2023-03-22') inside final_answer(). "
120
- "If the city is not found or the query is unclear (e.g., no city mentioned), return an error message in the same language via final_answer(). "
121
- "NEVER generate code without the ```py``` block or with invalid syntax. "
122
- "Do NOT ask for clarifications or generate responses outside the ```py``` block."
123
- ),
124
- "default": "Response: {{question}}",
125
- "planning": {
126
- "initial_plan": (
127
- "Analyze the query: {{question}}. If it contains a city name or phrases like 'сколько времени', "
128
- "use `get_timezone_by_city`, `get_current_time_in_timezone`, and `get_air_quality`. "
129
- "Write code in a code block:\n"
130
- "```py\n"
131
- "final_answer('YOUR ANSWER HERE')\n"
132
- "```"
133
- ),
134
- "update_plan_pre_messages": (
135
- "Review the query: {{question}}. Adjust the plan if needed. "
136
- "Write code in a code block:\n"
137
- "```py\n"
138
- "final_answer('YOUR ANSWER HERE')\n"
139
- "```"
140
- ),
141
- "update_plan_post_messages": (
142
- "Review the query: {{question}} and results. Adjust the plan if needed. "
143
- "Write code in a code block:\n"
144
- "```py\n"
145
- "final_answer('YOUR ANSWER HERE')\n"
146
- "```"
147
- ),
148
- },
149
- "managed_agent": {
150
- "execute": (
151
- "Execute the task: {{question}}. If it contains a city name or phrases like 'сколько времени', use `get_timezone_by_city`, `get_current_time_in_timezone`, and `get_air_quality`. "
152
- "Write code in a code block:\n"
153
- "```py\n"
154
- "query = '{{question}}'.strip()\n"
155
- "city = query.split(' в ')[-1].strip() if ' в ' in query else query\n"
156
- "timezone = get_timezone_by_city(city)\n"
157
- "if timezone.startswith('Error'):\n"
158
- " final_answer(timezone)\n"
159
- "else:\n"
160
- " time_result = get_current_time_in_timezone(timezone)\n"
161
- " air_result = get_air_quality(city)\n"
162
- " final_answer(time_result + '\\n' + air_result)\n"
163
- "```"
164
- ),
165
- "report": (
166
- "Summarize the execution of the task: {{question}}. "
167
- "Return the result via final_answer() in a code block:\n"
168
- "```py\n"
169
- "final_answer('YOUR ANSWER HERE')\n"
170
- "```"
171
- ),
172
- "task": (
173
- "Define the task based on the query: {{question}}. "
174
- "Return the task definition via final_answer() in a code block:\n"
175
- "```py\n"
176
- "final_answer('YOUR TASK DEFINITION HERE')\n"
177
- "```"
178
- ),
179
- },
180
- "final_answer": {
181
- "pre_messages": (
182
- "Prepare the final response for the query: {{question}}. "
183
- "Return the response via final_answer() in a code block:\n"
184
- "```py\n"
185
- "final_answer('YOUR ANSWER HERE')\n"
186
- "```"
187
- ),
188
- "template": "Final response: {{answer}}",
189
- "post_messages": (
190
- "Review the formatted response for the query: {{question}}. "
191
- "Return the final response via final_answer() in a code block:\n"
192
- "```py\n"
193
- "final_answer('YOUR ANSWER HERE')\n"
194
- "```"
195
- ),
196
- },
197
- }
198
-
199
- agent = CodeAgent(
200
- model=model,
201
- tools=[final_answer, get_current_time_in_timezone, get_timezone_by_city, get_air_quality],
202
- max_steps=3,
203
- verbosity_level=2,
204
- prompt_templates=prompt_templates,
205
- )
206
-
207
- def process_input(user_input):
208
- try:
209
- response = agent.run(user_input)
210
- return response if response else "Error: No response received from the agent."
211
- except Exception as e:
212
- return f"Error: {str(e)}"
213
-
214
- gr.Interface(
215
- fn=process_input,
216
- inputs="text",
217
- outputs="text",
218
- title="Helpful Assistant",
219
- description="Hello! What city or town are you from? I can tell you the time, air quality, and more!"
220
- ).launch()
 
6
  from geopy.geocoders import Nominatim
7
  from timezonefinder import TimezoneFinder
8
  import requests
9
+ from langdetect import detect
10
 
11
  @tool
12
  def get_timezone_by_city(city: str) -> str:
 
 
 
 
 
 
13
  if not isinstance(city, str):
14
  return f"Error: Expected a string for city, got: {type(city)}"
15
  try:
16
  geolocator = Nominatim(user_agent="smolagents_bot")
17
  location = geolocator.geocode(city, language="en")
18
  if not location:
19
+ city_name = city.split(",")[0].strip().title()
20
  location = geolocator.geocode(city_name, language="en")
21
  if not location:
22
  return f"Error: City '{city}' not found. Try a different spelling or provide more context."
 
30
 
31
  @tool
32
  def get_current_time_in_timezone(timezone: str) -> str:
 
 
 
 
33
  if not isinstance(timezone, str):
34
  return f"Error: Expected a string for timezone, got: {type(timezone)}"
35
  try:
36
  tz = pytz.timezone(timezone)
37
  local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
38
+ return local_time
39
  except Exception as e:
40
  return f"Error fetching time for timezone '{timezone}': {str(e)}"
41
 
42
  @tool
43
+ def get_air_quality(city: str, lang: str = "en") -> str:
 
 
 
 
 
 
44
  if not isinstance(city, str):
45
  return f"Error: Expected a string for city, got: {type(city)}"
46
  try:
47
  geolocator = Nominatim(user_agent="smolagents_bot")
48
  location = geolocator.geocode(city, language="en")
49
  if not location:
50
+ city_name = city.split(",")[0].strip().title()
51
  location = geolocator.geocode(city_name, language="en")
52
  if not location:
53
  return f"Error: City '{city}' not found for air quality data."
 
61
  data = response.json()
62
  aqi = data["list"][0]["main"]["aqi"]
63
  components = data["list"][0]["components"]
64
+
65
+ translations = {
66
+ "en": {
67
+ "aqi_desc": {1: "Good", 2: "Fair", 3: "Moderate", 4: "Poor", 5: "Very Poor"},
68
+ "air_quality": "Air quality",
69
+ "pm2_5": "Fine particles (PM2.5)",
70
+ "pm10": "Coarse particles (PM10)",
71
+ "co": "Carbon monoxide (CO)",
72
+ "no2": "Nitrogen dioxide (NO2)",
73
+ "so2": "Sulfur dioxide (SO2)",
74
+ "o3": "Ozone (O3)"
75
+ },
76
+ "ru": {
77
+ "aqi_desc": {1: "Хорошее", 2: "Удовлетворительное", 3: "Среднее", 4: "Плохое", 5: "Очень плохое"},
78
+ "air_quality": "Качество воздуха",
79
+ "pm2_5": "Мелкие частицы (PM2.5)",
80
+ "pm10": "Крупные частицы (PM10)",
81
+ "co": "Угарный газ (CO)",
82
+ "no2": "Диоксид азота (NO2)",
83
+ "so2": "Диоксид серы (SO2)",
84
+ "o3": "Озон (O3)"
85
+ }
86
+ }
87
+ lang = lang if lang in translations else "en"
88
+ t = translations[lang]
89
+ aqi_emoji = "🌱" if aqi <= 2 else "😷" if aqi <= 4 else "☣️"
90
 
 
91
  return (
92
+ f"😷 {t['air_quality']}: AQI {aqi} ({t['aqi_desc'].get(aqi, 'Unknown')}) {aqi_emoji}\n"
93
+ f"{t['pm2_5']}: {components['pm2_5']} µg/m³\n"
94
+ f"{t['pm10']}: {components['pm10']} µg/m³\n"
95
+ f"{t['co']}: {components['co']} µg/m³\n"
96
+ f"{t['no2']}: {components['no2']} µg/m³\n"
97
+ f"{t['so2']}: {components['so2']} µg/m³\n"
98
+ f"{t['o3']}: {components['o3']} µg/m³"
99
  )
100
  except Exception as e:
101
  return f"Error fetching air quality for '{city}': {str(e)}"
102
 
103
+ @tool
104
+ def get_weather(city: str, lang: str = "en") -> str:
105
+ if not isinstance(city, str):
106
+ return f"Error: Expected a string for city, got: {type(city)}"
107
+ try:
108
+ geolocator = Nominatim(user_agent="smolagents_bot")
109
+ location = geolocator.geocode(city, language="en")
110
+ if not location:
111
+ city_name = city.split(",")[0].strip().title()
112
+ location = geolocator.geocode(city_name, language="en")
113
+ if not location:
114
+ return f"Error: City '{city}' not found for weather data."
115
+
116
+ api_key = os.getenv("OPENWEATHERMAP_API_KEY", "93f518fda8d24cf89aee7050c26b27e9")
117
+ url = f"http://api.openweathermap.org/data/2.5/weather?lat={location.latitude}&lon={location.longitude}&appid={api_key}&units=metric"
118
+ response = requests.get(url)
119
+ if response.status_code != 200:
120
+ return f"Error fetching weather for '{city}': API returned status {response.status_code}"
121
+
122
+ data = response.json()
123
+ temp = data["main"]["temp"]
124
+ description = data["weather"][0]["description"]
125
+ weather_id = data["weather"][0]["id"]
126
+
127
+ translations = {
128
+ "en": {
129
+ "weather": "Weather in",
130
+ "clear": "Clear",
131
+ "clouds": "Cloudy",
132
+ "rain": "Rain",
133
+ "snow": "Snow",
134
+ "thunderstorm": "Thunderstorm",
135
+ "mist": "Mist"
136
+ },
137
+ "ru": {
138
+ "weather": "Погода в",
139
+ "clear": "Ясно",
140
+ "clouds": "Облачно",
141
+ "rain": "Дождь",
142
+ "snow": "Снег",
143
+ "thunderstorm": "Гроза",
144
+ "mist": "Туман"
145
+ }
146
+ }
147
+ lang = lang if lang in translations else "en"
148
+ t = translations[lang]
149
+
150
+ weather_emoji = {
151
+ "2": "⛈️", # Thunderstorm
152
+ "3": "🌧️", # Drizzle
153
+ "5": "🌧️", # Rain
154
+ "6": "❄️", # Snow
155
+ "7": "🌫️", # Mist
156
+ "800": "☀️", # Clear
157
+ "8": "☁️" # Clouds
158
+ }
159
+ emoji = weather_emoji.get(str(weather_id)[0], "🌤️") if weather_id != 800 else weather_emoji.get("800")
160
+
161
+ desc_trans = t.get(description, description.capitalize())
162
+ return f"🌤️ {t['weather']} {city}: {temp}°C, {desc_trans} {emoji}"
163
+ except Exception as e:
164
+ return f"Error fetching weather for '{city}': {str(e)}"
165
+
166
  @tool
167
  def final_answer(answer: str) -> str:
 
 
 
 
168
  return answer
169
 
170
  try:
 
179
  prompt_templates = {
180
  "system_prompt": (
181
  "You are a helpful assistant that responds in the same language as the user's query. "
182
+ "If the query contains a city name (e.g., 'Бураево', 'Sydney', 'न्यू यॉर्क') or phrases like 'сколько времени', 'what time', "
183
+ "or a city in any context (e.g., 'Что там в Бирске?'), return current time, air quality, and weather for that city. "
184
+ "Use `get_timezone_by_city`, `get_current_time_in_timezone`, `get_air_quality`, and `get_weather`. "
185
+ "Detect query language and pass it to `get_air_quality` and `get_weather` for translated output. "
186
+ "Return only the result via `final_answer()` in a code block:\n"
 
187
  "```py\n"
188
  "final_answer('YOUR ANSWER HERE')\n"
189
  "```\n"
190
+ "Do NOT include 'thoughts', 'code', explanations, or invalid dates. "
191
+ "If the city is not found or