yongyeol commited on
Commit
071ecd9
Β·
verified Β·
1 Parent(s): 3ea2291

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +76 -100
app.py CHANGED
@@ -1,114 +1,90 @@
1
- # app.py
2
- import gradio as gr
3
  import requests
 
4
  from datetime import datetime
5
- from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
6
- import os
7
 
8
- # βœ… Hugging Face token 인증 (ν•„μš”μ‹œ ν™˜κ²½λ³€μˆ˜ μ‚¬μš©)
9
- from huggingface_hub import login
10
- login(token=os.environ.get("HF_TOKEN"), new_session=False)
11
 
12
- # βœ… Gemma λͺ¨λΈ λ‘œλ“œ (gated repo)
13
- model_id = "google/gemma-2-2b-it"
14
- tokenizer = AutoTokenizer.from_pretrained(model_id, token=os.environ.get("HF_TOKEN"))
15
- model = AutoModelForCausalLM.from_pretrained(model_id, token=os.environ.get("HF_TOKEN"))
16
- generator = pipeline("text-generation", model=model, tokenizer=tokenizer)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
- # βœ… NEIS API
19
- NEIS_KEY = "a69e08342c8947b4a52cd72789a5ecaf"
20
- SCHOOL_INFO_URL = "https://open.neis.go.kr/hub/schoolInfo"
21
- SCHEDULE_URL = "https://open.neis.go.kr/hub/SchoolSchedule"
22
 
23
- REGIONS = {
24
- "μ„œμšΈνŠΉλ³„μ‹œκ΅μœ‘μ²­": "B10",
25
- "κ²½μƒλΆλ„κ΅μœ‘μ²­": "R10"
26
- }
 
 
27
 
28
- MONTH_NAMES = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]
 
29
 
 
30
 
31
- def get_school_code(region_code, school_name):
32
- params = {
33
- "KEY": NEIS_KEY,
34
- "Type": "json",
35
- "pIndex": 1,
36
- "pSize": 1,
37
- "SCHUL_NM": school_name,
38
- "ATPT_OFCDC_SC_CODE": region_code
39
- }
40
- res = requests.get(SCHOOL_INFO_URL, params=params)
41
- data = res.json()
42
- try:
43
- return data["schoolInfo"][1]["row"][0]["SD_SCHUL_CODE"], data["schoolInfo"][1]["row"][0]["ATPT_OFCDC_SC_CODE"]
44
- except:
45
- return None, None
46
-
47
-
48
- def get_schedule(region_code, school_code, year, month):
49
- from_ymd = f"{year}{month}01"
50
- to_ymd = f"{year}{month}31"
51
- params = {
52
- "KEY": NEIS_KEY,
53
- "Type": "json",
54
- "pIndex": 1,
55
- "pSize": 100,
56
- "ATPT_OFCDC_SC_CODE": region_code,
57
- "SD_SCHUL_CODE": school_code,
58
- "AA_FROM_YMD": from_ymd,
59
- "AA_TO_YMD": to_ymd
60
- }
61
- res = requests.get(SCHEDULE_URL, params=params)
62
- data = res.json()
63
- try:
64
- return data["SchoolSchedule"][1]["row"]
65
- except:
66
- return []
67
 
 
 
 
 
 
 
 
 
68
 
69
- def generate_answer(region, school_name, year, month, question):
70
- now = datetime.now()
71
- if not year:
72
- year = str(now.year)
73
- if not month:
74
- month = str(now.month).zfill(2)
75
 
76
- region_code = REGIONS.get(region)
77
- if not region_code:
78
- return "❌ 잘λͺ»λœ κ΅μœ‘μ²­μž…λ‹ˆλ‹€."
79
 
80
- school_code, confirmed_region = get_school_code(region_code, school_name)
81
- if not school_code:
82
- return "❌ 학ꡐ 정보λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€."
83
 
84
- schedule_rows = get_schedule(confirmed_region, school_code, year, month)
85
- if not schedule_rows:
86
- schedule_text = "ν˜„μž¬ 일정 μ •λ³΄λŠ” μ—†μŠ΅λ‹ˆλ‹€."
87
- else:
88
- schedule_text = "\n".join(f"{row['AA_YMD']}: {row['EVENT_NM']}" for row in schedule_rows)
89
-
90
- prompt = f"""일정 정보:
91
- {schedule_text}
92
-
93
- μ‚¬μš©μž 질문: {question}
94
-
95
- μžμ—°μŠ€λŸ½κ²Œ ν•œκ΅­μ–΄λ‘œ λŒ€λ‹΅ν•΄ μ£Όμ„Έμš”."""
96
-
97
- result = generator(prompt, max_new_tokens=200, temperature=0.7)[0]["generated_text"]
98
- return result
99
-
100
-
101
- with gr.Interface(
102
- fn=generate_answer,
103
- inputs=[
104
- gr.Dropdown(choices=list(REGIONS.keys()), label="ꡐ윑청 선택"),
105
- gr.Textbox(label="학ꡐλͺ… μž…λ ₯"),
106
- gr.Textbox(label="년도 μž…λ ₯ (예: 2025, λΉ„μ›Œλ‘λ©΄ ν˜„μž¬ 연도 μ‚¬μš©)"),
107
- gr.Dropdown(choices=MONTH_NAMES, label="μ›” 선택 (예: 07, λΉ„μ›Œλ‘λ©΄ ν˜„μž¬ μ›” μ‚¬μš©)"),
108
- gr.Textbox(label="질문 μž…λ ₯ (예: 여름방학은 μ–Έμ œμ•Ό?)")
109
- ],
110
- outputs=gr.Textbox(label="GPT의 응닡"),
111
- title="πŸ“… 학사일정 + GPT 챗봇 (Gemma 2B)",
112
- description="Gemma λͺ¨λΈ 기반의 학사일정 μ±—λ΄‡μž…λ‹ˆλ‹€. 연도/월은 μƒλž΅ μ‹œ 였늘 κΈ°μ€€μœΌλ‘œ μ²˜λ¦¬λ©λ‹ˆλ‹€."
113
- ) as app:
114
- app.launch()
 
1
+ import os
 
2
  import requests
3
+ import gradio as gr
4
  from datetime import datetime
5
+ from transformers import pipeline
 
6
 
7
+ # ────────────────────────────── λͺ¨λΈ 뢈러였기 ──────────────────────────────
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)
14
+ data = res.json()
15
+ school = data.get("schoolInfo", [{}])[1].get("row", [{}])[0]
16
+ return school.get("SD_SCHUL_CODE"), school.get("ATPT_OFCDC_SC_CODE")
17
+
18
+ def get_schedule(region_code, school_code, year, api_key):
19
+ from_ymd = f"{year}0101"
20
+ to_ymd = f"{year}1231"
21
+ 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}"
22
+ res = requests.get(url)
23
+ data = res.json()
24
+ rows = data.get("SchoolSchedule", [{}])[1].get("row", [])
25
+ return rows
26
+
27
+ 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
+ def load_and_summarize(region_code, school_name, year, month):
41
+ api_key = os.environ.get("NEIS_API_KEY", "a69e08342c8947b4a52cd72789a5ecaf")
42
+
43
+ if not school_name.strip():
44
+ return "❗ 학ꡐλͺ…을 μž…λ ₯ν•΄μ£Όμ„Έμš”.", "", ""
45
+
46
+ school_code, confirmed_region = get_school_info(region_code, school_name, api_key)
47
+ if not school_code:
48
+ return "❗ 학ꡐ 정보λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€. μž…λ ₯을 ν™•μΈν•΄μ£Όμ„Έμš”.", "", ""
49
 
50
+ schedule_rows = get_schedule(confirmed_region, school_code, year, api_key)
51
+ if not schedule_rows:
52
+ return "ℹ️ 학사일정 정보가 μ—†μŠ΅λ‹ˆλ‹€.", "", ""
 
53
 
54
+ # 월별 일정 필터링
55
+ month_rows = [r for r in schedule_rows if r["AA_YMD"].startswith(f"{year}{month:02}")]
56
+ month_display = "\n".join(
57
+ f"{datetime.strptime(r['AA_YMD'], '%Y%m%d').strftime('%Y-%m-%d')} - {r['EVENT_NM']}"
58
+ for r in month_rows
59
+ ) or "πŸ“­ μ„ νƒν•œ 월에 ν•΄λ‹Ήν•˜λŠ” 일정이 μ—†μŠ΅λ‹ˆλ‹€."
60
 
61
+ # μš”μ•½ 생성
62
+ summary = summarize_schedule(schedule_rows, school_name, year)
63
 
64
+ return f"βœ… {school_name}의 {year}λ…„ {month}μ›” μΌμ •μž…λ‹ˆλ‹€.", month_display, summary
65
 
66
+ # ────────────────────────────── Gradio UI ꡬ성 ──────────────────────────────
67
+ region_options = {
68
+ "B10": "μ„œμšΈ", "C10": "λΆ€μ‚°", "D10": "λŒ€κ΅¬", "E10": "인천", "F10": "κ΄‘μ£Ό", "G10": "λŒ€μ „",
69
+ "H10": "μšΈμ‚°", "I10": "μ„Έμ’…", "J10": "κ²½κΈ°", "K10": "강원", "M10": "좩뢁", "N10": "좩남",
70
+ "P10": "전뢁", "Q10": "전남", "R10": "경뢁", "S10": "경남", "T10": "제주"
71
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
+ with gr.Blocks(title="학사일정 μš”μ•½ μΊ˜λ¦°λ”") as demo:
74
+ gr.Markdown("## 🏫 학사일정 쑰회 및 AI μš”μ•½ (google/gemma-2-2b-it)")
75
+ with gr.Row():
76
+ region = gr.Dropdown(label="μ§€μ—­ ꡐ윑청", choices=list(region_options.keys()), value="B10", interactive=True)
77
+ school_name = gr.Textbox(label="학ꡐλͺ…", placeholder="예: μƒλ¦¬μ΄ˆλ“±ν•™κ΅")
78
+ with gr.Row():
79
+ year = gr.Dropdown(label="년도", choices=[2022, 2023, 2024, 2025], value=2024)
80
+ month = gr.Slider(label="μ›”", minimum=1, maximum=12, value=7, step=1)
81
 
82
+ btn = gr.Button("πŸ“… 일정 뢈러였기 및 μš”μ•½")
 
 
 
 
 
83
 
84
+ status = gr.Markdown()
85
+ month_output = gr.Textbox(label="πŸ“† μ„ νƒν•œ μ›”μ˜ 일정", lines=8)
86
+ summary_output = gr.Textbox(label="πŸ“ 1λ…„ 학사일정 μš”μ•½ (Gemma)", lines=6)
87
 
88
+ btn.click(fn=load_and_summarize, inputs=[region, school_name, year, month], outputs=[status, month_output, summary_output])
 
 
89
 
90
+ demo.launch()