diff --git a/changelogs/changelog.md b/changelogs/changelog.md index 8fe8c5e32..bef8ab146 100644 --- a/changelogs/changelog.md +++ b/changelogs/changelog.md @@ -17,6 +17,9 @@ - 私聊强制开启focus模式 - 支持解析reply_to和at - 修复focus冷却时间导致的固定沉默 +- 移除豆包画图插件,此插件现在插件广场提供 +- 修复表达器无法读取原始文本 +- 修复normal planner没有超时退出问题 diff --git a/src/chat/heart_flow/sub_heartflow.py b/src/chat/heart_flow/sub_heartflow.py index 98bc07337..cd417f872 100644 --- a/src/chat/heart_flow/sub_heartflow.py +++ b/src/chat/heart_flow/sub_heartflow.py @@ -368,16 +368,6 @@ class SubHeartflow: return self.normal_chat_instance.get_action_manager() return None - def set_normal_chat_planner_enabled(self, enabled: bool): - """设置NormalChat的planner是否启用 - - Args: - enabled: 是否启用planner - """ - if self.normal_chat_instance: - self.normal_chat_instance.set_planner_enabled(enabled) - else: - logger.warning(f"{self.log_prefix} NormalChat实例不存在,无法设置planner状态") async def get_full_state(self) -> dict: """获取子心流的完整状态,包括兴趣、思维和聊天状态。""" diff --git a/src/chat/message_receive/message_sender.py b/src/chat/message_receive/message_sender.py index 6cb256d32..e54f37d12 100644 --- a/src/chat/message_receive/message_sender.py +++ b/src/chat/message_receive/message_sender.py @@ -9,7 +9,6 @@ from src.common.message.api import get_global_api from .message import MessageSending, MessageThinking, MessageSet from src.chat.message_receive.storage import MessageStorage -from ...config.config import global_config from ..utils.utils import truncate_message, calculate_typing_time, count_messages_between from src.common.logger import get_logger @@ -192,19 +191,6 @@ class MessageManager: container = await self.get_container(chat_stream.stream_id) container.add_message(message) - def check_if_sending_message_exist(self, chat_id, thinking_id): - """检查指定聊天流的容器中是否存在具有特定 thinking_id 的 MessageSending 消息 或 emoji 消息""" - # 这个方法现在是非异步的,因为它只读取数据 - container = self.containers.get(chat_id) # 直接 get,因为读取不需要锁 - if container and container.has_messages(): - for message in container.get_all_messages(): - if isinstance(message, MessageSending): - msg_id = getattr(message.message_info, "message_id", None) - # 检查 message_id 是否匹配 thinking_id 或以 "me" 开头 (emoji) - if msg_id == thinking_id or (msg_id and msg_id.startswith("me")): - # logger.debug(f"检查到存在相同thinking_id或emoji的消息: {msg_id} for {thinking_id}") - return True - return False async def _handle_sending_message(self, container: MessageContainer, message: MessageSending): """处理单个 MessageSending 消息 (包含 set_reply 逻辑)""" @@ -216,12 +202,7 @@ class MessageManager: thinking_messages_count, thinking_messages_length = count_messages_between( start_time=thinking_start_time, end_time=now_time, stream_id=message.chat_stream.stream_id ) - # print(f"message.reply:{message.reply}") - # --- 条件应用 set_reply 逻辑 --- - # logger.debug( - # f"[message.apply_set_reply_logic:{message.apply_set_reply_logic},message.is_head:{message.is_head},thinking_messages_count:{thinking_messages_count},thinking_messages_length:{thinking_messages_length},message.is_private_message():{message.is_private_message()}]" - # ) if ( message.is_head and (thinking_messages_count > 3 or thinking_messages_length > 200) @@ -277,14 +258,6 @@ class MessageManager: flush=True, ) - # 检查是否超时 - if thinking_time > global_config.normal_chat.thinking_timeout: - logger.warning( - f"[{chat_id}] 消息思考超时 ({thinking_time:.1f}秒),移除消息 {message_earliest.message_info.message_id}" - ) - container.remove_message(message_earliest) - print() # 超时后换行,避免覆盖下一条日志 - elif isinstance(message_earliest, MessageSending): # --- 处理发送消息 --- await self._handle_sending_message(container, message_earliest) @@ -301,12 +274,6 @@ class MessageManager: logger.info(f"[{chat_id}] 处理超时发送消息: {msg.message_info.message_id}") await self._handle_sending_message(container, msg) # 复用处理逻辑 - # 清理空容器 (可选) - # async with self._container_lock: - # if not container.has_messages() and chat_id in self.containers: - # logger.debug(f"[{chat_id}] 容器已空,准备移除。") - # del self.containers[chat_id] - async def _start_processor_loop(self): """消息处理器主循环""" while self._running: diff --git a/src/chat/normal_chat/normal_chat.py b/src/chat/normal_chat/normal_chat.py index d88b9167f..128ce94d7 100644 --- a/src/chat/normal_chat/normal_chat.py +++ b/src/chat/normal_chat/normal_chat.py @@ -28,7 +28,6 @@ from .priority_manager import PriorityManager import traceback from .normal_chat_generator import NormalChatGenerator -from src.chat.normal_chat.normal_chat_expressor import NormalChatExpressor from src.chat.normal_chat.normal_chat_planner import NormalChatPlanner from src.chat.normal_chat.normal_chat_action_modifier import NormalChatActionModifier @@ -72,9 +71,6 @@ class NormalChat: self.stream_name = get_chat_manager().get_stream_name(self.stream_id) or self.stream_id - # 初始化Normal Chat专用表达器 - self.expressor = NormalChatExpressor(self.chat_stream) - # Interest dict self.interest_dict = interest_dict @@ -120,6 +116,8 @@ class NormalChat: self.get_cooldown_progress_callback = get_cooldown_progress_callback self._disabled = False # 增加停用标志 + + self.timeout_count = 0 # 加载持久化的缓存 self._load_cache() @@ -490,14 +488,10 @@ class NormalChat: logger.info( f"[{self.stream_name}] 从队列中取出消息进行处理: User {message.message_info.user_info.user_id}, Time: {time.strftime('%H:%M:%S', time.localtime(message.message_info.time))}" ) - # 执行定期清理 - self._cleanup_old_segments() - # 更新消息段信息 - self._update_user_message_segments(message) # 检查是否有用户满足关系构建条件 - asyncio.create_task(self._check_relation_building_conditions()) + asyncio.create_task(self._check_relation_building_conditions(message)) await self.reply_one_message(message) @@ -722,18 +716,9 @@ class NormalChat: if self.priority_manager: self.priority_manager.add_message(message) return - - # --- 以下为原有的 "兴趣" 模式逻辑 --- - await self._process_message(message, is_mentioned, interested_rate) - - async def _process_message(self, message: MessageRecv, is_mentioned: bool, interested_rate: float) -> None: - """ - 实际处理单条消息的逻辑,包括意愿判断、回复生成、动作执行等。 - """ - if self._disabled: - return - - # 新增:在auto模式下检查是否需要直接切换到focus模式 + + + # 新增:在auto模式下检查是否需要直接切换到focus模式 if global_config.chat.chat_mode == "auto": if await self._check_should_switch_to_focus(): logger.info(f"[{self.stream_name}] 检测到切换到focus聊天模式的条件,尝试执行切换") @@ -747,14 +732,20 @@ class NormalChat: else: logger.warning(f"[{self.stream_name}] 没有设置切换到focus聊天模式的回调函数,无法执行切换") - # 执行定期清理 - self._cleanup_old_segments() + # --- 以下为原有的 "兴趣" 模式逻辑 --- + await self._process_message(message, is_mentioned, interested_rate) + + async def _process_message(self, message: MessageRecv, is_mentioned: bool, interested_rate: float) -> None: + """ + 实际处理单条消息的逻辑,包括意愿判断、回复生成、动作执行等。 + """ + if self._disabled: + return + - # 更新消息段信息 - self._update_user_message_segments(message) # 检查是否有用户满足关系构建条件 - asyncio.create_task(self._check_relation_building_conditions()) + asyncio.create_task(self._check_relation_building_conditions(message)) timing_results = {} reply_probability = ( @@ -776,6 +767,10 @@ class NormalChat: reply_probability += message.message_info.additional_config["maimcore_reply_probability_gain"] reply_probability = min(max(reply_probability, 0), 1) # 确保概率在 0-1 之间 + # 处理表情包 + if message.is_emoji or message.is_picid: + reply_probability = 0 + # 应用疲劳期回复频率调整 fatigue_multiplier = self._get_fatigue_reply_multiplier() original_probability = reply_probability @@ -804,6 +799,8 @@ class NormalChat: await willing_manager.before_generate_reply_handle(message.message_info.message_id) do_reply = await self.reply_one_message(message) response_set = do_reply if do_reply else None + + # 输出性能计时结果 if do_reply and response_set: # 确保 response_set 不是 None timing_str = " | ".join([f"{step}: {duration:.2f}秒" for step, duration in timing_results.items()]) @@ -855,8 +852,6 @@ class NormalChat: return None try: - # 获取发送者名称(动作修改已在并行执行前完成) - sender_name = self._get_sender_name(message) no_action = { "action_result": { @@ -876,7 +871,7 @@ class NormalChat: return no_action # 执行规划 - plan_result = await self.planner.plan(message, sender_name) + plan_result = await self.planner.plan(message) action_type = plan_result["action_result"]["action_type"] action_data = plan_result["action_result"]["action_data"] reasoning = plan_result["action_result"]["reasoning"] @@ -914,9 +909,35 @@ class NormalChat: # 并行执行回复生成和动作规划 self.action_type = None # 初始化动作类型 self.is_parallel_action = False # 初始化并行动作标志 - response_set, plan_result = await asyncio.gather( - generate_normal_response(), plan_and_execute_actions(), return_exceptions=True - ) + + gen_task = asyncio.create_task(generate_normal_response()) + plan_task = asyncio.create_task(plan_and_execute_actions()) + + try: + gather_timeout = global_config.normal_chat.thinking_timeout + results = await asyncio.wait_for( + asyncio.gather(gen_task, plan_task, return_exceptions=True), + timeout=gather_timeout, + ) + response_set, plan_result = results + except asyncio.TimeoutError: + logger.warning(f"[{self.stream_name}] 并行执行回复生成和动作规划超时 ({gather_timeout}秒),正在取消相关任务...") + self.timeout_count += 1 + if self.timeout_count > 5: + logger.error(f"[{self.stream_name}] 连续回复超时,{global_config.normal_chat.thinking_timeout}秒 内大模型没有返回有效内容,请检查你的api是否速度过慢或配置错误。建议不要使用推理模型,推理模型生成速度过慢。") + return False + + # 取消未完成的任务 + if not gen_task.done(): + gen_task.cancel() + if not plan_task.done(): + plan_task.cancel() + + # 清理思考消息 + await self._cleanup_thinking_message_by_id(thinking_id) + + response_set = None + plan_result = None # 处理生成回复的结果 if isinstance(response_set, Exception): @@ -937,14 +958,7 @@ class NormalChat: elif self.enable_planner and self.action_type not in ["no_action"] and not self.is_parallel_action: logger.info(f"[{self.stream_name}] 模型选择其他动作(非并行动作)") # 如果模型未生成回复,移除思考消息 - container = await message_manager.get_container(self.stream_id) # 使用 self.stream_id - for msg in container.messages[:]: - if isinstance(msg, MessageThinking) and msg.message_info.message_id == thinking_id: - container.messages.remove(msg) - logger.debug(f"[{self.stream_name}] 已移除未产生回复的思考消息 {thinking_id}") - break - # 需要在此处也调用 not_reply_handle 和 delete 吗? - # 如果是因为模型没回复,也算是一种 "未回复" + await self._cleanup_thinking_message_by_id(thinking_id) return False # logger.info(f"[{self.stream_name}] 回复内容: {response_set}") @@ -969,9 +983,7 @@ class NormalChat: "user_nickname": message.message_info.user_info.user_nickname, }, "response": response_set, - # "is_mentioned": is_mentioned, "is_reference_reply": message.reply is not None, # 判断是否为引用回复 - # "timing": {k: round(v, 2) for k, v in timing_results.items()}, } self.recent_replies.append(reply_info) # 保持最近回复历史在限定数量内 @@ -1198,18 +1210,6 @@ class NormalChat: f"意愿放大器更新为: {self.willing_amplifier:.2f}" ) - def _get_sender_name(self, message: MessageRecv) -> str: - """获取发送者名称,用于planner""" - if message.chat_stream.user_info: - user_info = message.chat_stream.user_info - if user_info.user_cardname and user_info.user_nickname: - return f"[{user_info.user_nickname}][群昵称:{user_info.user_cardname}]" - elif user_info.user_nickname: - return f"[{user_info.user_nickname}]" - else: - return f"用户({user_info.user_id})" - return "某人" - async def _execute_action( self, action_type: str, action_data: dict, message: MessageRecv, thinking_id: str ) -> Optional[bool]: @@ -1246,17 +1246,18 @@ class NormalChat: return False - def set_planner_enabled(self, enabled: bool): - """设置是否启用planner""" - self.enable_planner = enabled - logger.info(f"[{self.stream_name}] Planner {'启用' if enabled else '禁用'}") - def get_action_manager(self) -> ActionManager: """获取动作管理器实例""" return self.action_manager - async def _check_relation_building_conditions(self): + async def _check_relation_building_conditions(self, message: MessageRecv): """检查person_engaged_cache中是否有满足关系构建条件的用户""" + # 执行定期清理 + self._cleanup_old_segments() + + # 更新消息段信息 + self._update_user_message_segments(message) + users_to_build_relationship = [] for person_id, segments in list(self.person_engaged_cache.items()): @@ -1401,3 +1402,16 @@ class NormalChat: ) return should_switch + + async def _cleanup_thinking_message_by_id(self, thinking_id: str): + """根据ID清理思考消息""" + try: + container = await message_manager.get_container(self.stream_id) + if container: + for msg in container.messages[:]: + if isinstance(msg, MessageThinking) and msg.message_info.message_id == thinking_id: + container.messages.remove(msg) + logger.info(f"[{self.stream_name}] 已清理思考消息 {thinking_id}") + break + except Exception as e: + logger.error(f"[{self.stream_name}] 清理思考消息 {thinking_id} 时出错: {e}") diff --git a/src/chat/normal_chat/normal_chat_expressor.py b/src/chat/normal_chat/normal_chat_expressor.py deleted file mode 100644 index c89ad8534..000000000 --- a/src/chat/normal_chat/normal_chat_expressor.py +++ /dev/null @@ -1,262 +0,0 @@ -""" -Normal Chat Expressor - -为Normal Chat专门设计的表达器,不需要经过LLM风格化处理, -直接发送消息,主要用于插件动作中需要发送消息的场景。 -""" - -import time -from typing import List, Optional, Tuple, Dict, Any -from src.chat.message_receive.message import MessageRecv, MessageSending, MessageThinking, Seg -from src.chat.message_receive.message import UserInfo -from src.chat.message_receive.chat_stream import ChatStream, get_chat_manager -from src.chat.message_receive.message_sender import message_manager -from src.config.config import global_config -from src.common.logger import get_logger - -logger = get_logger("normal_chat_expressor") - - -class NormalChatExpressor: - """Normal Chat专用表达器 - - 特点: - 1. 不经过LLM风格化,直接发送消息 - 2. 支持文本和表情包发送 - 3. 为插件动作提供简化的消息发送接口 - 4. 保持与focus_chat expressor相似的API,但去掉复杂的风格化流程 - """ - - def __init__(self, chat_stream: ChatStream): - """初始化Normal Chat表达器 - - Args: - chat_stream: 聊天流对象 - stream_name: 流名称 - """ - self.chat_stream = chat_stream - self.stream_name = get_chat_manager().get_stream_name(self.chat_stream.stream_id) or self.chat_stream.stream_id - self.log_prefix = f"[{self.stream_name}]Normal表达器" - - logger.debug(f"{self.log_prefix} 初始化完成") - - async def create_thinking_message( - self, anchor_message: Optional[MessageRecv], thinking_id: str - ) -> Optional[MessageThinking]: - """创建思考消息 - - Args: - anchor_message: 锚点消息 - thinking_id: 思考ID - - Returns: - MessageThinking: 创建的思考消息,如果失败返回None - """ - if not anchor_message or not anchor_message.chat_stream: - logger.error(f"{self.log_prefix} 无法创建思考消息,缺少有效的锚点消息或聊天流") - return None - - messageinfo = anchor_message.message_info - thinking_time_point = time.time() - - bot_user_info = UserInfo( - user_id=global_config.bot.qq_account, - user_nickname=global_config.bot.nickname, - platform=messageinfo.platform, - ) - - thinking_message = MessageThinking( - message_id=thinking_id, - chat_stream=self.chat_stream, - bot_user_info=bot_user_info, - reply=anchor_message, - thinking_start_time=thinking_time_point, - ) - - await message_manager.add_message(thinking_message) - logger.debug(f"{self.log_prefix} 创建思考消息: {thinking_id}") - return thinking_message - - async def send_response_messages( - self, - anchor_message: Optional[MessageRecv], - response_set: List[Tuple[str, str]], - thinking_id: str = "", - display_message: str = "", - ) -> Optional[MessageSending]: - """发送回复消息 - - Args: - anchor_message: 锚点消息 - response_set: 回复内容集合,格式为 [(type, content), ...] - thinking_id: 思考ID - display_message: 显示消息 - - Returns: - MessageSending: 发送的第一条消息,如果失败返回None - """ - try: - if not response_set: - logger.warning(f"{self.log_prefix} 回复内容为空") - return None - - # 如果没有thinking_id,生成一个 - if not thinking_id: - thinking_time_point = round(time.time(), 2) - thinking_id = "mt" + str(thinking_time_point) - - # 创建思考消息 - if anchor_message: - await self.create_thinking_message(anchor_message, thinking_id) - - # 创建消息集 - - mark_head = False - is_emoji = False - if len(response_set) == 0: - return None - message_id = f"{thinking_id}_{len(response_set)}" - response_type, content = response_set[0] - if len(response_set) > 1: - message_segment = Seg(type="seglist", data=[Seg(type=t, data=c) for t, c in response_set]) - else: - message_segment = Seg(type=response_type, data=content) - if response_type == "emoji": - is_emoji = True - - bot_msg = await self._build_sending_message( - message_id=message_id, - message_segment=message_segment, - thinking_id=thinking_id, - anchor_message=anchor_message, - thinking_start_time=time.time(), - reply_to=mark_head, - is_emoji=is_emoji, - display_message=display_message, - ) - logger.debug(f"{self.log_prefix} 添加{response_type}类型消息: {content}") - - # 提交消息集 - if bot_msg: - await message_manager.add_message(bot_msg) - logger.info( - f"{self.log_prefix} 成功发送 {response_type}类型消息: {str(content)[:200] + '...' if len(str(content)) > 200 else content}" - ) - container = await message_manager.get_container(self.chat_stream.stream_id) # 使用 self.stream_id - for msg in container.messages[:]: - if isinstance(msg, MessageThinking) and msg.message_info.message_id == thinking_id: - container.messages.remove(msg) - logger.debug(f"[{self.stream_name}] 已移除未产生回复的思考消息 {thinking_id}") - break - return bot_msg - else: - logger.warning(f"{self.log_prefix} 没有有效的消息被创建") - return None - - except Exception as e: - logger.error(f"{self.log_prefix} 发送消息失败: {e}") - import traceback - - traceback.print_exc() - return None - - async def _build_sending_message( - self, - message_id: str, - message_segment: Seg, - thinking_id: str, - anchor_message: Optional[MessageRecv], - thinking_start_time: float, - reply_to: bool = False, - is_emoji: bool = False, - display_message: str = "", - ) -> MessageSending: - """构建发送消息 - - Args: - message_id: 消息ID - message_segment: 消息段 - thinking_id: 思考ID - anchor_message: 锚点消息 - thinking_start_time: 思考开始时间 - reply_to: 是否回复 - is_emoji: 是否为表情包 - - Returns: - MessageSending: 构建的发送消息 - """ - bot_user_info = UserInfo( - user_id=global_config.bot.qq_account, - user_nickname=global_config.bot.nickname, - platform=anchor_message.message_info.platform if anchor_message else "unknown", - ) - - message_sending = MessageSending( - message_id=message_id, - chat_stream=self.chat_stream, - bot_user_info=bot_user_info, - message_segment=message_segment, - sender_info=self.chat_stream.user_info, - reply=anchor_message if reply_to else None, - thinking_start_time=thinking_start_time, - is_emoji=is_emoji, - display_message=display_message, - ) - - return message_sending - - async def deal_reply( - self, - cycle_timers: dict, - action_data: Dict[str, Any], - reasoning: str, - anchor_message: MessageRecv, - thinking_id: str, - ) -> Tuple[bool, Optional[str]]: - """处理回复动作 - 兼容focus_chat expressor API - - Args: - cycle_timers: 周期计时器(normal_chat中不使用) - action_data: 动作数据,包含text、target、emojis等 - reasoning: 推理说明 - anchor_message: 锚点消息 - thinking_id: 思考ID - - Returns: - Tuple[bool, Optional[str]]: (是否成功, 回复文本) - """ - try: - response_set = [] - - # 处理文本内容 - text_content = action_data.get("text", "") - if text_content: - response_set.append(("text", text_content)) - - # 处理表情包 - emoji_content = action_data.get("emojis", "") - if emoji_content: - response_set.append(("emoji", emoji_content)) - - if not response_set: - logger.warning(f"{self.log_prefix} deal_reply: 没有有效的回复内容") - return False, None - - # 发送消息 - result = await self.send_response_messages( - anchor_message=anchor_message, - response_set=response_set, - thinking_id=thinking_id, - ) - - if result: - return True, text_content if text_content else "发送成功" - else: - return False, None - - except Exception as e: - logger.error(f"{self.log_prefix} deal_reply执行失败: {e}") - import traceback - - traceback.print_exc() - return False, None diff --git a/src/chat/normal_chat/normal_chat_planner.py b/src/chat/normal_chat/normal_chat_planner.py index d3f1e8abc..9c4e08433 100644 --- a/src/chat/normal_chat/normal_chat_planner.py +++ b/src/chat/normal_chat/normal_chat_planner.py @@ -72,7 +72,7 @@ class NormalChatPlanner: self.action_manager = action_manager - async def plan(self, message: MessageThinking, sender_name: str = "某人") -> Dict[str, Any]: + async def plan(self, message: MessageThinking) -> Dict[str, Any]: """ Normal Chat 规划器: 使用LLM根据上下文决定做出什么动作。 diff --git a/src/chat/normal_chat/willing/mode_classical.py b/src/chat/normal_chat/willing/mode_classical.py index 3ffe23c46..a6929338c 100644 --- a/src/chat/normal_chat/willing/mode_classical.py +++ b/src/chat/normal_chat/willing/mode_classical.py @@ -33,28 +33,10 @@ class ClassicalWillingManager(BaseWillingManager): if willing_info.is_mentioned_bot: current_willing += 1 if current_willing < 1.0 else 0.05 - is_emoji_not_reply = False - if willing_info.is_emoji: - if global_config.normal_chat.emoji_response_penalty != 0: - current_willing *= global_config.normal_chat.emoji_response_penalty - else: - is_emoji_not_reply = True - - # 处理picid格式消息,直接不回复 - is_picid_not_reply = False - if willing_info.is_picid: - is_picid_not_reply = True - self.chat_reply_willing[chat_id] = min(current_willing, 3.0) reply_probability = min(max((current_willing - 0.5), 0.01) * 2, 1) - if is_emoji_not_reply: - reply_probability = 0 - - if is_picid_not_reply: - reply_probability = 0 - return reply_probability async def before_generate_reply_handle(self, message_id): @@ -71,8 +53,6 @@ class ClassicalWillingManager(BaseWillingManager): if current_willing < 1: self.chat_reply_willing[chat_id] = min(1.0, current_willing + 0.4) - async def bombing_buffer_message_handle(self, message_id): - return await super().bombing_buffer_message_handle(message_id) async def not_reply_handle(self, message_id): return await super().not_reply_handle(message_id) diff --git a/src/chat/normal_chat/willing/mode_custom.py b/src/chat/normal_chat/willing/mode_custom.py index 4b2e8f3c3..36334df43 100644 --- a/src/chat/normal_chat/willing/mode_custom.py +++ b/src/chat/normal_chat/willing/mode_custom.py @@ -17,8 +17,5 @@ class CustomWillingManager(BaseWillingManager): async def get_reply_probability(self, message_id: str): pass - async def bombing_buffer_message_handle(self, message_id: str): - pass - def __init__(self): super().__init__() diff --git a/src/chat/normal_chat/willing/mode_mxp.py b/src/chat/normal_chat/willing/mode_mxp.py index 03651d080..89f6b4757 100644 --- a/src/chat/normal_chat/willing/mode_mxp.py +++ b/src/chat/normal_chat/willing/mode_mxp.py @@ -19,7 +19,6 @@ Mxp 模式:梦溪畔独家赞助 下下策是询问一个菜鸟(@梦溪畔) """ -from src.config.config import global_config from .willing_manager import BaseWillingManager from typing import Dict import asyncio @@ -172,23 +171,11 @@ class MxpWillingManager(BaseWillingManager): self.logger.debug("进行中消息惩罚:归0") probability = self._willing_to_probability(current_willing) - - if w_info.is_emoji: - probability *= global_config.normal_chat.emoji_response_penalty - - if w_info.is_picid: - probability = 0 # picid格式消息直接不回复 - + 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: diff --git a/src/chat/normal_chat/willing/willing_manager.py b/src/chat/normal_chat/willing/willing_manager.py index 47c6bfd0f..9a7ce4857 100644 --- a/src/chat/normal_chat/willing/willing_manager.py +++ b/src/chat/normal_chat/willing/willing_manager.py @@ -20,7 +20,6 @@ before_generate_reply_handle 确定要回复后,在生成回复前的处理 after_generate_reply_handle 确定要回复后,在生成回复后的处理 not_reply_handle 确定不回复后的处理 get_reply_probability 获取回复概率 -bombing_buffer_message_handle 缓冲器炸飞消息后的处理 get_variable_parameters 暂不确定 set_variable_parameters 暂不确定 以下2个方法根据你的实现可以做调整: @@ -137,10 +136,6 @@ class BaseWillingManager(ABC): """抽象方法:获取回复概率""" raise NotImplementedError - @abstractmethod - async def bombing_buffer_message_handle(self, message_id: str): - """抽象方法:炸飞消息处理""" - pass async def get_willing(self, chat_id: str): """获取指定聊天流的回复意愿""" diff --git a/src/config/official_configs.py b/src/config/official_configs.py index f56f0e3d6..3cfeecf51 100644 --- a/src/config/official_configs.py +++ b/src/config/official_configs.py @@ -285,8 +285,6 @@ class NormalChatConfig(ConfigBase): response_interested_rate_amplifier: float = 1.0 """回复兴趣度放大系数""" - emoji_response_penalty: float = 0.0 - """表情包回复惩罚系数""" mentioned_bot_inevitable_reply: bool = False """提及 bot 必然回复""" @@ -297,6 +295,15 @@ class NormalChatConfig(ConfigBase): enable_planner: bool = False """是否启用动作规划器""" + gather_timeout: int = 110 # planner和generator的并行执行超时时间 + """planner和generator的并行执行超时时间""" + + auto_focus_threshold: float = 1.0 # 自动切换到专注模式的阈值,值越大越难触发 + """自动切换到专注模式的阈值,值越大越难触发""" + + fatigue_talk_frequency: float = 0.2 # 疲劳模式下的基础对话频率 (条/分钟) + """疲劳模式下的基础对话频率 (条/分钟)""" + @dataclass class FocusChatConfig(ConfigBase): diff --git a/template/bot_config_template.toml b/template/bot_config_template.toml index 84bca3718..c4ddd21d8 100644 --- a/template/bot_config_template.toml +++ b/template/bot_config_template.toml @@ -1,5 +1,5 @@ [inner] -version = "3.1.0" +version = "3.2.0" #----以下是给开发人员阅读的,如果你只是部署了麦麦,不需要阅读---- #如果你想要修改配置文件,请在修改后将version的值进行变更 @@ -61,7 +61,7 @@ enable_relationship = true # 是否启用关系系统 relation_frequency = 1 # 关系频率,麦麦构建关系的速度,仅在normal_chat模式下有效 [chat] #麦麦的聊天通用设置 -chat_mode = "normal" # 聊天模式 —— 普通模式:normal,专注模式:focus,在普通模式和专注模式之间自动切换 +chat_mode = "normal" # 聊天模式 —— 普通模式:normal,专注模式:focus,自动auto:在普通模式和专注模式之间自动切换 # chat_mode = "focus" # chat_mode = "auto" @@ -116,18 +116,17 @@ ban_msgs_regex = [ [normal_chat] #普通聊天 #一般回复参数 -emoji_chance = 0.2 # 麦麦一般回复时使用表情包的概率,设置为1让麦麦自己决定发不发 -thinking_timeout = 120 # 麦麦最长思考时间,超过这个时间的思考会放弃(往往是api反应太慢) +emoji_chance = 0.2 # 麦麦一般回复时使用表情包的概率 +thinking_timeout = 30 # 麦麦最长思考规划时间,超过这个时间的思考会放弃(往往是api反应太慢) willing_mode = "classical" # 回复意愿模式 —— 经典模式:classical,mxp模式:mxp,自定义模式:custom(需要你自己实现) response_interested_rate_amplifier = 1 # 麦麦回复兴趣度放大系数 -emoji_response_penalty = 0 # 对其他人发的表情包回复惩罚系数,设为0为不回复单个表情包,减少单独回复表情包的概率 mentioned_bot_inevitable_reply = true # 提及 bot 必然回复 at_bot_inevitable_reply = true # @bot 必然回复(包含提及) -enable_planner = false # 是否启用动作规划器(与focus_chat共享actions) +enable_planner = true # 是否启用动作规划器(与focus_chat共享actions) [focus_chat] #专注聊天 @@ -168,7 +167,7 @@ consolidation_check_percentage = 0.05 # 检查节点比例 #不希望记忆的词,已经记忆的不会受到影响,需要手动清理 memory_ban_words = [ "表情包", "图片", "回复", "聊天记录" ] -[mood] # 仅在 普通聊天 有效 +[mood] # 暂时不再有效,请不要使用 enable_mood = false # 是否启用情绪系统 mood_update_interval = 1.0 # 情绪更新间隔 单位秒 mood_decay_rate = 0.95 # 情绪衰减率 @@ -242,7 +241,7 @@ library_log_levels = { "aiohttp" = "WARNING"} # 设置特定库的日志级别 # thinking_budget = : 用于指定模型思考最长长度 [model] -model_max_output_length = 800 # 模型单次返回的最大token数 +model_max_output_length = 1000 # 模型单次返回的最大token数 #------------必填:组件模型------------ @@ -272,11 +271,12 @@ pri_out = 8 #模型的输出价格(非必填,可以记录消耗) temp = 0.2 #模型的温度,新V3建议0.1-0.3 [model.replyer_2] # 次要回复模型 -name = "Pro/deepseek-ai/DeepSeek-R1" +name = "Pro/deepseek-ai/DeepSeek-V3" provider = "SILICONFLOW" -pri_in = 4.0 #模型的输入价格(非必填,可以记录消耗) -pri_out = 16.0 #模型的输出价格(非必填,可以记录消耗) -temp = 0.7 +pri_in = 2 #模型的输入价格(非必填,可以记录消耗) +pri_out = 8 #模型的输出价格(非必填,可以记录消耗) +#默认temp 0.2 如果你使用的是老V3或者其他模型,请自己修改temp参数 +temp = 0.2 #模型的温度,新V3建议0.1-0.3 [model.memory_summary] # 记忆的概括模型