refactor ai_auto_response into xiaoniu group bot

This commit is contained in:
liuwei
2026-04-07 11:15:29 +08:00
parent 1c052a7d16
commit d616846098
13 changed files with 2150 additions and 445 deletions

View File

@@ -0,0 +1,87 @@
from __future__ import annotations
import re
from dataclasses import dataclass, field
from typing import Dict, List
QUESTION_PATTERNS = [
r"\?$", r"$", r"怎么", r"如何", r"咋弄", r"为啥", r"为什么",
r"有人知道", r"谁知道", r"能不能", r"可以吗", r"报错", r"怎么解决",
]
SOCIAL_PATTERNS = [r"小牛", r"在吗", r"出来", r"帮忙看", r"看看"]
@dataclass
class TriggerResult:
trigger_type: str = "none"
priority: float = 0.0
is_question: bool = False
is_followup: bool = False
is_social_call: bool = False
is_returning_member: bool = False
should_respond: bool = False
topic: str = ""
reasons: List[str] = field(default_factory=list)
class TriggerRouter:
def __init__(self, config: Dict):
self.config = config or {}
self.topic_keywords = [str(item).lower() for item in self.config.get("focus", [])]
def route(self, message: Dict, memory_hints: Dict) -> TriggerResult:
content = str(message.get("content", "")).strip()
content_lower = content.lower()
result = TriggerResult()
if message.get("is_at"):
result.trigger_type = "at_trigger"
result.priority = float(self.config.get("at_bot", 1.0))
result.should_respond = True
result.reasons.append("is_at")
if self._is_question(content):
if result.priority < float(self.config.get("explicit_question", 0.95)):
result.trigger_type = "question_trigger"
result.priority = float(self.config.get("explicit_question", 0.95))
result.is_question = True
result.should_respond = True
result.reasons.append("question")
if memory_hints.get("is_followup"):
if result.priority < float(self.config.get("followup", 0.90)):
result.trigger_type = "followup_trigger"
result.priority = float(self.config.get("followup", 0.90))
result.is_followup = True
result.should_respond = True
result.reasons.append("followup")
topic = self._detect_topic(content_lower)
if topic:
result.topic = topic
result.reasons.append("topic")
if result.priority < float(self.config.get("casual_topic", 0.35)):
result.trigger_type = result.trigger_type if result.trigger_type != "none" else "topic_trigger"
result.priority = max(result.priority, float(self.config.get("casual_topic", 0.35)))
if self._is_social_call(content_lower):
if result.priority < float(self.config.get("social_call", 0.65)):
result.trigger_type = result.trigger_type if result.trigger_type != "none" else "social_trigger"
result.priority = max(result.priority, float(self.config.get("social_call", 0.65)))
result.is_social_call = True
result.reasons.append("social_call")
if memory_hints.get("returning_member_state") in {"returning_member", "long_absent_member"}:
result.is_returning_member = True
result.reasons.append(memory_hints.get("returning_member_state"))
if result.trigger_type == "none":
result.trigger_type = "returning_member"
result.priority = max(result.priority, float(self.config.get("casual_topic", 0.35)))
return result
def _is_question(self, content: str) -> bool:
return any(re.search(pattern, content, flags=re.IGNORECASE) for pattern in QUESTION_PATTERNS)
def _is_social_call(self, content: str) -> bool:
return any(re.search(pattern, content, flags=re.IGNORECASE) for pattern in SOCIAL_PATTERNS)
def _detect_topic(self, content_lower: str) -> str:
for keyword in self.topic_keywords:
if keyword and keyword in content_lower:
return keyword
return ""