diff --git a/src/common/logger.py b/src/common/logger.py index 43972e1f2..b5317d58b 100644 --- a/src/common/logger.py +++ b/src/common/logger.py @@ -621,22 +621,22 @@ CHAT_IMAGE_STYLE_CONFIG = { }, } -# 兴趣log -INTEREST_STYLE_CONFIG = { +# HFC log +HFC_STYLE_CONFIG = { "advanced": { "console_format": ( "{time:YYYY-MM-DD HH:mm:ss} | " "{level: <8} | " - "兴趣 | " + "专注聊天 | " "{message}" ), - "file_format": "{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {extra[module]: <15} | 兴趣 | {message}", + "file_format": "{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {extra[module]: <15} | 专注聊天 | {message}", }, "simple": { "console_format": ( - "{time:MM-DD HH:mm} | 兴趣 | {message}" + "{time:MM-DD HH:mm} | 专注聊天 | {message}" ), - "file_format": "{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {extra[module]: <15} | 兴趣 | {message}", + "file_format": "{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {extra[module]: <15} | 专注聊天 | {message}", }, } @@ -847,7 +847,7 @@ CONFIG_STYLE_CONFIG = CONFIG_STYLE_CONFIG["simple"] if SIMPLE_OUTPUT else CONFIG TOOL_USE_STYLE_CONFIG = TOOL_USE_STYLE_CONFIG["simple"] if SIMPLE_OUTPUT else TOOL_USE_STYLE_CONFIG["advanced"] PFC_STYLE_CONFIG = PFC_STYLE_CONFIG["simple"] if SIMPLE_OUTPUT else PFC_STYLE_CONFIG["advanced"] LPMM_STYLE_CONFIG = LPMM_STYLE_CONFIG["simple"] if SIMPLE_OUTPUT else LPMM_STYLE_CONFIG["advanced"] -INTEREST_STYLE_CONFIG = INTEREST_STYLE_CONFIG["simple"] if SIMPLE_OUTPUT else INTEREST_STYLE_CONFIG["advanced"] +HFC_STYLE_CONFIG = HFC_STYLE_CONFIG["simple"] if SIMPLE_OUTPUT else HFC_STYLE_CONFIG["advanced"] TIANYI_STYLE_CONFIG = TIANYI_STYLE_CONFIG["simple"] if SIMPLE_OUTPUT else TIANYI_STYLE_CONFIG["advanced"] MODEL_UTILS_STYLE_CONFIG = MODEL_UTILS_STYLE_CONFIG["simple"] if SIMPLE_OUTPUT else MODEL_UTILS_STYLE_CONFIG["advanced"] PROMPT_STYLE_CONFIG = PROMPT_STYLE_CONFIG["simple"] if SIMPLE_OUTPUT else PROMPT_STYLE_CONFIG["advanced"] diff --git a/src/common/logger_manager.py b/src/common/logger_manager.py index ab1861e2b..5c5538385 100644 --- a/src/common/logger_manager.py +++ b/src/common/logger_manager.py @@ -23,7 +23,7 @@ from src.common.logger import ( PFC_ACTION_PLANNER_STYLE_CONFIG, MAI_STATE_CONFIG, LPMM_STYLE_CONFIG, - INTEREST_STYLE_CONFIG, + HFC_STYLE_CONFIG, TIANYI_STYLE_CONFIG, REMOTE_STYLE_CONFIG, TOPIC_STYLE_CONFIG, @@ -68,7 +68,7 @@ MODULE_LOGGER_CONFIGS = { "pfc_action_planner": PFC_ACTION_PLANNER_STYLE_CONFIG, # PFC私聊规划 "mai_state": MAI_STATE_CONFIG, # 麦麦状态 "lpmm": LPMM_STYLE_CONFIG, # LPMM - "interest": INTEREST_STYLE_CONFIG, # 兴趣 + "hfc": HFC_STYLE_CONFIG, # HFC "tianyi": TIANYI_STYLE_CONFIG, # 天依 "remote": REMOTE_STYLE_CONFIG, # 远程 "topic": TOPIC_STYLE_CONFIG, # 话题 diff --git a/src/do_tool/tool_can_use/base_tool.py b/src/do_tool/tool_can_use/base_tool.py index 47f4a54dc..1dd15bafc 100644 --- a/src/do_tool/tool_can_use/base_tool.py +++ b/src/do_tool/tool_can_use/base_tool.py @@ -62,7 +62,7 @@ def register_tool(tool_class: Type[BaseTool]): raise ValueError(f"工具类 {tool_class.__name__} 没有定义 name 属性") TOOL_REGISTRY[tool_name] = tool_class - logger.info(f"已注册工具: {tool_name}") + logger.info(f"已注册: {tool_name}") def discover_tools(): diff --git a/src/heart_flow/background_tasks.py b/src/heart_flow/background_tasks.py index 93bc50254..56fee2a91 100644 --- a/src/heart_flow/background_tasks.py +++ b/src/heart_flow/background_tasks.py @@ -200,12 +200,12 @@ class BackgroundTaskManager: async def _perform_absent_into_chat(self): """调用llm检测是否转换ABSENT-CHAT状态""" - logger.info("[状态评估任务] 开始基于LLM评估子心流状态...") + logger.debug("[状态评估任务] 开始基于LLM评估子心流状态...") await self.subheartflow_manager.sbhf_absent_into_chat() async def _normal_chat_timeout_check_work(self): """检查处于CHAT状态的子心流是否因长时间未发言而超时,并将其转为ABSENT""" - logger.info("[聊天超时检查] 开始检查处于CHAT状态的子心流...") + logger.debug("[聊天超时检查] 开始检查处于CHAT状态的子心流...") await self.subheartflow_manager.sbhf_chat_into_absent() async def _perform_cleanup_work(self): diff --git a/src/heart_flow/sub_heartflow.py b/src/heart_flow/sub_heartflow.py index 6b9ccd642..4a48e977c 100644 --- a/src/heart_flow/sub_heartflow.py +++ b/src/heart_flow/sub_heartflow.py @@ -299,7 +299,7 @@ class SubHeartflow: chat_stream = chat_manager.get_stream(self.chat_id) self.normal_chat_instance = NormalChat(chat_stream=chat_stream, interest_dict=self.get_interest_dict()) - logger.info(f"{log_prefix} 启动 NormalChat 随便水群...") + logger.info(f"{log_prefix} 开始普通聊天,随便水群...") await self.normal_chat_instance.start_chat() # <--- 修正:调用 start_chat return True except Exception as e: @@ -311,7 +311,7 @@ class SubHeartflow: async def _stop_heart_fc_chat(self): """停止并清理 HeartFChatting 实例""" if self.heart_fc_instance: - logger.info(f"{self.log_prefix} 关闭 HeartFChatting 实例...") + logger.debug(f"{self.log_prefix} 结束专注聊天...") try: await self.heart_fc_instance.shutdown() except Exception as e: @@ -386,7 +386,7 @@ class SubHeartflow: # 移除限额检查逻辑 logger.debug(f"{log_prefix} 准备进入或保持 聊天 状态") if await self._start_normal_chat(): - logger.info(f"{log_prefix} 成功进入或保持 NormalChat 状态。") + # logger.info(f"{log_prefix} 成功进入或保持 NormalChat 状态。") state_changed = True else: logger.error(f"{log_prefix} 启动 NormalChat 失败,无法进入 CHAT 状态。") @@ -416,7 +416,7 @@ class SubHeartflow: self.history_chat_state.append((current_state, self.chat_state_last_time)) logger.info( - f"{log_prefix} 麦麦的聊天状态从 {current_state.value} (持续了 {self.chat_state_last_time} 秒) 变更为 {new_state.value}" + f"{log_prefix} 麦麦的聊天状态从 {current_state.value} (持续了 {int(self.chat_state_last_time)} 秒) 变更为 {new_state.value}" ) self.chat_state.chat_status = new_state diff --git a/src/heart_flow/subheartflow_manager.py b/src/heart_flow/subheartflow_manager.py index b084d0385..fe555ea2d 100644 --- a/src/heart_flow/subheartflow_manager.py +++ b/src/heart_flow/subheartflow_manager.py @@ -1,7 +1,7 @@ import asyncio import time import random -from typing import Dict, Any, Optional, List +from typing import Dict, Any, Optional, List, Tuple import json # 导入 json 模块 import functools # <-- 新增导入 @@ -23,6 +23,7 @@ from src.individuality.individuality import Individuality import traceback + # 初始化日志记录器 logger = get_logger("subheartflow_manager") @@ -358,7 +359,7 @@ class SubHeartflowManager: # 3. 检查 CHAT 上限 current_chat_count = self.count_subflows_by_state_nolock(ChatState.CHAT) if current_chat_count >= chat_limit: - logger.debug( + logger.info( f"{log_prefix} 想看看能不能聊,但是聊天太多了, ({current_chat_count}/{chat_limit}) 满了。" ) return # 满了,这次就算了 @@ -419,14 +420,22 @@ class SubHeartflowManager: # --- 结束修改 --- # --- 4. LLM 评估是否想聊 --- - yao_kai_shi_liao_ma = await self._llm_evaluate_state_transition(prompt) + yao_kai_shi_liao_ma, reason = await self._llm_evaluate_state_transition(prompt) + + if reason: + if yao_kai_shi_liao_ma: + logger.info(f"{log_prefix} 打算开始聊,原因是: {reason}") + else: + logger.info(f"{log_prefix} 不打算聊,原因是: {reason}") + else: + logger.info(f"{log_prefix} 结果: {yao_kai_shi_liao_ma}") if yao_kai_shi_liao_ma is None: logger.debug(f"{log_prefix} 问AI想不想聊失败了,这次算了。") return # 评估失败,结束 if not yao_kai_shi_liao_ma: - logger.info(f"{log_prefix} 现在不想聊这个群。") + # logger.info(f"{log_prefix} 现在不想聊这个群。") return # 不想聊,结束 # --- 5. AI想聊,再次检查额度并尝试转换 --- @@ -434,7 +443,7 @@ class SubHeartflowManager: current_chat_count_before_change = self.count_subflows_by_state_nolock(ChatState.CHAT) if current_chat_count_before_change < chat_limit: logger.info( - f"{log_prefix} 想聊,而且还有空位 ({current_chat_count_before_change}/{chat_limit}),这就去聊!" + f"{log_prefix} 想聊,而且还有精力 ({current_chat_count_before_change}/{chat_limit}),这就去聊!" ) await sub_hf_to_evaluate.change_chat_state(ChatState.CHAT) # 确认转换成功 @@ -492,7 +501,7 @@ class SubHeartflowManager: should_deactivate = True reason = f"超过 {NORMAL_CHAT_TIMEOUT_SECONDS / 60:.0f} 分钟没 BB" logger.info( - f"{log_prefix} 检测到超时 ({reason}),准备转为 ABSENT。上次活动时间: {last_bot_dong_zuo_time:.0f}" + f"{log_prefix} 太久没有发言 ({reason}),不看了。上次活动时间: {last_bot_dong_zuo_time:.0f}" ) # else: # logger.debug(f"{log_prefix} Bot活动时间未超时 ({time_since_last_bb:.0f}s < {NORMAL_CHAT_TIMEOUT_SECONDS}s),保持 CHAT 状态。") @@ -509,25 +518,24 @@ class SubHeartflowManager: # --- 执行状态转换(如果超时) --- if should_deactivate: - logger.info(f"{log_prefix} 因超时 ({reason}),尝试转换为 ABSENT 状态。") + logger.debug(f"{log_prefix} 因超时 ({reason}),尝试转换为 ABSENT 状态。") await sub_hf.change_chat_state(ChatState.ABSENT) # 再次检查确保状态已改变 if sub_hf.chat_state.chat_status == ChatState.ABSENT: transitioned_to_absent += 1 - logger.info(f"{log_prefix} 已成功转换为 ABSENT 状态。") + logger.info(f"{log_prefix} 不看了。") else: logger.warning(f"{log_prefix} 尝试因超时转换为 ABSENT 失败。") if transitioned_to_absent > 0: - logger.info( + logger.debug( f"{log_prefix_task} 完成,共检查 {checked_count} 个子心流,{transitioned_to_absent} 个因超时转为 ABSENT。" ) - # else: - # logger.debug(f"{log_prefix_task} 完成,共检查 {checked_count} 个子心流,无超时转换。") + # --- 结束新增 --- - async def _llm_evaluate_state_transition(self, prompt: str) -> Optional[bool]: + async def _llm_evaluate_state_transition(self, prompt: str) -> Tuple[Optional[bool], Optional[str]]: """ 使用 LLM 评估是否应进行状态转换,期望 LLM 返回 JSON 格式。 @@ -544,7 +552,7 @@ class SubHeartflowManager: response_text, _ = await self.llm_state_evaluator.generate_response_async(prompt) # logger.debug(f"{log_prefix} 使用模型 {self.llm_state_evaluator.model_name} 评估") logger.debug(f"{log_prefix} 原始输入: {prompt}") - logger.debug(f"{log_prefix} 原始响应: {response_text}") + logger.debug(f"{log_prefix} 原始评估结果: {response_text}") # --- 解析 JSON 响应 --- try: @@ -555,34 +563,36 @@ class SubHeartflowManager: data = json.loads(cleaned_response) decision = data.get("decision") # 使用 .get() 避免 KeyError + reason = data.get("reason") if isinstance(decision, bool): logger.debug(f"{log_prefix} LLM评估结果 (来自JSON): {'建议转换' if decision else '建议不转换'}") - return decision + + return decision , reason else: logger.warning( f"{log_prefix} LLM 返回的 JSON 中 'decision' 键的值不是布尔型: {decision}。响应: {response_text}" ) - return None # 值类型不正确 + return None, None # 值类型不正确 except json.JSONDecodeError as json_err: logger.warning(f"{log_prefix} LLM 返回的响应不是有效的 JSON: {json_err}。响应: {response_text}") # 尝试在非JSON响应中查找关键词作为后备方案 (可选) if "true" in response_text.lower(): logger.debug(f"{log_prefix} 在非JSON响应中找到 'true',解释为建议转换") - return True + return True, None if "false" in response_text.lower(): logger.debug(f"{log_prefix} 在非JSON响应中找到 'false',解释为建议不转换") - return False - return None # JSON 解析失败,也未找到关键词 + return False, None + return None, None # JSON 解析失败,也未找到关键词 except Exception as parse_err: # 捕获其他可能的解析错误 logger.warning(f"{log_prefix} 解析 LLM JSON 响应时发生意外错误: {parse_err}。响应: {response_text}") - return None + return None, None except Exception as e: logger.error(f"{log_prefix} 调用 LLM 或处理其响应时出错: {e}", exc_info=True) traceback.print_exc() - return None # LLM 调用或处理失败 + return None, None # LLM 调用或处理失败 def count_subflows_by_state(self, state: ChatState) -> int: """统计指定状态的子心流数量""" diff --git a/src/plugins/chat/message_sender.py b/src/plugins/chat/message_sender.py index 0a2199f38..493397bbd 100644 --- a/src/plugins/chat/message_sender.py +++ b/src/plugins/chat/message_sender.py @@ -159,16 +159,16 @@ class MessageManager: logger.warning("Processor task already running.") return self._processor_task = asyncio.create_task(self._start_processor_loop()) - logger.info("MessageManager processor task started.") + logger.debug("MessageManager processor task started.") def stop(self): """停止后台处理器任务。""" self._running = False if hasattr(self, "_processor_task") and not self._processor_task.done(): self._processor_task.cancel() - logger.info("MessageManager processor task stopping.") + logger.debug("MessageManager processor task stopping.") else: - logger.info("MessageManager processor task not running or already stopped.") + logger.debug("MessageManager processor task not running or already stopped.") async def get_container(self, chat_id: str) -> MessageContainer: """获取或创建聊天流的消息容器 (异步,使用锁)""" diff --git a/src/plugins/emoji_system/emoji_manager.py b/src/plugins/emoji_system/emoji_manager.py index 501e4e89e..72af602fa 100644 --- a/src/plugins/emoji_system/emoji_manager.py +++ b/src/plugins/emoji_system/emoji_manager.py @@ -106,7 +106,7 @@ class MaiEmoji: os.remove(destination_path) os.rename(source_path, destination_path) - logger.info(f"[移动] 文件从 {source_path} 移动到 {destination_path}") + logger.debug(f"[移动] 文件从 {source_path} 移动到 {destination_path}") # 更新实例的路径属性为新目录 self.path = EMOJI_REGISTED_DIR except Exception as move_error: @@ -131,7 +131,7 @@ class MaiEmoji: # 使用upsert确保记录存在或被更新 db["emoji"].update_one({"hash": self.hash}, {"$set": emoji_record}, upsert=True) - logger.success(f"[注册] 表情包信息保存到数据库: {self.description}") + logger.success(f"[注册] 表情包信息保存到数据库: {self.description[:30]}...") return True @@ -158,7 +158,7 @@ class MaiEmoji: if os.path.exists(os.path.join(self.path, self.filename)): try: os.remove(os.path.join(self.path, self.filename)) - logger.info(f"[删除] 文件: {os.path.join(self.path, self.filename)}") + logger.debug(f"[删除] 文件: {os.path.join(self.path, self.filename)}") except Exception as e: logger.error(f"[错误] 删除文件失败 {os.path.join(self.path, self.filename)}: {str(e)}") # 继续执行,即使文件删除失败也尝试删除数据库记录 @@ -168,7 +168,7 @@ class MaiEmoji: deleted_in_db = result.deleted_count > 0 if deleted_in_db: - logger.success(f"[删除] 成功删除表情包记录: {self.description}") + logger.info(f"[删除] 表情包 {self.filename} 无对应文件,已删除") # 3. 标记对象已被删除 self.is_deleted = True @@ -195,7 +195,7 @@ class EmojiManager: self._scan_task = None self.vlm = LLMRequest(model=global_config.vlm, temperature=0.3, max_tokens=1000, request_type="emoji") self.llm_emotion_judge = LLMRequest( - model=global_config.llm_summary, max_tokens=600, temperature=0.8, request_type="emoji" + model=global_config.llm_normal, max_tokens=600, request_type="emoji" ) # 更高的温度,更少的token(后续可以根据情绪来调整温度) self.emoji_num = 0 @@ -682,7 +682,7 @@ class EmojiManager: if register_success: self.emoji_objects.append(new_emoji) self.emoji_num += 1 - logger.success(f"[成功] 注册表情包: {new_emoji.description}") + logger.success(f"[成功] 注册: {new_emoji.filename}") return True else: logger.error(f"[错误] 注册表情包到数据库失败: {new_emoji.filename}") @@ -719,10 +719,10 @@ class EmojiManager: # 调用AI获取描述 if image_format == "gif" or image_format == "GIF": image_base64 = image_manager.transform_gif(image_base64) - prompt = "这是一个动态图表情包,每一张图代表了动态图的某一帧,黑色背景代表透明,描述一下表情包表达的情感和内容,你可以关注其幽默和讽刺意味,必须从互联网梗,meme的角度去分析" + prompt = "这是一个动态图表情包,每一张图代表了动态图的某一帧,黑色背景代表透明,描述一下表情包表达的情感和内容,你可以关注其幽默和讽刺意味,动用贴吧,微博,小红书的知识,必须从互联网梗,meme的角度去分析" description, _ = await self.vlm.generate_response_for_image(prompt, image_base64, "jpg") else: - prompt = "这是一个表情包,请详细描述一下表情包所表达的情感和内容,你可以关注其幽默和讽刺意味,必须从互联网梗,meme的角度去分析" + prompt = "这是一个表情包,请详细描述一下表情包所表达的情感和内容,你可以关注其幽默和讽刺意味,动用贴吧,微博,小红书的知识,必须从互联网梗,meme的角度去分析" description, _ = await self.vlm.generate_response_for_image(prompt, image_base64, image_format) # 审核表情包 @@ -797,7 +797,7 @@ class EmojiManager: if register_success: self.emoji_objects.append(new_emoji) self.emoji_num += 1 - logger.success(f"[成功] 注册表情包: {filename}") + logger.success(f"[成功] 注册: {filename}") return True else: logger.error(f"[错误] 注册表情包到数据库失败: {filename}") @@ -814,7 +814,7 @@ class EmojiManager: 当目录中文件数超过50时,会全部删除 """ - logger.info("[清理] 开始清理临时表情包...") + logger.info("[清理] 开始清理缓存...") # 清理emoji目录 emoji_dir = os.path.join(BASE_DIR, "emoji") @@ -826,7 +826,7 @@ class EmojiManager: file_path = os.path.join(emoji_dir, filename) if os.path.isfile(file_path): os.remove(file_path) - logger.debug(f"[清理] 删除表情包文件: {filename}") + logger.debug(f"[清理] 删除: {filename}") # 清理image目录 image_dir = os.path.join(BASE_DIR, "image") @@ -838,14 +838,19 @@ class EmojiManager: file_path = os.path.join(image_dir, filename) if os.path.isfile(file_path): os.remove(file_path) - logger.debug(f"[清理] 删除图片文件: {filename}") + logger.debug(f"[清理] 删除图片: {filename}") - logger.success("[清理] 临时文件清理完成") + logger.success("[清理] 完成") async def clean_unused_emojis(self, emoji_dir, emoji_objects): """清理未使用的表情包文件 遍历指定文件夹中的所有文件,删除未在emoji_objects列表中的文件 """ + # 首先检查目录是否存在喵~ + if not os.path.exists(emoji_dir): + logger.warning(f"[清理] 表情包目录不存在,跳过清理: {emoji_dir}") + return + # 获取所有表情包路径 emoji_paths = {emoji.path for emoji in emoji_objects} diff --git a/src/plugins/heartFC_chat/heartFC_chat.py b/src/plugins/heartFC_chat/heartFC_chat.py index 99b76f035..bfdf2d6ae 100644 --- a/src/plugins/heartFC_chat/heartFC_chat.py +++ b/src/plugins/heartFC_chat/heartFC_chat.py @@ -37,7 +37,7 @@ EMOJI_SEND_PRO = 0.3 # 设置一个概率,比如 30% 才真的发 CONSECUTIVE_NO_REPLY_THRESHOLD = 3 # 连续不回复的阈值 -logger = get_logger("interest") # Logger Name Changed +logger = get_logger("HFC") # Logger Name Changed # 默认动作定义 diff --git a/src/plugins/willing/willing_manager.py b/src/plugins/willing/willing_manager.py index 4b105ec95..78c86e258 100644 --- a/src/plugins/willing/willing_manager.py +++ b/src/plugins/willing/willing_manager.py @@ -77,7 +77,7 @@ class BaseWillingManager(ABC): 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}") + logger.info(f"普通回复模式:{manager_type}") return manager_class() except (ImportError, AttributeError, TypeError) as e: module = importlib.import_module(".mode_classical", __package__)