ChienChung commited on
Commit
9bc707d
·
verified ·
1 Parent(s): e2ed768

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +114 -47
app.py CHANGED
@@ -41,6 +41,7 @@ from tempfile import mkdtemp
41
  from langchain.schema import AIMessage
42
  from datetime import datetime
43
  from zoneinfo import ZoneInfo
 
44
  import numexpr as ne
45
  import pandas as pd
46
 
@@ -53,6 +54,7 @@ from geopy.geocoders import Nominatim
53
  from timezonefinder import TimezoneFinder
54
  from langchain_experimental.agents import create_pandas_dataframe_agent
55
 
 
56
  session_retriever = None
57
  session_qa_chain = None
58
  csv_dataframe = None # CSV tool will use this
@@ -450,83 +452,148 @@ weather_api_key = os.environ.get("WEATHER_API_KEY")
450
 
451
  def weather_agent_tool(query: str) -> str:
452
  try:
 
 
 
 
 
 
 
 
453
  location_prompt = f"""
454
  You are a location extractor. Given a user's query about weather, return the location mentioned in it. If not found, return "London".
455
-
456
  Examples:
457
  - "What's the weather in Tokyo now?" → Tokyo
458
  - "紐約天氣如何?" → New York
459
  - "今天台北下雨嗎?" → Taipei
460
- - "Weather" → London
461
- - "Is it hot today in ldn?" → London
462
-
463
  Now process this query: "{query}"
464
  """
465
  location_response = llm_gpt4.invoke(location_prompt)
466
- if isinstance(location_response, AIMessage):
467
- location = location_response.content.strip()
468
- else:
469
- location = str(location_response).strip()
470
-
471
- url = f"http://api.weatherapi.com/v1/current.json?key={weather_api_key}&q={location}&aqi=no"
472
- response = requests.get(url)
473
- data = response.json()
474
-
475
- if "current" not in data:
476
- return f"Sorry, I couldn't find the weather info for '{location}'."
477
 
478
- current = data["current"]
479
- condition = current["condition"]["text"]
480
- temp_c = current["temp_c"]
481
- humidity = current["humidity"]
482
- wind_kph = current["wind_kph"]
483
- feelslike_c = current["feelslike_c"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
484
 
485
- return f"The current weather in {location.title()} is {condition} with {temp_c}°C, feels like {feelslike_c}°C, humidity {humidity}%, wind {wind_kph} kph."
 
 
 
 
 
 
486
 
487
  except Exception as e:
488
- return f"Weather API error: {e}"
489
 
 
490
  @tool("weather")
491
  def weather_tool(query: str) -> str:
492
- """Weather Agent: Provide real-time weather info for any major city."""
493
  try:
 
 
 
 
 
 
 
 
494
  location_prompt = f"""
495
  You are a location extractor. Given a user's query about weather, return the location mentioned in it. If not found, return "London".
496
-
497
  Examples:
498
  - "What's the weather in Tokyo now?" → Tokyo
499
  - "紐約天氣如何?" → New York
500
  - "今天台北下雨嗎?" → Taipei
501
- - "Weather" → London
502
- - "Is it hot today in ldn?" → London
503
-
504
  Now process this query: "{query}"
505
  """
506
  location_response = llm_gpt4.invoke(location_prompt)
507
- if isinstance(location_response, AIMessage):
508
- location = location_response.content.strip()
509
- else:
510
- location = str(location_response).strip()
511
-
512
- url = f"http://api.weatherapi.com/v1/current.json?key={weather_api_key}&q={location}&aqi=no"
513
- response = requests.get(url)
514
- data = response.json()
515
-
516
- if "current" not in data:
517
- return f"Sorry, I couldn't find the weather info for '{location}'."
518
 
519
- current = data["current"]
520
- condition = current["condition"]["text"]
521
- temp_c = current["temp_c"]
522
- humidity = current["humidity"]
523
- wind_kph = current["wind_kph"]
524
- feelslike_c = current["feelslike_c"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
525
 
526
- return f"The current weather in {location.title()} is {condition} with {temp_c}°C, feels like {feelslike_c}°C, humidity {humidity}%, wind {wind_kph} kph."
 
 
 
 
 
 
527
 
528
  except Exception as e:
529
- return f"Weather API error: {e}"
530
 
531
  @tool("summarise")
532
  def summarise_tool(query: str) -> str:
 
41
  from langchain.schema import AIMessage
42
  from datetime import datetime
43
  from zoneinfo import ZoneInfo
44
+ from dateutil import parser as date_parser
45
  import numexpr as ne
46
  import pandas as pd
47
 
 
54
  from timezonefinder import TimezoneFinder
55
  from langchain_experimental.agents import create_pandas_dataframe_agent
56
 
57
+
58
  session_retriever = None
59
  session_qa_chain = None
60
  csv_dataframe = None # CSV tool will use this
 
452
 
453
  def weather_agent_tool(query: str) -> str:
454
  try:
455
+ from dateutil import parser as date_parser
456
+ from zoneinfo import ZoneInfo
457
+
458
+ weather_api_key = os.environ.get("WEATHER_API_KEY")
459
+ if not weather_api_key:
460
+ return "Weather API key not found. Please set WEATHER_API_KEY env variable."
461
+
462
+ # GPT get location
463
  location_prompt = f"""
464
  You are a location extractor. Given a user's query about weather, return the location mentioned in it. If not found, return "London".
 
465
  Examples:
466
  - "What's the weather in Tokyo now?" → Tokyo
467
  - "紐約天氣如何?" → New York
468
  - "今天台北下雨嗎?" → Taipei
469
+ - "How's the weather?" → London
470
+ - "Is it gon rain in ldn" → London
471
+
472
  Now process this query: "{query}"
473
  """
474
  location_response = llm_gpt4.invoke(location_prompt)
475
+ location = location_response.content.strip() if isinstance(location_response, AIMessage) else str(location_response).strip()
 
 
 
 
 
 
 
 
 
 
476
 
477
+ # get local time
478
+ geo = Nominatim(user_agent="weather_agent_demo")
479
+ loc = geo.geocode(location)
480
+ tf = TimezoneFinder()
481
+ tz_str = tf.timezone_at(lat=loc.latitude, lng=loc.longitude) if loc else "Europe/London"
482
+ local_now = datetime.now(ZoneInfo(tz_str))
483
+ local_now_str = local_now.strftime("%Y-%m-%d %H:%M:%S")
484
+
485
+ # GPT get query time(transfer to Y-M-D)
486
+ time_prompt = f"""
487
+ It is currently {local_now_str} in {location}.
488
+ Based on the query: "{query}", return the intended local date (YYYY-MM-DD).
489
+ Return only a date like 2025-04-04. If unclear, use today.
490
+ """
491
+ date_response = llm_gpt4.invoke(time_prompt)
492
+ date_str = date_response.content.strip() if isinstance(date_response, AIMessage) else str(date_response).strip()
493
+ query_date = date_parser.parse(date_str).date()
494
+ today = local_now.date()
495
+
496
+ # choose to use current / forecast / history API according to time
497
+ if query_date == today:
498
+ url = f"http://api.weatherapi.com/v1/current.json?key={weather_api_key}&q={location}&aqi=no"
499
+ data = requests.get(url).json()
500
+ cur = data["current"]
501
+ return f"The current weather in {location.title()} is {cur['condition']['text']} with {cur['temp_c']}°C (feels like {cur['feelslike_c']}°C), humidity {cur['humidity']}%, wind {cur['wind_kph']} kph."
502
+
503
+ elif query_date > today:
504
+ url = f"http://api.weatherapi.com/v1/forecast.json?key={weather_api_key}&q={location}&days=3"
505
+ data = requests.get(url).json()
506
+ forecast_days = data.get("forecast", {}).get("forecastday", [])
507
+ for day in forecast_days:
508
+ if day["date"] == date_str:
509
+ d = day["day"]
510
+ return f"Forecast for {location.title()} on {query_date.strftime('%A, %B %d')}: {d['condition']['text']}, avg {d['avgtemp_c']}°C, humidity {d['avghumidity']}%, max {d['maxtemp_c']}°C, min {d['mintemp_c']}°C."
511
+ return f"Forecast unavailable for {query_date} (WeatherAPI supports up to 3 days ahead)."
512
 
513
+ else:
514
+ url = f"http://api.weatherapi.com/v1/history.json?key={weather_api_key}&q={location}&dt={date_str}"
515
+ data = requests.get(url).json()
516
+ hist = data.get("forecast", {}).get("forecastday", [{}])[0].get("day", {})
517
+ if not hist:
518
+ return f"Historical weather not found for {location.title()} on {query_date}."
519
+ return f"The weather in {location.title()} on {query_date.strftime('%A, %B %d')}: {hist['condition']['text']}, avg {hist['avgtemp_c']}°C, humidity {hist['avghumidity']}%, max {hist['maxtemp_c']}°C, min {hist['mintemp_c']}°C."
520
 
521
  except Exception as e:
522
+ return f"Weather Agent Error: {e}"
523
 
524
+
525
  @tool("weather")
526
  def weather_tool(query: str) -> str:
527
+ """Weather Agent: Provide real-time, future, or historical weather info (max 3 days forecast, 7 days history)."""
528
  try:
529
+ from dateutil import parser as date_parser
530
+ from zoneinfo import ZoneInfo
531
+
532
+ weather_api_key = os.environ.get("WEATHER_API_KEY")
533
+ if not weather_api_key:
534
+ return "Weather API key not found. Please set WEATHER_API_KEY env variable."
535
+
536
+ # GPT get location
537
  location_prompt = f"""
538
  You are a location extractor. Given a user's query about weather, return the location mentioned in it. If not found, return "London".
 
539
  Examples:
540
  - "What's the weather in Tokyo now?" → Tokyo
541
  - "紐約天氣如何?" → New York
542
  - "今天台北下雨嗎?" → Taipei
543
+ - "How's the weather?" → London
544
+ - "Is it gon rain in ldn" → London
545
+
546
  Now process this query: "{query}"
547
  """
548
  location_response = llm_gpt4.invoke(location_prompt)
549
+ location = location_response.content.strip() if isinstance(location_response, AIMessage) else str(location_response).strip()
 
 
 
 
 
 
 
 
 
 
550
 
551
+ # get local time
552
+ geo = Nominatim(user_agent="weather_agent_demo")
553
+ loc = geo.geocode(location)
554
+ tf = TimezoneFinder()
555
+ tz_str = tf.timezone_at(lat=loc.latitude, lng=loc.longitude) if loc else "Europe/London"
556
+ local_now = datetime.now(ZoneInfo(tz_str))
557
+ local_now_str = local_now.strftime("%Y-%m-%d %H:%M:%S")
558
+
559
+ # GPT get query time(transfer to Y-M-D)
560
+ time_prompt = f"""
561
+ It is currently {local_now_str} in {location}.
562
+ Based on the query: "{query}", return the intended local date (YYYY-MM-DD).
563
+ Return only a date like 2025-04-04. If unclear, use today.
564
+ """
565
+ date_response = llm_gpt4.invoke(time_prompt)
566
+ date_str = date_response.content.strip() if isinstance(date_response, AIMessage) else str(date_response).strip()
567
+ query_date = date_parser.parse(date_str).date()
568
+ today = local_now.date()
569
+
570
+ # chose to use current / forecast / history API according to time
571
+ if query_date == today:
572
+ url = f"http://api.weatherapi.com/v1/current.json?key={weather_api_key}&q={location}&aqi=no"
573
+ data = requests.get(url).json()
574
+ cur = data["current"]
575
+ return f"The current weather in {location.title()} is {cur['condition']['text']} with {cur['temp_c']}°C (feels like {cur['feelslike_c']}°C), humidity {cur['humidity']}%, wind {cur['wind_kph']} kph."
576
+
577
+ elif query_date > today:
578
+ url = f"http://api.weatherapi.com/v1/forecast.json?key={weather_api_key}&q={location}&days=3"
579
+ data = requests.get(url).json()
580
+ forecast_days = data.get("forecast", {}).get("forecastday", [])
581
+ for day in forecast_days:
582
+ if day["date"] == date_str:
583
+ d = day["day"]
584
+ return f"Forecast for {location.title()} on {query_date.strftime('%A, %B %d')}: {d['condition']['text']}, avg {d['avgtemp_c']}°C, humidity {d['avghumidity']}%, max {d['maxtemp_c']}°C, min {d['mintemp_c']}°C."
585
+ return f"Forecast unavailable for {query_date} (WeatherAPI supports up to 3 days ahead)."
586
 
587
+ else:
588
+ url = f"http://api.weatherapi.com/v1/history.json?key={weather_api_key}&q={location}&dt={date_str}"
589
+ data = requests.get(url).json()
590
+ hist = data.get("forecast", {}).get("forecastday", [{}])[0].get("day", {})
591
+ if not hist:
592
+ return f"Historical weather not found for {location.title()} on {query_date}."
593
+ return f"The weather in {location.title()} on {query_date.strftime('%A, %B %d')}: {hist['condition']['text']}, avg {hist['avgtemp_c']}°C, humidity {hist['avghumidity']}%, max {hist['maxtemp_c']}°C, min {hist['mintemp_c']}°C."
594
 
595
  except Exception as e:
596
+ return f"Weather Agent Error: {e}"
597
 
598
  @tool("summarise")
599
  def summarise_tool(query: str) -> str: