import streamlit as st import openai import json from annotated_text import annotated_text import os import pandas as pd import achivenment_standards as data # OpenAI API 설정 (환경 변수에서 읽어옴) openai.api_key = os.getenv("OPENAI_API_KEY") # gpt이용해서 추론함수 만들기 def generate_annotated_text(text): response = openai.ChatCompletion.create( model="gpt-4o-mini", messages=[ { "role": "system", "content": "성취기준 기반 학생의 특성 및 활동 평가 생성\n성취기준을 입력하시면, 해당 성취기준에 기반한 학생의 특성 및 활동에 대한 평가를 annotated_text 형식으로 제공합니다. 성취기준을 보며 학생의 특정 활동, 성취 수준, 교사의 총평, 그리고 학생의 역량을 고려하여 체계적으로 구성된 출력을 제공합니다. 주어는 반드시 생략합니다. \n\n예제:\n입력: ```성취기준: [6국01-07]상대가 처한 상황을 이해하고 공감하며 듣는 태도를 지닌다, [6국01-02] 의견을 제시하고 함께 조정하며 토의한다.```\n출력: ```annotated_text(\n (\"평소 자신의 생각을 일목요연하게 정리하는 습관이 있음.\", \"역량\", \"rgba(255, 0, 0, 0.3)\"),\n (\"사회 현안에 관한 주장하는 글쓰기를 잘함.\", \"성취수준\", \"rgba(0, 0, 255, 0.3)\"),\n (\"친구의 고민을 해결해주는 역할극에서 상대방을 배려하여 해결 가능한 방안을 제안함.\", \"수행\", \"rgba(0, 128, 0, 0.3)\"),\n (\"상대가 처한 상황을 이해하고 공감하는 태도를 가지고 친구들과 원만한 관계를 맺고 갈등을 조정함.\", \"교사총평\", \"rgba(128, 128, 128, 0.3)\"),\n (\"중간 놀이 시간에 운동장을 사용하는 방법 정하기를 주제로 한 토의에서 알맞은 근거와 뒷받침할 수 있는 자료를 토대로 자신의 의견을 타당하게 제시하면서 다른 사람의 의견을 능동적으로 수용하고 효과적으로 의견을 조정하는 능력을 보임.\", \"수행\", \"rgba(0, 128, 0, 0.3)\"),\n (\"상대의 의견을 존중하고 협력하는 태도를 보임.\", \"역량\", \"rgba(255, 0, 0, 0.3)\")\n)\n```" }, { "role": "user", "content": text } ], temperature=1, max_tokens=10000, top_p=1, frequency_penalty=0, presence_penalty=0 ) return response['choices'][0]['message']['content'] # 유사한 문장 생성 함수 def generate_similar_sentences(base_sentence): response = openai.ChatCompletion.create( model="gpt-4o-mini", messages=[ { "role": "system", "content": f"""다음 기준을 따라 '{base_sentence}'와 유사하지만 독창적인 학생 평가 문구 30개를 생성해 주세요: 1. 주어는 생략하고 서술어로 시작합니다. 2. 문장 끝은 '~임', '~함', '~음' 등 다양한 종결어미를 사용합니다. 3. 원래 문장의 핵심 의미는 유지하되, 다음 요소들을 변형하여 다양성을 높입니다: - 유사한 의미의 다른 단어나 표현 사용 - 문장 구조 변경 (예: 능동태/수동태 전환) - 구체적인 예시나 상황 추가 - 부사어구를 추가하여 의미 확장 4. 학생의 성장과 발전을 긍정적으로 표현합니다. 5. 교과 관련 역량, 창의성, 협동심, 리더십 등 다양한 측면을 고려합니다. 6. 특정 학년이나 과목에 국한되지 않도록 일반화합니다. 7. 각 문구는 최소 20자 이상, 최대 100자 이내로 작성합니다. 생성된 문구들은 원래 문장과 유사하면서도 충분히 다양하고 독창적이어야 합니다.""" }, { "role": "user", "content": base_sentence } ], temperature=0.7, max_tokens=10000, top_p=1, frequency_penalty=0, presence_penalty=0 ) generated_sentences = response.choices[0].message['content'].split('\n') return [sentence.strip() for sentence in generated_sentences if sentence.strip()] # Streamlit 앱의 제목 및 설명 st.title("성취기준 기반 학생의 특성 및 활동 평가 생성") st.write("성취기준을 입력하시면, 해당 성취기준에 기반한 학생의 특성 및 활동에 대한 평가를 \n\n [학생 활동, 성취 수준, 교사의 총평, 학생 역량] 4가지 요소를 조합하여 제공합니다.") # 성취기준 데이터 가져오기 achievement_standards = data.achievement_standards # 학년군 선택 드롭다운 grade_group = st.selectbox("학년군을 선택하세요:", list(achievement_standards.keys())) # 선택된 학년군에 따른 과목 목록 subject_list = list(achievement_standards[grade_group].keys()) subject = st.selectbox("과목을 선택하세요:", subject_list) # 선택된 과목에 따른 성취기준 목록 selected_standards = achievement_standards[grade_group][subject] selected_standard = st.selectbox("성취기준을 선택하세요:", selected_standards) # 선택된 성취기준을 텍스트 입력창의 기본값으로 사용 achievement_standard = st.text_input("성취기준 입력:", value=selected_standard) # 세션 상태 초기화 if 'generated_result' not in st.session_state: st.session_state.generated_result = None if 'selected_sentence' not in st.session_state: st.session_state.selected_sentence = None if 'similar_sentences' not in st.session_state: st.session_state.similar_sentences = [] # "평가 생성" 버튼 클릭 시의 동작 if st.button("평가 생성"): with st.spinner('답변 생성중...'): result = generate_annotated_text(achievement_standard) st.session_state.generated_result = result st.session_state.selected_sentence = None # 새로운 평가 생성시 선택된 문장 초기화 st.session_state.similar_sentences = [] # 이전 유사한 문장들 초기화 exec(result.replace('```', '')) # 셀렉트 박스 및 유사한 문장 생성 버튼 추가 if st.session_state.generated_result: # annotated_text 결과에서 문장만 추출 result_lines = st.session_state.generated_result.split('\n') sentences = [line[start_idx + 2:line.find('",', start_idx)].strip() for line in result_lines if (start_idx := line.find('("')) != -1] if sentences: selected_sentence = st.selectbox("문장을 선택하세요:", sentences, key="sentence_select") st.session_state.selected_sentence = selected_sentence # 유사한 문장 생성 버튼 if st.button("유사한 문구 생성") and st.session_state.selected_sentence: with st.spinner('문장 생성중...'): st.session_state.similar_sentences = generate_similar_sentences(st.session_state.selected_sentence) # 유사한 문장들 출력 for sentence in st.session_state.similar_sentences: st.write(sentence) # CSV 파일로 저장하는 버튼 추가 if st.session_state.similar_sentences: # 데이터프레임 생성 df = pd.DataFrame(st.session_state.similar_sentences, columns=["Similar Sentences"]) # UTF-8-SIG (BOM) 인코딩으로 CSV 파일 변환 csv = df.to_csv(index=False, encoding='utf-8-sig').encode('utf-8-sig') # 다운로드 버튼 생성 st.download_button( label="CSV로 저장", data=csv, file_name='similar_sentences.csv', mime='text/csv' )