Spaces:
Sleeping
Sleeping
Upload 2 files
Browse files- app.py +217 -0
- requirements.txt +5 -0
app.py
ADDED
@@ -0,0 +1,217 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import requests
|
3 |
+
import openai
|
4 |
+
from io import BytesIO
|
5 |
+
from PIL import Image
|
6 |
+
import os
|
7 |
+
from dotenv import load_dotenv
|
8 |
+
|
9 |
+
# Set page configuration as the first Streamlit command
|
10 |
+
st.set_page_config(page_title="Eco-Symphony", page_icon="🌱", layout="centered")
|
11 |
+
|
12 |
+
# Load environment variables from .env file
|
13 |
+
load_dotenv()
|
14 |
+
|
15 |
+
# Set API keys from environment
|
16 |
+
openai.api_key = os.getenv("OPENAI_API_KEY")
|
17 |
+
OPENWEATHER_API_KEY = os.getenv("OPENWEATHER_API_KEY")
|
18 |
+
HUGGINGFACE_API_KEY = os.getenv("HUGGINGFACE_API_KEY")
|
19 |
+
|
20 |
+
# Hugging Face API URLs
|
21 |
+
MUSICGEN_API_URL = "https://api-inference.huggingface.co/models/facebook/musicgen-small"
|
22 |
+
IMAGEGEN_API_URL = "https://api-inference.huggingface.co/models/Artples/LAI-ImageGeneration-vSDXL-2"
|
23 |
+
|
24 |
+
# Headers for Hugging Face API requests
|
25 |
+
headers = {"Authorization": f"Bearer {HUGGINGFACE_API_KEY}"}
|
26 |
+
|
27 |
+
# Inject custom CSS for green theme
|
28 |
+
st.markdown("""
|
29 |
+
<style>
|
30 |
+
body {
|
31 |
+
background-color: #ffffff;
|
32 |
+
}
|
33 |
+
.stApp {
|
34 |
+
color: #2e7d32;
|
35 |
+
font-family: 'Arial', sans-serif;
|
36 |
+
}
|
37 |
+
.stButton>button {
|
38 |
+
background-color: #66bb6a;
|
39 |
+
color: #fff;
|
40 |
+
font-weight: bold;
|
41 |
+
}
|
42 |
+
.stTextInput>div>input {
|
43 |
+
background-color: #e8f5e9;
|
44 |
+
color: #2e7d32;
|
45 |
+
}
|
46 |
+
.stMarkdown h1, .stMarkdown h2, .stMarkdown h3, .stMarkdown p {
|
47 |
+
color: #388e3c;
|
48 |
+
}
|
49 |
+
.stMarkdown h2 {
|
50 |
+
font-weight: bold;
|
51 |
+
}
|
52 |
+
</style>
|
53 |
+
""", unsafe_allow_html=True)
|
54 |
+
|
55 |
+
# Function to fetch weather data
|
56 |
+
def fetch_real_data(city: str) -> dict:
|
57 |
+
weather_url = f'https://api.openweathermap.org/data/2.5/weather?q={city}&appid={OPENWEATHER_API_KEY}&units=metric'
|
58 |
+
weather_response = requests.get(weather_url)
|
59 |
+
if weather_response.status_code != 200:
|
60 |
+
st.error("Error fetching weather data.")
|
61 |
+
return {}
|
62 |
+
weather_data = weather_response.json()
|
63 |
+
return {
|
64 |
+
"temperature": weather_data['main'].get('temp', 'Data not available'),
|
65 |
+
"humidity": weather_data['main'].get('humidity', 'Data not available'),
|
66 |
+
"weather_condition": weather_data['weather'][0].get('main', 'Data not available')
|
67 |
+
}
|
68 |
+
|
69 |
+
# Function to determine mood based on weather data
|
70 |
+
def determine_mood(data: dict) -> str:
|
71 |
+
weather_condition = data["weather_condition"].lower()
|
72 |
+
temperature = data["temperature"]
|
73 |
+
if "rain" in weather_condition:
|
74 |
+
return "rainy"
|
75 |
+
elif "clear" in weather_condition and temperature > 25:
|
76 |
+
return "sunny"
|
77 |
+
elif "cloud" in weather_condition:
|
78 |
+
return "cloudy"
|
79 |
+
elif temperature < 15:
|
80 |
+
return "cool"
|
81 |
+
else:
|
82 |
+
return "neutral"
|
83 |
+
|
84 |
+
# Function to create a narrative
|
85 |
+
def create_narrative(city: str, data: dict) -> str:
|
86 |
+
return f"In {city}, the weather is {data['weather_condition']} with a temperature of {data['temperature']}°C."
|
87 |
+
|
88 |
+
# Function to generate a story using OpenAI
|
89 |
+
def generate_story_with_ai(narrative: str, mood: str) -> str:
|
90 |
+
messages = [
|
91 |
+
{"role": "system", "content": "You are a creative storyteller using characters and imagery."},
|
92 |
+
{"role": "user", "content": f"{narrative} The mood is '{mood}', write a story about how the environment feels in 50 words."}
|
93 |
+
]
|
94 |
+
response = openai.ChatCompletion.create(
|
95 |
+
model="gpt-3.5-turbo",
|
96 |
+
messages=messages,
|
97 |
+
max_tokens=150,
|
98 |
+
temperature=0.7
|
99 |
+
)
|
100 |
+
return response.choices[0].message['content'].strip()
|
101 |
+
|
102 |
+
# Function to generate simulated environmental data
|
103 |
+
def generate_simulated_data(city: str) -> dict:
|
104 |
+
prompt = (
|
105 |
+
f"Generate simulated environmental data for {city} in JSON format with fields:\n"
|
106 |
+
f"1. AQI\n2. Deforestation Rate\n3. Water Quality\n4. Biodiversity Impact"
|
107 |
+
)
|
108 |
+
response = openai.ChatCompletion.create(
|
109 |
+
model="gpt-3.5-turbo",
|
110 |
+
messages=[{"role": "user", "content": prompt}],
|
111 |
+
max_tokens=100,
|
112 |
+
temperature=0.8
|
113 |
+
)
|
114 |
+
response_content = response.choices[0].message['content'].strip()
|
115 |
+
try:
|
116 |
+
return eval(response_content)
|
117 |
+
except Exception as e:
|
118 |
+
st.error(f"Error parsing simulated data: {e}")
|
119 |
+
return {}
|
120 |
+
|
121 |
+
# Function to generate music from Hugging Face API
|
122 |
+
def generate_music(description: str) -> bytes:
|
123 |
+
payload = {"inputs": description}
|
124 |
+
response = requests.post(MUSICGEN_API_URL, headers=headers, json=payload)
|
125 |
+
if response.status_code != 200:
|
126 |
+
st.error(f"Error generating music: {response.status_code} {response.text}")
|
127 |
+
return None
|
128 |
+
return response.content
|
129 |
+
|
130 |
+
# Function to generate an image based on the story
|
131 |
+
def generate_image(description: str) -> bytes:
|
132 |
+
payload = {"inputs": description}
|
133 |
+
response = requests.post(IMAGEGEN_API_URL, headers=headers, json=payload)
|
134 |
+
if response.status_code != 200:
|
135 |
+
st.error(f"Error generating image: {response.status_code} {response.text}")
|
136 |
+
return None
|
137 |
+
return response.content
|
138 |
+
|
139 |
+
# Function to create a dynamic music description
|
140 |
+
def create_music_description(data):
|
141 |
+
mood = data["mood"]
|
142 |
+
weather_condition = data["real_data"]["weather_condition"].lower()
|
143 |
+
temperature = data["real_data"]["temperature"]
|
144 |
+
|
145 |
+
description = f"{mood} mood with {weather_condition} weather"
|
146 |
+
|
147 |
+
if temperature < 10:
|
148 |
+
description += " and a cold ambiance"
|
149 |
+
elif 10 <= temperature <= 20:
|
150 |
+
description += " and a cool feel"
|
151 |
+
elif 20 < temperature <= 30:
|
152 |
+
description += " and a warm, lively environment"
|
153 |
+
else:
|
154 |
+
description += " and a hot, energetic vibe"
|
155 |
+
|
156 |
+
return description
|
157 |
+
|
158 |
+
# Streamlit UI
|
159 |
+
st.title("🌿 Eco-Symphony 🎶")
|
160 |
+
st.write("Enter a city to explore real-time environmental data, generate AI-created music, and see an AI-generated image based on the story.")
|
161 |
+
|
162 |
+
# Input box for city
|
163 |
+
city = st.text_input("Enter City Name:", placeholder="Type the name of a city...")
|
164 |
+
|
165 |
+
# Generate Button
|
166 |
+
if st.button("Generate Environmental Narrative, Music, and Image"):
|
167 |
+
# Fetch real weather data
|
168 |
+
real_data = fetch_real_data(city)
|
169 |
+
|
170 |
+
if real_data:
|
171 |
+
# Generate narrative and mood
|
172 |
+
narrative = create_narrative(city, real_data)
|
173 |
+
mood = determine_mood(real_data)
|
174 |
+
|
175 |
+
# Generate AI story
|
176 |
+
story = generate_story_with_ai(narrative, mood)
|
177 |
+
|
178 |
+
# Generate Music and Image Based on Story and Mood
|
179 |
+
music_description = create_music_description({"mood": mood, "real_data": real_data})
|
180 |
+
|
181 |
+
st.subheader("🎶 Generated Music")
|
182 |
+
st.write(f"Generating music based on: {music_description}")
|
183 |
+
music_bytes = generate_music(music_description)
|
184 |
+
if music_bytes:
|
185 |
+
audio_data = BytesIO(music_bytes)
|
186 |
+
st.audio(audio_data, format="audio/wav")
|
187 |
+
|
188 |
+
st.subheader("🖼️ Generated Image")
|
189 |
+
st.write("Generating image based on the story...")
|
190 |
+
image_bytes = generate_image(story)
|
191 |
+
if image_bytes:
|
192 |
+
image = Image.open(BytesIO(image_bytes))
|
193 |
+
st.image(image, caption="Generated Image based on Story", use_column_width=True)
|
194 |
+
|
195 |
+
# Display Environmental Narrative and Data
|
196 |
+
st.subheader("📜 Environmental Narrative")
|
197 |
+
st.write(narrative)
|
198 |
+
|
199 |
+
st.subheader("💭 Mood")
|
200 |
+
st.write(f"**Mood**: {mood}")
|
201 |
+
|
202 |
+
st.subheader("🌈 AI-Generated Story")
|
203 |
+
st.write(story)
|
204 |
+
|
205 |
+
# Generate and Display Simulated Environmental Data
|
206 |
+
simulated_data = generate_simulated_data(city)
|
207 |
+
simulated_inner_data = simulated_data.get("data", {})
|
208 |
+
st.subheader("📊 Real Weather Data")
|
209 |
+
st.write("Temperature (°C):", real_data.get("temperature", "Data not available"))
|
210 |
+
st.write("Humidity (%):", real_data.get("humidity", "Data not available"))
|
211 |
+
st.write("Weather Condition:", real_data.get("weather_condition", "Data not available"))
|
212 |
+
|
213 |
+
st.subheader("🧪 Simulated Environmental Data")
|
214 |
+
st.write("AQI:", simulated_inner_data.get("AQI", "Data not available"))
|
215 |
+
st.write("Deforestation Rate:", simulated_inner_data.get("Deforestation Rate", "Data not available"))
|
216 |
+
st.write("Water Quality:", simulated_inner_data.get("Water Quality", "Data not available"))
|
217 |
+
st.write("Biodiversity Impact:", simulated_inner_data.get("Biodiversity Impact", "Data not available"))
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
streamlit
|
2 |
+
openai
|
3 |
+
requests
|
4 |
+
pillow
|
5 |
+
python-dotenv
|