import sys import traceback import streamlit as st # 우리가 만든 백엔드 파일에서 엔진 함수 수입해오기 from backend import load_all_models, predict_ensemble # 1. 스트림릿 UI 기본 설정 st.set_page_config( page_title="문체 기반 동일인 판별 시스템", page_icon="🧠", layout="centered" ) # 2. 리소스를 한 번만 로드하도록 캐싱 세팅 @st.cache_resource(show_spinner=False) def get_cached_models(): try: return load_all_models() except ModuleNotFoundError as e: raise ModuleNotFoundError( "필수 패키지가 설치되지 않았습니다. requirements.txt를 확인하세요.\n\n" f"원본 오류: {e}" ) # 3. 메인 화면 레이아웃 그리기 st.title("🧠 문체 기반 동일인 판별 시스템") st.markdown( """ 이 시스템은 **KcBERT, DeBERTa, Multi-Scale Char-CNN 앙상블 모델**을 활용하여 두 텍스트의 동일 작성자 가능성을 분석합니다. """ ) st.info("두 텍스트를 입력한 뒤 [판별하기] 버튼을 누르면 동일 작성자 가능성을 출력합니다.") # 입력 텍스트 상자 text_a = st.text_area("텍스트 A", height=180, placeholder="첫 번째 텍스트를 입력하세요.") text_b = st.text_area("텍스트 B", height=180, placeholder="두 번째 텍스트를 입력하세요.") col1, col2 = st.columns(2) with col1: analyze_button = st.button("판별하기", use_container_width=True) with col2: clear_button = st.button("입력 초기화 안내", use_container_width=True) if clear_button: st.warning("입력창 내용은 직접 지우거나 브라우저 새로고침을 하면 초기화됩니다.") # 4. 판별 버튼 클릭 시 백엔드 엔진 구동 if analyze_button: if not text_a.strip() or not text_b.strip(): st.warning("텍스트 A와 텍스트 B를 모두 입력하세요.") else: try: with st.spinner("AI 모델로 분석 중입니다. 처음 실행 시 시간이 다소 걸릴 수 있습니다."): # 캐시된 모델 가져오기 model_bundle = get_cached_models() # 백엔드 연산 함수 호출 result = predict_ensemble(text_a, text_b, model_bundle) st.divider() st.subheader("분석 결과") same_percent = result["same_prob"] * 100 diff_percent = result["diff_prob"] * 100 # 결과에 따른 UI 연출 if result["pred_label"] == 0: st.success("판별 결과: 동일 작성자 가능성이 높습니다.") else: st.error("판별 결과: 동일 작성자 가능성이 낮습니다.") metric_col1, metric_col2 = st.columns(2) with metric_col1: st.metric("동일 작성자 가능성", f"{same_percent:.2f}%") with metric_col2: st.metric("비동일 작성자 가능성", f"{diff_percent:.2f}%") st.progress(min(max(result["same_prob"], 0.0), 1.0)) # 모델별 디테일 수치 표 출력 st.subheader("모델별 예측 확률") model_table = { "모델": ["KcBERT", "Multi-Scale Char-CNN", "DeBERTa"], "Same(0)": [ f"{result['kc_prob'][0] * 100:.2f}%", f"{result['cnn_prob'][0] * 100:.2f}%", f"{result['deberta_prob'][0] * 100:.2f}%" ], "Diff(1)": [ f"{result['kc_prob'][1] * 100:.2f}%", f"{result['cnn_prob'][1] * 100:.2f}%", f"{result['deberta_prob'][1] * 100:.2f}%" ] } st.table(model_table) # 확장 탭 정보 with st.expander("기술 정보"): st.write("실행 장치:", result["device"]) st.write("Python 실행 경로:") st.code(sys.executable) st.write("모델 경로:") st.code(result["model_dir"]) st.caption("주의: 본 결과는 AI 모델 기반 추정값이며, 실제 동일인을 단정하는 법적 판단이 아닙니다.") except Exception as e: st.error("고급 모델 실행 중 오류가 발생했습니다.") st.code(str(e)) with st.expander("상세 오류 보기"): st.code(traceback.format_exc())