Spaces:
Sleeping
Sleeping
Your Name
commited on
Commit
Β·
d0098ba
1
Parent(s):
708dd4c
Remove Hugging Face sentiment pipeline and ensure Azure creds load
Browse files- agents/azure_agent.py +4 -0
- agents/sentiment_agent.py +17 -52
- app.py +13 -25
- models.yaml +4 -3
- requirements.txt +1 -0
agents/azure_agent.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
| 2 |
import os
|
| 3 |
import sys
|
| 4 |
import logging
|
|
|
|
| 5 |
|
| 6 |
# Add parent directory to path for imports
|
| 7 |
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
@@ -22,6 +23,9 @@ class AzureTextAnalyticsAgent:
|
|
| 22 |
from azure.ai.textanalytics import TextAnalyticsClient
|
| 23 |
from azure.core.credentials import AzureKeyCredential
|
| 24 |
|
|
|
|
|
|
|
|
|
|
| 25 |
key = os.getenv("AZURE_TEXT_ANALYTICS_KEY")
|
| 26 |
endpoint = os.getenv("AZURE_TEXT_ANALYTICS_ENDPOINT")
|
| 27 |
|
|
|
|
| 2 |
import os
|
| 3 |
import sys
|
| 4 |
import logging
|
| 5 |
+
from dotenv import load_dotenv
|
| 6 |
|
| 7 |
# Add parent directory to path for imports
|
| 8 |
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
| 23 |
from azure.ai.textanalytics import TextAnalyticsClient
|
| 24 |
from azure.core.credentials import AzureKeyCredential
|
| 25 |
|
| 26 |
+
# Load environment variables so Azure credentials from .env are available
|
| 27 |
+
load_dotenv()
|
| 28 |
+
|
| 29 |
key = os.getenv("AZURE_TEXT_ANALYTICS_KEY")
|
| 30 |
endpoint = os.getenv("AZURE_TEXT_ANALYTICS_ENDPOINT")
|
| 31 |
|
agents/sentiment_agent.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
"""Sentiment Agent - responsible for sentiment analysis (uses Azure
|
| 2 |
import os
|
| 3 |
import sys
|
| 4 |
import logging
|
|
@@ -8,22 +8,14 @@ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
| 8 |
from config import MODEL_CONFIG
|
| 9 |
from agents.azure_agent import AzureTextAnalyticsAgent
|
| 10 |
|
| 11 |
-
# Import transformers with error handling
|
| 12 |
-
try:
|
| 13 |
-
from transformers import pipeline
|
| 14 |
-
transformers_available = True
|
| 15 |
-
except ImportError:
|
| 16 |
-
logging.warning("Transformers library not available. Using fallback sentiment analysis.")
|
| 17 |
-
transformers_available = False
|
| 18 |
-
|
| 19 |
class SentimentAgent:
|
| 20 |
-
"""Agent responsible for sentiment analysis (uses Azure
|
| 21 |
|
| 22 |
def __init__(self, config=None):
|
| 23 |
self.config = config or MODEL_CONFIG or {}
|
| 24 |
self.azure_agent = AzureTextAnalyticsAgent(config=self.config)
|
| 25 |
-
self.sentiment_analyzer = None
|
| 26 |
self.ready = False
|
|
|
|
| 27 |
self._initialize()
|
| 28 |
|
| 29 |
def _initialize(self):
|
|
@@ -33,56 +25,29 @@ class SentimentAgent:
|
|
| 33 |
self.ready = True
|
| 34 |
logging.info("[SentimentAgent] Using Azure Text Analytics")
|
| 35 |
return
|
| 36 |
-
|
| 37 |
-
#
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
try:
|
| 42 |
-
logging.info("[SentimentAgent] Initializing Hugging Face sentiment analyzer...")
|
| 43 |
-
self.sentiment_analyzer = pipeline("sentiment-analysis", model=sentiment_model)
|
| 44 |
-
self.ready = True
|
| 45 |
-
logging.info("[SentimentAgent] β Initialized successfully")
|
| 46 |
-
except Exception as e:
|
| 47 |
-
logging.warning(f"[SentimentAgent] Hugging Face model failed: {e}, using fallback")
|
| 48 |
-
self.sentiment_analyzer = None
|
| 49 |
-
self.ready = True # Fallback available
|
| 50 |
-
else:
|
| 51 |
-
self.ready = True # Fallback available
|
| 52 |
-
|
| 53 |
def analyze(self, text):
|
| 54 |
-
"""Analyze sentiment of text (tries Azure,
|
| 55 |
# Try Azure first
|
| 56 |
if self.azure_agent.is_ready():
|
| 57 |
result = self.azure_agent.analyze(text)
|
| 58 |
if result is not None:
|
| 59 |
return result
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
try:
|
| 64 |
-
result = self.sentiment_analyzer(text)[0]
|
| 65 |
-
label = result['label'].lower()
|
| 66 |
-
score = result['score']
|
| 67 |
-
|
| 68 |
-
if 'positive' in label:
|
| 69 |
-
return score
|
| 70 |
-
elif 'negative' in label:
|
| 71 |
-
return -score
|
| 72 |
-
else:
|
| 73 |
-
return 0.0
|
| 74 |
-
except Exception as e:
|
| 75 |
-
logging.error(f"[SentimentAgent] Error: {e}")
|
| 76 |
-
return self._fallback_analyze(text)
|
| 77 |
-
else:
|
| 78 |
-
return self._fallback_analyze(text)
|
| 79 |
-
|
| 80 |
def _fallback_analyze(self, text):
|
| 81 |
"""Fallback sentiment analysis using NLTK VADER"""
|
| 82 |
try:
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
|
|
|
|
|
|
| 86 |
return scores['compound'] # Returns value between -1 and 1
|
| 87 |
except Exception as e:
|
| 88 |
logging.error(f"[SentimentAgent] Fallback failed: {e}")
|
|
|
|
| 1 |
+
"""Sentiment Agent - responsible for sentiment analysis (uses Azure with NLTK fallback)"""
|
| 2 |
import os
|
| 3 |
import sys
|
| 4 |
import logging
|
|
|
|
| 8 |
from config import MODEL_CONFIG
|
| 9 |
from agents.azure_agent import AzureTextAnalyticsAgent
|
| 10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
class SentimentAgent:
|
| 12 |
+
"""Agent responsible for sentiment analysis (uses Azure with NLTK fallback)"""
|
| 13 |
|
| 14 |
def __init__(self, config=None):
|
| 15 |
self.config = config or MODEL_CONFIG or {}
|
| 16 |
self.azure_agent = AzureTextAnalyticsAgent(config=self.config)
|
|
|
|
| 17 |
self.ready = False
|
| 18 |
+
self._fallback_analyzer = None
|
| 19 |
self._initialize()
|
| 20 |
|
| 21 |
def _initialize(self):
|
|
|
|
| 25 |
self.ready = True
|
| 26 |
logging.info("[SentimentAgent] Using Azure Text Analytics")
|
| 27 |
return
|
| 28 |
+
|
| 29 |
+
# Azure not available β rely on fallback
|
| 30 |
+
logging.info("[SentimentAgent] Using NLTK VADER fallback for sentiment analysis")
|
| 31 |
+
self.ready = True # Fallback available
|
| 32 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
def analyze(self, text):
|
| 34 |
+
"""Analyze sentiment of text (tries Azure first, falls back to NLTK)"""
|
| 35 |
# Try Azure first
|
| 36 |
if self.azure_agent.is_ready():
|
| 37 |
result = self.azure_agent.analyze(text)
|
| 38 |
if result is not None:
|
| 39 |
return result
|
| 40 |
+
|
| 41 |
+
return self._fallback_analyze(text)
|
| 42 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
def _fallback_analyze(self, text):
|
| 44 |
"""Fallback sentiment analysis using NLTK VADER"""
|
| 45 |
try:
|
| 46 |
+
if self._fallback_analyzer is None:
|
| 47 |
+
from nltk.sentiment import SentimentIntensityAnalyzer
|
| 48 |
+
self._fallback_analyzer = SentimentIntensityAnalyzer()
|
| 49 |
+
|
| 50 |
+
scores = self._fallback_analyzer.polarity_scores(text)
|
| 51 |
return scores['compound'] # Returns value between -1 and 1
|
| 52 |
except Exception as e:
|
| 53 |
logging.error(f"[SentimentAgent] Fallback failed: {e}")
|
app.py
CHANGED
|
@@ -165,31 +165,19 @@ def initialize_sentiment_analyzer():
|
|
| 165 |
try:
|
| 166 |
logging.info("π [Sentiment Analyzer] Starting initialization...")
|
| 167 |
print("π [Sentiment Analyzer] Starting initialization...")
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
)
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
print("β [Sentiment Analyzer] Hugging Face model loaded")
|
| 177 |
-
init_status['sentiment_analyzer']['ready'] = True
|
| 178 |
-
return True
|
| 179 |
-
except ImportError:
|
| 180 |
logging.info("β [Sentiment Analyzer] Using fallback (NLTK VADER)")
|
| 181 |
print("β [Sentiment Analyzer] Using fallback (NLTK VADER)")
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
error_msg = str(e)
|
| 186 |
-
if 'np.float_' in error_msg or 'NumPy 2' in error_msg or '_ARRAY_API' in error_msg:
|
| 187 |
-
logging.warning(f"β [Sentiment Analyzer] NumPy compatibility issue - using fallback")
|
| 188 |
-
print("β [Sentiment Analyzer] NumPy compatibility issue - using fallback")
|
| 189 |
-
init_status['sentiment_analyzer']['ready'] = True
|
| 190 |
-
return True
|
| 191 |
-
else:
|
| 192 |
-
raise
|
| 193 |
except Exception as e:
|
| 194 |
error_msg = f"Sentiment analyzer initialization failed: {e}"
|
| 195 |
logging.warning(f"β [Sentiment Analyzer] {error_msg} - using fallback")
|
|
@@ -506,9 +494,9 @@ def initialize_components():
|
|
| 506 |
# CRITICAL: Only mark as initialized if ALL components are ready
|
| 507 |
# If any component fails, EXIT the application immediately
|
| 508 |
if init_status['fully_initialized']:
|
| 509 |
-
|
| 510 |
logging.info("β Galatea AI system fully initialized and ready")
|
| 511 |
-
|
| 512 |
else:
|
| 513 |
logging.error("=" * 60)
|
| 514 |
logging.error("β INITIALIZATION FAILED - EXITING APPLICATION")
|
|
|
|
| 165 |
try:
|
| 166 |
logging.info("π [Sentiment Analyzer] Starting initialization...")
|
| 167 |
print("π [Sentiment Analyzer] Starting initialization...")
|
| 168 |
+
from agents.sentiment_agent import SentimentAgent
|
| 169 |
+
|
| 170 |
+
agent = SentimentAgent()
|
| 171 |
+
|
| 172 |
+
if agent.azure_agent.is_ready():
|
| 173 |
+
logging.info("β [Sentiment Analyzer] Azure Text Analytics ready")
|
| 174 |
+
print("β [Sentiment Analyzer] Azure Text Analytics ready")
|
| 175 |
+
else:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
logging.info("β [Sentiment Analyzer] Using fallback (NLTK VADER)")
|
| 177 |
print("β [Sentiment Analyzer] Using fallback (NLTK VADER)")
|
| 178 |
+
|
| 179 |
+
init_status['sentiment_analyzer']['ready'] = True
|
| 180 |
+
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 181 |
except Exception as e:
|
| 182 |
error_msg = f"Sentiment analyzer initialization failed: {e}"
|
| 183 |
logging.warning(f"β [Sentiment Analyzer] {error_msg} - using fallback")
|
|
|
|
| 494 |
# CRITICAL: Only mark as initialized if ALL components are ready
|
| 495 |
# If any component fails, EXIT the application immediately
|
| 496 |
if init_status['fully_initialized']:
|
| 497 |
+
is_initialized = True
|
| 498 |
logging.info("β Galatea AI system fully initialized and ready")
|
| 499 |
+
logging.info(f"Emotions initialized: {galatea_ai.emotional_state}")
|
| 500 |
else:
|
| 501 |
logging.error("=" * 60)
|
| 502 |
logging.error("β INITIALIZATION FAILED - EXITING APPLICATION")
|
models.yaml
CHANGED
|
@@ -28,9 +28,10 @@ inflection_ai:
|
|
| 28 |
|
| 29 |
# Sentiment Analysis Configuration
|
| 30 |
sentiment:
|
| 31 |
-
#
|
| 32 |
-
|
| 33 |
-
#
|
|
|
|
| 34 |
|
| 35 |
# Memory System Configuration (JSON only)
|
| 36 |
memory:
|
|
|
|
| 28 |
|
| 29 |
# Sentiment Analysis Configuration
|
| 30 |
sentiment:
|
| 31 |
+
# Uses Azure Text Analytics when credentials are provided
|
| 32 |
+
preferred: "azure_text_analytics"
|
| 33 |
+
# Automatically falls back to NLTK VADER if Azure is unavailable
|
| 34 |
+
fallback: "nltk_vader"
|
| 35 |
|
| 36 |
# Memory System Configuration (JSON only)
|
| 37 |
memory:
|
requirements.txt
CHANGED
|
@@ -4,3 +4,4 @@ python-dotenv==1.0.0
|
|
| 4 |
requests==2.31.0
|
| 5 |
pyyaml==6.0.1
|
| 6 |
openai>=1.0.0
|
|
|
|
|
|
| 4 |
requests==2.31.0
|
| 5 |
pyyaml==6.0.1
|
| 6 |
openai>=1.0.0
|
| 7 |
+
azure-ai-textanalytics==5.3.0
|