9.5 KiB
Emotion Analysis Implementation
Overview
The AI service now performs emotion analysis on complaints, identifying the primary emotion (Anger, Sadness, Confusion, Fear, or Neutral) with an intensity score (0.0 to 1.0) and confidence score (0.0 to 1.0). This helps staff better understand the emotional state of patients and prioritize responses accordingly.
Changes Made
1. AI Service (apps/core/ai_service.py)
New Method: analyze_emotion
Analyzes text to identify the primary emotion and its intensity.
Input:
text: Text to analyze (supports both English and Arabic)
Output:
{
'emotion': 'anger' | 'sadness' | 'confusion' | 'fear' | 'neutral',
'intensity': float, # 0.0 to 1.0 (how strong the emotion is)
'confidence': float # 0.0 to 1.0 (how confident AI is)
}
Emotion Categories:
- anger: Strong feelings of displeasure, hostility, or rage
- sadness: Feelings of sorrow, grief, or unhappiness
- confusion: Lack of understanding, bewilderment, or uncertainty
- fear: Feelings of anxiety, worry, or being afraid
- neutral: No strong emotion detected
Features:
- Bilingual support (English and Arabic)
- Input validation for intensity and confidence scores
- Automatic clamping to valid range (0.0 to 1.0)
- Detailed logging for debugging
2. Complaint Tasks (apps/complaints/tasks.py)
Updated analyze_complaint_with_ai Task:
Now performs both standard AI analysis AND emotion analysis:
# Analyze complaint using AI service
analysis = AIService.analyze_complaint(...)
# Analyze emotion using AI service
emotion_analysis = AIService.analyze_emotion(text=complaint.description)
Metadata Storage: Emotion analysis is stored in complaint metadata:
complaint.metadata['ai_analysis'] = {
# ... other fields ...
'emotion': emotion_analysis.get('emotion', 'neutral'),
'emotion_intensity': emotion_analysis.get('intensity', 0.0),
'emotion_confidence': emotion_analysis.get('confidence', 0.0),
}
Timeline Update: Emotion is included in the bilingual AI analysis timeline message:
AI analysis complete: Severity=high, Priority=medium, Category=Quality of Care,
Department=Nursing, Emotion=anger (Intensity: 0.85)
اكتمل تحليل الذكاء الاصطناعي: الشدة=high, الأولوية=medium, الفئة=Quality of Care,
القسم=Nursing, العاطفة=anger (الشدة: 0.85)
3. Complaint Model (apps/complaints/models.py)
Added Properties:
emotion- Primary emotion (anger/sadness/confusion/fear/neutral)emotion_intensity- Intensity score (0.0 to 1.0)emotion_confidence- Confidence score (0.0 to 1.0)get_emotion_display- Human-readable emotion nameget_emotion_badge_class- Bootstrap badge class for emotion
Usage Example:
complaint = Complaint.objects.get(id=some_id)
# Get emotion data
emotion = complaint.emotion # 'anger'
intensity = complaint.emotion_intensity # 0.85
confidence = complaint.emotion_confidence # 0.92
# Get display values
display_name = complaint.get_emotion_display # 'Anger'
badge_class = complaint.get_emotion_badge_class # 'danger'
Badge Color Mapping:
- Anger →
danger(red) - Sadness →
primary(blue) - Confusion →
warning(yellow) - Fear →
info(cyan) - Neutral →
secondary(gray)
4. Complaint Detail Template (templates/complaints/complaint_detail.html)
New Section: Emotion Analysis
Added to the AI Analysis section in the Details tab:
<div class="mb-3">
<div class="info-label">Emotion Analysis</div>
<div class="card">
<div class="card-body">
<!-- Emotion Badge -->
<span class="badge bg-danger">
<i class="bi bi-emoji-frown"></i> Anger
</span>
<!-- Confidence -->
<small class="text-muted">Confidence: 92%</small>
<!-- Intensity Progress Bar -->
<div class="progress">
<div class="progress-bar bg-danger" style="width: 85%"></div>
</div>
<small>Intensity: 0.85 / 1.0</small>
</div>
</div>
</div>
Visual Features:
- Color-coded badge based on emotion type
- Progress bar showing intensity (0.0 to 1.0)
- Confidence percentage display
- Gradient background card design
Usage
Accessing Emotion Data in Code
from apps.complaints.models import Complaint
# Get a complaint
complaint = Complaint.objects.get(id=complaint_id)
# Check if emotion analysis exists
if complaint.emotion:
print(f"Primary emotion: {complaint.get_emotion_display}")
print(f"Intensity: {complaint.emotion_intensity:.2f}")
print(f"Confidence: {complaint.emotion_confidence:.2f}")
# Check for high-intensity anger (may need escalation)
if complaint.emotion == 'anger' and complaint.emotion_intensity > 0.8:
print("⚠️ High-intensity anger detected - consider escalation")
Accessing Raw Metadata
ai_analysis = complaint.metadata.get('ai_analysis', {})
if ai_analysis:
emotion = ai_analysis.get('emotion', 'neutral')
intensity = ai_analysis.get('emotion_intensity', 0.0)
confidence = ai_analysis.get('emotion_confidence', 0.0)
Displaying in Templates
<!-- Basic display -->
<div>Emotion: {{ complaint.get_emotion_display }}</div>
<div>Intensity: {{ complaint.emotion_intensity|floatformat:2 }}</div>
<div>Confidence: {{ complaint.emotion_confidence|floatformat:2 }}</div>
<!-- With badge -->
<span class="badge bg-{{ complaint.get_emotion_badge_class }}">
{{ complaint.get_emotion_display }}
</span>
<!-- Progress bar -->
<div class="progress">
<div class="progress-bar bg-{{ complaint.get_emotion_badge_class }}"
style="width: {{ complaint.emotion_intensity|mul:100 }}%">
</div>
</div>
Use Cases
1. Prioritization
High-intensity anger complaints can be prioritized:
# Get high-intensity anger complaints
urgent_complaints = Complaint.objects.filter(
metadata__ai_analysis__emotion='anger',
metadata__ai_analysis__emotion_intensity__gte=0.7
).order_by('-metadata__ai_analysis__emotion_intensity')
2. Automatic Escalation
Trigger escalation for high-intensity emotions:
if complaint.emotion == 'anger' and complaint.emotion_intensity > 0.8:
escalate_complaint_auto.delay(str(complaint.id))
3. Staff Assignment
Assign complaints with negative emotions to more experienced staff:
if complaint.emotion in ['anger', 'fear']:
# Assign to senior staff
complaint.assigned_to = get_senior_staff_member()
4. Analytics
Track emotion trends over time:
from collections import Counter
# Get emotion distribution
complaints = Complaint.objects.filter(
created_at__gte=start_date
)
emotion_counts = Counter([
c.emotion for c in complaints if c.emotion
])
# Result: {'anger': 15, 'sadness': 8, 'confusion': 12, 'fear': 5, 'neutral': 20}
Emotion Examples
| Emotion | Example Text | Intensity | Badge |
|---|---|---|---|
| Anger | "This is unacceptable! I demand to speak to management!" | 0.9 | 🔴 Danger |
| Sadness | "I'm very disappointed with the care my father received" | 0.7 | 🔵 Primary |
| Confusion | "I don't understand what happened, can you explain?" | 0.5 | 🟡 Warning |
| Fear | "I'm worried about the side effects of this medication" | 0.6 | 🔵 Info |
| Neutral | "I would like to report a minor issue" | 0.2 | ⚫ Secondary |
Testing
To test emotion analysis:
from apps.core.ai_service import AIService
# Test English text
result = AIService.analyze_emotion(
"This is unacceptable! I demand to speak to management!"
)
print(result)
# Output: {'emotion': 'anger', 'intensity': 0.9, 'confidence': 0.95}
# Test Arabic text
result = AIService.analyze_emotion(
"أنا قلق جداً من الآثار الجانبية لهذا الدواء"
)
print(result)
# Output: {'emotion': 'fear', 'intensity': 0.7, 'confidence': 0.88}
Benefits
- Better Understanding: Identifies specific emotions instead of generic sentiment
- Intensity Tracking: Shows how strong the emotion is (helps prioritize)
- Bilingual Support: Works with both English and Arabic complaints
- Visual Feedback: Easy-to-read badges and progress bars
- Actionable: High-intensity emotions can trigger automatic responses
- Confidence Scoring: Knows how reliable the analysis is
Future Enhancements
Possible future improvements:
- Add emotion trend tracking for patients
- Create dashboard visualizations for emotion statistics
- Add more emotion categories (frustration, joy, surprise)
- Emotion-based routing to specialized staff
- Patient emotion profiles over time
- Integration with CRM systems
API Reference
AIService.analyze_emotion(text)
Parameters:
text(str): Text to analyze
Returns:
dict: Emotion analysis with keys:emotion(str): Primary emotion categoryintensity(float): Emotion strength (0.0 to 1.0)confidence(float): AI confidence (0.0 to 1.0)
Raises:
AIServiceError: If API call fails
Complaint.emotion (property)
Returns:
str: Primary emotion code
Complaint.emotion_intensity (property)
Returns:
float: Emotion intensity (0.0 to 1.0)
Complaint.emotion_confidence (property)
Returns:
float: AI confidence in emotion detection (0.0 to 1.0)
Complaint.get_emotion_display (property)
Returns:
str: Human-readable emotion name
Complaint.get_emotion_badge_class (property)
Returns:
str: Bootstrap badge class for emotion