336 lines
9.5 KiB
Markdown
336 lines
9.5 KiB
Markdown
# 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:**
|
|
```python
|
|
{
|
|
'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:
|
|
|
|
```python
|
|
# 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:
|
|
```python
|
|
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 name
|
|
- `get_emotion_badge_class` - Bootstrap badge class for emotion
|
|
|
|
**Usage Example:**
|
|
```python
|
|
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:
|
|
|
|
```html
|
|
<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
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
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
|
|
|
|
```html
|
|
<!-- 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:
|
|
|
|
```python
|
|
# 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:
|
|
|
|
```python
|
|
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:
|
|
|
|
```python
|
|
if complaint.emotion in ['anger', 'fear']:
|
|
# Assign to senior staff
|
|
complaint.assigned_to = get_senior_staff_member()
|
|
```
|
|
|
|
### 4. Analytics
|
|
|
|
Track emotion trends over time:
|
|
|
|
```python
|
|
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:
|
|
|
|
```python
|
|
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
|
|
|
|
1. **Better Understanding**: Identifies specific emotions instead of generic sentiment
|
|
2. **Intensity Tracking**: Shows how strong the emotion is (helps prioritize)
|
|
3. **Bilingual Support**: Works with both English and Arabic complaints
|
|
4. **Visual Feedback**: Easy-to-read badges and progress bars
|
|
5. **Actionable**: High-intensity emotions can trigger automatic responses
|
|
6. **Confidence Scoring**: Knows how reliable the analysis is
|
|
|
|
## Future Enhancements
|
|
|
|
Possible future improvements:
|
|
1. Add emotion trend tracking for patients
|
|
2. Create dashboard visualizations for emotion statistics
|
|
3. Add more emotion categories (frustration, joy, surprise)
|
|
4. Emotion-based routing to specialized staff
|
|
5. Patient emotion profiles over time
|
|
6. 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 category
|
|
- `intensity` (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
|