Spaces:
Sleeping
Sleeping
import streamlit as st | |
import random | |
import time | |
from streamlit.components.v1 import html | |
# Set page config with light purple theme | |
st.set_page_config( | |
page_title="Emotion Mirror Chatbot", | |
page_icon="π", | |
layout="centered", | |
initial_sidebar_state="collapsed" | |
) | |
# Custom CSS for enhanced light purple theme | |
st.markdown(""" | |
<style> | |
:root { | |
--primary: #b19cd9; | |
--primary-dark: #8a7faa; | |
--background: linear-gradient(135deg, #f5f0ff, #e6d7ff); | |
--secondary-background: #e6e0fa; | |
--text: #4a4a4a; | |
--font: "Arial", sans-serif; | |
} | |
body { | |
background-image: var(--background); | |
background-attachment: fixed; | |
color: var(--text); | |
font-family: var(--font); | |
} | |
.stTextInput>div>div>input { | |
background-color: var(--secondary-background) !important; | |
color: var(--text) !important; | |
border: 2px solid var(--primary) !important; | |
border-radius: 12px; | |
} | |
.stButton>button { | |
background-color: var(--primary) !important; | |
color: white !important; | |
border: none; | |
border-radius: 12px; | |
padding: 8px 16px; | |
transition: all 0.3s ease; | |
} | |
.stButton>button:hover { | |
background-color: var(--primary-dark) !important; | |
transform: scale(1.05); | |
} | |
.stMarkdown { | |
font-family: monospace !important; | |
font-size: 16px !important; | |
} | |
.chat-message { | |
padding: 12px 16px; | |
border-radius: 16px; | |
margin: 10px 0; | |
max-width: 80%; | |
box-shadow: 0 2px 6px rgba(0,0,0,0.1); | |
} | |
.user-message { | |
background-color: var(--secondary-background); | |
margin-left: auto; | |
text-align: left; | |
border-bottom-right-radius: 4px; | |
} | |
.bot-message { | |
background-color: var(--primary); | |
color: white; | |
margin-right: auto; | |
border-bottom-left-radius: 4px; | |
} | |
.face-container { | |
text-align: center; | |
padding: 20px; | |
background: rgba(255, 255, 255, 0.7); | |
backdrop-filter: blur(5px); | |
border-radius: 20px; | |
box-shadow: 0 8px 20px rgba(0,0,0,0.1); | |
margin: 20px auto; | |
max-width: 300px; | |
border: 2px solid var(--primary); | |
} | |
.header { | |
text-align: center; | |
margin-bottom: 20px; | |
} | |
.title { | |
color: var(--primary); | |
font-size: 2.5rem; | |
margin-bottom: 10px; | |
text-shadow: 1px 1px 3px rgba(0,0,0,0.1); | |
} | |
.subtitle { | |
color: var(--text); | |
font-size: 1.1rem; | |
margin-bottom: 30px; | |
} | |
.footer { | |
text-align: center; | |
margin-top: 30px; | |
color: var(--primary); | |
font-size: 0.9rem; | |
} | |
</style> | |
""", unsafe_allow_html=True) | |
# Emotion databases | |
POSITIVE_WORDS = {"happy", "awesome", "great", "joy", "excited", "good", "wonderful", "fantastic", "amazing", "yay", "ecstatic"} | |
NEGATIVE_WORDS = {"sad", "depressed", "angry", "cry", "lonely", "bad", "terrible", "awful", "miserable", "upset", "grief"} | |
LOVE_WORDS = {"love", "heart", "adore", "crush", "romance", "affection", "passion"} | |
HELP_RESPONSES = [ | |
"Would you like to talk about it? π¬", | |
"I'm here to listen whenever you need π", | |
"Want some uplifting quotes? π", | |
"Would a virtual hug help? π€", | |
"Let's focus on something positive π", | |
"Remember: this too shall pass π€οΈ" | |
] | |
# ASCII Art Library | |
FACES = { | |
"happy": r""" | |
ββββββββββββββ | |
π AWESOME DAY! | |
ββββββββββββββ | |
""", | |
"sad": r""" | |
ββββββββββββββ | |
π’ TOUGH TIMES? | |
ββββββββββββββ | |
""", | |
"neutral": r""" | |
ββββββββββββββ | |
π HELLO THERE | |
ββββββββββββββ | |
""", | |
"love": r""" | |
ββββββββββββββ | |
π LOVELY FEELING! | |
ββββββββββββββ | |
""", | |
"angry": r""" | |
ββββββββββββββ | |
π TAKE A DEEP BREATH | |
ββββββββββββββ | |
""" | |
} | |
# Confetti effect using JavaScript | |
def confetti_effect(): | |
confetti_js = """ | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/confetti.browser.min.js"></script> | |
<script> | |
const count = 200; | |
const defaults = { | |
origin: { y: 0.7 } | |
}; | |
function fire(particleRatio, opts) { | |
confetti(Object.assign({}, defaults, opts, { | |
particleCount: Math.floor(count * particleRatio), | |
colors: ['#b19cd9', '#e6d7ff', '#8a7faa', '#ffffff'] | |
})); | |
} | |
fire(0.25, { spread: 26, startVelocity: 55 }); | |
fire(0.2, { spread: 60 }); | |
fire(0.35, { spread: 100, decay: 0.91, scalar: 0.8 }); | |
fire(0.1, { spread: 120, startVelocity: 25, decay: 0.92, scalar: 1.2 }); | |
fire(0.1, { spread: 120, startVelocity: 45 }); | |
</script> | |
""" | |
html(confetti_js) | |
# Emotion detection function | |
def detect_emotion(text): | |
text = text.lower() | |
if any(word in text for word in POSITIVE_WORDS): | |
return "happy" | |
elif any(word in text for word in NEGATIVE_WORDS): | |
return "sad" | |
elif any(word in text for word in LOVE_WORDS): | |
return "love" | |
elif "angry" in text or "mad" in text or "furious" in text: | |
return "angry" | |
return "neutral" | |
# Initialize chat history | |
if "messages" not in st.session_state: | |
st.session_state.messages = [] | |
st.session_state.current_emotion = "neutral" | |
# Header with title and description | |
st.markdown('<div class="header"><div class="title">β¨ Emotion Mirror Chatbot</div><div class="subtitle">I\'m a reactive AI agent that mirrors your emotions! Try words like <i>happy, sad, love,</i> or <i>awesome</i></div></div>', unsafe_allow_html=True) | |
# Display current face | |
with st.container(): | |
st.markdown(f"<div class='face-container'>\n{FACES[st.session_state.current_emotion]}\n</div>", | |
unsafe_allow_html=True) | |
# Display chat messages | |
for message in st.session_state.messages: | |
with st.chat_message(message["role"]): | |
st.markdown(f"<div class='chat-message {message['role']}-message'>{message['content']}</div>", | |
unsafe_allow_html=True) | |
# User input | |
if prompt := st.chat_input("How are you feeling today?"): | |
# Add user message to chat history | |
st.session_state.messages.append({"role": "user", "content": prompt}) | |
# Detect emotion | |
emotion = detect_emotion(prompt) | |
st.session_state.current_emotion = emotion | |
# Generate bot response | |
if emotion == "happy": | |
response = FACES["happy"] + "\n\nπ That's wonderful to hear! Keep spreading positivity!" | |
confetti_effect() | |
elif emotion == "sad": | |
response = FACES["sad"] + "\n\n" + random.choice(HELP_RESPONSES) | |
elif emotion == "love": | |
response = FACES["love"] + "\n\nπ Love is the most beautiful feeling! Treasure it." | |
elif emotion == "angry": | |
response = FACES["angry"] + "\n\nβοΈ Take a deep breath. Count to ten. You've got this." | |
else: | |
response = FACES["neutral"] + "\n\nTell me more about your feelings..." | |
# Add bot response to chat history | |
st.session_state.messages.append({"role": "bot", "content": response}) | |
# Rerun to update the display | |
st.rerun() | |
# Add reset button | |
if st.button("Reset Conversation"): | |
st.session_state.messages = [] | |
st.session_state.current_emotion = "neutral" | |
st.rerun() | |
# Footer | |
st.markdown('<div class="footer">Made with β€οΈ | Reactive AI Agent | Streamlit</div>', unsafe_allow_html=True) |