Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| from huggingface_hub import InferenceClient | |
| from datetime import datetime | |
| import pandas as pd | |
| import os | |
| import uuid | |
| import json | |
| import re | |
| # Page configuration | |
| st.set_page_config( | |
| page_title="Mental Wellness Diary Analyzer", | |
| page_icon="π§ ", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| # Custom CSS for better appearance | |
| st.markdown(""" | |
| <style> | |
| .main .block-container { | |
| padding-top: 2rem; | |
| padding-bottom: 2rem; | |
| } | |
| .stTextArea textarea { | |
| font-size: 16px; | |
| } | |
| .journal-history { | |
| border-left: 2px solid #f0f2f6; | |
| padding-left: 20px; | |
| } | |
| .css-1v3fvcr { | |
| background-color: #fcfcff; | |
| } | |
| .stButton button { | |
| background-color: #4e89ae; | |
| color: white; | |
| border-radius: 5px; | |
| padding: 0.5rem 1rem; | |
| font-weight: bold; | |
| } | |
| .stButton button:hover { | |
| background-color: #3d7092; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # App title and description | |
| st.title("π§ Mental Wellness Diary Analyzer") | |
| st.markdown(""" | |
| Track your mental wellness journey with AI-powered insights. Write your daily thoughts, | |
| and receive personalized analysis to help you understand your emotional patterns. | |
| """) | |
| # Initialize session state for journal entries | |
| if 'journal_entries' not in st.session_state: | |
| # Try to load from file if it exists | |
| if os.path.exists('journal_entries.json'): | |
| try: | |
| with open('journal_entries.json', 'r') as f: | |
| st.session_state.journal_entries = json.load(f) | |
| except: | |
| st.session_state.journal_entries = [] | |
| else: | |
| st.session_state.journal_entries = [] | |
| # Hugging Face API setup | |
| def get_hf_api_token(): | |
| # First check if token exists in secrets | |
| if hasattr(st, 'secrets') and 'huggingface' in st.secrets: | |
| return st.secrets["huggingface"]["api_token"] | |
| # For local development, check environment variable | |
| return os.environ.get("HF_API_TOKEN") | |
| # Initialize the InferenceClient | |
| def get_inference_client(): | |
| api_token = get_hf_api_token() | |
| if not api_token: | |
| st.error("No Hugging Face API token found. Please configure it in your Spaces secrets.") | |
| return None | |
| return InferenceClient( | |
| provider="nebius", | |
| api_key=api_token, | |
| ) | |
| # Clean the output to remove thinking process | |
| def clean_output(text): | |
| # Extract only the parts after the headings | |
| cleaned_text = "" | |
| # Extract Emotional tone section | |
| if "Emotional tone:" in text: | |
| match = re.search(r'Emotional tone:(.*?)(?:Recurring themes:|$)', text, re.DOTALL) | |
| if match: | |
| emotional_tone = match.group(1).strip() | |
| cleaned_text += f"π **Emotional tone:** {emotional_tone}\n\n" | |
| # Extract Recurring themes section | |
| if "Recurring themes:" in text: | |
| match = re.search(r'Recurring themes:(.*?)(?:Advice:|$)', text, re.DOTALL) | |
| if match: | |
| themes = match.group(1).strip() | |
| cleaned_text += f"π **Recurring themes:** {themes}\n\n" | |
| # Extract Advice section | |
| if "Advice:" in text: | |
| match = re.search(r'Advice:(.*?)$', text, re.DOTALL) | |
| if match: | |
| advice = match.group(1).strip() | |
| cleaned_text += f"π‘ **Advice:** {advice}" | |
| return cleaned_text if cleaned_text else text | |
| # Function to analyze journal entries | |
| def analyze_journal(entry, model_name="deepseek-ai/DeepSeek-R1"): | |
| client = get_inference_client() | |
| if not client: | |
| return "Error: Could not initialize the Inference Client." | |
| try: | |
| prompt = f"""You are a compassionate mental wellness assistant. Analyze the following journal entry with empathy and provide helpful insights. | |
| Journal entry: "{entry}" | |
| Please provide the following analysis directly, without explaining your thinking process: | |
| 1. Emotional tone: Identify the primary emotions expressed in the entry | |
| 2. Recurring themes: Note any patterns or important topics mentioned | |
| 3. Advice: Offer kind, supportive guidance tailored to what was shared | |
| Format your response with only these three sections, using the exact headings: "Emotional tone:", "Recurring themes:", and "Advice:". Do not include any additional explanations or thinking. | |
| """ | |
| completion = client.chat.completions.create( | |
| model=model_name, | |
| messages=[ | |
| { | |
| "role": "user", | |
| "content": prompt | |
| } | |
| ], | |
| max_tokens=512, | |
| temperature=0.7, | |
| ) | |
| output = completion.choices[0].message.content | |
| # Clean the output to remove any thinking process | |
| return clean_output(output) | |
| except Exception as e: | |
| st.error(f"API Error: {str(e)}") | |
| return f"Error analyzing journal entry: {str(e)}" | |
| # Function to save an entry | |
| def save_entry(entry, analysis): | |
| entry_id = str(uuid.uuid4()) | |
| timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
| # Extract emotional tone for tagging (simplified) | |
| emotional_tone = "neutral" | |
| if "Emotional tone:" in analysis: | |
| tone_text = analysis.split("Emotional tone:")[1].split("\n\n")[0].strip() | |
| if "anxious" in tone_text.lower() or "stress" in tone_text.lower(): | |
| emotional_tone = "anxious" | |
| elif "happy" in tone_text.lower() or "joy" in tone_text.lower(): | |
| emotional_tone = "happy" | |
| elif "sad" in tone_text.lower() or "depress" in tone_text.lower(): | |
| emotional_tone = "sad" | |
| elif "angry" in tone_text.lower() or "frustrat" in tone_text.lower(): | |
| emotional_tone = "angry" | |
| new_entry = { | |
| "id": entry_id, | |
| "date": timestamp, | |
| "entry": entry, | |
| "analysis": analysis, | |
| "emotion": emotional_tone | |
| } | |
| st.session_state.journal_entries.append(new_entry) | |
| # Save to file (for spaces persistence) | |
| try: | |
| with open('journal_entries.json', 'w') as f: | |
| json.dump(st.session_state.journal_entries, f) | |
| except Exception as e: | |
| st.warning(f"Could not save entries to file: {str(e)}") | |
| # Sidebar for navigation and settings | |
| with st.sidebar: | |
| st.header("Navigation") | |
| page = st.radio("", ["Write New Entry", "View Journal History"]) | |
| st.header("Settings") | |
| model_choice = st.selectbox( | |
| "Language Model", | |
| ["deepseek-ai/DeepSeek-R1", "meta-llama/Llama-3-8b-chat", "microsoft/phi-3-mini-4k-instruct"], | |
| index=0, | |
| help="Select which AI model to use for analysis" | |
| ) | |
| st.markdown("---") | |
| st.markdown("### About") | |
| st.info(""" | |
| This Mental Wellness Diary Analyzer helps you track your emotional wellbeing. | |
| All entries are stored locally in your browser session. | |
| **Disclaimer**: This app is not a substitute for professional mental health support. | |
| """) | |
| # Main content based on selected page | |
| if page == "Write New Entry": | |
| st.header("π New Journal Entry") | |
| # Current date display | |
| st.markdown(f"**Today**: {datetime.now().strftime('%A, %B %d, %Y')}") | |
| # Journal input | |
| journal_entry = st.text_area( | |
| "How are you feeling today?", | |
| height=200, | |
| placeholder="Write about your day, feelings, thoughts, or anything on your mind..." | |
| ) | |
| # Mood tracker (optional quick selection) | |
| cols = st.columns(5) | |
| with cols[0]: | |
| mood_happy = st.button("π Happy") | |
| with cols[1]: | |
| mood_calm = st.button("π Calm") | |
| with cols[2]: | |
| mood_anxious = st.button("π° Anxious") | |
| with cols[3]: | |
| mood_sad = st.button("π’ Sad") | |
| with cols[4]: | |
| mood_angry = st.button("π Angry") | |
| # Handle mood button clicks | |
| mood_prefix = "" | |
| if mood_happy: | |
| mood_prefix = "I'm feeling happy today. " | |
| elif mood_calm: | |
| mood_prefix = "I'm feeling calm and relaxed today. " | |
| elif mood_anxious: | |
| mood_prefix = "I'm feeling anxious today. " | |
| elif mood_sad: | |
| mood_prefix = "I'm feeling sad today. " | |
| elif mood_angry: | |
| mood_prefix = "I'm feeling angry and frustrated today. " | |
| if mood_prefix and not journal_entry.startswith(mood_prefix): | |
| journal_entry = mood_prefix + journal_entry | |
| # Analyze button | |
| col1, col2, col3 = st.columns([1, 1, 1]) | |
| with col2: | |
| analyze_button = st.button("π§ Analyze My Entry", use_container_width=True) | |
| # Sample entries | |
| with st.expander("Need inspiration? Try a sample entry"): | |
| sample_1 = st.button("Sample: Stressed at work") | |
| sample_2 = st.button("Sample: Good day") | |
| sample_3 = st.button("Sample: Relationship issues") | |
| if sample_1: | |
| journal_entry = "I feel really stressed and anxious about my work. I haven't been sleeping well, and I'm worried about meeting deadlines. My boss keeps adding more tasks, and I don't know how to say no." | |
| elif sample_2: | |
| journal_entry = "Today was a great day! I finished a project I've been working on for weeks, and my team was really impressed. I feel proud of myself and motivated to keep up the good work." | |
| elif sample_3: | |
| journal_entry = "I had an argument with my partner today. We've been fighting a lot lately about small things. I'm not sure if it's just stress or if there's a bigger issue we need to address." | |
| # Analysis section | |
| if analyze_button and journal_entry.strip(): | |
| with st.spinner("Analyzing your thoughts..."): | |
| analysis = analyze_journal(journal_entry, model_choice) | |
| st.markdown("### π Your Wellness Insights") | |
| st.markdown(analysis) | |
| # Save option | |
| if st.button("π Save this entry to your journal"): | |
| save_entry(journal_entry, analysis) | |
| st.success("Entry saved successfully!") | |
| # Supportive message | |
| st.markdown("---") | |
| st.markdown("πͺ **Remember**: Writing about your feelings is already a positive step for your mental wellness!") | |
| elif analyze_button: | |
| st.warning("Please write in your journal entry first.") | |
| else: # View Journal History page | |
| st.header("π Your Journal History") | |
| if not st.session_state.journal_entries: | |
| st.info("You haven't saved any journal entries yet. Head to 'Write New Entry' to get started!") | |
| else: | |
| # Filter options | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| filter_option = st.selectbox( | |
| "Filter by emotion:", | |
| ["All", "happy", "anxious", "sad", "angry", "neutral"] | |
| ) | |
| with col2: | |
| sort_option = st.selectbox( | |
| "Sort by:", | |
| ["Newest first", "Oldest first"] | |
| ) | |
| # Filter and sort entries | |
| filtered_entries = st.session_state.journal_entries | |
| if filter_option != "All": | |
| filtered_entries = [e for e in filtered_entries if e.get("emotion") == filter_option] | |
| if sort_option == "Newest first": | |
| filtered_entries = sorted(filtered_entries, key=lambda x: x.get("date", ""), reverse=True) | |
| else: | |
| filtered_entries = sorted(filtered_entries, key=lambda x: x.get("date", "")) | |
| # Display entries | |
| for i, entry in enumerate(filtered_entries): | |
| with st.expander(f"π {entry.get('date', 'Unknown date')}"): | |
| st.markdown("#### Journal Entry") | |
| st.write(entry.get("entry", "")) | |
| st.markdown("#### Analysis") | |
| st.markdown(entry.get("analysis", "No analysis available")) | |
| # Delete option | |
| if st.button(f"ποΈ Delete this entry", key=f"delete_{i}"): | |
| st.session_state.journal_entries.remove(entry) | |
| with open('journal_entries.json', 'w') as f: | |
| json.dump(st.session_state.journal_entries, f) | |
| st.experimental_rerun() | |
| # Add insights section if there are enough entries | |
| if len(st.session_state.journal_entries) >= 3: | |
| st.markdown("---") | |
| st.header("π Emotional Trends") | |
| # Create a dataframe for visualization | |
| entries_df = pd.DataFrame(st.session_state.journal_entries) | |
| entries_df['date'] = pd.to_datetime(entries_df['date']) | |
| # Count emotions | |
| emotion_counts = entries_df['emotion'].value_counts() | |
| st.bar_chart(emotion_counts) | |
| # Most common themes - this would require more sophisticated analysis | |
| st.markdown("### Common Themes") | |
| st.info("This feature will analyze common themes across your entries in a future update.") | |
| # Footer | |
| st.markdown("---") | |
| st.caption(""" | |
| **Disclaimer**: This app is for educational purposes only and is not a substitute for professional mental health advice, diagnosis, or treatment. | |
| Always seek the advice of your physician or other qualified health provider with any questions regarding a medical condition. | |
| """) |