import streamlit as st
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime
import json
import warnings
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import LabelEncoder
import numpy as np
import html
import re
warnings.filterwarnings('ignore')
# Import our modules
from config import Config
from database_manager import DatabaseManager
from groq_agent import GroqAgent
from granite_agent import GraniteAgent
from granite_chat import GraniteChatAgent # New import for chat functionality
from reward_system import RewardSystem
from summarisation import create_summarizer
def clean_health_ai_response(raw_response):
"""
Health-specific AI response cleaner with medical disclaimer handling.
"""
if not raw_response or not isinstance(raw_response, str):
return None, {}
try:
response = raw_response.strip()
# Remove HTML tags
response = re.sub(r'<[^>]+>', '', response)
response = html.unescape(response)
# Clean up formatting
response = re.sub(r'\n{3,}', '\n\n', response)
response = re.sub(r' {2,}', ' ', response)
# Remove system prefixes
response = re.sub(r'^(Assistant|AI|Bot|Health Coach):\s*', '', response, flags=re.IGNORECASE)
# Ensure medical disclaimer is properly formatted if present
if "consult" in response.lower() and "doctor" in response.lower():
response = re.sub(
r'(.*consult.*doctor.*)',
r'**Important:** \1',
response,
flags=re.IGNORECASE
)
# Clean up any JSON-like formatting
response = re.sub(r'^\{.*?\}$', '', response, flags=re.DOTALL)
response = re.sub(r'"[^"]*":\s*', '', response)
response = re.sub(r'[{}"\[\],]', '', response)
response = response.strip()
if not response:
return None, {"error": "Response became empty after cleaning"}
metadata = {
"original_length": len(raw_response),
"cleaned_length": len(response),
"has_disclaimer": "consult" in response.lower() and "doctor" in response.lower(),
"response_type": "health_advice"
}
return response, metadata
except Exception as e:
return None, {"error": f"Error cleaning health response: {str(e)}"}
# Page configuration
st.set_page_config(
page_title="🌟 Dynamic Wellness Platform",
page_icon="🌟",
layout="wide"
)
# Custom CSS with improved styling
st.markdown("""
""", unsafe_allow_html=True)
# Initialize services
@st.cache_resource
def initialize_services():
config = Config()
db_manager = DatabaseManager(config)
groq_agent = GroqAgent(config)
granite_agent = GraniteAgent(config)
granite_chat_agent = GraniteChatAgent(config) # Add GraniteChatAgent
reward_system = RewardSystem(config, db_manager)
summarizer = create_summarizer(config)
return config, db_manager, groq_agent, granite_agent, granite_chat_agent, reward_system, summarizer
def calculate_health_scores(user_profile):
"""Calculate strict health factor scores based on user profile"""
scores = {}
# Sleep Quality Score (stricter evaluation)
sleep_hours = user_profile.get('Sleep_Hours', 7)
sleep_quality = user_profile.get('Sleep_Quality', 'Fair')
if sleep_hours >= 7 and sleep_hours <= 9 and sleep_quality in ['Excellent', 'Good']:
scores['Sleep Quality'] = 9
elif sleep_hours >= 6 and sleep_hours <= 10 and sleep_quality == 'Good':
scores['Sleep Quality'] = 7
elif sleep_hours >= 6 and sleep_hours <= 10 and sleep_quality == 'Fair':
scores['Sleep Quality'] = 5
else:
scores['Sleep Quality'] = 3
# Stress Level Score (stricter)
stress_level = user_profile.get('Stress_Level', 'Medium')
anxiety_freq = user_profile.get('Anxiety_Frequency', 'Sometimes')
if stress_level == 'Low' and anxiety_freq in ['Never', 'Rarely']:
scores['Stress Management'] = 9
elif stress_level == 'Low' and anxiety_freq == 'Sometimes':
scores['Stress Management'] = 7
elif stress_level == 'Medium' and anxiety_freq in ['Never', 'Rarely']:
scores['Stress Management'] = 6
elif stress_level == 'Medium' and anxiety_freq == 'Sometimes':
scores['Stress Management'] = 4
else:
scores['Stress Management'] = 2
# Work-Life Balance Score (stricter)
work_hours = user_profile.get('Work_Hours', 40)
energy_level = user_profile.get('Energy_Level', 'Medium')
if work_hours <= 40 and energy_level in ['Very High', 'High']:
scores['Work-Life Balance'] = 9
elif work_hours <= 45 and energy_level in ['High', 'Medium']:
scores['Work-Life Balance'] = 7
elif work_hours <= 50 and energy_level == 'Medium':
scores['Work-Life Balance'] = 5
elif work_hours <= 55:
scores['Work-Life Balance'] = 3
else:
scores['Work-Life Balance'] = 1
# Physical Activity Score (stricter)
activity_hours = user_profile.get('Physical_Activity_Hours', 3)
if activity_hours >= 5:
scores['Physical Activity'] = 9
elif activity_hours >= 3:
scores['Physical Activity'] = 7
elif activity_hours >= 1.5:
scores['Physical Activity'] = 5
elif activity_hours >= 0.5:
scores['Physical Activity'] = 3
else:
scores['Physical Activity'] = 1
# Diet & Lifestyle Score (new, stricter)
diet = user_profile.get('Diet', 'Average')
smoking = user_profile.get('Smoking', 'Non-Smoker')
alcohol = user_profile.get('Alcohol_Consumption', 'Rarely')
diet_score = 9 if diet == 'Healthy' else 5 if diet == 'Average' else 2
smoking_penalty = 0 if smoking == 'Non-Smoker' else -2 if smoking == 'Occasional Smoker' else -4
alcohol_penalty = 0 if alcohol in ['Never', 'Rarely'] else -1 if alcohol == 'Occasionally' else -3
scores['Diet & Lifestyle'] = max(1, diet_score + smoking_penalty + alcohol_penalty)
# Social Media & Digital Wellness (new)
social_media_hours = user_profile.get('Social_Media_Hours', 3)
if social_media_hours <= 1:
scores['Digital Wellness'] = 9
elif social_media_hours <= 2:
scores['Digital Wellness'] = 7
elif social_media_hours <= 4:
scores['Digital Wellness'] = 5
elif social_media_hours <= 6:
scores['Digital Wellness'] = 3
else:
scores['Digital Wellness'] = 1
return scores
def calculate_risk_level(user_profile):
"""Calculate overall risk level based on health scores"""
health_scores = calculate_health_scores(user_profile)
# Calculate weighted average of health scores
# Lower scores indicate higher risk, so we need to invert the scale
total_score = sum(health_scores.values())
max_possible_score = len(health_scores) * 9 # Maximum score per factor is 9
# Convert to risk scale (1-10, where 10 is highest risk)
# If average score is 9, risk should be 1
# If average score is 1, risk should be 10
average_score = total_score / len(health_scores)
risk_level = max(1, min(10, 11 - average_score))
# Apply additional risk factors
additional_risk = 0
# High work hours increase risk
if user_profile.get('Work_Hours', 40) > 60:
additional_risk += 1
# Poor mood significantly increases risk
mood = user_profile.get('Mood', 'Neutral')
if mood in ['Sad', 'Very Sad']:
additional_risk += 2
elif mood == 'Neutral':
additional_risk += 0.5
# High stress with frequent anxiety increases risk
if (user_profile.get('Stress_Level') == 'High' and
user_profile.get('Anxiety_Frequency') in ['Often', 'Always']):
additional_risk += 1.5
# Very low sleep hours increase risk
if user_profile.get('Sleep_Hours', 7) < 5:
additional_risk += 1
# Current medication might indicate existing health issues
if user_profile.get('Medication') == 'Yes':
additional_risk += 0.5
final_risk = min(10, risk_level + additional_risk)
return round(final_risk)
def get_risk_indicator(risk_level):
"""Return risk indicator HTML"""
if risk_level <= 3:
risk_class = "risk-low"
risk_text = "LOW RISK"
risk_description = "Your wellness indicators look good"
elif risk_level <= 6:
risk_class = "risk-medium"
risk_text = "MODERATE RISK"
risk_description = "Some areas need attention"
else:
risk_class = "risk-high"
risk_text = "HIGH RISK"
risk_description = "Important to address wellness concerns"
return f"""
{risk_text} ({risk_level}/10)
{risk_description}
"""
def collect_user_profile():
"""Collect user profile data using the same form as the mental health app"""
st.header("👤 Your Health Profile")
st.markdown("*Please fill out your information to get started with personalized wellness coaching*")
with st.form("user_profile_form"):
st.subheader("📋 Personal Information")
col1, col2 = st.columns(2)
with col1:
age = st.number_input("Age", min_value=18, max_value=100, value=30)
gender = st.selectbox("Gender", ["Male", "Female", "Non-binary", "Prefer not to say"])
occupation = st.selectbox("Occupation", ["Engineering", "Healthcare", "Education", "IT", "Finance", "Sales", "Other"])
country = st.selectbox("Country", ["USA", "Canada", "UK", "Germany", "Australia", "India", "Other"])
with col2:
consultation = st.selectbox("Previous Mental Health Consultation", ["Yes", "No"])
medication = st.selectbox("Currently Taking Medication", ["Yes", "No"])
diet = st.selectbox("Diet Quality", ["Healthy", "Average", "Unhealthy"])
smoking = st.selectbox("Smoking Habit", ["Non-Smoker", "Occasional Smoker", "Regular Smoker", "Heavy Smoker"])
st.subheader("📊 Lifestyle Factors")
col3, col4 = st.columns(2)
with col3:
sleep_hours = st.slider("Average Sleep Hours per Night", 4, 12, 7)
work_hours = st.slider("Work Hours per Week", 20, 80, 40)
social_media_hours = st.slider("Social Media Hours per Day", 0, 12, 3)
with col4:
physical_activity = st.slider("Physical Activity Hours per Week", 0, 20, 3)
stress_level = st.selectbox("Stress Level", ["Low", "Medium", "High"])
alcohol_consumption = st.selectbox("Alcohol Consumption", ["Never", "Rarely", "Occasionally", "Regularly"])
st.subheader("💭 Mental Health & Mood")
col5, col6 = st.columns(2)
with col5:
mood = st.selectbox("General Mood", ["Very Happy", "Happy", "Neutral", "Sad", "Very Sad"])
anxiety_frequency = st.selectbox("Anxiety Frequency", ["Never", "Rarely", "Sometimes", "Often", "Always"])
with col6:
sleep_quality = st.selectbox("Sleep Quality", ["Excellent", "Good", "Fair", "Poor"])
energy_level = st.selectbox("Energy Level", ["Very High", "High", "Medium", "Low", "Very Low"])
submitted = st.form_submit_button("🚀 Start My Wellness Journey", type="primary", use_container_width=True)
if submitted:
# Create user profile dictionary
user_profile = {
"user_id": f"user_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
"Age": age,
"Gender": gender,
"Occupation": occupation,
"Country": country,
"Mental_Health_Consultation": consultation,
"Medication": medication,
"Diet": diet,
"Smoking": smoking,
"Sleep_Hours": sleep_hours,
"Work_Hours": work_hours,
"Social_Media_Hours": social_media_hours,
"Physical_Activity_Hours": physical_activity,
"Stress_Level": stress_level,
"Alcohol_Consumption": alcohol_consumption,
"Mood": mood,
"Anxiety_Frequency": anxiety_frequency,
"Sleep_Quality": sleep_quality,
"Energy_Level": energy_level,
"created_at": datetime.now()
}
return user_profile
return None
def display_user_dashboard(user_profile, db_manager, groq_agent, granite_agent, granite_chat_agent, reward_system, summarizer):
"""Display the main user dashboard with all features using the summarizer"""
config = Config()
user_id = user_profile['user_id']
# Header with user info
st.markdown('🌟 Your Personal Wellness Dashboard
', unsafe_allow_html=True)
st.markdown(f"*Welcome back! Here's your personalized wellness experience.*")
# Top metrics row
col1, col2, col3, col4 = st.columns(4)
reward_summary = reward_system.get_reward_summary(user_id)
with col1:
st.metric("💰 Total Coins", reward_summary['total_coins'])
with col2:
st.metric("⚡ Coins Earned", reward_summary['total_earned'])
with col3:
st.metric("⏳ Pending Tasks", reward_summary['pending_tasks'])
with col4:
st.metric("🏆 Tasks Done", reward_summary['completed_tasks'])
# Tabs for different sections
tab1, tab2, tab3, tab4 = st.tabs(["🤖 AI Health Coach", "📋 My Tasks", "💬 Ask Questions", "📊 My Progress"])
with tab1:
st.header("🤖 AI Health Analysis & Coaching")
col1, col2 = st.columns([2, 1])
with col1:
if st.button("🔍 Get AI Health Analysis", type="primary", use_container_width=True):
with st.spinner("🤖 Analyzing your health profile..."):
# Calculate risk level based on health scores
risk_level = calculate_risk_level(user_profile)
# Get mental health assessment from Groq
assessment, _ = groq_agent.analyze_mental_health(user_profile)
# Use summarizer for clean display
summarized_assessment = summarizer.summarize_health_analysis(
assessment, risk_level, user_profile
)
# Display risk level indicator
st.markdown(get_risk_indicator(risk_level), unsafe_allow_html=True)
# Display summarized assessment in bullet format
st.markdown(f"""
🎯 Your Wellness Assessment
{summarized_assessment}
AI-Powered Analysis • {datetime.now().strftime('%Y-%m-%d %H:%M')}
""", unsafe_allow_html=True)
# Save conversation with both original and summarized versions
db_manager.save_conversation(user_id, {
"type": "health_analysis",
"assessment": assessment,
"summarized_assessment": summarized_assessment,
"risk_level": risk_level
})
# If risk level is concerning, get tasks from Granite
if risk_level >= 4: # Medium to high risk
st.warning("⚠️ Your assessment indicates some areas that need attention. Let me create a personalized wellness plan for you.")
with st.spinner("🎯 Creating personalized wellness tasks..."):
# Get tasks from Granite
tasks = granite_agent.assign_wellness_tasks(user_profile, assessment, risk_level)
if tasks:
st.success(f"✅ Created {len(tasks)} personalized wellness tasks for you!")
# Save tasks to database
for task in tasks:
task_id = db_manager.save_task(user_id, task)
if task_id:
st.markdown(f"""
🎯 {task['title']}
Type: {task['task_type'].replace('_', ' ').title()}
Description: {task['description']}
Duration: {task['duration_days']} days
Difficulty: {task['difficulty'].title()}
Instructions: {task['instructions']}
Completion Criteria: {task['completion_criteria']}
Reward: {reward_system.calculate_task_reward(task['task_type'], task['difficulty'])} coins
""", unsafe_allow_html=True)
st.info("📋 Your new tasks have been added to the 'My Tasks' tab. Complete them to earn coins!")
else:
st.error("❌ Unable to create tasks at this time. Please try again later.")
else:
st.success("🎉 Great news! Your mental health profile looks good. Here are some tips to maintain your wellness:")
# Get wellness tips from Groq and summarize them
with st.spinner("💡 Getting personalized tips..."):
tips = groq_agent.get_health_tips(user_profile)
summarized_tips = summarizer.summarize_wellness_tips(tips, user_profile)
# Display summarized tips
st.markdown(f"""
💡 Personalized Wellness Tips
{summarized_tips}
""", unsafe_allow_html=True)
# Save tips conversation
db_manager.save_conversation(user_id, {
"type": "wellness_tips",
"tips": tips,
"summarized_tips": summarized_tips
})
with col2:
st.subheader("📊 Quick Health Insights")
# Calculate health scores based on user profile
health_factors = calculate_health_scores(user_profile)
fig = go.Figure(go.Bar(
x=list(health_factors.values()),
y=list(health_factors.keys()),
orientation='h',
marker_color=['green' if v >= 7 else 'orange' if v >= 5 else 'red' for v in health_factors.values()],
text=[f"{v}/10" for v in health_factors.values()],
textposition='inside'
))
fig.update_layout(
title="Health Factors Score (1-10)",
xaxis_title="Score",
height=350,
showlegend=False,
xaxis=dict(range=[0, 10]),
font=dict(color="black")
)
st.plotly_chart(fig, use_container_width=True)
# Show calculated risk level
current_risk = calculate_risk_level(user_profile)
st.markdown(get_risk_indicator(current_risk), unsafe_allow_html=True)
# Quick wellness tips button
st.subheader("💡 Daily Wellness Tips")
if st.button("Get Fresh Tips", use_container_width=True):
with st.spinner("💡 Generating fresh tips..."):
# Get tips from Groq and summarize
tips = groq_agent.get_health_tips(user_profile)
summarized_tips = summarizer.summarize_wellness_tips(tips, user_profile)
st.markdown(f"""
""", unsafe_allow_html=True)
with tab2:
st.header("📋 My Wellness Tasks")
# Get user tasks
pending_tasks = db_manager.get_user_tasks(user_id, "pending")
completed_tasks = db_manager.get_user_tasks(user_id, "completed")
col1, col2 = st.columns(2)
with col1:
st.subheader("⏳ Pending Tasks")
if pending_tasks:
for task in pending_tasks:
st.markdown(f"""
🎯 {task['title']}
Type: {task['task_type'].replace('_', ' ').title()}
Description: {task['description']}
Instructions: {task['instructions']}
Reward: {reward_system.calculate_task_reward(task['task_type'], task.get('difficulty', 'medium'))} coins
""", unsafe_allow_html=True)
# Task completion form
with st.expander(f"✅ Complete: {task['title']}"):
st.write(f"**Completion Criteria:** {task['completion_criteria']}")
with st.form(f"complete_task_{task['task_id']}"):
st.write("Please provide details about your task completion:")
completion_notes = st.text_area(
"How did you complete this task?",
placeholder="Describe what you did, how it went, any challenges..."
)
quality_rating = st.slider(
"Rate the quality of your completion (1-5)",
min_value=1, max_value=5, value=3
)
exceeded_expectations = st.checkbox(
"I went above and beyond the basic requirements"
)
if st.form_submit_button("🎉 Mark as Completed"):
completion_data = {
"notes": completion_notes,
"quality_rating": quality_rating,
"exceeded_expectations": exceeded_expectations
}
coins_earned = reward_system.award_task_completion(
user_id, task['task_id'], completion_data
)
if coins_earned > 0:
st.markdown(f"""
🎉 Congratulations! You earned {coins_earned} coins!
""", unsafe_allow_html=True)
st.success(f"✅ Task completed successfully! You earned {coins_earned} coins!")
st.balloons()
# Rerun to update the display
st.rerun()
else:
st.error("❌ There was an issue completing the task. Please try again.")
else:
st.info("🎯 No pending tasks right now. Get an AI health analysis to receive personalized wellness tasks!")
with col2:
st.subheader("✅ Completed Tasks")
if completed_tasks:
for task in completed_tasks[-5:]: # Show last 5 completed tasks
completed_date = task.get('completed_at', datetime.now()).strftime('%Y-%m-%d')
coins_earned = reward_system.calculate_task_reward(
task['task_type'],
task.get('difficulty', 'medium'),
task.get('completion_data', {})
)
st.markdown(f"""
✅ {task['title']}
Completed: {completed_date}
Coins Earned: {coins_earned}
""", unsafe_allow_html=True)
else:
st.info("🏆 Completed tasks will appear here as you finish them!")
# Progress summary
if completed_tasks or pending_tasks:
total_tasks = len(completed_tasks) + len(pending_tasks)
completion_rate = len(completed_tasks) / total_tasks * 100 if total_tasks > 0 else 0
fig_progress = go.Figure(go.Indicator(
mode="gauge+number",
value=completion_rate,
title={'text': "Task Completion Rate"},
domain={'x': [0, 1], 'y': [0, 1]},
gauge={
'axis': {'range': [None, 100]},
'bar': {'color': "darkgreen"},
'steps': [
{'range': [0, 50], 'color': "lightgray"},
{'range': [50, 80], 'color': "yellow"},
{'range': [80, 100], 'color': "lightgreen"}
]
}
))
fig_progress.update_layout(height=250, font=dict(color="black"))
st.plotly_chart(fig_progress, use_container_width=True)
# TAB 3 - UPDATED WITH GRANITE CHAT AGENT
with tab3:
st.header("💬 Ask Your AI Health Coach")
# Add indicator that we're using Granite Chat
st.markdown(f"""
🧠 Powered by IBM Granite Chat AI - Advanced conversational health coaching with memory
""", unsafe_allow_html=True)
st.markdown("*Ask any health-related question and get personalized advice based on your profile with conversation memory*")
# Initialize chat history for this user
if f"granite_chat_history_{user_id}" not in st.session_state:
st.session_state[f"granite_chat_history_{user_id}"] = [
{"role": "assistant", "content": "Hello! I'm your personal AI health coach powered by IBM Granite Chat. I know your profile and I maintain conversation memory to provide better, contextual responses. How can I assist you today?"}
]
# Display chat messages with enhanced health-specific styling
for message in st.session_state[f"granite_chat_history_{user_id}"]:
with st.chat_message(message["role"]):
if message["role"] == "assistant":
content = message["content"]
# Check if this message contains medical advice
if "consult" in content.lower() and "doctor" in content.lower():
# Highlight medical disclaimers
st.markdown(f'''
⚠️ Medical Advice:
{content}
''', unsafe_allow_html=True)
else:
st.markdown(f'{content}
', unsafe_allow_html=True)
else:
st.markdown(f'{message["content"]}
', unsafe_allow_html=True)
# Chat input
if prompt := st.chat_input("Ask me anything about health and wellness..."):
# Add user message
st.session_state[f"granite_chat_history_{user_id}"].append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(f'{prompt}
', unsafe_allow_html=True)
# Generate AI response using Granite Chat agent
with st.chat_message("assistant"):
with st.spinner("🧠 Granite Chat AI is thinking..."):
try:
# Use Granite Chat agent for chat response with conversation memory
raw_response = granite_chat_agent.get_chat_response(prompt, user_profile, context=None)
# Use health-specific cleaning function
response, metadata = clean_health_ai_response(raw_response)
if response:
# Add medical disclaimer styling if present
if metadata.get('has_disclaimer', False):
response_html = f'''
⚠️ Medical Advice:
{response}
'''
else:
response_html = f'{response}
'
st.markdown(response_html, unsafe_allow_html=True)
st.session_state[f"granite_chat_history_{user_id}"].append({"role": "assistant", "content": response})
# Save with enhanced metadata
db_manager.save_conversation(user_id, {
"type": "granite_chat_interaction",
"user_question": prompt,
"ai_response": response,
"agent_used": "granite_chat",
"metadata": metadata,
"has_medical_disclaimer": metadata.get('has_disclaimer', False),
"conversation_length": len(granite_chat_agent.conversation_history)
})
else:
error_msg = "I'm having trouble processing your question right now. Could you please rephrase or try again?"
st.markdown(f'{error_msg}
', unsafe_allow_html=True)
st.session_state[f"granite_chat_history_{user_id}"].append({"role": "assistant", "content": error_msg})
except Exception as e:
error_msg = f"I encountered an error while processing your question. Please try again or rephrase your question."
st.markdown(f'{error_msg}
', unsafe_allow_html=True)
st.session_state[f"granite_chat_history_{user_id}"].append({"role": "assistant", "content": error_msg})
# Quick question buttons - now using Granite Chat
st.subheader("🚀 Quick Questions")
col1, col2, col3 = st.columns(3)
quick_questions = [
"How can I reduce my stress levels?",
"What's the best sleep routine for me?",
"How much exercise should I be doing?",
"How can I improve my work-life balance?",
"What foods should I eat for better mood?",
"How can I manage my social media usage?"
]
for i, question in enumerate(quick_questions[:6]):
col = [col1, col2, col3][i % 3]
with col:
if st.button(question, key=f"granite_quick_q_{i}"):
# Add question to chat and trigger response
st.session_state[f"granite_chat_history_{user_id}"].append({"role": "user", "content": question})
# Generate AI response using Granite Chat
with st.spinner("🧠 Granite Chat AI is thinking..."):
try:
# Use Granite Chat agent for chat response
raw_response = granite_chat_agent.get_chat_response(question, user_profile, context=None)
# Use health-specific cleaning function
response, metadata = clean_health_ai_response(raw_response)
if response:
st.session_state[f"granite_chat_history_{user_id}"].append({"role": "assistant", "content": response})
# Save with enhanced metadata
db_manager.save_conversation(user_id, {
"type": "granite_chat_interaction",
"user_question": question,
"ai_response": response,
"agent_used": "granite_chat",
"metadata": metadata,
"has_medical_disclaimer": metadata.get('has_disclaimer', False),
"conversation_length": len(granite_chat_agent.conversation_history)
})
else:
error_msg = "I'm having trouble processing your question right now. Please try again."
st.session_state[f"granite_chat_history_{user_id}"].append({"role": "assistant", "content": error_msg})
except Exception as e:
error_msg = f"I encountered an error while processing your question. Please try again."
st.session_state[f"granite_chat_history_{user_id}"].append({"role": "assistant", "content": error_msg})
# Rerun to show the new messages
st.rerun()
# Add Granite Chat-specific features
st.markdown("---")
st.subheader("🧠 Granite Chat AI Features")
col1, col2, col3 = st.columns(3)
with col1:
if st.button("💡 Get Wellness Advice", use_container_width=True, key="granite_wellness_advice"):
with st.spinner("🧠 Granite Chat AI generating wellness advice..."):
advice = granite_chat_agent.get_wellness_advice("general wellness based on my profile", user_profile)
cleaned_advice, _ = clean_health_ai_response(advice)
if cleaned_advice:
st.session_state[f"granite_chat_history_{user_id}"].append({"role": "assistant", "content": cleaned_advice})
st.rerun()
with col2:
if st.button("❓ Ask Health Question", use_container_width=True, key="granite_health_question"):
question = "What should I focus on most for better health based on my profile?"
with st.spinner("🧠 Granite Chat AI answering..."):
answer = granite_chat_agent.answer_question(question, user_profile)
cleaned_answer, _ = clean_health_ai_response(answer)
if cleaned_answer:
st.session_state[f"granite_chat_history_{user_id}"].append({"role": "user", "content": question})
st.session_state[f"granite_chat_history_{user_id}"].append({"role": "assistant", "content": cleaned_answer})
st.rerun()
with col3:
if st.button("🤝 Get Support", use_container_width=True, key="granite_support"):
concern = "feeling overwhelmed with my wellness goals"
with st.spinner("🧠 Granite Chat AI providing support..."):
support = granite_chat_agent.provide_support(concern, user_profile)
cleaned_support, _ = clean_health_ai_response(support)
if cleaned_support:
st.session_state[f"granite_chat_history_{user_id}"].append({"role": "user", "content": f"I'm {concern}"})
st.session_state[f"granite_chat_history_{user_id}"].append({"role": "assistant", "content": cleaned_support})
st.rerun()
# Granite Chat conversation controls
st.markdown("---")
st.subheader("🎛️ Chat Controls")
col1, col2, col3 = st.columns(3)
with col1:
if st.button("🗑️ Clear Chat History", use_container_width=True, key="granite_clear_chat"):
st.session_state[f"granite_chat_history_{user_id}"] = [
{"role": "assistant", "content": "Hello! I'm your personal AI health coach powered by IBM Granite Chat. How can I assist you today?"}
]
granite_chat_agent.clear_conversation_history()
st.success("Chat history cleared!")
st.rerun()
with col2:
if st.button("📊 Conversation Summary", use_container_width=True, key="granite_conv_summary"):
summary = granite_chat_agent.get_conversation_summary()
st.info(summary)
with col3:
# Chat personality selector
personality_type = st.selectbox("🎭 Chat Personality",
["supportive", "professional", "casual", "direct"],
key="granite_personality_select",
help="Choose how the AI should respond to you")
if st.button("Set Personality", use_container_width=True, key="granite_set_personality"):
granite_chat_agent.set_chat_personality(personality_type)
st.success(f"Chat personality set to: {personality_type}")
# Display conversation statistics
st.markdown("---")
st.subheader("📈 Chat Statistics")
col1, col2, col3 = st.columns(3)
total_messages = len(st.session_state.get(f"granite_chat_history_{user_id}", []))
user_messages = len([msg for msg in st.session_state.get(f"granite_chat_history_{user_id}", []) if msg["role"] == "user"])
assistant_messages = len([msg for msg in st.session_state.get(f"granite_chat_history_{user_id}", []) if msg["role"] == "assistant"])
with col1:
st.metric("Total Messages", total_messages)
with col2:
st.metric("Your Questions", user_messages)
with col3:
st.metric("AI Responses", assistant_messages)
# Show Granite Chat agent internal conversation history length
granite_internal_history = len(granite_chat_agent.conversation_history)
st.info(f"🧠 Granite Chat AI is maintaining {granite_internal_history} conversation turns in memory for better context.")
with tab4:
st.header("📊 My Wellness Progress")
# Get user's progress data
all_tasks = db_manager.get_user_tasks(user_id)
completed_tasks = [task for task in all_tasks if task.get('status') == 'completed']
conversations = list(db_manager.db[config.CONVERSATIONS_COLLECTION].find(
{"user_id": user_id}
).sort("timestamp", -1).limit(10))
col1, col2 = st.columns(2)
with col1:
st.subheader("🏆 Achievement Summary")
# Use summarizer for progress summary
progress_summary = summarizer.create_progress_summary(completed_tasks, user_profile)
# Display progress summary
st.markdown(f"""
📈 Your Progress Highlights
{progress_summary}
""", unsafe_allow_html=True)
# Calculate achievements
reward_summary = reward_system.get_reward_summary(user_id)
st.metric("Total Coins Earned", reward_summary['total_earned'])
st.metric("Current Coin Balance", reward_summary['total_coins'])
st.metric("Tasks Completed", reward_summary['completed_tasks'])
st.metric("Pending Tasks", reward_summary['pending_tasks'])
# Current risk level display
current_risk = calculate_risk_level(user_profile)
st.markdown(f"""
Current Risk Level: {current_risk}/10
Based on your health profile analysis
""", unsafe_allow_html=True)
# Task completion by type
if all_tasks:
completed_by_type = {}
for task in all_tasks:
if task.get('status') == 'completed':
task_type = task['task_type'].replace('_', ' ').title()
completed_by_type[task_type] = completed_by_type.get(task_type, 0) + 1
if completed_by_type:
fig_tasks = px.pie(
values=list(completed_by_type.values()),
names=list(completed_by_type.keys()),
title="Completed Tasks by Type"
)
fig_tasks.update_layout(font=dict(color="black"))
st.plotly_chart(fig_tasks, use_container_width=True)
with col2:
st.subheader("📈 Progress Timeline")
if all_tasks:
# Create timeline of task completions
task_timeline = []
for task in all_tasks:
if task.get('status') == 'completed' and task.get('completed_at'):
task_timeline.append({
'date': task['completed_at'].strftime('%Y-%m-%d'),
'task': task['title'],
'coins': reward_system.calculate_task_reward(
task['task_type'],
task.get('difficulty', 'medium')
)
})
if task_timeline:
timeline_df = pd.DataFrame(task_timeline)
# Group by date and sum coins
daily_coins = timeline_df.groupby('date')['coins'].sum().reset_index()
fig_timeline = px.line(
daily_coins,
x='date',
y='coins',
title="Daily Coins Earned",
markers=True
)
fig_timeline.update_layout(font=dict(color="black"))
st.plotly_chart(fig_timeline, use_container_width=True)
else:
st.info("Complete some tasks to see your progress timeline!")
else:
st.info("Your progress will appear here as you complete tasks and interact with the AI coach!")
# Health scores visualization
st.subheader("📊 Health Factor Trends")
health_scores = calculate_health_scores(user_profile)
fig_health = go.Figure(data=go.Scatterpolar(
r=list(health_scores.values()),
theta=list(health_scores.keys()),
fill='toself',
name='Health Scores'
))
fig_health.update_layout(
polar=dict(
radialaxis=dict(
visible=True,
range=[0, 10]
)),
showlegend=False,
title="Health Factors Radar Chart",
font=dict(color="black")
)
st.plotly_chart(fig_health, use_container_width=True)
# Recent activity with summarized content
st.subheader("📝 Recent Activity")
if conversations:
for conv in conversations[:5]:
timestamp = conv['timestamp'].strftime('%Y-%m-%d %H:%M')
conv_type = conv.get('type', 'unknown')
agent_used = conv.get('agent_used', 'unknown')
with st.expander(f"{conv_type.replace('_', ' ').title()} ({agent_used.title()}) - {timestamp}"):
if conv_type == 'health_analysis':
st.write(f"**Risk Level:** {conv.get('risk_level', 'N/A')}/10")
# Use summarized assessment if available, otherwise original
assessment_display = conv.get('summarized_assessment', conv.get('assessment', 'N/A'))
st.markdown(f"""
Assessment:
{assessment_display}
""", unsafe_allow_html=True)
elif conv_type == 'wellness_tips':
# Use summarized tips if available
tips_display = conv.get('summarized_tips', conv.get('tips', 'N/A'))
st.markdown(f"""
""", unsafe_allow_html=True)
elif conv_type in ['chat_interaction', 'granite_chat_interaction']:
st.write(f"**Question:** {conv.get('user_question', 'N/A')}")
# Use summarized response if available
response_display = conv.get('summarized_response', conv.get('ai_response', 'N/A'))
st.markdown(f"""
Response:
{response_display}
""", unsafe_allow_html=True)
# Show conversation metadata if available
if conv.get('conversation_length'):
st.write(f"**Conversation Context:** {conv['conversation_length']} turns in memory")
if conv.get('has_medical_disclaimer'):
st.write("⚠️ **Contains Medical Disclaimer**")
else:
st.info("Your recent interactions with the AI coach will appear here!")
def main():
"""Main application function"""
config, db_manager, groq_agent, granite_agent, granite_chat_agent, reward_system, summarizer = initialize_services()
# Check if user profile exists in session
if "user_profile" not in st.session_state:
st.session_state.user_profile = None
# If no user profile, show profile collection form
if st.session_state.user_profile is None:
st.markdown('🌟 Welcome to Your Dynamic Wellness Platform
', unsafe_allow_html=True)
st.markdown("*Get personalized AI health coaching, dynamic task assignments, and earn rewards for your wellness journey*")
# Show features overview
col1, col2, col3 = st.columns(3)
with col1:
st.markdown("""
### 🤖 AI Health Coach
- Advanced risk calculation
- Groq AI analyzes your profile
- Summarized, bullet-point insights
- Smart risk assessment
""")
with col2:
st.markdown("""
### 🎯 Dynamic Tasks
- Granite AI assigns wellness tasks
- Based on calculated risk levels
- Earn coins for completion
- Personalized difficulty levels
""")
with col3:
st.markdown("""
### 💬 Interactive Chat
- **IBM Granite Chat AI**
- Conversation memory & context
- Get personalized health advice
- Multiple personality modes
""")
st.markdown("---")
# Show enhanced features
st.info("""
🔍 **Enhanced Features with Granite Chat AI**:
- **IBM Granite Conversational AI**: Advanced chat capabilities with conversation memory
- **Context-Aware Responses**: Remembers previous conversations for better continuity
- **Enhanced Risk Assessment**: Multi-factor risk calculation based on sleep, stress, work-life balance, and lifestyle
- **Smart Response Processing**: Clean, readable responses with medical disclaimer detection
- **Contextual Advice**: Personalized recommendations based on your specific profile and conversation history
- **Multiple Personality Modes**: Supportive, professional, casual, or direct conversation styles
- **Advanced Chat Features**: Wellness advice, Q&A, support functions with conversation memory
- **Progress Tracking**: Comprehensive conversation history and achievement summaries
""")
# Collect user profile
user_profile = collect_user_profile()
if user_profile:
# Save to database
if db_manager.save_user_profile(user_profile):
st.session_state.user_profile = user_profile
# Show initial risk calculation
risk_level = calculate_risk_level(user_profile)
st.markdown(get_risk_indicator(risk_level), unsafe_allow_html=True)
st.success("✅ Profile saved successfully! Redirecting to your dashboard...")
st.rerun()
else:
st.error("❌ Error saving profile. Please try again.")
else:
# Display main dashboard with granite chat agent
display_user_dashboard(
st.session_state.user_profile,
db_manager,
groq_agent,
granite_agent,
granite_chat_agent, # Added granite_chat_agent parameter
reward_system,
summarizer
)
# Add a reset button in sidebar
with st.sidebar:
st.header("⚙️ Settings")
user_profile = st.session_state.user_profile
reward_summary = reward_system.get_reward_summary(user_profile['user_id'])
risk_level = calculate_risk_level(user_profile)
st.metric("💰 Total Coins", reward_summary['total_coins'])
st.metric("🏆 Tasks Completed", reward_summary['completed_tasks'])
st.metric("⏳ Pending Tasks", reward_summary['pending_tasks'])
st.metric("⚠️ Risk Level", f"{risk_level}/10")
st.markdown("---")
# Health scores breakdown
st.subheader("📊 Health Scores")
health_scores = calculate_health_scores(user_profile)
for factor, score in health_scores.items():
color = "🟢" if score >= 7 else "🟡" if score >= 5 else "🔴"
st.write(f"{color} {factor}: {score}/10")
st.markdown("---")
if st.button("🔄 New User Profile", type="secondary"):
st.session_state.user_profile = None
st.rerun()
st.markdown("---")
st.markdown("""
### 🎯 Enhanced Features:
1. **IBM Granite Chat AI**: Advanced conversational health coaching with memory
2. **Context-Aware Conversations**: Remembers your chat history for better responses
3. **Smart Risk Analysis**: Multi-factor health assessment with personalized insights
4. **Dynamic Task Assignment**: AI creates tasks based on your specific risk profile
5. **Interactive Chat Features**: Wellness advice, Q&A, and support with conversation continuity
6. **Progress Tracking**: View comprehensive achievements and progress highlights
7. **Reward System**: Earn coins for completing wellness activities
### 🆕 Latest Updates:
- **Granite Chat Integration**: Advanced IBM Granite Chat AI with conversation memory
- **Enhanced Context Awareness**: AI remembers your previous conversations
- **Improved Response Quality**: Better cleaning and processing of AI responses
- **Personality Modes**: Choose between supportive, professional, casual, or direct styles
- **Conversation Statistics**: Track your chat interactions and AI memory usage
- **Medical Disclaimer Detection**: Automatic detection and highlighting of medical advice
""")
# Footer
st.markdown("---")
st.markdown("""
🌟 Enhanced Dynamic Wellness Platform with IBM Granite Chat AI
IBM Granite Chat AI with Memory • Advanced Risk Assessment • Personalized Task Assignment • Smart Health Coaching
⚠️ This tool provides wellness guidance. Consult healthcare professionals for medical advice.
""", unsafe_allow_html=True)
if __name__ == "__main__":
main()