ReAct-Text-Analyzer / src /tools /sentiment_analyzer.py
Easonwangzk's picture
Initial commit
a01e687
"""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]
}