mirror of https://github.com/Mai-with-u/MaiBot.git
179 lines
7.9 KiB
Python
179 lines
7.9 KiB
Python
import asyncio
|
||
from typing import Dict
|
||
import datetime
|
||
|
||
|
||
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._decay_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)
|
||
|
||
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:
|
||
"""改变指定聊天流的回复意愿并返回回复概率"""
|
||
# 获取或创建聊天流
|
||
stream = chat_stream
|
||
chat_id = stream.stream_id
|
||
|
||
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}")
|
||
|
||
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}")
|
||
|
||
# 基于UTC时间调整回复意愿
|
||
if global_config.enable_utc_time_control:
|
||
current_utc_hour = datetime.datetime.utcnow().hour
|
||
|
||
# 查找当前时间所在的时间段
|
||
current_period = None
|
||
for period in global_config.time_periods:
|
||
start_hour = period["start_hour"]
|
||
end_hour = period["end_hour"]
|
||
|
||
# 检查当前时间是否在这个时间段内
|
||
if start_hour <= current_utc_hour < end_hour:
|
||
current_period = period
|
||
break
|
||
|
||
# 如果找到当前时间所在的时间段,应用相应的回复意愿调整
|
||
if current_period:
|
||
start_hour = current_period["start_hour"]
|
||
end_hour = current_period["end_hour"]
|
||
mode = current_period["mode"]
|
||
|
||
# 计算在时间段内的位置(0-1之间)
|
||
time_range = end_hour - start_hour
|
||
if time_range <= 0: # 处理跨夜的情况
|
||
time_range += 24
|
||
position = (current_utc_hour - start_hour) / time_range
|
||
|
||
if mode == "decrease":
|
||
# 逐渐降低意愿至0
|
||
willing_factor = max(0, 1 - position)
|
||
original_willing = current_willing
|
||
current_willing *= willing_factor
|
||
logger.debug(f"UTC时间{current_utc_hour}在降低时间段{start_hour}-{end_hour}内,位置{position:.2f},意愿因子{willing_factor:.2f},调整前意愿: {original_willing:.2f},调整后意愿: {current_willing:.2f}")
|
||
|
||
elif mode == "increase":
|
||
# 从0逐渐恢复到配置值
|
||
willing_factor = min(1, position)
|
||
original_willing = current_willing
|
||
# 这里可能需要根据上一个时间段的终点调整起始值
|
||
# 如果上一个时间段结束于0,则从0开始提高
|
||
current_willing *= willing_factor
|
||
logger.debug(f"UTC时间{current_utc_hour}在提高时间段{start_hour}-{end_hour}内,位置{position:.2f},意愿因子{willing_factor:.2f},调整前意愿: {original_willing:.2f},调整后意愿: {current_willing:.2f}")
|
||
else:
|
||
# 未找到当前时间的配置,需要确定延续哪个时间点的值
|
||
|
||
# 找到最接近当前时间的时间段结束点
|
||
closest_period_end = None
|
||
min_hours_diff = 24
|
||
|
||
for period in global_config.time_periods:
|
||
end_hour = period["end_hour"]
|
||
# 计算结束时间与当前时间的差距(考虑跨天)
|
||
hours_diff = (current_utc_hour - end_hour) % 24
|
||
|
||
if hours_diff < min_hours_diff:
|
||
min_hours_diff = hours_diff
|
||
closest_period_end = period
|
||
|
||
if closest_period_end:
|
||
mode = closest_period_end["mode"]
|
||
# 如果最近的时间段是降低模式,那么当前回复意愿应为0
|
||
if mode == "decrease":
|
||
current_willing = 0
|
||
logger.debug(f"UTC时间{current_utc_hour}不在任何配置时间段内,延续最近的降低时间段结束值,意愿设为0")
|
||
# 如果最近的时间段是提高模式,保持原值不变(已经是global_config.response_willing_amplifier的值)
|
||
else:
|
||
logger.debug(f"UTC时间{current_utc_hour}不在任何配置时间段内,延续最近的提高时间段结束值,保持原意愿{current_willing:.2f}")
|
||
|
||
reply_probability = max((current_willing - 0.45) * 2, 0)
|
||
|
||
# 检查群组权限(如果是群聊)
|
||
if chat_stream.group_info:
|
||
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
|
||
|
||
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):
|
||
"""发送消息后提高聊天流的回复意愿"""
|
||
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)
|
||
|
||
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())
|
||
self._started = True
|
||
|
||
|
||
# 创建全局实例
|
||
willing_manager = WillingManager()
|