PD03's picture
Update app.py
e7df474 verified
"""
RICA Agent - Complete Fixed Version
"""
import streamlit as st
import os
import sys
from pathlib import Path
import json
# Add project root to path for imports
if str(Path(__file__).parent) not in sys.path:
sys.path.append(str(Path(__file__).parent))
# Import modules
try:
from utils.model_trainer import EmbeddedChurnTrainer
from agent.rica_agent import execute_rica_analysis_hf
except ImportError as e:
st.error(f"Import error: {e}")
st.stop()
# Initialize session state
if 'api_key_valid' not in st.session_state:
st.session_state.api_key_valid = False
if 'model_trained' not in st.session_state:
st.session_state.model_trained = False
if 'trainer' not in st.session_state:
st.session_state.trainer = EmbeddedChurnTrainer()
if 'analysis_type' not in st.session_state:
st.session_state.analysis_type = 'comprehensive'
if 'risk_threshold' not in st.session_state:
st.session_state.risk_threshold = 0.6
if 'max_customers' not in st.session_state:
st.session_state.max_customers = 200
# Page configuration
st.set_page_config(
page_title="RICA - AI Revenue Intelligence",
page_icon="πŸ€–",
layout="wide",
initial_sidebar_state="expanded"
)
# Custom CSS
st.markdown("""
<style>
.main-header {
font-size: 2.5rem;
font-weight: bold;
text-align: center;
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 1rem;
}
.stAlert > div {
padding: 0.5rem;
}
.metric-container {
background: #f0f2f6;
padding: 1rem;
border-radius: 0.5rem;
margin: 0.5rem 0;
}
</style>
""", unsafe_allow_html=True)
# Header
st.markdown('<h1 class="main-header">πŸ€– RICA - AI Revenue Intelligence Agent</h1>', unsafe_allow_html=True)
st.markdown("### Enterprise Business Intelligence Powered by Machine Learning")
# Sidebar configuration
with st.sidebar:
st.header("πŸ”§ Configuration")
# API Key input with proper validation
openai_key = st.text_input(
"OpenAI API Key",
type="password",
help="Required for AI agent operations",
key="openai_api_key",
placeholder="sk-..."
)
# Validate and store API key
if openai_key and openai_key.startswith('sk-') and len(openai_key) > 20:
os.environ["OPENAI_API_KEY"] = openai_key
st.session_state.api_key_valid = True
st.success("βœ… OpenAI API Key Configured")
st.caption("Key validated and ready for use")
elif openai_key:
st.session_state.api_key_valid = False
st.error("❌ Invalid API Key Format")
st.caption("Key should start with 'sk-' and be longer than 20 characters")
else:
st.session_state.api_key_valid = False
st.warning("⚠️ Enter API Key to enable AI features")
st.divider()
# Model status
st.header("🧠 ML Model Status")
trainer = st.session_state.trainer
model_exists = trainer.model_exists()
if model_exists:
st.success("βœ… Model Ready")
try:
metadata = trainer.load_existing_metadata()
if metadata and 'metrics' in metadata:
st.metric("Model Accuracy", f"{metadata['metrics'].get('test_accuracy', 0):.1%}")
st.metric("Training Date", metadata.get('training_date', 'Unknown')[:10])
st.session_state.model_trained = True
except:
st.info("Model exists but metadata unavailable")
st.session_state.model_trained = True
else:
st.warning("⚠️ Model Not Trained")
st.session_state.model_trained = False
if st.button("πŸ‹οΈ Train Model Now", type="primary", key="train_model_btn"):
if not st.session_state.api_key_valid:
st.error("Please configure API key first")
else:
with st.spinner("Training ML model... This may take 1-2 minutes"):
try:
metrics = trainer.train_model_if_needed()
if metrics:
st.success("πŸŽ‰ Model trained successfully!")
st.session_state.model_trained = True
st.rerun()
else:
st.error("Training failed. Please check the logs.")
except Exception as e:
st.error(f"Training error: {str(e)}")
st.divider()
# Analysis configuration (only if API key is valid)
if st.session_state.api_key_valid:
st.header("πŸ“Š Analysis Options")
analysis_type = st.selectbox(
"Select Analysis Type",
["comprehensive", "churn_focus", "quick_insights"],
format_func=lambda x: {
"comprehensive": "🎯 Comprehensive Review",
"churn_focus": "🚨 Churn Risk Analysis",
"quick_insights": "⚑ Quick Insights"
}[x],
key="analysis_type_select"
)
st.session_state.analysis_type = analysis_type
# Advanced options
with st.expander("βš™οΈ Advanced Options"):
risk_threshold = st.slider(
"Churn Risk Threshold",
0.3, 0.9, 0.6,
key="risk_threshold_slider"
)
max_customers = st.number_input(
"Max Customers to Analyze",
50, 500, 200,
key="max_customers_input"
)
st.session_state.risk_threshold = risk_threshold
st.session_state.max_customers = max_customers
# Main content logic
if not st.session_state.api_key_valid:
# Show welcome screen when API key not configured
st.info("πŸ‘ˆ Please enter your OpenAI API Key in the sidebar to begin")
col1, col2 = st.columns(2)
with col1:
st.markdown("""
## πŸš€ Capabilities
**RICA** combines machine learning with autonomous AI to deliver:
- 🎯 **Churn Prediction**: ML models identify at-risk customers
- πŸ“Š **Real-time Analysis**: Direct SAP data integration
- πŸ€– **Autonomous Insights**: LLM-powered recommendations
- πŸ“ˆ **Business Impact**: Actionable revenue optimization
""")
with col2:
st.markdown("""
## πŸ—οΈ Architecture
- **Data Source**: Real SAP/SALT dataset
- **ML Engine**: Scikit-learn Random Forest
- **Agent Framework**: smolagents + OpenAI
- **Analytics**: DuckDB high-performance processing
- **UI**: Streamlit interactive interface
""")
# Demo metrics
st.markdown("## πŸ“Š Sample Analytics Preview")
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric("Customers", "2,847", delta="12%")
with col2:
st.metric("Churn Risk", "23 customers", delta="-8", delta_color="inverse")
with col3:
st.metric("Revenue at Risk", "$1.2M", delta="15%")
with col4:
st.metric("Model Accuracy", "87.3%", delta="2.1%")
elif not st.session_state.model_trained:
# Model training required
st.warning("🧠 Machine learning model needs to be trained before analysis")
st.info("πŸ‘ˆ Use the 'Train Model Now' button in the sidebar (takes 1-2 minutes)")
st.markdown("## πŸ”„ Training Process")
st.markdown("""
1. **Load SAP Data**: Customer and sales data from Hugging Face Hub
2. **Feature Engineering**: RFM analysis and behavioral patterns
3. **Model Training**: Random Forest classifier with cross-validation
4. **Performance Validation**: Accuracy testing and metrics calculation
5. **Model Persistence**: Save for future predictions
""")
else:
# Main analysis interface - API key valid and model trained
st.markdown("## 🎯 AI Business Intelligence Dashboard")
# Analysis execution
if st.button("πŸš€ Run RICA Analysis", type="primary", use_container_width=True):
with st.spinner("πŸ€– RICA is analyzing your business data..."):
try:
# Execute analysis
parameters = {
"risk_threshold": st.session_state.risk_threshold,
"max_customers": st.session_state.max_customers
}
result = execute_rica_analysis_hf(st.session_state.analysis_type, parameters)
# Display results
st.success("βœ… Analysis Complete!")
# Create tabs for different result views
if st.session_state.analysis_type == "comprehensive":
tab1, tab2, tab3 = st.tabs(["πŸ“Š Executive Summary", "🚨 Risk Analysis", "πŸ’‘ Recommendations"])
with tab1:
st.markdown("### Executive Dashboard")
st.info(str(result))
with tab2:
st.markdown("### Customer Risk Analysis")
st.write("Detailed churn risk breakdown and customer segmentation")
with tab3:
st.markdown("### AI Recommendations")
st.write("Specific actions prioritized by business impact")
else:
st.markdown(f"### {st.session_state.analysis_type.replace('_', ' ').title()} Results")
st.info(str(result))
# Raw response in expander
with st.expander("πŸ” Detailed Analysis Response"):
st.code(str(result), language="text")
except Exception as e:
st.error(f"❌ Analysis failed: {str(e)}")
st.info("Please check your API key and model status")
# Show model performance metrics
if st.session_state.trainer.model_exists():
st.markdown("## πŸ“ˆ Model Performance")
try:
metadata = st.session_state.trainer.load_existing_metadata()
if metadata and 'metrics' in metadata:
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Model Accuracy", f"{metadata['metrics'].get('test_accuracy', 0):.1%}")
with col2:
st.metric("Training Samples", f"{metadata['metrics'].get('training_samples', 0):,}")
with col3:
st.metric("Churn Rate", f"{metadata['metrics'].get('churn_rate', 0):.1%}")
except:
st.info("Model performance metrics unavailable")
# Footer
st.markdown("---")
st.markdown("πŸ€– **RICA Agent** | ML + AI for Business Intelligence | Deployed on πŸ€— Hugging Face Spaces")