import streamlit as st import nltk import spacy import matplotlib.pyplot as plt from transformers import pipeline import random import subprocess # Ensure spaCy model is installed try: nlp = spacy.load("en_core_web_sm") except OSError: subprocess.run(["python", "-m", "spacy", "download", "en_core_web_sm"]) nlp = spacy.load("en_core_web_sm") # Ensure NLTK resources are available nltk.download("vader_lexicon") from nltk.sentiment import SentimentIntensityAnalyzer sia = SentimentIntensityAnalyzer() # Load English emotion detection pipeline emotion_pipeline = pipeline("text-classification", model="j-hartmann/emotion-english-distilroberta-base", return_all_scores=True) # Load multilingual sentiment model (returns star ratings 1-5 for non-English texts) multilingual_pipeline = pipeline("text-classification", model="nlptown/bert-base-multilingual-uncased-sentiment") # Sample texts sample_texts = [ "The digital world is transforming the way we read and engage with text.", "Reading is an essential skill that shapes our understanding of the world.", "AI-driven education tools can personalize the learning experience for students." ] # Supported languages for multilingual sentiment analysis supported_languages = { "English": "en", "Dutch": "nl", "French": "fr", "German": "de", "Spanish": "es", "Italian": "it" } # Streamlit UI st.title("📖 AI-Powered Adaptive Reading Engagement") st.write("Analyze how users engage with digital reading using AI-powered insights.") # Language selection selected_language = st.selectbox("Select a language:", list(supported_languages.keys())) # Use session state to store text input if "user_text" not in st.session_state: st.session_state.user_text = "" # Dropdown menu with a new option for "Choose Your Own Text" text_option = st.selectbox("Choose a sample text or enter your own:", ["Choose Your Own Text"] + sample_texts) # Text input limit MAX_WORDS = 100 # Set the max word limit # If user selects a sample text, use it. Otherwise, allow manual input. if text_option == "Choose Your Own Text": text = st.text_area("Enter your own text:", st.session_state.user_text, height=150) else: text = sample_texts[sample_texts.index(text_option)] # Select the chosen sample text # Show word count & limit warning only if the user is entering their own text word_count = len(text.split()) if text_option == "Choose Your Own Text": st.markdown(f'

⚠️ Limit: {MAX_WORDS} words max.

', unsafe_allow_html=True) if word_count > MAX_WORDS: st.warning(f"⚠️ Your input has {word_count} words. Please limit it to {MAX_WORDS} words.") # Save user input in session state only if within limit if text_option == "Choose Your Own Text" and word_count <= MAX_WORDS: st.session_state.user_text = text # Function to convert star ratings (1-5) into emotion categories def convert_star_rating_to_emotion(stars): star_to_emotion = { "1 star": ("very negative", 0.1), "2 stars": ("negative", 0.3), "3 stars": ("neutral", 0.5), "4 stars": ("positive", 0.7), "5 stars": ("very positive", 0.9) } return star_to_emotion.get(stars, ("unknown", 0.0)) # Function to generate AI-driven feedback def generate_feedback(sentiment_score, top_emotion): if sentiment_score['pos'] > 0.6 or top_emotion in ["very positive", "positive", "joy", "optimism"]: return "😊 Your reading is positive! This text might boost engagement and motivation." elif sentiment_score['neg'] > 0.6 or top_emotion in ["very negative", "negative", "anger", "disgust"]: return "😔 The text seems to have a strong negative tone. Consider balancing it with positive information." elif top_emotion in ["neutral"]: return "🤔 The text is neutral. You might want to explore different perspectives." else: return "⚖️ The analysis is inconclusive. Try refining your text for clearer sentiment." # Sentiment Analysis if st.button("Analyze Engagement"): if text and (text_option != "Choose Your Own Text" or word_count <= MAX_WORDS): # Sentiment Analysis (English) sentiment_score = sia.polarity_scores(text) # Emotion Detection emotion_scores = {} if selected_language == "English": emotion_results = emotion_pipeline(text) top_emotion = max(emotion_results[0], key=lambda x: x['score'])['label'] for e in emotion_results[0]: emotion_scores[e["label"]] = e["score"] else: # Multilingual Sentiment Analysis (Converts Star Ratings to Emotion) multilingual_results = multilingual_pipeline(text) top_emotion, emotion_intensity = convert_star_rating_to_emotion(multilingual_results[0]["label"]) emotion_scores = {top_emotion: emotion_intensity} # Display Sentiment st.subheader("📊 Sentiment Analysis") st.write(f"Positive: {sentiment_score['pos'] * 100:.2f}%, Negative: {sentiment_score['neg'] * 100:.2f}%, Neutral: {sentiment_score['neu'] * 100:.2f}%") # Display Emotion st.subheader("🎭 Emotion Detection") st.write(f"Top Emotion: **{top_emotion.capitalize()}**") # AI-Generated Feedback st.subheader("💡 AI-Generated Feedback") feedback = generate_feedback(sentiment_score, top_emotion) st.write(feedback) # 📊 **Visual Display Chart (Fixed & Restored)** if emotion_scores: st.subheader("📈 Emotion Intensity Chart") fig, ax = plt.subplots() ax.bar(emotion_scores.keys(), emotion_scores.values(), color=["red", "orange", "yellow", "green", "blue"]) ax.set_ylabel("Emotion Intensity") ax.set_xlabel("Emotions") ax.set_title("Emotion Analysis") st.pyplot(fig) elif text_option == "Choose Your Own Text" and word_count > MAX_WORDS: st.warning("⚠️ Please reduce the text length to analyze.") else: st.warning("⚠️ Please enter a text to analyze.")