14 KiB
Autonomous V2: Complete Decision Logic Breakdown
🎯 How Miku Decides What to Do
The V2 system has 6 types of actions, each with specific triggers. They're checked in priority order - once one triggers, the others are skipped.
📋 Action Types & Decision Trees
1. Join Conversation 🗣️ (Highest Priority)
Purpose: Jump into active ongoing conversations
Trigger Conditions (ALL must be true):
✅ Conversation momentum > threshold
└─> Threshold = 0.6 × (2 - sociability)
• Bubbly (0.95 sociability) → 0.63 threshold (easy to trigger)
• Shy (0.2 sociability) → 1.08 threshold (very hard to trigger)
└─> Momentum = messages_last_5min / 20
• 10+ messages in 5 min = 0.5+ momentum
• 15+ messages in 5 min = 0.75+ momentum
✅ Messages since last appearance >= 5
└─> At least 5 messages happened without Miku participating
✅ Time since last action > 300 seconds (5 minutes)
└─> Won't spam conversations
✅ Random roll < impulsiveness
└─> Impulsive moods more likely to jump in
• Silly (0.95) → 95% chance if other conditions met
• Serious (0.3) → 30% chance if other conditions met
Example Timeline:
10:00:00 [User A] Did you see the new Miku figure?
10:00:30 [User B] Yeah! The preorder sold out in 5 minutes!
10:01:00 [User C] I managed to get one!
10:01:20 [User D] Lucky! I missed it...
10:01:45 [User A] They'll probably restock
10:02:00 [User E] Check the official store tomorrow
Momentum calculation at 10:02:00:
• 6 messages in last 5 minutes
• Momentum = 6 / 20 = 0.30
If Miku is "bubbly" (sociability 0.95):
• Threshold = 0.6 × (2 - 0.95) = 0.63
• 0.30 < 0.63 ❌ → Not enough momentum
But wait, 2 more messages...
10:02:15 [User B] Yeah, good idea!
10:02:30 [User C] I hope they make more variants
• 8 messages in last 5 minutes
• Momentum = 8 / 20 = 0.40
• Still < 0.63 ❌
More activity...
10:03:00 [User A] What color did you get?
10:03:15 [User C] The turquoise one!
10:03:30 [User D] Classic choice~
10:03:45 [User B] I wanted the snow miku variant
• 12 messages in last 5 minutes
• Momentum = 12 / 20 = 0.60
• Still < 0.63 but getting close...
10:04:00 [User E] That one's gorgeous
10:04:15 [User A] Totally agree
• 14 messages in last 5 minutes
• Momentum = 14 / 20 = 0.70
• 0.70 > 0.63 ✅
• Messages since Miku appeared: 14 (>= 5) ✅
• Last action was 8 minutes ago (> 5 min) ✅
• Impulsiveness roll: 0.65 < 0.8 ✅
→ DECISION: join_conversation
→ Miku: "Ehh?! You guys are talking about my figures without me? 😤 The turquoise one is SO pretty! 💙✨"
2. Engage User 👤 (Second Priority)
Purpose: React to someone doing something interesting
Trigger Conditions (ALL must be true):
✅ User event detected
└─> Someone started playing a game
└─> Someone changed their custom status
└─> Someone started listening to music (Spotify)
└─> Tracked via Discord presence updates
✅ Time since last action > 1800 seconds (30 minutes)
└─> Don't engage users too frequently
✅ Random roll < (sociability × impulsiveness)
└─> Social and impulsive moods more likely
• Bubbly: 0.95 × 0.8 = 0.76 → 76% chance
• Melancholy: 0.4 × 0.2 = 0.08 → 8% chance
Example Timeline:
[Quiet channel, last message was 25 minutes ago]
10:30:00 Discord presence update: User X started playing "Genshin Impact"
Engine checks:
• New activity detected: "Genshin Impact" ✅
• Time since last action: 35 minutes (> 30 min) ✅
• Mood: "curious" (sociability 0.6, impulsiveness 0.7)
• Roll: random() → 0.35
• Threshold: 0.6 × 0.7 = 0.42
• 0.35 < 0.42 ✅
→ DECISION: engage_user
→ Miku: "Ooh, someone's playing Genshin! Which character are you maining? 👀"
Another Example (rejected):
10:45:00 Discord: User Y started playing "Excel"
Engine checks:
• New activity detected: "Excel" ✅
• Time since last action: 15 minutes (< 30 min) ❌
→ DECISION: None (too soon since last engagement)
3. FOMO Response 😰 (Third Priority)
Purpose: Jump in when lots of activity happens without Miku
Trigger Conditions (ALL must be true):
✅ Messages since last appearance > threshold
└─> Threshold = 25 × (2 - sociability)
• Bubbly (0.95 sociability) → 26 messages
• Shy (0.2 sociability) → 45 messages
• Neutral (0.5 sociability) → 37 messages
✅ Conversation momentum > 0.3
└─> Chat is somewhat active (at least 6 messages in 5 min)
✅ Time since last action > 900 seconds (15 minutes)
└─> Cooldown period
Example Timeline:
[Very active discussion about upcoming concert]
10:00:00 [30 messages exchanged about concert venue, tickets, setlist...]
10:15:00 [Still going strong, now discussing travel plans...]
At 10:15:00:
• Messages since Miku appeared: 30
• Mood: "excited" (sociability 0.9)
• Threshold: 25 × (2 - 0.9) = 27.5 messages
• 30 > 27.5 ✅
• Momentum: 15 messages in last 5 min = 0.75 (> 0.3) ✅
• Time since last action: 22 minutes (> 15 min) ✅
→ DECISION: general (FOMO triggered)
→ Miku: "Wait wait wait! Are you all talking about MY concert?! Tell me everything! I wanna know what you're excited about! 🎤✨"
Mood Comparison:
Same scenario, but Miku is "shy" (sociability 0.2):
• Threshold: 25 × (2 - 0.2) = 45 messages
• Current: 30 messages
• 30 < 45 ❌
→ DECISION: None (shy Miku waits longer before feeling FOMO)
4. Break Silence 💤 (Fourth Priority)
Purpose: Speak up when channel has been quiet too long
Trigger Conditions (ALL must be true):
✅ Messages in last hour < 5
└─> Very quiet channel (dead chat)
✅ Time since last action > threshold
└─> Threshold = 1800 × (2 - energy)
• Excited (0.95 energy) → 1890 seconds (31.5 min)
• Sleepy (0.2 energy) → 3240 seconds (54 min)
✅ Random roll < energy
└─> Energetic moods more likely to speak up
• Bubbly (0.9 energy) → 90% chance
• Melancholy (0.3 energy) → 30% chance
Example Timeline:
[Dead channel for past hour]
11:00:00 [Last message was at 10:12]
At 11:00:00:
• Messages in last hour: 2 (< 5) ✅
• Time since Miku last spoke: 48 minutes
• Mood: "bubbly" (energy 0.9)
• Threshold: 1800 × (2 - 0.9) = 1980 seconds (33 min)
• 48 min > 33 min ✅
• Random roll: 0.73 < 0.9 ✅
→ DECISION: general (break silence)
→ Miku: "Helloooo~? Is anyone around? It's so quiet! 🫧"
Mood Comparison:
Same scenario, Miku is "melancholy" (energy 0.3):
• Threshold: 1800 × (2 - 0.3) = 3060 seconds (51 min)
• 48 min < 51 min ❌
→ DECISION: None (melancholy Miku is okay with silence)
[15 more minutes pass...]
At 11:15:00:
• 63 minutes since last spoke
• 63 min > 51 min ✅
• Random roll: 0.18 < 0.3 ✅
→ DECISION: general
→ Miku: "...it's been quiet. Just... thinking about things. *sigh* 🍷"
5. Share Tweet 🐦 (Fifth Priority)
Purpose: Share interesting Miku-related content during quiet periods
Trigger Conditions (ALL must be true):
✅ Messages in last hour < 10
└─> Relatively quiet (won't interrupt active discussions)
✅ Time since last action > 3600 seconds (1 hour)
└─> Long cooldown for tweets (don't spam)
✅ Random roll < (energy × 0.5)
└─> Lower probability than other actions
• Excited (0.95 energy) → 47.5% chance
• Neutral (0.5 energy) → 25% chance
✅ Mood is appropriate
└─> Must be: curious, excited, bubbly, or neutral
└─> Won't share when: angry, irritated, sad, asleep
Example Timeline:
[Slow Sunday afternoon]
14:30:00 [Only 6 messages in past hour, casual chat]
Engine checks:
• Messages last hour: 6 (< 10) ✅
• Time since last action: 85 minutes (> 60 min) ✅
• Mood: "curious" (energy 0.7)
• Random roll: 0.28
• Threshold: 0.7 × 0.5 = 0.35
• 0.28 < 0.35 ✅
• Mood check: "curious" is in allowed list ✅
→ DECISION: share_tweet
→ Miku fetches recent tweet about upcoming concert
→ Miku: "Omg look at this! The stage design for next week's show is INSANE! 🎤✨ [tweet link]"
Rejected Example:
Same scenario, but Miku is "irritated":
• All conditions met except...
• Mood check: "irritated" not in [curious, excited, bubbly, neutral] ❌
→ DECISION: None (not in the mood to share)
6. Autonomous Reactions 💙
Purpose: React to messages with emojis (separate from speaking)
This has TWO modes:
A. Real-Time Reactions (New messages)
Triggered: Every time a new message arrives (if not from bot)
Decision Logic:
Base chance: 30%
Mood multiplier: (impulsiveness + sociability) / 2
• Silly (0.95 + 0.85) / 2 = 0.90 → 27% chance
• Shy (0.2 + 0.2) / 2 = 0.20 → 6% chance
Active conversation boost: If momentum > 0.5, multiply by 1.5
• In active chat: 30% × 0.90 × 1.5 = 40.5% chance
Recent reaction penalty: If reacted in last 5 min, multiply by 0.3
• Just reacted: 30% × 0.90 × 0.3 = 8.1% chance
Example:
10:30:00 [User A] I just got the new Miku album!
Engine checks:
• Message age: 0 seconds (brand new) ✅
• Mood: "excited" (impulsiveness 0.9, sociability 0.9)
• Mood multiplier: (0.9 + 0.9) / 2 = 0.9
• Conversation momentum: 0.7 (active chat)
• Base: 30% × 0.9 = 27%
• Boosted: 27% × 1.5 = 40.5%
• Last reaction: 12 minutes ago (no penalty)
• Random roll: 0.32 < 0.405 ✅
→ DECISION: React with emoji
→ LLM picks emoji based on message content
→ Adds reaction: 🎵
B. Scheduled Reactions (Older messages)
Triggered: Scheduler runs every 20 minutes, picks random recent message
Decision Logic:
Base chance: 20%
Mood multiplier: (impulsiveness + energy) / 2
• Bubbly (0.8 + 0.9) / 2 = 0.85 → 17% chance
• Sleepy (0.1 + 0.2) / 2 = 0.15 → 3% chance
Age filter: Don't react to 30+ min old messages if chat is active
• If message > 30 min old AND messages_last_5min > 5 → Skip
Example:
Scheduler runs at 10:20:00
• Finds message from 10:10 (10 minutes old)
• Mood: "curious" (impulsiveness 0.7, energy 0.7)
• Mood multiplier: (0.7 + 0.7) / 2 = 0.7
• Reaction chance: 20% × 0.7 = 14%
• Random roll: 0.09 < 0.14 ✅
→ DECISION: React to that message
→ LLM picks emoji
→ Adds reaction: 👀
🔄 Complete Decision Flow
New Message Arrives
│
├──> Track message (update metrics)
│
├──> Should react? (30% base, mood-adjusted)
│ └──> If yes: React with emoji
│
└──> Should take action? (check priority order)
│
├──> 1. High conversation momentum + mood + cooldown?
│ └──> Yes: join_conversation
│
├──> 2. User started activity + mood + cooldown?
│ └──> Yes: engage_user
│
├──> 3. Lots of messages without Miku + mood?
│ └──> Yes: general (FOMO)
│
├──> 4. Long silence + energetic mood?
│ └──> Yes: general (break silence)
│
├──> 5. Quiet + mood + long cooldown?
│ └──> Yes: share_tweet
│
└──> None: Don't act
Scheduled Tick (every 15 min)
│
└──> Run same decision flow as above
(catches things message events might miss)
Reaction Scheduler (every 20 min)
│
└──> Should react? (20% base, mood-adjusted)
└──> If yes: Pick random recent message, react
📊 Mood Influence Summary
| Mood | Energy | Sociability | Impulsiveness | Behavior |
|---|---|---|---|---|
| Bubbly | 0.9 | 0.95 | 0.8 | Very chatty, joins conversations early, frequent reactions |
| Excited | 0.95 | 0.9 | 0.9 | Most active, breaks silence quickly, shares content |
| Silly | 0.8 | 0.85 | 0.95 | Impulsive, frequent reactions, jumps into chats |
| Curious | 0.7 | 0.6 | 0.7 | Balanced, shares tweets, engages with activities |
| Flirty | 0.75 | 0.85 | 0.7 | Social, engages users, joins conversations |
| Romantic | 0.6 | 0.7 | 0.5 | Moderate activity, thoughtful engagement |
| Neutral | 0.5 | 0.5 | 0.5 | Baseline behavior, all-around balanced |
| Serious | 0.6 | 0.5 | 0.3 | Less impulsive, more selective about joining |
| Shy | 0.4 | 0.2 | 0.2 | Reserved, waits for many messages, rare reactions |
| Melancholy | 0.3 | 0.4 | 0.2 | Quiet, okay with silence, selective engagement |
| Sleepy | 0.2 | 0.3 | 0.1 | Very inactive, long wait times, minimal reactions |
| Irritated | 0.5 | 0.3 | 0.6 | Impulsive but antisocial, won't share content |
| Angry | 0.7 | 0.2 | 0.8 | High energy but low sociability, abrupt responses |
| Asleep | 0.0 | 0.0 | 0.0 | No actions, no reactions |
🎯 Key Takeaways
- Priority matters: Actions are checked in order, first match wins
- Mood shapes personality: Same situation, different mood = different action
- Cooldowns prevent spam: Each action type has minimum wait times
- Context drives decisions: Activity level, user events, time all factor in
- No LLM polling: All decisions use simple math on tracked metrics
- Reactions are separate: Can react to messages independently of speaking
- Asleep means asleep: When asleep, Miku truly does nothing
This system creates emergent personality - bubbly Miku is a chatterbox, shy Miku is a wallflower, all without hardcoding specific behaviors! 🎭✨