diff --git a/src/heart_flow/0.6.3TODO.md b/src/heart_flow/0.6.3TODO.md index 4048fec8f..5e9e96ab9 100644 --- a/src/heart_flow/0.6.3TODO.md +++ b/src/heart_flow/0.6.3TODO.md @@ -1,45 +1,45 @@ # 0.6.3 版本发布前待办事项 -- **统一化人格配置:** +- [0.6.3]**统一化人格配置:** - 检查代码中是否存在硬编码的人格相关配置。 - 将所有硬编码的人格配置替换为使用 `individual` 模块进行管理。 -- **在 Planner 中添加回复计数信息:** +- [0.6.3]**在 Planner 中添加回复计数信息:** - 修改 `HeartFlowChatInstance` 的 `Plan` 阶段逻辑。 - 将当前周期的回复计数(或其他相关统计信息)作为输入提供给 Planner。 - 目的是为 Planner 提供负反馈,减少连续回复或不当回复的可能性。 -- **恢复/检查被停止的功能:** +- [0.6.3]**恢复/检查被停止的功能:** - 全面审查代码,特别是对比之前的版本或设计文档。 - 识别并重新启用那些暂时被禁用但应该恢复的功能。 - 确认没有核心功能意外丢失。 -- **参数提取与配置化:** +- [0.6.3]**参数提取与配置化:** - 识别代码中散落的各种可调参数(例如:概率阈值、时间间隔、次数限制、LLM 模型名称等)。 - 将这些参数统一提取到模块或类的顶部。 - 最终将这些参数移至外部配置文件(如 YAML 或 JSON 文件),方便用户自定义。 -- **提供 HFC (HeartFlowChatInstance) 开启/关闭选项:** +- **[0.6.3]提供 HFC (HeartFlowChatInstance) 开启/关闭选项:** - 增加一个全局或针对特定子心流的配置选项。 - 允许用户控制是否启用 `FOCUSED` 状态以及关联的 `HeartFlowChatInstance`。 - 如果禁用 HFC,子心流可能只会在 `ABSENT` 和 `CHAT` 状态间切换。 -- **添加防破线机制 (针对接收消息):** +- [0.6.3]**添加防破线机制 (针对接收消息):** - 在消息处理流程的早期阶段 (例如 `HeartHC_processor` 或类似模块),增加对接收到的消息文本长度的检查。 - 对超过预设长度阈值的*接收*消息进行截断处理。 - 目的是防止过长的输入(可能包含"破限"提示词)影响后续的兴趣计算、LLM 回复生成等环节。 -- **NormalChat 模式下的记忆与 Prompt 优化:** +- [0.6.3]**NormalChat 模式下的记忆与 Prompt 优化:** - 重点审视 `NormalChatInstance` (闲聊/推理模式) 中记忆调用 (例如 `HippocampusManager` 的使用) 的方式。 - 评估在该模式下引入工具调用 (Tool Calling) 机制以更结构化访问记忆的必要性。 - 优化 `NormalChatInstance` 中与记忆检索、应用相关的 Prompt。 -- **完善简易兴趣监控 GUI:** +- [0.6.3]**完善简易兴趣监控 GUI:** - 改进现有的、用于监控聊天兴趣度 (`InterestChatting`?) 的简单 GUI 界面。 - 使其能更清晰地展示关键参数和状态,作为查看日志之外的更直观的监控方式。 - 作为完整外部 UI 开发完成前的临时替代方案。 -- **修复/完善中期记忆 (Midterm Memory):** +- [0.6.3]**修复/完善中期记忆 (Midterm Memory):** - 检查当前中期记忆模块的状态。 - 修复已知问题,使其能够稳定运行。 - (优先级视开发时间而定) diff --git a/src/plugins/heartFC_chat/heartFC_chat.py b/src/plugins/heartFC_chat/heartFC_chat.py index a6ed990a6..7fd2cb80d 100644 --- a/src/plugins/heartFC_chat/heartFC_chat.py +++ b/src/plugins/heartFC_chat/heartFC_chat.py @@ -408,7 +408,7 @@ class HeartFChatting: # 在获取规划结果后检查新消息 if await self._check_new_messages(planner_start_db_time): - if random.random() < 0.3: + if random.random() < 0.2: logger.info(f"{self.log_prefix} 看到了新消息,麦麦决定重新观察和规划...") # 重新规划 with Timer("重新决策", cycle_timers): @@ -977,38 +977,87 @@ class HeartFChatting: replan_prompt: str, ) -> str: """构建 Planner LLM 的提示词""" + try: + # 准备结构化信息块 + structured_info_block = "" + if structured_info: + structured_info_block = f"以下是一些额外的信息:\n{structured_info}\n" - # 准备结构化信息块 - structured_info_block = "" - if structured_info: - structured_info_block = f"以下是一些额外的信息:\n{structured_info}\n" + # 准备聊天内容块 + chat_content_block = "" + if observed_messages_str: + chat_content_block = "观察到的最新聊天内容如下:\n---\n" + chat_content_block += observed_messages_str + chat_content_block += "\n---" + else: + chat_content_block = "当前没有观察到新的聊天内容。\n" - # 准备聊天内容块 - chat_content_block = "" - if observed_messages_str: - chat_content_block = "观察到的最新聊天内容如下:\n---\n" - chat_content_block += observed_messages_str - chat_content_block += "\n---" - else: - chat_content_block = "当前没有观察到新的聊天内容。\n" + # 准备当前思维块 + current_mind_block = "" + if current_mind: + current_mind_block = f"{current_mind}" + else: + current_mind_block = "[没有特别的想法]" + + # 准备循环信息块 (分析最近的活动循环) + recent_active_cycles = [] + for cycle in reversed(self._cycle_history): + # 只关心实际执行了动作的循环 + if cycle.action_taken: + recent_active_cycles.append(cycle) + # 最多找最近的3个活动循环 + if len(recent_active_cycles) == 3: + break - # 准备当前思维块 - current_mind_block = "" - if current_mind: - current_mind_block = f"{current_mind}" - else: - current_mind_block = "[没有特别的想法]" + cycle_info_block = "" + consecutive_text_replies = 0 + responses_for_prompt = [] - # 获取提示词模板并填充数据 - prompt = (await global_prompt_manager.get_prompt_async("planner_prompt")).format( - bot_name=global_config.BOT_NICKNAME, - structured_info_block=structured_info_block, - chat_content_block=chat_content_block, - current_mind_block=current_mind_block, - replan=replan_prompt, - ) + # 检查这最近的活动循环中有多少是连续的文本回复 (从最近的开始看) + for cycle in recent_active_cycles: + if cycle.action_type == "text_reply": + consecutive_text_replies += 1 + # 获取回复内容,如果不存在则返回'[空回复]' + response_text = cycle.response_info.get("response_text", []) + # 使用简单的 join 来格式化回复内容列表 + formatted_response = "[空回复]" if not response_text else " ".join(response_text) + responses_for_prompt.append(formatted_response) + else: + # 一旦遇到非文本回复,连续性中断 + break - return prompt + # 根据连续文本回复的数量构建提示信息 + # 注意: responses_for_prompt 列表是从最近到最远排序的 + if consecutive_text_replies >= 3: # 如果最近的三个活动都是文本回复 + cycle_info_block = f'你已经连续回复了三条消息(最近: "{responses_for_prompt[0]}",第二近: "{responses_for_prompt[1]}",第三近: "{responses_for_prompt[2]}")。你回复的有点多了,请注意' + elif consecutive_text_replies == 2: # 如果最近的两个活动是文本回复 + cycle_info_block = f'你已经连续回复了两条消息(最近: "{responses_for_prompt[0]}",第二近: "{responses_for_prompt[1]}"),请注意' + elif consecutive_text_replies == 1: # 如果最近的一个活动是文本回复 + cycle_info_block = f'你刚刚已经回复一条消息(内容: "{responses_for_prompt[0]}")' + + # 包装提示块,增加可读性,即使没有连续回复也给个标记 + if cycle_info_block: + cycle_info_block = f'\n【近期回复历史】\n{cycle_info_block}\n' + else: + # 如果最近的活动循环不是文本回复,或者没有活动循环 + cycle_info_block = '\n【近期回复历史】\n(最近没有连续文本回复)\n' + + # 获取提示词模板并填充数据 + prompt = (await global_prompt_manager.get_prompt_async("planner_prompt")).format( + bot_name=global_config.BOT_NICKNAME, + structured_info_block=structured_info_block, + chat_content_block=chat_content_block, + current_mind_block=current_mind_block, + replan=replan_prompt, + cycle_info_block=cycle_info_block, + ) + + return prompt + + except Exception as e: + logger.error(f"{self.log_prefix}[Planner] 构建提示词时出错: {e}") + logger.error(traceback.format_exc()) + return "" # --- 回复器 (Replier) 的定义 --- # async def _replier_work( diff --git a/src/plugins/heartFC_chat/heartflow_prompt_builder.py b/src/plugins/heartFC_chat/heartflow_prompt_builder.py index d6141a3c8..b77c737d2 100644 --- a/src/plugins/heartFC_chat/heartflow_prompt_builder.py +++ b/src/plugins/heartFC_chat/heartflow_prompt_builder.py @@ -55,6 +55,7 @@ def init_prompt(): 你的内心想法: {current_mind_block} {replan} +{cycle_info_block} 请综合分析聊天内容和你看到的新消息,参考内心想法,使用'decide_reply_action'工具做出决策。决策时请注意: diff --git a/src/plugins/utils/json_utils.py b/src/plugins/utils/json_utils.py index 44e555dc7..b46ac7510 100644 --- a/src/plugins/utils/json_utils.py +++ b/src/plugins/utils/json_utils.py @@ -277,7 +277,15 @@ def process_llm_tool_response( if not success: return False, {}, error_msg + # 新增检查:确保响应包含预期的工具调用部分 + if len(normalized_response) != 3: + # 如果长度不为3,说明LLM响应不包含工具调用部分,这在期望工具调用的上下文中是错误的 + error_msg = f"LLM响应未包含预期的工具调用部分: 元素数量{len(normalized_response)},响应内容:{normalized_response}" + logger.warning(f"{log_prefix}{error_msg}") + return False, {}, error_msg + # 使用新的工具调用处理函数 + # 此时已知 normalized_response 长度必定为 3 success, valid_tool_calls, error_msg = process_llm_tool_calls(normalized_response, log_prefix) if not success: return False, {}, error_msg