Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -178,41 +178,21 @@ def get_korean_weekday(date):
|
|
| 178 |
}
|
| 179 |
return weekday_dict[weekday]
|
| 180 |
|
| 181 |
-
# ์ธ์
์ด๊ธฐํ
|
| 182 |
-
if 'last_weather_data' not in st.session_state:
|
| 183 |
-
st.session_state.last_weather_data = None
|
| 184 |
-
st.session_state.last_successful_update = None
|
| 185 |
-
st.session_state.last_forecast_message = None
|
| 186 |
-
st.session_state.data_initialized = False
|
| 187 |
-
|
| 188 |
@st.cache_data(ttl=300) # 5๋ถ๋ง๋ค ์บ์ ๊ฐฑ์
|
| 189 |
def get_weather_data():
|
| 190 |
url = "http://openapi.seoul.go.kr:8088/77544e69764a414d363647424a655a/xml/citydata/1/5/์ ๋ฆผ์ญ"
|
| 191 |
try:
|
| 192 |
-
response = requests.get(url
|
| 193 |
-
response.raise_for_status()
|
| 194 |
-
if not response.text.strip():
|
| 195 |
raise ValueError("์๋ต์ด ๋น์ด ์์ต๋๋ค.")
|
| 196 |
data = xmltodict.parse(response.text)
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
st.
|
| 202 |
-
|
| 203 |
-
return weather_data
|
| 204 |
-
|
| 205 |
-
except (requests.exceptions.RequestException, ValueError, KeyError) as e:
|
| 206 |
-
if not st.session_state.data_initialized:
|
| 207 |
-
st.error("๋ ์จ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค. ๋คํธ์ํฌ ์ฐ๊ฒฐ์ ํ์ธํด์ฃผ์ธ์.")
|
| 208 |
-
return None
|
| 209 |
-
|
| 210 |
-
st.warning("๋คํธ์ํฌ ์ฐ๊ฒฐ์ด ๋ถ์์ ํ์ฌ ์ด์ ๋ ์จ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํฉ๋๋ค.")
|
| 211 |
-
if st.session_state.last_weather_data is not None:
|
| 212 |
-
last_update = st.session_state.last_successful_update or "์ ์ ์์"
|
| 213 |
-
st.info(f"๋ง์ง๋ง ์
๋ฐ์ดํธ: {last_update}")
|
| 214 |
-
return st.session_state.last_weather_data
|
| 215 |
-
return None
|
| 216 |
|
| 217 |
def get_background_color(pm10_value):
|
| 218 |
try:
|
|
@@ -405,7 +385,7 @@ def show_weather_info(data):
|
|
| 405 |
st.markdown(f'''
|
| 406 |
<div class="time-container">
|
| 407 |
<div style="text-align: center; margin-bottom: 0.5rem; font-size: 6em; font-weight: bold; color: black;">
|
| 408 |
-
{temp}
|
| 409 |
</div>
|
| 410 |
<span class="date-text">{formatted_date}</span>
|
| 411 |
</div>
|
|
@@ -440,61 +420,6 @@ def show_weather_info(data):
|
|
| 440 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 441 |
|
| 442 |
|
| 443 |
-
def get_forecast_message(current_time, forecast_data_str):
|
| 444 |
-
try:
|
| 445 |
-
# ๋คํธ์ํฌ ์ฐ๊ฒฐ ํ์ธ
|
| 446 |
-
try:
|
| 447 |
-
requests.get("https://glhf.chat", timeout=3)
|
| 448 |
-
except:
|
| 449 |
-
if st.session_state.last_forecast_message:
|
| 450 |
-
st.warning("๋คํธ์ํฌ ์ฐ๊ฒฐ์ด ๋ถ์์ ํ์ฌ ์ด์ ๋ ์จ ์๋ณด๋ฅผ ํ์ํฉ๋๋ค.")
|
| 451 |
-
return st.session_state.last_forecast_message
|
| 452 |
-
return "ํ์ฌ ๋ ์จ ์๋ณด ์์ฑ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค. ๋คํธ์ํฌ ์ฐ๊ฒฐ์ ํ์ธํด์ฃผ์ธ์."
|
| 453 |
-
|
| 454 |
-
client = OpenAI(
|
| 455 |
-
api_key="glhf_9ea0e0babe1e45353dd03b44cb979e22",
|
| 456 |
-
base_url="https://glhf.chat/api/openai/v1",
|
| 457 |
-
http_client=httpx.Client(
|
| 458 |
-
follow_redirects=True,
|
| 459 |
-
timeout=30.0
|
| 460 |
-
)
|
| 461 |
-
)
|
| 462 |
-
|
| 463 |
-
response = client.chat.completions.create(
|
| 464 |
-
model="hf:Nexusflow/Athene-V2-Chat",
|
| 465 |
-
messages=[
|
| 466 |
-
{"role": "system", "content": "๋น์ ์ ๋ ์จ ์๋ณด๊ด์
๋๋ค. ์ฃผ์ด์ง ์๊ฐ๋๋ณ ๋ ์จ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ์ผ๋ก ์ ํํ ๋ ์จ ์๋ณด๋ฅผ ์์ฑํด์ฃผ์ธ์. FCST_DT์ ์๊ฐ์ 24์๊ฐ์ ๋ก ํ์๋ฉ๋๋ค (์: 1900์ ์ ๋
7์์
๋๋ค)."},
|
| 467 |
-
{"role": "user", "content": f"""ํ์ฌ ์๊ฐ์ {current_time.strftime('%H์ %M๋ถ')}์
๋๋ค.
|
| 468 |
-
|
| 469 |
-
๋ค์ FCST_DT์ ์๊ฐ๋๋ณ ๋ ์จ ๋ฐ์ดํฐ๋ฅผ ๋ณด๊ณ ์ค์ ๋ ์จ ์ํฉ์ ๋ง๋ ์ ํํ ๋ ์จ ์๋ณด๋ฅผ 200์์ ์์ฐ์ค๋ฌ์ด ๋ฌธ์ฅ์ผ๋ก ๋ง๋ค์ด์ฃผ์ธ์. ๋น๋ ๋ ์๋ณด๊ฐ ์๋ ๊ฒฝ์ฐ์๋ง ์ฐ์ฐ์ ์ค๋นํ๋๋ก ์๋ดํด์ฃผ์ธ์. ์ท์ฐจ๋ฆผ์ ๋ค์์ ์ฐธ๊ณ ํ์ธ์.
|
| 470 |
-
27ยฐC์ด์: ๋ฐํํฐ, ๋ฐ๏ฟฝ๏ฟฝ์ง, ๋ฏผ์๋งค
|
| 471 |
-
23ยฐC~26ยฐC: ์์ ์
์ธ , ๋ฐ๋ฐ์ง
|
| 472 |
-
20ยฐC~22ยฐC: ์์ ๊ฐ๋๊ฑด, ๊ธดํ
|
| 473 |
-
17ยฐC~19ยฐC: ์์ ๋ํธ, ๋งจํฌ๋งจ, ๊ธด๋ฐ์ง
|
| 474 |
-
12ยฐC~16ยฐC: ์์ผ, ๊ฐ๋๊ฑด, ๊ธด๋ฐ์ง
|
| 475 |
-
9ยฐC~11ยฐC: ํธ๋ ์น์ฝํธ, ์ผ์, ๊ธฐ๋ชจ๋ฐ์ง
|
| 476 |
-
5ยฐC~8ยฐC: ์ฝํธ, ๊ฐ์ฃฝ์์ผ, ๋ํธ
|
| 477 |
-
4ยฐC ์ดํ: ํจ๋ฉ, ๋๊บผ์ด ์ฝํธ, ๋ชฉ๋๋ฆฌ
|
| 478 |
-
|
| 479 |
-
{forecast_data_str}"""}
|
| 480 |
-
],
|
| 481 |
-
temperature=0.7,
|
| 482 |
-
max_tokens=500,
|
| 483 |
-
top_p=0.8,
|
| 484 |
-
frequency_penalty=0,
|
| 485 |
-
presence_penalty=0
|
| 486 |
-
)
|
| 487 |
-
message = response.choices[0].message.content
|
| 488 |
-
st.session_state.last_forecast_message = message
|
| 489 |
-
return message
|
| 490 |
-
|
| 491 |
-
except Exception as e:
|
| 492 |
-
if st.session_state.last_forecast_message:
|
| 493 |
-
st.warning("๋ ์จ ์๋ณด ์์ฑ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ์ด์ ์๋ณด๋ฅผ ํ์ํฉ๋๋ค.")
|
| 494 |
-
return st.session_state.last_forecast_message
|
| 495 |
-
return "ํ์ฌ ๋ ์จ ์๋ณด ์์ฑ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค. ๋คํธ์ํฌ ์ฐ๊ฒฐ์ ํ์ธํด์ฃผ์ธ์."
|
| 496 |
-
|
| 497 |
-
|
| 498 |
def show_temperature_graph(data):
|
| 499 |
st.markdown('<div class="section-container">', unsafe_allow_html=True)
|
| 500 |
st.markdown('<h1 style="text-align: center; margin-bottom: 1rem;">์๊ฐ๋๋ณ ์จ๋</h1>', unsafe_allow_html=True)
|
|
@@ -672,7 +597,7 @@ def show_temperature_graph(data):
|
|
| 672 |
y=max(temps) + 3,
|
| 673 |
text=f"{icon}",
|
| 674 |
showarrow=False,
|
| 675 |
-
font=dict(size=30
|
| 676 |
)
|
| 677 |
fig.add_annotation(
|
| 678 |
x=times[i],
|
|
@@ -723,64 +648,61 @@ def show_temperature_graph(data):
|
|
| 723 |
|
| 724 |
st.plotly_chart(fig, use_container_width=True)
|
| 725 |
|
| 726 |
-
#
|
| 727 |
-
|
| 728 |
-
|
| 729 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 730 |
|
| 731 |
-
forecast_data_str = "\n".join([
|
| 732 |
-
f"[{f['FCST_DT'][:4]}๋
{f['FCST_DT'][4:6]}์ {f['FCST_DT'][6:8]}์ผ {f['FCST_DT'][8:10]}์] {temp}๋, {description}"
|
| 733 |
-
for f, time, temp, description in zip(valid_forecast_data, times, temps, weather_descriptions)
|
| 734 |
-
])
|
| 735 |
|
| 736 |
-
|
| 737 |
-
|
| 738 |
-
|
| 739 |
-
|
| 740 |
-
|
| 741 |
-
|
| 742 |
-
|
| 743 |
-
|
| 744 |
-
|
| 745 |
-
|
| 746 |
-
|
| 747 |
-
|
| 748 |
-
|
| 749 |
-
|
| 750 |
-
|
| 751 |
-
|
| 752 |
-
|
| 753 |
-
|
| 754 |
-
|
| 755 |
-
|
| 756 |
-
|
| 757 |
-
|
| 758 |
-
|
| 759 |
-
|
| 760 |
-
|
| 761 |
-
|
| 762 |
-
|
| 763 |
-
|
| 764 |
-
|
| 765 |
-
|
| 766 |
-
|
| 767 |
-
|
| 768 |
-
|
| 769 |
-
|
| 770 |
-
|
| 771 |
-
|
|
|
|
| 772 |
</div>
|
| 773 |
-
|
| 774 |
-
unsafe_allow_html=True
|
| 775 |
-
)
|
| 776 |
|
| 777 |
# ์คํฌ๋กค ํ
์คํธ ์์ ๋ฒํผ์ด ์ค๋๋ก ๋ง์ง ์ถ๊ฐ
|
| 778 |
st.markdown('''
|
| 779 |
-
<style>
|
| 780 |
-
div.stButton > button {
|
| 781 |
-
margin-top: 2rem;
|
| 782 |
-
}
|
| 783 |
-
</style>
|
| 784 |
''', unsafe_allow_html=True)
|
| 785 |
|
| 786 |
# ์ฐ๋ฆฌ์ง ๋ ์จ ์ ๋ณด๋ก ๋์๊ฐ๊ธฐ ๋ฒํผ ์ถ๊ฐ
|
|
@@ -788,7 +710,6 @@ def show_temperature_graph(data):
|
|
| 788 |
|
| 789 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 790 |
|
| 791 |
-
|
| 792 |
def main():
|
| 793 |
if 'current_section' not in st.session_state:
|
| 794 |
st.session_state.current_section = 'weather'
|
|
|
|
| 178 |
}
|
| 179 |
return weekday_dict[weekday]
|
| 180 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 181 |
@st.cache_data(ttl=300) # 5๋ถ๋ง๋ค ์บ์ ๊ฐฑ์
|
| 182 |
def get_weather_data():
|
| 183 |
url = "http://openapi.seoul.go.kr:8088/77544e69764a414d363647424a655a/xml/citydata/1/5/์ ๋ฆผ์ญ"
|
| 184 |
try:
|
| 185 |
+
response = requests.get(url)
|
| 186 |
+
response.raise_for_status() # HTTPError์ ๋ํด ์์ธ ๋ฐ์
|
| 187 |
+
if not response.text.strip(): # ๋น ์๋ต ์ฒ๋ฆฌ
|
| 188 |
raise ValueError("์๋ต์ด ๋น์ด ์์ต๋๋ค.")
|
| 189 |
data = xmltodict.parse(response.text)
|
| 190 |
+
return data['SeoulRtd.citydata']['CITYDATA']['WEATHER_STTS']['WEATHER_STTS']
|
| 191 |
+
except requests.exceptions.RequestException as e:
|
| 192 |
+
st.error(f"API ํธ์ถ ์ค ์ค๋ฅ ๋ฐ์: {e}")
|
| 193 |
+
except Exception as e:
|
| 194 |
+
st.error(f"๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค: {e}")
|
| 195 |
+
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
|
| 197 |
def get_background_color(pm10_value):
|
| 198 |
try:
|
|
|
|
| 385 |
st.markdown(f'''
|
| 386 |
<div class="time-container">
|
| 387 |
<div style="text-align: center; margin-bottom: 0.5rem; font-size: 6em; font-weight: bold; color: black;">
|
| 388 |
+
{temp}{precip_mark} {tomorrow_morning_weather}
|
| 389 |
</div>
|
| 390 |
<span class="date-text">{formatted_date}</span>
|
| 391 |
</div>
|
|
|
|
| 420 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 421 |
|
| 422 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 423 |
def show_temperature_graph(data):
|
| 424 |
st.markdown('<div class="section-container">', unsafe_allow_html=True)
|
| 425 |
st.markdown('<h1 style="text-align: center; margin-bottom: 1rem;">์๊ฐ๋๋ณ ์จ๋</h1>', unsafe_allow_html=True)
|
|
|
|
| 597 |
y=max(temps) + 3,
|
| 598 |
text=f"{icon}",
|
| 599 |
showarrow=False,
|
| 600 |
+
font=dict(size=30)
|
| 601 |
)
|
| 602 |
fig.add_annotation(
|
| 603 |
x=times[i],
|
|
|
|
| 648 |
|
| 649 |
st.plotly_chart(fig, use_container_width=True)
|
| 650 |
|
| 651 |
+
# ๋ ์จ ์๋ณด ์์ฑ ๋ฐ ํ์ ๋ถ๋ถ์ ์ธ์
์ํ๋ก ๊ด๋ฆฌ
|
| 652 |
+
if 'weather_forecast' not in st.session_state:
|
| 653 |
+
client = OpenAI(
|
| 654 |
+
api_key="glhf_9ea0e0babe1e45353dd03b44cb979e22",
|
| 655 |
+
base_url="https://glhf.chat/api/openai/v1",
|
| 656 |
+
http_client=httpx.Client(
|
| 657 |
+
follow_redirects=True,
|
| 658 |
+
timeout=30.0
|
| 659 |
+
)
|
| 660 |
+
)
|
| 661 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 662 |
|
| 663 |
+
# ํ์ฌ ์๊ฐ๊ณผ ์๋ณด ์๊ฐ ์ ๋ณด ์ถ๊ฐ
|
| 664 |
+
current_time = datetime.utcnow() + timedelta(hours=9)
|
| 665 |
+
current_date_str = current_time.strftime('%Y๋
%m์ %d์ผ')
|
| 666 |
+
tomorrow_date_str = (current_time + timedelta(days=1)).strftime('%Y๋
%m์ %d์ผ')
|
| 667 |
+
|
| 668 |
+
forecast_data_str = "\n".join([
|
| 669 |
+
f"[{f['FCST_DT'][:4]}๋
{f['FCST_DT'][4:6]}์ {f['FCST_DT'][6:8]}์ผ {f['FCST_DT'][8:10]}์] {temp}๋, {description}"
|
| 670 |
+
for f, time, temp, description in zip(valid_forecast_data, times, temps, weather_descriptions)
|
| 671 |
+
])
|
| 672 |
+
|
| 673 |
+
response = client.chat.completions.create(
|
| 674 |
+
model="hf:Nexusflow/Athene-V2-Chat",
|
| 675 |
+
messages=[
|
| 676 |
+
{"role": "system", "content": "๋น์ ์ ๋ ์จ ์๋ณด๊ด์
๋๋ค. ์ฃผ์ด์ง ์๊ฐ๋๋ณ ๋ ์จ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ์ผ๋ก ์ ํํ ๋ ์จ ์๋ณด๋ฅผ ์์ฑํด์ฃผ์ธ์."},
|
| 677 |
+
{"role": "user", "content": f"""ํ์ฌ ์๊ฐ์ {current_time.strftime('%H์ %M๋ถ')}์
๋๋ค.
|
| 678 |
+
|
| 679 |
+
๋ค์ FCST_DT์ ์๊ฐ๋๋ณ ๋ ์จ ๋ฐ์ดํฐ๋ฅผ ๋ณด๊ณ ์ค์ ๋ ์จ ์ํฉ์ ๋ง๋ ์ ํํ ๋ ์จ ์๋ณด๋ฅผ 200์์ ์์ฐ์ค๋ฌ์ด ๋ฌธ์ฅ์ผ๋ก ๋ง๋ค์ด์ฃผ์ธ์. ๋น๋ ๋ ์๋ณด๊ฐ ์๋ ๊ฒฝ์ฐ์๋ง ์ฐ์ฐ์ ์ค๋นํ๋๋ก ์๋ดํด์ฃผ์ธ์. ์ท์ฐจ๋ฆผ์ ๋ค์์ ์ฐธ๊ณ ํ์ธ์.
|
| 680 |
+
27ยฐC์ด์: ๋ฐํํฐ, ๋ฐ๋ฐ์ง, ๋ฏผ์๋งค
|
| 681 |
+
23ยฐC~26ยฐC: ์์ ์
์ธ , ๋ฐํํฐ, ๋ฐ๋ฐ์ง, ๋ฉด๋ฐ์ง
|
| 682 |
+
20ยฐC~22ยฐC: ์์ ๊ฐ๋๊ฑด, ๊ธดํํฐ, ๊ธด๋ฐ์ง
|
| 683 |
+
17ยฐC~19ยฐC: ์์ ๋ํธ, ๊ฐ๋๊ฑด, ๋งจํฌ๋งจ, ์์ ์์ผ, ๊ธด๋ฐ์ง
|
| 684 |
+
12ยฐC~16ยฐC: ์์ผ, ๊ฐ๋๊ฑด, ์ผ์, ๋งจํฌ๋งจ, ๋ํธ, ์คํํน, ๊ธด๋ฐ์ง
|
| 685 |
+
9ยฐC~11ยฐC: ํธ๋ ์น์ฝํธ, ์ผ์, ๊ฐ์ฃฝ ์์ผ, ์คํํน, ๊ธด๋ฐ์ง
|
| 686 |
+
5ยฐC~8ยฐC: ์ฝํธ, ํํธํ
, ๋ํธ, ๊ธด๋ฐ์ง
|
| 687 |
+
4ยฐC์ดํ: ํจ๋ฉ, ๋๊บผ์ด ์ฝํธ, ๋ชฉ๋๋ฆฌ, ๊ธฐ๋ชจ์ ํ
|
| 688 |
+
|
| 689 |
+
์๊ฐ๋๋ณ ๋ ์จ ๋ฐ์ดํฐ:
|
| 690 |
+
{forecast_data_str}"""}
|
| 691 |
+
]
|
| 692 |
+
)
|
| 693 |
+
|
| 694 |
+
st.session_state.weather_forecast = response.choices[0].message.content
|
| 695 |
+
|
| 696 |
+
# ์ ์ฅ๋ ๋ ์จ ์๋ณด ํ์
|
| 697 |
+
st.markdown(f'''
|
| 698 |
+
<div class="scroll-container">
|
| 699 |
+
<div class="scroll-text">{st.session_state.weather_forecast}</div>
|
| 700 |
</div>
|
| 701 |
+
''', unsafe_allow_html=True)
|
|
|
|
|
|
|
| 702 |
|
| 703 |
# ์คํฌ๋กค ํ
์คํธ ์์ ๋ฒํผ์ด ์ค๋๋ก ๋ง์ง ์ถ๊ฐ
|
| 704 |
st.markdown('''
|
| 705 |
+
<div style="margin-bottom: 10px;">
|
|
|
|
|
|
|
|
|
|
|
|
|
| 706 |
''', unsafe_allow_html=True)
|
| 707 |
|
| 708 |
# ์ฐ๋ฆฌ์ง ๋ ์จ ์ ๋ณด๋ก ๋์๊ฐ๊ธฐ ๋ฒํผ ์ถ๊ฐ
|
|
|
|
| 710 |
|
| 711 |
st.markdown('</div>', unsafe_allow_html=True)
|
| 712 |
|
|
|
|
| 713 |
def main():
|
| 714 |
if 'current_section' not in st.session_state:
|
| 715 |
st.session_state.current_section = 'weather'
|