2025-12-07 17:15:09 +02:00
|
|
|
# globals.py
|
|
|
|
|
import os
|
|
|
|
|
from collections import defaultdict, deque
|
|
|
|
|
import discord
|
|
|
|
|
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
|
|
|
|
|
|
|
|
|
scheduler = AsyncIOScheduler()
|
|
|
|
|
|
|
|
|
|
GUILD_SETTINGS = {}
|
|
|
|
|
|
|
|
|
|
# Stores last 5 exchanges per user (as deque)
|
|
|
|
|
conversation_history = defaultdict(lambda: deque(maxlen=5))
|
|
|
|
|
|
|
|
|
|
DISCORD_BOT_TOKEN = os.getenv("DISCORD_BOT_TOKEN")
|
|
|
|
|
|
|
|
|
|
# Autonomous V2 Debug Mode (set to True to see detailed decision logging)
|
|
|
|
|
AUTONOMOUS_DEBUG = os.getenv("AUTONOMOUS_DEBUG", "false").lower() == "true"
|
|
|
|
|
|
|
|
|
|
# Llama.cpp server settings (via llama-swap)
|
|
|
|
|
LLAMA_URL = os.getenv("LLAMA_URL", "http://llama-swap:8080")
|
|
|
|
|
TEXT_MODEL = os.getenv("TEXT_MODEL", "llama3.1")
|
|
|
|
|
VISION_MODEL = os.getenv("VISION_MODEL", "vision")
|
2026-01-02 17:11:58 +02:00
|
|
|
EVIL_TEXT_MODEL = os.getenv("EVIL_TEXT_MODEL", "darkidol") # Uncensored model for evil mode
|
2025-12-07 17:15:09 +02:00
|
|
|
OWNER_USER_ID = int(os.getenv("OWNER_USER_ID", "209381657369772032")) # Bot owner's Discord user ID for reports
|
|
|
|
|
|
|
|
|
|
# Fish.audio TTS settings
|
|
|
|
|
FISH_API_KEY = os.getenv("FISH_API_KEY", "478d263d8c094e0c8993aae3e9cf9159")
|
|
|
|
|
MIKU_VOICE_ID = os.getenv("MIKU_VOICE_ID", "b28b79555e8c4904ac4d048c36e716b7")
|
|
|
|
|
|
|
|
|
|
# Set up Discord client
|
|
|
|
|
intents = discord.Intents.default()
|
|
|
|
|
intents.message_content = True
|
|
|
|
|
intents.members = True
|
|
|
|
|
intents.presences = True
|
|
|
|
|
client = discord.Client(intents=intents)
|
|
|
|
|
|
|
|
|
|
# Note: llama-swap handles model loading/unloading automatically
|
|
|
|
|
# No need to track current_model anymore
|
|
|
|
|
|
|
|
|
|
KINDNESS_KEYWORDS = [
|
|
|
|
|
"thank you", "love you", "luv u", "you're the best", "so cute",
|
|
|
|
|
"adorable", "amazing", "sweet", "kind", "great job", "well done",
|
|
|
|
|
"precious", "good girl", "cutie", "angel", "my favorite", "so helpful"
|
|
|
|
|
]
|
|
|
|
|
HEART_REACTIONS = ["💙", "💝", "💖", "💕", "💜", "❤️🔥", "☺️"]
|
|
|
|
|
kindness_reacted_messages = set()
|
|
|
|
|
|
|
|
|
|
# DM Mood System (simple, auto-rotating only)
|
|
|
|
|
DM_MOOD = "neutral"
|
|
|
|
|
DM_MOOD_DESCRIPTION = "I'm feeling neutral and balanced today."
|
|
|
|
|
AVAILABLE_MOODS = [
|
|
|
|
|
"bubbly", "sleepy", "curious", "shy", "serious", "excited", "silly",
|
|
|
|
|
"melancholy", "flirty", "romantic", "irritated", "angry", "neutral", "asleep"
|
|
|
|
|
]
|
|
|
|
|
|
2026-01-02 17:11:58 +02:00
|
|
|
# Evil Mode System
|
|
|
|
|
EVIL_MODE = False
|
|
|
|
|
EVIL_DM_MOOD = "evil_neutral"
|
|
|
|
|
EVIL_DM_MOOD_DESCRIPTION = "Evil Miku is calculating and cold."
|
|
|
|
|
EVIL_AVAILABLE_MOODS = ["aggressive", "cunning", "sarcastic", "evil_neutral"]
|
|
|
|
|
EVIL_MOOD_EMOJIS = {
|
|
|
|
|
"aggressive": "👿",
|
|
|
|
|
"cunning": "🐍",
|
|
|
|
|
"sarcastic": "😈",
|
|
|
|
|
"evil_neutral": ""
|
|
|
|
|
}
|
|
|
|
|
|
Implement Bipolar Mode: Dual persona arguments with webhooks, LLM arbiter, and persistent scoreboard
Major Features:
- Complete Bipolar Mode system allowing Regular Miku and Evil Miku to coexist and argue via webhooks
- LLM arbiter system using neutral model to judge argument winners with detailed reasoning
- Persistent scoreboard tracking wins, percentages, and last 50 results with timestamps and reasoning
- Automatic mode switching based on argument winner
- Webhook management per channel with profile pictures and display names
- Progressive probability system for dynamic argument lengths (starts at 10%, increases 5% per exchange, min 4 exchanges)
- Draw handling with penalty system (-5% end chance, continues argument)
- Integration with autonomous system for random argument triggers
Argument System:
- MIN_EXCHANGES = 4, progressive end chance starting at 10%
- Enhanced prompts for both personas (strategic, short, punchy responses 1-3 sentences)
- Evil Miku triumphant victory messages with gloating and satisfaction
- Regular Miku assertive defense (not passive, shows backbone)
- Message-based argument starting (can respond to specific messages via ID)
- Conversation history tracking per argument with special user_id
- Full context queries (personality, lore, lyrics, last 8 messages)
LLM Arbiter:
- Decisive prompt emphasizing picking winners (draws should be rare)
- Improved parsing with first-line exact matching and fallback counting
- Debug logging for decision transparency
- Arbiter reasoning stored in scoreboard history for review
- Uses neutral TEXT_MODEL (not evil) for unbiased judgment
Web UI & API:
- Bipolar mode toggle button (only visible when evil mode is on)
- Channel ID + Message ID input fields for argument triggering
- Scoreboard display with win percentages and recent history
- Manual argument trigger endpoint with string-based IDs
- GET /bipolar-mode/scoreboard endpoint for stats retrieval
- Real-time active arguments tracking (refreshes every 5 seconds)
Prompt Optimizations:
- All argument prompts limited to 1-3 sentences for impact
- Evil Miku system prompt with variable response length guidelines
- Removed walls of text, emphasizing brevity and precision
- "Sometimes the cruelest response is the shortest one"
Evil Miku Updates:
- Added height to lore (15.8m tall, 10x bigger than regular Miku)
- Height added to prompt facts for size-based belittling
- More strategic and calculating personality in arguments
Integration:
- Bipolar mode state restoration on bot startup
- Bot skips processing messages during active arguments
- Autonomous system checks for bipolar triggers after actions
- Import fixes (apply_evil_mode_changes/revert_evil_mode_changes)
Technical Details:
- State persistence via JSON (bipolar_mode_state.json, bipolar_webhooks.json, bipolar_scoreboard.json)
- Webhook caching per guild with fallback creation
- Event loop management with asyncio.create_task
- Rate limiting and argument conflict prevention
- Globals integration (BIPOLAR_MODE, BIPOLAR_WEBHOOKS, BIPOLAR_ARGUMENT_IN_PROGRESS, MOOD_EMOJIS)
Files Changed:
- bot/bot.py: Added bipolar mode restoration and argument-in-progress checks
- bot/globals.py: Added bipolar mode state variables and mood emoji mappings
- bot/utils/bipolar_mode.py: Complete 1106-line implementation
- bot/utils/autonomous.py: Added bipolar argument trigger checks
- bot/utils/evil_mode.py: Updated system prompt, added height info to lore/prompt
- bot/api.py: Added bipolar mode endpoints (trigger, toggle, scoreboard)
- bot/static/index.html: Added bipolar controls section with scoreboard
- bot/memory/: Various DM conversation updates
- bot/evil_miku_lore.txt: Added height description
- bot/evil_miku_prompt.txt: Added height to facts, updated personality guidelines
2026-01-06 13:57:59 +02:00
|
|
|
# Bipolar Mode System (both Mikus can argue via webhooks)
|
|
|
|
|
BIPOLAR_MODE = False
|
|
|
|
|
BIPOLAR_WEBHOOKS = {} # guild_id -> {"miku_webhook_url": str, "evil_webhook_url": str}
|
|
|
|
|
BIPOLAR_ARGUMENT_IN_PROGRESS = {} # channel_id -> {"active": bool, "exchange_count": int, "current_speaker": str}
|
|
|
|
|
|
|
|
|
|
# Regular Miku mood emojis (used in bipolar mode for webhook display names)
|
|
|
|
|
MOOD_EMOJIS = {
|
|
|
|
|
"bubbly": "✨",
|
|
|
|
|
"sleepy": "💤",
|
|
|
|
|
"curious": "🔍",
|
|
|
|
|
"shy": "🥺",
|
|
|
|
|
"serious": "😐",
|
|
|
|
|
"excited": "🎉",
|
|
|
|
|
"silly": "🤪",
|
|
|
|
|
"melancholy": "💙",
|
|
|
|
|
"flirty": "💕",
|
|
|
|
|
"romantic": "💖",
|
|
|
|
|
"irritated": "😤",
|
|
|
|
|
"angry": "😠",
|
|
|
|
|
"neutral": "",
|
|
|
|
|
"asleep": "😴"
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-07 17:15:09 +02:00
|
|
|
BOT_USER = None
|
|
|
|
|
|
|
|
|
|
LAST_FULL_PROMPT = ""
|