diff --git a/matrixbot/commands.py b/matrixbot/commands.py index 35fe219..49410ee 100644 --- a/matrixbot/commands.py +++ b/matrixbot/commands.py @@ -1231,24 +1231,32 @@ def _hangman_display(game: dict) -> str: async def _generate_hangman_word() -> dict | None: - prompt = ( - "Generate a hangman word game. Pick a common English word between 5 and 8 letters. " - "Respond with ONLY valid JSON, no markdown: " - '{"word": "example", "hint": "a short category or hint about the word"}. ' - "The word must be all lowercase letters only, no spaces or hyphens." + system_msg = ( + "You are a hangman game generator. Always respond with ONLY a JSON object — no markdown, no explanation. " + 'Format: {"word": "example", "hint": "short category or hint"}' ) + user_msg = "Pick a common English word between 5 and 8 letters (lowercase letters only, no hyphens or spaces) and give a short hint." try: timeout = aiohttp.ClientTimeout(total=20) async with aiohttp.ClientSession(timeout=timeout) as session: async with session.post( - f"{OLLAMA_URL}/api/generate", - json={"model": ASK_MODEL, "prompt": prompt, "stream": False}, + f"{OLLAMA_URL}/api/chat", + json={ + "model": ASK_MODEL, + "stream": False, + "messages": [ + {"role": "system", "content": system_msg}, + {"role": "user", "content": user_msg}, + ], + }, ) as response: data = await response.json() - text = data.get("response", "").strip() - # Strip markdown fences + text = data.get("message", {}).get("content", "").strip() if "```" in text: - text = text.split("```")[1].lstrip("json").strip() + text = re.sub(r"```[a-z]*\n?", "", text).strip() + m = re.search(r"\{[^{}]+\}", text, re.DOTALL) + if m: + text = m.group(0) parsed = json.loads(text) word = parsed.get("word", "").lower().strip() hint = parsed.get("hint", "").strip() @@ -1430,23 +1438,32 @@ _SCRAMBLE_GAMES: dict[str, dict] = {} async def _generate_scramble_word() -> dict | None: - prompt = ( - "Pick a common English word between 4 and 8 letters. " - "Respond with ONLY valid JSON, no markdown: " - '{"word": "example"}. ' - "The word must be all lowercase letters only, no spaces or hyphens." + system_msg = ( + "You are a word game generator. Always respond with ONLY a JSON object — no markdown, no explanation. " + 'Format: {"word": "example"}' ) + user_msg = "Pick a common English word between 4 and 8 letters (lowercase letters only, no hyphens or spaces)." try: timeout = aiohttp.ClientTimeout(total=20) async with aiohttp.ClientSession(timeout=timeout) as session: async with session.post( - f"{OLLAMA_URL}/api/generate", - json={"model": ASK_MODEL, "prompt": prompt, "stream": False}, + f"{OLLAMA_URL}/api/chat", + json={ + "model": ASK_MODEL, + "stream": False, + "messages": [ + {"role": "system", "content": system_msg}, + {"role": "user", "content": user_msg}, + ], + }, ) as response: data = await response.json() - text = data.get("response", "").strip() + text = data.get("message", {}).get("content", "").strip() if "```" in text: - text = text.split("```")[1].lstrip("json").strip() + text = re.sub(r"```[a-z]*\n?", "", text).strip() + m = re.search(r"\{[^{}]+\}", text, re.DOTALL) + if m: + text = m.group(0) parsed = json.loads(text) word = parsed.get("word", "").lower().strip() if word.isalpha() and 4 <= len(word) <= 8: @@ -1641,23 +1658,32 @@ _RIDDLE_ACTIVE: dict[str, dict] = {} async def _generate_riddle() -> dict | None: - prompt = ( - "Generate a clever riddle and its answer. " - "Respond with ONLY valid JSON, no markdown: " - '{"riddle": "...", "answer": "..."}. ' - "The answer should be a short word or phrase (1-4 words). Make it interesting!" + system_msg = ( + "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"}' ) + user_msg = "Generate a clever riddle. The answer should be 1-4 words." try: timeout = aiohttp.ClientTimeout(total=20) async with aiohttp.ClientSession(timeout=timeout) as session: async with session.post( - f"{OLLAMA_URL}/api/generate", - json={"model": ASK_MODEL, "prompt": prompt, "stream": False}, + f"{OLLAMA_URL}/api/chat", + json={ + "model": ASK_MODEL, + "stream": False, + "messages": [ + {"role": "system", "content": system_msg}, + {"role": "user", "content": user_msg}, + ], + }, ) as response: data = await response.json() - text = data.get("response", "").strip() + text = data.get("message", {}).get("content", "").strip() if "```" in text: - text = text.split("```")[1].lstrip("json").strip() + text = re.sub(r"```[a-z]*\n?", "", text).strip() + m = re.search(r"\{[^{}]+\}", text, re.DOTALL) + if m: + text = m.group(0) parsed = json.loads(text) riddle = parsed.get("riddle", "").strip() answer = parsed.get("answer", "").strip()