import os import streamlit as st import requests from dotenv import load_dotenv # --- 1. Initial Setup --- load_dotenv() st.set_page_config(layout="wide", page_title="Jan-Contract Unified Assistant", page_icon="⚖️") # Backend Configuration # Default to local server (run with: python -m uvicorn main:app --port 8000) LOCAL_URL = "http://localhost:8000" default_url = os.getenv("BACKEND_URL", LOCAL_URL) with st.sidebar: with st.expander("⚙️ Connection Settings"): BACKEND_URL = st.text_input( "Backend API URL", value=default_url, help="URL of the deployed Jan-Contract API" ) # Test Connection if st.button("Test Connection"): try: resp = requests.get(f"{BACKEND_URL}/health", timeout=10) if resp.status_code == 200: st.success("✅ Connected!") else: st.error(f"❌ Error: {resp.status_code}") except Exception as e: st.error(f"❌ Failed: {e}") # Only strip trailing slash if it exists if BACKEND_URL.endswith("/"): BACKEND_URL = BACKEND_URL[:-1] # --- Custom CSS --- st.markdown(""" """, unsafe_allow_html=True) st.title("Jan-Contract: Digital Workforce Assistant") st.caption(f"Connected to Backend: `{BACKEND_URL}`") st.write("Empowering India's workforce with accessible legal tools and government scheme discovery.") # --- 2. Streamlit UI with Tabs --- tab1, tab2, tab3 = st.tabs([ "Contract Generator", "Scheme Finder", "Document Demystifier" ]) # --- TAB 1: Contract Generator --- with tab1: st.header("Digital Agreement Generator") st.write("Create a clear digital agreement from plain text and record video consent.") col1, col2 = st.columns([1, 1]) with col1: st.subheader("Agreement Details") user_request = st.text_area("Describe the terms of the agreement...", height=150, key="contract_request", placeholder="E.g., I, Rajesh, agree to paint Mr. Sharma's house for 5000 rupees by next Tuesday.") if st.button("Generate Agreement", type="primary", key="btn_generate_contract"): if user_request: with st.spinner("Drafting agreement via API..."): try: payload = {"user_request": user_request} response = requests.post(f"{BACKEND_URL}/api/v1/contracts/generate", json=payload) if response.status_code == 200: data = response.json() if data.get("success"): st.session_state.legal_result = data["data"] if 'video_path_from_component' in st.session_state: del st.session_state['video_path_from_component'] else: st.error(f"API Error: {data.get('message')}") else: st.error(f"Server Error: {response.text}") except Exception as e: st.error(f"Connection failed: {e}") else: st.warning("Please describe the agreement details.") with col2: if 'legal_result' in st.session_state: result = st.session_state.legal_result contract_text = result.get('contract', '') st.subheader("Drafted Agreement") with st.container(border=True): st.markdown(contract_text) # PDF Download via API if st.button("Download PDF"): try: pdf_Payload = {"user_request": result.get('user_request', user_request)} pdf_resp = requests.post(f"{BACKEND_URL}/api/v1/contracts/generate-pdf", json=pdf_Payload) if pdf_resp.status_code == 200: st.download_button(label="Click to Save PDF", data=pdf_resp.content, file_name="agreement.pdf", mime="application/pdf") else: st.error("Failed to generate PDF") except Exception as e: st.error(f"Download failed: {e}") if result.get('legal_trivia') and result['legal_trivia'].get('trivia'): with st.expander("Legal Insights"): for item in result['legal_trivia']['trivia']: st.markdown(f"**{item['point']}**") st.caption(item['explanation']) st.markdown(f"[Source]({item['source_url']})") st.divider() from components.video_recorder import record_consent_video st.subheader("Video Consent Recording") saved_video_path = record_consent_video() # Upload video to backend if recorded if saved_video_path and 'legal_result' in st.session_state: contract_id = st.session_state.legal_result.get('contract_id') if contract_id: if st.button("Upload Consent to Server"): try: with open(saved_video_path, 'rb') as f: files = {'file': (os.path.basename(saved_video_path), f, 'video/mp4')} data = {'contract_id': contract_id, 'consent_text': "I agree to the terms."} up_resp = requests.post(f"{BACKEND_URL}/api/v1/media/upload-video", files=files, data=data) if up_resp.status_code == 200: st.success("Consent uploaded to server securely!") else: st.error(f"Upload failed: {up_resp.text}") except Exception as e: st.error(f"Upload error: {e}") # --- TAB 2: Scheme Finder --- with tab2: st.header("Government Scheme Finder") st.write("Find relevant government schemes based on your profile.") user_profile = st.text_input("Enter your profile description...", key="scheme_profile", placeholder="E.g., A female farmer in Maharashtra owning 2 acres of land.") if st.button("Search Schemes", type="primary", key="btn_find_schemes"): if user_profile: with st.spinner("Searching schemes via API..."): try: payload = {"user_profile": user_profile} response = requests.post(f"{BACKEND_URL}/api/v1/schemes/find", json=payload) if response.status_code == 200: st.session_state.scheme_response = response.json().get('data', {}) else: st.error(f"Error: {response.text}") except Exception as e: st.error(f"Connection error: {e}") else: st.warning("Please enter a profile description.") if 'scheme_response' in st.session_state: response = st.session_state.scheme_response st.subheader(f"Results") schemes = response.get('schemes', []) if schemes: for scheme in schemes: with st.container(border=True): st.markdown(f"#### {scheme.get('scheme_name')}") st.write(scheme.get('description')) st.write(f"**Target Audience:** {scheme.get('target_audience')}") st.markdown(f"[Official Website]({scheme.get('official_link')})") else: st.info("No specific schemes found.") # --- TAB 3: Demystifier --- with tab3: st.header("Document Demystifier") st.write("Upload a legal document to get a simplified summary and ask questions.") uploaded_file = st.file_uploader("Upload PDF Document", type="pdf", key="demystify_uploader") if uploaded_file and st.button("Analyze Document", type="primary"): with st.spinner("Uploading and analyzing..."): try: files = {"file": (uploaded_file.name, uploaded_file.getvalue(), "application/pdf")} response = requests.post(f"{BACKEND_URL}/api/v1/demystify/upload", files=files) if response.status_code == 200: st.session_state.demystify_data = response.json().get('data', {}) st.session_state.session_id = st.session_state.demystify_data.get('session_id') st.success("Analysis complete!") else: st.error(f"Analysis failed: {response.text}") except Exception as e: st.error(f"Connection error: {e}") if 'demystify_data' in st.session_state: st.divider() report = st.session_state.demystify_data.get('report', {}) tab_summary, tab_chat = st.tabs(["Summary & Analysis", "Chat with Document"]) with tab_summary: st.subheader("Document Summary") st.write(report.get('summary', '')) st.subheader("Key Terms Explained") for term in report.get('key_terms', []): with st.expander(f"{term.get('term')}"): st.write(term.get('explanation')) st.markdown(f"[Learn More]({term.get('resource_link')})") st.info(f"**Advice:** {report.get('overall_advice')}") with tab_chat: st.subheader("Ask Questions") # Simple Chat Interface for API if "messages" not in st.session_state: st.session_state.messages = [] for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) if prompt := st.chat_input("Ask about the document..."): st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("user"): st.markdown(prompt) with st.chat_message("assistant"): with st.spinner("Thinking..."): try: payload = { "session_id": st.session_state.session_id, "question": prompt } chat_resp = requests.post(f"{BACKEND_URL}/api/v1/demystify/chat", json=payload) if chat_resp.status_code == 200: answer = chat_resp.json()['data']['answer'] st.markdown(answer) st.session_state.messages.append({"role": "assistant", "content": answer}) else: st.error("Failed to get answer.") except Exception as e: st.error(f"Error: {e}")