Yescia's picture
Update app.py
773e819 verified
import streamlit as st
import requests
# -------------------------------
# 1. λ¬Έμ„œ νŒŒμ‹± ν•¨μˆ˜ (HTML μΆ”μΆœ)
# -------------------------------
def parse_document_to_html(file, api_key):
url = "https://api.upstage.ai/v1/document-ai/document-parse"
headers = {'Authorization': f'Bearer {api_key}'}
files = {"document": file}
data = {
"base64_encoding": "['table']",
"model": "document-parse"
}
response = requests.post(url, headers=headers, files=files, data=data)
if response.status_code != 200:
return None, f"λ¬Έμ„œ νŒŒμ‹± μ‹€νŒ¨ (status code: {response.status_code})"
html_text = response.json().get("content", {}).get("html", "")
return html_text, None
# -------------------------------
# 2. Solar-Pro: 질문 응닡
# -------------------------------
def chat_with_solar_document(html_text, user_question, history, api_key):
url = "https://api.upstage.ai/v1/chat/completions"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
system_prompt = f"""
λ‹€μŒμ€ HTML ν˜•μ‹μœΌλ‘œ μΆ”μΆœλœ λ¬Έμ„œμž…λ‹ˆλ‹€.
HTML μ•ˆμ˜ λ‚΄μš©λ§Œ 근거둜 μ‚Όμ•„ ν•™μƒμ˜ μ§ˆλ¬Έμ— μ •ν™•ν•˜κ³  μ‰½κ²Œ λ‹΅ν•΄μ£Όμ„Έμš”.
λ¬Έμ„œ:
{html_text}
"""
messages = [{"role": "system", "content": system_prompt}]
for user, bot in history:
messages.append({"role": "user", "content": user})
messages.append({"role": "assistant", "content": bot})
messages.append({"role": "user", "content": user_question})
payload = {
"model": "solar-pro",
"messages": messages,
"temperature": 0,
"max_tokens": 2048
}
try:
response = requests.post(url, headers=headers, json=payload)
if response.status_code != 200:
return None, history, f"μƒνƒœ μ½”λ“œ: {response.status_code}"
bot_reply = response.json()["choices"][0]["message"]["content"]
history.append((user_question, bot_reply))
return bot_reply, history, None
except Exception as e:
return None, history, f"μ˜ˆμ™Έ λ°œμƒ: {str(e)}"
# -------------------------------
# 3. μΆ”μ²œ ν‚€μ›Œλ“œ 생성
# -------------------------------
def get_recommended_keywords(html_text, user_question, api_key):
url = "https://api.upstage.ai/v1/chat/completions"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
prompt = f"""
λ‹€μŒμ€ HTML둜 μΆ”μΆœλœ 문제 λ‚΄μš©μž…λ‹ˆλ‹€.
λ¬Έμ œμ™€ μ§ˆλ¬Έμ„ λ°”νƒ•μœΌλ‘œ ν•™μƒμ—κ²Œ 도움이 될 λ§Œν•œ 곡뢀 ν‚€μ›Œλ“œ 3κ°€μ§€λ₯Ό μ œμ•ˆν•΄μ£Όμ„Έμš”. ν‚€μ›Œλ“œλ§Œ 콀마둜 κ΅¬λΆ„ν•΄μ„œ 좜λ ₯ν•΄μ£Όμ„Έμš”.
λ¬Έμ„œ: {html_text}
학생 질문: {user_question}
"""
payload = {
"model": "solar-pro",
"messages": [{"role": "user", "content": prompt}],
"temperature": 0.5,
"max_tokens": 100
}
try:
res = requests.post(url, headers=headers, json=payload)
if res.status_code != 200:
return []
raw_text = res.json()["choices"][0]["message"]["content"]
keywords = [kw.strip() for kw in raw_text.split(",") if kw.strip()]
return keywords[:3]
except:
return []
# -------------------------------
# 4. ν‚€μ›Œλ“œλ³„ 곡뢀 팁 생성
# -------------------------------
def get_study_tip_for_keyword(keyword, api_key):
url = "https://api.upstage.ai/v1/chat/completions"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
prompt = f"""
학생이 '{keyword}'을(λ₯Ό) κ³΅λΆ€ν•˜κ³  μ‹Άμ–΄ν•©λ‹ˆλ‹€.
κ°œλ… 이해, 곡뢀 방법, μΆ”μ²œ μˆœμ„œ 등을 포함해 μΉœμ ˆν•˜κ²Œ ν•™μŠ΅ νŒμ„ μ œκ³΅ν•΄μ£Όμ„Έμš”.
"""
payload = {
"model": "solar-pro",
"messages": [{"role": "user", "content": prompt}],
"temperature": 0.7,
"max_tokens": 300
}
try:
res = requests.post(url, headers=headers, json=payload)
return res.json()["choices"][0]["message"]["content"]
except:
return "⚠️ ν•™μŠ΅ μΆ”μ²œ 생성에 μ‹€νŒ¨ν–ˆμ–΄μš”."
# -------------------------------
# 5. Streamlit UI
# -------------------------------
def main():
st.set_page_config(page_title="Solar 곡뢀 λ©˜ν† ", layout="wide")
st.title("πŸ‘©β€πŸ« Solar 곡뢀 λ©˜ν† ")
api_key = st.text_input("πŸ” Upstage API Key", type="password")
uploaded_file = st.file_uploader("πŸ“Ž 문제 이미지 μ—…λ‘œλ“œ", type=["pdf", "png", "jpg", "jpeg"])
if "html_text" not in st.session_state:
st.session_state.html_text = ""
if "chat_history" not in st.session_state:
st.session_state.chat_history = []
if "keywords" not in st.session_state:
st.session_state.keywords = []
if "study_tips" not in st.session_state:
st.session_state.study_tips = {}
if uploaded_file and api_key and st.button("πŸ“„ λ¬Έμ„œ 뢄석 μ‹œμž‘"):
with st.spinner("λ¬Έμ„œλ₯Ό νŒŒμ‹±ν•˜κ³  μžˆμ–΄μš”..."):
html_text, err = parse_document_to_html(uploaded_file, api_key)
if err:
st.error(err)
return
st.session_state.html_text = html_text
st.success("λ¬Έμ„œ νŒŒμ‹± 성곡 βœ…")
# ✨ μ§ˆμ˜μ‘λ‹΅: 이미지와 λΆ„λ¦¬ν•΄μ„œ 별도 μ˜μ—­μ— μœ„μΉ˜
if st.session_state.html_text:
left_col, right_col = st.columns([1, 2])
with left_col:
st.image(uploaded_file, caption="πŸ–ΌοΈ μ—…λ‘œλ“œν•œ 문제 이미지", use_container_width=True)
with right_col:
st.subheader("❓ κΆκΈˆν•œ λ‚΄μš©μ„ μ§ˆλ¬Έν•΄λ³΄μ„Έμš”")
user_question = st.text_input("μ§ˆλ¬Έμ„ μž…λ ₯ν•˜κ³  μ•„λž˜ λ²„νŠΌμ„ λˆŒλŸ¬λ³΄μ„Έμš”", key="question_input")
if st.button("πŸ’¬ Solarμ—κ²Œ 물어보기") and user_question:
with st.spinner("Solar μ„ μƒλ‹˜μ΄ λ‹΅λ³€ μ€‘μž…λ‹ˆλ‹€..."):
answer, history, err = chat_with_solar_document(
st.session_state.html_text,
user_question,
st.session_state.chat_history,
api_key
)
if err:
st.error(f"❌ Solar 응닡 였λ₯˜: {err}")
else:
st.session_state.chat_history = history
st.chat_message("user").write(user_question)
st.chat_message("assistant").write(answer)
# ν‚€μ›Œλ“œ μΆ”μ²œ 생성
st.session_state.keywords = get_recommended_keywords(
st.session_state.html_text,
user_question,
api_key
)
# ✨ 이미지 μ•„λž˜μ— μΆ”μ²œ ν‚€μ›Œλ“œ ν‘œμ‹œ
if st.session_state.keywords:
st.markdown("### πŸ”Ž μΆ”μ²œ 곡뢀 ν‚€μ›Œλ“œ")
for keyword in st.session_state.keywords:
if st.button(f"πŸ“˜ {keyword} 곡뢀 μΆ”μ²œλ°›κΈ°", key=f"btn_{keyword}"):
tip = get_study_tip_for_keyword(keyword, api_key)
st.session_state.study_tips[keyword] = tip
for keyword, tip in st.session_state.study_tips.items():
with st.expander(f"πŸ“˜ {keyword} 곡뢀법 보기"):
st.write(tip)
if __name__ == "__main__":
main()