import gradio as gr from transformers import pipeline import random from datetime import datetime import logging # Initialize models with smaller, faster alternatives sentiment_analyzer = pipeline( "sentiment-analysis", model="distilbert-base-uncased-finetuned-sst-2-english", device=-1 # Force CPU usage ) # Configure logging logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") # Pre-defined prompts and affirmations for different sentiments PROMPT_TEMPLATES = { "POSITIVE": [ "- What made this positive experience particularly meaningful to you?", "- How can you carry this positive energy forward?", "- Who would you like to share this joy with and why?" ], "NEGATIVE": [ "- What can you learn from this challenging situation?", "- What small step could you take to feel better?", "- Who or what helps you feel supported during difficult times?" ], "NEUTRAL": [ "- What does this experience teach you about balance?", "- How does this experience fit into your overall life story?", "- What is something small you are grateful for today?" ] } AFFIRMATIONS = { "POSITIVE": [ "I deserve this joy and all good things coming my way.", "My positive energy creates positive experiences.", "I choose to embrace and celebrate this moment." ], "NEGATIVE": [ "This too shall pass, and I am growing stronger.", "I trust in my ability to handle challenging situations.", "Every experience is teaching me something valuable." ], "NEUTRAL": [ "I appreciate the calmness of the present moment.", "I am in harmony with life’s natural flow.", "Balance is a gift I cultivate every day." ] } class JournalCompanion: def __init__(self): self.entries = [] def get_prompts(self, sentiment): prompts = PROMPT_TEMPLATES.get(sentiment, PROMPT_TEMPLATES["NEUTRAL"]) return "\n\nReflective Prompts:\n" + "\n".join(prompts) def get_affirmation(self, sentiment): affirmations = AFFIRMATIONS.get(sentiment, AFFIRMATIONS["NEUTRAL"]) return random.choice(affirmations) def analyze_entry(self, entry_text): if not entry_text.strip(): return ("Please write something in your journal entry.", "", "", "") try: # Perform sentiment analysis sentiment_result = sentiment_analyzer(entry_text)[0] sentiment = sentiment_result["label"].upper() sentiment_score = sentiment_result["score"] except Exception as e: logging.error("Error during sentiment analysis: %s", e) return ( "An error occurred during analysis. Please try again.", "Error", "Could not analyze sentiment due to an error.", "Could not generate affirmation due to an error." ) entry_data = { "text": entry_text, "timestamp": datetime.now().isoformat(), "sentiment": sentiment, "sentiment_score": sentiment_score } self.entries.append(entry_data) # Get pre-defined responses prompts = self.get_prompts(sentiment) affirmation = self.get_affirmation(sentiment) sentiment_percentage = f"{sentiment_score * 100:.1f}%" message = f"Entry analyzed! Sentiment: {sentiment} ({sentiment_percentage} confidence)" return message, sentiment, prompts, affirmation def get_monthly_insights(self): if not self.entries: return "No entries yet to analyze." current_month = datetime.now().month monthly_entries = [entry for entry in self.entries if datetime.fromisoformat(entry["timestamp"]).month == current_month] total_entries = len(monthly_entries) if total_entries == 0: return "No entries this month to analyze." positive_entries = sum(1 for entry in monthly_entries if entry["sentiment"] == "POSITIVE") neutral_entries = sum(1 for entry in monthly_entries if entry["sentiment"] == "NEUTRAL") negative_entries = total_entries - positive_entries - neutral_entries try: percentage_positive = (positive_entries / total_entries * 100) percentage_neutral = (neutral_entries / total_entries * 100) percentage_negative = (negative_entries / total_entries * 100) insights = f"""Monthly Insights: Total Entries: {total_entries} Positive Entries: {positive_entries} ({percentage_positive:.1f}%) Neutral Entries: {neutral_entries} ({percentage_neutral:.1f}%) Negative Entries: {negative_entries} ({percentage_negative:.1f}%) """ return insights except ZeroDivisionError: return "No entries available for analysis." def create_journal_interface(): journal = JournalCompanion() # Custom CSS for better styling custom_css = """ @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap'); * { font-family: 'Roboto', sans-serif; } .container { max-width: 1200px; margin: 0 auto; padding: 20px; } .header { text-align: center; margin-bottom: 2rem; background: linear-gradient(135deg, #2196f3 0%, #26c6da 100%); padding: 2rem; border-radius: 15px; color: #ffffff; } .input-container { background: white; border-radius: 15px; padding: 20px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); margin-bottom: 20px; } .output-container { background: #f8f9fa; border-radius: 15px; padding: 20px; margin-top: 20px; } .custom-button { background: linear-gradient(135deg, #009688 0%, #0072ff 100%); border: none; padding: 10px 20px; border-radius: 8px; color: white; font-weight: bold; cursor: pointer; transition: transform 0.2s, box-shadow 0.2s; } .custom-button:hover { transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0, 114, 255, 0.4); } .card { background: white; border-radius: 10px; padding: 15px; margin: 10px 0; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); transition: transform 0.2s; } .card:hover { transform: translateY(-2px); } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .result-animation { animation: fadeIn 0.5s ease-out; } @media (max-width: 768px) { .container { padding: 10px; } .header { padding: 1rem; } } """ with gr.Blocks(css=custom_css, title="AI Journal Companion") as interface: with gr.Column(elem_classes="container"): with gr.Column(elem_classes="header"): gr.Markdown("# 📔 AI Journal Companion") gr.Markdown("Transform your thoughts into insights with AI-powered journaling", elem_classes="subtitle") with gr.Row(): with gr.Column(scale=1, elem_classes="input-container"): entry_input = gr.Textbox( label="Write Your Thoughts", placeholder="Share what's on your mind...", lines=8, elem_classes="journal-input" ) submit_btn = gr.Button("✨ Analyze Entry", variant="primary", elem_classes="custom-button") with gr.Column(scale=1, elem_classes="output-container"): with gr.Column(elem_classes="card result-animation"): result_message = gr.Markdown(label="Analysis") sentiment_output = gr.Textbox(label="Emotional Tone", elem_classes="sentiment-output") with gr.Column(elem_classes="card result-animation"): prompt_output = gr.Markdown(label="Reflection Prompts", elem_classes="prompts-output") with gr.Column(elem_classes="card result-animation"): affirmation_output = gr.Textbox(label="Your Daily Affirmation", elem_classes="affirmation-output") with gr.Row(elem_classes="insights-section"): with gr.Column(scale=1): insights_btn = gr.Button("📊 View Monthly Insights", elem_classes="custom-button") insights_output = gr.Markdown(elem_classes="card insights-card") submit_btn.click( fn=journal.analyze_entry, inputs=[entry_input], outputs=[result_message, sentiment_output, prompt_output, affirmation_output] ) insights_btn.click( fn=journal.get_monthly_insights, inputs=[], outputs=[insights_output] ) return interface if __name__ == "__main__": interface = create_journal_interface() interface.launch()