import streamlit as st import os import tempfile from pathlib import Path import time import logging import asyncio # Import modules from modules.llm_interface import analyze_with_llm from modules.report_generator import generate_report # Import configuration from config import settings # Get logger logger = logging.getLogger(__name__) # --- Password Authentication Function --- def check_authentication(): """Returns `True` if the user is authenticated.""" expected_password = st.secrets.get("APP_PASSWORD") if not expected_password: st.session_state.authenticated = True return True if "authenticated" not in st.session_state: st.session_state.authenticated = False if st.session_state.authenticated: return True with st.form(key="password_form"): st.subheader("Enter Password to Access") password_attempt = st.text_input("Password", type="password", key="password_input_field") login_button = st.form_submit_button("Login") if login_button: if password_attempt == expected_password: st.session_state.authenticated = True st.rerun() else: st.error("Incorrect password. Please try again.") return False return False # Set page configuration st.set_page_config( page_title="Graduate Center Dissertation Review Tool", page_icon="📚", layout="wide", initial_sidebar_state="expanded" ) # Custom CSS st.markdown(""" """, unsafe_allow_html=True) # Initialize session state if "analysis_results" not in st.session_state: st.session_state.analysis_results = None if "report_generated" not in st.session_state: st.session_state.report_generated = False # Title and description st.title("Graduate Center Dissertation Review Tool") st.markdown(""" This tool automatically checks dissertations and theses for formatting and citation rules. Upload your document to receive a detailed report. """) # Sidebar for configuration with st.sidebar: st.header("Configuration") # Reset button if st.button("Start Over"): for key in st.session_state.keys(): del st.session_state[key] st.rerun() if check_authentication(): # Main content area tab1, tab2 = st.tabs(["Document Upload", "Review Report"]) with tab1: st.header("Upload Your Document") uploaded_file = st.file_uploader("Choose a PDF or Word document", type=["pdf", "docx"]) if uploaded_file is not None: # Display file info file_details = { "Filename": uploaded_file.name, "File size": f"{uploaded_file.size / 1024:.2f} KB", "File type": uploaded_file.type } st.write("File Details:") for key, value in file_details.items(): st.write(f"- {key}: {value}") # Process button if st.button("Process Document"): logger.info(f"Processing document: {uploaded_file.name}") try: with st.spinner("Processing document..."): # Process document progress_bar = st.progress(0) # Step 1: Read file bytes pdf_bytes = uploaded_file.getvalue() progress_bar.progress(25) time.sleep(0.5) # Simulate processing time # Step 2: Metadata extraction logger.info("Extracting metadata...") st.write("Extracting metadata...") metadata = {"title": uploaded_file.name} # Dummy metadata progress_bar.progress(50) time.sleep(0.5) # Simulate processing time # Step 3: LLM analysis logger.info("Performing analysis with LLM...") st.write("Performing analysis with LLM...") analysis_results = analyze_with_llm( pdf_file=pdf_bytes, metadata=metadata ) st.session_state.analysis_results = analysis_results progress_bar.progress(100) # Generate report logger.info("Generating report...") st.session_state.report = generate_report(analysis_results) st.session_state.report_generated = True # Switch to report tab st.success("Document processed successfully! View the compliance report in the next tab.") except Exception as e: logger.error(f"An error occurred during processing: {str(e)}", exc_info=True) st.error(f"An error occurred during processing: {str(e)}") with tab2: st.header("Review Report") if not st.session_state.report_generated: st.info("Upload and process a document to generate a review report.") else: # Display summary st.subheader("Summary") summary = st.session_state.analysis_results.get("summary", {}) st.write(f"**Overall Assessment**: {summary.get('overall_assessment', 'N/A')}") st.write(f"**Total Issues**: {summary.get('total_issues', 'N/A')}") st.write(f"**Critical Issues**: {summary.get('critical_issues', 'N/A')}") st.write(f"**Warning Issues**: {summary.get('warning_issues', 'N/A')}") # Display recommendations st.subheader("Recommendations") recommendations = st.session_state.analysis_results.get("recommendations", []) if recommendations: for rec in recommendations: st.write(f"- {rec}") else: st.write("No recommendations.") # Display detailed report st.subheader("Detailed Report") issues = st.session_state.analysis_results.get("issues", []) if issues: for issue in issues: severity = issue.get('severity', 'N/A').lower() message = f"**{issue.get('severity', 'N/A').upper()}**: {issue.get('message', 'N/A')}" if severity == 'critical': st.error(message) elif severity == 'warning': st.warning(message) elif severity == 'info': st.info(message) else: st.success(message) st.write(f"**Location**: {issue.get('location', 'N/A')}") st.write(f"**Suggestion**: {issue.get('suggestion', 'N/A')}") st.divider() else: st.success("No issues found.") # Footer st.markdown("---") st.markdown("© Graduate Center, CUNY. Developed to assist with dissertation and thesis review.")