Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -1021,7 +1021,7 @@ def show_admin_dashboard():
|
|
| 1021 |
st.info("No admin activities logged yet")
|
| 1022 |
|
| 1023 |
# Export functionality
|
| 1024 |
-
st.header("
|
| 1025 |
col1, col2 = st.columns(2)
|
| 1026 |
|
| 1027 |
with col1:
|
|
@@ -1068,11 +1068,77 @@ def transcribe_audio_file(uploaded_audio):
|
|
| 1068 |
except Exception as e:
|
| 1069 |
return f"Error: {str(e)}"
|
| 1070 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1071 |
def show_main_app():
|
| 1072 |
"""Main DilBot application"""
|
| 1073 |
username = st.session_state.username
|
| 1074 |
-
|
| 1075 |
-
st.set_page_config(page_title="DilBot - Emotional AI", page_icon="🧠", layout="wide")
|
| 1076 |
|
| 1077 |
# --- DEFINE QUOTE CATEGORIES HERE ---
|
| 1078 |
quote_categories = {
|
|
@@ -1083,7 +1149,7 @@ def show_main_app():
|
|
| 1083 |
}
|
| 1084 |
# --- END QUOTE CATEGORIES DEFINITION ---
|
| 1085 |
|
| 1086 |
-
# --- ENHANCED CUSTOM CSS FOR MAIN APP ---
|
| 1087 |
st.markdown("""
|
| 1088 |
<style>
|
| 1089 |
/* Global Styles & Background */
|
|
@@ -1261,6 +1327,8 @@ def show_main_app():
|
|
| 1261 |
/* FIX: Selectbox selected value text color and ensure it fits properly */
|
| 1262 |
[data-testid="stSelectbox"] input[type="text"] {
|
| 1263 |
color: black !important; /* Force text to be black */
|
|
|
|
|
|
|
| 1264 |
flex-grow: 1; /* Allow input to take up most space */
|
| 1265 |
padding: 12px 5px; /* Adjust vertical padding within the input */
|
| 1266 |
font-size: 1.05em; /* Ensure consistent font size */
|
|
@@ -1296,30 +1364,41 @@ def show_main_app():
|
|
| 1296 |
fill: black !important;
|
| 1297 |
}
|
| 1298 |
|
|
|
|
| 1299 |
/* File Uploader */
|
| 1300 |
-
|
| 1301 |
border-radius: 12px; /* More rounded */
|
| 1302 |
border: 2px dashed #a0a8b4;
|
| 1303 |
-
background-color: #ffffff;
|
| 1304 |
padding: 25px; /* More padding */
|
| 1305 |
transition: border-color 0.3s ease, background-color 0.3s ease;
|
| 1306 |
margin-bottom: 1.5rem;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1307 |
}
|
| 1308 |
[data-testid="stFileUploaderDropzone"]:hover {
|
| 1309 |
border-color: #5d6dbe; /* Highlight on hover */
|
| 1310 |
background-color: #f7f9fb;
|
| 1311 |
}
|
| 1312 |
-
|
| 1313 |
-
|
|
|
|
|
|
|
| 1314 |
[data-testid="stFileUploaderDropzone"] p,
|
| 1315 |
[data-testid="stFileUploaderDropzone"] span,
|
| 1316 |
-
[data-testid="stFileUploaderDropzone"] div {
|
| 1317 |
-
color: black !important;
|
| 1318 |
-
white-space: normal !important;
|
| 1319 |
-
word-break: break-word !important;
|
| 1320 |
-
font-weight: normal !important;
|
| 1321 |
-
opacity: 1 !important;
|
| 1322 |
}
|
|
|
|
| 1323 |
[data-testid="stFileUploaderDropzone"] > div > div > div:nth-child(2) > div:first-child {
|
| 1324 |
color: black !important;
|
| 1325 |
}
|
|
@@ -1327,6 +1406,7 @@ def show_main_app():
|
|
| 1327 |
color: black !important;
|
| 1328 |
}
|
| 1329 |
|
|
|
|
| 1330 |
[data-testid="stFileUploaderFileName"] {
|
| 1331 |
font-size: 0.95em;
|
| 1332 |
color: #495057;
|
|
@@ -1355,18 +1435,44 @@ def show_main_app():
|
|
| 1355 |
/* Specific styles for each type with slightly richer colors */
|
| 1356 |
[data-testid="stAlert"] .streamlit-warning {
|
| 1357 |
background-color: #fef7e0; color: #7a5f00; border-left: 6px solid #ffcc00;
|
| 1358 |
-
|
|
|
|
| 1359 |
[data-testid="stAlert"] .streamlit-success {
|
| 1360 |
-
background-color: #e6ffe6;
|
| 1361 |
-
border-left: 6px solid #4CAF50;
|
| 1362 |
-
color
|
| 1363 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1364 |
[data-testid="stAlert"] .streamlit-error {
|
| 1365 |
-
|
| 1366 |
-
|
| 1367 |
-
|
| 1368 |
-
|
| 1369 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1370 |
|
| 1371 |
|
| 1372 |
/* Chat Message Bubbles */
|
|
@@ -1414,22 +1520,6 @@ def show_main_app():
|
|
| 1414 |
margin-bottom: 2rem;
|
| 1415 |
}
|
| 1416 |
|
| 1417 |
-
/* Quote for you (st.info) */
|
| 1418 |
-
.stInfo {
|
| 1419 |
-
background-color: #e6f7ff; /* Lighter blue for quote box */
|
| 1420 |
-
border-left: 6px solid #64b5f6; /* Accent border, slightly brighter blue */
|
| 1421 |
-
color: black !important; /* FORCED BLACK TEXT COLOR */
|
| 1422 |
-
border-radius: 10px;
|
| 1423 |
-
padding: 18px 25px;
|
| 1424 |
-
margin-top: 2rem;
|
| 1425 |
-
font-style: italic;
|
| 1426 |
-
font-size: 1.05em;
|
| 1427 |
-
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
|
| 1428 |
-
}
|
| 1429 |
-
.stInfo span, .stInfo strong { /* Ensure any span/bold text inside is also black */
|
| 1430 |
-
color: black !important;
|
| 1431 |
-
}
|
| 1432 |
-
|
| 1433 |
|
| 1434 |
/* Audio Player */
|
| 1435 |
.stAudio {
|
|
@@ -1501,7 +1591,6 @@ def show_main_app():
|
|
| 1501 |
|
| 1502 |
</style>
|
| 1503 |
""", unsafe_allow_html=True)
|
| 1504 |
-
# --- END CUSTOM CSS ---
|
| 1505 |
|
| 1506 |
# --- Streamlit UI Components ---
|
| 1507 |
# Header with logout button
|
|
@@ -1521,8 +1610,9 @@ def show_main_app():
|
|
| 1521 |
with st.container(border=True): # Streamlit's built-in container with border
|
| 1522 |
col1, col2 = st.columns(2)
|
| 1523 |
with col1:
|
| 1524 |
-
|
| 1525 |
-
|
|
|
|
| 1526 |
|
| 1527 |
with col2:
|
| 1528 |
st.markdown("<h5>📁 Custom Quotes & Voice Input</h5>", unsafe_allow_html=True)
|
|
@@ -1542,7 +1632,7 @@ def show_main_app():
|
|
| 1542 |
# Handle vectorstore (ORIGINAL LOGIC - NO CHANGE)
|
| 1543 |
current_quotes = []
|
| 1544 |
vectorstore = None
|
| 1545 |
-
|
| 1546 |
if uploaded_quotes:
|
| 1547 |
custom_quotes = uploaded_quotes.read().decode("utf-8").splitlines()
|
| 1548 |
custom_quotes = [quote.strip() for quote in custom_quotes if quote.strip()]
|
|
@@ -1555,7 +1645,7 @@ def show_main_app():
|
|
| 1555 |
if vectorstore is None:
|
| 1556 |
vectorstore = build_user_vectorstore(username, default_quotes)
|
| 1557 |
current_quotes = default_quotes
|
| 1558 |
-
|
| 1559 |
# Input area for user message
|
| 1560 |
st.markdown("<h3>💬 What's on your mind?</h3>", unsafe_allow_html=True)
|
| 1561 |
user_input = st.text_area(
|
|
@@ -1565,11 +1655,12 @@ def show_main_app():
|
|
| 1565 |
placeholder="Type here or use your transcribed voice message...",
|
| 1566 |
label_visibility="collapsed" # Hide default label
|
| 1567 |
)
|
| 1568 |
-
|
|
|
|
| 1569 |
|
| 1570 |
|
| 1571 |
final_input = user_input.strip() or st.session_state.transcribed_text.strip()
|
| 1572 |
-
|
| 1573 |
# Main interaction button
|
| 1574 |
if st.button("🧠 Talk to DilBot", type="primary", use_container_width=True):
|
| 1575 |
if not final_input:
|
|
@@ -1578,11 +1669,11 @@ def show_main_app():
|
|
| 1578 |
with st.spinner("DilBot is thinking and feeling..."):
|
| 1579 |
# Emotion detection (ORIGINAL LOGIC - NO CHANGE)
|
| 1580 |
emotion, score = detect_emotion(final_input)
|
| 1581 |
-
|
| 1582 |
# Get AI response (ORIGINAL LOGIC - NO CHANGE)
|
| 1583 |
prompt_template = PromptTemplate(
|
| 1584 |
input_variables=["context", "user_input", "username"],
|
| 1585 |
-
template="""You are DilBot, an empathetic emotional support AI companion for {username}.
|
| 1586 |
Use the following emotional quote context to respond gently, supportively, and personally.
|
| 1587 |
Context quotes:
|
| 1588 |
{context}
|
|
@@ -1590,19 +1681,19 @@ User's message:
|
|
| 1590 |
{user_input}
|
| 1591 |
Respond as DilBot with warmth, empathy, and understanding. Keep it conversational and supportive."""
|
| 1592 |
)
|
| 1593 |
-
|
| 1594 |
# Get similar quotes (ORIGINAL LOGIC - NO CHANGE)
|
| 1595 |
similar_docs = vectorstore.similarity_search(final_input, k=2)
|
| 1596 |
context = "\n".join([doc.page_content for doc in similar_docs])
|
| 1597 |
-
|
| 1598 |
# Generate response (ORIGINAL LOGIC - NO CHANGE)
|
| 1599 |
groq_llm = ChatGroq(api_key=GROQ_API_KEY, model="llama3-70b-8192")
|
| 1600 |
chain = LLMChain(llm=groq_llm, prompt=prompt_template)
|
| 1601 |
response = chain.run(context=context, user_input=final_input, username=username)
|
| 1602 |
-
|
| 1603 |
# Save to user's journal (ORIGINAL LOGIC - NO CHANGE)
|
| 1604 |
save_user_journal(username, final_input, emotion, score, response)
|
| 1605 |
-
|
| 1606 |
# Display results with new chat bubble styling
|
| 1607 |
st.markdown("<h3 class='chat-title'>🤖 DilBot's Conversation:</h3>", unsafe_allow_html=True)
|
| 1608 |
with st.container(border=True): # Container for the conversation output
|
|
@@ -1628,7 +1719,7 @@ Respond as DilBot with warmth, empathy, and understanding. Keep it conversationa
|
|
| 1628 |
|
| 1629 |
speak(response, username)
|
| 1630 |
st.session_state.transcribed_text = ""
|
| 1631 |
-
|
| 1632 |
# Add a visual separator after each conversation turn (optional)
|
| 1633 |
st.markdown("<div class='chat-separator'></div>", unsafe_allow_html=True)
|
| 1634 |
|
|
@@ -1636,10 +1727,10 @@ Respond as DilBot with warmth, empathy, and understanding. Keep it conversationa
|
|
| 1636 |
# User's personal dashboard
|
| 1637 |
st.markdown("---")
|
| 1638 |
st.header("📊 Your Personal Dashboard")
|
| 1639 |
-
|
| 1640 |
# Load user's journal (ORIGINAL LOGIC - NO CHANGE)
|
| 1641 |
journal_data = load_user_journal(username)
|
| 1642 |
-
|
| 1643 |
if journal_data:
|
| 1644 |
# Statistics
|
| 1645 |
st.subheader("📈 Your Emotional Statistics") # Moved statistics to the top of dashboard for prominence
|
|
@@ -1672,7 +1763,7 @@ Respond as DilBot with warmth, empathy, and understanding. Keep it conversationa
|
|
| 1672 |
})
|
| 1673 |
if df_data:
|
| 1674 |
df_chart = pd.DataFrame(df_data) # Use pandas DataFrame for better Altair integration
|
| 1675 |
-
|
| 1676 |
chart = alt.Chart(df_chart).mark_bar().encode(
|
| 1677 |
x=alt.X('date:N', title='Date', sort=None), # Sort by date ensures correct order
|
| 1678 |
y=alt.Y('count():Q', title='Frequency'),
|
|
@@ -1698,13 +1789,12 @@ Respond as DilBot with warmth, empathy, and understanding. Keep it conversationa
|
|
| 1698 |
st.markdown(f"**DilBot replied:** {entry['response']}")
|
| 1699 |
else:
|
| 1700 |
st.info("No recent conversations yet. Start talking to DilBot!")
|
| 1701 |
-
|
| 1702 |
else:
|
| 1703 |
st.info("🌟 Start your first conversation with DilBot to see your personal dashboard and insights!")
|
| 1704 |
|
| 1705 |
st.markdown("---")
|
| 1706 |
-
st.markdown("<p class='footer-caption'>Built by Members of CSG Hackathon Team | Your data is stored privately and securely</p>", unsafe_allow_html=True)
|
| 1707 |
-
|
| 1708 |
# Main app logic
|
| 1709 |
def main():
|
| 1710 |
if not st.session_state.authenticated:
|
|
|
|
| 1021 |
st.info("No admin activities logged yet")
|
| 1022 |
|
| 1023 |
# Export functionality
|
| 1024 |
+
st.header("Data Export")
|
| 1025 |
col1, col2 = st.columns(2)
|
| 1026 |
|
| 1027 |
with col1:
|
|
|
|
| 1068 |
except Exception as e:
|
| 1069 |
return f"Error: {str(e)}"
|
| 1070 |
|
| 1071 |
+
My apologies for the persistent issue. It's clear that the previous CSS attempts were not sufficient to override Streamlit's internal styling for those specific elements, especially given the screenshots consistently show white text.
|
| 1072 |
+
|
| 1073 |
+
The problem with directly setting color: black !important; on the .streamlit-success and .stInfo classes is that Streamlit's internal components might have even more specific rules or JavaScript that re-applies white color. The key is to target the actual text-holding elements (like p, span, div) within those containers, with higher specificity.
|
| 1074 |
+
|
| 1075 |
+
Let's try a more robust and complete CSS solution within your show_main_app function. I will embed the full CSS block, with very targeted and aggressive !important rules for the problematic text colors, and ensure no other styles interfere.
|
| 1076 |
+
|
| 1077 |
+
Here's the complete show_main_app function with the most robust CSS fixes for text color.
|
| 1078 |
+
|
| 1079 |
+
Python
|
| 1080 |
+
|
| 1081 |
+
import streamlit as st
|
| 1082 |
+
import os, json, datetime, hashlib
|
| 1083 |
+
from langchain_community.vectorstores import FAISS
|
| 1084 |
+
from langchain_community.embeddings import HuggingFaceEmbeddings
|
| 1085 |
+
from langchain_groq import ChatGroq
|
| 1086 |
+
from langchain.chains import LLMChain
|
| 1087 |
+
from langchain.prompts import PromptTemplate
|
| 1088 |
+
from gtts import gTTS
|
| 1089 |
+
from pathlib import Path
|
| 1090 |
+
from dotenv import load_dotenv
|
| 1091 |
+
from sentence_transformers import SentenceTransformer, util
|
| 1092 |
+
import altair as alt
|
| 1093 |
+
import speech_recognition as sr
|
| 1094 |
+
from transformers import pipeline
|
| 1095 |
+
import torch
|
| 1096 |
+
import pickle
|
| 1097 |
+
import re
|
| 1098 |
+
import pandas as pd
|
| 1099 |
+
|
| 1100 |
+
# Load environment variables (ensure these are loaded at the top of your script)
|
| 1101 |
+
load_dotenv()
|
| 1102 |
+
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
|
| 1103 |
+
CRISIS_KEYWORDS = ["suicide", "kill myself", "end it all", "worthless", "can't go on", "hurt myself", "self harm", "want to disappear", "no reason to live"]
|
| 1104 |
+
|
| 1105 |
+
# Initialize session state (ensure these are at the top of your script)
|
| 1106 |
+
if "authenticated" not in st.session_state:
|
| 1107 |
+
st.session_state.authenticated = False
|
| 1108 |
+
if "username" not in st.session_state:
|
| 1109 |
+
st.session_state.username = None
|
| 1110 |
+
if "is_admin" not in st.session_state:
|
| 1111 |
+
st.session_state.is_admin = False
|
| 1112 |
+
if "transcribed_text" not in st.session_state:
|
| 1113 |
+
st.session_state.transcribed_text = ""
|
| 1114 |
+
|
| 1115 |
+
# Admin configuration (ensure these are at the top of your script)
|
| 1116 |
+
ADMIN_USERNAME = os.getenv("ADMIN_USERNAME")
|
| 1117 |
+
ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD")
|
| 1118 |
+
|
| 1119 |
+
# Assume these functions are defined elsewhere in your script:
|
| 1120 |
+
# login, signup, load_user_journal, save_user_journal,
|
| 1121 |
+
# detect_emotion, is_crisis, build_user_vectorstore, load_user_vectorstore,
|
| 1122 |
+
# transcribe_audio_file, speak
|
| 1123 |
+
|
| 1124 |
+
# Example placeholder functions (REMOVE THESE IF YOU HAVE YOUR ACTUAL FUNCTIONS)
|
| 1125 |
+
def login(u, p): return True, "Logged in!", False
|
| 1126 |
+
def signup(u, p, e): return True, "Signed up!"
|
| 1127 |
+
def load_user_journal(u): return []
|
| 1128 |
+
def save_user_journal(u, i, e, c, r): pass
|
| 1129 |
+
def detect_emotion(text): return "neutral", 0.8
|
| 1130 |
+
def is_crisis(text): return False
|
| 1131 |
+
def build_user_vectorstore(u, q): return FAISS.from_texts(q, HuggingFaceEmbeddings())
|
| 1132 |
+
def load_user_vectorstore(u): return None
|
| 1133 |
+
def transcribe_audio_file(file): return "This is a transcribed voice message."
|
| 1134 |
+
def speak(text, username): st.audio(b"", format="audio/ogg") # Placeholder for actual speech
|
| 1135 |
+
|
| 1136 |
+
|
| 1137 |
def show_main_app():
|
| 1138 |
"""Main DilBot application"""
|
| 1139 |
username = st.session_state.username
|
| 1140 |
+
|
| 1141 |
+
st.set_page_config(page_title="DilBot - Emotional AI", page_icon="🧠", layout="wide")
|
| 1142 |
|
| 1143 |
# --- DEFINE QUOTE CATEGORIES HERE ---
|
| 1144 |
quote_categories = {
|
|
|
|
| 1149 |
}
|
| 1150 |
# --- END QUOTE CATEGORIES DEFINITION ---
|
| 1151 |
|
| 1152 |
+
# --- ENHANCED CUSTOM CSS FOR MAIN APP (INCLUDING ALL FIXES) ---
|
| 1153 |
st.markdown("""
|
| 1154 |
<style>
|
| 1155 |
/* Global Styles & Background */
|
|
|
|
| 1327 |
/* FIX: Selectbox selected value text color and ensure it fits properly */
|
| 1328 |
[data-testid="stSelectbox"] input[type="text"] {
|
| 1329 |
color: black !important; /* Force text to be black */
|
| 1330 |
+
-webkit-text-fill-color: black !important; /* For Webkit browsers like Chrome, Safari */
|
| 1331 |
+
opacity: 1 !important; /* Ensure no transparency issues */
|
| 1332 |
flex-grow: 1; /* Allow input to take up most space */
|
| 1333 |
padding: 12px 5px; /* Adjust vertical padding within the input */
|
| 1334 |
font-size: 1.05em; /* Ensure consistent font size */
|
|
|
|
| 1364 |
fill: black !important;
|
| 1365 |
}
|
| 1366 |
|
| 1367 |
+
|
| 1368 |
/* File Uploader */
|
| 1369 |
+
[data-testid="stFileUploaderDropzone"] {
|
| 1370 |
border-radius: 12px; /* More rounded */
|
| 1371 |
border: 2px dashed #a0a8b4;
|
| 1372 |
+
background-color: #ffffff !important; /* Ensure background is white */
|
| 1373 |
padding: 25px; /* More padding */
|
| 1374 |
transition: border-color 0.3s ease, background-color 0.3s ease;
|
| 1375 |
margin-bottom: 1.5rem;
|
| 1376 |
+
display: flex; /* Ensure content is centered */
|
| 1377 |
+
flex-direction: column;
|
| 1378 |
+
justify-content: center;
|
| 1379 |
+
align-items: center;
|
| 1380 |
+
text-align: center;
|
| 1381 |
+
min-height: 120px;
|
| 1382 |
+
overflow: hidden; /* Hide overflowing content */
|
| 1383 |
}
|
| 1384 |
[data-testid="stFileUploaderDropzone"]:hover {
|
| 1385 |
border-color: #5d6dbe; /* Highlight on hover */
|
| 1386 |
background-color: #f7f9fb;
|
| 1387 |
}
|
| 1388 |
+
|
| 1389 |
+
/* FIX: File Uploader text color */
|
| 1390 |
+
/* Target all relevant text elements inside the file uploader dropzone */
|
| 1391 |
+
[data-testid="stFileUploaderDropzone"] *,
|
| 1392 |
[data-testid="stFileUploaderDropzone"] p,
|
| 1393 |
[data-testid="stFileUploaderDropzone"] span,
|
| 1394 |
+
[data-testid="stFileUploaderDropzone"] div {
|
| 1395 |
+
color: black !important; /* Force all text to black */
|
| 1396 |
+
white-space: normal !important; /* Prevent text clipping */
|
| 1397 |
+
word-break: break-word !important; /* Allow long words to break */
|
| 1398 |
+
font-weight: normal !important; /* Reset any bolding that might make text appear thinner */
|
| 1399 |
+
opacity: 1 !important; /* Ensure full visibility */
|
| 1400 |
}
|
| 1401 |
+
/* More specific selectors for file uploader text, often containing the "Drag and drop..." message */
|
| 1402 |
[data-testid="stFileUploaderDropzone"] > div > div > div:nth-child(2) > div:first-child {
|
| 1403 |
color: black !important;
|
| 1404 |
}
|
|
|
|
| 1406 |
color: black !important;
|
| 1407 |
}
|
| 1408 |
|
| 1409 |
+
|
| 1410 |
[data-testid="stFileUploaderFileName"] {
|
| 1411 |
font-size: 0.95em;
|
| 1412 |
color: #495057;
|
|
|
|
| 1435 |
/* Specific styles for each type with slightly richer colors */
|
| 1436 |
[data-testid="stAlert"] .streamlit-warning {
|
| 1437 |
background-color: #fef7e0; color: #7a5f00; border-left: 6px solid #ffcc00;
|
| 1438 |
+
}
|
| 1439 |
+
/* FIX: Emotion Detected (st.success) text color to black */
|
| 1440 |
[data-testid="stAlert"] .streamlit-success {
|
| 1441 |
+
background-color: #e6ffe6;
|
| 1442 |
+
border-left: 6px solid #4CAF50;
|
| 1443 |
+
/* Set color here as fallback, but specific p/span/div below are more robust */
|
| 1444 |
+
color: black !important;
|
| 1445 |
+
}
|
| 1446 |
+
/* More aggressive targeting for text inside st.success alert */
|
| 1447 |
+
[data-testid="stAlert"] .streamlit-success p,
|
| 1448 |
+
[data-testid="stAlert"] .streamlit-success span,
|
| 1449 |
+
[data-testid="stAlert"] .streamlit-success div {
|
| 1450 |
+
color: black !important;
|
| 1451 |
+
}
|
| 1452 |
+
|
| 1453 |
[data-testid="stAlert"] .streamlit-error {
|
| 1454 |
+
background-color: #ffe6e6; color: #8c0a0a; border-left: 6px solid #e74c3c;
|
| 1455 |
+
}
|
| 1456 |
+
/* FIX: Quote for you (st.info) text color to black */
|
| 1457 |
+
.stInfo {
|
| 1458 |
+
background-color: #e6f7ff; /* Lighter blue for quote box */
|
| 1459 |
+
border-left: 6px solid #64b5f6; /* Accent border, slightly brighter blue */
|
| 1460 |
+
/* Set color here as fallback, but specific p/span/strong/div below are more robust */
|
| 1461 |
+
color: black !important;
|
| 1462 |
+
border-radius: 10px;
|
| 1463 |
+
padding: 18px 25px;
|
| 1464 |
+
margin-top: 2rem;
|
| 1465 |
+
font-style: italic;
|
| 1466 |
+
font-size: 1.05em;
|
| 1467 |
+
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
|
| 1468 |
+
}
|
| 1469 |
+
/* More aggressive targeting for text inside st.info alert */
|
| 1470 |
+
.stInfo p,
|
| 1471 |
+
.stInfo span,
|
| 1472 |
+
.stInfo strong,
|
| 1473 |
+
.stInfo div {
|
| 1474 |
+
color: black !important;
|
| 1475 |
+
}
|
| 1476 |
|
| 1477 |
|
| 1478 |
/* Chat Message Bubbles */
|
|
|
|
| 1520 |
margin-bottom: 2rem;
|
| 1521 |
}
|
| 1522 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1523 |
|
| 1524 |
/* Audio Player */
|
| 1525 |
.stAudio {
|
|
|
|
| 1591 |
|
| 1592 |
</style>
|
| 1593 |
""", unsafe_allow_html=True)
|
|
|
|
| 1594 |
|
| 1595 |
# --- Streamlit UI Components ---
|
| 1596 |
# Header with logout button
|
|
|
|
| 1610 |
with st.container(border=True): # Streamlit's built-in container with border
|
| 1611 |
col1, col2 = st.columns(2)
|
| 1612 |
with col1:
|
| 1613 |
+
# Using a custom markdown for the label as selectbox label_visibility is collapsed
|
| 1614 |
+
st.markdown("<label class='stSelectbox>label' style='margin-bottom:0.6rem;padding-left:5px;'>🎯 Choose a quote theme:</label>", unsafe_allow_html=True)
|
| 1615 |
+
selected_category = st.selectbox("Choose a quote theme", list(quote_categories.keys()), label_visibility="collapsed")
|
| 1616 |
|
| 1617 |
with col2:
|
| 1618 |
st.markdown("<h5>📁 Custom Quotes & Voice Input</h5>", unsafe_allow_html=True)
|
|
|
|
| 1632 |
# Handle vectorstore (ORIGINAL LOGIC - NO CHANGE)
|
| 1633 |
current_quotes = []
|
| 1634 |
vectorstore = None
|
| 1635 |
+
|
| 1636 |
if uploaded_quotes:
|
| 1637 |
custom_quotes = uploaded_quotes.read().decode("utf-8").splitlines()
|
| 1638 |
custom_quotes = [quote.strip() for quote in custom_quotes if quote.strip()]
|
|
|
|
| 1645 |
if vectorstore is None:
|
| 1646 |
vectorstore = build_user_vectorstore(username, default_quotes)
|
| 1647 |
current_quotes = default_quotes
|
| 1648 |
+
|
| 1649 |
# Input area for user message
|
| 1650 |
st.markdown("<h3>💬 What's on your mind?</h3>", unsafe_allow_html=True)
|
| 1651 |
user_input = st.text_area(
|
|
|
|
| 1655 |
placeholder="Type here or use your transcribed voice message...",
|
| 1656 |
label_visibility="collapsed" # Hide default label
|
| 1657 |
)
|
| 1658 |
+
# Custom label for text area
|
| 1659 |
+
st.markdown("<label class='stTextArea>label' style='margin-bottom:0.6rem;padding-left:5px;'>Share your thoughts, feelings, or experiences...</label>", unsafe_allow_html=True)
|
| 1660 |
|
| 1661 |
|
| 1662 |
final_input = user_input.strip() or st.session_state.transcribed_text.strip()
|
| 1663 |
+
|
| 1664 |
# Main interaction button
|
| 1665 |
if st.button("🧠 Talk to DilBot", type="primary", use_container_width=True):
|
| 1666 |
if not final_input:
|
|
|
|
| 1669 |
with st.spinner("DilBot is thinking and feeling..."):
|
| 1670 |
# Emotion detection (ORIGINAL LOGIC - NO CHANGE)
|
| 1671 |
emotion, score = detect_emotion(final_input)
|
| 1672 |
+
|
| 1673 |
# Get AI response (ORIGINAL LOGIC - NO CHANGE)
|
| 1674 |
prompt_template = PromptTemplate(
|
| 1675 |
input_variables=["context", "user_input", "username"],
|
| 1676 |
+
template="""You are DilBot, an empathetic emotional support AI companion for {username}.
|
| 1677 |
Use the following emotional quote context to respond gently, supportively, and personally.
|
| 1678 |
Context quotes:
|
| 1679 |
{context}
|
|
|
|
| 1681 |
{user_input}
|
| 1682 |
Respond as DilBot with warmth, empathy, and understanding. Keep it conversational and supportive."""
|
| 1683 |
)
|
| 1684 |
+
|
| 1685 |
# Get similar quotes (ORIGINAL LOGIC - NO CHANGE)
|
| 1686 |
similar_docs = vectorstore.similarity_search(final_input, k=2)
|
| 1687 |
context = "\n".join([doc.page_content for doc in similar_docs])
|
| 1688 |
+
|
| 1689 |
# Generate response (ORIGINAL LOGIC - NO CHANGE)
|
| 1690 |
groq_llm = ChatGroq(api_key=GROQ_API_KEY, model="llama3-70b-8192")
|
| 1691 |
chain = LLMChain(llm=groq_llm, prompt=prompt_template)
|
| 1692 |
response = chain.run(context=context, user_input=final_input, username=username)
|
| 1693 |
+
|
| 1694 |
# Save to user's journal (ORIGINAL LOGIC - NO CHANGE)
|
| 1695 |
save_user_journal(username, final_input, emotion, score, response)
|
| 1696 |
+
|
| 1697 |
# Display results with new chat bubble styling
|
| 1698 |
st.markdown("<h3 class='chat-title'>🤖 DilBot's Conversation:</h3>", unsafe_allow_html=True)
|
| 1699 |
with st.container(border=True): # Container for the conversation output
|
|
|
|
| 1719 |
|
| 1720 |
speak(response, username)
|
| 1721 |
st.session_state.transcribed_text = ""
|
| 1722 |
+
|
| 1723 |
# Add a visual separator after each conversation turn (optional)
|
| 1724 |
st.markdown("<div class='chat-separator'></div>", unsafe_allow_html=True)
|
| 1725 |
|
|
|
|
| 1727 |
# User's personal dashboard
|
| 1728 |
st.markdown("---")
|
| 1729 |
st.header("📊 Your Personal Dashboard")
|
| 1730 |
+
|
| 1731 |
# Load user's journal (ORIGINAL LOGIC - NO CHANGE)
|
| 1732 |
journal_data = load_user_journal(username)
|
| 1733 |
+
|
| 1734 |
if journal_data:
|
| 1735 |
# Statistics
|
| 1736 |
st.subheader("📈 Your Emotional Statistics") # Moved statistics to the top of dashboard for prominence
|
|
|
|
| 1763 |
})
|
| 1764 |
if df_data:
|
| 1765 |
df_chart = pd.DataFrame(df_data) # Use pandas DataFrame for better Altair integration
|
| 1766 |
+
|
| 1767 |
chart = alt.Chart(df_chart).mark_bar().encode(
|
| 1768 |
x=alt.X('date:N', title='Date', sort=None), # Sort by date ensures correct order
|
| 1769 |
y=alt.Y('count():Q', title='Frequency'),
|
|
|
|
| 1789 |
st.markdown(f"**DilBot replied:** {entry['response']}")
|
| 1790 |
else:
|
| 1791 |
st.info("No recent conversations yet. Start talking to DilBot!")
|
| 1792 |
+
|
| 1793 |
else:
|
| 1794 |
st.info("🌟 Start your first conversation with DilBot to see your personal dashboard and insights!")
|
| 1795 |
|
| 1796 |
st.markdown("---")
|
| 1797 |
+
st.markdown("<p class='footer-caption'>Built by Members of CSG Hackathon Team | Your data is stored privately and securely</p>", unsafe_allow_html=True)
|
|
|
|
| 1798 |
# Main app logic
|
| 1799 |
def main():
|
| 1800 |
if not st.session_state.authenticated:
|