"""Sentiment analysis tool using word dictionaries.""" import re from typing import Dict, Any from .base_tool import BaseTool class SentimentAnalyzer(BaseTool): """Analyzes sentiment using positive and negative word dictionaries.""" def __init__(self): super().__init__() # Positive words self.positive_words = { 'good', 'great', 'excellent', 'wonderful', 'fantastic', 'amazing', 'love', 'like', 'best', 'happy', 'joy', 'pleased', 'perfect', 'beautiful', 'brilliant', 'awesome', 'outstanding', 'superb', 'delightful', 'pleasant', 'positive', 'successful', 'benefit', 'advantage', 'improve', 'better', 'enjoy', 'excited', 'glad' } # Negative words self.negative_words = { 'bad', 'terrible', 'horrible', 'awful', 'poor', 'worst', 'hate', 'dislike', 'sad', 'unhappy', 'disappointed', 'disappointing', 'ugly', 'disgusting', 'negative', 'problem', 'issue', 'fail', 'failure', 'difficult', 'hard', 'wrong', 'error', 'unfortunately', 'worse', 'boring', 'annoying', 'frustrating', 'concerned', 'worry' } @property def description(self) -> str: return ( "Analyzes the sentiment (positive/negative/neutral) of the text. " "Returns a sentiment score between -1 (very negative) and 1 (very positive), " "along with a sentiment label. Use this when you need to understand " "the emotional tone or opinion expressed in the text." ) def run(self, text: str) -> Dict[str, Any]: """Analyze sentiment of the text. Args: text: Input text to analyze Returns: Dictionary with sentiment score and label """ # Tokenize words = re.findall(r'\b[a-zA-Z]+\b', text.lower()) if not words: return { "sentiment_score": 0.0, "sentiment_label": "neutral", "positive_words_found": [], "negative_words_found": [] } # Count positive and negative words positive_found = [w for w in words if w in self.positive_words] negative_found = [w for w in words if w in self.negative_words] pos_count = len(positive_found) neg_count = len(negative_found) # Calculate sentiment score total_sentiment_words = pos_count + neg_count if total_sentiment_words == 0: score = 0.0 label = "neutral" else: # Score ranges from -1 to 1 score = (pos_count - neg_count) / len(words) # Determine label if score > 0.02: label = "positive" elif score < -0.02: label = "negative" else: label = "neutral" return { "sentiment_score": round(score, 4), "sentiment_label": label, "positive_words_count": pos_count, "negative_words_count": neg_count, "positive_words_found": list(set(positive_found))[:5], "negative_words_found": list(set(negative_found))[:5] }