Add auto-polls to settle disagreements between users
LLM analysis now detects when two users are in a genuine disagreement. When detected, the bot creates a native Discord poll with each user's position as an option. - Disagreement detection added to LLM analysis tool schema - Polls last 4 hours with 1 hour per-channel cooldown - LLM extracts topic, both positions, and usernames - Configurable via polls section in config.yaml Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -90,6 +90,36 @@ 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"],
|
||||
},
|
||||
@@ -213,6 +243,19 @@ 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:
|
||||
|
||||
Reference in New Issue
Block a user