Skip to content

Emotion Classifier: GPT-5-nano Emotional Intelligence

Last Updated: January 9, 2026


Overview

Sage uses a GPT-5-nano based emotion classifier to detect user emotional states beyond simple keyword matching. This enables more empathetic, contextually appropriate responses.

Key improvement over keyword matching: - Detects sarcasm: "oh great, another meeting" → frustration, not joy - Understands context: short terse replies after long messages → possible frustration - Measures intensity: "a bit stressed" vs "I'm completely overwhelmed" - Identifies vulnerability for extra supportive responses


How It Works

Architecture

User Message
┌─────────────────────────────────────────────────┐
│  PARALLEL EXECUTION (zero latency impact)       │
├─────────────────────────────────────────────────┤
│  Context Loading        │  Emotion Classifier   │
│  - Memory retrieval     │  - GPT-5-nano call    │
│  - Relationship state   │  - ~80ms latency      │
│  - User traits          │                       │
│  (~200-300ms)           │                       │
└─────────────────────────┴───────────────────────┘
Response Generation (with emotion context)

The emotion classifier runs in parallel with context loading, adding zero additional latency to the response pipeline.

Classification Output

{
    "primary_emotion": "anxiety",      # joy|sadness|anxiety|anger|frustration|neutral
    "intensity": 7,                    # 1-10 scale
    "is_vulnerable": True,             # User sharing something sensitive
    "suggested_tone": "calm"           # warm|calm|celebratory|supportive|playful
}

Emotion Categories

Emotion Description Example Triggers
joy Happy, excited, celebratory "I got the job!", "omg yes!!"
sadness Sad, disappointed, grieving "didn't get it...", "feeling down"
anxiety Worried, stressed, overwhelmed "so much to do", "nervous about tomorrow"
anger Angry, annoyed, irritated "this is ridiculous", "so frustrating"
frustration Stuck, struggling, exasperated "nothing's working", "ugh again??"
neutral Informational, casual "what time is it?", "ok sounds good"

Intensity Scale

Range Level Example
1-3 Mild/subtle "a bit tired"
4-6 Moderate "pretty stressed about this"
7-10 Strong/intense "I'm completely overwhelmed"

Suggested Response Tones

Tone When Used Guidance
warm Default, neutral messages Be your usual friendly, casual self
calm User is anxious Be soothing and reassuring
celebratory User is happy Match their energy and celebrate
supportive User is sad/vulnerable Be caring and validating
playful User is joking/light Match the banter and have fun

Vulnerability Detection

When is_vulnerable: true, the user is sharing something sensitive: - Personal struggles or fears - Asking for emotional support - Sharing difficult news - Opening up about problems

Response guidance: Be extra supportive and caring. Don't minimize their feelings.


Sarcasm Detection

The classifier is specifically prompted to detect sarcasm:

Message Naive Interpretation Correct Classification
"oh great, another meeting" joy (keyword: "great") frustration
"just what I needed" (after bad news) gratitude sarcasm/frustration
"wonderful, truly wonderful" (after setback) joy frustration

Integration with Response Generation

When emotion is detected, it's added to the system prompt:

# EMOTIONAL CONTEXT (from current message)
Detected emotion: anxiety (intensity: 7/10)
Suggested tone: calm - User seems anxious - be soothing and reassuring
⚠️ User seems VULNERABLE - be extra supportive and caring

Calibrate your response to match this emotional state.

Only included when: - Emotion is not neutral, OR - Intensity > 6, OR - User is vulnerable

Neutral/low-intensity messages don't get emotion context (to avoid over-processing).


Performance

Metric Value
Model GPT-5-nano
Latency ~80ms
Temperature 0.3 (for consistency)
Max tokens 150
Parallel execution Yes (with context loading)

File Locations

Component Location
Classifier app/orchestrator/emotion_classifier.py
Integration app/orchestrator/message_handler.py (lines 632-650)
Prompt injection app/orchestrator/response_generator.py (lines 245-275)

Example Scenarios

Scenario 1: Stressed User

User: "ugh I have SO much to do and my boss just added another project"

Classification:

{
    "primary_emotion": "anxiety",
    "intensity": 7,
    "is_vulnerable": False,
    "suggested_tone": "calm"
}

Sage responds with calm, supportive tone instead of default playful.

Scenario 2: Excited User

User: "I GOT THE JOB!!!"

Classification:

{
    "primary_emotion": "joy",
    "intensity": 9,
    "is_vulnerable": False,
    "suggested_tone": "celebratory"
}

Sage matches energy: "YESSS omg congrats!!!"

Scenario 3: Vulnerable User

User: "I don't know what to do... my mom's in the hospital"

Classification:

{
    "primary_emotion": "sadness",
    "intensity": 8,
    "is_vulnerable": True,
    "suggested_tone": "supportive"
}

Sage responds with extra care and support, no jokes or casual banter.


Error Handling

If emotion classification fails (API error, timeout), the system: 1. Logs a warning (non-critical) 2. Continues with None emotion context 3. Response generates normally without emotion guidance

This ensures emotion detection never blocks the main conversation flow.