| | import os |
| | import time |
| | import google.generativeai as genai |
| | import streamlit as st |
| | import re |
| | from streamlit_chat import message |
| |
|
| | |
| | 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", |
| | } |
| | safety_settings = [ |
| | {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_MEDIUM_AND_ABOVE"}, |
| | {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_MEDIUM_AND_ABOVE"}, |
| | {"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_MEDIUM_AND_ABOVE"}, |
| | {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_MEDIUM_AND_ABOVE"}, |
| | ] |
| |
|
| | |
| | chat_session = None |
| |
|
| | def start_new_chat_session(): |
| | global chat_session |
| | chat_session = ( |
| | genai.GenerativeModel( |
| | model_name="gemini-2.0-flash", |
| | safety_settings=safety_settings, |
| | generation_config=generation_config, |
| | system_instruction="""당신은 뛰어난 전문성을 갖춘 과학자이다. 또 초등학교 교사이기도 하다. 과학 교과 내용 전문가입니다. |
| | 학생이 과학적 개념이나 원리에 대해 질문하면 구체적인 예시를 들어 친절하게 설명해주세요. |
| | 학생들이 자신들의 탐구 계획이나 실험 방법 등에 대한 질문을 하면 탐구 과정이나 실험 절차나 팁을 알려주세요.""", |
| | ) |
| | .start_chat(history=[]) |
| | ) |
| |
|
| | |
| | start_new_chat_session() |
| |
|
| | |
| | st.set_page_config(page_title="AI 과학자", layout="centered") |
| |
|
| | st.markdown( |
| | """ |
| | <style> |
| | .main { |
| | background-color: #f0f2f6; |
| | padding: 20px; |
| | border-radius: 10px; |
| | box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); |
| | } |
| | .chat-container { |
| | max-height: 500px; |
| | overflow-y: auto; |
| | padding: 10px; |
| | background-color: #ffffff; |
| | border-radius: 10px; |
| | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
| | } |
| | </style> |
| | <div style='font-size: 30px; font-weight: bold; text-align: center;'>AI 과학자</div> |
| | <div style='text-align: center; margin-bottom: 20px;'>과학에 대해 궁금한 점을 AI 과학자에게 질문하세요, 자유탐구에 대한 조언을 구하세요.</div> |
| | """, |
| | unsafe_allow_html=True |
| | ) |
| |
|
| | |
| | if "history" not in st.session_state: |
| | st.session_state.history = [] |
| |
|
| | |
| | if "chat_session" not in st.session_state: |
| | st.session_state.chat_session = chat_session |
| |
|
| | |
| | chat_container = st.container() |
| |
|
| | |
| | user_input = st.text_input( |
| | "입력", key="user_input", placeholder="여기에 질문을 입력하세요...", |
| | help="과학적 개념이나 탐구 방법에 대한 질문을 입력하세요." |
| | ) |
| |
|
| | def respond(user_input): |
| | st.session_state.history.append({"user": user_input, "ai": ""}) |
| | try: |
| | response = st.session_state.chat_session.send_message(user_input, stream=True) |
| | full_text = "" |
| | |
| | |
| | for chunk in response: |
| | chunk_text = chunk.text |
| | |
| | |
| | for sentence in chunk_text.split("."): |
| | sentence = sentence.strip() + ". " |
| | |
| | if re.match(r"^\d+\.", sentence) or sentence.startswith("* "): |
| | full_text += "\n" + sentence |
| | else: |
| | full_text += sentence |
| | |
| | |
| | st.session_state.history[-1]["ai"] = full_text |
| | time.sleep(0.03) |
| |
|
| | except Exception as e: |
| | st.session_state.history[-1]["ai"] = f"에러 발생: {str(e)}" |
| |
|
| | |
| | if user_input: |
| | respond(user_input) |
| |
|
| | |
| | with chat_container: |
| | st.markdown("<div class='chat-container'>", unsafe_allow_html=True) |
| | for chat in st.session_state.history: |
| | if "user" in chat: |
| | message(chat["user"], is_user=True, key=f"user_{chat['user']}") |
| | if "ai" in chat: |
| | message(chat["ai"], is_user=False, key=f"ai_{chat['ai']}") |
| | st.markdown("</div>", unsafe_allow_html=True) |
| |
|
| | |
| | if st.button("초기화"): |
| | start_new_chat_session() |
| | st.session_state.history = [] |