调整自动回复逻辑
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import re
|
import re
|
||||||
from datetime import datetime, time
|
from datetime import datetime, time, timedelta
|
||||||
import toml
|
import toml
|
||||||
import os
|
import os
|
||||||
|
|
||||||
@@ -10,31 +10,40 @@ class InterventionBot:
|
|||||||
self.config = {}
|
self.config = {}
|
||||||
if config_path and os.path.exists(config_path):
|
if config_path and os.path.exists(config_path):
|
||||||
self.config = toml.load(config_path)
|
self.config = toml.load(config_path)
|
||||||
|
|
||||||
# 从配置中获取关键词
|
# 从配置中获取关键词和阈值
|
||||||
keywords = self.config.get("Keywords", {})
|
keywords = self.config.get("Keywords", {})
|
||||||
time_window = self.config.get("TimeWindow", {})
|
time_window = self.config.get("TimeWindow", {})
|
||||||
|
reply_threshold = self.config.get("ReplyThreshold", {})
|
||||||
|
|
||||||
# 表情符号库
|
# 表情符号库
|
||||||
self.emojis = keywords.get("emojis", ["[捂脸]", "[奸笑]", "[可怜]", "[擦汗]", "[发呆]", "[抠鼻]", "[破涕为笑]", "[旺柴]"])
|
self.emojis = keywords.get("emojis",
|
||||||
|
["[捂脸]", "[奸笑]", "[可怜]", "[擦汗]", "[发呆]", "[抠鼻]", "[破涕为笑]", "[旺柴]"])
|
||||||
# 话题关键词
|
# 话题关键词
|
||||||
self.hot_topics = keywords.get("hot_topics", ["咖啡", "手机", "小米", "华为", "苹果", "价格", "流畅", "螺蛳粉", "外卖"])
|
self.hot_topics = keywords.get("hot_topics",
|
||||||
self.fish_keywords = keywords.get("fish_keywords", ["鱼缸", "鱼便", "红边", "造浪", "养鱼", "进货", "鳑鲏", "吸鳅"])
|
["咖啡", "手机", "小米", "华为", "苹果", "价格", "流畅", "螺蛳粉", "外卖"])
|
||||||
self.tech_keywords = keywords.get("tech_keywords", ["MIUI", "鸿蒙", "iPhone", "安卓", "推送", "充电", "屏幕", "电池"])
|
self.fish_keywords = keywords.get("fish_keywords",
|
||||||
self.mechanism_keywords = keywords.get("mechanism_keywords", ["积分", "AI ", "功能列表", "黑丝", "打劫", "指令"])
|
["鱼缸", "鱼便", "红边", "造浪", "养鱼", "进货", "鳑鲏", "吸鳅"])
|
||||||
|
self.tech_keywords = keywords.get("tech_keywords",
|
||||||
|
["MIUI", "鸿蒙", "iPhone", "安卓", "推送", "充电", "屏幕", "电池"])
|
||||||
|
self.mechanism_keywords = keywords.get("mechanism_keywords",
|
||||||
|
["积分", "AI ", "功能列表", "黑丝", "打劫", "指令"])
|
||||||
self.news_keywords = keywords.get("news_keywords", ["新闻", "骨灰房", "法院", "判决", "住建局"])
|
self.news_keywords = keywords.get("news_keywords", ["新闻", "骨灰房", "法院", "判决", "住建局"])
|
||||||
|
|
||||||
# 早晨签到时间窗口
|
# 早晨签到时间窗口
|
||||||
morning_start_hour = time_window.get("morning_start_hour", 8)
|
morning_start_hour = time_window.get("morning_start_hour", 8)
|
||||||
morning_start_minute = time_window.get("morning_start_minute", 0)
|
morning_start_minute = time_window.get("morning_start_minute", 0)
|
||||||
morning_end_hour = time_window.get("morning_end_hour", 8)
|
morning_end_hour = time_window.get("morning_end_hour", 8)
|
||||||
morning_end_minute = time_window.get("morning_end_minute", 30)
|
morning_end_minute = time_window.get("morning_end_minute", 30)
|
||||||
|
|
||||||
self.morning_window = (
|
self.morning_window = (
|
||||||
time(morning_start_hour, morning_start_minute),
|
time(morning_start_hour, morning_start_minute),
|
||||||
time(morning_end_hour, morning_end_minute)
|
time(morning_end_hour, morning_end_minute)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 回复阈值配置
|
||||||
|
self.messages_per_minute_threshold = reply_threshold.get("messages_per_minute_threshold", 3)
|
||||||
|
self.analysis_window_minutes = reply_threshold.get("analysis_window_minutes", 5)
|
||||||
|
|
||||||
def is_morning_window(self, timestamp):
|
def is_morning_window(self, timestamp):
|
||||||
"""检查是否在早晨签到时间窗口"""
|
"""检查是否在早晨签到时间窗口"""
|
||||||
try:
|
try:
|
||||||
@@ -45,6 +54,8 @@ class InterventionBot:
|
|||||||
|
|
||||||
def detect_topic(self, message):
|
def detect_topic(self, message):
|
||||||
"""检测消息所属话题类型"""
|
"""检测消息所属话题类型"""
|
||||||
|
if not isinstance(message, str):
|
||||||
|
return None
|
||||||
message_lower = message.lower()
|
message_lower = message.lower()
|
||||||
if any(keyword in message_lower for keyword in self.fish_keywords):
|
if any(keyword in message_lower for keyword in self.fish_keywords):
|
||||||
return "fish"
|
return "fish"
|
||||||
@@ -88,7 +99,40 @@ class InterventionBot:
|
|||||||
"""规则7:猎奇或社会新闻反应"""
|
"""规则7:猎奇或社会新闻反应"""
|
||||||
return self.detect_topic(message) == "news"
|
return self.detect_topic(message) == "news"
|
||||||
|
|
||||||
def should_intervene(self, timestamp, message, messages):
|
def rule_high_reply_rate(self, timestamp, chat_log):
|
||||||
|
"""规则8:高回复频率(每分钟消息数超过阈值)"""
|
||||||
|
try:
|
||||||
|
# 解析当前时间
|
||||||
|
current_time = datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S")
|
||||||
|
window_start = current_time - timedelta(minutes=self.analysis_window_minutes)
|
||||||
|
|
||||||
|
# 计算时间窗口内的消息数
|
||||||
|
recent_messages = []
|
||||||
|
for msg in chat_log:
|
||||||
|
try:
|
||||||
|
msg_time = datetime.strptime(msg["timestamp"], "%Y-%m-%d %H:%M:%S")
|
||||||
|
if window_start <= msg_time <= current_time:
|
||||||
|
recent_messages.append(msg)
|
||||||
|
except (ValueError, KeyError, TypeError):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 如果消息太少,不触发
|
||||||
|
if len(recent_messages) < self.messages_per_minute_threshold:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 计算消息频率
|
||||||
|
messages_per_minute = len(recent_messages) / self.analysis_window_minutes
|
||||||
|
|
||||||
|
# 记录日志,便于调试
|
||||||
|
if messages_per_minute >= self.messages_per_minute_threshold:
|
||||||
|
print(f"[高频率检测] 当前消息频率: {messages_per_minute:.2f}/分钟,阈值: {self.messages_per_minute_threshold}/分钟")
|
||||||
|
|
||||||
|
return messages_per_minute >= self.messages_per_minute_threshold
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[高频率检测] 错误: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def should_intervene(self, timestamp, message, messages, chat_log):
|
||||||
"""判断是否需要介入"""
|
"""判断是否需要介入"""
|
||||||
rules = [
|
rules = [
|
||||||
self.rule_morning_signin,
|
self.rule_morning_signin,
|
||||||
@@ -97,20 +141,24 @@ class InterventionBot:
|
|||||||
self.rule_fish_discussion,
|
self.rule_fish_discussion,
|
||||||
self.rule_mechanism_interaction,
|
self.rule_mechanism_interaction,
|
||||||
self.rule_humor_tease,
|
self.rule_humor_tease,
|
||||||
self.rule_news_reaction
|
self.rule_news_reaction,
|
||||||
|
self.rule_high_reply_rate
|
||||||
]
|
]
|
||||||
|
|
||||||
for rule in rules:
|
for rule in rules:
|
||||||
if rule == self.rule_morning_signin:
|
if rule == self.rule_morning_signin:
|
||||||
if rule(timestamp, messages):
|
if rule(timestamp, messages):
|
||||||
return True
|
return True
|
||||||
|
elif rule == self.rule_high_reply_rate:
|
||||||
|
if rule(timestamp, chat_log):
|
||||||
|
return True
|
||||||
elif rule(message, messages):
|
elif rule(message, messages):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def process_message(self, timestamp, message, messages):
|
def process_message(self, timestamp, message, messages, chat_log):
|
||||||
"""处理单条消息,返回介入状态"""
|
"""处理单条消息,返回介入状态"""
|
||||||
if self.should_intervene(timestamp, message, messages):
|
if self.should_intervene(timestamp, message, messages, chat_log):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -122,7 +170,7 @@ class InterventionBot:
|
|||||||
for i, line in enumerate(chat_log):
|
for i, line in enumerate(chat_log):
|
||||||
timestamp = line["timestamp"]
|
timestamp = line["timestamp"]
|
||||||
message = line["message"]
|
message = line["message"]
|
||||||
intervention = self.process_message(timestamp, message, messages[:i + 1])
|
intervention = self.process_message(timestamp, message, messages[:i + 1], chat_log)
|
||||||
results.append({
|
results.append({
|
||||||
"timestamp": timestamp,
|
"timestamp": timestamp,
|
||||||
"message": message,
|
"message": message,
|
||||||
|
|||||||
@@ -18,4 +18,10 @@ news_keywords = ["新闻", "骨灰房", "法院", "判决", "住建局"]
|
|||||||
morning_start_hour = 8
|
morning_start_hour = 8
|
||||||
morning_start_minute = 0
|
morning_start_minute = 0
|
||||||
morning_end_hour = 8
|
morning_end_hour = 8
|
||||||
morning_end_minute = 30
|
morning_end_minute = 30
|
||||||
|
|
||||||
|
[ReplyThreshold]
|
||||||
|
# 每分钟消息数阈值,超过此值将触发AI介入
|
||||||
|
messages_per_minute_threshold = 3
|
||||||
|
# 分析窗口大小(分钟)
|
||||||
|
analysis_window_minutes = 5
|
||||||
@@ -61,12 +61,12 @@ class AIAutoResponsePlugin(MessagePluginInterface):
|
|||||||
|
|
||||||
# 加载配置
|
# 加载配置
|
||||||
config_path = os.path.join(os.path.dirname(__file__), "config.toml")
|
config_path = os.path.join(os.path.dirname(__file__), "config.toml")
|
||||||
self.enable = self._config.get("AIAutoResponse", {}).get("enable", True)
|
self.enable = self._config.get("enable", True)
|
||||||
|
self._commands = ["ai介入", "ai对话", "ai自动回复"]
|
||||||
|
|
||||||
# 从配置中获取DIFY API密钥
|
# 从配置中获取DIFY API密钥
|
||||||
self.dify_api_key = self._config.get("AIAutoResponse", {}).get("dify_api_key", "")
|
self.dify_api_key = self._config.get("dify_api_key", "")
|
||||||
self.dify_api_url = self._config.get("AIAutoResponse", {}).get("dify_api_url",
|
self.dify_api_url = self._config.get("dify_api_url", "http://192.168.2.240/v1/chat-messages")
|
||||||
"http://192.168.2.240/v1/chat-messages")
|
|
||||||
|
|
||||||
# 初始化介入机器人
|
# 初始化介入机器人
|
||||||
self.intervention_bot = InterventionBot(config_path)
|
self.intervention_bot = InterventionBot(config_path)
|
||||||
@@ -103,11 +103,14 @@ class AIAutoResponsePlugin(MessagePluginInterface):
|
|||||||
self.group_messages[roomid] = []
|
self.group_messages[roomid] = []
|
||||||
|
|
||||||
# 添加新消息
|
# 添加新消息
|
||||||
self.group_messages[roomid].append({
|
current_message = {
|
||||||
"timestamp": message.get("timestamp", ""),
|
"timestamp": message.get("timestamp", ""),
|
||||||
"message": content,
|
"message": content,
|
||||||
"sender": message.get("sender", "")
|
"sender": message.get("sender", "")
|
||||||
})
|
}
|
||||||
|
|
||||||
|
# 添加新消息
|
||||||
|
self.group_messages[roomid].append(current_message)
|
||||||
|
|
||||||
# 限制消息数量
|
# 限制消息数量
|
||||||
if len(self.group_messages[roomid]) > self.max_messages:
|
if len(self.group_messages[roomid]) > self.max_messages:
|
||||||
@@ -117,7 +120,8 @@ class AIAutoResponsePlugin(MessagePluginInterface):
|
|||||||
messages = [msg["message"] for msg in self.group_messages[roomid]]
|
messages = [msg["message"] for msg in self.group_messages[roomid]]
|
||||||
timestamp = message.get("timestamp", "")
|
timestamp = message.get("timestamp", "")
|
||||||
|
|
||||||
return self.intervention_bot.should_intervene(timestamp, content, messages)
|
# 传递完整的聊天记录给should_intervene方法
|
||||||
|
return self.intervention_bot.should_intervene(timestamp, content, messages, self.group_messages[roomid])
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -136,6 +140,10 @@ class AIAutoResponsePlugin(MessagePluginInterface):
|
|||||||
# 获取最近的消息
|
# 获取最近的消息
|
||||||
messages = [msg["message"] for msg in self.group_messages[roomid]]
|
messages = [msg["message"] for msg in self.group_messages[roomid]]
|
||||||
timestamp = message.get("timestamp", "")
|
timestamp = message.get("timestamp", "")
|
||||||
|
|
||||||
|
# 记录触发原因
|
||||||
|
if self.intervention_bot.rule_high_reply_rate(timestamp, self.group_messages[roomid]):
|
||||||
|
self.LOG.info(f"[{roomid}] 触发高频率回复规则,准备生成回复")
|
||||||
|
|
||||||
# 生成回复
|
# 生成回复
|
||||||
response = self._generate_response_with_dify(content, messages)
|
response = self._generate_response_with_dify(content, messages)
|
||||||
@@ -143,6 +151,8 @@ class AIAutoResponsePlugin(MessagePluginInterface):
|
|||||||
# 发送回复
|
# 发送回复
|
||||||
await bot.send_text_message(roomid, response, sender)
|
await bot.send_text_message(roomid, response, sender)
|
||||||
return True, "自动回复成功"
|
return True, "自动回复成功"
|
||||||
|
else:
|
||||||
|
return False, "生成回复失败"
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.LOG.error(f"处理AI自动对话出错: {e}")
|
self.LOG.error(f"处理AI自动对话出错: {e}")
|
||||||
|
|||||||
Reference in New Issue
Block a user