From 815f616dfd0889abef26b95a9a0389ea46e4d39c Mon Sep 17 00:00:00 2001 From: Bakadax Date: Tue, 29 Apr 2025 19:58:16 +0800 Subject: [PATCH 01/15] =?UTF-8?q?=E5=B0=8620=E5=91=BD=E5=90=8D=E4=B8=BA?= =?UTF-8?q?=E5=B8=B8=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/emoji_system/emoji_manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/emoji_system/emoji_manager.py b/src/plugins/emoji_system/emoji_manager.py index 211a4a83..315cfb80 100644 --- a/src/plugins/emoji_system/emoji_manager.py +++ b/src/plugins/emoji_system/emoji_manager.py @@ -22,7 +22,7 @@ logger = get_logger("emoji") BASE_DIR = os.path.join("data") EMOJI_DIR = os.path.join(BASE_DIR, "emoji") # 表情包存储目录 EMOJI_REGISTED_DIR = os.path.join(BASE_DIR, "emoji_registed") # 已注册的表情包注册目录 - +MAX_EMOJI_FOR_PROMPT = 20 # 最大表情包描述于图片替换的 prompt 中 """ 还没经过测试,有些地方数据库和内存数据同步可能不完全 @@ -634,7 +634,7 @@ class EmojiManager: # 使用概率分布选择最多20个表情包 selected_emojis = random.choices( - emoji_objects, weights=normalized_probabilities, k=min(20, len(emoji_objects)) + emoji_objects, weights=normalized_probabilities, k=min(MAX_EMOJI_FOR_PROMPT, len(emoji_objects)) ) # 将表情包信息转换为可读的字符串 From fbb17e42742483ae916b7c50196f777e871c5ccb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A2=A8=E6=A2=93=E6=9F=92?= <1787882683@qq.com> Date: Wed, 30 Apr 2025 09:33:49 +0800 Subject: [PATCH 02/15] =?UTF-8?q?feat=EF=BC=9A=E6=96=B0=E5=A2=9E=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E6=83=B3=E6=B3=95=E9=98=9F=E5=88=97=E5=8F=8A=E5=AE=9E?= =?UTF-8?q?=E6=97=B6=E7=9B=91=E6=8E=A7=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/interest_monitor_gui.py | 99 ++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) diff --git a/scripts/interest_monitor_gui.py b/scripts/interest_monitor_gui.py index fb9e51cf..fb61eefd 100644 --- a/scripts/interest_monitor_gui.py +++ b/scripts/interest_monitor_gui.py @@ -19,6 +19,7 @@ REFRESH_INTERVAL_MS = 200 # 刷新间隔 (毫秒) - 可以适当调长,因为 WINDOW_TITLE = "Interest Monitor (Live History)" MAX_HISTORY_POINTS = 1000 # 图表上显示的最大历史点数 (可以增加) MAX_STREAMS_TO_DISPLAY = 15 # 最多显示多少个聊天流的折线图 (可以增加) +MAX_QUEUE_SIZE = 30 # 新增:历史想法队列最大长度 # *** 添加 Matplotlib 中文字体配置 *** # 尝试使用 'SimHei' 或 'Microsoft YaHei',如果找不到,matplotlib 会回退到默认字体 @@ -61,6 +62,10 @@ class InterestMonitorApp: self.single_stream_last_active = tk.StringVar(value="活跃: N/A") self.single_stream_last_interaction = tk.StringVar(value="交互: N/A") + # 新增:历史想法队列 + self.main_mind_history = deque(maxlen=MAX_QUEUE_SIZE) + self.last_main_mind_timestamp = 0 # 记录最后一条main_mind的时间戳 + # --- UI 元素 --- # --- 新增:顶部全局信息框架 --- @@ -143,6 +148,20 @@ class InterestMonitorApp: self.canvas_widget_single = self.canvas_single.get_tk_widget() self.canvas_widget_single.pack(side=tk.TOP, fill=tk.BOTH, expand=1) + # --- 新增第三个选项卡:麦麦历史想法 --- + self.frame_mind_history = ttk.Frame(self.notebook, padding="5 5 5 5") + self.notebook.add(self.frame_mind_history, text="麦麦历史想法") + + # 聊天框样式的文本框(只读)+ 滚动条 + self.mind_text_scroll = tk.Scrollbar(self.frame_mind_history) + self.mind_text_scroll.pack(side=tk.RIGHT, fill=tk.Y) + self.mind_text = tk.Text( + self.frame_mind_history, height=25, state="disabled", wrap="word", font=("微软雅黑", 12), + yscrollcommand=self.mind_text_scroll.set + ) + self.mind_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=1, padx=5, pady=5) + self.mind_text_scroll.config(command=self.mind_text.yview) + # --- 初始化和启动刷新 --- self.update_display() # 首次加载并开始刷新循环 @@ -154,6 +173,78 @@ class InterestMonitorApp: """生成随机颜色用于区分线条""" return "#{:06x}".format(random.randint(0, 0xFFFFFF)) + def load_main_mind_history(self): + """只读取包含main_mind的日志行,维护历史想法队列""" + if not os.path.exists(LOG_FILE_PATH): + return + + main_mind_entries = [] + try: + with open(LOG_FILE_PATH, "r", encoding="utf-8") as f: + for line in f: + try: + log_entry = json.loads(line.strip()) + if "main_mind" in log_entry: + ts = log_entry.get("timestamp", 0) + main_mind_entries.append((ts, log_entry)) + except Exception: + continue + main_mind_entries.sort(key=lambda x: x[0]) + recent_entries = main_mind_entries[-MAX_QUEUE_SIZE:] + self.main_mind_history.clear() + for ts, entry in recent_entries: + self.main_mind_history.append(entry) + if recent_entries: + self.last_main_mind_timestamp = recent_entries[-1][0] + # 首次加载时刷新 + self.refresh_mind_text() + except Exception: + pass + + def update_main_mind_history(self): + """实时监控log文件,发现新main_mind数据则更新队列和展示(仅有新数据时刷新)""" + if not os.path.exists(LOG_FILE_PATH): + return + + new_entries = [] + try: + with open(LOG_FILE_PATH, "r", encoding="utf-8") as f: + for line in reversed(list(f)): + try: + log_entry = json.loads(line.strip()) + if "main_mind" in log_entry: + ts = log_entry.get("timestamp", 0) + if ts > self.last_main_mind_timestamp: + new_entries.append((ts, log_entry)) + else: + break + except Exception: + continue + if new_entries: + for ts, entry in sorted(new_entries): + if len(self.main_mind_history) >= MAX_QUEUE_SIZE: + self.main_mind_history.popleft() + self.main_mind_history.append(entry) + self.last_main_mind_timestamp = ts + self.refresh_mind_text() # 只有有新数据时才刷新 + except Exception: + pass + + def refresh_mind_text(self): + """刷新聊天框样式的历史想法展示""" + self.mind_text.config(state="normal") + self.mind_text.delete(1.0, tk.END) + for entry in self.main_mind_history: + ts = entry.get("timestamp", 0) + dt_str = datetime.fromtimestamp(ts).strftime("%Y-%m-%d %H:%M:%S") if ts else "" + main_mind = entry.get("main_mind", "") + mai_state = entry.get("mai_state", "") + subflow_count = entry.get("subflow_count", "") + msg = f"[{dt_str}] 状态:{mai_state} 子流:{subflow_count}\n{main_mind}\n\n" + self.mind_text.insert(tk.END, msg) + self.mind_text.see(tk.END) + self.mind_text.config(state="disabled") + def load_and_update_history(self): """从 history log 文件加载数据并更新历史记录""" if not os.path.exists(LOG_FILE_PATH): @@ -537,8 +628,14 @@ class InterestMonitorApp: def update_display(self): """主更新循环""" try: - self.load_and_update_history() # 从文件加载数据并更新内部状态 + # --- 新增:首次加载历史想法 --- + if not hasattr(self, "_main_mind_loaded"): + self.load_main_mind_history() + self._main_mind_loaded = True + else: + self.update_main_mind_history() # 只有有新main_mind数据时才刷新界面 # *** 修改:分别调用两个图表的更新方法 *** + self.load_and_update_history() # 从文件加载数据并更新内部状态 self.update_all_streams_plot() # 更新所有流的图表 self.update_single_stream_plot() # 更新单个流的图表 except Exception as e: From 42505960e18a926840b8d8db1f386ba023899c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A2=A8=E6=A2=93=E6=9F=92?= <1787882683@qq.com> Date: Wed, 30 Apr 2025 09:40:45 +0800 Subject: [PATCH 03/15] fix: Ruff --- scripts/interest_monitor_gui.py | 2 +- src/heart_flow/mai_state_manager.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/interest_monitor_gui.py b/scripts/interest_monitor_gui.py index fb61eefd..4e688a30 100644 --- a/scripts/interest_monitor_gui.py +++ b/scripts/interest_monitor_gui.py @@ -192,7 +192,7 @@ class InterestMonitorApp: main_mind_entries.sort(key=lambda x: x[0]) recent_entries = main_mind_entries[-MAX_QUEUE_SIZE:] self.main_mind_history.clear() - for ts, entry in recent_entries: + for _ts, entry in recent_entries: self.main_mind_history.append(entry) if recent_entries: self.last_main_mind_timestamp = recent_entries[-1][0] diff --git a/src/heart_flow/mai_state_manager.py b/src/heart_flow/mai_state_manager.py index 4d92d7fd..a3ff34e1 100644 --- a/src/heart_flow/mai_state_manager.py +++ b/src/heart_flow/mai_state_manager.py @@ -144,7 +144,7 @@ class MaiStateManager: # 辅助函数:根据 prevent_offline_state 标志调整目标状态 def _resolve_offline(candidate_state: MaiState) -> MaiState: if prevent_offline_state and candidate_state == MaiState.OFFLINE: - logger.debug(f"阻止进入 OFFLINE,改为 PEEKING") + logger.debug("阻止进入 OFFLINE,改为 PEEKING") return MaiState.PEEKING return candidate_state From ed3d8098414b3d6774bae3af228bf7d16e5d8095 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 30 Apr 2025 01:41:00 +0000 Subject: [PATCH 04/15] =?UTF-8?q?=F0=9F=A4=96=20=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E6=A0=BC=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 --- scripts/interest_monitor_gui.py | 8 ++- src/heart_flow/mai_state_manager.py | 11 ++-- src/plugins/heartFC_chat/heartFC_chat.py | 76 ++++++++++++++---------- 3 files changed, 57 insertions(+), 38 deletions(-) diff --git a/scripts/interest_monitor_gui.py b/scripts/interest_monitor_gui.py index 4e688a30..adb83f72 100644 --- a/scripts/interest_monitor_gui.py +++ b/scripts/interest_monitor_gui.py @@ -156,8 +156,12 @@ class InterestMonitorApp: self.mind_text_scroll = tk.Scrollbar(self.frame_mind_history) self.mind_text_scroll.pack(side=tk.RIGHT, fill=tk.Y) self.mind_text = tk.Text( - self.frame_mind_history, height=25, state="disabled", wrap="word", font=("微软雅黑", 12), - yscrollcommand=self.mind_text_scroll.set + self.frame_mind_history, + height=25, + state="disabled", + wrap="word", + font=("微软雅黑", 12), + yscrollcommand=self.mind_text_scroll.set, ) self.mind_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=1, padx=5, pady=5) self.mind_text_scroll.config(command=self.mind_text.yview) diff --git a/src/heart_flow/mai_state_manager.py b/src/heart_flow/mai_state_manager.py index a3ff34e1..48eead1a 100644 --- a/src/heart_flow/mai_state_manager.py +++ b/src/heart_flow/mai_state_manager.py @@ -9,9 +9,9 @@ logger = get_logger("mai_state") # -- 状态相关的可配置参数 (可以从 glocal_config 加载) -- -enable_unlimited_hfc_chat = True # 调试用:无限专注聊天 +enable_unlimited_hfc_chat = True # 调试用:无限专注聊天 # enable_unlimited_hfc_chat = False -prevent_offline_state = True # 调试用:防止进入离线状态 +prevent_offline_state = True # 调试用:防止进入离线状态 # 不同状态下普通聊天的最大消息数 MAX_NORMAL_CHAT_NUM_PEEKING = 30 @@ -25,6 +25,7 @@ MAX_FOCUSED_CHAT_NUM_FOCUSED = 40 # -- 状态定义 -- + class MaiState(enum.Enum): """ 聊天状态: @@ -204,8 +205,10 @@ class MaiStateManager: if time_limit_exceeded: next_state_candidate = random.choices(choices_list, weights=weights, k=1)[0] resolved_candidate = _resolve_offline(next_state_candidate) - logger.debug(f"规则{rule_id}:时间到,随机选择 {next_state_candidate.value},resolve 为 {resolved_candidate.value}") - next_state = resolved_candidate # 直接使用解析后的状态 + logger.debug( + f"规则{rule_id}:时间到,随机选择 {next_state_candidate.value},resolve 为 {resolved_candidate.value}" + ) + next_state = resolved_candidate # 直接使用解析后的状态 # 注意:enable_unlimited_hfc_chat 优先级高于 prevent_offline_state # 如果触发了这个,它会覆盖上面规则2设置的 next_state diff --git a/src/plugins/heartFC_chat/heartFC_chat.py b/src/plugins/heartFC_chat/heartFC_chat.py index 25cf854a..c15c4f83 100644 --- a/src/plugins/heartFC_chat/heartFC_chat.py +++ b/src/plugins/heartFC_chat/heartFC_chat.py @@ -1,7 +1,7 @@ import asyncio import time import traceback -import random # <--- 添加导入 +import random # <--- 添加导入 from typing import List, Optional, Dict, Any, Deque, Callable, Coroutine from collections import deque from src.plugins.chat.message import MessageRecv, BaseMessageInfo, MessageThinking, MessageSending @@ -32,7 +32,7 @@ from src.individuality.individuality import Individuality INITIAL_DURATION = 60.0 -WAITING_TIME_THRESHOLD = 300 # 等待新消息时间阈值,单位秒 +WAITING_TIME_THRESHOLD = 300 # 等待新消息时间阈值,单位秒 logger = get_logger("interest") # Logger Name Changed @@ -48,11 +48,11 @@ class ActionManager: def __init__(self): # 初始化为默认动作集 self._available_actions: Dict[str, str] = DEFAULT_ACTIONS.copy() - self._original_actions_backup: Optional[Dict[str, str]] = None # 用于临时移除时的备份 + self._original_actions_backup: Optional[Dict[str, str]] = None # 用于临时移除时的备份 def get_available_actions(self) -> Dict[str, str]: """获取当前可用的动作集""" - return self._available_actions.copy() # 返回副本以防外部修改 + return self._available_actions.copy() # 返回副本以防外部修改 def add_action(self, action_name: str, description: str) -> bool: """ @@ -518,7 +518,7 @@ class HeartFChatting: logger.error(f"{self.log_prefix} 处理{action}时出错: {e}") # 出错时也重置计数器 self._lian_xu_bu_hui_fu_ci_shu = 0 - self._lian_xu_deng_dai_shi_jian = 0.0 # 重置累计等待时间 + self._lian_xu_deng_dai_shi_jian = 0.0 # 重置累计等待时间 return False, "" async def _handle_text_reply(self, reasoning: str, emoji_query: str, cycle_timers: dict) -> tuple[bool, str]: @@ -541,7 +541,7 @@ class HeartFChatting: """ # 重置连续不回复计数器 self._lian_xu_bu_hui_fu_ci_shu = 0 - self._lian_xu_deng_dai_shi_jian = 0.0 # 重置累计等待时间 + self._lian_xu_deng_dai_shi_jian = 0.0 # 重置累计等待时间 # 获取锚点消息 anchor_message = await self._get_anchor_message() @@ -597,7 +597,7 @@ class HeartFChatting: bool: 是否发送成功 """ logger.info(f"{self.log_prefix} 决定回复表情({emoji_query}): {reasoning}") - self._lian_xu_deng_dai_shi_jian = 0.0 # 重置累计等待时间(即使不计数也保持一致性) + self._lian_xu_deng_dai_shi_jian = 0.0 # 重置累计等待时间(即使不计数也保持一致性) try: anchor = await self._get_anchor_message() @@ -633,17 +633,16 @@ class HeartFChatting: observation = self.observations[0] if self.observations else None try: - dang_qian_deng_dai = 0.0 # 初始化本次等待时间 + dang_qian_deng_dai = 0.0 # 初始化本次等待时间 with Timer("等待新消息", cycle_timers): # 等待新消息、超时或关闭信号,并获取结果 await self._wait_for_new_message(observation, planner_start_db_time, self.log_prefix) # 从计时器获取实际等待时间 dang_qian_deng_dai = cycle_timers.get("等待新消息", 0.0) - if not self._shutting_down: self._lian_xu_bu_hui_fu_ci_shu += 1 - self._lian_xu_deng_dai_shi_jian += dang_qian_deng_dai # 累加等待时间 + self._lian_xu_deng_dai_shi_jian += dang_qian_deng_dai # 累加等待时间 logger.debug( f"{self.log_prefix} 连续不回复计数增加: {self._lian_xu_bu_hui_fu_ci_shu}/{self.CONSECUTIVE_NO_REPLY_THRESHOLD}, " f"本次等待: {dang_qian_deng_dai:.2f}秒, 累计等待: {self._lian_xu_deng_dai_shi_jian:.2f}秒" @@ -651,8 +650,10 @@ class HeartFChatting: # 检查是否同时达到次数和时间阈值 time_threshold = 0.66 * WAITING_TIME_THRESHOLD * self.CONSECUTIVE_NO_REPLY_THRESHOLD - if (self._lian_xu_bu_hui_fu_ci_shu >= self.CONSECUTIVE_NO_REPLY_THRESHOLD and - self._lian_xu_deng_dai_shi_jian >= time_threshold): + if ( + self._lian_xu_bu_hui_fu_ci_shu >= self.CONSECUTIVE_NO_REPLY_THRESHOLD + and self._lian_xu_deng_dai_shi_jian >= time_threshold + ): logger.info( f"{self.log_prefix} 连续不回复达到阈值 ({self._lian_xu_bu_hui_fu_ci_shu}次) " f"且累计等待时间达到 {self._lian_xu_deng_dai_shi_jian:.2f}秒 (阈值 {time_threshold}秒)," @@ -668,7 +669,6 @@ class HeartFChatting: ) # else: 次数和时间都未达到阈值,不做处理 - return True except asyncio.CancelledError: @@ -793,9 +793,9 @@ class HeartFChatting: logger.info(f"{self.log_prefix}[Planner] 开始{'重新' if is_re_planned else ''}执行规划器") # --- 新增:检查历史动作并调整可用动作 --- - lian_xu_wen_ben_hui_fu = 0 # 连续文本回复次数 + lian_xu_wen_ben_hui_fu = 0 # 连续文本回复次数 actions_to_remove_temporarily = [] - probability_roll = random.random() # 在循环外掷骰子一次,用于概率判断 + probability_roll = random.random() # 在循环外掷骰子一次,用于概率判断 # 反向遍历最近的循环历史 for cycle in reversed(self._cycle_history): @@ -804,9 +804,11 @@ class HeartFChatting: if cycle.action_type == "text_reply": lian_xu_wen_ben_hui_fu += 1 else: - break # 遇到非文本回复,中断计数 + break # 遇到非文本回复,中断计数 # 检查最近的3个循环即可,避免检查过多历史 (如果历史很长) - if len(self._cycle_history) > 0 and cycle.cycle_id <= self._cycle_history[0].cycle_id + (len(self._cycle_history) - 4): + if len(self._cycle_history) > 0 and cycle.cycle_id <= self._cycle_history[0].cycle_id + ( + len(self._cycle_history) - 4 + ): break logger.debug(f"{self.log_prefix}[Planner] 检测到连续文本回复次数: {lian_xu_wen_ben_hui_fu}") @@ -816,13 +818,15 @@ class HeartFChatting: logger.info(f"{self.log_prefix}[Planner] 连续回复 >= 3 次,强制移除 text_reply 和 emoji_reply") actions_to_remove_temporarily.extend(["text_reply", "emoji_reply"]) elif lian_xu_wen_ben_hui_fu == 2: - if probability_roll < 0.8: # 80% 概率 + if probability_roll < 0.8: # 80% 概率 logger.info(f"{self.log_prefix}[Planner] 连续回复 2 次,80% 概率移除 text_reply 和 emoji_reply (触发)") actions_to_remove_temporarily.extend(["text_reply", "emoji_reply"]) else: - logger.info(f"{self.log_prefix}[Planner] 连续回复 2 次,80% 概率移除 text_reply 和 emoji_reply (未触发)") + logger.info( + f"{self.log_prefix}[Planner] 连续回复 2 次,80% 概率移除 text_reply 和 emoji_reply (未触发)" + ) elif lian_xu_wen_ben_hui_fu == 1: - if probability_roll < 0.4: # 40% 概率 + if probability_roll < 0.4: # 40% 概率 logger.info(f"{self.log_prefix}[Planner] 连续回复 1 次,40% 概率移除 text_reply (触发)") actions_to_remove_temporarily.append("text_reply") else: @@ -847,7 +851,9 @@ class HeartFChatting: # --- 新增:应用临时动作移除 --- if actions_to_remove_temporarily: self.action_manager.temporarily_remove_actions(actions_to_remove_temporarily) - logger.debug(f"{self.log_prefix}[Planner] 临时移除的动作: {actions_to_remove_temporarily}, 当前可用: {list(self.action_manager.get_available_actions().keys())}") + logger.debug( + f"{self.log_prefix}[Planner] 临时移除的动作: {actions_to_remove_temporarily}, 当前可用: {list(self.action_manager.get_available_actions().keys())}" + ) # --- 构建提示词 --- replan_prompt_str = "" @@ -862,7 +868,7 @@ class HeartFChatting: # --- 调用 LLM --- try: planner_tools = self.action_manager.get_planner_tool_definition() - logger.debug(f"{self.log_prefix}[Planner] 本次使用的工具定义: {planner_tools}") # 记录本次使用的工具 + logger.debug(f"{self.log_prefix}[Planner] 本次使用的工具定义: {planner_tools}") # 记录本次使用的工具 _response_text, _reasoning_content, tool_calls = await self.planner_llm.generate_response_tool_async( prompt=prompt, tools=planner_tools, @@ -914,13 +920,15 @@ class HeartFChatting: action = "no_reply" reasoning = f"LLM返回了当前不可用的动作: {extracted_action}" emoji_query = "" - llm_error = False # 视为逻辑修正而非 LLM 错误 + llm_error = False # 视为逻辑修正而非 LLM 错误 # --- 检查 'no_reply' 是否也恰好被移除了 (极端情况) --- if "no_reply" not in self.action_manager.get_available_actions(): - logger.error(f"{self.log_prefix}[Planner] 严重错误:'no_reply' 动作也不可用!无法执行任何动作。") - action = "error" # 回退到错误状态 - reasoning = "无法执行任何有效动作,包括 no_reply" - llm_error = True + logger.error( + f"{self.log_prefix}[Planner] 严重错误:'no_reply' 动作也不可用!无法执行任何动作。" + ) + action = "error" # 回退到错误状态 + reasoning = "无法执行任何有效动作,包括 no_reply" + llm_error = True else: # 动作有效且可用,使用提取的值 action = extracted_action @@ -944,11 +952,13 @@ class HeartFChatting: # 如果没有有效的工具调用,我们需要检查 'no_reply' 是否是当前唯一可用的动作 available_actions = list(self.action_manager.get_available_actions().keys()) if available_actions == ["no_reply"]: - logger.info(f"{self.log_prefix}[Planner] LLM未返回工具调用,但当前唯一可用动作是 'no_reply',将执行 'no_reply'") + logger.info( + f"{self.log_prefix}[Planner] LLM未返回工具调用,但当前唯一可用动作是 'no_reply',将执行 'no_reply'" + ) action = "no_reply" reasoning = "LLM未返回工具调用,且当前仅 'no_reply' 可用" emoji_query = "" - llm_error = False # 视为逻辑选择而非错误 + llm_error = False # 视为逻辑选择而非错误 else: reasoning = "LLM未返回有效的工具调用" logger.warning(f"{self.log_prefix}[Planner] {reasoning}") @@ -963,9 +973,11 @@ class HeartFChatting: llm_error = True # --- 新增:确保动作恢复 --- finally: - if actions_to_remove_temporarily: # 只有当确实移除了动作时才需要恢复 - self.action_manager.restore_actions() - logger.debug(f"{self.log_prefix}[Planner] 恢复了原始动作集, 当前可用: {list(self.action_manager.get_available_actions().keys())}") + if actions_to_remove_temporarily: # 只有当确实移除了动作时才需要恢复 + self.action_manager.restore_actions() + logger.debug( + f"{self.log_prefix}[Planner] 恢复了原始动作集, 当前可用: {list(self.action_manager.get_available_actions().keys())}" + ) # --- 结束:确保动作恢复 --- # --- 结束 LLM 决策 --- # From 15c4fd1abaf6b891e37da2e245a4d444b2d32ffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A2=A8=E6=A2=93=E6=9F=92?= <1787882683@qq.com> Date: Wed, 30 Apr 2025 10:47:01 +0800 Subject: [PATCH 05/15] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20llm=5Ftool?= =?UTF-8?q?=5Fbenchmark=5Fresults.json=20=E5=88=B0=20.gitignore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7e093053..88995ecc 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ log/ logs/ tool_call_benchmark.py run_ad.bat +llm_tool_benchmark_results.json MaiBot-Napcat-Adapter-main MaiBot-Napcat-Adapter /test From 3ed58359370fd1cbfaae9d9e84280c3b1876f07f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A2=A8=E6=A2=93=E6=9F=92?= <1787882683@qq.com> Date: Wed, 30 Apr 2025 12:03:28 +0800 Subject: [PATCH 06/15] =?UTF-8?q?feat:=20=E5=88=A0=E9=99=A4=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/count.py | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 scripts/count.py diff --git a/scripts/count.py b/scripts/count.py deleted file mode 100644 index f7370875..00000000 --- a/scripts/count.py +++ /dev/null @@ -1,16 +0,0 @@ -def 计算字符串长度(输入字符串: str) -> int: - """计算输入字符串的长度 - - 参数: - 输入字符串: 要计算长度的字符串 - - 返回: - 字符串的长度(整数) - """ - return len(输入字符串) - - -if __name__ == "__main__": - # 测试代码 - 测试字符串 = """你。""" - print(f"字符串 '{测试字符串}' 的长度是: {计算字符串长度(测试字符串)}") From d5ae3173aa40487e3158ef5fa59372e36eb4547d Mon Sep 17 00:00:00 2001 From: Bakadax Date: Wed, 30 Apr 2025 13:56:34 +0800 Subject: [PATCH 07/15] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dpfc=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E7=9F=A5=E8=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/PFC/conversation.py | 4 ++-- src/plugins/PFC/pfc_KnowledgeFetcher.py | 19 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/plugins/PFC/conversation.py b/src/plugins/PFC/conversation.py index c1b31426..9f744c30 100644 --- a/src/plugins/PFC/conversation.py +++ b/src/plugins/PFC/conversation.py @@ -525,9 +525,9 @@ class Conversation: ) action_successful = True except Exception as fetch_err: - logger.error(f"[私聊][{self.private_name}]获取知识时出错: {fetch_err}") + logger.error(f"[私聊][{self.private_name}]获取知识时出错: {str(fetch_err)}") conversation_info.done_action[action_index].update( - {"status": "recall", "final_reason": f"获取知识失败: {fetch_err}"} + {"status": "recall", "final_reason": f"获取知识失败: {str(fetch_err)}"} ) self.conversation_info.last_successful_reply_action = None # 重置状态 diff --git a/src/plugins/PFC/pfc_KnowledgeFetcher.py b/src/plugins/PFC/pfc_KnowledgeFetcher.py index 099b4979..673e418c 100644 --- a/src/plugins/PFC/pfc_KnowledgeFetcher.py +++ b/src/plugins/PFC/pfc_KnowledgeFetcher.py @@ -68,16 +68,19 @@ class KnowledgeFetcher: max_depth=3, fast_retrieval=False, ) - knowledge = "" + knowledge_text = "" + sources = [] if related_memory: - sources = [] for memory in related_memory: - knowledge += memory[1] + "\n" + knowledge_text += memory[1] + "\n" sources.append(f"记忆片段{memory[0]}") - knowledge = knowledge.strip(), ",".join(sources) + knowledge_text = knowledge_text.strip() + sources_text = ",".join(sources) + + knowledge_text += "现在有以下**知识**可供参考:\n " + knowledge_text += self._lpmm_get_knowledge(query) + knowledge_text += "请记住这些**知识**,并根据**知识**回答问题。\n" + + return knowledge_text or "未找到相关知识", sources_text or "无记忆匹配" - knowledge += "现在有以下**知识**可供参考:\n " - knowledge += self._lpmm_get_knowledge(query) - knowledge += "请记住这些**知识**,并根据**知识**回答问题。\n" - return "未找到相关知识", "无记忆匹配" From 4802c1584bc9757f157cf73212702fb3f8e16197 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 30 Apr 2025 05:57:04 +0000 Subject: [PATCH 08/15] =?UTF-8?q?=F0=9F=A4=96=20=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E6=A0=BC=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/plugins/PFC/pfc_KnowledgeFetcher.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugins/PFC/pfc_KnowledgeFetcher.py b/src/plugins/PFC/pfc_KnowledgeFetcher.py index 673e418c..7453aa0e 100644 --- a/src/plugins/PFC/pfc_KnowledgeFetcher.py +++ b/src/plugins/PFC/pfc_KnowledgeFetcher.py @@ -82,5 +82,3 @@ class KnowledgeFetcher: knowledge_text += "请记住这些**知识**,并根据**知识**回答问题。\n" return knowledge_text or "未找到相关知识", sources_text or "无记忆匹配" - - From 7789050a45d5931eb53bd94ab2403a22bc44f5f4 Mon Sep 17 00:00:00 2001 From: 114514 <2514624910@qq.com> Date: Wed, 30 Apr 2025 14:45:28 +0800 Subject: [PATCH 09/15] =?UTF-8?q?=E6=8F=92=E5=85=A5=E7=9F=A5=E8=AF=86?= =?UTF-8?q?=E5=BA=93=E5=92=8C=E8=AE=B0=E5=BF=86=E6=A3=80=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/PFC/action_planner.py | 39 +++++++++++++++++++++++++- src/plugins/PFC/reply_generator.py | 45 ++++++++++++++++++++++++++++-- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/src/plugins/PFC/action_planner.py b/src/plugins/PFC/action_planner.py index a80e96b1..dd7355fa 100644 --- a/src/plugins/PFC/action_planner.py +++ b/src/plugins/PFC/action_planner.py @@ -21,6 +21,7 @@ PROMPT_INITIAL_REPLY = """{persona_text}。现在你在参与一场QQ私聊, 【当前对话目标】 {goals_str} +{knowledge_info_str} 【最近行动历史概要】 {action_history_summary} @@ -33,7 +34,7 @@ PROMPT_INITIAL_REPLY = """{persona_text}。现在你在参与一场QQ私聊, ------ 可选行动类型以及解释: -fetch_knowledge: 需要调取知识,当需要专业知识或特定信息时选择,对方若提到你不太认识的人名或实体也可以尝试选择 +fetch_knowledge: 需要调取知识或记忆,当需要专业知识或特定信息时选择,对方若提到你不太认识的人名或实体也可以尝试选择 listening: 倾听对方发言,当你认为对方话才说到一半,发言明显未结束时选择 direct_reply: 直接回复对方 rethink_goal: 思考一个对话目标,当你觉得目前对话需要目标,或当前目标不再适用,或话题卡住时选择。注意私聊的环境是灵活的,有可能需要经常选择 @@ -53,6 +54,7 @@ PROMPT_FOLLOW_UP = """{persona_text}。现在你在参与一场QQ私聊,刚刚 【当前对话目标】 {goals_str} +{knowledge_info_str} 【最近行动历史概要】 {action_history_summary} @@ -224,6 +226,40 @@ class ActionPlanner: logger.error(f"[私聊][{self.private_name}]构建对话目标字符串时出错: {e}") goals_str = "- 构建对话目标时出错。\n" + # --- 知识信息字符串构建开始 --- + knowledge_info_str = "【已获取的相关知识和记忆】\n" + try: + # 检查 conversation_info 是否有 knowledge_list 并且不为空 + if hasattr(conversation_info, "knowledge_list") and conversation_info.knowledge_list: + # 最多只显示最近的 3 条知识,防止 Prompt 过长 + recent_knowledge = conversation_info.knowledge_list[-3:] + for i, knowledge_item in enumerate(recent_knowledge): + if isinstance(knowledge_item, dict): + query = knowledge_item.get('query', '未知查询') + knowledge = knowledge_item.get('knowledge', '无知识内容') + source = knowledge_item.get('source', '未知来源') + # 只取知识内容的前 150 个字,避免太长 + knowledge_snippet = knowledge[:150] + "..." if len(knowledge) > 150 else knowledge + knowledge_info_str += f"{i+1}. 关于 '{query}' 的知识 (来源: {source}):\n {knowledge_snippet}\n" + else: + # 处理列表里不是字典的异常情况 + knowledge_info_str += f"{i+1}. 发现一条格式不正确的知识记录。\n" + + if not recent_knowledge: # 如果 knowledge_list 存在但为空 + knowledge_info_str += "- 暂无相关知识和记忆。\n" + + else: + # 如果 conversation_info 没有 knowledge_list 属性,或者列表为空 + knowledge_info_str += "- 暂无相关知识记忆。\n" + except AttributeError: + logger.warning(f"[私聊][{self.private_name}]ConversationInfo 对象可能缺少 knowledge_list 属性。") + knowledge_info_str += "- 获取知识列表时出错。\n" + except Exception as e: + logger.error(f"[私聊][{self.private_name}]构建知识信息字符串时出错: {e}") + knowledge_info_str += "- 处理知识列表时出错。\n" + # --- 知识信息字符串构建结束 --- + + # 获取聊天历史记录 (chat_history_text) chat_history_text = "" try: @@ -349,6 +385,7 @@ class ActionPlanner: time_since_last_bot_message_info=time_since_last_bot_message_info, timeout_context=timeout_context, chat_history_text=chat_history_text if chat_history_text.strip() else "还没有聊天记录。", + knowledge_info_str=knowledge_info_str ) logger.debug(f"[私聊][{self.private_name}]发送到LLM的最终提示词:\n------\n{prompt}\n------") diff --git a/src/plugins/PFC/reply_generator.py b/src/plugins/PFC/reply_generator.py index 9b497ef2..f813e140 100644 --- a/src/plugins/PFC/reply_generator.py +++ b/src/plugins/PFC/reply_generator.py @@ -17,6 +17,9 @@ logger = get_module_logger("reply_generator") PROMPT_DIRECT_REPLY = """{persona_text}。现在你在参与一场QQ私聊,请根据以下信息生成一条回复: 当前对话目标:{goals_str} + +{knowledge_info_str} + 最近的聊天记录: {chat_history_text} @@ -25,7 +28,7 @@ PROMPT_DIRECT_REPLY = """{persona_text}。现在你在参与一场QQ私聊,请 1. 符合对话目标,以"你"的角度发言(不要自己与自己对话!) 2. 符合你的性格特征和身份细节 3. 通俗易懂,自然流畅,像正常聊天一样,简短(通常20字以内,除非特殊情况) -4. 适当利用相关知识,但不要生硬引用 +4. 可以适当利用相关知识,但不要生硬引用 5. 自然、得体,结合聊天记录逻辑合理,且没有重复表达同质内容 请注意把握聊天内容,不要回复的太有条理,可以有个性。请分清"你"和对方说的话,不要把"你"说的话当做对方说的话,这是你自己说的话。 @@ -39,6 +42,9 @@ PROMPT_DIRECT_REPLY = """{persona_text}。现在你在参与一场QQ私聊,请 PROMPT_SEND_NEW_MESSAGE = """{persona_text}。现在你在参与一场QQ私聊,**刚刚你已经发送了一条或多条消息**,现在请根据以下信息再发一条新消息: 当前对话目标:{goals_str} + +{knowledge_info_str} + 最近的聊天记录: {chat_history_text} @@ -47,7 +53,7 @@ PROMPT_SEND_NEW_MESSAGE = """{persona_text}。现在你在参与一场QQ私聊 1. 符合对话目标,以"你"的角度发言(不要自己与自己对话!) 2. 符合你的性格特征和身份细节 3. 通俗易懂,自然流畅,像正常聊天一样,简短(通常20字以内,除非特殊情况) -4. 适当利用相关知识,但不要生硬引用 +4. 可以适当利用相关知识,但不要生硬引用 5. 跟之前你发的消息自然的衔接,逻辑合理,且没有重复表达同质内容或部分重叠内容 请注意把握聊天内容,不用太有条理,可以有个性。请分清"你"和对方说的话,不要把"你"说的话当做对方说的话,这是你自己说的话。 @@ -131,6 +137,36 @@ class ReplyGenerator: else: goals_str = "- 目前没有明确对话目标\n" # 简化无目标情况 + # --- 新增:构建知识信息字符串 --- + knowledge_info_str = "【供参考的相关知识和记忆】\n" # 稍微改下标题,表明是供参考 + try: + # 检查 conversation_info 是否有 knowledge_list 并且不为空 + if hasattr(conversation_info, "knowledge_list") and conversation_info.knowledge_list: + # 最多只显示最近的 3 条知识 + recent_knowledge = conversation_info.knowledge_list[-3:] + for i, knowledge_item in enumerate(recent_knowledge): + if isinstance(knowledge_item, dict): + query = knowledge_item.get('query', '未知查询') + knowledge = knowledge_item.get('knowledge', '无知识内容') + source = knowledge_item.get('source', '未知来源') + # 只取知识内容的前 150 个字 + knowledge_snippet = knowledge[:150] + "..." if len(knowledge) > 150 else knowledge + knowledge_info_str += f"{i+1}. 关于 '{query}' (来源: {source}): {knowledge_snippet}\n" # 格式微调,更简洁 + else: + knowledge_info_str += f"{i+1}. 发现一条格式不正确的知识记录。\n" + + if not recent_knowledge: + knowledge_info_str += "- 暂无。\n" # 更简洁的提示 + + else: + knowledge_info_str += "- 暂无。\n" + except AttributeError: + logger.warning(f"[私聊][{self.private_name}]ConversationInfo 对象可能缺少 knowledge_list 属性。") + knowledge_info_str += "- 获取知识列表时出错。\n" + except Exception as e: + logger.error(f"[私聊][{self.private_name}]构建知识信息字符串时出错: {e}") + knowledge_info_str += "- 处理知识列表时出错。\n" + # 获取聊天历史记录 (chat_history_text) chat_history_text = observation_info.chat_history_str if observation_info.new_messages_count > 0 and observation_info.unprocessed_messages: @@ -162,7 +198,10 @@ class ReplyGenerator: # --- 格式化最终的 Prompt --- prompt = prompt_template.format( - persona_text=persona_text, goals_str=goals_str, chat_history_text=chat_history_text + persona_text=persona_text, + goals_str=goals_str, + chat_history_text=chat_history_text, + knowledge_info_str=knowledge_info_str ) # --- 调用 LLM 生成 --- From 837b0b36889976e3a55689024fd2ee9c1eefc226 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 30 Apr 2025 06:49:22 +0000 Subject: [PATCH 10/15] =?UTF-8?q?=F0=9F=A4=96=20=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E6=A0=BC=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/plugins/PFC/action_planner.py | 19 ++++++++++--------- src/plugins/PFC/reply_generator.py | 24 +++++++++++++----------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/plugins/PFC/action_planner.py b/src/plugins/PFC/action_planner.py index dd7355fa..036d4780 100644 --- a/src/plugins/PFC/action_planner.py +++ b/src/plugins/PFC/action_planner.py @@ -235,18 +235,20 @@ class ActionPlanner: recent_knowledge = conversation_info.knowledge_list[-3:] for i, knowledge_item in enumerate(recent_knowledge): if isinstance(knowledge_item, dict): - query = knowledge_item.get('query', '未知查询') - knowledge = knowledge_item.get('knowledge', '无知识内容') - source = knowledge_item.get('source', '未知来源') + query = knowledge_item.get("query", "未知查询") + knowledge = knowledge_item.get("knowledge", "无知识内容") + source = knowledge_item.get("source", "未知来源") # 只取知识内容的前 150 个字,避免太长 knowledge_snippet = knowledge[:150] + "..." if len(knowledge) > 150 else knowledge - knowledge_info_str += f"{i+1}. 关于 '{query}' 的知识 (来源: {source}):\n {knowledge_snippet}\n" + knowledge_info_str += ( + f"{i + 1}. 关于 '{query}' 的知识 (来源: {source}):\n {knowledge_snippet}\n" + ) else: # 处理列表里不是字典的异常情况 - knowledge_info_str += f"{i+1}. 发现一条格式不正确的知识记录。\n" + knowledge_info_str += f"{i + 1}. 发现一条格式不正确的知识记录。\n" - if not recent_knowledge: # 如果 knowledge_list 存在但为空 - knowledge_info_str += "- 暂无相关知识和记忆。\n" + if not recent_knowledge: # 如果 knowledge_list 存在但为空 + knowledge_info_str += "- 暂无相关知识和记忆。\n" else: # 如果 conversation_info 没有 knowledge_list 属性,或者列表为空 @@ -259,7 +261,6 @@ class ActionPlanner: knowledge_info_str += "- 处理知识列表时出错。\n" # --- 知识信息字符串构建结束 --- - # 获取聊天历史记录 (chat_history_text) chat_history_text = "" try: @@ -385,7 +386,7 @@ class ActionPlanner: time_since_last_bot_message_info=time_since_last_bot_message_info, timeout_context=timeout_context, chat_history_text=chat_history_text if chat_history_text.strip() else "还没有聊天记录。", - knowledge_info_str=knowledge_info_str + knowledge_info_str=knowledge_info_str, ) logger.debug(f"[私聊][{self.private_name}]发送到LLM的最终提示词:\n------\n{prompt}\n------") diff --git a/src/plugins/PFC/reply_generator.py b/src/plugins/PFC/reply_generator.py index f813e140..134b2740 100644 --- a/src/plugins/PFC/reply_generator.py +++ b/src/plugins/PFC/reply_generator.py @@ -137,8 +137,8 @@ class ReplyGenerator: else: goals_str = "- 目前没有明确对话目标\n" # 简化无目标情况 - # --- 新增:构建知识信息字符串 --- - knowledge_info_str = "【供参考的相关知识和记忆】\n" # 稍微改下标题,表明是供参考 + # --- 新增:构建知识信息字符串 --- + knowledge_info_str = "【供参考的相关知识和记忆】\n" # 稍微改下标题,表明是供参考 try: # 检查 conversation_info 是否有 knowledge_list 并且不为空 if hasattr(conversation_info, "knowledge_list") and conversation_info.knowledge_list: @@ -146,17 +146,19 @@ class ReplyGenerator: recent_knowledge = conversation_info.knowledge_list[-3:] for i, knowledge_item in enumerate(recent_knowledge): if isinstance(knowledge_item, dict): - query = knowledge_item.get('query', '未知查询') - knowledge = knowledge_item.get('knowledge', '无知识内容') - source = knowledge_item.get('source', '未知来源') + query = knowledge_item.get("query", "未知查询") + knowledge = knowledge_item.get("knowledge", "无知识内容") + source = knowledge_item.get("source", "未知来源") # 只取知识内容的前 150 个字 knowledge_snippet = knowledge[:150] + "..." if len(knowledge) > 150 else knowledge - knowledge_info_str += f"{i+1}. 关于 '{query}' (来源: {source}): {knowledge_snippet}\n" # 格式微调,更简洁 + knowledge_info_str += ( + f"{i + 1}. 关于 '{query}' (来源: {source}): {knowledge_snippet}\n" # 格式微调,更简洁 + ) else: - knowledge_info_str += f"{i+1}. 发现一条格式不正确的知识记录。\n" + knowledge_info_str += f"{i + 1}. 发现一条格式不正确的知识记录。\n" if not recent_knowledge: - knowledge_info_str += "- 暂无。\n" # 更简洁的提示 + knowledge_info_str += "- 暂无。\n" # 更简洁的提示 else: knowledge_info_str += "- 暂无。\n" @@ -165,7 +167,7 @@ class ReplyGenerator: knowledge_info_str += "- 获取知识列表时出错。\n" except Exception as e: logger.error(f"[私聊][{self.private_name}]构建知识信息字符串时出错: {e}") - knowledge_info_str += "- 处理知识列表时出错。\n" + knowledge_info_str += "- 处理知识列表时出错。\n" # 获取聊天历史记录 (chat_history_text) chat_history_text = observation_info.chat_history_str @@ -199,9 +201,9 @@ class ReplyGenerator: # --- 格式化最终的 Prompt --- prompt = prompt_template.format( persona_text=persona_text, - goals_str=goals_str, + goals_str=goals_str, chat_history_text=chat_history_text, - knowledge_info_str=knowledge_info_str + knowledge_info_str=knowledge_info_str, ) # --- 调用 LLM 生成 --- From d09965571f432f50a4c907c33aaee0538649e930 Mon Sep 17 00:00:00 2001 From: 114514 <2514624910@qq.com> Date: Wed, 30 Apr 2025 15:06:01 +0800 Subject: [PATCH 11/15] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AD=97=E6=95=B0?= =?UTF-8?q?=E4=B8=8A=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/PFC/action_planner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/PFC/action_planner.py b/src/plugins/PFC/action_planner.py index dd7355fa..ec5eb8a8 100644 --- a/src/plugins/PFC/action_planner.py +++ b/src/plugins/PFC/action_planner.py @@ -238,8 +238,8 @@ class ActionPlanner: query = knowledge_item.get('query', '未知查询') knowledge = knowledge_item.get('knowledge', '无知识内容') source = knowledge_item.get('source', '未知来源') - # 只取知识内容的前 150 个字,避免太长 - knowledge_snippet = knowledge[:150] + "..." if len(knowledge) > 150 else knowledge + # 只取知识内容的前 2000 个字,避免太长 + knowledge_snippet = knowledge[:2000] + "..." if len(knowledge) > 200 else knowledge knowledge_info_str += f"{i+1}. 关于 '{query}' 的知识 (来源: {source}):\n {knowledge_snippet}\n" else: # 处理列表里不是字典的异常情况 From 7ef65cadc24e1d7c94ae65ea2672094a0b95e4b0 Mon Sep 17 00:00:00 2001 From: Bakadax Date: Wed, 30 Apr 2025 15:07:34 +0800 Subject: [PATCH 12/15] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=A9=BA=E6=9D=A5?= =?UTF-8?q?=E6=BA=90=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/PFC/pfc_KnowledgeFetcher.py | 3 ++- src/plugins/PFC/reply_generator.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plugins/PFC/pfc_KnowledgeFetcher.py b/src/plugins/PFC/pfc_KnowledgeFetcher.py index 7453aa0e..171ba705 100644 --- a/src/plugins/PFC/pfc_KnowledgeFetcher.py +++ b/src/plugins/PFC/pfc_KnowledgeFetcher.py @@ -69,8 +69,9 @@ class KnowledgeFetcher: fast_retrieval=False, ) knowledge_text = "" - sources = [] + sources_text = "无记忆匹配" # 默认值 if related_memory: + sources = [] for memory in related_memory: knowledge_text += memory[1] + "\n" sources.append(f"记忆片段{memory[0]}") diff --git a/src/plugins/PFC/reply_generator.py b/src/plugins/PFC/reply_generator.py index f813e140..3de22fcf 100644 --- a/src/plugins/PFC/reply_generator.py +++ b/src/plugins/PFC/reply_generator.py @@ -137,7 +137,7 @@ class ReplyGenerator: else: goals_str = "- 目前没有明确对话目标\n" # 简化无目标情况 - # --- 新增:构建知识信息字符串 --- + # --- 新增:构建知识信息字符串 --- knowledge_info_str = "【供参考的相关知识和记忆】\n" # 稍微改下标题,表明是供参考 try: # 检查 conversation_info 是否有 knowledge_list 并且不为空 @@ -156,7 +156,7 @@ class ReplyGenerator: knowledge_info_str += f"{i+1}. 发现一条格式不正确的知识记录。\n" if not recent_knowledge: - knowledge_info_str += "- 暂无。\n" # 更简洁的提示 + knowledge_info_str += "- 暂无。\n" # 更简洁的提示 else: knowledge_info_str += "- 暂无。\n" From 94dd06561e88d7d5ffbf60bb44ac7785cf16cbec Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 30 Apr 2025 07:08:58 +0000 Subject: [PATCH 13/15] =?UTF-8?q?=F0=9F=A4=96=20=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E6=A0=BC=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/plugins/PFC/action_planner.py | 10 ++++++---- src/plugins/PFC/reply_generator.py | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/plugins/PFC/action_planner.py b/src/plugins/PFC/action_planner.py index 7082e281..78f41936 100644 --- a/src/plugins/PFC/action_planner.py +++ b/src/plugins/PFC/action_planner.py @@ -235,12 +235,14 @@ class ActionPlanner: recent_knowledge = conversation_info.knowledge_list[-3:] for i, knowledge_item in enumerate(recent_knowledge): if isinstance(knowledge_item, dict): - query = knowledge_item.get('query', '未知查询') - knowledge = knowledge_item.get('knowledge', '无知识内容') - source = knowledge_item.get('source', '未知来源') + query = knowledge_item.get("query", "未知查询") + knowledge = knowledge_item.get("knowledge", "无知识内容") + source = knowledge_item.get("source", "未知来源") # 只取知识内容的前 2000 个字,避免太长 knowledge_snippet = knowledge[:2000] + "..." if len(knowledge) > 200 else knowledge - knowledge_info_str += f"{i+1}. 关于 '{query}' 的知识 (来源: {source}):\n {knowledge_snippet}\n" + knowledge_info_str += ( + f"{i + 1}. 关于 '{query}' 的知识 (来源: {source}):\n {knowledge_snippet}\n" + ) else: # 处理列表里不是字典的异常情况 knowledge_info_str += f"{i + 1}. 发现一条格式不正确的知识记录。\n" diff --git a/src/plugins/PFC/reply_generator.py b/src/plugins/PFC/reply_generator.py index f5e7c1e6..134b2740 100644 --- a/src/plugins/PFC/reply_generator.py +++ b/src/plugins/PFC/reply_generator.py @@ -138,7 +138,7 @@ class ReplyGenerator: goals_str = "- 目前没有明确对话目标\n" # 简化无目标情况 # --- 新增:构建知识信息字符串 --- - knowledge_info_str = "【供参考的相关知识和记忆】\n" # 稍微改下标题,表明是供参考 + knowledge_info_str = "【供参考的相关知识和记忆】\n" # 稍微改下标题,表明是供参考 try: # 检查 conversation_info 是否有 knowledge_list 并且不为空 if hasattr(conversation_info, "knowledge_list") and conversation_info.knowledge_list: @@ -158,7 +158,7 @@ class ReplyGenerator: knowledge_info_str += f"{i + 1}. 发现一条格式不正确的知识记录。\n" if not recent_knowledge: - knowledge_info_str += "- 暂无。\n" # 更简洁的提示 + knowledge_info_str += "- 暂无。\n" # 更简洁的提示 else: knowledge_info_str += "- 暂无。\n" From 03a9f50128b458130de0804a13afc3c47062dd04 Mon Sep 17 00:00:00 2001 From: 114514 <2514624910@qq.com> Date: Wed, 30 Apr 2025 15:10:26 +0800 Subject: [PATCH 14/15] 1 --- src/plugins/PFC/action_planner.py | 6 +++--- src/plugins/PFC/reply_generator.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plugins/PFC/action_planner.py b/src/plugins/PFC/action_planner.py index ec5eb8a8..63677b04 100644 --- a/src/plugins/PFC/action_planner.py +++ b/src/plugins/PFC/action_planner.py @@ -231,15 +231,15 @@ class ActionPlanner: try: # 检查 conversation_info 是否有 knowledge_list 并且不为空 if hasattr(conversation_info, "knowledge_list") and conversation_info.knowledge_list: - # 最多只显示最近的 3 条知识,防止 Prompt 过长 - recent_knowledge = conversation_info.knowledge_list[-3:] + # 最多只显示最近的 5 条知识,防止 Prompt 过长 + recent_knowledge = conversation_info.knowledge_list[-5:] for i, knowledge_item in enumerate(recent_knowledge): if isinstance(knowledge_item, dict): query = knowledge_item.get('query', '未知查询') knowledge = knowledge_item.get('knowledge', '无知识内容') source = knowledge_item.get('source', '未知来源') # 只取知识内容的前 2000 个字,避免太长 - knowledge_snippet = knowledge[:2000] + "..." if len(knowledge) > 200 else knowledge + knowledge_snippet = knowledge[:2000] + "..." if len(knowledge) > 2000 else knowledge knowledge_info_str += f"{i+1}. 关于 '{query}' 的知识 (来源: {source}):\n {knowledge_snippet}\n" else: # 处理列表里不是字典的异常情况 diff --git a/src/plugins/PFC/reply_generator.py b/src/plugins/PFC/reply_generator.py index f813e140..438a21ac 100644 --- a/src/plugins/PFC/reply_generator.py +++ b/src/plugins/PFC/reply_generator.py @@ -142,15 +142,15 @@ class ReplyGenerator: try: # 检查 conversation_info 是否有 knowledge_list 并且不为空 if hasattr(conversation_info, "knowledge_list") and conversation_info.knowledge_list: - # 最多只显示最近的 3 条知识 - recent_knowledge = conversation_info.knowledge_list[-3:] + # 最多只显示最近的 5 条知识 + recent_knowledge = conversation_info.knowledge_list[-5:] for i, knowledge_item in enumerate(recent_knowledge): if isinstance(knowledge_item, dict): query = knowledge_item.get('query', '未知查询') knowledge = knowledge_item.get('knowledge', '无知识内容') source = knowledge_item.get('source', '未知来源') # 只取知识内容的前 150 个字 - knowledge_snippet = knowledge[:150] + "..." if len(knowledge) > 150 else knowledge + knowledge_snippet = knowledge[:2000] + "..." if len(knowledge) > 2000 else knowledge knowledge_info_str += f"{i+1}. 关于 '{query}' (来源: {source}): {knowledge_snippet}\n" # 格式微调,更简洁 else: knowledge_info_str += f"{i+1}. 发现一条格式不正确的知识记录。\n" From 0caaec69c19b6f98cc8747e18427056427fbcea5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 30 Apr 2025 08:20:16 +0000 Subject: [PATCH 15/15] =?UTF-8?q?=F0=9F=A4=96=20=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E6=A0=BC=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/plugins/PFC/reply_generator.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/PFC/reply_generator.py b/src/plugins/PFC/reply_generator.py index b577872f..890f807c 100644 --- a/src/plugins/PFC/reply_generator.py +++ b/src/plugins/PFC/reply_generator.py @@ -151,7 +151,9 @@ class ReplyGenerator: source = knowledge_item.get("source", "未知来源") # 只取知识内容的前 2000 个字 knowledge_snippet = knowledge[:2000] + "..." if len(knowledge) > 2000 else knowledge - knowledge_info_str += f"{i+1}. 关于 '{query}' (来源: {source}): {knowledge_snippet}\n" # 格式微调,更简洁 + knowledge_info_str += ( + f"{i + 1}. 关于 '{query}' (来源: {source}): {knowledge_snippet}\n" # 格式微调,更简洁 + ) else: knowledge_info_str += f"{i + 1}. 发现一条格式不正确的知识记录。\n"