yongyeol commited on
Commit
7cc4611
ยท
verified ยท
1 Parent(s): d0ecfa7

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +118 -9
src/streamlit_app.py CHANGED
@@ -1,13 +1,122 @@
 
 
1
  import streamlit as st
 
2
  from transformers import pipeline
3
 
4
- st.set_page_config(page_title="pipeline ํ…Œ์ŠคํŠธ")
5
- st.title("โœ… transformers.pipeline import ํ™•์ธ")
6
 
7
- try:
8
- pipe = pipeline("text-generation", model="gpt2")
9
- output = pipe("Hello, my name is", max_new_tokens=10)
10
- st.success("pipeline import ๋ฐ ์‹คํ–‰ ์„ฑ๊ณต!")
11
- st.write(output[0]["generated_text"])
12
- except Exception as e:
13
- st.error(f"์‹คํŒจ: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import requests
3
  import streamlit as st
4
+ from datetime import datetime
5
  from transformers import pipeline
6
 
7
+ st.set_page_config(page_title="ํ•™์‚ฌ์ผ์ • ์บ˜๋ฆฐ๋”", layout="centered")
 
8
 
9
+ # โœ… ๋ฐ”๋กœ ํ† ํฐ ํ™•์ธ (๋””๋ฒ„๊น…์šฉ)
10
+ st.write("๐Ÿ” ํ† ํฐ ์žˆ์Œ:", os.environ.get("HUGGINGFACE_TOKEN") is not None)
11
+
12
+ # Gemma ๋ชจ๋ธ ๋กœ๋”ฉ
13
+ @st.cache_resource
14
+ def load_model():
15
+ return pipeline(
16
+ "text-generation",
17
+ model="google/gemma-2-2b-it",
18
+ max_new_tokens=512,
19
+ use_auth_token=os.environ.get("HUGGINGFACE_TOKEN") # โœ… ์ง์ ‘ ์ „๋‹ฌ
20
+ )
21
+ llm = load_model()
22
+
23
+ # ํ•™๊ต ์ •๋ณด ๋ฐ ์ผ์ • ๊ฐ€์ ธ์˜ค๊ธฐ ํ•จ์ˆ˜
24
+ def get_school_info(region_code, school_name, api_key):
25
+ url = f"https://open.neis.go.kr/hub/schoolInfo?KEY={api_key}&Type=json&pIndex=1&pSize=1&SCHUL_NM={school_name}&ATPT_OFCDC_SC_CODE={region_code}"
26
+ res = requests.get(url)
27
+ data = res.json()
28
+ school = data.get("schoolInfo", [{}])[1].get("row", [{}])[0]
29
+ return school.get("SD_SCHUL_CODE"), school.get("ATPT_OFCDC_SC_CODE")
30
+
31
+ def get_schedule(region_code, school_code, year, api_key):
32
+ from_ymd = f"{year}0101"
33
+ to_ymd = f"{year}1231"
34
+ url = f"https://open.neis.go.kr/hub/SchoolSchedule?KEY={api_key}&Type=json&pIndex=1&pSize=500&ATPT_OFCDC_SC_CODE={region_code}&SD_SCHUL_CODE={school_code}&AA_FROM_YMD={from_ymd}&AA_TO_YMD={to_ymd}"
35
+ res = requests.get(url)
36
+ data = res.json()
37
+ rows = data.get("SchoolSchedule", [{}])[1].get("row", [])
38
+ return rows
39
+
40
+ def summarize_schedule(rows, school_name, year):
41
+ lines = []
42
+ for row in rows:
43
+ date = row["AA_YMD"]
44
+ dt = datetime.strptime(date, "%Y%m%d").strftime("%-mๆœˆ %-dๆ—ฅ")
45
+ event = row["EVENT_NM"]
46
+ lines.append(f"{dt}: {event}")
47
+ text = "\n".join(lines)
48
+ prompt = f"{school_name}๊ฐ€ {year}๋…„๋„์— ๊ฐ€์ง€๋Š” ํ•™์‚ฌ์ผ์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:\n{text}\n์ฃผ์š” ์ผ์ •์„ ๊ฐ€๋ณ€์ ์œผ๋กœ ์š”์•ฝํ•ด์ฃผ์„ธ์š”."
49
+ result = llm([{"role": "user", "content": prompt}])
50
+ return result[0]["generated_text"].replace(prompt, "").strip()
51
+
52
+ # Streamlit UI
53
+ st.set_page_config(page_title="ํ•™์‚ฌ์ผ์ • ์บ˜๋ฆฐ๋”", layout="centered")
54
+ st.title("๐Ÿ“… ํ•™์‚ฌ์ผ์ • ์บ˜๋ฆฐ๋” + AI ์š”์•ฝ")
55
+ st.markdown("NEIS API์—์„œ ํ•™์‚ฌ์ผ์ •์„ ๋ถˆ๋Ÿฌ์˜ค๊ณ  FullCalendar๋กœ ์‹œ๊ฐํ™”ํ•ฉ๋‹ˆ๋‹ค.")
56
+
57
+ region_options = {
58
+ "B10": "์„œ์šธ", "C10": "๋ถ€์‚ฐ", "D10": "๋Œ€๊ตฌ", "E10": "์ธ์ฒœ", "F10": "๊ด‘์ฃผ", "G10": "๋Œ€์ „",
59
+ "H10": "์šธ์‚ฐ", "I10": "์„ธ์ข…", "J10": "๊ฒฝ๊ธฐ", "K10": "๊ฐ•์›", "M10": "์ถฉ๋ถ", "N10": "์ถฉ๋‚จ",
60
+ "P10": "์ „๋ถ", "Q10": "์ „๋‚จ", "R10": "๊ฒฝ๋ถ", "S10": "๊ฒฝ๋‚จ", "T10": "์ œ์ฃผ"
61
+ }
62
+
63
+ with st.form("query_form"):
64
+ region = st.selectbox("์ง€์—ญ ๊ต์œก์ฒญ", options=list(region_options.keys()), format_func=lambda x: f"{region_options[x]} ({x})")
65
+ school_name = st.text_input("ํ•™๊ต๋ช…", placeholder="์˜ˆ: ์ƒ๋ฆฌ์ดˆ๋“ฑํ•™๊ต")
66
+ year = st.selectbox("๋…„๋„", options=[2022, 2023, 2024, 2025], index=2)
67
+ submitted = st.form_submit_button("๐Ÿ“… ํ•™์‚ฌ์ผ์ • ๋ถˆ๋Ÿฌ์˜ค๊ธฐ")
68
+
69
+ if submitted:
70
+ with st.spinner("์ผ์ • ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘..."):
71
+ api_key = os.environ.get("NEIS_API_KEY", "a69e08342c8947b4a52cd72789a5ecaf")
72
+ school_code, region_code = get_school_info(region, school_name, api_key)
73
+ if not school_code:
74
+ st.error("ํ•™๊ต ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
75
+ else:
76
+ schedule_rows = get_schedule(region_code, school_code, year, api_key)
77
+ if not schedule_rows:
78
+ st.info("ํ•ด๋‹น ์กฐ๊ฑด์˜ ํ•™์‚ฌ์ผ์ •์ด ์—†์Šต๋‹ˆ๋‹ค.")
79
+ else:
80
+ # ์ผ์ • ๋ฐ์ดํ„ฐ๋ฅผ HTML ์บ˜๋ฆฐ๋”์— ๋„ฃ๊ธฐ ์œ„ํ•œ JSON ์ƒ์„ฑ
81
+ events = [
82
+ {
83
+ "title": row["EVENT_NM"],
84
+ "start": datetime.strptime(row["AA_YMD"], "%Y%m%d").strftime("%Y-%m-%d")
85
+ }
86
+ for row in schedule_rows
87
+ ]
88
+
89
+ import json
90
+ event_json = json.dumps(events, ensure_ascii=False)
91
+
92
+ # FullCalendar ์‚ฝ์ž…
93
+ st.components.v1.html(f"""
94
+ <html>
95
+ <head>
96
+ <link href='https://cdn.jsdelivr.net/npm/[email protected]/index.global.min.css' rel='stylesheet' />
97
+ <script src='https://cdn.jsdelivr.net/npm/[email protected]/index.global.min.js'></script>
98
+ <script>
99
+ document.addEventListener('DOMContentLoaded', function() {{
100
+ var calendarEl = document.getElementById('calendar');
101
+ var calendar = new FullCalendar.Calendar(calendarEl, {{
102
+ initialView: 'dayGridMonth',
103
+ locale: 'ko',
104
+ height: 600,
105
+ events: {event_json}
106
+ }});
107
+ calendar.render();
108
+ }});
109
+ </script>
110
+ </head>
111
+ <body>
112
+ <div id='calendar'></div>
113
+ </body>
114
+ </html>
115
+ """, height=650)
116
+
117
+ with st.expander("โœจ 1๋…„์น˜ ์š”์•ฝ ๋ณด๊ธฐ", expanded=False):
118
+ if st.button("๐Ÿค– ์š”์•ฝ ์ƒ์„ฑํ•˜๊ธฐ"):
119
+ with st.spinner("Gemma ๋ชจ๋ธ์ด ์š”์•ฝ ์ค‘..."):
120
+ summary = summarize_schedule(schedule_rows, school_name, year)
121
+ st.success("์š”์•ฝ ์™„๋ฃŒ!")
122
+ st.markdown(f"**{school_name} {year}๋…„ ํ•™์‚ฌ์ผ์ • ์š”์•ฝ:**\n\n{summary}")