Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 28 additions & 23 deletions ai.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,36 @@

> pip install openai
"""
# pylint: disable=C0301
import os
from openai import OpenAI

# To authenticate with the model you will need to generate a personal access token (PAT) in your GitHub settings.
# Create your PAT token by following instructions here: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
client = OpenAI(
base_url="https://models.inference.ai.azure.com",
api_key=os.getenv("GITHUB_TOKEN"),
)
def generate_ai_text(forecast):
"""
Method that generates AI text
"""
# To authenticate with the model you will need to generate a personal access token (PAT) in your GitHub settings.
# Create your PAT token by following instructions here: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
client = OpenAI(
base_url="https://models.inference.ai.azure.com",
api_key=os.getenv("OPENAI_API_KEY"),
)

response = client.chat.completions.create(
messages=[
{
"role": "system",
"content": "You are a young meteorologist explaining the next day's forecast in Syracuse NY in the morning",
},
{
"role": "user",
"content": "Saturday, Temperature: 15, Wind Speed: 5 to 9 mph, windDirection: NW, detailedForecast: Partly sunny, with a high near 15. Wind chill values as low as -1. Northwest wind 5 to 9 mph. New snow accumulation of less than half an inch possible. ",
}
],
model="gpt-4o",
temperature=1,
max_tokens=4096,
top_p=1
)
response = client.chat.completions.create(
messages=[
{
"role": "system",
"content": "You are a young meteorologist explaining the next three day's forecast in Syracuse NY in the morning(Say 'Good Morning Syracuse!'). Act like you're making a social media post. Make sure to Consildate the days into one description (don't do morning and night seperately)",
},
{
"role": "user",
"content": forecast,
}
],
model="gpt-4o",
temperature=1,
max_tokens=4096,
top_p=1
)

print(response.choices[0].message.content)
print(response.choices[0].message.content)
12 changes: 2 additions & 10 deletions bluesky.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
"""
The Module contains the Authentication methods for the following:

BlueSkyAPI
NWSAPI
OpenAIAPI

Dependencies:

Author:
- Andrew Markarian
This module handles all interactions with the Bluesky API, including authentication, session management,
and posting formatted weather updates to the Bluesky social media platform.
"""

import os
Expand Down
15 changes: 12 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@

import bluesky
import weather
import ai

def main():
"""
This runs the main module of BlueSkyTracker
"""
print("Loading Credentials...")
bluesky_handle, bluesky_app_password = bluesky.load_bluesky_credentials()

Expand All @@ -29,7 +33,12 @@ def main():

print("Fetching Forecast")
forecast = weather.fetch_weather_forecast()
print(forecast)


print("Formatting Weather Data")
forecast = weather.format_weather_data(forecast)

print("Generating AI Text")
ai.generate_ai_text(forecast)

if __name__ == "__main__":
main()
main()
4 changes: 2 additions & 2 deletions tests/weather_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ def test_successful_api_call(self, mock_get):
result = fetch_weather_forecast()

self.assertIsNotNone(result)
self.assertEqual(len(result), 3)
self.assertEqual(len(result), 2)
self.assertEqual(result["day_1"][0]["name"], "Monday")
self.assertEqual(result["day_3"][0]["name"], "Wednesday")
self.assertEqual(result["day_2"][0]["name"], "Tuesday")

@patch("requests.get")
def test_api_connection_error(self, mock_get):
Expand Down
36 changes: 29 additions & 7 deletions weather.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
"""
This module handles all weather-related functionality within the project. It is responsible for
fetching weather forecast data from the National Weather Service (NWS) API, parsing and extracting
relevant information, and formatting it for use in other parts of the project.
"""
# pylint: disable=C0301
import requests

def fetch_weather_forecast():
Expand All @@ -9,15 +15,15 @@ def fetch_weather_forecast():
try:
url = "https://api.weather.gov/gridpoints/BGM/52,99/forecast"

response = requests.get(url)
response = requests.get(url, timeout=10)
response.raise_for_status()
data = response.json()

forecast = data.get("properties", {}).get("periods", [])

forecast_days = []

for i in range(6):
for i in range(4):
period = forecast[i]
forecast_days.append({
"name": period.get("name"),
Expand All @@ -28,16 +34,32 @@ def fetch_weather_forecast():
"windDirection": period.get("windDirection"),
"detailedForecast": period.get("detailedForecast")
})
# Group forecast into three-day structure

# Group forecast into two-day structure
consolidated_forecast = {
"day_1": forecast_days[:2],
"day_2": forecast_days[2:4],
"day_3": forecast_days[4:6]
}

return consolidated_forecast

except requests.exceptions.RequestException as err:
print("Error Fetching Weather Data: ", {err})
return None
return None

def format_weather_data(weather_data):
"""
This method is responsible for formatting the weather data retrieved from fetch_weather_data()
"""
weather_input = ""
for forecast in weather_data.values():
weather_input += f"{forecast[0]['name']} & {forecast[1]['name']}:\n"
for period in forecast:
weather_input += (
f"Temperature: {period['temperature']}{period['temperatureUnit']}\n"
f"Probability Of Precipitation: {period['probabilityOfPrecipitation']}\n"
f"Wind Speed: {period['windSpeed']}, Direction {period['windDirection']}\n"
f"Detailed Forecast: {period['detailedForecast']}\n\n"
)
print(weather_input)
return weather_input