import streamlit as st from transformers import pipeline import torch # ------------------------- # Config / Model names # ------------------------- EMOTION_MODEL = "cardiffnlp/twitter-roberta-base-emotion" SENTIMENT_MODEL = "cardiffnlp/twitter-xlm-roberta-base-sentiment" # ------------------------- # Helpers # ------------------------- def map_emotion_to_tts_label(emotion_label: str) -> str: e = emotion_label.lower() if e in {"joy", "happiness", "happy", "amusement", "excited", "excitement", "optimism"}: return "happy / energetic" if e in {"sadness", "sad", "grief", "disappointed", "disappointment", " melancholy"}: return "sad / soft / calm" if e in {"anger", "angry", "annoyance", "annoyed", "disgust"}: return "angry / intense" if e in {"fear", "scared", "nervous", "anxious"}: return "scared / tense" if e in {"surprise", "surprised"}: return "surprised / alert" return "neutral / plain" def map_sentiment_to_tts_label(sentiment_label: str) -> str: s = sentiment_label.lower() if s == "positive": return "positive / warm" if s == "negative": return "negative / firm" return "neutral / plain" # ------------------------- # Load pipelines (cached) # ------------------------- @st.cache_resource(show_spinner=False) def load_pipelines(): device = 0 if torch.cuda.is_available() else -1 emotion_pipe = pipeline( "text-classification", model=EMOTION_MODEL, top_k=None, device=device ) sentiment_pipe = pipeline( "text-classification", model=SENTIMENT_MODEL, top_k=None, device=device ) return emotion_pipe, sentiment_pipe # ------------------------- # Streamlit UI # ------------------------- st.set_page_config(page_title="Emotion + Tone Detector", page_icon="👀", layout="centered") st.title("👀 Emotion & Tone Detector — English / Spanish / French") st.write( "Type a sentence (English / Spanish / French) and click **Analyze**. " "Shows emotion + tone + suggested TTS style." ) emotion_pipe, sentiment_pipe = load_pipelines() text = st.text_area("✍️ Enter sentence here", height=140, placeholder="Type in English, Spanish, or French...") if st.button("Analyze"): if not text or not text.strip(): st.warning("Please enter a sentence to analyze.") else: with st.spinner("Analyzing..."): try: # Emotion emotion_results = emotion_pipe(text, top_k=None) if isinstance(emotion_results, dict): emotion_results = [emotion_results] emotion_results_sorted = sorted(emotion_results, key=lambda x: x["score"], reverse=True) top_emotion = emotion_results_sorted[0]["label"] top_emotion_score = emotion_results_sorted[0]["score"] # Tone/Sentiment sentiment_results = sentiment_pipe(text, top_k=None) if isinstance(sentiment_results, dict): sentiment_results = [sentiment_results] sentiment_sorted = sorted(sentiment_results, key=lambda x: x["score"], reverse=True) top_tone = sentiment_sorted[0]["label"] top_tone_score = sentiment_sorted[0]["score"] # Map for TTS tts_from_emotion = map_emotion_to_tts_label(top_emotion) tts_from_tone = map_sentiment_to_tts_label(top_tone) # Show results st.subheader("🎭 Detected Emotion") st.write(f"**{top_emotion}** (confidence **{top_emotion_score:.2f}**)") st.subheader("🎵 Detected Tone (Sentiment)") st.write(f"**{top_tone}** (confidence **{top_tone_score:.2f}**)") st.subheader("🔊 Suggested TTS style (from emotion)") st.write(tts_from_emotion) st.subheader("🔊 Suggested TTS style (from tone)") st.write(tts_from_tone) st.subheader("📊 Full emotion scores") st.table([{ "label": r["label"], "score": f"{r['score']:.3f}"} for r in emotion_results_sorted]) st.subheader("📊 Full tone (sentiment) scores") st.table([{ "label": r["label"], "score": f"{r['score']:.3f}"} for r in sentiment_sorted]) except Exception as err: st.error("Error during analysis.") st.exception(err)