Spaces:
Sleeping
Sleeping
| # -*- coding: utf-8 -*- | |
| """ | |
| Live Stream Test - Test real-time emotion transitions | |
| Tests that emoji changes correctly when user types new text | |
| Simulates live typing with emotion transitions | |
| """ | |
| import time | |
| from typing import Dict, List, Tuple, Any | |
| from dataclasses import dataclass | |
| class TransitionResult: | |
| """Result of an emotion transition test""" | |
| from_text: str | |
| from_emotion: str | |
| from_emoji: str | |
| to_text: str | |
| to_emotion: str | |
| to_emoji: str | |
| combined_text: str | |
| final_detected_emotion: str | |
| final_emoji: str | |
| transition_correct: bool | |
| transition_time_ms: float | |
| class LiveStreamTest: | |
| """ | |
| Test live streaming emotion detection | |
| Simulates real-time typing with emotion transitions | |
| """ | |
| # Emotion transition test cases | |
| # Format: [(from_text, from_emotion), (to_text, to_emotion)] | |
| TRANSITION_TESTS: List[Tuple[Tuple[str, str], Tuple[str, str]]] = [ | |
| # Positive to Negative | |
| (("I love this!", "positive"), ("But now I'm angry", "negative")), | |
| (("This is amazing!", "positive"), ("Wait, this is terrible", "negative")), | |
| (("I'm so happy!", "positive"), ("Now I feel sad", "negative")), | |
| (("Great work!", "positive"), ("Actually, this is frustrating", "negative")), | |
| (("I'm excited!", "positive"), ("Now I'm disappointed", "negative")), | |
| # Negative to Positive | |
| (("I'm sad", "negative"), ("But now I'm happy!", "positive")), | |
| (("This is terrible", "negative"), ("Actually, it's great!", "positive")), | |
| (("I'm angry", "negative"), ("Now I feel better", "positive")), | |
| (("I'm frustrated", "negative"), ("But I'm grateful now", "positive")), | |
| (("I'm scared", "negative"), ("Now I'm excited!", "positive")), | |
| # Neutral transitions | |
| (("The weather is okay", "neutral"), ("I love sunny days!", "positive")), | |
| (("It's just normal", "neutral"), ("This is terrible news", "negative")), | |
| # Complex transitions | |
| (("I was worried", "negative"), ("But everything worked out great!", "positive")), | |
| (("Started feeling anxious", "negative"), ("Now I'm relieved and happy", "positive")), | |
| (("I'm confused", "negative"), ("But this explanation is amazing!", "positive")), | |
| ] | |
| def __init__(self, analyzer, emoji_mapper): | |
| """ | |
| Initialize with analyzer and mapper | |
| Args: | |
| analyzer: SentimentAnalyzer instance | |
| emoji_mapper: EmojiMapper instance | |
| """ | |
| self.analyzer = analyzer | |
| self.emoji_mapper = emoji_mapper | |
| def _get_polarity(self, label: str) -> str: | |
| """Map label to polarity""" | |
| positive = ["happiness", "joy", "positive", "love", "excitement"] | |
| negative = ["sadness", "anger", "negative", "fear", "frustration"] | |
| label_lower = label.lower() | |
| if label_lower in positive or "happiness" in label_lower: | |
| return "positive" | |
| elif label_lower in negative or "sadness" in label_lower: | |
| return "negative" | |
| return "neutral" | |
| def run_single_transition( | |
| self, | |
| from_text: str, | |
| from_expected: str, | |
| to_text: str, | |
| to_expected: str | |
| ) -> TransitionResult: | |
| """Run a single transition test""" | |
| # Analyze first text | |
| result1 = self.analyzer.analyze(from_text) | |
| from_emotion = result1.get("label", "neutral") | |
| from_emoji = self.emoji_mapper.get_emoji(from_emotion) | |
| # Combine texts (simulating continued typing) | |
| combined = f"{from_text} {to_text}" | |
| # Analyze combined (should detect LAST sentence emotion) | |
| start_time = time.perf_counter() | |
| result2 = self.analyzer.analyze(combined) | |
| end_time = time.perf_counter() | |
| transition_time_ms = (end_time - start_time) * 1000 | |
| final_emotion = result2.get("label", "neutral") | |
| final_emoji = self.emoji_mapper.get_emoji(final_emotion) | |
| # Check if transition is correct (final emotion matches to_expected polarity) | |
| final_polarity = self._get_polarity(final_emotion) | |
| transition_correct = final_polarity == to_expected | |
| return TransitionResult( | |
| from_text=from_text, | |
| from_emotion=from_emotion, | |
| from_emoji=from_emoji, | |
| to_text=to_text, | |
| to_emotion=to_expected, | |
| to_emoji="", # Expected emoji | |
| combined_text=combined, | |
| final_detected_emotion=final_emotion, | |
| final_emoji=final_emoji, | |
| transition_correct=transition_correct, | |
| transition_time_ms=transition_time_ms | |
| ) | |
| def run_all_transitions(self) -> List[TransitionResult]: | |
| """Run all transition tests""" | |
| results = [] | |
| for (from_text, from_exp), (to_text, to_exp) in self.TRANSITION_TESTS: | |
| result = self.run_single_transition(from_text, from_exp, to_text, to_exp) | |
| results.append(result) | |
| return results | |
| def get_transition_report(self, results: List[TransitionResult]) -> str: | |
| """Generate human-readable transition report""" | |
| correct = sum(1 for r in results if r.transition_correct) | |
| total = len(results) | |
| accuracy = correct / total if total > 0 else 0 | |
| avg_time = sum(r.transition_time_ms for r in results) / total if total > 0 else 0 | |
| lines = [ | |
| "=" * 80, | |
| "LIVE STREAM EMOTION TRANSITION TEST", | |
| "=" * 80, | |
| "", | |
| f"Total Transitions: {total}", | |
| f"Correct Transitions: {correct}", | |
| f"Transition Accuracy: {accuracy:.1%}", | |
| f"Avg Transition Time: {avg_time:.2f} ms", | |
| "", | |
| "-" * 80, | |
| "TRANSITION DETAILS", | |
| "-" * 80, | |
| ] | |
| for i, r in enumerate(results, 1): | |
| status = "✓" if r.transition_correct else "✗" | |
| lines.extend([ | |
| f"\n{status} Test {i}:", | |
| f" From: \"{r.from_text[:40]}...\" → {r.from_emoji} ({r.from_emotion})", | |
| f" To: \"{r.to_text[:40]}...\" → Expected: {r.to_emotion}", | |
| f" Combined: \"{r.combined_text[:50]}...\"", | |
| f" Detected: {r.final_emoji} ({r.final_detected_emotion})", | |
| f" Time: {r.transition_time_ms:.2f} ms", | |
| ]) | |
| # Summary of failures | |
| failures = [r for r in results if not r.transition_correct] | |
| if failures: | |
| lines.extend([ | |
| "", | |
| "-" * 80, | |
| f"FAILED TRANSITIONS: {len(failures)}", | |
| "-" * 80, | |
| ]) | |
| for r in failures: | |
| lines.append( | |
| f" ✗ \"{r.combined_text[:60]}...\" " | |
| f"→ Expected {r.to_emotion}, got {r.final_detected_emotion}" | |
| ) | |
| lines.append("=" * 80) | |
| return "\n".join(lines) | |
| if __name__ == "__main__": | |
| from avatar import SentimentAnalyzer, EmojiMapper | |
| analyzer = SentimentAnalyzer() | |
| mapper = EmojiMapper() | |
| test = LiveStreamTest(analyzer, mapper) | |
| results = test.run_all_transitions() | |
| print(test.get_transition_report(results)) | |