yongyeol commited on
Commit
48f9050
Β·
verified Β·
1 Parent(s): cdf21bf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -68
app.py CHANGED
@@ -1,13 +1,17 @@
1
  import os
2
  import requests
3
- import gradio as gr
4
  from datetime import datetime
5
  from transformers import pipeline
6
 
7
- # ──────── Gemma λͺ¨λΈ λ‘œλ”© (1회 μΊμ‹œ) ────────
8
- llm = pipeline("text-generation", model="google/gemma-2-2b-it", max_new_tokens=512)
 
 
9
 
10
- # ──────── API ν•¨μˆ˜ μ •μ˜ ────────
 
 
11
  def get_school_info(region_code, school_name, api_key):
12
  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}"
13
  res = requests.get(url)
@@ -28,79 +32,82 @@ def summarize_schedule(rows, school_name, year):
28
  lines = []
29
  for row in rows:
30
  date = row["AA_YMD"]
31
- dt = datetime.strptime(date, "%Y%m%d").strftime("%-mμ›” %-d일")
32
  event = row["EVENT_NM"]
33
  lines.append(f"{dt}: {event}")
34
  text = "\n".join(lines)
35
- prompt = f"{school_name}의 {year}λ…„ 학사일정은 λ‹€μŒκ³Ό κ°™λ‹€:\n{text}\n이 λ‚΄μš©μ„ μš”μ•½ν•΄μ€˜. μ£Όμš” 일정 μ€‘μ‹¬μœΌλ‘œ κ°„κ²°ν•˜κ²Œ."
36
  result = llm([{"role": "user", "content": prompt}])
37
  return result[0]["generated_text"].replace(prompt, "").strip()
38
 
39
- # ──────── μ§€μ—­ μ½”λ“œ λͺ©λ‘ ────────
 
 
 
 
40
  region_options = {
41
  "B10": "μ„œμšΈ", "C10": "λΆ€μ‚°", "D10": "λŒ€κ΅¬", "E10": "인천", "F10": "κ΄‘μ£Ό", "G10": "λŒ€μ „",
42
  "H10": "μšΈμ‚°", "I10": "μ„Έμ’…", "J10": "κ²½κΈ°", "K10": "강원", "M10": "좩뢁", "N10": "좩남",
43
  "P10": "전뢁", "Q10": "전남", "R10": "경뢁", "S10": "경남", "T10": "제주"
44
  }
45
 
46
- # ──────── μ›” μΌμ •λ§Œ λ¨Όμ € λ³΄μ—¬μ£ΌλŠ” ν•¨μˆ˜ ────────
47
- def fetch_month_schedule(region_code, school_name, year, month):
48
- api_key = os.environ.get("NEIS_API_KEY", "a69e08342c8947b4a52cd72789a5ecaf")
49
-
50
- if not school_name.strip():
51
- return "❗ 학ꡐλͺ…을 μž…λ ₯ν•΄μ£Όμ„Έμš”.", "", "", None
52
-
53
- school_code, confirmed_region = get_school_info(region_code, school_name, api_key)
54
- if not school_code:
55
- return "❗ 학ꡐ 정보λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.", "", "", None
56
-
57
- schedule_rows = get_schedule(confirmed_region, school_code, year, api_key)
58
- if not schedule_rows:
59
- return "ℹ️ 학사일정 정보가 μ—†μŠ΅λ‹ˆλ‹€.", "", "", None
60
-
61
- # 월별 일정 필터링
62
- month_rows = [r for r in schedule_rows if r["AA_YMD"].startswith(f"{year}{month:02}")]
63
- month_display = "\n".join(
64
- f"{datetime.strptime(r['AA_YMD'], '%Y%m%d').strftime('%Y-%m-%d')} - {r['EVENT_NM']}"
65
- for r in month_rows
66
- ) or "πŸ“­ μ„ νƒν•œ 월에 ν•΄λ‹Ήν•˜λŠ” 일정이 μ—†μŠ΅λ‹ˆλ‹€."
67
-
68
- return f"βœ… {school_name}의 {year}λ…„ {month}μ›” μΌμ •μž…λ‹ˆλ‹€.", month_display, "✨ [μ•„λž˜ λ²„νŠΌμœΌλ‘œ μš”μ•½ 생성]", schedule_rows
69
-
70
- # ──────── μš”μ•½ λ²„νŠΌμ΄ λˆŒλ Έμ„ λ•Œ μ‹€ν–‰λ˜λŠ” ν•¨μˆ˜ ────────
71
- def generate_summary(school_name, year, rows):
72
- if not rows:
73
- return "⚠️ λ¨Όμ € 일정을 λΆˆλŸ¬μ™€ μ£Όμ„Έμš”."
74
- return summarize_schedule(rows, school_name, year)
75
-
76
- # ──────── Gradio μΈν„°νŽ˜μ΄μŠ€ ꡬ성 ────────
77
- with gr.Blocks(title="학사일정 μš”μ•½ μΊ˜λ¦°λ”") as demo:
78
- gr.Markdown("## 🏫 학사일정 쑰회 및 AI μš”μ•½ (google/gemma-2-2b-it)")
79
-
80
- with gr.Row():
81
- region = gr.Dropdown(label="μ§€μ—­ ꡐ윑청", choices=list(region_options.keys()), value="B10", interactive=True)
82
- school_name = gr.Textbox(label="학ꡐλͺ…", placeholder="예: μƒλ¦¬μ΄ˆλ“±ν•™κ΅")
83
- with gr.Row():
84
- year = gr.Dropdown(label="년도", choices=[2022, 2023, 2024, 2025], value=2024)
85
- month = gr.Slider(label="μ›”", minimum=1, maximum=12, value=7, step=1)
86
-
87
- load_btn = gr.Button("πŸ“… μ›” 일정 뢈러였기")
88
- status = gr.Markdown()
89
- month_output = gr.Textbox(label="πŸ“† μ„ νƒν•œ μ›”μ˜ 일정", lines=8)
90
- summary_notice = gr.Markdown()
91
- stored_rows = gr.State()
92
-
93
- with gr.Accordion("✨ 1λ…„μΉ˜ AI μš”μ•½ 보기", open=False):
94
- summarize_btn = gr.Button("πŸ€– μš”μ•½ μƒμ„±ν•˜κΈ°")
95
- summary_output = gr.Textbox(label="πŸ“ 학사일정 μš”μ•½", lines=6)
96
-
97
- # 이벀트 μ—°κ²°
98
- load_btn.click(fn=fetch_month_schedule,
99
- inputs=[region, school_name, year, month],
100
- outputs=[status, month_output, summary_notice, stored_rows])
101
-
102
- summarize_btn.click(fn=generate_summary,
103
- inputs=[school_name, year, stored_rows],
104
- outputs=summary_output)
105
-
106
- demo.launch()
 
1
  import os
2
  import requests
3
+ import streamlit as st
4
  from datetime import datetime
5
  from transformers import pipeline
6
 
7
+ # Gemma λͺ¨λΈ λ‘œλ”©
8
+ @st.cache_resource
9
+ def load_model():
10
+ return pipeline("text-generation", model="google/gemma-2-2b-it", max_new_tokens=512)
11
 
12
+ llm = load_model()
13
+
14
+ # 학ꡐ 정보 및 일정 κ°€μ Έμ˜€κΈ° ν•¨μˆ˜
15
  def get_school_info(region_code, school_name, api_key):
16
  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}"
17
  res = requests.get(url)
 
32
  lines = []
33
  for row in rows:
34
  date = row["AA_YMD"]
35
+ dt = datetime.strptime(date, "%Y%m%d").strftime("%-m月 %-dζ—₯")
36
  event = row["EVENT_NM"]
37
  lines.append(f"{dt}: {event}")
38
  text = "\n".join(lines)
39
+ prompt = f"{school_name}κ°€ {year}년도에 κ°€μ§€λŠ” 학사일정은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:\n{text}\nμ£Όμš” 일정을 κ°€λ³€μ μœΌλ‘œ μš”μ•½ν•΄μ£Όμ„Έμš”."
40
  result = llm([{"role": "user", "content": prompt}])
41
  return result[0]["generated_text"].replace(prompt, "").strip()
42
 
43
+ # Streamlit UI
44
+ st.set_page_config(page_title="학사일정 μΊ˜λ¦°λ”", layout="centered")
45
+ st.title("πŸ“… 학사일정 μΊ˜λ¦°λ” + AI μš”μ•½")
46
+ st.markdown("NEIS APIμ—μ„œ 학사일정을 뢈러였고 FullCalendar둜 μ‹œκ°ν™”ν•©λ‹ˆλ‹€.")
47
+
48
  region_options = {
49
  "B10": "μ„œμšΈ", "C10": "λΆ€μ‚°", "D10": "λŒ€κ΅¬", "E10": "인천", "F10": "κ΄‘μ£Ό", "G10": "λŒ€μ „",
50
  "H10": "μšΈμ‚°", "I10": "μ„Έμ’…", "J10": "κ²½κΈ°", "K10": "강원", "M10": "좩뢁", "N10": "좩남",
51
  "P10": "전뢁", "Q10": "전남", "R10": "경뢁", "S10": "경남", "T10": "제주"
52
  }
53
 
54
+ with st.form("query_form"):
55
+ region = st.selectbox("μ§€μ—­ ꡐ윑청", options=list(region_options.keys()), format_func=lambda x: f"{region_options[x]} ({x})")
56
+ school_name = st.text_input("학ꡐλͺ…", placeholder="예: μƒλ¦¬μ΄ˆλ“±ν•™κ΅")
57
+ year = st.selectbox("년도", options=[2022, 2023, 2024, 2025], index=2)
58
+ submitted = st.form_submit_button("πŸ“… 학사일정 뢈러였기")
59
+
60
+ if submitted:
61
+ with st.spinner("일정 λΆˆλŸ¬μ˜€λŠ” 쀑..."):
62
+ api_key = os.environ.get("NEIS_API_KEY", "a69e08342c8947b4a52cd72789a5ecaf")
63
+ school_code, region_code = get_school_info(region, school_name, api_key)
64
+ if not school_code:
65
+ st.error("학ꡐ 정보λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.")
66
+ else:
67
+ schedule_rows = get_schedule(region_code, school_code, year, api_key)
68
+ if not schedule_rows:
69
+ st.info("ν•΄λ‹Ή 쑰건의 학사일정이 μ—†μŠ΅λ‹ˆλ‹€.")
70
+ else:
71
+ # 일정 데이터λ₯Ό HTML μΊ˜λ¦°λ”μ— λ„£κΈ° μœ„ν•œ JSON 생성
72
+ events = [
73
+ {
74
+ "title": row["EVENT_NM"],
75
+ "start": datetime.strptime(row["AA_YMD"], "%Y%m%d").strftime("%Y-%m-%d")
76
+ }
77
+ for row in schedule_rows
78
+ ]
79
+
80
+ import json
81
+ event_json = json.dumps(events, ensure_ascii=False)
82
+
83
+ # FullCalendar μ‚½μž…
84
+ st.components.v1.html(f"""
85
+ <html>
86
+ <head>
87
+ <link href='https://cdn.jsdelivr.net/npm/[email protected]/index.global.min.css' rel='stylesheet' />
88
+ <script src='https://cdn.jsdelivr.net/npm/[email protected]/index.global.min.js'></script>
89
+ <script>
90
+ document.addEventListener('DOMContentLoaded', function() {{
91
+ var calendarEl = document.getElementById('calendar');
92
+ var calendar = new FullCalendar.Calendar(calendarEl, {{
93
+ initialView: 'dayGridMonth',
94
+ locale: 'ko',
95
+ height: 600,
96
+ events: {event_json}
97
+ }});
98
+ calendar.render();
99
+ }});
100
+ </script>
101
+ </head>
102
+ <body>
103
+ <div id='calendar'></div>
104
+ </body>
105
+ </html>
106
+ """, height=650)
107
+
108
+ with st.expander("✨ 1λ…„μΉ˜ μš”μ•½ 보기", expanded=False):
109
+ if st.button("πŸ€– μš”μ•½ μƒμ„±ν•˜κΈ°"):
110
+ with st.spinner("Gemma λͺ¨λΈμ΄ μš”μ•½ 쀑..."):
111
+ summary = summarize_schedule(schedule_rows, school_name, year)
112
+ st.success("μš”μ•½ μ™„λ£Œ!")
113
+ st.markdown(f"**{school_name} {year}λ…„ 학사일정 μš”μ•½:**\n\n{summary}")