diff --git a/src/heart_flow/background_tasks.py b/src/heart_flow/background_tasks.py index 21254ce78..f5131a59a 100644 --- a/src/heart_flow/background_tasks.py +++ b/src/heart_flow/background_tasks.py @@ -231,7 +231,7 @@ class BackgroundTaskManager: stopped_count += 1 logger.info(f"[Background Task Cleanup] Cleanup cycle finished. Stopped {stopped_count} inactive flows.") # else: - # logger.debug("[Background Task Cleanup] Cleanup cycle finished. No inactive flows found.") + # logger.debug("[Background Task Cleanup] Cleanup cycle finished. No inactive flows found.") async def _perform_logging_work(self): """执行一轮状态日志记录。""" diff --git a/src/heart_flow/sub_mind.py b/src/heart_flow/sub_mind.py index 6b2bdaac3..d8b1f75be 100644 --- a/src/heart_flow/sub_mind.py +++ b/src/heart_flow/sub_mind.py @@ -41,7 +41,7 @@ def init_prompt(): prompt += "3. 如需处理消息或回复,请使用工具\n" Prompt(prompt, "sub_heartflow_prompt_before") - + prompt = "" prompt += "刚刚你的内心想法是:{current_thinking_info}\n" prompt += "{if_replan_prompt}\n" @@ -131,7 +131,7 @@ class SubMind: ("进行深入思考", 0.2), ] - #上一次决策信息 + # 上一次决策信息 if last_cycle != None: last_action = last_cycle.action_type last_reasoning = last_cycle.reasoning @@ -147,12 +147,11 @@ class SubMind: if_replan_prompt = "" if current_thinking_info: last_loop_prompt = (await global_prompt_manager.get_prompt_async("last_loop")).format( - current_thinking_info=current_thinking_info, - if_replan_prompt=if_replan_prompt + current_thinking_info=current_thinking_info, if_replan_prompt=if_replan_prompt ) else: last_loop_prompt = "" - + # 加权随机选择思考指导 hf_do_next = local_random.choices( [option[0] for option in hf_options], weights=[option[1] for option in hf_options], k=1 @@ -168,7 +167,7 @@ class SubMind: chat_observe_info=chat_observe_info, mood_info=mood_info, hf_do_next=hf_do_next, - last_loop_prompt=last_loop_prompt + last_loop_prompt=last_loop_prompt, ) # logger.debug(f"[{self.subheartflow_id}] 心流思考提示词构建完成") diff --git a/src/plugins/chat/message_buffer.py b/src/plugins/chat/message_buffer.py index 2c04fd50e..d76d23289 100644 --- a/src/plugins/chat/message_buffer.py +++ b/src/plugins/chat/message_buffer.py @@ -3,7 +3,7 @@ from src.common.logger import get_module_logger import asyncio from dataclasses import dataclass, field from .message import MessageRecv -from maim_message import BaseMessageInfo, GroupInfo, Seg +from maim_message import BaseMessageInfo, GroupInfo import hashlib from typing import Dict from collections import OrderedDict @@ -128,8 +128,8 @@ class MessageBuffer: if result: async with self.lock: # 再次加锁 # 清理所有早于当前消息的已处理消息, 收集所有早于当前消息的F消息的processed_plain_text - keep_msgs = OrderedDict() # 用于存放 T 消息之后的消息 - collected_texts = [] # 用于收集 T 消息及之前 F 消息的文本 + keep_msgs = OrderedDict() # 用于存放 T 消息之后的消息 + collected_texts = [] # 用于收集 T 消息及之前 F 消息的文本 process_target_found = False # 遍历当前用户的所有缓冲消息 @@ -138,7 +138,10 @@ class MessageBuffer: if msg_id == message.message_info.message_id: process_target_found = True # 收集这条 T 消息的文本 (如果有) - if hasattr(cache_msg.message, "processed_plain_text") and cache_msg.message.processed_plain_text: + if ( + hasattr(cache_msg.message, "processed_plain_text") + and cache_msg.message.processed_plain_text + ): collected_texts.append(cache_msg.message.processed_plain_text) # 不立即放入 keep_msgs,因为它之前的 F 消息也处理完了 @@ -150,16 +153,23 @@ class MessageBuffer: else: if cache_msg.result == "F": # 收集这条 F 消息的文本 (如果有) - if hasattr(cache_msg.message, "processed_plain_text") and cache_msg.message.processed_plain_text: + if ( + hasattr(cache_msg.message, "processed_plain_text") + and cache_msg.message.processed_plain_text + ): collected_texts.append(cache_msg.message.processed_plain_text) elif cache_msg.result == "U": # 理论上不应该在 T 消息之前还有 U 消息,记录日志 - logger.warning(f"异常状态:在目标 T 消息 {message.message_info.message_id} 之前发现未处理的 U 消息 {cache_msg.message.message_info.message_id}") + logger.warning( + f"异常状态:在目标 T 消息 {message.message_info.message_id} 之前发现未处理的 U 消息 {cache_msg.message.message_info.message_id}" + ) # 也可以选择收集其文本 - if hasattr(cache_msg.message, "processed_plain_text") and cache_msg.message.processed_plain_text: + if ( + hasattr(cache_msg.message, "processed_plain_text") + and cache_msg.message.processed_plain_text + ): collected_texts.append(cache_msg.message.processed_plain_text) - # 更新当前消息 (message) 的 processed_plain_text # 只有在收集到的文本多于一条,或者只有一条但与原始文本不同时才合并 if collected_texts: @@ -172,9 +182,11 @@ class MessageBuffer: if merged_text and merged_text != message.processed_plain_text: message.processed_plain_text = merged_text # 如果合并了文本,原消息不再视为纯 emoji - if hasattr(message, 'is_emoji'): + if hasattr(message, "is_emoji"): message.is_emoji = False - logger.debug(f"合并了 {len(unique_texts)} 条消息的文本内容到当前消息 {message.message_info.message_id}") + logger.debug( + f"合并了 {len(unique_texts)} 条消息的文本内容到当前消息 {message.message_info.message_id}" + ) # 更新缓冲池,只保留 T 消息之后的消息 self.buffer_pool[person_id_] = keep_msgs diff --git a/src/plugins/heartFC_chat/heartFC_Cycleinfo.py b/src/plugins/heartFC_chat/heartFC_Cycleinfo.py index 030018ddf..966773841 100644 --- a/src/plugins/heartFC_chat/heartFC_Cycleinfo.py +++ b/src/plugins/heartFC_chat/heartFC_Cycleinfo.py @@ -1,8 +1,10 @@ import time from typing import List, Optional, Dict, Any + class CycleInfo: """循环信息记录类""" + def __init__(self, cycle_id: int): self.cycle_id = cycle_id self.start_time = time.time() @@ -13,16 +15,16 @@ class CycleInfo: self.timers: Dict[str, float] = {} self.thinking_id = "" self.replanned = False - + # 添加响应信息相关字段 self.response_info: Dict[str, Any] = { "response_text": [], # 回复的文本列表 - "emoji_info": "", # 表情信息 + "emoji_info": "", # 表情信息 "anchor_message_id": "", # 锚点消息ID "reply_message_ids": [], # 回复消息ID列表 "sub_mind_thinking": "", # 子思维思考内容 } - + def to_dict(self) -> Dict[str, Any]: """将循环信息转换为字典格式""" return { @@ -34,29 +36,31 @@ class CycleInfo: "reasoning": self.reasoning, "timers": self.timers, "thinking_id": self.thinking_id, - "response_info": self.response_info + "response_info": self.response_info, } - + def complete_cycle(self): """完成循环,记录结束时间""" self.end_time = time.time() - + def set_action_info(self, action_type: str, reasoning: str, action_taken: bool): """设置动作信息""" self.action_type = action_type self.reasoning = reasoning self.action_taken = action_taken - + def set_thinking_id(self, thinking_id: str): """设置思考消息ID""" self.thinking_id = thinking_id - def set_response_info(self, - response_text: Optional[List[str]] = None, - emoji_info: Optional[str] = None, - anchor_message_id: Optional[str] = None, - reply_message_ids: Optional[List[str]] = None, - sub_mind_thinking: Optional[str] = None): + def set_response_info( + self, + response_text: Optional[List[str]] = None, + emoji_info: Optional[str] = None, + anchor_message_id: Optional[str] = None, + reply_message_ids: Optional[List[str]] = None, + sub_mind_thinking: Optional[str] = None, + ): """设置响应信息""" if response_text is not None: self.response_info["response_text"] = response_text @@ -67,4 +71,4 @@ class CycleInfo: if reply_message_ids is not None: self.response_info["reply_message_ids"] = reply_message_ids if sub_mind_thinking is not None: - self.response_info["sub_mind_thinking"] = sub_mind_thinking \ No newline at end of file + self.response_info["sub_mind_thinking"] = sub_mind_thinking diff --git a/src/plugins/heartFC_chat/heartFC_chat.py b/src/plugins/heartFC_chat/heartFC_chat.py index d57885b9a..ba6be7eb1 100644 --- a/src/plugins/heartFC_chat/heartFC_chat.py +++ b/src/plugins/heartFC_chat/heartFC_chat.py @@ -147,6 +147,7 @@ class SenderError(HeartFCError): pass + class HeartFChatting: """ 管理一个连续的Plan-Replier-Sender循环 @@ -289,12 +290,10 @@ class HeartFChatting: # 记录规划开始时间点 planner_start_db_time = time.time() - + # 主循环:思考->决策->执行 - action_taken, thinking_id = await self._think_plan_execute_loop( - cycle_timers, planner_start_db_time - ) - + action_taken, thinking_id = await self._think_plan_execute_loop(cycle_timers, planner_start_db_time) + # 更新循环信息 self._current_cycle.set_thinking_id(thinking_id) self._current_cycle.timers = cycle_timers @@ -377,16 +376,16 @@ class HeartFChatting: # 记录子思维思考内容 if self._current_cycle: self._current_cycle.set_response_info(sub_mind_thinking=current_mind) - + # plan:决策 with Timer("决策", cycle_timers): planner_result = await self._planner(current_mind, cycle_timers) - + action = planner_result.get("action", "error") reasoning = planner_result.get("reasoning", "未提供理由") - + self._current_cycle.set_action_info(action, reasoning, False) - + # 在获取规划结果后检查新消息 if await self._check_new_messages(planner_start_db_time): if random.random() < 0.3: @@ -407,11 +406,13 @@ class HeartFChatting: if planner_result.get("llm_error"): logger.error(f"{self.log_prefix} LLM失败: {reasoning}") return False, "" - + # execute:执行 with Timer("执行动作", cycle_timers): - return await self._handle_action(action, reasoning, planner_result.get("emoji_query", ""), cycle_timers, planner_start_db_time) - + return await self._handle_action( + action, reasoning, planner_result.get("emoji_query", ""), cycle_timers, planner_start_db_time + ) + except PlannerError as e: logger.error(f"{self.log_prefix} 规划错误: {e}") # 更新循环信息 @@ -505,7 +506,7 @@ class HeartFChatting: response_set=reply, send_emoji=emoji_query, ) - + return True, thinking_id except (ReplierError, SenderError) as e: @@ -645,9 +646,7 @@ class HeartFChatting: with Timer("思考", cycle_timers): # 获取上一个循环的动作 # 传递上一个循环的信息给 do_thinking_before_reply - current_mind, _past_mind = await self.sub_mind.do_thinking_before_reply( - last_cycle=last_cycle - ) + current_mind, _past_mind = await self.sub_mind.do_thinking_before_reply(last_cycle=last_cycle) return current_mind except Exception as e: logger.error(f"{self.log_prefix}[SubMind] 思考失败: {e}") @@ -854,19 +853,21 @@ class HeartFChatting: logger.warning(f"{self.log_prefix} 已释放处理锁") logger.info(f"{self.log_prefix} HeartFChatting关闭完成") - - async def _build_replan_prompt( - self, action: str, reasoning: str - ) -> str: + + async def _build_replan_prompt(self, action: str, reasoning: str) -> str: """构建 Replanner LLM 的提示词""" prompt = (await global_prompt_manager.get_prompt_async("replan_prompt")).format( action=action, reasoning=reasoning, ) return prompt - + async def _build_planner_prompt( - self, observed_messages_str: str, current_mind: Optional[str], structured_info: Dict[str, Any], replan_prompt: str + self, + observed_messages_str: str, + current_mind: Optional[str], + structured_info: Dict[str, Any], + replan_prompt: str, ) -> str: """构建 Planner LLM 的提示词""" diff --git a/src/plugins/heartFC_chat/heartflow_prompt_builder.py b/src/plugins/heartFC_chat/heartflow_prompt_builder.py index eddc5c5ac..661c4e8af 100644 --- a/src/plugins/heartFC_chat/heartflow_prompt_builder.py +++ b/src/plugins/heartFC_chat/heartflow_prompt_builder.py @@ -88,9 +88,12 @@ def init_prompt(): "planner_prompt", ) - Prompt('''你原本打算{action},因为:{reasoning} -但是你看到了新的消息,你决定重新决定行动。''', "replan_prompt") - + Prompt( + """你原本打算{action},因为:{reasoning} +但是你看到了新的消息,你决定重新决定行动。""", + "replan_prompt", + ) + Prompt("你正在qq群里聊天,下面是群里在聊的内容:", "chat_target_group1") Prompt("和群里聊天", "chat_target_group2") Prompt("你正在和{sender_name}聊天,这是你们之前聊的内容:", "chat_target_private1") diff --git a/src/plugins/person_info/person_info.py b/src/plugins/person_info/person_info.py index f5ec6d8f3..1ec9f6d06 100644 --- a/src/plugins/person_info/person_info.py +++ b/src/plugins/person_info/person_info.py @@ -387,7 +387,7 @@ class PersonInfoManager: time_interval = [t for t in time_interval if 200 <= t <= 8000] # --- 修改后的逻辑 --- # 数据量检查 (至少需要 30 条有效间隔,并且足够进行头尾截断) - if len(time_interval) >= 30 + 10: # 至少30条有效+头尾各5条 + if len(time_interval) >= 30 + 10: # 至少30条有效+头尾各5条 time_interval.sort() # 画图(log) - 这部分保留 @@ -397,8 +397,17 @@ class PersonInfoManager: plt.figure(figsize=(10, 6)) # 使用截断前的数据画图,更能反映原始分布 time_series_original = pd.Series(time_interval) - plt.hist(time_series_original, bins=50, density=True, alpha=0.4, color="pink", label="Histogram (Original Filtered)") - time_series_original.plot(kind="kde", color="mediumpurple", linewidth=1, label="Density (Original Filtered)") + plt.hist( + time_series_original, + bins=50, + density=True, + alpha=0.4, + color="pink", + label="Histogram (Original Filtered)", + ) + time_series_original.plot( + kind="kde", color="mediumpurple", linewidth=1, label="Density (Original Filtered)" + ) plt.grid(True, alpha=0.2) plt.xlim(0, 8000) plt.title(f"Message Interval Distribution (User: {person_id[:8]}...)") @@ -414,7 +423,7 @@ class PersonInfoManager: trimmed_interval = time_interval[5:-5] # 计算截断后数据的 37% 分位数 - if trimmed_interval: # 确保截断后列表不为空 + if trimmed_interval: # 确保截断后列表不为空 msg_interval = int(round(np.percentile(trimmed_interval, 37))) # 更新数据库 await self.update_one_field(person_id, "msg_interval", msg_interval) @@ -422,7 +431,9 @@ class PersonInfoManager: else: logger.trace(f"用户{person_id}截断后数据为空,无法计算msg_interval") else: - logger.trace(f"用户{person_id}有效消息间隔数量 ({len(time_interval)}) 不足进行推断 (需要至少 {30+10} 条)") + logger.trace( + f"用户{person_id}有效消息间隔数量 ({len(time_interval)}) 不足进行推断 (需要至少 {30 + 10} 条)" + ) # --- 修改结束 --- except Exception as e: logger.trace(f"用户{person_id}消息间隔计算失败: {type(e).__name__}: {str(e)}") diff --git a/src/plugins/utils/chat_message_builder.py b/src/plugins/utils/chat_message_builder.py index 8ba49d9cd..5d9494488 100644 --- a/src/plugins/utils/chat_message_builder.py +++ b/src/plugins/utils/chat_message_builder.py @@ -168,10 +168,10 @@ async def _build_readable_messages_internal( user_info = msg.get("user_info", {}) platform = user_info.get("platform") user_id = user_info.get("user_id") - + user_nickname = user_info.get("user_nickname") user_cardname = user_info.get("user_cardname") - + timestamp = msg.get("time") content = msg.get("processed_plain_text", "") # 默认空字符串 @@ -311,9 +311,7 @@ async def build_readable_messages( ) readable_read_mark = translate_timestamp_to_human_readable(read_mark, mode=timestamp_mode) - read_mark_line = ( - f"\n--- 以上消息已读 (标记时间: {readable_read_mark}) ---\n--- 以下新消息未读---\n" - ) + read_mark_line = f"\n--- 以上消息已读 (标记时间: {readable_read_mark}) ---\n--- 以下新消息未读---\n" # 组合结果,确保空部分不引入多余的标记或换行 if formatted_before and formatted_after: diff --git a/tool_call_benchmark.py b/tool_call_benchmark.py index 7ef00c7c3..a3e282734 100644 --- a/tool_call_benchmark.py +++ b/tool_call_benchmark.py @@ -212,7 +212,7 @@ async def run_alternating_tests(iterations=5): 包含两种测试方法结果的元组 """ print(f"开始交替测试(每种方法{iterations}次)...") - + # 初始化结果列表 times_without_tools = [] times_with_tools = [] @@ -221,7 +221,7 @@ async def run_alternating_tests(iterations=5): for i in range(iterations): print(f"\n第 {i + 1}/{iterations} 轮交替测试") - + # 不使用工具的测试 print("\n 执行不使用工具调用的测试...") start_time = time.time()