Spaces:
Paused
Paused
| import streamlit as st | |
| import streamlit.components.v1 as components | |
| import pandas as pd | |
| import numpy as np | |
| import plotly.graph_objects as go | |
| import gc | |
| import requests | |
| import json | |
| import joblib | |
| import os | |
| # ============================================================================== | |
| # 0. SAYFA KONFİGÜRASYONU VE STİL | |
| # ============================================================================== | |
| st.set_page_config( | |
| page_title="AI-Driven Financial Decision Support Portal", | |
| page_icon="🧠", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| st.markdown(""" | |
| <style> | |
| .main-title { font-size: 38px; font-weight: 700; color: #1E3A8A; margin-bottom: 5px; } | |
| .subtitle { font-size: 18px; color: #4B5563; margin-bottom: 25px; font-weight: 400; } | |
| .section-header { font-size: 24px; font-weight: 600; color: #1F2937; border-bottom: 2px solid #E5E7EB; padding-bottom: 10px; margin-top: 20px; margin-bottom: 15px; } | |
| .metric-card { background-color: #F9FAFB; padding: 15px; border-radius: 8px; border-left: 5px solid #10B981; box-shadow: 0 1px 3px rgba(0,0,0,0.05); } | |
| .pipeline-box { background-color: #EFF6FF; padding: 12px; border-radius: 6px; border: 1px solid #BFDBFE; text-align: center; font-size: 13px; font-weight: 500; color: #1E40AF; } | |
| .pipeline-arrow { text-align: center; font-size: 20px; color: #3B82F6; margin: 5px 0; } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # ============================================================================== | |
| # HAFIZA VE VERİ TİPİ OPTİMİZASYONU FONKSİYONU | |
| # ============================================================================== | |
| def optimize_dataframe(df): | |
| for col in df.select_dtypes(include=['int64', 'float64']).columns: | |
| col_type = df[col].dtype | |
| if col_type == 'int64': | |
| c_min = df[col].min() | |
| c_max = df[col].max() | |
| if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max: | |
| df[col] = df[col].astype(np.int8) | |
| elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max: | |
| df[col] = df[col].astype(np.int16) | |
| elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max: | |
| df[col] = df[col].astype(np.int32) | |
| else: | |
| df[col] = df[col].astype(np.float32) | |
| gc.collect() | |
| return df | |
| # ============================================================================== | |
| # MODEL YÜKLEME VE CANLI TAHMİN MOTORU | |
| # ============================================================================== | |
| def load_production_model(): | |
| model_paths = ["model.pkl", "gradient_boosting_model.pkl", "loan_model.pkl"] | |
| for path in model_paths: | |
| if os.path.exists(path): | |
| try: | |
| return joblib.load(path), True | |
| except Exception: | |
| pass | |
| return None, False | |
| saved_model, is_model_loaded = load_production_model() | |
| def predict_credit_risk(loan_amount, credit_score, annual_income, credit_utilization): | |
| if is_model_loaded and saved_model is not None: | |
| try: | |
| input_data = pd.DataFrame([{ | |
| 'Current Loan Amount': loan_amount, | |
| 'Credit Score': credit_score, | |
| 'Annual Income': annual_income, | |
| 'Credit Utilization': credit_utilization | |
| }]) | |
| probabilities = saved_model.predict_proba(input_data)[0] | |
| prob_default = probabilities[0] | |
| total_risk_score = prob_default * 100 | |
| if total_risk_score > 42.0: | |
| return 0, "HIGH RISK (Class 0 - High Default Probability [Real Model Output])", total_risk_score | |
| else: | |
| return 1, "LOW RISK (Class 1 - Safe / Approvable [Real Model Output])", total_risk_score | |
| except Exception: | |
| pass | |
| norm_loan = (loan_amount / 2000000) * 100 | |
| norm_score = ((850 - credit_score) / (850 - 300)) * 100 | |
| norm_income = (1 - (min(annual_income, 1500000) / 1500000)) * 100 | |
| norm_util = credit_utilization | |
| total_risk_score = ( | |
| (norm_loan * 0.43) + | |
| (norm_score * 0.31) + | |
| (norm_income * 0.07) + | |
| (norm_util * 0.03) | |
| ) / (0.43 + 0.31 + 0.07 + 0.03) | |
| if total_risk_score > 42.0: | |
| return 0, "HIGH RISK (Class 0 - High Default Probability)", total_risk_score | |
| else: | |
| return 1, "LOW RISK (Class 1 - Safe / Approvable)", total_risk_score | |
| # ============================================================================== | |
| # 1. SIDEBAR (YAN MENÜ) | |
| # ============================================================================== | |
| st.sidebar.image("https://img.icons8.com/fluent/96/000000/artificial-intelligence.png", width=80) | |
| st.sidebar.markdown("### Elif Ş. Beşiktepe") | |
| st.sidebar.markdown("*Data Scientist - AI & Machine Learning*") | |
| if is_model_loaded: | |
| st.sidebar.success("⚡ Real ML Model (joblib) Active") | |
| else: | |
| st.sidebar.info("ℹ️ Rule Engine Active (Weight Sealed)") | |
| st.sidebar.write("---") | |
| st.sidebar.markdown("## 🧭 Menu Navigation") | |
| page = st.sidebar.radio( | |
| "Select the analysis layer you want to visit:", | |
| [ | |
| "📊 Interactive Audit Reports (EDA)", | |
| "🧠 Credit Risk Modeling", | |
| "📋 Strategic Guideline", | |
| "🤖 Automation (AI Agent)" | |
| ] | |
| ) | |
| st.sidebar.write("---") | |
| st.sidebar.markdown("### 🛠️ SAP / DATEV Integration Point") | |
| uploaded_file = st.sidebar.file_uploader("Upload raw financial CSV file from SAP:", type=["csv"]) | |
| if uploaded_file is not None: | |
| try: | |
| raw_df = pd.read_csv(uploaded_file) | |
| st.sidebar.success(f"✔ {uploaded_file.name} successfully uploaded.") | |
| optimized_df = optimize_dataframe(raw_df) | |
| st.sidebar.caption("⚡ Memory optimization applied (gc.collect() executed).") | |
| except Exception: | |
| st.sidebar.error("An error occurred while reading the file.") | |
| st.sidebar.write("---") | |
| st.sidebar.markdown("### 🎯 Project Vision (Alphabots Vision)") | |
| st.sidebar.info( | |
| "A fully transparent, traceable, and explainable decision support architecture " | |
| "that optimizes manual routines in financial processes through AI integration." | |
| ) | |
| # ============================================================================== | |
| # ANA BAŞLIK | |
| # ============================================================================== | |
| st.markdown('<div class="main-title">AI-Driven Financial Decision Support System</div>', unsafe_allow_html=True) | |
| st.markdown('<div class="subtitle">An Explainable and Documented Decision Support System for Optimizing Financial Routines with AI</div>', unsafe_allow_html=True) | |
| # ============================================================================== | |
| # KATMAN 1: INTERACTIVE AUDIT REPORTS (EDA) | |
| # ============================================================================== | |
| if page == "📊 Interactive Audit Reports (EDA)": | |
| st.markdown('<div class="section-header">📊 Data Hygiene and Automated Audit Portal (Controlling)</div>', unsafe_allow_html=True) | |
| st.write( | |
| "An interactive layer that eliminates the manual data review workload of the Controlling department, " | |
| "reporting data quality, missing values, and anomaly distributions with a single click." | |
| ) | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| st.markdown('<div class="metric-card"><b>Report Type:</b><br>Dynamic Data Profiling Report</div>', unsafe_allow_html=True) | |
| with col2: | |
| st.markdown('<div class="metric-card"><b>Dataset Status:</b><br>Final Pre-Production Hygiene Check</div>', unsafe_allow_html=True) | |
| with col3: | |
| st.markdown('<div class="metric-card"><b>Data Quality Score:</b><br>94.2% Automatically Approved</div>', unsafe_allow_html=True) | |
| st.write("---") | |
| report_file = "report_minimal.html" if os.path.exists("report_minimal.html") else ("rapor.html" if os.path.exists("rapor.html") else None) | |
| if report_file: | |
| try: | |
| with open(report_file, "r", encoding="utf-8") as f: | |
| html_content = f.read() | |
| st.caption(f"ℹ️ Automated Audit Panel Active ({report_file}). You can analyze inter-variable relationships and correlations live.") | |
| components.html(html_content, height=800, scrolling=True) | |
| except Exception as e: | |
| st.error(f"A technical error occurred while reading the report file: {e}") | |
| else: | |
| st.error("Error: 'report_minimal.html' or 'rapor.html' file not found in the directory. Please add the automated report file to the directory.") | |
| # ============================================================================== | |
| # KATMAN 2: CREDIT RISK MODELING | |
| # ============================================================================== | |
| elif page == "🧠 Credit Risk Modeling": | |
| st.markdown('<div class="section-header">🧠 Credit Risk Modeling and Explainable AI (XAI)</div>', unsafe_allow_html=True) | |
| left_col, right_col = st.columns([1, 1]) | |
| with left_col: | |
| st.subheader("⚙️ Traceable Data Processing Pipeline (Pipeline Schema)") | |
| st.markdown(""" | |
| <div class="pipeline-box">1. RAW DATA INPUT (SAP / DATEV Excel & CSV Data)</div> | |
| <div class="pipeline-arrow">⬇</div> | |
| <div class="pipeline-box">2. MISSING DATA IMPUTATION (MICE Imputation Algorithmus)</div> | |
| <div class="pipeline-arrow">⬇</div> | |
| <div class="pipeline-box">3. CATEGORICAL ENCODING (Label Encoding Module)</div> | |
| <div class="pipeline-arrow">⬇</div> | |
| <div class="pipeline-box">4. SCALING & VARIANCE CONTROL (Robust/Standard Scaler Sealing)</div> | |
| <div class="pipeline-arrow">⬇</div> | |
| <div class="pipeline-box">5. MODEL INFERENCE (Gradient Boosting - Time-Based Validation split: 62.1% Recall)</div> | |
| """, unsafe_allow_html=True) | |
| st.write("---") | |
| st.subheader("📊 Most Influential Factors Driving the Model (Feature Importance)") | |
| features = ["Current Loan Amount", "Credit Score", "Annual Income", "Credit Utilization"] | |
| importances = [43.0, 31.0, 7.0, 3.0] | |
| df_fi = pd.DataFrame({"Feature": features, "Importance": importances}).sort_values(by="Importance", ascending=True) | |
| fig = go.Figure() | |
| fig.add_trace(go.Bar( | |
| y=df_fi["Feature"], x=df_fi["Importance"], orientation='h', | |
| marker=dict(color='#1E3A8A', line=dict(color='#10B981', width=1.5)), | |
| text=[f"{val}%" for val in df_fi["Importance"]], textposition='outside' | |
| )) | |
| fig.update_layout( | |
| xaxis=dict(title="Impact Rate on Model (%)", range=[0, 55]), | |
| margin=dict(l=5, r=5, t=10, b=10), height=250, template="plotly_white" | |
| ) | |
| st.plotly_chart(fig, use_container_width=True) | |
| st.info( | |
| "💡 **XAI Analysis:** 74% of model decisions are shaped directly by **Current Loan Amount** and **Credit Score**. " | |
| "This mathematically proves the hierarchy that field teams must focus on." | |
| ) | |
| with right_col: | |
| st.subheader("🔮 Live Inference Module") | |
| st.write("Production layer that allows field teams or management units to perform instant risk analysis during interviews:") | |
| input_loan = st.number_input("Current Loan Amount (Requested Loan Amount):", min_value=0, value=500000, step=25000) | |
| input_score = st.slider("Credit Score (Historical Credit Score):", min_value=300, max_value=850, value=650) | |
| input_income = st.number_input("Annual Income (Annual Documented Income):", min_value=0, value=350000, step=10000) | |
| input_util = st.slider("Credit Utilization Rate (Current Limit Utilization %):", min_value=0, max_value=100, value=45) | |
| st.write("") | |
| if st.button("🚀 Calculate Live Risk Status (Predict)", use_container_width=True): | |
| class_res, text_res, score_res = predict_credit_risk(input_loan, input_score, input_income, input_util) | |
| st.markdown("### 🎯 Model Output Result:") | |
| st.metric(label="Calculated Final Risk Score", value=f"{score_res:.1f}%") | |
| if class_res == 0: | |
| st.error(f"**Result:** {text_res}") | |
| st.markdown("⚠️ *Recommendation:* The interview should be structured in detail according to the RISK-2026-004 guideline, and partial approval should be considered if necessary.") | |
| else: | |
| st.success(f"**Result:** {text_res}") | |
| st.markdown("✅ *Recommendation:* Default risk remains within the safe threshold. The standard process can be executed.") | |
| # ============================================================================== | |
| # KATMAN 3: STRATEGIC GUIDELINE | |
| # ============================================================================== | |
| elif page == "📋 Strategic Guideline": | |
| st.markdown('<div class="section-header">📋 Strategic Field Interview Guideline and Decision Matrix</div>', unsafe_allow_html=True) | |
| st.write( | |
| "The dynamic and interactive software conversion of the business rules documented in the Credit Risk Report (RISK-2026-004). " | |
| "Field teams or Project Managers can access the operational action plan by selecting the relevant field during interviews or reviews." | |
| ) | |
| st.subheader("🔍 Criteria-Based Operational Action Inquiry") | |
| kriter = st.selectbox( | |
| "Select the critical criteria you want to examine or conduct an interview for:", | |
| [ | |
| "I. CRITICAL THRESHOLD: Current Loan Amount (Impact: 43%)", | |
| "II. FINANCIAL CHARACTER: Credit Score (Impact: 31%)", | |
| "III. REPAYMENT CAPACITY: Annual Income (Impact: 7%)", | |
| "IV. LIMIT DYNAMICS: Credit Utilization (Impact: 3%)" | |
| ] | |
| ) | |
| st.write("---") | |
| if "Current Loan Amount" in kriter: | |
| st.error("🚨 **43% Impact Rate | CRITICAL THRESHOLD: Current Loan Amount**") | |
| st.markdown(""" | |
| * **Strategic Approach:** This is the most sensitive variable for the model. In high-amount requests, the risk coefficient increases logarithmically. | |
| * **Interview Focus Question:** *"Can you elaborate on how you plan to use the requested amount? Do you have the possibility to use equity (down payment) for a portion of this amount?"* | |
| * **Operational Action (Field Management):** Instead of issuing an absolute rejection for borderline customers, risk exposure should be minimized by operating a **'Partial Approval'** mechanism. | |
| """) | |
| elif "Credit Score" in kriter: | |
| st.warning("🔶 **31% Impact Rate | FINANCIAL CHARACTER: Credit Score**") | |
| st.markdown(""" | |
| * **Strategic Approach:** The customer's past payment discipline is the strongest statistical indicator of future default probability. | |
| * **Interview Focus Question:** *"Was there a specific reason for any delays in your payment history over the last 24 months? What steps have you taken to improve your current financial situation?"* | |
| * **Operational Action (Field Management):** Documentation requirements should be tightened for customers whose justification for delays is based on force majeure and who request restructuring. | |
| """) | |
| elif "Annual Income" in kriter: | |
| st.info("🔷 **7% Impact Rate | REPAYMENT CAPACITY: Annual Income**") | |
| st.markdown(""" | |
| * **Strategic Approach:** Income level is a fundamental indicator of cash flow sustainability. | |
| * **Interview Focus Question:** *"Do you have any additional documented income sources besides your salary, such as rent, investments, or side income?"* | |
| * **Operational Action (Field Management):** Applications where the monthly credit installment to documented net income ratio (**Income/Installment Ratio**) exceeds 50% should be flagged directly as 'High Risk'. | |
| """) | |
| elif "Credit Utilization" in kriter: | |
| st.success("🟢 **3% Impact Rate | LIMIT DYNAMICS: Credit Utilization Rate**") | |
| st.markdown(""" | |
| * **Strategic Approach:** High utilization of existing limits signals potential liquidity stress or a debt spiral. | |
| * **Interview Focus Question:** *"Is the high utilization rate of your limits at other financial institutions due to a temporary cash cycle?"* | |
| * **Operational Action (Field Management):** Candidates with high indebtedness but positive payment intent should be offered a **'Debt Consolidation / Debt Transfer Loan'** option to mitigate risk. | |
| """) | |
| # ============================================================================== | |
| # KATMAN 4: AUTOMATION (PROCESS OPTIMIZATION AGENT) | |
| # ============================================================================== | |
| elif page == "🤖 Automation (AI Agent)": | |
| st.markdown('<div class="section-header">🤖 Automation and Process Optimization: Alphabots Senior Analyst Agent</div>', unsafe_allow_html=True) | |
| st.write("LLM Agent that automates risk analysis and process improvement steps for the Controlling department:") | |
| example_text = ( | |
| "Customer ID: 49204. Requested Loan: 1.200.000 TL. Credit Score: 580. " | |
| "Annual Income: 450.000 TL. Credit Utilization: 78%. " | |
| "The customer declared in the past interview that payments were delayed in the last 6 months due to a cyclical bottleneck." | |
| ) | |
| if "agent_input" not in st.session_state: | |
| st.session_state["agent_input"] = "" | |
| if st.button("💡 Load Example Anomaly Text"): | |
| st.session_state["agent_input"] = example_text | |
| st.rerun() | |
| user_input = st.text_area( | |
| "Paste the complex financial anomaly or audit summary you want analyzed here:", | |
| value=st.session_state["agent_input"], height=150, placeholder="Enter financial raw data or text here..." | |
| ) | |
| st.session_state["agent_input"] = user_input | |
| if st.button("🚀 Execute Live API Call and Generate Process Optimization Report"): | |
| if user_input.strip() == "": | |
| st.warning("Please enter a text for analysis.") | |
| else: | |
| with st.spinner("Running Senior Financial Analyst Agent via OpenRouter API..."): | |
| api_key = None | |
| try: | |
| if hasattr(st, "secrets") and "OPENROUTER_API_KEY" in st.secrets: | |
| api_key = st.secrets["OPENROUTER_API_KEY"] | |
| except Exception: | |
| api_key = None | |
| system_prompt = ( | |
| "You are an Alphabots Senior Financial Analyst and Process Optimization Expert. " | |
| "Analyze the given financial anomaly or customer data based on the weights in the RISK-2026-004 document " | |
| "(Loan Amount 43%, Score 31%, Income 7%, Limit 3%). When making your analysis, do not just provide a simple " | |
| "risk score; present concrete improvement recommendations that will increase the operational efficiency of the " | |
| "Controlling department, resolve bottlenecks, and hit the 'process optimization' goals in the campaign criteria." | |
| ) | |
| if api_key: | |
| try: | |
| headers = { | |
| "Authorization": f"Bearer {api_key}", | |
| "Content-Type": "application/json" | |
| } | |
| data = { | |
| "model": "google/gemini-2.5-flash", | |
| "messages": [ | |
| {"role": "system", "content": system_prompt}, | |
| {"role": "user", "content": user_input} | |
| ] | |
| } | |
| response = requests.post("https://openrouter.ai/api/v1/chat/completions", headers=headers, data=json.dumps(data)) | |
| result = response.json() | |
| llm_output = result['choices'][0]['message']['content'] | |
| st.success("✔ Process optimization analysis completed via live API!") | |
| st.markdown(llm_output) | |
| except Exception: | |
| api_key = None | |
| if not api_key: | |
| st.info("ℹ️ Local environment fallback engine active. Generating smart briefing based on RISK-2026-004 rules:") | |
| st.success("✔ Rule-Based Process Improvement Summary Successfully Generated") | |
| st.markdown(""" | |
| ### 📋 Alphabots Senior Financial Analyst Briefing | |
| * **Risk Distribution and Detection:** The Loan Amount and Limit utilization in the inputs exceeded the 43% and 3% weight thresholds of the model, pushing the system into the high-risk area. | |
| * **Process Improvement Recommendations for Controlling Department (Process Optimization):** | |
| 1. **Bottleneck Resolution:** Field teams' interview statements and Limit Utilization data in the system must be linked with an automated cross-check mechanism to eliminate manual controls. | |
| 2. **Risk-Approval Balance:** Considering the model's 62% Recall target, 'Conditional Approval' rules including maturity shortening and limit reduction should be automatically assigned to customers in this segment instead of an 'Absolute Rejection'. | |
| 3. **Process Optimization:** The financial documentation gathering process should be made autonomous with digital signature control via SAP/DATEV integration, reducing the turnaround time. | |
| """) |