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

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +25 -20
src/streamlit_app.py CHANGED
@@ -1,26 +1,33 @@
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)
@@ -28,6 +35,7 @@ def get_school_info(region_code, school_name, api_key):
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"
@@ -37,23 +45,20 @@ def get_schedule(region_code, school_code, year, api_key):
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": "์ถฉ๋‚จ",
@@ -66,6 +71,7 @@ with st.form("query_form"):
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")
@@ -77,7 +83,7 @@ if submitted:
77
  if not schedule_rows:
78
  st.info("ํ•ด๋‹น ์กฐ๊ฑด์˜ ํ•™์‚ฌ์ผ์ •์ด ์—†์Šต๋‹ˆ๋‹ค.")
79
  else:
80
- # ์ผ์ • ๋ฐ์ดํ„ฐ๋ฅผ HTML ์บ˜๋ฆฐ๋”์— ๋„ฃ๊ธฐ ์œ„ํ•œ JSON ์ƒ์„ฑ
81
  events = [
82
  {
83
  "title": row["EVENT_NM"],
@@ -85,8 +91,6 @@ if submitted:
85
  }
86
  for row in schedule_rows
87
  ]
88
-
89
- import json
90
  event_json = json.dumps(events, ensure_ascii=False)
91
 
92
  # FullCalendar ์‚ฝ์ž…
@@ -114,6 +118,7 @@ if submitted:
114
  </html>
115
  """, height=650)
116
 
 
117
  with st.expander("โœจ 1๋…„์น˜ ์š”์•ฝ ๋ณด๊ธฐ", expanded=False):
118
  if st.button("๐Ÿค– ์š”์•ฝ ์ƒ์„ฑํ•˜๊ธฐ"):
119
  with st.spinner("Gemma ๋ชจ๋ธ์ด ์š”์•ฝ ์ค‘..."):
 
1
  import os
2
+ import json
3
  import requests
4
  import streamlit as st
5
  from datetime import datetime
6
+ from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
7
 
8
+ # โœ… ์บ์‹œ ๋””๋ ‰ํ† ๋ฆฌ ์„ค์ • (๊ถŒํ•œ ์˜ค๋ฅ˜ ๋ฐฉ์ง€)
9
+ os.environ["TRANSFORMERS_CACHE"] = "/tmp/hf_cache"
10
+
11
+ # โœ… Streamlit ๊ธฐ๋ณธ ์„ค์ •
12
  st.set_page_config(page_title="ํ•™์‚ฌ์ผ์ • ์บ˜๋ฆฐ๋”", layout="centered")
13
+ st.title("๐Ÿ“… ํ•™์‚ฌ์ผ์ • ์บ˜๋ฆฐ๋” + AI ์š”์•ฝ")
14
+ st.markdown("NEIS API์—์„œ ํ•™์‚ฌ์ผ์ •์„ ๋ถˆ๋Ÿฌ์˜ค๊ณ  FullCalendar๋กœ ์‹œ๊ฐํ™”ํ•ฉ๋‹ˆ๋‹ค.")
15
 
16
+ # โœ… ๋””๋ฒ„๊น…์šฉ ํ† ํฐ ํ™•์ธ
17
  st.write("๐Ÿ” ํ† ํฐ ์žˆ์Œ:", os.environ.get("HUGGINGFACE_TOKEN") is not None)
18
 
19
+ # โœ… Gemma ๋ชจ๋ธ ๋กœ๋”ฉ ํ•จ์ˆ˜
20
  @st.cache_resource
21
  def load_model():
22
+ token = os.environ.get("HUGGINGFACE_TOKEN")
23
+ model_id = "google/gemma-2-2b-it"
24
+ tokenizer = AutoTokenizer.from_pretrained(model_id, use_auth_token=token)
25
+ model = AutoModelForCausalLM.from_pretrained(model_id, use_auth_token=token)
26
+ return pipeline("text-generation", model=model, tokenizer=tokenizer)
27
+
28
  llm = load_model()
29
 
30
+ # โœ… ํ•™๊ต ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ
31
  def get_school_info(region_code, school_name, api_key):
32
  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}"
33
  res = requests.get(url)
 
35
  school = data.get("schoolInfo", [{}])[1].get("row", [{}])[0]
36
  return school.get("SD_SCHUL_CODE"), school.get("ATPT_OFCDC_SC_CODE")
37
 
38
+ # โœ… ํ•™์‚ฌ์ผ์ • ๊ฐ€์ ธ์˜ค๊ธฐ
39
  def get_schedule(region_code, school_code, year, api_key):
40
  from_ymd = f"{year}0101"
41
  to_ymd = f"{year}1231"
 
45
  rows = data.get("SchoolSchedule", [{}])[1].get("row", [])
46
  return rows
47
 
48
+ # โœ… AI ์š”์•ฝ ํ•จ์ˆ˜
49
  def summarize_schedule(rows, school_name, year):
50
  lines = []
51
  for row in rows:
52
  date = row["AA_YMD"]
53
+ dt = datetime.strptime(date, "%Y%m%d").strftime("%-m์›” %-d์ผ")
54
  event = row["EVENT_NM"]
55
  lines.append(f"{dt}: {event}")
56
  text = "\n".join(lines)
57
+ prompt = f"{school_name}๊ฐ€ {year}๋…„๋„์— ๊ฐ€์ง€๋Š” ํ•™์‚ฌ์ผ์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:\n{text}\n์ฃผ์š” ์ผ์ •์„ ์š”์•ฝํ•ด์ฃผ์„ธ์š”."
58
  result = llm([{"role": "user", "content": prompt}])
59
  return result[0]["generated_text"].replace(prompt, "").strip()
60
 
61
+ # โœ… UI: ์ง€์—ญ / ํ•™๊ต / ์—ฐ๋„ ์„ ํƒ
 
 
 
 
62
  region_options = {
63
  "B10": "์„œ์šธ", "C10": "๋ถ€์‚ฐ", "D10": "๋Œ€๊ตฌ", "E10": "์ธ์ฒœ", "F10": "๊ด‘์ฃผ", "G10": "๋Œ€์ „",
64
  "H10": "์šธ์‚ฐ", "I10": "์„ธ์ข…", "J10": "๊ฒฝ๊ธฐ", "K10": "๊ฐ•์›", "M10": "์ถฉ๋ถ", "N10": "์ถฉ๋‚จ",
 
71
  year = st.selectbox("๋…„๋„", options=[2022, 2023, 2024, 2025], index=2)
72
  submitted = st.form_submit_button("๐Ÿ“… ํ•™์‚ฌ์ผ์ • ๋ถˆ๋Ÿฌ์˜ค๊ธฐ")
73
 
74
+ # โœ… ์ œ์ถœ ์‹œ ์ฒ˜๋ฆฌ
75
  if submitted:
76
  with st.spinner("์ผ์ • ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘..."):
77
  api_key = os.environ.get("NEIS_API_KEY", "a69e08342c8947b4a52cd72789a5ecaf")
 
83
  if not schedule_rows:
84
  st.info("ํ•ด๋‹น ์กฐ๊ฑด์˜ ํ•™์‚ฌ์ผ์ •์ด ์—†์Šต๋‹ˆ๋‹ค.")
85
  else:
86
+ # ์บ˜๋ฆฐ๋”์šฉ JSON ์ƒ์„ฑ
87
  events = [
88
  {
89
  "title": row["EVENT_NM"],
 
91
  }
92
  for row in schedule_rows
93
  ]
 
 
94
  event_json = json.dumps(events, ensure_ascii=False)
95
 
96
  # FullCalendar ์‚ฝ์ž…
 
118
  </html>
119
  """, height=650)
120
 
121
+ # ์š”์•ฝ ๋ฒ„ํŠผ
122
  with st.expander("โœจ 1๋…„์น˜ ์š”์•ฝ ๋ณด๊ธฐ", expanded=False):
123
  if st.button("๐Ÿค– ์š”์•ฝ ์ƒ์„ฑํ•˜๊ธฐ"):
124
  with st.spinner("Gemma ๋ชจ๋ธ์ด ์š”์•ฝ ์ค‘..."):