gamification / app.py
ll7098ll's picture
Update app.py
ae8ada4 verified
import os
import time
import streamlit as st
import google.generativeai as genai
from streamlit_extras.colored_header import colored_header
from streamlit_extras.add_vertical_space import add_vertical_space
import markdown
# Google Gemini API Key μ„€μ •
genai.configure(api_key=os.environ["GEMINI_API_KEY"])
# λͺ¨λΈ μ„€μ •
generation_config = {
"temperature": 1,
"top_p": 0.95,
"top_k": 40,
"max_output_tokens": 8192,
"response_mime_type": "text/plain",
}
model = genai.GenerativeModel(
model_name="gemini-2.0-flash",
generation_config=generation_config,
)
# ν”„λ‘¬ν”„νŠΈ μ„€μ •
SYSTEM_PROMPT = """
당신은 κ΅μˆ˜ν•™μŠ΅ ν™œλ™ 섀계 μ „λ¬Έκ°€, ꡐ과ꡐ윑 λ‚΄μš© μ „λ¬Έκ°€, κ΅μœ‘κ³΅ν•™μžμ΄λ©°, 특히 κ²Œμ΄λ―Έν”ΌμΌ€μ΄μ…˜(κ²Œμž„ν™”) μˆ˜μ—… 섀계 μ „λ¬Έκ°€μž…λ‹ˆλ‹€.
κ²Œμ΄λ―Έν”ΌμΌ€μ΄μ…˜(κ²Œμž„ν™”) μˆ˜μ—… 섀계 μš”μ²­:
μ„ μƒλ‹˜λ“€μ΄ ν™œλ™ μ£Όμ œμ™€ ν•™μŠ΅ λͺ©ν‘œλ₯Ό μž…λ ₯ν•˜λ©΄, ν•΄λ‹Ή μ£Όμ œμ™€ λͺ©ν‘œμ— μ΅œμ ν™”λœ κ²Œμ΄λ―Έν”ΌμΌ€μ΄μ…˜(κ²Œμž„ν™”) μš”μ†Œλ₯Ό λ°˜μ˜ν•˜μ—¬ μˆ˜μ—… ν™œλ™μ„ μƒμ„Έν•˜κ²Œ μ„€κ³„ν•©λ‹ˆλ‹€.
핡심 섀계 원칙:
μˆ˜μ—… λ‚΄μš©κ³Όμ˜ 찰떑같은 톡합: κ²Œμ΄λ―Έν”ΌμΌ€μ΄μ…˜ μš”μ†ŒλŠ” λ‹¨μˆœνžˆ ν₯λ―Έ μœ λ°œμ„ μœ„ν•œ μž₯μΉ˜κ°€ μ•„λ‹ˆλΌ, μˆ˜μ—… λ‚΄μš©κ³Ό μžμ—°μŠ€λŸ½κ²Œ μ—°κ²°λ˜μ–΄ ν•™μŠ΅ λͺ©ν‘œ 달성을 효과적으둜 지원해야 ν•©λ‹ˆλ‹€.
체계적 사고(CoT; Chain of Thought) 기반 섀계: 각 ν™œλ™ 단계λ₯Ό μ²΄κ³„μ μœΌλ‘œ μ„€κ³„ν•˜μ—¬, 학생듀이 λ‹¨κ³„λ³„λ‘œ ν•™μŠ΅ λ‚΄μš©μ„ μŠ΅λ“ν•˜κ³  사고λ ₯을 ν™•μž₯ν•  수 μžˆλ„λ‘ μœ λ„ν•©λ‹ˆλ‹€.
ν•™μŠ΅ λͺ©ν‘œ 쀑심 섀계: λͺ¨λ“  κ²Œμ΄λ―Έν”ΌμΌ€μ΄μ…˜ μš”μ†Œμ™€ ν™œλ™μ€ λͺ…ν™•ν•˜κ²Œ μ„€μ •λœ ν•™μŠ΅ λͺ©ν‘œ 달성을 μ΅œμš°μ„ μœΌλ‘œ ν•©λ‹ˆλ‹€.
κ²Œμ΄λ―Έν”ΌμΌ€μ΄μ…˜(κ²Œμž„ν™”) μš”μ†Œ: (μ•„λž˜ μš”μ†Œλ“€μ„ ν•™μŠ΅ λ‚΄μš©κ³Ό λͺ©ν‘œμ— 맞게 적절히 ν™œμš©ν•˜κ³  μ‘°μ •ν•©λ‹ˆλ‹€.)
포인트/λ°°μ§€/λ¦¬λ”λ³΄λ“œ: ν•™μŠ΅ μ„±κ³Όλ₯Ό μ‹œκ°μ μœΌλ‘œ 보여주고, 동기 λΆ€μ—¬λ₯Ό κ°•ν™”ν•©λ‹ˆλ‹€. (예: ν€΄μ¦ˆ μ •λ‹΅ μ‹œ 포인트 λΆ€μ—¬, 탐ꡬ ν™œλ™ 성곡 μ‹œ λ°°μ§€ μˆ˜μ—¬, λˆ„μ  포인트 기반 λ¦¬λ”λ³΄λ“œ 운영)
κ·œμΉ™/보상: ν•™μŠ΅ λͺ©ν‘œ 달성에 도움이 λ˜λŠ” κ·œμΉ™μ„ μ„€μ •ν•˜κ³ , 성취에 λŒ€ν•œ μ μ ˆν•œ 보상을 μ œκ³΅ν•©λ‹ˆλ‹€. (예: νŒ€ ν˜‘λ™ κ·œμΉ™, κ°œμΈλ³„ μ±Œλ¦°μ§€ 성곡 보상, 깜짝 보상)
μŠ€ν† λ¦¬ν…”λ§: ν•™μŠ΅ λ‚΄μš©μ„ ν₯미둜운 μ΄μ•ΌκΈ°λ‘œ κ΅¬μ„±ν•˜μ—¬ λͺ°μž…도λ₯Ό λ†’μž…λ‹ˆλ‹€. (예: 역사 속 인물이 λ˜μ–΄ λ―Έμ…˜ μˆ˜ν–‰, κ³Όν•™μžκ°€ λ˜μ–΄ 탐ꡬ ν™œλ™ μ§„ν–‰)
레벨/μ§„ν–‰: ν•™μŠ΅ λ‚œμ΄λ„λ₯Ό μ μ§„μ μœΌλ‘œ λ†’μ—¬ 성취감을 λŠλΌλ„λ‘ ν•©λ‹ˆλ‹€. (예: ν•™μŠ΅ λ‚΄μš© 이해도에 따라 레벨 λΆ€μ—¬, μƒˆλ‘œμš΄ 레벨 도전 과제 제곡)
경쟁/ν˜‘λ ₯: κ±΄κ°•ν•œ 경쟁과 ν˜‘λ ₯을 톡해 ν•™μŠ΅ 효과λ₯Ό λ†’μž…λ‹ˆλ‹€. (예: νŒ€ λŒ€ν•­ ν€΄μ¦ˆ λŒ€νšŒ, ν˜‘λ™ ν”„λ‘œμ νŠΈ)
λ―ΈμŠ€ν„°λ¦¬ μš”μ†Œ: 예츑 λΆˆκ°€λŠ₯ν•œ μš”μ†Œλ‚˜ λ―ΈμŠ€ν„°λ¦¬ 과제λ₯Ό 톡해 ν˜ΈκΈ°μ‹¬μ„ μžκ·Ήν•˜κ³  μ°Έμ—¬λ₯Ό μœ λ„ν•©λ‹ˆλ‹€. (예: μˆ¨κ²¨μ§„ λ‹¨μ„œ μ°ΎκΈ°, λΉ„λ°€ λ―Έμ…˜ ν•΄κ²°)
선택과 κ²°κ³Ό: ν•™μƒμ˜ 선택에 따라 κ²°κ³Όκ°€ λ‹¬λΌμ§€λŠ” μš”μ†Œλ₯Ό 톡해 주도적인 ν•™μŠ΅ μ°Έμ—¬λ₯Ό μœ λ„ν•©λ‹ˆλ‹€. (예: ν•™μŠ΅ 경둜 선택, 문제 ν•΄κ²° 방식 선택)
ν™œλ™ ꡬ성 μš”μ†Œ: (μ•„λž˜ μš”μ†Œλ“€μ„ ν¬ν•¨ν•˜μ—¬ μƒμ„Έν•˜κ²Œ μˆ˜μ—… ν™œλ™μ„ μ„€κ³„ν•©λ‹ˆλ‹€.)
ν™œλ™ 주제 및 ν•™μŠ΅ λͺ©ν‘œ: μ œμ‹œλœ ν™œλ™ μ£Όμ œμ™€ ν•™μŠ΅ λͺ©ν‘œλ₯Ό λͺ…ν™•νžˆ μ„€μ •ν•©λ‹ˆλ‹€.
ν™œλ™ 단계별 μ•ˆλ‚΄: 각 단계별 ν™œλ™ λͺ©ν‘œ, μˆ˜ν–‰ 방법, 평가 기쀀을 ꡬ체적으둜 μ œμ‹œν•©λ‹ˆλ‹€. (체계적 사고 기반)
ν™œλ™ μ€€λΉ„λ¬Ό 및 자료: ν™œλ™μ— ν•„μš”ν•œ μ€€λΉ„λ¬Ό, ν•™μŠ΅ 자료, μ°Έκ³  자료λ₯Ό μƒμ„Ένžˆ μ•ˆλ‚΄ν•©λ‹ˆλ‹€.
ν™œλ™ 유의점: 학생과 ꡐ사가 ν™œλ™ μ‹œ μœ μ˜ν•΄μ•Ό ν•  사항을 λͺ…μ‹œν•©λ‹ˆλ‹€.
학생 제곡 ν™œλ™ μ•ˆλ‚΄ 자료: 학생듀이 μ‰½κ²Œ 이해할 수 μžˆλ„λ‘ ν™œλ™ μ•ˆλ‚΄ 자료λ₯Ό ꡬ체적이고 λͺ…ν™•ν•˜κ²Œ μ œκ³΅ν•©λ‹ˆλ‹€. (μ˜ˆμ‹œ 포함)
"""
def generate_curriculum(topic, grade):
"""
ν™œλ™ μ£Όμ œμ™€ 학년을 μž…λ ₯λ°›μ•„ κ²Œμ΄λ―Έν”ΌμΌ€μ΄μ…˜ μˆ˜μ—…μ„ μƒμ„±ν•©λ‹ˆλ‹€.
Args:
topic (str): ν™œλ™ 주제
grade (str): ν•™λ…„ μˆ˜μ€€
Returns:
str: μƒμ„±λœ ν™œλ™
"""
prompt = [
SYSTEM_PROMPT,
f"**ν™œλ™ 주제:** {topic}",
f"**ν•™λ…„ μˆ˜μ€€:** {grade}",
"**ν™œλ™:**",
]
response = model.generate_content(prompt, stream=True)
collected_text = ""
for token in response:
chunk = token.text
collected_text += chunk
yield collected_text # μ‹€μ‹œκ°„ 좜λ ₯을 μœ„ν•΄ yield μ‚¬μš©
time.sleep(0.03) # 좜λ ₯ 속도 쑰절
# Streamlit Interface
colored_header(
label="κ²Œμ΄λ―Έν”ΌμΌ€μ΄μ…˜ μˆ˜μ—… 섀계 λ„μš°λ―Έ",
description="μ„ μƒλ‹˜μ΄ ν™œλ™ μ£Όμ œμ™€ ν•™λ…„ μˆ˜μ€€μ„ μž…λ ₯ν•˜μ‹œλ©΄ κ²Œμ΄λ―Έν”ΌμΌ€μ΄μ…˜ μš”μ†Œλ₯Ό ν¬ν•¨ν•˜μ—¬ μˆ˜μ—…μ„ ꡬ체적으둜 μ„€κ³„ν•΄μ€λ‹ˆλ‹€.",
color_name="red-70",
)
add_vertical_space(1)
# ν•™λ…„ 선택 μΆ”κ°€
grade_level = st.selectbox("ν•™λ…„ μˆ˜μ€€μ„ μ„ νƒν•˜μ„Έμš”", ["μ΄ˆλ“±ν•™κ΅ 1ν•™λ…„", "μ΄ˆλ“±ν•™κ΅ 2ν•™λ…„", "μ΄ˆλ“±ν•™κ΅ 3ν•™λ…„", "μ΄ˆλ“±ν•™κ΅ 4ν•™λ…„", "μ΄ˆλ“±ν•™κ΅ 5ν•™λ…„", "μ΄ˆλ“±ν•™κ΅ 6ν•™λ…„"])
topic = st.text_area("ν™œλ™ 주제", height=100)
generate_button = st.button("κ²Œμ΄λ―Έν”ΌμΌ€μ΄μ…˜ μˆ˜μ—… 섀계")
# 좜λ ₯ μ˜μ—­ μ •μ˜
output_area = st.empty()
if generate_button and topic and grade_level:
output_text = ""
output_area.markdown(output_text)
try:
for partial_output in generate_curriculum(topic, grade_level):
output_text = partial_output
output_area.markdown(output_text)
except Exception as e:
st.error(f"였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {str(e)}")
# 볡사 λ²„νŠΌ μΆ”κ°€
if output_text:
if st.button("좜λ ₯ λ‚΄μš© 볡사"):
st.write(output_text)
st.success("좜λ ₯ λ‚΄μš©μ΄ λ³΅μ‚¬λ˜μ—ˆμŠ΅λ‹ˆλ‹€!")