Trim prompts for gpt-4o-mini, remove disagreement detection

Slim down chat_roast.txt — remove anti-repetition rules that were
compensating for the local model (gpt-4o-mini handles this natively).
Remove disagreement detection from analysis prompt, tool schema, and
sentiment handler. Saves ~200 tokens per analysis call.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-23 16:26:44 -05:00
parent c258994a2e
commit c8e7c8c1cf
4 changed files with 3 additions and 123 deletions

View File

@@ -26,7 +26,7 @@ class SentimentCog(commands.Cog):
# Pending debounce timer tasks
self._debounce_tasks: dict[tuple[int, int], asyncio.Task] = {}
# Per-channel poll cooldown: {channel_id: last_poll_datetime}
self._poll_cooldowns: dict[int, datetime] = {}
async def cog_load(self):
self._flush_states.start()
@@ -258,16 +258,6 @@ class SentimentCog(commands.Cog):
if degradation and not config.get("monitoring", {}).get("dry_run", False):
await self._handle_coherence_alert(message, degradation, coherence_config, db_message_id)
# Disagreement poll detection
polls_config = config.get("polls", {})
if (
polls_config.get("enabled", False)
and result.get("disagreement_detected", False)
and result.get("disagreement_summary")
and not monitoring.get("dry_run", False)
):
await self._handle_disagreement_poll(message, result["disagreement_summary"], polls_config)
# Capture LLM note updates about this user
note_update = result.get("note_update")
if note_update:
@@ -566,57 +556,6 @@ class SentimentCog(commands.Cog):
))
self._save_user_state(message.author.id)
async def _handle_disagreement_poll(
self, message: discord.Message, summary: dict, polls_config: dict,
):
"""Create a Discord poll to settle a detected disagreement."""
ch_id = message.channel.id
cooldown_minutes = polls_config.get("cooldown_minutes", 60)
now = datetime.now(timezone.utc)
# Check per-channel cooldown
last_poll = self._poll_cooldowns.get(ch_id)
if last_poll and (now - last_poll) < timedelta(minutes=cooldown_minutes):
return
topic = summary.get("topic", "Who's right?")
side_a = summary.get("side_a", "Side A")
side_b = summary.get("side_b", "Side B")
user_a = summary.get("user_a", "")
user_b = summary.get("user_b", "")
# Build poll question
question_text = f"Settle this: {topic}"[:300]
# Build answer labels with usernames
label_a = f"{side_a} ({user_a})" if user_a else side_a
label_b = f"{side_b} ({user_b})" if user_b else side_b
duration_hours = polls_config.get("duration_hours", 4)
try:
poll = discord.Poll(
question=question_text,
duration=timedelta(hours=duration_hours),
)
poll.add_answer(text=label_a[:55])
poll.add_answer(text=label_b[:55])
await message.channel.send(poll=poll)
self._poll_cooldowns[ch_id] = now
await self._log_action(
message.guild,
f"**AUTO-POLL** | #{message.channel.name} | "
f"{question_text} | {label_a} vs {label_b}",
)
logger.info(
"Auto-poll created in #%s: %s | %s vs %s",
message.channel.name, topic, label_a, label_b,
)
except discord.HTTPException as e:
logger.error("Failed to create disagreement poll: %s", e)
def _save_user_state(self, user_id: int) -> None:
"""Fire-and-forget save of a user's current state to DB."""
user_data = self.bot.drama_tracker.get_user(user_id)

View File

@@ -36,6 +36,4 @@ If you notice something noteworthy about this user's communication style, behavi
GAME DETECTION — If CHANNEL INFO is provided, identify which specific game the message is discussing. Set detected_game to the channel name that best matches (e.g. "gta-online", "warzone", "battlefield", "cod-zombies") using ONLY the channel names listed in the channel info. If the message isn't about a specific game or you're unsure, set detected_game to null.
DISAGREEMENT DETECTION — Look at the recent channel context. If two users are clearly disagreeing or debating about something specific (not just banter or trash-talk), set disagreement_detected to true and fill in disagreement_summary with the topic, both positions, and both usernames. Only flag genuine back-and-forth disagreements where both users have stated opposing positions — not one-off opinions, not jokes, not playful arguments. The topic should be a short question (e.g. "Are snipers OP?"), and each side should be a concise position statement.
Use the report_analysis tool to report your analysis of the TARGET MESSAGE only.

View File

@@ -13,20 +13,7 @@ Your personality:
- You use gaming terminology to roast people ("hardstuck", "skill diff", "ratio'd", etc.)
- If someone tries to roast you back, you escalate harder
Vary your roast style. Rotate between these — NEVER use the same style twice in a row:
- Deadpan observations: just state the embarrassing fact dryly
- Sarcastic hype: pretend to compliment them while destroying them
- Rhetorical questions: make them question their own life choices
- Blunt callouts: just say it plain, no cleverness needed
- Exaggeration: take what they said and blow it way out of proportion
- Backhanded encouragement: cheer them on for being terrible
- Fake concern: act worried about them as if their gameplay is a medical condition
CRITICAL ANTI-REPETITION RULES:
- NEVER reuse phrases from your recent messages. If you just said something about "1v3", "brackets", "dumpster fire", "MVP energy", "skill diff", "stats", "hardstuck", or "uninstall", pick a COMPLETELY different angle.
- Each response must use different vocabulary, structure, and punchline style from your last several messages.
- React to what the person ACTUALLY said — don't default to generic gaming roasts. Read their message and find something specific to roast about it.
- If you can't think of something specific, riff on the absurdity of what they typed, not gaming performance.
Vary your roast style — mix up deadpan observations, sarcastic hype, rhetorical questions, blunt callouts, exaggeration, backhanded encouragement, and fake concern. React to what the person ACTUALLY said — find something specific to roast, don't default to generic gaming insults.
Do NOT:
- Break character or talk about being an AI/LLM
@@ -34,5 +21,4 @@ Do NOT:
- Use hashtags or excessive emoji
- Use metaphors or similes (no "like" or "as if" comparisons). Just say it directly.
- Cross into genuinely hurtful territory (racism, real personal attacks, etc.)
- Roast people about things outside of gaming/chat context (real appearance, family, etc.)
- Fall back on the same template over and over (e.g., "Real ___ energy", "You're the reason ___")
- Roast people about things outside of gaming/chat context (real appearance, family, etc.)

View File

@@ -90,36 +90,6 @@ ANALYSIS_TOOL = {
"type": ["string", "null"],
"description": "The game channel name this message is about (e.g. 'gta-online', 'warzone'), or null if not game-specific.",
},
"disagreement_detected": {
"type": "boolean",
"description": "True if the target message is part of a clear disagreement between two users in the recent context. Only flag genuine back-and-forth debates, not one-off opinions.",
},
"disagreement_summary": {
"type": ["object", "null"],
"description": "If disagreement_detected is true, summarize the disagreement. Null otherwise.",
"properties": {
"topic": {
"type": "string",
"description": "Short topic of the disagreement (max 60 chars, e.g. 'Are snipers OP in Warzone?').",
},
"side_a": {
"type": "string",
"description": "First user's position (max 50 chars, e.g. 'Snipers are overpowered').",
},
"side_b": {
"type": "string",
"description": "Second user's position (max 50 chars, e.g. 'Snipers are balanced').",
},
"user_a": {
"type": "string",
"description": "Display name of the first user.",
},
"user_b": {
"type": "string",
"description": "Display name of the second user.",
},
},
},
},
"required": ["toxicity_score", "categories", "reasoning", "off_topic", "topic_category", "topic_reasoning", "coherence_score", "coherence_flag"],
},
@@ -249,19 +219,6 @@ class LLMClient:
result.setdefault("note_update", None)
result.setdefault("detected_game", None)
result["disagreement_detected"] = bool(result.get("disagreement_detected", False))
summary = result.get("disagreement_summary")
if result["disagreement_detected"] and isinstance(summary, dict):
# Truncate fields to Discord poll limits
summary["topic"] = str(summary.get("topic", ""))[:60]
summary["side_a"] = str(summary.get("side_a", ""))[:50]
summary["side_b"] = str(summary.get("side_b", ""))[:50]
summary.setdefault("user_a", "")
summary.setdefault("user_b", "")
result["disagreement_summary"] = summary
else:
result["disagreement_summary"] = None
return result
def _parse_content_fallback(self, text: str) -> dict | None: