From 69a1f60841d9a0a6f28c6f3fe939b2fda42aec48 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Fri, 12 Sep 2025 20:34:31 +0800 Subject: [PATCH] =?UTF-8?q?feat(chat):=20=E5=A2=9E=E5=BC=BAprompt=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98=E5=8C=96=E5=9B=9E?= =?UTF-8?q?=E5=A4=8D=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为HfcContext和ChatStream添加focus_energy配置支持 - 修复默认回复生成器中识别自身消息的逻辑 - 完整实现prompt构建中的表达习惯、记忆、工具信息和知识模块 - 优化错误处理,使用原生异常链式传递 - 确保数据库操作中focus_energy字段的持久化 这些改进提升了聊天系统的上下文感知能力和回复质量,同时增强了模块的健壮性和可维护性。 --- src/chat/chat_loop/hfc_context.py | 4 +- src/chat/message_receive/chat_stream.py | 6 +- src/chat/replyer/default_generator.py | 18 ++- src/chat/utils/prompt.py | 201 ++++++++++++++++++++++-- 4 files changed, 208 insertions(+), 21 deletions(-) diff --git a/src/chat/chat_loop/hfc_context.py b/src/chat/chat_loop/hfc_context.py index e6a4b31f3..fe5d283ae 100644 --- a/src/chat/chat_loop/hfc_context.py +++ b/src/chat/chat_loop/hfc_context.py @@ -5,6 +5,7 @@ from src.person_info.relationship_builder_manager import RelationshipBuilder from src.chat.express.expression_learner import ExpressionLearner from src.chat.planner_actions.action_manager import ActionManager from src.chat.chat_loop.hfc_utils import CycleDetail +from src.config.config import global_config if TYPE_CHECKING: from .sleep_manager.wakeup_manager import WakeUpManager @@ -64,7 +65,8 @@ class HfcContext: self.energy_manager: Optional["EnergyManager"] = None self.sleep_manager: Optional["SleepManager"] = None - self.focus_energy = 1 + # 从聊天流获取focus_energy,如果没有则使用配置文件中的值 + self.focus_energy = getattr(self.chat_stream, "focus_energy", global_config.chat.focus_value) self.no_reply_consecutive = 0 self.total_interest = 0.0 # breaking形式下的累积兴趣值 diff --git a/src/chat/message_receive/chat_stream.py b/src/chat/message_receive/chat_stream.py index c43901eab..f5822acfb 100644 --- a/src/chat/message_receive/chat_stream.py +++ b/src/chat/message_receive/chat_stream.py @@ -83,7 +83,8 @@ class ChatStream: self.sleep_pressure = data.get("sleep_pressure", 0.0) if data else 0.0 self.saved = False self.context: ChatMessageContext = None # type: ignore # 用于存储该聊天的上下文信息 - self.focus_energy = 1 + # 从配置文件中读取focus_value,如果没有则使用默认值1.0 + self.focus_energy = data.get("focus_energy", global_config.chat.focus_value) if data else global_config.chat.focus_value self.no_reply_consecutive = 0 self.breaking_accumulated_interest = 0.0 @@ -98,6 +99,7 @@ class ChatStream: "last_active_time": self.last_active_time, "energy_value": self.energy_value, "sleep_pressure": self.sleep_pressure, + "focus_energy": self.focus_energy, "breaking_accumulated_interest": self.breaking_accumulated_interest, } @@ -360,6 +362,7 @@ class ChatManager: "group_name": group_info_d["group_name"] if group_info_d else "", "energy_value": s_data_dict.get("energy_value", 5.0), "sleep_pressure": s_data_dict.get("sleep_pressure", 0.0), + "focus_energy": s_data_dict.get("focus_energy", global_config.chat.focus_value), } # 根据数据库类型选择插入语句 @@ -421,6 +424,7 @@ class ChatManager: "last_active_time": model_instance.last_active_time, "energy_value": model_instance.energy_value, "sleep_pressure": model_instance.sleep_pressure, + "focus_energy": getattr(model_instance, "focus_energy", global_config.chat.focus_value), } loaded_streams_data.append(data_for_from_dict) session.commit() diff --git a/src/chat/replyer/default_generator.py b/src/chat/replyer/default_generator.py index ef9cce84d..d601e7030 100644 --- a/src/chat/replyer/default_generator.py +++ b/src/chat/replyer/default_generator.py @@ -139,8 +139,6 @@ def init_prompt(): -------------------------------- {time_block} -{reply_target_block} - 注意不要复读你前面发过的内容,意思相近也不行。 请注意不要输出多余内容(包括前后缀,冒号和引号,at或 @等 )。只输出回复内容。 @@ -832,16 +830,22 @@ class DefaultReplyer: reply_message.get("user_id"), # type: ignore ) person_name = await person_info_manager.get_value(person_id, "person_name") - sender = person_name + + # 检查是否是bot自己的名字,如果是则替换为"(你)" + bot_user_id = str(global_config.bot.qq_account) + current_user_id = person_info_manager.get_value_sync(person_id, "user_id") + current_platform = reply_message.get("chat_info_platform") + + if current_user_id == bot_user_id and current_platform == global_config.bot.platform: + sender = f"{person_name}(你)" + else: + # 如果不是bot自己,直接使用person_name + sender = person_name target = reply_message.get("processed_plain_text") person_info_manager = get_person_info_manager() person_id = person_info_manager.get_person_id_by_person_name(sender) - user_id = person_info_manager.get_value_sync(person_id, "user_id") platform = chat_stream.platform - if user_id == global_config.bot.qq_account and platform == global_config.bot.platform: - logger.warning("选取了自身作为回复对象,跳过构建prompt") - return "" target = replace_user_references_sync(target, chat_stream.platform, replace_bot_name=True) diff --git a/src/chat/utils/prompt.py b/src/chat/utils/prompt.py index b5cf140c5..ae0c9c4b1 100644 --- a/src/chat/utils/prompt.py +++ b/src/chat/utils/prompt.py @@ -312,16 +312,15 @@ class Prompt: except asyncio.TimeoutError as e: logger.error(f"构建Prompt超时: {e}") - raise TimeoutError(f"构建Prompt超时: {e}") + raise TimeoutError(f"构建Prompt超时: {e}") from e except Exception as e: logger.error(f"构建Prompt失败: {e}") - raise RuntimeError(f"构建Prompt失败: {e}") + raise RuntimeError(f"构建Prompt失败: {e}") from e async def _build_context_data(self) -> Dict[str, Any]: """构建智能上下文数据""" # 并行执行所有构建任务 start_time = time.time() - timing_logs = {} try: # 准备构建任务 @@ -381,7 +380,6 @@ class Prompt: results = [] for i in range(0, len(tasks), max_concurrent_tasks): batch_tasks = tasks[i : i + max_concurrent_tasks] - batch_names = task_names[i : i + max_concurrent_tasks] batch_results = await asyncio.wait_for( asyncio.gather(*batch_tasks, return_exceptions=True), timeout=timeout_seconds @@ -520,13 +518,99 @@ class Prompt: async def _build_expression_habits(self) -> Dict[str, Any]: """构建表达习惯""" - # 简化的实现,完整实现需要导入相关模块 - return {"expression_habits_block": ""} + if not global_config.expression.enable_expression: + return {"expression_habits_block": ""} + + try: + from src.chat.express.expression_selector import ExpressionSelector + + # 获取聊天历史用于表情选择 + chat_history = "" + if self.parameters.message_list_before_now_long: + recent_messages = self.parameters.message_list_before_now_long[-10:] + chat_history = build_readable_messages( + recent_messages, + replace_bot_name=True, + timestamp_mode="normal", + truncate=True + ) + + # 创建表情选择器 + expression_selector = ExpressionSelector(self.parameters.chat_id) + + # 选择合适的表情 + selected_expressions = await expression_selector.select_suitable_expressions_llm( + chat_history=chat_history, + current_message=self.parameters.target, + emotional_tone="neutral", + topic_type="general" + ) + + # 构建表达习惯块 + if selected_expressions: + style_habits_str = "\n".join([f"- {expr}" for expr in selected_expressions]) + expression_habits_block = f"你可以参考以下的语言习惯,当情景合适就使用,但不要生硬使用,以合理的方式结合到你的回复中:\n{style_habits_str}" + else: + expression_habits_block = "" + + return {"expression_habits_block": expression_habits_block} + + except Exception as e: + logger.error(f"构建表达习惯失败: {e}") + return {"expression_habits_block": ""} async def _build_memory_block(self) -> Dict[str, Any]: """构建记忆块""" - # 简化的实现 - return {"memory_block": ""} + if not global_config.memory.enable_memory: + return {"memory_block": ""} + + try: + from src.chat.memory_system.memory_activator import MemoryActivator + from src.chat.memory_system.async_instant_memory_wrapper import async_memory + + # 获取聊天历史 + chat_history = "" + if self.parameters.message_list_before_now_long: + recent_messages = self.parameters.message_list_before_now_long[-20:] + chat_history = build_readable_messages( + recent_messages, + replace_bot_name=True, + timestamp_mode="normal", + truncate=True + ) + + # 激活长期记忆 + memory_activator = MemoryActivator() + running_memories = await memory_activator.activate_memory_with_chat_history( + chat_history=chat_history, + target_user=self.parameters.sender, + chat_id=self.parameters.chat_id + ) + + # 获取即时记忆 + instant_memory = await async_memory.get_memory_with_fallback( + chat_id=self.parameters.chat_id, + target_user=self.parameters.sender + ) + + # 构建记忆块 + memory_parts = [] + + if running_memories: + memory_parts.append("以下是当前在聊天中,你回忆起的记忆:") + for memory in running_memories: + memory_parts.append(f"- {memory['content']}") + + if instant_memory: + memory_parts.append(f"- {instant_memory}") + + memory_block = "\n".join(memory_parts) if memory_parts else "" + + return {"memory_block": memory_block} + + except Exception as e: + logger.error(f"构建记忆块失败: {e}") + return {"memory_block": ""} async def _build_relation_info(self) -> Dict[str, Any]: """构建关系信息""" @@ -539,13 +623,106 @@ class Prompt: async def _build_tool_info(self) -> Dict[str, Any]: """构建工具信息""" - # 简化的实现 - return {"tool_info_block": ""} + if not global_config.tool.enable_tool: + return {"tool_info_block": ""} + + try: + from src.plugin_system.core.tool_use import ToolExecutor + + # 获取聊天历史 + chat_history = "" + if self.parameters.message_list_before_now_long: + recent_messages = self.parameters.message_list_before_now_long[-15:] + chat_history = build_readable_messages( + recent_messages, + replace_bot_name=True, + timestamp_mode="normal", + truncate=True + ) + + # 创建工具执行器 + tool_executor = ToolExecutor() + + # 执行工具获取信息 + tool_results, _, _ = await tool_executor.execute_from_chat_message( + sender=self.parameters.sender, + target_message=self.parameters.target, + chat_history=chat_history, + return_details=False + ) + + # 构建工具信息块 + if tool_results: + tool_info_parts = ["以下是你通过工具获取到的实时信息:"] + for tool_result in tool_results: + tool_name = tool_result.get("tool_name", "unknown") + content = tool_result.get("content", "") + result_type = tool_result.get("type", "tool_result") + + tool_info_parts.append(f"- 【{tool_name}】{result_type}: {content}") + + tool_info_parts.append("以上是你获取到的实时信息,请在回复时参考这些信息。") + tool_info_block = "\n".join(tool_info_parts) + else: + tool_info_block = "" + + return {"tool_info_block": tool_info_block} + + except Exception as e: + logger.error(f"构建工具信息失败: {e}") + return {"tool_info_block": ""} async def _build_knowledge_info(self) -> Dict[str, Any]: """构建知识信息""" - # 简化的实现 - return {"knowledge_prompt": ""} + if not global_config.lpmm_knowledge.enable: + return {"knowledge_prompt": ""} + + try: + from src.chat.knowledge.knowledge_lib import QAManager + + # 获取问题文本(当前消息) + question = self.parameters.target or "" + if not question: + return {"knowledge_prompt": ""} + + # 创建QA管理器 + qa_manager = QAManager() + + # 搜索相关知识 + knowledge_results = await qa_manager.get_knowledge( + question=question, + chat_id=self.parameters.chat_id, + max_results=5, + min_similarity=0.5 + ) + + # 构建知识块 + if knowledge_results and knowledge_results.get("knowledge_items"): + knowledge_parts = ["以下是与你当前对话相关的知识信息:"] + + for item in knowledge_results["knowledge_items"]: + content = item.get("content", "") + source = item.get("source", "") + relevance = item.get("relevance", 0.0) + + if content: + if source: + knowledge_parts.append(f"- [{relevance:.2f}] {content} (来源: {source})") + else: + knowledge_parts.append(f"- [{relevance:.2f}] {content}") + + if knowledge_results.get("summary"): + knowledge_parts.append(f"\n知识总结: {knowledge_results['summary']}") + + knowledge_prompt = "\n".join(knowledge_parts) + else: + knowledge_prompt = "" + + return {"knowledge_prompt": knowledge_prompt} + + except Exception as e: + logger.error(f"构建知识信息失败: {e}") + return {"knowledge_prompt": ""} async def _build_cross_context(self) -> Dict[str, Any]: """构建跨群上下文"""