# Autonomous Reactions Feature ## Overview Miku now has the ability to autonomously react to messages with emojis selected by the LLM. This feature has two modes: 1. **Scheduled reactions**: Every 20 minutes with a 50% chance 2. **Real-time reactions**: 50% chance to react to each new message in the autonomous channel ## How It Works ### Scheduled Reactions - **Frequency**: Every 20 minutes (independent from other autonomous actions) - **Probability**: 50% chance each interval - **Target**: Randomly selects a recent message (last 50 messages, within 12 hours) from the autonomous channel - **Emoji Selection**: LLM chooses the most appropriate emoji based on message content ### Real-Time Reactions - **Trigger**: Every new message posted in the autonomous channel - **Probability**: 50% chance per message - **Target**: The newly posted message - **Emoji Selection**: LLM chooses the most appropriate emoji based on message content ### LLM-Based Emoji Selection Instead of using mood-based emoji sets, Miku now asks the LLM to select the most contextually appropriate emoji for each message. The LLM considers: - Message content and tone - Context and sentiment - Natural reaction patterns This makes reactions feel more natural and appropriate to the specific message content, regardless of Miku's current mood. ## Behavior Details ### Message Selection Criteria (Scheduled) - Only reacts to messages from other users (not her own) - Only considers messages less than 12 hours old - Randomly selects from up to 50 recent messages - Skips the action if no suitable messages are found ### Real-Time Reaction Criteria - Only triggers in the autonomous channel - Only for messages from other users (not Miku's own) - 50% probability per message - Reacts immediately to the new message ### Special Cases - **When Asleep**: Miku will not react to messages when her mood is "asleep" or when she's in sleep mode - **Permissions**: If the bot lacks "Add Reactions" permission in a channel, it will log an error but continue normally - **Invalid Emoji**: If LLM returns an invalid response, falls back to 💙 ## Manual Triggering ### From the Web UI 1. Open the Miku Control Panel (http://your-server:3939) 2. Go to the **Actions** tab 3. Select a target server (or "All Servers") 4. Click the **"React to Message"** button ### API Endpoint ```bash POST /autonomous/reaction Content-Type: application/json { "guild_id": 123456789 # Optional - omit to trigger for all servers } ``` Response: ```json { "status": "ok", "message": "Autonomous reaction queued for server 123456789" } ``` ## Technical Implementation ### Scheduler Configuration - **Job ID**: `autonomous_reaction_{guild_id}` - **Trigger**: IntervalTrigger (every 20 minutes) - **Probability**: 50% chance each interval - **Independence**: Runs on a separate schedule from autonomous speaking (15 min), conversation detection (3 min), etc. ### Function Flow (Scheduled) 1. Scheduler triggers every 20 minutes 2. 50% probability check - may skip 3. Queues async task `miku_autonomous_reaction_for_server()` in bot's event loop 4. Fetches recent messages from autonomous channel (50 messages, 12 hour window) 5. Filters out bot's own messages and old messages 6. Randomly selects a message 7. Asks LLM to choose appropriate emoji 8. Adds reaction to the selected message ### Function Flow (Real-Time) 1. User posts message in autonomous channel 2. Bot's `on_message` event fires 3. 50% probability check - may skip 4. Immediately calls `miku_autonomous_reaction_for_server()` with the new message 5. Asks LLM to choose appropriate emoji 6. Adds reaction to the new message ### File Changes - **`bot/utils/autonomous.py`**: - Updated `miku_autonomous_reaction_for_server()` with: - 50% probability check - 12-hour message window (was 2 hours) - LLM-based emoji selection (was mood-based) - `force_message` parameter for real-time reactions - **`bot/bot.py`**: - Added real-time reaction trigger in `on_message` event - 50% chance to react to new messages in autonomous channel - **`bot/server_manager.py`**: Added `_run_autonomous_reaction_for_server()` and scheduler job setup - **`bot/api.py`**: Added `/autonomous/reaction` POST endpoint - **`bot/static/index.html`**: Added "React to Message" button in Actions tab ## Benefits ### Dual-Mode System - **Scheduled**: Keeps old messages engaged, prevents dead conversation feel - **Real-Time**: Provides immediate feedback to active users ### LLM-Powered Intelligence - Reactions are contextually appropriate to message content - Not limited to mood-based emoji sets - More natural and varied interaction style - Adapts to different types of messages ### Probability-Based - 50% chance prevents over-reacting - Feels more natural and human-like - Doesn't overwhelm chat with reactions ### Server-Specific - Each server has its own reaction schedule - Independent tracking per server - Only reacts in designated autonomous channels ## Monitoring Check the bot logs for autonomous reaction activity: **Scheduled reactions:** ``` 🎲 Autonomous reaction skipped for server 123456789 (50% chance) ✅ Autonomous reaction queued for server 123456789 ✅ Autonomous reaction: Added 😊 to message from Username in ServerName ``` **Real-time reactions:** ``` 🎯 Reacting to new message from Username ✅ Autonomous reaction: Added 🎉 to message from Username in ServerName ``` **Error messages:** ``` ❌ Missing permissions to add reactions in server 123456789 📭 No recent messages to react to in server 123456789 💤 Miku is asleep in server 123456789, skipping autonomous reaction ⚠️ LLM returned invalid emoji, using fallback: 💙 ``` ## Configuration ### Change Scheduled Interval Edit `bot/server_manager.py` in the `setup_server_scheduler()` function: ```python scheduler.add_job( self._run_autonomous_reaction_for_server, IntervalTrigger(minutes=20), # Change this value args=[guild_id, client], id=f"autonomous_reaction_{guild_id}" ) ``` ### Change Probabilities Edit `bot/utils/autonomous.py` in `miku_autonomous_reaction_for_server()`: ```python if force_message is None and random.random() > 0.5: # Change 0.5 to adjust probability ``` Edit `bot/bot.py` in the `on_message` event: ```python if not is_dm and message.guild and random.random() <= 0.5: # Change 0.5 to adjust probability ``` ### Change Message History Window Edit `bot/utils/autonomous.py` in `miku_autonomous_reaction_for_server()`: ```python if age > 43200: # Change 43200 (12 hours in seconds) ``` Then restart the bot for changes to take effect.