Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import google.generativeai as genai | |
| import pandas as pd | |
| import io | |
| import re | |
| # ========================================== | |
| # 1. UI CONFIGURATION & INTERFACE SETUP | |
| # ========================================== | |
| st.set_page_config(page_title="CX Architect Auto-Mapper", layout="wide", page_icon="ποΈ") | |
| st.title("ποΈ CX Architect: Omni-Channel Generator") | |
| st.markdown("Upload your PRD, VOC data, or an existing spreadsheet. The AI engine will instantly map the customer journey and generate a structured VA Design Sheet.") | |
| # Global state variables initialization | |
| api_key = "" | |
| demo_mode = False | |
| # Sidebar Configuration Panel | |
| with st.sidebar: | |
| st.header("βοΈ Configuration") | |
| # 100% stable checkbox for system compatibility | |
| demo_mode = st.checkbox("π Activate Demo Simulation Mode", value=False) | |
| if not demo_mode: | |
| api_key = st.text_input("Enter Gemini API Key", type="password", placeholder="Paste your AIza... key here") | |
| if api_key and api_key.startswith("AQ."): | |
| st.warning("β οΈ Restricted token format detected. Switch to Demo Simulation Mode if it blocks.") | |
| else: | |
| st.success("π’ Simulation Mode Active (No Key Required)") | |
| st.markdown("---") | |
| st.markdown("**Framework: LAMF Process Automation Engine**") | |
| # Multi-Format File Upload Area | |
| uploaded_file = st.file_uploader("Drop your Lending Document here (PDF, TXT, or CSV)", type=["pdf", "txt", "csv"]) | |
| # ========================================== | |
| # 2. FAIL-SAFE DATA MATRICES | |
| # ========================================== | |
| def get_simulation_assets(): | |
| """Returns layout datasets modeled directly from real lending configurations""" | |
| flow_text = ( | |
| "π MILESTONE 1: USER_AUTHENTICATION\n" | |
| " - Happy Path: Identity verified instantly via core onboarding APIs.\n" | |
| " - Unhappy Scenario: Low credit profile or verification drop-off.\n\n" | |
| "π MILESTONE 2: PV_KYC & KYC_VERIFICATION\n" | |
| " - Happy Path: Live selfie matching passes onboarding criteria.\n" | |
| " - Unhappy Scenario: Selfie verification failed or device camera initialization error (33% of Tickets).\n" | |
| " - Bot Intercept: Provides dynamic lighting tips and escalates directly to manual queues.\n\n" | |
| "π MILESTONE 3: CREDIT_LIMIT_SELECTION\n" | |
| " - Happy Path: System establishes available loan limits cleanly.\n" | |
| " - Unhappy Scenario: Screen encounters a generic 'Something went wrong' network glitch.\n" | |
| " - Bot Intercept: Catch-all logic translates the network error and routes to core tech support groups.\n\n" | |
| "π MILESTONE 4: PLEDGE_OFFER & DIGITAL SIGNING\n" | |
| " - Happy Path: Digital locks successfully bind target mutual fund assets.\n" | |
| " - Unhappy Scenario: User queries interest fees late or submits a cancellation/data deletion request.\n" | |
| " - Bot Intercept: Intercepts drop-offs with micro-educational comparisons explaining asset growth." | |
| ) | |
| headers = ["Current Milestone", "Scenario", "Context Message", "User Selection", "Short Note", "Ticket Creation", "Group", "Issue / GTIS", "TAG"] | |
| rows = [ | |
| ["PV_KYC", "Unhappy: Selfie Verification Failed", "We noticed you are facing issues capturing your live selfie for verification.", "1. How to capture correctly\n2. Retry Upload", "Ensure you are in a well-lit room and remove glasses. Click 'Retry' on the main window interface.", "No", "NA", "Pre disbursal_KYC", "first_response_by_app_bot"], | |
| ["PV_KYC", "Unhappy: Selfie Failed (Max Retries)", "If your camera link is still not responding, we can escalate for manual profile checks.", "1. Escalate Request", "Your request has been raised. Our operations support team will email a manual submission form link within 2 hours.", "Yes", "Pre disbursal", "KYC verification failed_To be escalated", "kyc_manual_escalation"], | |
| ["PLEDGE_OFFER", "Unhappy: Late Charge Discovery Queries", "You seem to have a question before pledging your mutual funds. What details would you like to review?", "1. Rate of Interest\n2. Processing Fees", "Interest builds daily only on balances you actively draw. Total processing fee calculation is βΉ1,500 + 18% GST (βΉ1,770 total).", "No", "NA", "Loan details_Info given", "first_response_by_app_bot"], | |
| ["PLEDGE_OFFER", "Unhappy: Data Deletion / Cancellation", "We notice you want to cancel your application. Your mutual funds remain perfectly secure and earn standard returns.", "1. Confirm Cancellation\n2. Talk to Agent", "Your application records have been safely cleared out. Click proceed if you want to wipe historically fetched portfolio rows.", "Yes", "Pre disbursal", "Cancellation request_Processed", "lamf_cancellation"], | |
| ["CREDIT_LIMIT", "Unhappy: Generic Technical Failure Screen", "We see your portfolio balance evaluation was interrupted due to a background system exception.", "1. Refresh Pipeline", "Lender communication arrays are undergoing a brief update sync. We have logged this block and will text you when open.", "Yes", "Pre disbursal", "Approval pending_Asked to wait", "tech_failure_limit"] | |
| ] | |
| return flow_text, pd.DataFrame(rows, columns=headers) | |
| def safe_read_file(file): | |
| try: | |
| if file.name.endswith('.pdf'): | |
| import PyPDF2 | |
| pdf_reader = PyPDF2.PdfReader(io.BytesIO(file.getvalue())) | |
| return "".join([page.extract_text() or "" for page in pdf_reader.pages]) | |
| elif file.name.endswith('.csv'): | |
| df = pd.read_csv(io.BytesIO(file.getvalue()), errors='ignore') | |
| return df.to_string() | |
| else: | |
| return file.getvalue().decode("utf-8", errors="ignore") | |
| except Exception as e: | |
| return f"Error: {str(e)}" | |
| # ========================================== | |
| # 3. RUNTIME OPERATION CONTROLLER | |
| # ========================================== | |
| if st.button("π Generate Design Sheets & Flow"): | |
| # Fail-safe condition adjustment: Bypasses file validation rules if user has Demo Mode activated | |
| if not demo_mode and not api_key: | |
| st.error("β οΈ Configuration Key Required! Please input your Gemini API Key or activate Demo Simulation Mode in the sidebar.") | |
| elif not demo_mode and not uploaded_file: | |
| st.error("β οΈ Data Source Missing! Please upload a PDF, TXT, or CSV file to analyze.") | |
| else: | |
| with st.spinner("Processing customer journey parameters..."): | |
| try: | |
| flow_output = "" | |
| dataframe_output = None | |
| # SCENARIO A: Direct Demo Mode (No File or Key requirements enforced) | |
| if demo_mode: | |
| flow_output, dataframe_output = get_simulation_assets() | |
| # SCENARIO B: Live Data Extraction Pipeline | |
| else: | |
| if uploaded_file.name.endswith('.csv'): | |
| raw_df = pd.read_csv(io.BytesIO(uploaded_file.getvalue()), errors='ignore') | |
| dataframe_output = raw_df | |
| flow_output = f"π Loaded configuration layout rows directly from '{uploaded_file.name}'." | |
| else: | |
| doc_text = safe_read_file(uploaded_file) | |
| genai.configure(api_key=api_key) | |
| model = genai.GenerativeModel('gemini-1.5-flash') | |
| prompt = f""" | |
| You are an elite Fintech CX Architect mapping a Virtual Assistant flow for Loan Against Mutual Funds (LAMF). | |
| Output exactly two structural segments inside these XML tag elements. Do not use markdown backticks. | |
| <FLOW> | |
| List the Happy Path milestones, and then list the Unhappy Path scenarios along with recommended Bot Actions. | |
| </FLOW> | |
| <TABLE> | |
| Current Milestone | Scenario | Context Message | User Selection | Short Note | Ticket Creation | Group | Issue / GTIS | TAG | |
| Provide at least 4 custom rows separated by standard pipe characters (|) matching this sequence. | |
| </TABLE> | |
| Data text: {doc_text} | |
| """ | |
| ai_response = model.generate_content(prompt).text | |
| flow_match = re.search(r"<FLOW>(.*?)</FLOW>", ai_response, re.DOTALL) | |
| table_match = re.search(r"<TABLE>(.*?)</TABLE>", ai_response, re.DOTALL) | |
| flow_output = flow_match.group(1).strip() if flow_match else "Journey breakdown completed." | |
| raw_table_str = table_match.group(1).strip() if table_match else "" | |
| table_lines = [l.strip() for l in raw_table_str.split('\n') if l.strip() and '---' not in l] | |
| if table_lines: | |
| headers = [h.strip() for h in table_lines[0].split('|')] | |
| data_rows = [[cell.strip() for cell in r.split('|')] for r in table_lines[1:] if '|' in r] | |
| clean_rows = [] | |
| for row in data_rows: | |
| if len(row) < len(headers): row += ["NA"] * (len(headers) - len(row)) | |
| elif len(row) > len(headers): row = row[:len(headers)] | |
| clean_rows.append(row) | |
| dataframe_output = pd.DataFrame(clean_rows, columns=headers) | |
| # ========================================== | |
| # 4. OUTPUT DISPLAY LAYOUT | |
| # ========================================== | |
| st.success("π― Omni-Channel Assets Rendered Successfully!") | |
| tab1, tab2 = st.tabs(["πΊοΈ Visual Journey Path", "π VA Design Sheet (Excel)"]) | |
| with tab1: | |
| st.subheader("Process Flow Optimization Strategy") | |
| st.code(flow_output, language="text") | |
| with tab2: | |
| st.subheader("Automated Routing Matrix (GTIS Mapping)") | |
| if dataframe_output is not None: | |
| st.dataframe(dataframe_output, use_container_width=True) | |
| csv_stream = dataframe_output.to_csv(index=False).encode('utf-8') | |
| st.download_button( | |
| label="β¬οΈ Download Sheet as CSV/Excel", | |
| data=csv_stream, | |
| file_name='Automated_VA_Design_Sheet.csv', | |
| mime='text/csv', | |
| ) | |
| else: | |
| st.warning("Data rows could not be arranged into a standard matrix format layout.") | |
| except Exception as runtime_err: | |
| st.error(f"Execution Interrupted: {str(runtime_err)}") |