From a6542b1be74b8b8f26d2913098a50f3d33ec563d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 19 Apr 2025 12:34:49 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20=E8=87=AA=E5=8A=A8=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96=E4=BB=A3=E7=A0=81=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/do_tool/tool_can_use/get_memory.py | 2 +- src/do_tool/tool_use.py | 5 ++-- src/heart_flow/observation.py | 15 +++++------- src/heart_flow/sub_heartflow.py | 13 ++++++---- src/plugins/chat/bot.py | 2 +- .../chat_module/heartFC_chat/heartFC_chat.py | 5 +--- .../heartFC_chat/heartFC_processor.py | 6 ++--- .../chat_module/heartFC_chat/interest.py | 2 +- .../chat_module/heartFC_chat/pf_chatting.py | 24 +++++++------------ src/plugins/memory_system/Hippocampus.py | 5 ++-- 10 files changed, 33 insertions(+), 46 deletions(-) diff --git a/src/do_tool/tool_can_use/get_memory.py b/src/do_tool/tool_can_use/get_memory.py index a2921938e..28346d46c 100644 --- a/src/do_tool/tool_can_use/get_memory.py +++ b/src/do_tool/tool_can_use/get_memory.py @@ -33,7 +33,7 @@ class GetMemoryTool(BaseTool): try: topic = function_args.get("topic", message_txt) max_memory_num = function_args.get("max_memory_num", 2) - + # 将主题字符串转换为列表 topic_list = topic.split(",") diff --git a/src/do_tool/tool_use.py b/src/do_tool/tool_use.py index 2b072a53e..d8c33e93a 100644 --- a/src/do_tool/tool_use.py +++ b/src/do_tool/tool_use.py @@ -50,11 +50,10 @@ class ToolUser: # prompt += f"你注意到{sender_name}刚刚说:{message_txt}\n" prompt += f"注意你就是{bot_name},{bot_name}是你的名字。根据之前的聊天记录补充问题信息,搜索时避开你的名字。\n" prompt += "你现在需要对群里的聊天内容进行回复,现在选择工具来对消息和你的回复进行处理,你是否需要额外的信息,比如回忆或者搜寻已有的知识,改变关系和情感,或者了解你现在正在做什么。" - + prompt = await relationship_manager.convert_all_person_sign_to_person_name(prompt) prompt = parse_text_timestamps(prompt, mode="lite") - - + return prompt @staticmethod diff --git a/src/heart_flow/observation.py b/src/heart_flow/observation.py index 8874d8914..200494e55 100644 --- a/src/heart_flow/observation.py +++ b/src/heart_flow/observation.py @@ -49,9 +49,8 @@ class ChattingObservation(Observation): initial_messages = list(initial_messages_cursor) initial_messages.reverse() # 恢复时间正序 - self.talking_message = initial_messages # 将这些消息设为初始上下文 - self.now_message_info = self.translate_message_list_to_str(self.talking_message) # 更新初始的 now_message_info - + self.talking_message = initial_messages # 将这些消息设为初始上下文 + self.now_message_info = self.translate_message_list_to_str(self.talking_message) # 更新初始的 now_message_info self.llm_summary = LLMRequest( model=global_config.llm_observation, temperature=0.7, max_tokens=300, request_type="chat_observation" @@ -100,9 +99,7 @@ class ChattingObservation(Observation): # 检查是否有任何新消息(即使超出限制),以决定是否更新 last_observe_time # 注意:这里的查询也可能与其他并发 observe 冲突,但锁保护了状态更新 # 由于外部已加锁,此处的并发冲突担忧不再需要 - any_new_message = db.messages.find_one( - {"chat_id": self.chat_id, "time": {"$gt": self.last_observe_time}} - ) + any_new_message = db.messages.find_one({"chat_id": self.chat_id, "time": {"$gt": self.last_observe_time}}) if not any_new_message: return # 确实没有新消息 @@ -120,11 +117,9 @@ class ChattingObservation(Observation): self.last_observe_time = latest_time_doc["time"] return # 返回,因为我们只关心限制内的最新消息 - self.last_observe_time = new_messages[-1]["time"] self.talking_message.extend(new_messages) - if len(self.talking_message) > self.max_now_obs_len: try: # 使用 try...finally 仅用于可能的LLM调用错误处理 # 计算需要移除的消息数量,保留最新的 max_now_obs_len 条 @@ -164,7 +159,9 @@ class ChattingObservation(Observation): mid_memory_str = "之前聊天的内容概述是:\n" for mid_memory_item in self.mid_memorys: # 重命名循环变量以示区分 time_diff = int((datetime.now().timestamp() - mid_memory_item["created_at"]) / 60) - mid_memory_str += f"距离现在{time_diff}分钟前(聊天记录id:{mid_memory_item['id']}):{mid_memory_item['theme']}\n" + mid_memory_str += ( + f"距离现在{time_diff}分钟前(聊天记录id:{mid_memory_item['id']}):{mid_memory_item['theme']}\n" + ) self.mid_memory_info = mid_memory_str except Exception as e: # 将异常处理移至此处以覆盖整个总结过程 logger.error(f"处理和总结旧消息时出错 for chat {self.chat_id}: {e}") diff --git a/src/heart_flow/sub_heartflow.py b/src/heart_flow/sub_heartflow.py index 8a5a44a70..041f94489 100644 --- a/src/heart_flow/sub_heartflow.py +++ b/src/heart_flow/sub_heartflow.py @@ -43,9 +43,13 @@ def init_prompt(): prompt += "你现在{mood_info}\n" # prompt += "你注意到{sender_name}刚刚说:{message_txt}\n" prompt += "现在请你根据刚刚的想法继续思考,思考时可以想想如何对群聊内容进行回复,关注新话题,可以适当转换话题,大家正在说的话才是聊天的主题。\n" - prompt += "回复的要求是:平淡一些,简短一些,说中文,尽量不要说你说过的话。如果你要回复,最好只回复一个人的一个话题\n" + prompt += ( + "回复的要求是:平淡一些,简短一些,说中文,尽量不要说你说过的话。如果你要回复,最好只回复一个人的一个话题\n" + ) prompt += "请注意不要输出多余内容(包括前后缀,冒号和引号,括号, 表情,等),不要带有括号和动作描写" - prompt += "现在请你继续生成你在这个聊天中的想法,不要分点输出,生成内心想法,文字不要浮夸,注意{bot_name}指的就是你。" + prompt += ( + "现在请你继续生成你在这个聊天中的想法,不要分点输出,生成内心想法,文字不要浮夸,注意{bot_name}指的就是你。" + ) Prompt(prompt, "sub_heartflow_prompt_before") @@ -241,9 +245,9 @@ class SubHeartflow: try: response, reasoning_content = await self.llm_model.generate_response_async(prompt) - + logger.debug(f"[{self.subheartflow_id}] 心流思考结果:\n{response}\n") - + if not response: # 如果 LLM 返回空,给一个默认想法 response = "(不知道该想些什么...)" logger.warning(f"[{self.subheartflow_id}] LLM 返回空结果,思考失败。") @@ -258,7 +262,6 @@ class SubHeartflow: # logger.info(f"[{self.subheartflow_id}] 思考前脑内状态:{self.current_mind}") return self.current_mind, self.past_mind - def update_current_mind(self, response): self.past_mind.append(self.current_mind) self.current_mind = response diff --git a/src/plugins/chat/bot.py b/src/plugins/chat/bot.py index 2716a5ee5..9eab99c72 100644 --- a/src/plugins/chat/bot.py +++ b/src/plugins/chat/bot.py @@ -32,7 +32,7 @@ class ChatBot: self.think_flow_chat = ThinkFlowChat() self.reasoning_chat = ReasoningChat() self.heartFC_processor = HeartFC_Processor() # 新增 - + # 创建初始化PFC管理器的任务,会在_ensure_started时执行 self.only_process_chat = MessageProcessor() self.pfc_manager = PFCManager.get_instance() diff --git a/src/plugins/chat_module/heartFC_chat/heartFC_chat.py b/src/plugins/chat_module/heartFC_chat/heartFC_chat.py index 09189c06d..062cb67e1 100644 --- a/src/plugins/chat_module/heartFC_chat/heartFC_chat.py +++ b/src/plugins/chat_module/heartFC_chat/heartFC_chat.py @@ -276,9 +276,7 @@ class HeartFC_Chat: ) self.mood_manager.update_mood_from_emotion(emotion, global_config.mood_intensity_factor) - - - #暂不使用 + # 暂不使用 async def trigger_reply_generation(self, stream_id: str, observed_messages: List[dict]): """根据 SubHeartflow 的触发信号生成回复 (基于观察)""" stream_name = chat_manager.get_stream_name(stream_id) or stream_id # <--- 在开始时获取名称 @@ -534,4 +532,3 @@ class HeartFC_Chat: finally: # 可以在这里添加清理逻辑,如果有的话 pass - diff --git a/src/plugins/chat_module/heartFC_chat/heartFC_processor.py b/src/plugins/chat_module/heartFC_chat/heartFC_processor.py index 714f3b477..5d76faf0b 100644 --- a/src/plugins/chat_module/heartFC_chat/heartFC_processor.py +++ b/src/plugins/chat_module/heartFC_chat/heartFC_processor.py @@ -27,9 +27,7 @@ logger = get_module_logger("heartFC_processor", config=processor_config) class HeartFC_Processor: def __init__(self): self.storage = MessageStorage() - self.interest_manager = ( - InterestManager() - ) + self.interest_manager = InterestManager() # self.chat_instance = chat_instance # 持有 HeartFC_Chat 实例 async def process_message(self, message_data: str) -> None: @@ -44,7 +42,7 @@ class HeartFC_Processor: 5. 应用全局配置中的过滤词和正则表达式,过滤不符合规则的消息。 6. 查询消息缓冲结果,如果消息被缓冲器拦截(例如,判断为消息轰炸的一部分),则中止后续处理。 7. 对于通过缓冲的消息,将其存储到 `MessageStorage` 中。 - + 8. 调用海马体(`HippocampusManager`)计算消息内容的记忆激活率。(这部分算法后续会进行优化) 9. 根据是否被提及(@)和记忆激活率,计算最终的兴趣度增量。(提及的额外兴趣增幅) 10. 使用计算出的增量更新 `InterestManager` 中对应会话的兴趣度。 diff --git a/src/plugins/chat_module/heartFC_chat/interest.py b/src/plugins/chat_module/heartFC_chat/interest.py index 2c112fed5..692e98ac1 100644 --- a/src/plugins/chat_module/heartFC_chat/interest.py +++ b/src/plugins/chat_module/heartFC_chat/interest.py @@ -130,7 +130,7 @@ class InterestChatting: # 限制概率不超过最大值 self.current_reply_probability = min(self.current_reply_probability, self.max_reply_probability) - else: + else: if 0 < self.probability_decay_factor < 1: decay_multiplier = math.pow(self.probability_decay_factor, time_delta) # old_prob = self.current_reply_probability diff --git a/src/plugins/chat_module/heartFC_chat/pf_chatting.py b/src/plugins/chat_module/heartFC_chat/pf_chatting.py index 94e51ae20..af962a750 100644 --- a/src/plugins/chat_module/heartFC_chat/pf_chatting.py +++ b/src/plugins/chat_module/heartFC_chat/pf_chatting.py @@ -45,7 +45,7 @@ PLANNER_TOOL_DEFINITION = [ "reasoning": {"type": "string", "description": "做出此决定的简要理由。"}, "emoji_query": { "type": "string", - "description": '如果行动是\'emoji_reply\',指定表情的主题或概念。如果行动是\'text_reply\'且希望在文本后追加表情,也在此指定表情主题。', + "description": "如果行动是'emoji_reply',指定表情的主题或概念。如果行动是'text_reply'且希望在文本后追加表情,也在此指定表情主题。", }, }, "required": ["action", "reasoning"], @@ -386,9 +386,9 @@ class PFChatting: # --- 获取最新的观察信息 --- try: - observation = self.sub_hf._get_primary_observation() # Call only once + observation = self.sub_hf._get_primary_observation() # Call only once - if observation: # Now check if the result is truthy + if observation: # Now check if the result is truthy # logger.debug(f"{log_prefix}[Planner] 调用 observation.observe()...") await observation.observe() # 主动观察以获取最新消息 observed_messages = observation.talking_message # 获取更新后的消息列表 @@ -409,7 +409,7 @@ class PFChatting: ] observation_context_text = " ".join(context_texts) # logger.debug(f"{log_prefix}[Planner] Context for tools: {observation_context_text[:100]}...") - + tool_result = await self.heartfc_chat.tool_user.use_tool( message_txt=observation_context_text, chat_stream=self.chat_stream, sub_heartflow=self.sub_hf ) @@ -417,15 +417,12 @@ class PFChatting: tool_result_info = tool_result.get("structured_info", {}) logger.debug(f"{log_prefix}[Planner] 规划前工具结果: {tool_result_info}") if "mid_chat_mem" in tool_result_info: - get_mid_memory_id = [ - mem["content"] for mem in tool_result_info["mid_chat_mem"] if "content" in mem - ] + get_mid_memory_id = [mem["content"] for mem in tool_result_info["mid_chat_mem"] if "content" in mem] except Exception as e_tool: logger.error(f"{log_prefix}[Planner] 规划前工具使用失败: {e_tool}") # --- 结束工具使用 --- - current_mind, _past_mind = await self.sub_hf.do_thinking_before_reply( chat_stream=self.chat_stream, extra_info=tool_result_info, @@ -713,7 +710,6 @@ class PFChatting: prompt = f"你的名字是 {global_config.BOT_NICKNAME}。是一个女大二学生,正在QQ聊天,正在决定是否以及如何回应当前的聊天。\n" # Add current mind state if available - if observed_messages: context_text = " ".join( @@ -724,15 +720,14 @@ class PFChatting: prompt += "\n---\n" else: prompt += "当前没有观察到新的聊天内容。\n" - + prompt += "\n看了这些内容,你的想法是:" - + if current_mind: prompt += f"\n---\n{current_mind}\n---\n\n" - prompt += ( - "\n请结合你的内部想法和观察到的聊天内容,分析情况并使用 \'decide_reply_action\' 工具来决定你的最终行动。\n" + "\n请结合你的内部想法和观察到的聊天内容,分析情况并使用 'decide_reply_action' 工具来决定你的最终行动。\n" ) prompt += "决策依据:\n" prompt += "1. 如果聊天内容无聊、与你无关、或者你的内部想法认为不适合回复,选择 'no_reply'。\n" @@ -742,8 +737,7 @@ class PFChatting: ) prompt += "4. 如果你已经回复过消息,也没有人又回复你,选择'no_reply'。\n" prompt += "5. 除非大家都在这么做,否则不要重复聊相同的内容。\n" - prompt += "必须调用 \'decide_reply_action\' 工具并提供 \'action\' 和 \'reasoning\'。如果选择了 'emoji_reply' 或者选择了 'text_reply' 并想追加表情,则必须提供 \'emoji_query\'。" - + prompt += "必须调用 'decide_reply_action' 工具并提供 'action' 和 'reasoning'。如果选择了 'emoji_reply' 或者选择了 'text_reply' 并想追加表情,则必须提供 'emoji_query'。" prompt = await relationship_manager.convert_all_person_sign_to_person_name(prompt) prompt = parse_text_timestamps(prompt, mode="lite") diff --git a/src/plugins/memory_system/Hippocampus.py b/src/plugins/memory_system/Hippocampus.py index 3a9c27dbd..557b42f2b 100644 --- a/src/plugins/memory_system/Hippocampus.py +++ b/src/plugins/memory_system/Hippocampus.py @@ -1257,7 +1257,7 @@ class Hippocampus: logger.info(f"选中记忆: {memory} (来自节点: {topic})") return result - + async def get_memory_from_topic( self, keywords: list[str], @@ -1343,7 +1343,6 @@ class Hippocampus: else: activate_map[node] = activation_value - # 基于激活值平方的独立概率选择 remember_map = {} # logger.info("基于激活值平方的归一化选择:") @@ -1941,7 +1940,7 @@ class HippocampusManager: logger.error(f"文本激活记忆失败: {e}") response = [] return response - + async def get_memory_from_topic( self, valid_keywords: list[str],