From 144475d2f4231374ac31c7e24207840f75dc0770 Mon Sep 17 00:00:00 2001 From: Pocketfans Date: Wed, 12 Mar 2025 17:57:50 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E8=AE=A9=E5=9B=9E=E5=A4=8D=E6=84=8F?= =?UTF-8?q?=E6=84=BF=E6=9B=B4=E5=8A=A0=E6=8B=9F=E4=BA=BA=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E9=AB=98=E4=BD=8E=E5=9B=9E=E5=A4=8D=E6=84=8F=E6=84=BF?= =?UTF-8?q?=E5=91=A8=E6=9C=9F=EF=BC=8C=E4=B8=94=E5=A2=9E=E5=8A=A0=E4=BA=86?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E7=AE=80=E5=8D=95=E7=9A=84=E8=BF=BD=E9=97=AE?= =?UTF-8?q?=E5=9B=9E=E5=A4=8D=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/chat/bot.py | 10 +- src/plugins/chat/willing_manager.py | 256 ++++++++++++++++++++++------ 2 files changed, 209 insertions(+), 57 deletions(-) diff --git a/src/plugins/chat/bot.py b/src/plugins/chat/bot.py index 1db38477c..5002cb162 100644 --- a/src/plugins/chat/bot.py +++ b/src/plugins/chat/bot.py @@ -135,7 +135,7 @@ class ChatBot: for pattern in global_config.ban_msgs_regex: if re.search(pattern, message.raw_message): logger.info( - f"[{chat.group_info.group_name if chat.group_info.group_id else '私聊'}]{userinfo.user_nickname}:{message.raw_message}" + f"[{chat.group_info.group_name if chat.group_info.group_id else '私聊'}]{message.user_nickname}:{message.raw_message}" ) logger.info(f"[正则表达式过滤]消息匹配到{pattern},filtered") return @@ -159,6 +159,7 @@ class ChatBot: config=global_config, is_emoji=message.is_emoji, interested_rate=interested_rate, + sender_id=str(message.message_info.user_info.user_id), ) current_willing = willing_manager.get_willing(chat_stream=chat) @@ -189,6 +190,9 @@ class ChatBot: willing_manager.change_reply_willing_sent(chat) response, raw_content = await self.gpt.generate_response(message) + else: + # 决定不回复时,也更新回复意愿 + willing_manager.change_reply_willing_not_sent(chat) # print(f"response: {response}") if response: @@ -235,10 +239,10 @@ class ChatBot: is_head=not mark_head, is_emoji=False, ) - logger.debug(f"bot_message: {bot_message}") + print(f"bot_message: {bot_message}") if not mark_head: mark_head = True - logger.debug(f"添加消息到message_set: {bot_message}") + print(f"添加消息到message_set: {bot_message}") message_set.add_message(bot_message) # message_set 可以直接加入 message_manager diff --git a/src/plugins/chat/willing_manager.py b/src/plugins/chat/willing_manager.py index 773d40c6e..81a4fe62a 100644 --- a/src/plugins/chat/willing_manager.py +++ b/src/plugins/chat/willing_manager.py @@ -1,109 +1,257 @@ import asyncio +import random +import time from typing import Dict from .config import global_config from .chat_stream import ChatStream -from loguru import logger - class WillingManager: def __init__(self): self.chat_reply_willing: Dict[str, float] = {} # 存储每个聊天流的回复意愿 + self.chat_high_willing_mode: Dict[str, bool] = {} # 存储每个聊天流是否处于高回复意愿期 + self.chat_msg_count: Dict[str, int] = {} # 存储每个聊天流接收到的消息数量 + self.chat_last_mode_change: Dict[str, float] = {} # 存储每个聊天流上次模式切换的时间 + self.chat_high_willing_duration: Dict[str, int] = {} # 高意愿期持续时间(秒) + self.chat_low_willing_duration: Dict[str, int] = {} # 低意愿期持续时间(秒) + self.chat_last_reply_time: Dict[str, float] = {} # 存储每个聊天流上次回复的时间 + self.chat_last_sender_id: Dict[str, str] = {} # 存储每个聊天流上次回复的用户ID + self.chat_conversation_context: Dict[str, bool] = {} # 标记是否处于对话上下文中 self._decay_task = None + self._mode_switch_task = None self._started = False - + async def _decay_reply_willing(self): """定期衰减回复意愿""" while True: await asyncio.sleep(5) - for chat_id in self.chat_reply_willing: - self.chat_reply_willing[chat_id] = max(0, self.chat_reply_willing[chat_id] * 0.6) - + for chat_id in list(self.chat_reply_willing.keys()): + is_high_mode = self.chat_high_willing_mode.get(chat_id, False) + if is_high_mode: + # 高回复意愿期内轻微衰减 + self.chat_reply_willing[chat_id] = max(0.5, self.chat_reply_willing[chat_id] * 0.95) + else: + # 低回复意愿期内正常衰减 + self.chat_reply_willing[chat_id] = max(0, self.chat_reply_willing[chat_id] * 0.8) + + async def _mode_switch_check(self): + """定期检查是否需要切换回复意愿模式""" + while True: + current_time = time.time() + await asyncio.sleep(10) # 每10秒检查一次 + + for chat_id in list(self.chat_high_willing_mode.keys()): + last_change_time = self.chat_last_mode_change.get(chat_id, 0) + is_high_mode = self.chat_high_willing_mode.get(chat_id, False) + + # 获取当前模式的持续时间 + duration = 0 + if is_high_mode: + duration = self.chat_high_willing_duration.get(chat_id, 180) # 默认3分钟 + else: + duration = self.chat_low_willing_duration.get(chat_id, random.randint(300, 1200)) # 默认5-20分钟 + + # 检查是否需要切换模式 + if current_time - last_change_time > duration: + self._switch_willing_mode(chat_id) + elif not is_high_mode and random.random() < 0.1: + # 低回复意愿期有10%概率随机切换到高回复期 + self._switch_willing_mode(chat_id) + + # 检查对话上下文状态是否需要重置 + last_reply_time = self.chat_last_reply_time.get(chat_id, 0) + if current_time - last_reply_time > 300: # 5分钟无交互,重置对话上下文 + self.chat_conversation_context[chat_id] = False + + def _switch_willing_mode(self, chat_id: str): + """切换聊天流的回复意愿模式""" + is_high_mode = self.chat_high_willing_mode.get(chat_id, False) + + if is_high_mode: + # 从高回复期切换到低回复期 + self.chat_high_willing_mode[chat_id] = False + self.chat_reply_willing[chat_id] = 0.1 # 设置为最低回复意愿 + self.chat_low_willing_duration[chat_id] = random.randint(600, 1200) # 10-20分钟 + print(f"聊天流 {chat_id} 切换到低回复意愿期,持续 {self.chat_low_willing_duration[chat_id]} 秒") + else: + # 从低回复期切换到高回复期 + self.chat_high_willing_mode[chat_id] = True + self.chat_reply_willing[chat_id] = 1.0 # 设置为较高回复意愿 + self.chat_high_willing_duration[chat_id] = random.randint(180, 240) # 3-4分钟 + print(f"聊天流 {chat_id} 切换到高回复意愿期,持续 {self.chat_high_willing_duration[chat_id]} 秒") + + self.chat_last_mode_change[chat_id] = time.time() + self.chat_msg_count[chat_id] = 0 # 重置消息计数 + def get_willing(self, chat_stream: ChatStream) -> float: """获取指定聊天流的回复意愿""" stream = chat_stream if stream: return self.chat_reply_willing.get(stream.stream_id, 0) return 0 - + def set_willing(self, chat_id: str, willing: float): """设置指定聊天流的回复意愿""" self.chat_reply_willing[chat_id] = willing - - async def change_reply_willing_received( - self, - chat_stream: ChatStream, - topic: str = None, - is_mentioned_bot: bool = False, - config=None, - is_emoji: bool = False, - interested_rate: float = 0, - ) -> float: + + def _ensure_chat_initialized(self, chat_id: str): + """确保聊天流的所有数据已初始化""" + if chat_id not in self.chat_reply_willing: + self.chat_reply_willing[chat_id] = 0.1 + + if chat_id not in self.chat_high_willing_mode: + self.chat_high_willing_mode[chat_id] = False + self.chat_last_mode_change[chat_id] = time.time() + self.chat_low_willing_duration[chat_id] = random.randint(300, 1200) # 5-20分钟 + + if chat_id not in self.chat_msg_count: + self.chat_msg_count[chat_id] = 0 + + if chat_id not in self.chat_conversation_context: + self.chat_conversation_context[chat_id] = False + + async def change_reply_willing_received(self, + chat_stream: ChatStream, + topic: str = None, + is_mentioned_bot: bool = False, + config = None, + is_emoji: bool = False, + interested_rate: float = 0, + sender_id: str = None) -> float: """改变指定聊天流的回复意愿并返回回复概率""" # 获取或创建聊天流 stream = chat_stream chat_id = stream.stream_id - + current_time = time.time() + + self._ensure_chat_initialized(chat_id) + + # 增加消息计数 + self.chat_msg_count[chat_id] = self.chat_msg_count.get(chat_id, 0) + 1 + current_willing = self.chat_reply_willing.get(chat_id, 0) - - if is_mentioned_bot and current_willing < 1.0: - current_willing += 0.9 - logger.debug(f"被提及, 当前意愿: {current_willing}") - elif is_mentioned_bot: - current_willing += 0.05 - logger.debug(f"被重复提及, 当前意愿: {current_willing}") - + is_high_mode = self.chat_high_willing_mode.get(chat_id, False) + msg_count = self.chat_msg_count.get(chat_id, 0) + in_conversation_context = self.chat_conversation_context.get(chat_id, False) + + # 检查是否是对话上下文中的追问 + last_reply_time = self.chat_last_reply_time.get(chat_id, 0) + last_sender = self.chat_last_sender_id.get(chat_id, "") + is_follow_up_question = False + + # 如果是同一个人在短时间内(2分钟内)发送消息,且消息数量较少(<=5条),视为追问 + if sender_id and sender_id == last_sender and current_time - last_reply_time < 120 and msg_count <= 5: + is_follow_up_question = True + in_conversation_context = True + self.chat_conversation_context[chat_id] = True + print(f"检测到追问 (同一用户), 提高回复意愿") + current_willing += 0.3 + + # 特殊情况处理 + if is_mentioned_bot: + current_willing += 0.3 + in_conversation_context = True + self.chat_conversation_context[chat_id] = True + print(f"被提及, 当前意愿: {current_willing}") + if is_emoji: current_willing *= 0.1 - logger.debug(f"表情包, 当前意愿: {current_willing}") - - logger.debug(f"放大系数_interested_rate: {global_config.response_interested_rate_amplifier}") - interested_rate *= global_config.response_interested_rate_amplifier # 放大回复兴趣度 - if interested_rate > 0.4: - # print(f"兴趣度: {interested_rate}, 当前意愿: {current_willing}") - current_willing += interested_rate - 0.4 - - current_willing *= global_config.response_willing_amplifier # 放大回复意愿 - # print(f"放大系数_willing: {global_config.response_willing_amplifier}, 当前意愿: {current_willing}") - - reply_probability = max((current_willing - 0.45) * 2, 0) - + print(f"表情包, 当前意愿: {current_willing}") + + # 根据话题兴趣度适当调整 + if interested_rate > 0.5: + current_willing += (interested_rate - 0.5) * 0.5 + + # 根据当前模式计算回复概率 + base_probability = 0.0 + + if in_conversation_context: + # 在对话上下文中,提高基础回复概率 + base_probability = 0.75 if is_high_mode else 0.5 + print(f"处于对话上下文中,基础回复概率: {base_probability}") + elif is_high_mode: + # 高回复周期:4-8句话有65%的概率会回复一次 + base_probability = 0.65 if 4 <= msg_count <= 8 else 0.3 + else: + # 低回复周期:需要最少15句才有50%的概率会回一句 + base_probability = 0.5 if msg_count >= 15 else 0.05 * min(msg_count, 10) + + # 考虑回复意愿的影响 + reply_probability = base_probability * current_willing + # 检查群组权限(如果是群聊) - if chat_stream.group_info: + if chat_stream.group_info and config: if chat_stream.group_info.group_id in config.talk_frequency_down_groups: reply_probability = reply_probability / global_config.down_frequency_rate reply_probability = min(reply_probability, 1) if reply_probability < 0: reply_probability = 0 - + + # 记录当前发送者ID以便后续追踪 + if sender_id: + self.chat_last_sender_id[chat_id] = sender_id + self.chat_reply_willing[chat_id] = min(current_willing, 3.0) return reply_probability - + def change_reply_willing_sent(self, chat_stream: ChatStream): """开始思考后降低聊天流的回复意愿""" stream = chat_stream if stream: - current_willing = self.chat_reply_willing.get(stream.stream_id, 0) - self.chat_reply_willing[stream.stream_id] = max(0, current_willing - 2) - - def change_reply_willing_after_sent(self, chat_stream: ChatStream): - """发送消息后提高聊天流的回复意愿""" + chat_id = stream.stream_id + self._ensure_chat_initialized(chat_id) + is_high_mode = self.chat_high_willing_mode.get(chat_id, False) + current_willing = self.chat_reply_willing.get(chat_id, 0) + + # 回复后减少回复意愿 + self.chat_reply_willing[chat_id] = max(0, current_willing - 0.3) + + # 标记为对话上下文中 + self.chat_conversation_context[chat_id] = True + + # 记录最后回复时间 + self.chat_last_reply_time[chat_id] = time.time() + + # 重置消息计数 + self.chat_msg_count[chat_id] = 0 + + def change_reply_willing_not_sent(self, chat_stream: ChatStream): + """决定不回复后提高聊天流的回复意愿""" stream = chat_stream if stream: - current_willing = self.chat_reply_willing.get(stream.stream_id, 0) - if current_willing < 1: - self.chat_reply_willing[stream.stream_id] = min(1, current_willing + 0.2) - + chat_id = stream.stream_id + self._ensure_chat_initialized(chat_id) + is_high_mode = self.chat_high_willing_mode.get(chat_id, False) + current_willing = self.chat_reply_willing.get(chat_id, 0) + in_conversation_context = self.chat_conversation_context.get(chat_id, False) + + # 根据当前模式调整不回复后的意愿增加 + if is_high_mode: + willing_increase = 0.1 + elif in_conversation_context: + # 在对话上下文中但决定不回复,小幅增加回复意愿 + willing_increase = 0.15 + else: + willing_increase = random.uniform(0.05, 0.1) + + self.chat_reply_willing[chat_id] = min(2.0, current_willing + willing_increase) + + def change_reply_willing_after_sent(self, chat_stream: ChatStream): + """发送消息后提高聊天流的回复意愿""" + # 由于已经在sent中处理,这个方法保留但不再需要额外调整 + pass + async def ensure_started(self): - """确保衰减任务已启动""" + """确保所有任务已启动""" if not self._started: if self._decay_task is None: self._decay_task = asyncio.create_task(self._decay_reply_willing()) + if self._mode_switch_task is None: + self._mode_switch_task = asyncio.create_task(self._mode_switch_check()) self._started = True - # 创建全局实例 -willing_manager = WillingManager() +willing_manager = WillingManager() \ No newline at end of file From e50c73932b0e0ae08d4cff1c4ba5477180dac6f9 Mon Sep 17 00:00:00 2001 From: Pocketfans Date: Wed, 12 Mar 2025 18:27:04 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E9=99=8D=E4=BD=8E=E4=B9=8B=E5=89=8D?= =?UTF-8?q?=E5=9B=9E=E5=A4=8D=E7=9A=84=E9=80=9F=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/chat/willing_manager.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/plugins/chat/willing_manager.py b/src/plugins/chat/willing_manager.py index 81a4fe62a..9754848c4 100644 --- a/src/plugins/chat/willing_manager.py +++ b/src/plugins/chat/willing_manager.py @@ -151,7 +151,7 @@ class WillingManager: # 特殊情况处理 if is_mentioned_bot: - current_willing += 0.3 + current_willing += 0.5 in_conversation_context = True self.chat_conversation_context[chat_id] = True print(f"被提及, 当前意愿: {current_willing}") @@ -168,15 +168,15 @@ class WillingManager: base_probability = 0.0 if in_conversation_context: - # 在对话上下文中,提高基础回复概率 - base_probability = 0.75 if is_high_mode else 0.5 + # 在对话上下文中,降低基础回复概率 + base_probability = 0.5 if is_high_mode else 0.25 print(f"处于对话上下文中,基础回复概率: {base_probability}") elif is_high_mode: - # 高回复周期:4-8句话有65%的概率会回复一次 - base_probability = 0.65 if 4 <= msg_count <= 8 else 0.3 + # 高回复周期:4-8句话有50%的概率会回复一次 + base_probability = 0.50 if 4 <= msg_count <= 8 else 0.2 else: - # 低回复周期:需要最少15句才有50%的概率会回一句 - base_probability = 0.5 if msg_count >= 15 else 0.05 * min(msg_count, 10) + # 低回复周期:需要最少15句才有30%的概率会回一句 + base_probability = 0.30 if msg_count >= 15 else 0.03 * min(msg_count, 10) # 考虑回复意愿的影响 reply_probability = base_probability * current_willing @@ -186,7 +186,8 @@ class WillingManager: if chat_stream.group_info.group_id in config.talk_frequency_down_groups: reply_probability = reply_probability / global_config.down_frequency_rate - reply_probability = min(reply_probability, 1) + # 限制最大回复概率 + reply_probability = min(reply_probability, 0.75) # 设置最大回复概率为75% if reply_probability < 0: reply_probability = 0 From 8ee53fb312a793ab6f1fc4e7950a7d015eb900b7 Mon Sep 17 00:00:00 2001 From: HYY Date: Wed, 12 Mar 2025 22:01:05 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E4=B8=80=E5=A4=84?= =?UTF-8?q?=E5=B0=8Fbug=EF=BC=8C=E5=B9=B6=E4=B8=94=E6=8A=8Aprint=E6=94=B9?= =?UTF-8?q?=E4=B8=BAlogger=EF=BC=8C=E5=87=8F=E5=B0=91review=E8=A1=80?= =?UTF-8?q?=E5=8E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/chat/bot.py | 6 +++--- src/plugins/chat/willing_manager.py | 13 +++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/plugins/chat/bot.py b/src/plugins/chat/bot.py index 5002cb162..53266fccf 100644 --- a/src/plugins/chat/bot.py +++ b/src/plugins/chat/bot.py @@ -135,7 +135,7 @@ class ChatBot: for pattern in global_config.ban_msgs_regex: if re.search(pattern, message.raw_message): logger.info( - f"[{chat.group_info.group_name if chat.group_info.group_id else '私聊'}]{message.user_nickname}:{message.raw_message}" + f"[{chat.group_info.group_name if chat.group_info.group_id else '私聊'}]{userinfo.user_nickname}:{message.raw_message}" ) logger.info(f"[正则表达式过滤]消息匹配到{pattern},filtered") return @@ -239,10 +239,10 @@ class ChatBot: is_head=not mark_head, is_emoji=False, ) - print(f"bot_message: {bot_message}") + logger.debug(f"bot_message: {bot_message}") if not mark_head: mark_head = True - print(f"添加消息到message_set: {bot_message}") + logger.debug(f"添加消息到message_set: {bot_message}") message_set.add_message(bot_message) # message_set 可以直接加入 message_manager diff --git a/src/plugins/chat/willing_manager.py b/src/plugins/chat/willing_manager.py index 9754848c4..345461703 100644 --- a/src/plugins/chat/willing_manager.py +++ b/src/plugins/chat/willing_manager.py @@ -2,6 +2,7 @@ import asyncio import random import time from typing import Dict +from loguru import logger from .config import global_config @@ -27,7 +28,7 @@ class WillingManager: """定期衰减回复意愿""" while True: await asyncio.sleep(5) - for chat_id in list(self.chat_reply_willing.keys()): + for chat_id in self.chat_reply_willing: is_high_mode = self.chat_high_willing_mode.get(chat_id, False) if is_high_mode: # 高回复意愿期内轻微衰减 @@ -42,7 +43,7 @@ class WillingManager: current_time = time.time() await asyncio.sleep(10) # 每10秒检查一次 - for chat_id in list(self.chat_high_willing_mode.keys()): + for chat_id in self.chat_high_willing_mode: last_change_time = self.chat_last_mode_change.get(chat_id, 0) is_high_mode = self.chat_high_willing_mode.get(chat_id, False) @@ -146,7 +147,7 @@ class WillingManager: is_follow_up_question = True in_conversation_context = True self.chat_conversation_context[chat_id] = True - print(f"检测到追问 (同一用户), 提高回复意愿") + logger.debug(f"检测到追问 (同一用户), 提高回复意愿") current_willing += 0.3 # 特殊情况处理 @@ -154,11 +155,11 @@ class WillingManager: current_willing += 0.5 in_conversation_context = True self.chat_conversation_context[chat_id] = True - print(f"被提及, 当前意愿: {current_willing}") + logger.debug(f"被提及, 当前意愿: {current_willing}") if is_emoji: current_willing *= 0.1 - print(f"表情包, 当前意愿: {current_willing}") + logger.debug(f"表情包, 当前意愿: {current_willing}") # 根据话题兴趣度适当调整 if interested_rate > 0.5: @@ -170,7 +171,7 @@ class WillingManager: if in_conversation_context: # 在对话上下文中,降低基础回复概率 base_probability = 0.5 if is_high_mode else 0.25 - print(f"处于对话上下文中,基础回复概率: {base_probability}") + logger.debug(f"处于对话上下文中,基础回复概率: {base_probability}") elif is_high_mode: # 高回复周期:4-8句话有50%的概率会回复一次 base_probability = 0.50 if 4 <= msg_count <= 8 else 0.2 From 62810c7bc72c69bf1d97190b559a67ac7ccb1777 Mon Sep 17 00:00:00 2001 From: HYY Date: Wed, 12 Mar 2025 22:01:35 +0800 Subject: [PATCH 4/4] =?UTF-8?q?chore:logger=E6=9B=BF=E6=8D=A2print?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/chat/willing_manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/chat/willing_manager.py b/src/plugins/chat/willing_manager.py index 345461703..6df27f3a4 100644 --- a/src/plugins/chat/willing_manager.py +++ b/src/plugins/chat/willing_manager.py @@ -75,13 +75,13 @@ class WillingManager: self.chat_high_willing_mode[chat_id] = False self.chat_reply_willing[chat_id] = 0.1 # 设置为最低回复意愿 self.chat_low_willing_duration[chat_id] = random.randint(600, 1200) # 10-20分钟 - print(f"聊天流 {chat_id} 切换到低回复意愿期,持续 {self.chat_low_willing_duration[chat_id]} 秒") + logger.debug(f"聊天流 {chat_id} 切换到低回复意愿期,持续 {self.chat_low_willing_duration[chat_id]} 秒") else: # 从低回复期切换到高回复期 self.chat_high_willing_mode[chat_id] = True self.chat_reply_willing[chat_id] = 1.0 # 设置为较高回复意愿 self.chat_high_willing_duration[chat_id] = random.randint(180, 240) # 3-4分钟 - print(f"聊天流 {chat_id} 切换到高回复意愿期,持续 {self.chat_high_willing_duration[chat_id]} 秒") + logger.debug(f"聊天流 {chat_id} 切换到高回复意愿期,持续 {self.chat_high_willing_duration[chat_id]} 秒") self.chat_last_mode_change[chat_id] = time.time() self.chat_msg_count[chat_id] = 0 # 重置消息计数