import re def _name_mentioned(name: str, text: str) -> bool: """Cek apakah nama AI disebut dalam pesan (case-insensitive, word-boundary).""" text_lower = text.lower() name_lower = name.lower() pattern = r'\b' + re.escape(name_lower) + r'\b' return bool(re.search(pattern, text_lower)) def need_response(message: str, sender_nickname: str, recent_history: str, my_name: str) -> str: """ Decide whether the AI should respond to a message. Args: message: The latest message to evaluate. sender_nickname: Nickname of the sender. recent_history: Recent conversation history for context. my_name: The AI's name. Returns: "true" → should respond "false" → should stay silent Rules: 1. STRONG — Direct call/mention of AI's name → always True 2. BRIEF — Talks about AI in third person → True 3. CONTEXTUAL — Related to AI's previous conversation → True 4. NO REPLY — Unrelated, confusing, between other people → False """ msg = message.strip() # --- Rule 4: Empty message --- if not msg: return "false" # --- Rule 1: Direct mention/name call --- if _name_mentioned(my_name, msg): return "true" # --- Rule 2: Talks about AI (third person) --- name_parts = my_name.lower().split() text_lower = msg.lower() if any(part in text_lower for part in name_parts if len(part) > 1): return "true" # --- Rule 3: Contextual — check recent history --- if recent_history: return "true" # --- Rule 4: Default — no strong signal, stay silent --- return "false" def should_respond(message: str, sender_nickname: str, recent_history: str, my_name: str) -> bool: """ Python-side helper: return boolean directly. Used by XMPP client to gate whether to send the LLM's response. """ result = need_response(message, sender_nickname, recent_history, my_name) return result.strip().lower() == "true" schema_need_response = { "type": "function", "function": { "name": "need_response", "description": ( "Decide whether you should respond to the current message. " "Use this tool when you are unsure whether to reply or stay silent. " "Returns 'true' if you should respond, 'false' if you should stay silent. " "Rules: " "- Return 'true' if your name is mentioned or someone talks about you. " "- Return 'true' if the message is related to your previous conversation. " "- Return 'false' if the message is between other people, unclear, " "unrelated to you, or you have nothing to add." ), "parameters": { "type": "object", "properties": { "message": { "type": "string", "description": "The latest message to evaluate.", }, "sender_nickname": { "type": "string", "description": "The nickname of the person who sent the message.", }, "recent_history": { "type": "string", "description": "Recent conversation history for context (last few messages).", }, "my_name": { "type": "string", "description": "Your (the AI's) name.", }, }, "required": ["message", "sender_nickname", "recent_history", "my_name"], }, }, }