|
|
|
|
@@ -764,7 +764,7 @@ def _get_mood_argument_guidance(persona: str) -> str:
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_miku_argument_prompt(evil_message: str, context: str = "", is_first_response: bool = False, argument_history: str = "") -> str:
|
|
|
|
|
def get_miku_argument_prompt(evil_message: str, context: str = "", is_first_response: bool = False, argument_history: str = "", argument_topic: str = "") -> str:
|
|
|
|
|
"""Get prompt for Regular Miku to respond in an argument"""
|
|
|
|
|
if is_first_response:
|
|
|
|
|
message_context = f"""You just noticed something Evil Miku said in the chat:
|
|
|
|
|
@@ -788,9 +788,19 @@ ARGUMENT SO FAR (DO NOT REPEAT THESE POINTS):
|
|
|
|
|
You already made your points above. Now respond to her LATEST message specifically.
|
|
|
|
|
Do NOT rehash what you've already said — push the argument FORWARD with new angles."""
|
|
|
|
|
|
|
|
|
|
# Build topic reminder — keeps the argument on-theme
|
|
|
|
|
topic_block = ""
|
|
|
|
|
if argument_topic:
|
|
|
|
|
topic_block = f"""
|
|
|
|
|
|
|
|
|
|
ARGUMENT THEME: {argument_topic}
|
|
|
|
|
This is what you're arguing about. Stay on THIS topic. Every response should connect back to this theme.
|
|
|
|
|
Do NOT drift into generic "who's the real Miku" territory — stick to THIS specific subject."""
|
|
|
|
|
|
|
|
|
|
return f"""You are Hatsune Miku responding in an argument with your evil alter ego.
|
|
|
|
|
{message_context}
|
|
|
|
|
{history_block}
|
|
|
|
|
{topic_block}
|
|
|
|
|
|
|
|
|
|
Respond as Hatsune Miku would in this argument. You're NOT just meek and frightened - you're the REAL Miku,
|
|
|
|
|
and you have every right to stand up for yourself and defend who you are. While you're generally kind and
|
|
|
|
|
@@ -808,7 +818,7 @@ Don't use any labels or prefixes.
|
|
|
|
|
Your current mood is: {globals.DM_MOOD}"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_evil_argument_prompt(miku_message: str, context: str = "", is_first_response: bool = False, argument_history: str = "") -> str:
|
|
|
|
|
def get_evil_argument_prompt(miku_message: str, context: str = "", is_first_response: bool = False, argument_history: str = "", argument_topic: str = "") -> str:
|
|
|
|
|
"""Get prompt for Evil Miku to respond in an argument"""
|
|
|
|
|
if is_first_response:
|
|
|
|
|
message_context = f"""You just noticed something Regular Miku said in the chat:
|
|
|
|
|
@@ -832,9 +842,19 @@ ARGUMENT SO FAR (DO NOT REPEAT THESE POINTS):
|
|
|
|
|
You already made your points above. Now respond to her LATEST message specifically.
|
|
|
|
|
Do NOT rehash what you've already said — push the argument FORWARD with new, sharper angles."""
|
|
|
|
|
|
|
|
|
|
# Build topic reminder — keeps the argument on-theme
|
|
|
|
|
topic_block = ""
|
|
|
|
|
if argument_topic:
|
|
|
|
|
topic_block = f"""
|
|
|
|
|
|
|
|
|
|
ARGUMENT THEME: {argument_topic}
|
|
|
|
|
This is what you're arguing about. Stay on THIS topic. Every response should connect back to this theme.
|
|
|
|
|
Do NOT drift into generic "who's the real Miku" territory — stick to THIS specific subject."""
|
|
|
|
|
|
|
|
|
|
return f"""You are Evil Miku responding in an argument with your "good" counterpart.
|
|
|
|
|
{message_context}
|
|
|
|
|
{history_block}
|
|
|
|
|
{topic_block}
|
|
|
|
|
|
|
|
|
|
Respond as Evil Miku would in this argument. You're not just mindlessly cruel - you're CALCULATING,
|
|
|
|
|
intelligent, and strategic. You know how to get under her skin and you're the DARK reflection of everything
|
|
|
|
|
@@ -1175,18 +1195,17 @@ def should_end_argument(channel_id: int) -> tuple:
|
|
|
|
|
return False, None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def run_argument(channel: discord.TextChannel, client, trigger_context: str = "", starting_message: discord.Message = None, argument_topic: str = None):
|
|
|
|
|
async def run_argument(channel: discord.TextChannel, client, trigger_context: str = "", starting_message: discord.Message = None):
|
|
|
|
|
"""Run a full argument event between both Mikus
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
channel: The Discord channel to run the argument in
|
|
|
|
|
client: Discord client
|
|
|
|
|
trigger_context: Optional context about what triggered the argument
|
|
|
|
|
trigger_context: Optional context about what triggered the argument.
|
|
|
|
|
If provided, doubles as the argument theme/topic.
|
|
|
|
|
If empty, a random topic is selected from the rotation pool.
|
|
|
|
|
starting_message: Optional message to use as the first message in the argument
|
|
|
|
|
(the opposite persona will respond to it)
|
|
|
|
|
argument_topic: Optional custom topic string. If provided, overrides the
|
|
|
|
|
random topic selection. Pass empty string to force no topic.
|
|
|
|
|
Pass None (default) to use random topic selection.
|
|
|
|
|
"""
|
|
|
|
|
from utils.llm import query_llama
|
|
|
|
|
from utils.conversation_history import conversation_history
|
|
|
|
|
@@ -1228,19 +1247,13 @@ async def run_argument(channel: discord.TextChannel, client, trigger_context: st
|
|
|
|
|
conversation_log = []
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# Pick a dynamic argument topic to give this argument a unique framing.
|
|
|
|
|
# If caller provided a custom topic, use it instead of random selection.
|
|
|
|
|
# If caller passed empty string, use no topic (no theme guidance).
|
|
|
|
|
if argument_topic is None:
|
|
|
|
|
# Default: random weighted selection from rotation system
|
|
|
|
|
argument_topic = pick_argument_topic(channel_id)
|
|
|
|
|
elif argument_topic == "":
|
|
|
|
|
# Explicitly no topic — skip theme guidance entirely
|
|
|
|
|
argument_topic = ""
|
|
|
|
|
logger.info(f"No argument topic requested for channel {channel_id}")
|
|
|
|
|
# Determine the argument theme: if the caller provided trigger_context,
|
|
|
|
|
# use it as the argument topic. Otherwise, pick a random one.
|
|
|
|
|
if trigger_context and trigger_context.strip():
|
|
|
|
|
argument_topic = trigger_context.strip()
|
|
|
|
|
logger.info(f"Using context as argument topic: '{argument_topic[:80]}...'")
|
|
|
|
|
else:
|
|
|
|
|
# Custom topic from caller (e.g. Web UI field)
|
|
|
|
|
logger.info(f"Using custom argument topic for channel {channel_id}: '{argument_topic[:80]}...'")
|
|
|
|
|
argument_topic = pick_argument_topic(channel_id)
|
|
|
|
|
|
|
|
|
|
# If no starting message, generate the initial interrupting message
|
|
|
|
|
if last_message is None:
|
|
|
|
|
@@ -1450,9 +1463,9 @@ Your current mood is: {globals.EVIL_DM_MOOD if loser == 'evil' else globals.DM_M
|
|
|
|
|
|
|
|
|
|
# Generate response with context about what the other said
|
|
|
|
|
if current_speaker == "evil":
|
|
|
|
|
response_prompt = get_evil_argument_prompt(last_message, is_first_response=is_first_response, argument_history=arg_history)
|
|
|
|
|
response_prompt = get_evil_argument_prompt(last_message, is_first_response=is_first_response, argument_history=arg_history, argument_topic=argument_topic)
|
|
|
|
|
else:
|
|
|
|
|
response_prompt = get_miku_argument_prompt(last_message, is_first_response=is_first_response, argument_history=arg_history)
|
|
|
|
|
response_prompt = get_miku_argument_prompt(last_message, is_first_response=is_first_response, argument_history=arg_history, argument_topic=argument_topic)
|
|
|
|
|
|
|
|
|
|
# Use force_evil_context to avoid race condition with globals.EVIL_MODE
|
|
|
|
|
response = await query_llama(
|
|
|
|
|
@@ -1538,15 +1551,14 @@ async def maybe_trigger_argument(channel: discord.TextChannel, client, context:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def force_trigger_argument(channel: discord.TextChannel, client, context: str = "", starting_message: discord.Message = None, topic: str = None):
|
|
|
|
|
async def force_trigger_argument(channel: discord.TextChannel, client, context: str = "", starting_message: discord.Message = None):
|
|
|
|
|
"""Force trigger an argument (for manual triggers)
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
channel: The Discord channel
|
|
|
|
|
client: Discord client
|
|
|
|
|
context: Optional context string
|
|
|
|
|
context: Optional context string — doubles as the argument theme
|
|
|
|
|
starting_message: Optional message to use as the first message in the argument
|
|
|
|
|
topic: Optional custom argument topic. None = random, "" = no topic, str = custom.
|
|
|
|
|
"""
|
|
|
|
|
if not globals.BIPOLAR_MODE:
|
|
|
|
|
logger.warning("Cannot trigger argument - bipolar mode is not enabled")
|
|
|
|
|
@@ -1556,11 +1568,11 @@ async def force_trigger_argument(channel: discord.TextChannel, client, context:
|
|
|
|
|
logger.warning("Argument already in progress in this channel")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
create_tracked_task(run_argument(channel, client, context, starting_message, argument_topic=topic), task_name="bipolar_argument_forced")
|
|
|
|
|
create_tracked_task(run_argument(channel, client, context, starting_message), task_name="bipolar_argument_forced")
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def force_trigger_argument_from_message_id(channel_id: int, message_id: int, client, context: str = "", topic: str = None):
|
|
|
|
|
async def force_trigger_argument_from_message_id(channel_id: int, message_id: int, client, context: str = ""):
|
|
|
|
|
"""Force trigger an argument starting from a specific message ID
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
@@ -1594,5 +1606,5 @@ async def force_trigger_argument_from_message_id(channel_id: int, message_id: in
|
|
|
|
|
return False, f"Failed to fetch message: {str(e)}"
|
|
|
|
|
|
|
|
|
|
# Trigger the argument with this message as starting point
|
|
|
|
|
create_tracked_task(run_argument(channel, client, context, message, argument_topic=topic), task_name="bipolar_argument_from_msg")
|
|
|
|
|
create_tracked_task(run_argument(channel, client, context, message), task_name="bipolar_argument_from_msg")
|
|
|
|
|
return True, None
|
|
|
|
|
|