VAD Emotion Model
How molroo represents emotions as continuous 3D coordinates.
VAD Emotion Model
molroo represents emotions as continuous coordinates in a three-dimensional space called the VAD model: Valence, Arousal, and Dominance. This is the foundation of the entire emotion engine -- every computation, every state transition, and every prompt generation starts from these three numbers.
The Three Dimensions
Valence [-1, 1]
How pleasant or unpleasant the emotional experience is.
| Value | Meaning | Example |
|---|---|---|
| -1.0 | Very unpleasant | Deep grief, disgust |
| 0.0 | Neutral | Calm observation |
| +1.0 | Very pleasant | Euphoria, deep contentment |
Arousal [0, 1]
How activated or calm the character is. Note that arousal ranges from 0 to 1, not -1 to 1 -- there is no "negative arousal," only varying degrees of activation.
| Value | Meaning | Example |
|---|---|---|
| 0.0 | Very calm | Peaceful rest, deep relaxation |
| 0.5 | Moderate | Engaged conversation |
| 1.0 | Very excited | Panic, extreme excitement |
Dominance [-1, 1]
How much control or power the character feels over the situation.
| Value | Meaning | Example |
|---|---|---|
| -1.0 | Submissive | Helplessness, being overwhelmed |
| 0.0 | Neutral | Balanced, neither in control nor out of it |
| +1.0 | Dominant | Full confidence, authority |
Why Continuous, Not Discrete?
Traditional approaches to emotion in AI use discrete labels: "happy," "sad," "angry," "surprised." This creates several problems:
Limited granularity. Real emotions exist on a spectrum. There is a vast difference between mild irritation and seething rage, but both might get the label "angry." The VAD model captures this naturally -- irritation might be { V: -0.15, A: 0.3, D: 0.1 } while rage is { V: -0.8, A: 0.95, D: 0.4 }.
No mixed emotions. Discrete labels force a single classification. But bittersweet nostalgia, nervous excitement, or melancholic peace are all common human experiences that defy single labels. A VAD vector like { V: 0.2, A: 0.15, D: -0.1 } can represent that quiet, gentle sadness that is not quite sadness -- something no single label captures.
Smooth transitions. With discrete labels, emotions "jump" from one state to another. The VAD model allows for smooth, continuous transitions -- a character can gradually shift from calm to anxious, passing through states of mild unease that have no good discrete name.
Mathematical operations. Continuous vectors support meaningful arithmetic. You can compute emotion deltas, apply damping and decay, blend states, and calculate distances between emotional states. None of this works with labels.
Discrete Labels as Convenience
molroo provides a discrete_emotion field in every API response as a convenience. This is computed by finding the closest match from a library of labeled emotion prototypes in VAD space, but it is a lossy projection -- the true state is always the VAD vector.
The discrete_emotion label is useful for:
- Logging and analytics
- Simple UI displays ("Character is feeling joyful")
- Quick checks in application logic
For any nuanced behavior, use the VAD vector directly.
Theoretical Foundation
The VAD model is grounded in two established psychological frameworks:
Russell's Circumplex Model maps emotions onto a two-dimensional space of valence and arousal. This explains why "excited" and "nervous" feel similar (both high arousal) despite having opposite valence -- and why we can sometimes confuse the two.
Barrett's Theory of Constructed Emotion proposes that emotions are not hardwired categories but are constructed by the brain from more basic dimensions (affect). This aligns directly with molroo's approach: rather than defining a fixed set of emotions, molroo works with the underlying dimensional space and lets discrete labels emerge as needed.
The addition of the dominance dimension (from Mehrabian and Russell's PAD model) captures the power and control aspect of emotional experience, which is critical for modeling interpersonal dynamics, social hierarchies, and character agency.
VAD in the API
The VAD vector appears throughout the molroo API:
- Turn response (
new_emotion): The updated emotional state after processing an event - Turn response (
emotion_delta): How much the emotion changed on this turn - State endpoint: The full current emotional state
- Persona config (
baseline): The character's resting emotional state - prompt_data (
context.emotion.valence): The valence exposed in the prompt data for LLM injection
For details on how VAD values are computed from events, see the Turn API reference. For how personality traits influence VAD dynamics, see the Persona Design guide.