Merge pull request #710 from na10xi27da/dev
willing模块接口化,并且新增一个willing模式
This commit is contained in:
@@ -284,7 +284,7 @@ WILLING_STYLE_CONFIG = {
|
||||
},
|
||||
"simple": {
|
||||
"console_format": (
|
||||
"<green>{time:MM-DD HH:mm}</green> | <light-blue>意愿</light-blue> | <light-blue>{message}</light-blue>"
|
||||
"<green>{time:MM-DD HH:mm}</green> | <light-blue>意愿</light-blue> | {message}"
|
||||
), # noqa: E501
|
||||
"file_format": ("{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {extra[module]: <15} | 意愿 | {message}"),
|
||||
},
|
||||
|
||||
@@ -64,7 +64,7 @@ class MainSystem:
|
||||
asyncio.create_task(person_info_manager.personal_habit_deduction())
|
||||
|
||||
# 启动愿望管理器
|
||||
await willing_manager.ensure_started()
|
||||
await willing_manager.async_task_starter()
|
||||
|
||||
# 启动消息处理器
|
||||
if not self._message_manager_started:
|
||||
|
||||
@@ -55,7 +55,6 @@ class ReasoningChat:
|
||||
)
|
||||
|
||||
message_manager.add_message(thinking_message)
|
||||
willing_manager.change_reply_willing_sent(chat)
|
||||
|
||||
return thinking_id
|
||||
|
||||
@@ -131,7 +130,7 @@ class ReasoningChat:
|
||||
)
|
||||
message_manager.add_message(bot_message)
|
||||
|
||||
async def _update_relationship(self, message, response_set):
|
||||
async def _update_relationship(self, message: MessageRecv, response_set):
|
||||
"""更新关系情绪"""
|
||||
ori_response = ",".join(response_set)
|
||||
stance, emotion = await self.gpt._get_emotion_tags(ori_response, message.processed_plain_text)
|
||||
@@ -183,7 +182,17 @@ class ReasoningChat:
|
||||
|
||||
# 查询缓冲器结果,会整合前面跳过的消息,改变processed_plain_text
|
||||
buffer_result = await message_buffer.query_buffer_result(message)
|
||||
|
||||
# 处理提及
|
||||
is_mentioned, reply_probability = is_mentioned_bot_in_message(message)
|
||||
|
||||
# 意愿管理器:设置当前message信息
|
||||
willing_manager.setup(message, chat, is_mentioned, interested_rate)
|
||||
|
||||
# 处理缓冲器结果
|
||||
if not buffer_result:
|
||||
await willing_manager.bombing_buffer_message_handle(message.message_info.message_id)
|
||||
willing_manager.delete(message.message_info.message_id)
|
||||
if message.message_segment.type == "text":
|
||||
logger.info(f"触发缓冲,已炸飞消息:{message.processed_plain_text}")
|
||||
elif message.message_segment.type == "image":
|
||||
@@ -192,45 +201,32 @@ class ReasoningChat:
|
||||
logger.info("触发缓冲,已炸飞消息列")
|
||||
return
|
||||
|
||||
# 处理提及
|
||||
is_mentioned, reply_probability = is_mentioned_bot_in_message(message)
|
||||
# 获取回复概率
|
||||
is_willing = False
|
||||
if reply_probability != 1:
|
||||
is_willing = True
|
||||
reply_probability = await willing_manager.get_reply_probability(message.message_info.message_id)
|
||||
|
||||
# 计算回复意愿
|
||||
current_willing = willing_manager.get_willing(chat_stream=chat)
|
||||
willing_manager.set_willing(chat.stream_id, current_willing)
|
||||
|
||||
# 意愿激活
|
||||
timer1 = time.time()
|
||||
real_reply_probability = await willing_manager.change_reply_willing_received(
|
||||
chat_stream=chat,
|
||||
is_mentioned_bot=is_mentioned,
|
||||
config=global_config,
|
||||
is_emoji=message.is_emoji,
|
||||
interested_rate=interested_rate,
|
||||
sender_id=str(message.message_info.user_info.user_id),
|
||||
)
|
||||
if reply_probability != 1 or (groupinfo and (groupinfo.group_id not in global_config.talk_allowed_groups)):
|
||||
reply_probability = real_reply_probability
|
||||
timer2 = time.time()
|
||||
timing_results["意愿激活"] = timer2 - timer1
|
||||
if message.message_info.additional_config:
|
||||
if "maimcore_reply_probability_gain" in message.message_info.additional_config.keys():
|
||||
reply_probability += message.message_info.additional_config["maimcore_reply_probability_gain"]
|
||||
|
||||
# 打印消息信息
|
||||
mes_name = chat.group_info.group_name if chat.group_info else "私聊"
|
||||
current_time = time.strftime("%H:%M:%S", time.localtime(messageinfo.time))
|
||||
current_time = time.strftime("%H:%M:%S", time.localtime(message.message_info.time))
|
||||
willing_log = f"[回复意愿:{await willing_manager.get_willing(chat.stream_id):.2f}]" if is_willing else ""
|
||||
logger.info(
|
||||
f"[{current_time}][{mes_name}]"
|
||||
f"{chat.user_info.user_nickname}:"
|
||||
f"{message.processed_plain_text}[回复意愿:{current_willing:.2f}][概率:{reply_probability * 100:.1f}%]"
|
||||
f"{message.processed_plain_text}{willing_log}[概率:{reply_probability * 100:.1f}%]"
|
||||
)
|
||||
|
||||
if message.message_info.additional_config:
|
||||
if "maimcore_reply_probability_gain" in message.message_info.additional_config.keys():
|
||||
reply_probability += message.message_info.additional_config["maimcore_reply_probability_gain"]
|
||||
|
||||
do_reply = False
|
||||
if random() < reply_probability:
|
||||
do_reply = True
|
||||
|
||||
# 回复前处理
|
||||
await willing_manager.before_generate_reply_handle(message.message_info.message_id)
|
||||
|
||||
# 创建思考消息
|
||||
timer1 = time.time()
|
||||
thinking_id = await self._create_thinking_message(message, chat, userinfo, messageinfo)
|
||||
@@ -280,12 +276,21 @@ class ReasoningChat:
|
||||
timer2 = time.time()
|
||||
timing_results["更新关系情绪"] = timer2 - timer1
|
||||
|
||||
# 回复后处理
|
||||
await willing_manager.after_generate_reply_handle(message.message_info.message_id)
|
||||
|
||||
# 输出性能计时结果
|
||||
if do_reply:
|
||||
timing_str = " | ".join([f"{step}: {duration:.2f}秒" for step, duration in timing_results.items()])
|
||||
trigger_msg = message.processed_plain_text
|
||||
response_msg = " ".join(response_set) if response_set else "无回复"
|
||||
logger.info(f"触发消息: {trigger_msg[:20]}... | 推理消息: {response_msg[:20]}... | 性能计时: {timing_str}")
|
||||
else:
|
||||
# 不回复处理
|
||||
await willing_manager.not_reply_handle(message.message_info.message_id)
|
||||
|
||||
# 意愿管理器:注销当前message信息
|
||||
willing_manager.delete(message.message_info.message_id)
|
||||
|
||||
def _check_ban_words(self, text: str, chat, userinfo) -> bool:
|
||||
"""检查消息中是否包含过滤词"""
|
||||
|
||||
@@ -153,6 +153,7 @@ class ResponseGenerator:
|
||||
- "中立":不表达明确立场或无关回应
|
||||
2. 从"开心,愤怒,悲伤,惊讶,平静,害羞,恐惧,厌恶,困惑"中选出最匹配的1个情感标签
|
||||
3. 按照"立场-情绪"的格式直接输出结果,例如:"反对-愤怒"
|
||||
4. 考虑回复者的人格设定为{global_config.personality_core}
|
||||
|
||||
对话示例:
|
||||
被回复:「A就是笨」
|
||||
|
||||
@@ -56,7 +56,6 @@ class ThinkFlowChat:
|
||||
)
|
||||
|
||||
message_manager.add_message(thinking_message)
|
||||
willing_manager.change_reply_willing_sent(chat)
|
||||
|
||||
return thinking_id
|
||||
|
||||
@@ -154,7 +153,7 @@ class ThinkFlowChat:
|
||||
|
||||
await heartflow.get_subheartflow(stream_id).do_thinking_after_reply(response_set, chat_talking_prompt)
|
||||
|
||||
async def _update_relationship(self, message, response_set):
|
||||
async def _update_relationship(self, message: MessageRecv, response_set):
|
||||
"""更新关系情绪"""
|
||||
ori_response = ",".join(response_set)
|
||||
stance, emotion = await self.gpt._get_emotion_tags(ori_response, message.processed_plain_text)
|
||||
@@ -211,7 +210,17 @@ class ThinkFlowChat:
|
||||
|
||||
# 查询缓冲器结果,会整合前面跳过的消息,改变processed_plain_text
|
||||
buffer_result = await message_buffer.query_buffer_result(message)
|
||||
|
||||
# 处理提及
|
||||
is_mentioned, reply_probability = is_mentioned_bot_in_message(message)
|
||||
|
||||
# 意愿管理器:设置当前message信息
|
||||
willing_manager.setup(message, chat, is_mentioned, interested_rate)
|
||||
|
||||
# 处理缓冲器结果
|
||||
if not buffer_result:
|
||||
await willing_manager.bombing_buffer_message_handle(message.message_info.message_id)
|
||||
willing_manager.delete(message.message_info.message_id)
|
||||
if message.message_segment.type == "text":
|
||||
logger.info(f"触发缓冲,已炸飞消息:{message.processed_plain_text}")
|
||||
elif message.message_segment.type == "image":
|
||||
@@ -220,47 +229,33 @@ class ThinkFlowChat:
|
||||
logger.info("触发缓冲,已炸飞消息列")
|
||||
return
|
||||
|
||||
# 处理提及
|
||||
is_mentioned, reply_probability = is_mentioned_bot_in_message(message)
|
||||
|
||||
# 计算回复意愿
|
||||
current_willing_old = willing_manager.get_willing(chat_stream=chat)
|
||||
# current_willing_new = (heartflow.get_subheartflow(chat.stream_id).current_state.willing - 5) / 4
|
||||
# current_willing = (current_willing_old + current_willing_new) / 2
|
||||
# 有点bug
|
||||
current_willing = current_willing_old
|
||||
# current_willing_old = willing_manager.get_willing(chat_stream=chat)
|
||||
# # current_willing_new = (heartflow.get_subheartflow(chat.stream_id).current_state.willing - 5) / 4
|
||||
# # current_willing = (current_willing_old + current_willing_new) / 2
|
||||
# # 有点bug
|
||||
# current_willing = current_willing_old
|
||||
|
||||
willing_manager.set_willing(chat.stream_id, current_willing)
|
||||
# 获取回复概率
|
||||
is_willing = False
|
||||
if reply_probability != 1:
|
||||
is_willing = True
|
||||
reply_probability = await willing_manager.get_reply_probability(message.message_info.message_id)
|
||||
|
||||
# 意愿激活
|
||||
timer1 = time.time()
|
||||
real_reply_probability = await willing_manager.change_reply_willing_received(
|
||||
chat_stream=chat,
|
||||
is_mentioned_bot=is_mentioned,
|
||||
config=global_config,
|
||||
is_emoji=message.is_emoji,
|
||||
interested_rate=interested_rate,
|
||||
sender_id=str(message.message_info.user_info.user_id),
|
||||
)
|
||||
if reply_probability != 1 or (groupinfo and (groupinfo.group_id not in global_config.talk_allowed_groups)):
|
||||
reply_probability = real_reply_probability
|
||||
timer2 = time.time()
|
||||
timing_results["意愿激活"] = timer2 - timer1
|
||||
logger.debug(f"意愿激活: {reply_probability}")
|
||||
if message.message_info.additional_config:
|
||||
if "maimcore_reply_probability_gain" in message.message_info.additional_config.keys():
|
||||
reply_probability += message.message_info.additional_config["maimcore_reply_probability_gain"]
|
||||
|
||||
# 打印消息信息
|
||||
mes_name = chat.group_info.group_name if chat.group_info else "私聊"
|
||||
current_time = time.strftime("%H:%M:%S", time.localtime(messageinfo.time))
|
||||
current_time = time.strftime("%H:%M:%S", time.localtime(message.message_info.time))
|
||||
willing_log = f"[回复意愿:{await willing_manager.get_willing(chat.stream_id):.2f}]" if is_willing else ""
|
||||
logger.info(
|
||||
f"[{current_time}][{mes_name}]"
|
||||
f"{chat.user_info.user_nickname}:"
|
||||
f"{message.processed_plain_text}[回复意愿:{current_willing:.2f}][概率:{reply_probability * 100:.1f}%]"
|
||||
f"{message.processed_plain_text}{willing_log}[概率:{reply_probability * 100:.1f}%]"
|
||||
)
|
||||
|
||||
if message.message_info.additional_config:
|
||||
if "maimcore_reply_probability_gain" in message.message_info.additional_config.keys():
|
||||
reply_probability += message.message_info.additional_config["maimcore_reply_probability_gain"]
|
||||
|
||||
do_reply = False
|
||||
if random() < reply_probability:
|
||||
try:
|
||||
@@ -268,6 +263,9 @@ class ThinkFlowChat:
|
||||
|
||||
|
||||
|
||||
# 回复前处理
|
||||
await willing_manager.before_generate_reply_handle(message.message_info.message_id)
|
||||
|
||||
# 创建思考消息
|
||||
try:
|
||||
timer1 = time.time()
|
||||
@@ -362,6 +360,9 @@ class ThinkFlowChat:
|
||||
except Exception as e:
|
||||
logger.error(f"心流更新关系情绪失败: {e}")
|
||||
|
||||
# 回复后处理
|
||||
await willing_manager.after_generate_reply_handle(message.message_info.message_id)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"心流处理消息失败: {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
@@ -372,6 +373,12 @@ class ThinkFlowChat:
|
||||
trigger_msg = message.processed_plain_text
|
||||
response_msg = " ".join(response_set) if response_set else "无回复"
|
||||
logger.info(f"触发消息: {trigger_msg[:20]}... | 思维消息: {response_msg[:20]}... | 性能计时: {timing_str}")
|
||||
else:
|
||||
# 不回复处理
|
||||
await willing_manager.not_reply_handle(message.message_info.message_id)
|
||||
|
||||
# 意愿管理器:注销当前message信息
|
||||
willing_manager.delete(message.message_info.message_id)
|
||||
|
||||
def _check_ban_words(self, text: str, chat, userinfo) -> bool:
|
||||
"""检查消息中是否包含过滤词"""
|
||||
|
||||
@@ -189,6 +189,7 @@ class ResponseGenerator:
|
||||
- "中立":不表达明确立场或无关回应
|
||||
2. 从"开心,愤怒,悲伤,惊讶,平静,害羞,恐惧,厌恶,困惑"中选出最匹配的1个情感标签
|
||||
3. 按照"立场-情绪"的格式直接输出结果,例如:"反对-愤怒"
|
||||
4. 考虑回复者的人格设定为{global_config.personality_core}
|
||||
|
||||
对话示例:
|
||||
被回复:「A就是笨」
|
||||
|
||||
@@ -43,12 +43,12 @@ class RelationshipManager:
|
||||
"厌恶",
|
||||
]
|
||||
|
||||
if label in positive_list and stance != "反对":
|
||||
if label in positive_list:
|
||||
if 7 > self.positive_feedback_value >= 0:
|
||||
self.positive_feedback_value += 1
|
||||
elif self.positive_feedback_value < 0:
|
||||
self.positive_feedback_value = 0
|
||||
elif label in negative_list and stance != "支持":
|
||||
elif label in negative_list:
|
||||
if -7 < self.positive_feedback_value <= 0:
|
||||
self.positive_feedback_value -= 1
|
||||
elif self.positive_feedback_value > 0:
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import asyncio
|
||||
from typing import Dict
|
||||
from ..chat.chat_stream import ChatStream
|
||||
from ..config.config import global_config
|
||||
from .willing_manager import BaseWillingManager
|
||||
|
||||
|
||||
class WillingManager:
|
||||
class ClassicalWillingManager(BaseWillingManager):
|
||||
def __init__(self):
|
||||
self.chat_reply_willing: Dict[str, float] = {} # 存储每个聊天流的回复意愿
|
||||
self._decay_task = None
|
||||
self._started = False
|
||||
super().__init__()
|
||||
self._decay_task: asyncio.Task = None
|
||||
|
||||
async def _decay_reply_willing(self):
|
||||
"""定期衰减回复意愿"""
|
||||
@@ -17,86 +13,66 @@ class WillingManager:
|
||||
for chat_id in self.chat_reply_willing:
|
||||
self.chat_reply_willing[chat_id] = max(0, self.chat_reply_willing[chat_id] * 0.9)
|
||||
|
||||
def get_willing(self, chat_stream: ChatStream) -> float:
|
||||
"""获取指定聊天流的回复意愿"""
|
||||
if chat_stream:
|
||||
return self.chat_reply_willing.get(chat_stream.stream_id, 0)
|
||||
return 0
|
||||
async def async_task_starter(self):
|
||||
if self._decay_task is None:
|
||||
self._decay_task = asyncio.create_task(self._decay_reply_willing())
|
||||
|
||||
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,
|
||||
is_mentioned_bot: bool = False,
|
||||
config=None,
|
||||
is_emoji: bool = False,
|
||||
interested_rate: float = 0,
|
||||
sender_id: str = None,
|
||||
) -> float:
|
||||
"""改变指定聊天流的回复意愿并返回回复概率"""
|
||||
chat_id = chat_stream.stream_id
|
||||
async def get_reply_probability(self, message_id):
|
||||
willing_info = self.ongoing_messages[message_id]
|
||||
chat_id = willing_info.chat_id
|
||||
current_willing = self.chat_reply_willing.get(chat_id, 0)
|
||||
|
||||
interested_rate = interested_rate * config.response_interested_rate_amplifier
|
||||
interested_rate = willing_info.interested_rate * self.global_config.response_interested_rate_amplifier
|
||||
|
||||
if interested_rate > 0.4:
|
||||
current_willing += interested_rate - 0.3
|
||||
|
||||
if is_mentioned_bot and current_willing < 1.0:
|
||||
if willing_info.is_mentioned_bot and current_willing < 1.0:
|
||||
current_willing += 1
|
||||
elif is_mentioned_bot:
|
||||
elif willing_info.is_mentioned_bot:
|
||||
current_willing += 0.05
|
||||
|
||||
if is_emoji:
|
||||
current_willing *= global_config.emoji_response_penalty
|
||||
is_emoji_not_reply = False
|
||||
if willing_info.is_emoji:
|
||||
if self.global_config.emoji_response_penalty != 0:
|
||||
current_willing *= self.global_config.emoji_response_penalty
|
||||
else:
|
||||
is_emoji_not_reply = True
|
||||
|
||||
self.chat_reply_willing[chat_id] = min(current_willing, 3.0)
|
||||
|
||||
reply_probability = min(max((current_willing - 0.5), 0.01) * config.response_willing_amplifier * 2, 1)
|
||||
reply_probability = min(max((current_willing - 0.5), 0.01) * self.global_config.response_willing_amplifier * 2, 1)
|
||||
|
||||
# 检查群组权限(如果是群聊)
|
||||
if chat_stream.group_info and config:
|
||||
if chat_stream.group_info.group_id not in config.talk_allowed_groups:
|
||||
current_willing = 0
|
||||
reply_probability = 0
|
||||
if willing_info.group_info and willing_info.group_info.group_id in self.global_config.talk_frequency_down_groups:
|
||||
reply_probability = reply_probability / self.global_config.down_frequency_rate
|
||||
|
||||
if chat_stream.group_info.group_id in config.talk_frequency_down_groups:
|
||||
reply_probability = reply_probability / config.down_frequency_rate
|
||||
if is_emoji_not_reply:
|
||||
reply_probability = 0
|
||||
|
||||
return reply_probability
|
||||
|
||||
async def before_generate_reply_handle(self, message_id):
|
||||
chat_id = self.ongoing_messages[message_id].chat_id
|
||||
current_willing = self.chat_reply_willing.get(chat_id, 0)
|
||||
self.chat_reply_willing[chat_id] = max(0, current_willing - 1.8)
|
||||
|
||||
def change_reply_willing_sent(self, chat_stream: ChatStream):
|
||||
"""发送消息后降低聊天流的回复意愿"""
|
||||
if chat_stream:
|
||||
chat_id = chat_stream.stream_id
|
||||
current_willing = self.chat_reply_willing.get(chat_id, 0)
|
||||
self.chat_reply_willing[chat_id] = max(0, current_willing - 1.8)
|
||||
async def after_generate_reply_handle(self, message_id):
|
||||
chat_id = self.ongoing_messages[message_id].chat_id
|
||||
current_willing = self.chat_reply_willing.get(chat_id, 0)
|
||||
if current_willing < 1:
|
||||
self.chat_reply_willing[chat_id] = min(1, current_willing + 0.4)
|
||||
|
||||
def change_reply_willing_not_sent(self, chat_stream: ChatStream):
|
||||
"""未发送消息后降低聊天流的回复意愿"""
|
||||
if chat_stream:
|
||||
chat_id = chat_stream.stream_id
|
||||
current_willing = self.chat_reply_willing.get(chat_id, 0)
|
||||
self.chat_reply_willing[chat_id] = max(0, current_willing - 0)
|
||||
async def bombing_buffer_message_handle(self, message_id):
|
||||
return await super().bombing_buffer_message_handle(message_id)
|
||||
|
||||
def change_reply_willing_after_sent(self, chat_stream: ChatStream):
|
||||
"""发送消息后提高聊天流的回复意愿"""
|
||||
if chat_stream:
|
||||
chat_id = chat_stream.stream_id
|
||||
current_willing = self.chat_reply_willing.get(chat_id, 0)
|
||||
if current_willing < 1:
|
||||
self.chat_reply_willing[chat_id] = min(1, current_willing + 0.4)
|
||||
async def not_reply_handle(self, message_id):
|
||||
return await super().not_reply_handle(message_id)
|
||||
|
||||
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()
|
||||
async def get_variable_parameters(self):
|
||||
return await super().get_variable_parameters()
|
||||
|
||||
async def set_variable_parameters(self, parameters):
|
||||
return await super().set_variable_parameters(parameters)
|
||||
|
||||
|
||||
|
||||
@@ -1,101 +1,7 @@
|
||||
import asyncio
|
||||
from typing import Dict
|
||||
from ..chat.chat_stream import ChatStream
|
||||
from .willing_manager import BaseWillingManager
|
||||
|
||||
|
||||
class WillingManager:
|
||||
class CustomWillingManager(BaseWillingManager):
|
||||
def __init__(self):
|
||||
self.chat_reply_willing: Dict[str, float] = {} # 存储每个聊天流的回复意愿
|
||||
self._decay_task = None
|
||||
self._started = False
|
||||
super().__init__()
|
||||
|
||||
async def _decay_reply_willing(self):
|
||||
"""定期衰减回复意愿"""
|
||||
while True:
|
||||
await asyncio.sleep(1)
|
||||
for chat_id in self.chat_reply_willing:
|
||||
self.chat_reply_willing[chat_id] = max(0, self.chat_reply_willing[chat_id] * 0.9)
|
||||
|
||||
def get_willing(self, chat_stream: ChatStream) -> float:
|
||||
"""获取指定聊天流的回复意愿"""
|
||||
if chat_stream:
|
||||
return self.chat_reply_willing.get(chat_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,
|
||||
is_mentioned_bot: bool = False,
|
||||
config=None,
|
||||
is_emoji: bool = False,
|
||||
interested_rate: float = 0,
|
||||
sender_id: str = None,
|
||||
) -> float:
|
||||
"""改变指定聊天流的回复意愿并返回回复概率"""
|
||||
chat_id = chat_stream.stream_id
|
||||
current_willing = self.chat_reply_willing.get(chat_id, 0)
|
||||
|
||||
interested_rate = interested_rate * config.response_interested_rate_amplifier
|
||||
|
||||
if interested_rate > 0.4:
|
||||
current_willing += interested_rate - 0.3
|
||||
|
||||
if is_mentioned_bot and current_willing < 1.0:
|
||||
current_willing += 1
|
||||
elif is_mentioned_bot:
|
||||
current_willing += 0.05
|
||||
|
||||
if is_emoji:
|
||||
current_willing *= 0.2
|
||||
|
||||
self.chat_reply_willing[chat_id] = min(current_willing, 3.0)
|
||||
|
||||
reply_probability = min(max((current_willing - 0.5), 0.01) * config.response_willing_amplifier * 2, 1)
|
||||
|
||||
# 检查群组权限(如果是群聊)
|
||||
if chat_stream.group_info and config:
|
||||
if chat_stream.group_info.group_id not in config.talk_allowed_groups:
|
||||
current_willing = 0
|
||||
reply_probability = 0
|
||||
|
||||
if chat_stream.group_info.group_id in config.talk_frequency_down_groups:
|
||||
reply_probability = reply_probability / config.down_frequency_rate
|
||||
|
||||
return reply_probability
|
||||
|
||||
def change_reply_willing_sent(self, chat_stream: ChatStream):
|
||||
"""发送消息后降低聊天流的回复意愿"""
|
||||
if chat_stream:
|
||||
chat_id = chat_stream.stream_id
|
||||
current_willing = self.chat_reply_willing.get(chat_id, 0)
|
||||
self.chat_reply_willing[chat_id] = max(0, current_willing - 1.8)
|
||||
|
||||
def change_reply_willing_not_sent(self, chat_stream: ChatStream):
|
||||
"""未发送消息后降低聊天流的回复意愿"""
|
||||
if chat_stream:
|
||||
chat_id = chat_stream.stream_id
|
||||
current_willing = self.chat_reply_willing.get(chat_id, 0)
|
||||
self.chat_reply_willing[chat_id] = max(0, current_willing - 0)
|
||||
|
||||
def change_reply_willing_after_sent(self, chat_stream: ChatStream):
|
||||
"""发送消息后提高聊天流的回复意愿"""
|
||||
if chat_stream:
|
||||
chat_id = chat_stream.stream_id
|
||||
current_willing = self.chat_reply_willing.get(chat_id, 0)
|
||||
if current_willing < 1:
|
||||
self.chat_reply_willing[chat_id] = min(1, current_willing + 0.4)
|
||||
|
||||
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()
|
||||
|
||||
@@ -2,15 +2,12 @@ import asyncio
|
||||
import random
|
||||
import time
|
||||
from typing import Dict
|
||||
from src.common.logger import get_module_logger
|
||||
from ..config.config import global_config
|
||||
from ..chat.chat_stream import ChatStream
|
||||
|
||||
logger = get_module_logger("mode_dynamic")
|
||||
from .willing_manager import BaseWillingManager
|
||||
|
||||
|
||||
class WillingManager:
|
||||
class DynamicWillingManager(BaseWillingManager):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.chat_reply_willing: Dict[str, float] = {} # 存储每个聊天流的回复意愿
|
||||
self.chat_high_willing_mode: Dict[str, bool] = {} # 存储每个聊天流是否处于高回复意愿期
|
||||
self.chat_msg_count: Dict[str, int] = {} # 存储每个聊天流接收到的消息数量
|
||||
@@ -22,7 +19,13 @@ class WillingManager:
|
||||
self.chat_conversation_context: Dict[str, bool] = {} # 标记是否处于对话上下文中
|
||||
self._decay_task = None
|
||||
self._mode_switch_task = None
|
||||
self._started = False
|
||||
|
||||
|
||||
async def async_task_starter(self):
|
||||
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())
|
||||
|
||||
async def _decay_reply_willing(self):
|
||||
"""定期衰减回复意愿"""
|
||||
@@ -75,28 +78,17 @@ 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分钟
|
||||
logger.debug(f"聊天流 {chat_id} 切换到低回复意愿期,持续 {self.chat_low_willing_duration[chat_id]} 秒")
|
||||
self.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分钟
|
||||
logger.debug(f"聊天流 {chat_id} 切换到高回复意愿期,持续 {self.chat_high_willing_duration[chat_id]} 秒")
|
||||
self.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 # 重置消息计数
|
||||
|
||||
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
|
||||
|
||||
def _ensure_chat_initialized(self, chat_id: str):
|
||||
"""确保聊天流的所有数据已初始化"""
|
||||
if chat_id not in self.chat_reply_willing:
|
||||
@@ -113,20 +105,13 @@ class WillingManager:
|
||||
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:
|
||||
async def get_reply_probability(self, message_id):
|
||||
"""改变指定聊天流的回复意愿并返回回复概率"""
|
||||
# 获取或创建聊天流
|
||||
stream = chat_stream
|
||||
willing_info = self.ongoing_messages[message_id]
|
||||
stream = willing_info.chat
|
||||
chat_id = stream.stream_id
|
||||
sender_id = str(willing_info.message.message_info.user_info.user_id)
|
||||
current_time = time.time()
|
||||
|
||||
self._ensure_chat_initialized(chat_id)
|
||||
@@ -147,23 +132,23 @@ class WillingManager:
|
||||
if sender_id and sender_id == last_sender and current_time - last_reply_time < 120 and msg_count <= 5:
|
||||
in_conversation_context = True
|
||||
self.chat_conversation_context[chat_id] = True
|
||||
logger.debug("检测到追问 (同一用户), 提高回复意愿")
|
||||
self.logger.debug("检测到追问 (同一用户), 提高回复意愿")
|
||||
current_willing += 0.3
|
||||
|
||||
# 特殊情况处理
|
||||
if is_mentioned_bot:
|
||||
if willing_info.is_mentioned_bot:
|
||||
current_willing += 0.5
|
||||
in_conversation_context = True
|
||||
self.chat_conversation_context[chat_id] = True
|
||||
logger.debug(f"被提及, 当前意愿: {current_willing}")
|
||||
self.logger.debug(f"被提及, 当前意愿: {current_willing}")
|
||||
|
||||
if is_emoji:
|
||||
current_willing = global_config.emoji_response_penalty * 0.1
|
||||
logger.debug(f"表情包, 当前意愿: {current_willing}")
|
||||
if willing_info.is_emoji:
|
||||
current_willing = self.global_config.emoji_response_penalty * 0.1
|
||||
self.logger.debug(f"表情包, 当前意愿: {current_willing}")
|
||||
|
||||
# 根据话题兴趣度适当调整
|
||||
if interested_rate > 0.5:
|
||||
current_willing += (interested_rate - 0.5) * 0.5 * global_config.response_interested_rate_amplifier
|
||||
if willing_info.interested_rate > 0.5:
|
||||
current_willing += (willing_info.interested_rate - 0.5) * 0.5 * self.global_config.response_interested_rate_amplifier
|
||||
|
||||
# 根据当前模式计算回复概率
|
||||
base_probability = 0.0
|
||||
@@ -171,7 +156,7 @@ class WillingManager:
|
||||
if in_conversation_context:
|
||||
# 在对话上下文中,降低基础回复概率
|
||||
base_probability = 0.5 if is_high_mode else 0.25
|
||||
logger.debug(f"处于对话上下文中,基础回复概率: {base_probability}")
|
||||
self.logger.debug(f"处于对话上下文中,基础回复概率: {base_probability}")
|
||||
elif is_high_mode:
|
||||
# 高回复周期:4-8句话有50%的概率会回复一次
|
||||
base_probability = 0.50 if 4 <= msg_count <= 8 else 0.2
|
||||
@@ -180,12 +165,12 @@ class WillingManager:
|
||||
base_probability = 0.30 if msg_count >= 15 else 0.03 * min(msg_count, 10)
|
||||
|
||||
# 考虑回复意愿的影响
|
||||
reply_probability = base_probability * current_willing * global_config.response_willing_amplifier
|
||||
reply_probability = base_probability * current_willing * self.global_config.response_willing_amplifier
|
||||
|
||||
# 检查群组权限(如果是群聊)
|
||||
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
|
||||
if willing_info.group_info:
|
||||
if willing_info.group_info.group_id in self.global_config.talk_frequency_down_groups:
|
||||
reply_probability = reply_probability / self.global_config.down_frequency_rate
|
||||
|
||||
# 限制最大回复概率
|
||||
reply_probability = min(reply_probability, 0.75) # 设置最大回复概率为75%
|
||||
@@ -197,11 +182,12 @@ class WillingManager:
|
||||
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):
|
||||
async def before_generate_reply_handle(self, message_id):
|
||||
"""开始思考后降低聊天流的回复意愿"""
|
||||
stream = chat_stream
|
||||
stream = self.ongoing_messages[message_id].chat
|
||||
if stream:
|
||||
chat_id = stream.stream_id
|
||||
self._ensure_chat_initialized(chat_id)
|
||||
@@ -219,9 +205,9 @@ class WillingManager:
|
||||
# 重置消息计数
|
||||
self.chat_msg_count[chat_id] = 0
|
||||
|
||||
def change_reply_willing_not_sent(self, chat_stream: ChatStream):
|
||||
async def not_reply_handle(self, message_id):
|
||||
"""决定不回复后提高聊天流的回复意愿"""
|
||||
stream = chat_stream
|
||||
stream = self.ongoing_messages[message_id].chat
|
||||
if stream:
|
||||
chat_id = stream.stream_id
|
||||
self._ensure_chat_initialized(chat_id)
|
||||
@@ -240,20 +226,14 @@ class WillingManager:
|
||||
|
||||
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 bombing_buffer_message_handle(self, message_id):
|
||||
return await super().bombing_buffer_message_handle(message_id)
|
||||
|
||||
async def after_generate_reply_handle(self, message_id):
|
||||
return await super().after_generate_reply_handle(message_id)
|
||||
|
||||
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()
|
||||
async def get_variable_parameters(self):
|
||||
return await super().get_variable_parameters()
|
||||
|
||||
async def set_variable_parameters(self, parameters):
|
||||
return await super().set_variable_parameters(parameters)
|
||||
235
src/plugins/willing/mode_mxp.py
Normal file
235
src/plugins/willing/mode_mxp.py
Normal file
@@ -0,0 +1,235 @@
|
||||
"""
|
||||
Mxp 模式:梦溪畔独家赞助
|
||||
此模式的一些参数不会在配置文件中显示,要修改请在可变参数下修改
|
||||
同时一些全局设置对此模式无效
|
||||
此模式的可变参数暂时比较草率,需要调参仙人的大手
|
||||
此模式的特点:
|
||||
1.每个聊天流的每个用户的意愿是独立的
|
||||
2.接入关系系统,关系会影响意愿值
|
||||
3.会根据群聊的热度来调整基础意愿值
|
||||
4.限制同时思考的消息数量,防止喷射
|
||||
5.拥有单聊增益,无论在群里还是私聊,只要bot一直和你聊,就会增加意愿值
|
||||
6.意愿分为衰减意愿+临时意愿
|
||||
|
||||
如果你发现本模式出现了bug
|
||||
上上策是询问智慧的小草神()
|
||||
上策是询问万能的千石可乐
|
||||
中策是发issue
|
||||
下下策是询问一个菜鸟(@梦溪畔)
|
||||
"""
|
||||
from .willing_manager import BaseWillingManager
|
||||
from typing import Dict
|
||||
import asyncio
|
||||
import time
|
||||
import math
|
||||
|
||||
class MxpWillingManager(BaseWillingManager):
|
||||
"""Mxp意愿管理器"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.chat_person_reply_willing: Dict[str, Dict[str, float]] = {} # chat_id: {person_id: 意愿值}
|
||||
self.chat_new_message_time: Dict[str, list[float]] = {} # 聊天流ID: 消息时间
|
||||
self.last_response_person: Dict[str, tuple[str, int]] = {} # 上次回复的用户信息
|
||||
self.temporary_willing: float = 0 # 临时意愿值
|
||||
|
||||
# 可变参数
|
||||
self.intention_decay_rate = 0.93 # 意愿衰减率
|
||||
self.message_expiration_time = 120 # 消息过期时间(秒)
|
||||
self.number_of_message_storage = 10 # 消息存储数量
|
||||
self.basic_maximum_willing = 0.5 # 基础最大意愿值
|
||||
self.mention_willing_gain = 0.6 # 提及意愿增益
|
||||
self.interest_willing_gain = 0.3 # 兴趣意愿增益
|
||||
self.emoji_response_penalty = self.global_config.emoji_response_penalty # 表情包回复惩罚
|
||||
self.down_frequency_rate = self.global_config.down_frequency_rate # 降低回复频率的群组惩罚系数
|
||||
self.single_chat_gain = 0.12 # 单聊增益
|
||||
|
||||
async def async_task_starter(self) -> None:
|
||||
"""异步任务启动器"""
|
||||
asyncio.create_task(self._return_to_basic_willing())
|
||||
asyncio.create_task(self._chat_new_message_to_change_basic_willing())
|
||||
|
||||
async def before_generate_reply_handle(self, message_id: str):
|
||||
"""回复前处理"""
|
||||
pass
|
||||
|
||||
async def after_generate_reply_handle(self, message_id: str):
|
||||
"""回复后处理"""
|
||||
async with self.lock:
|
||||
w_info = self.ongoing_messages[message_id]
|
||||
rel_value = await w_info.person_info_manager.get_value(w_info.person_id, "relationship_value")
|
||||
rel_level = self._get_relationship_level_num(rel_value)
|
||||
self.chat_person_reply_willing[w_info.chat_id][w_info.person_id] += rel_level * 0.05
|
||||
|
||||
now_chat_new_person = self.last_response_person.get(w_info.chat_id, ["", 0])
|
||||
if now_chat_new_person[0] == w_info.person_id:
|
||||
if now_chat_new_person[1] < 2:
|
||||
now_chat_new_person[1] += 1
|
||||
else:
|
||||
self.last_response_person[w_info.chat_id] = [w_info.person_id, 0]
|
||||
|
||||
async def not_reply_handle(self, message_id: str):
|
||||
"""不回复处理"""
|
||||
async with self.lock:
|
||||
w_info = self.ongoing_messages[message_id]
|
||||
if w_info.is_mentioned_bot:
|
||||
self.chat_person_reply_willing[w_info.chat_id][w_info.person_id] += 0.2
|
||||
if w_info.chat_id in self.last_response_person and self.last_response_person[w_info.chat_id][0] == w_info.person_id:
|
||||
self.chat_person_reply_willing[w_info.chat_id][w_info.person_id] +=\
|
||||
self.single_chat_gain * (2 * self.last_response_person[w_info.chat_id][1] + 1)
|
||||
|
||||
async def get_reply_probability(self, message_id: str):
|
||||
"""获取回复概率"""
|
||||
async with self.lock:
|
||||
w_info = self.ongoing_messages[message_id]
|
||||
current_willing = self.chat_person_reply_willing[w_info.chat_id][w_info.person_id]
|
||||
|
||||
if w_info.is_mentioned_bot:
|
||||
current_willing += self.mention_willing_gain / (int(current_willing) + 1)
|
||||
|
||||
if w_info.interested_rate > 0:
|
||||
current_willing += math.atan(w_info.interested_rate / 2) / math.pi * 2 * self.interest_willing_gain
|
||||
|
||||
self.chat_person_reply_willing[w_info.chat_id][w_info.person_id] = current_willing
|
||||
|
||||
rel_value = await w_info.person_info_manager.get_value(w_info.person_id, "relationship_value")
|
||||
rel_level = self._get_relationship_level_num(rel_value)
|
||||
current_willing += rel_level * 0.1
|
||||
|
||||
if w_info.chat_id in self.last_response_person and self.last_response_person[w_info.chat_id][0] == w_info.person_id:
|
||||
current_willing += self.single_chat_gain * (2 * self.last_response_person[w_info.chat_id][1] + 1)
|
||||
|
||||
chat_ongoing_messages = [msg for msg in self.ongoing_messages.values() if msg.chat_id == w_info.chat_id]
|
||||
chat_person_ogoing_messages = [msg for msg in chat_ongoing_messages if msg.person_id == w_info.person_id]
|
||||
if len(chat_person_ogoing_messages) >= 2:
|
||||
current_willing = 0
|
||||
elif len(chat_ongoing_messages) == 2:
|
||||
current_willing -= 0.5
|
||||
elif len(chat_ongoing_messages) == 3:
|
||||
current_willing -= 1.5
|
||||
elif len(chat_ongoing_messages) >= 4:
|
||||
current_willing = 0
|
||||
|
||||
probability = self._willing_to_probability(current_willing)
|
||||
|
||||
if w_info.is_emoji:
|
||||
probability *= self.emoji_response_penalty
|
||||
|
||||
if w_info.group_info and w_info.group_info.group_id in self.global_config.talk_frequency_down_groups:
|
||||
probability /= self.down_frequency_rate
|
||||
|
||||
self.temporary_willing = current_willing
|
||||
|
||||
return probability
|
||||
|
||||
async def bombing_buffer_message_handle(self, message_id: str):
|
||||
"""炸飞消息处理"""
|
||||
async with self.lock:
|
||||
w_info = self.ongoing_messages[message_id]
|
||||
self.chat_person_reply_willing[w_info.chat_id][w_info.person_id] += 0.1
|
||||
|
||||
async def _return_to_basic_willing(self):
|
||||
"""使每个人的意愿恢复到chat基础意愿"""
|
||||
while True:
|
||||
await asyncio.sleep(3)
|
||||
async with self.lock:
|
||||
for chat_id, person_willing in self.chat_person_reply_willing.items():
|
||||
for person_id, willing in person_willing.items():
|
||||
if chat_id not in self.chat_reply_willing:
|
||||
self.logger.debug(f"聊天流{chat_id}不存在,错误")
|
||||
continue
|
||||
basic_willing = self.chat_reply_willing[chat_id]
|
||||
person_willing[person_id] = basic_willing + (willing - basic_willing) * self.intention_decay_rate
|
||||
|
||||
def setup(self, message, chat, is_mentioned_bot, interested_rate):
|
||||
super().setup(message, chat, is_mentioned_bot, interested_rate)
|
||||
|
||||
self.chat_reply_willing[chat.stream_id] = self.chat_reply_willing.get(chat.stream_id, self.basic_maximum_willing)
|
||||
self.chat_person_reply_willing[chat.stream_id] = self.chat_person_reply_willing.get(chat.stream_id, {})
|
||||
self.chat_person_reply_willing[chat.stream_id][self.ongoing_messages[message.message_info.message_id].person_id] = \
|
||||
self.chat_person_reply_willing[chat.stream_id].get(self.ongoing_messages[message.message_info.message_id].person_id,
|
||||
self.chat_reply_willing[chat.stream_id])
|
||||
|
||||
if chat.stream_id not in self.chat_new_message_time:
|
||||
self.chat_new_message_time[chat.stream_id] = []
|
||||
self.chat_new_message_time[chat.stream_id].append(time.time())
|
||||
if len(self.chat_new_message_time[chat.stream_id]) > self.number_of_message_storage:
|
||||
self.chat_new_message_time[chat.stream_id].pop(0)
|
||||
|
||||
def _willing_to_probability(self, willing: float) -> float:
|
||||
"""意愿值转化为概率"""
|
||||
willing = max(0, willing)
|
||||
if willing < 2:
|
||||
probability = math.atan(willing * 2) / math.pi * 2
|
||||
else:
|
||||
probability = math.atan(willing * 4) / math.pi * 2
|
||||
return probability
|
||||
|
||||
async def _chat_new_message_to_change_basic_willing(self):
|
||||
"""聊天流新消息改变基础意愿"""
|
||||
while True:
|
||||
update_time = 20
|
||||
await asyncio.sleep(update_time)
|
||||
async with self.lock:
|
||||
for chat_id, message_times in self.chat_new_message_time.items():
|
||||
|
||||
# 清理过期消息
|
||||
current_time = time.time()
|
||||
message_times = [msg_time for msg_time in message_times if current_time - msg_time < self.message_expiration_time]
|
||||
self.chat_new_message_time[chat_id] = message_times
|
||||
|
||||
if len(message_times) < self.number_of_message_storage:
|
||||
self.chat_reply_willing[chat_id] = self.basic_maximum_willing
|
||||
update_time = 20
|
||||
elif len(message_times) == self.number_of_message_storage:
|
||||
time_interval = current_time - message_times[0]
|
||||
basic_willing = self.basic_maximum_willing * math.sqrt(time_interval / self.message_expiration_time)
|
||||
self.chat_reply_willing[chat_id] = basic_willing
|
||||
update_time = 17 * math.sqrt(time_interval / self.message_expiration_time) + 3
|
||||
else:
|
||||
self.logger.debug(f"聊天流{chat_id}消息时间数量异常,数量:{len(message_times)}")
|
||||
self.chat_reply_willing[chat_id] = 0
|
||||
|
||||
async def get_variable_parameters(self) -> Dict[str, str]:
|
||||
"""获取可变参数"""
|
||||
return {
|
||||
"intention_decay_rate": "意愿衰减率",
|
||||
"message_expiration_time": "消息过期时间(秒)",
|
||||
"number_of_message_storage": "消息存储数量",
|
||||
"basic_maximum_willing": "基础最大意愿值",
|
||||
"mention_willing_gain": "提及意愿增益",
|
||||
"interest_willing_gain": "兴趣意愿增益",
|
||||
"emoji_response_penalty": "表情包回复惩罚",
|
||||
"down_frequency_rate": "降低回复频率的群组惩罚系数",
|
||||
"single_chat_gain": "单聊增益(不仅是私聊)"
|
||||
}
|
||||
|
||||
async def set_variable_parameters(self, parameters: Dict[str, any]):
|
||||
"""设置可变参数"""
|
||||
async with self.lock:
|
||||
for key, value in parameters.items():
|
||||
if hasattr(self, key):
|
||||
setattr(self, key, value)
|
||||
self.logger.debug(f"参数 {key} 已更新为 {value}")
|
||||
else:
|
||||
self.logger.debug(f"尝试设置未知参数 {key}")
|
||||
|
||||
def _get_relationship_level_num(self, relationship_value) -> int:
|
||||
"""关系等级计算"""
|
||||
if -1000 <= relationship_value < -227:
|
||||
level_num = 0
|
||||
elif -227 <= relationship_value < -73:
|
||||
level_num = 1
|
||||
elif -73 <= relationship_value < 227:
|
||||
level_num = 2
|
||||
elif 227 <= relationship_value < 587:
|
||||
level_num = 3
|
||||
elif 587 <= relationship_value < 900:
|
||||
level_num = 4
|
||||
elif 900 <= relationship_value <= 1000:
|
||||
level_num = 5
|
||||
else:
|
||||
level_num = 5 if relationship_value > 1000 else 0
|
||||
return level_num - 2
|
||||
|
||||
async def get_willing(self, chat_id):
|
||||
return self.temporary_willing
|
||||
@@ -1,22 +1,169 @@
|
||||
from typing import Optional
|
||||
from src.common.logger import get_module_logger
|
||||
|
||||
from ..config.config import global_config
|
||||
from .mode_classical import WillingManager as ClassicalWillingManager
|
||||
from .mode_dynamic import WillingManager as DynamicWillingManager
|
||||
from .mode_custom import WillingManager as CustomWillingManager
|
||||
from src.common.logger import LogConfig, WILLING_STYLE_CONFIG
|
||||
from src.common.logger import LogConfig, WILLING_STYLE_CONFIG, LoguruLogger, get_module_logger
|
||||
from dataclasses import dataclass
|
||||
from ..config.config import global_config, BotConfig
|
||||
from ..chat.chat_stream import ChatStream, GroupInfo
|
||||
from ..chat.message import MessageRecv
|
||||
from ..person_info.person_info import person_info_manager, PersonInfoManager
|
||||
from abc import ABC, abstractmethod
|
||||
import importlib
|
||||
from typing import Dict, Optional
|
||||
import asyncio
|
||||
|
||||
"""
|
||||
基类方法概览:
|
||||
以下8个方法是你必须在子类重写的(哪怕什么都不干):
|
||||
async_task_starter 在程序启动时执行,在其中用asyncio.create_task启动你想要执行的异步任务
|
||||
before_generate_reply_handle 确定要回复后,在生成回复前的处理
|
||||
after_generate_reply_handle 确定要回复后,在生成回复后的处理
|
||||
not_reply_handle 确定不回复后的处理
|
||||
get_reply_probability 获取回复概率
|
||||
bombing_buffer_message_handle 缓冲器炸飞消息后的处理
|
||||
get_variable_parameters 获取可变参数组,返回一个字典,key为参数名称,value为参数描述(此方法是为拆分全局设置准备)
|
||||
set_variable_parameters 设置可变参数组,你需要传入一个字典,key为参数名称,value为参数值(此方法是为拆分全局设置准备)
|
||||
以下2个方法根据你的实现可以做调整:
|
||||
get_willing 获取某聊天流意愿
|
||||
set_willing 设置某聊天流意愿
|
||||
规范说明:
|
||||
模块文件命名: `mode_{manager_type}.py`
|
||||
示例: 若 `manager_type="aggressive"`,则模块文件应为 `mode_aggressive.py`
|
||||
类命名: `{manager_type}WillingManager` (首字母大写)
|
||||
示例: 在 `mode_aggressive.py` 中,类名应为 `AggressiveWillingManager`
|
||||
"""
|
||||
|
||||
willing_config = LogConfig(
|
||||
# 使用消息发送专用样式
|
||||
console_format=WILLING_STYLE_CONFIG["console_format"],
|
||||
file_format=WILLING_STYLE_CONFIG["file_format"],
|
||||
)
|
||||
|
||||
logger = get_module_logger("willing", config=willing_config)
|
||||
|
||||
@dataclass
|
||||
class WillingInfo:
|
||||
"""此类保存意愿模块常用的参数
|
||||
|
||||
Attributes:
|
||||
message (MessageRecv): 原始消息对象
|
||||
chat (ChatStream): 聊天流对象
|
||||
person_info_manager (PersonInfoManager): 用户信息管理对象
|
||||
chat_id (str): 当前聊天流的标识符
|
||||
person_id (str): 发送者的个人信息的标识符
|
||||
group_id (str): 群组ID(如果是私聊则为空)
|
||||
is_mentioned_bot (bool): 是否提及了bot
|
||||
is_emoji (bool): 是否为表情包
|
||||
interested_rate (float): 兴趣度
|
||||
"""
|
||||
message: MessageRecv
|
||||
chat: ChatStream
|
||||
person_info_manager: PersonInfoManager
|
||||
chat_id: str
|
||||
person_id: str
|
||||
group_info: Optional[GroupInfo]
|
||||
is_mentioned_bot: bool
|
||||
is_emoji: bool
|
||||
interested_rate: float
|
||||
# current_mood: float 当前心情?
|
||||
|
||||
def init_willing_manager() -> Optional[object]:
|
||||
class BaseWillingManager(ABC):
|
||||
"""回复意愿管理基类"""
|
||||
|
||||
@classmethod
|
||||
def create(cls, manager_type: str) -> 'BaseWillingManager':
|
||||
try:
|
||||
module = importlib.import_module(f".mode_{manager_type}", __package__)
|
||||
manager_class = getattr(module, f"{manager_type.capitalize()}WillingManager")
|
||||
if not issubclass(manager_class, cls):
|
||||
raise TypeError(
|
||||
f"Manager class {manager_class.__name__} is not a subclass of {cls.__name__}"
|
||||
)
|
||||
else:
|
||||
logger.info(f"成功载入willing模式:{manager_type}")
|
||||
return manager_class()
|
||||
except (ImportError, AttributeError, TypeError) as e:
|
||||
module = importlib.import_module(".mode_classical", __package__)
|
||||
manager_class = module.ClassicalWillingManager
|
||||
logger.info(f"载入当前意愿模式{manager_type}失败,使用经典配方~~~~")
|
||||
logger.debug(f"加载willing模式{manager_type}失败,原因: {str(e)}。")
|
||||
return manager_class()
|
||||
|
||||
def __init__(self):
|
||||
self.chat_reply_willing: Dict[str, float] = {} # 存储每个聊天流的回复意愿(chat_id)
|
||||
self.ongoing_messages: Dict[str, WillingInfo] = {} # 当前正在进行的消息(message_id)
|
||||
self.lock = asyncio.Lock()
|
||||
self.global_config: BotConfig = global_config
|
||||
self.logger: LoguruLogger = logger
|
||||
|
||||
def setup(self, message: MessageRecv, chat: ChatStream, is_mentioned_bot: bool, interested_rate: float):
|
||||
person_id = person_info_manager.get_person_id(chat.platform, chat.user_info.user_id)
|
||||
self.ongoing_messages[message.message_info.message_id] = WillingInfo(
|
||||
message=message,
|
||||
chat=chat,
|
||||
person_info_manager=person_info_manager,
|
||||
chat_id=chat.stream_id,
|
||||
person_id=person_id,
|
||||
group_info=chat.group_info,
|
||||
is_mentioned_bot=is_mentioned_bot,
|
||||
is_emoji=message.is_emoji,
|
||||
interested_rate=interested_rate,
|
||||
)
|
||||
|
||||
def delete(self, message_id: str):
|
||||
del_message = self.ongoing_messages.pop(message_id, None)
|
||||
if not del_message:
|
||||
logger.debug(f"删除异常,当前消息{message_id}不存在")
|
||||
|
||||
@abstractmethod
|
||||
async def async_task_starter(self) -> None:
|
||||
"""抽象方法:异步任务启动器"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def before_generate_reply_handle(self, message_id: str):
|
||||
"""抽象方法:回复前处理"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def after_generate_reply_handle(self, message_id: str):
|
||||
"""抽象方法:回复后处理"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def not_reply_handle(self, message_id: str):
|
||||
"""抽象方法:不回复处理"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def get_reply_probability(self, message_id: str):
|
||||
"""抽象方法:获取回复概率"""
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
async def bombing_buffer_message_handle(self, message_id: str):
|
||||
"""抽象方法:炸飞消息处理"""
|
||||
pass
|
||||
|
||||
async def get_willing(self, chat_id: str):
|
||||
"""获取指定聊天流的回复意愿"""
|
||||
async with self.lock:
|
||||
return self.chat_reply_willing.get(chat_id, 0)
|
||||
|
||||
async def set_willing(self, chat_id: str, willing: float):
|
||||
"""设置指定聊天流的回复意愿"""
|
||||
async with self.lock:
|
||||
self.chat_reply_willing[chat_id] = willing
|
||||
|
||||
@abstractmethod
|
||||
async def get_variable_parameters(self) -> Dict[str, str]:
|
||||
"""抽象方法:获取可变参数"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def set_variable_parameters(self, parameters: Dict[str, any]):
|
||||
"""抽象方法:设置可变参数"""
|
||||
pass
|
||||
|
||||
|
||||
def init_willing_manager() -> BaseWillingManager:
|
||||
"""
|
||||
根据配置初始化并返回对应的WillingManager实例
|
||||
|
||||
@@ -24,20 +171,7 @@ def init_willing_manager() -> Optional[object]:
|
||||
对应mode的WillingManager实例
|
||||
"""
|
||||
mode = global_config.willing_mode.lower()
|
||||
|
||||
if mode == "classical":
|
||||
logger.info("使用经典回复意愿管理器")
|
||||
return ClassicalWillingManager()
|
||||
elif mode == "dynamic":
|
||||
logger.info("使用动态回复意愿管理器")
|
||||
return DynamicWillingManager()
|
||||
elif mode == "custom":
|
||||
logger.warning(f"自定义的回复意愿管理器模式: {mode}")
|
||||
return CustomWillingManager()
|
||||
else:
|
||||
logger.warning(f"未知的回复意愿管理器模式: {mode}, 将使用经典模式")
|
||||
return ClassicalWillingManager()
|
||||
|
||||
return BaseWillingManager.create(mode)
|
||||
|
||||
# 全局willing_manager对象
|
||||
willing_manager = init_willing_manager()
|
||||
|
||||
Reference in New Issue
Block a user