File size: 13,267 Bytes
b437175
cb0cd2a
87b5e15
 
 
 
 
004d749
b437175
87b5e15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b437175
87b5e15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b437175
cb0cd2a
 
 
87b5e15
 
cb0cd2a
 
87b5e15
cb0cd2a
 
 
 
 
004d749
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cb0cd2a
 
 
 
 
87b5e15
cb0cd2a
 
e61f017
87b5e15
b437175
004d749
 
 
87b5e15
 
 
004d749
b437175
87b5e15
cb0cd2a
 
 
 
 
 
 
 
 
 
 
 
 
87b5e15
004d749
 
87b5e15
 
cb0cd2a
 
87b5e15
 
 
 
 
 
 
 
e61f017
87b5e15
 
 
 
 
 
 
 
 
e61f017
87b5e15
 
 
 
 
 
 
e61f017
87b5e15
e61f017
87b5e15
 
 
 
 
 
b437175
87b5e15
 
 
 
 
 
 
 
cb0cd2a
87b5e15
 
 
 
 
 
 
 
 
 
 
 
e61f017
87b5e15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e61f017
87b5e15
 
e61f017
87b5e15
 
 
 
 
 
e61f017
87b5e15
e61f017
 
87b5e15
 
 
e61f017
87b5e15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b437175
87b5e15
 
 
 
 
004d749
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
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
@st.cache_resource
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.
""")