Spaces:
Running
Running
| import streamlit as st | |
| import asyncio | |
| from pathlib import Path | |
| from main import red_flag_analyzer | |
| import fitz | |
| # ============================================================================ | |
| # DATA FLOW: | |
| # 1. User uploads .txt or .doc file via Streamlit UI | |
| # 2. File is read and text is extracted | |
| # 3. Text is passed to red_flag_analyzer() from main.py | |
| # 4. red_flag_analyzer() sends text to AI model | |
| # 5. AI analyzes and returns RedFlagReport with identified red flags | |
| # 6. Results are displayed in Streamlit UI with severity color-coding | |
| # ============================================================================ | |
| if "show_disclaimer" not in st.session_state: | |
| st.session_state.show_disclaimer = None | |
| # ============================================================================ | |
| # PAGE CONFIGURATION | |
| # ============================================================================ | |
| st.set_page_config( | |
| page_title="Red Flag Analyzer", | |
| page_icon="π©", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| st.title("π© Red Flag Analyzer") | |
| st.markdown("Upload a document to identify potential risks and unfair clauses") | |
| # ============================================================================ | |
| # SIDEBAR - FILE UPLOAD | |
| # ============================================================================ | |
| st.sidebar.header("π Upload Document") | |
| st.sidebar.markdown("Supported formats: `.txt`, `.docx`, `.pdf`") | |
| # File uploader widget | |
| uploaded_file = st.sidebar.file_uploader( | |
| "Choose a file", | |
| type=["txt", "docx", "pdf"], | |
| help="Upload your document for analysis" | |
| ) | |
| # ============================================================================ | |
| # FUNCTION: Extract text from uploaded file | |
| # ============================================================================ | |
| def extract_text_from_file(uploaded_file): | |
| """ | |
| Extract text from uploaded file based on file type. | |
| Args: | |
| uploaded_file: Streamlit UploadedFile object | |
| Returns: | |
| str: Extracted text from the file | |
| """ | |
| file_extension = Path(uploaded_file.name).suffix.lower() #gets the extension of the file | |
| try: | |
| #checking which extension does it belong | |
| if file_extension == ".txt": | |
| # For .txt files, decode directly | |
| text = uploaded_file.getvalue().decode("utf-8") | |
| return text | |
| if file_extension == ".docx": | |
| from docx import Document | |
| from io import BytesIO | |
| # Extract text from document | |
| doc = Document(BytesIO(uploaded_file.getbuffer())) | |
| text = "\n".join([para.text for para in doc.paragraphs]) | |
| return text | |
| if file_extension == ".pdf": | |
| # Ensure the stream buffer is at the beginning | |
| uploaded_file.seek(0) | |
| # Extract text from PDF using PyMuPDF (fitz) | |
| pdf_document = fitz.open(stream=uploaded_file.read(), filetype="pdf") | |
| text = "" | |
| # 'page' is already the loaded page object, no need to re-load it | |
| for page in pdf_document: | |
| text += page.get_text() | |
| pdf_document.close() # Clean up memory handles | |
| return text | |
| except Exception as e: | |
| st.error(f"Error reading file: {str(e)}") | |
| return None | |
| # ============================================================================ | |
| # MAIN APP LOGIC | |
| # ============================================================================ | |
| if uploaded_file is not None: | |
| # Step 1: Extract text from file | |
| st.sidebar.success(f"β File uploaded: {uploaded_file.name}") | |
| with st.spinner("π Reading document..."): | |
| document_text = extract_text_from_file(uploaded_file) | |
| if document_text: | |
| # Step 2: Display document preview | |
| st.subheader("π Document Preview") | |
| with st.expander("View full document", expanded=False): | |
| st.text_area( | |
| "Document Content", | |
| value=document_text, | |
| height=200, | |
| disabled=True | |
| ) | |
| st.markdown(f"**Document Size:** {len(document_text)} characters") | |
| st.markdown("---") | |
| if st.button("π Analyze for Red Flags", type="primary"): | |
| st.session_state.show_disclaimer=True | |
| if st.session_state.show_disclaimer: | |
| if st.session_state.show_disclaimer==True: | |
| st.warning( | |
| "This tool is designed to assist you in identifying potential " | |
| "risks and red flags in documents. However, it should not be considered legal advice. " | |
| "**Please consult with a qualified legal professional before making any final decisions.** " | |
| "This analysis is for awareness purposes only.", | |
| icon="β οΈ") | |
| if st.checkbox("I understand and wish to proceed with the analysis"): | |
| st.session_state.show_disclaimer=False | |
| with st.spinner("π€ AI is analyzing your document..."): | |
| try: | |
| # Call the red_flag_analyzer function | |
| result = red_flag_analyzer(document_text) #from main.py | |
| # Step 4: Display results | |
| st.success("β Analysis complete!") | |
| st.markdown("---") | |
| # Display document summary | |
| st.subheader("π Document Summary") | |
| st.info(result.document_summary) | |
| # Display red flags | |
| st.subheader(f"π© Red Flags Found: {len(result.red_flags)}") | |
| #if result returns any red flag | |
| if result.red_flags: | |
| # Color mapping for severity levels | |
| severity_colors = { | |
| "High": "π΄", | |
| "Medium": "π‘", | |
| "Low": "π’" | |
| } | |
| # Display each red flag in a card-like format | |
| for idx, flag in enumerate(result.red_flags, 1): | |
| # Create a container for each red flag | |
| with st.container(border=True): | |
| col1, col2 = st.columns([3, 1]) | |
| with col1: | |
| st.markdown( | |
| f"### {severity_colors.get(flag.severity, 'β')} " | |
| f"Red Flag #{idx}" | |
| ) | |
| with col2: | |
| st.markdown( | |
| f"**Severity:** `{flag.severity}`" | |
| ) | |
| st.markdown("**Problem Text:**") | |
| st.code(flag.item, language="text") | |
| st.markdown("**Why it's a problem:**") | |
| st.write(flag.reason) | |
| st.markdown("---") | |
| else: | |
| st.success("β¨ No red flags found! This document looks good.") | |
| except Exception as e: | |
| st.error(f"β Error during analysis: {str(e)}") | |
| st.info("Make sure your `.env` file is configured with the API key.") | |
| else: | |
| # Show empty state when no file is uploaded | |
| st.info("π Upload a document in the sidebar to get started!") | |
| # Display example | |
| with st.expander("βΉοΈ Example - What kind of red flags will be detected?"): | |
| st.markdown(""" | |
| The analyzer looks for: | |
| - **Unfair clauses** (one-sided terms, hidden conditions) | |
| - **Hidden fees** (unexpected costs, surprise charges) | |
| - **High-risk commitments** (unlimited liability, perpetual obligations) | |
| - **Ambiguous rules** (vague language, unclear definitions) | |
| - **Legal risks** (arbitration clauses, waived rights) | |
| """) | |
| # ============================================================================ | |
| # FOOTER | |
| # ============================================================================ | |
| st.markdown("---") | |
| st.markdown( | |
| "π‘ **Tip:** Use this tool to review contracts, terms of service, and agreements. " | |
| "Always consult with legal professionals for final decisions." | |
| ) | |