riddle/wyr: fix quality issues from tonight's chat
riddle: - Tighten generation prompt with explicit rules: specific noun answer, no answer word in the riddle, no 'what could it possibly mean', clues must logically point to ONE answer, prefer concrete things - Fix answer matching: strip articles (a/an/the), allow partial match so 'person' hits 'a person' and 'shadow' hits 'my shadow' etc. wyr: - Prompt now asks for genuinely difficult dilemmas with real downsides on both sides; explicitly bans boring options like dolphins/karaoke Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+31
-8
@@ -1647,11 +1647,15 @@ def record_wyr_vote(event_id: str, sender: str, key: str) -> None:
|
|||||||
|
|
||||||
async def _generate_wyr() -> dict | None:
|
async def _generate_wyr() -> dict | None:
|
||||||
system_msg = (
|
system_msg = (
|
||||||
"You are a game host generating Would You Rather questions. "
|
"You are a game host generating Would You Rather questions for a group of adult friends. "
|
||||||
"Always respond with ONLY a JSON object — no markdown fences, no explanation. "
|
"Always respond with ONLY a JSON object — no markdown fences, no explanation. "
|
||||||
'Format: {"question": "Would you rather...", "option_a": "short option", "option_b": "short option"}'
|
'Format: {"question": "Would you rather...", "option_a": "short option", "option_b": "short option"}\n'
|
||||||
|
"Make the dilemma genuinely difficult — both options should have real downsides so it's actually a hard choice. "
|
||||||
|
"Be creative and edgy: embarrassing scenarios, weird superpowers, social nightmares, gross but survivable situations, "
|
||||||
|
"impossible tradeoffs. Avoid boring safe options like 'dance with dolphins' or 'sing karaoke'. "
|
||||||
|
"Keep each option under 10 words."
|
||||||
)
|
)
|
||||||
user_msg = "Generate a fun, creative Would You Rather question. Keep each option under 10 words."
|
user_msg = "Generate a spicy, genuinely difficult Would You Rather question."
|
||||||
try:
|
try:
|
||||||
timeout = aiohttp.ClientTimeout(total=60)
|
timeout = aiohttp.ClientTimeout(total=60)
|
||||||
async with aiohttp.ClientSession(timeout=timeout) as session:
|
async with aiohttp.ClientSession(timeout=timeout) as session:
|
||||||
@@ -1774,9 +1778,16 @@ async def _generate_riddle() -> dict | None:
|
|||||||
) if _riddle_recent else ""
|
) if _riddle_recent else ""
|
||||||
system_msg = (
|
system_msg = (
|
||||||
"You are a riddle generator. Always respond with ONLY a JSON object — no markdown fences, no explanation. "
|
"You are a riddle generator. Always respond with ONLY a JSON object — no markdown fences, no explanation. "
|
||||||
'Format: {"riddle": "the riddle text", "answer": "short answer"}'
|
'Format: {"riddle": "the riddle text", "answer": "short answer"}\n'
|
||||||
|
"Rules for a good riddle:\n"
|
||||||
|
"- The answer must be a specific, unambiguous noun (1-3 words). Avoid abstract answers.\n"
|
||||||
|
"- The riddle must describe the answer through metaphor or wordplay — NOT by literally describing it.\n"
|
||||||
|
"- Do NOT include the answer word anywhere in the riddle text.\n"
|
||||||
|
"- Do NOT end the riddle with 'what am I?' or 'what could it possibly mean?' — the riddle should stand alone.\n"
|
||||||
|
"- The clues must logically point to ONE specific answer. Test it: would most people agree this answer is correct?\n"
|
||||||
|
"- Avoid riddles about riddles, shadows, or abstract concepts. Prefer concrete things: candle, mirror, clock, river, echo, stamp, etc."
|
||||||
)
|
)
|
||||||
user_msg = f"Generate a clever, original riddle. The answer should be 1-4 words.{avoid_clause}"
|
user_msg = f"Generate a clever, original riddle with a clear unambiguous answer.{avoid_clause}"
|
||||||
try:
|
try:
|
||||||
timeout = aiohttp.ClientTimeout(total=60)
|
timeout = aiohttp.ClientTimeout(total=60)
|
||||||
async with aiohttp.ClientSession(timeout=timeout) as session:
|
async with aiohttp.ClientSession(timeout=timeout) as session:
|
||||||
@@ -1856,14 +1867,26 @@ async def cmd_riddle(client: AsyncClient, room_id: str, sender: str, args: str):
|
|||||||
_RIDDLE_ACTIVE[room_id]["task"] = task
|
_RIDDLE_ACTIVE[room_id]["task"] = task
|
||||||
|
|
||||||
|
|
||||||
|
def _riddle_matches(answer: str, body: str) -> bool:
|
||||||
|
"""Fuzzy match: strip articles, allow the core word to appear in the guess or vice versa."""
|
||||||
|
def _normalize(s: str) -> str:
|
||||||
|
s = s.strip().lower()
|
||||||
|
for art in ("a ", "an ", "the "):
|
||||||
|
if s.startswith(art):
|
||||||
|
s = s[len(art):]
|
||||||
|
return s.strip()
|
||||||
|
|
||||||
|
ans = _normalize(answer)
|
||||||
|
guess = _normalize(body)
|
||||||
|
return ans == guess or ans in guess or guess in ans
|
||||||
|
|
||||||
|
|
||||||
async def check_riddle_answer(client: AsyncClient, room_id: str, sender: str, body: str) -> bool:
|
async def check_riddle_answer(client: AsyncClient, room_id: str, sender: str, body: str) -> bool:
|
||||||
"""Check if a room message answers the active riddle. Returns True if correct."""
|
"""Check if a room message answers the active riddle. Returns True if correct."""
|
||||||
if room_id not in _RIDDLE_ACTIVE:
|
if room_id not in _RIDDLE_ACTIVE:
|
||||||
return False
|
return False
|
||||||
game = _RIDDLE_ACTIVE[room_id]
|
game = _RIDDLE_ACTIVE[room_id]
|
||||||
answer_lower = game["answer"].lower()
|
if _riddle_matches(game["answer"], body.strip()):
|
||||||
body_lower = body.strip().lower()
|
|
||||||
if answer_lower in body_lower:
|
|
||||||
task = game.get("task")
|
task = game.get("task")
|
||||||
if task:
|
if task:
|
||||||
task.cancel()
|
task.cancel()
|
||||||
|
|||||||
Reference in New Issue
Block a user