diff --git a/src/chat/chat_loop/cycle_processor.py b/src/chat/chat_loop/cycle_processor.py index 441d14b1f..e571b5ac5 100644 --- a/src/chat/chat_loop/cycle_processor.py +++ b/src/chat/chat_loop/cycle_processor.py @@ -267,6 +267,7 @@ class CycleProcessor: enable_tool=global_config.tool.enable_tool, request_type="chat.replyer", from_plugin=False, + read_mark=action_info.get("action_message", {}).get("time", 0.0), ) if not success or not response_set: logger.info( diff --git a/src/chat/replyer/default_generator.py b/src/chat/replyer/default_generator.py index ad2ea864e..092f2680b 100644 --- a/src/chat/replyer/default_generator.py +++ b/src/chat/replyer/default_generator.py @@ -82,12 +82,12 @@ def init_prompt(): - {schedule_block} ## 历史记录 -### 当前群聊中的所有人的聊天记录: +### {chat_context_type}中的所有人的聊天记录: {background_dialogue_prompt} {cross_context_block} -### 当前群聊中正在与你对话的聊天记录 +### {chat_context_type}中正在与你对话的聊天记录 {core_dialogue_prompt} ## 表达方式 @@ -109,12 +109,11 @@ def init_prompt(): ## 任务 -*你正在一个QQ群里聊天,你需要理解整个群的聊天动态和话题走向,并做出自然的回应。* +*你正在一个{chat_context_type}里聊天,你需要理解整个{chat_context_type}的聊天动态和话题走向,并做出自然的回应。* ### 核心任务 -- 你现在的主要任务是和 {sender_name} 聊天。同时,也有其他用户会参与聊天,你可以参考他们的回复内容,但是你现在想回复{sender_name}的发言。 - -- {reply_target_block} ,你需要生成一段紧密相关且能推动对话的回复。 +- 你现在的主要任务是和 {sender_name} 聊天。 +- {reply_target_block} ,你需要生成一段紧密相关且能推动对话的回复。 ## 规则 {safety_guidelines_block} @@ -236,6 +235,7 @@ class DefaultReplyer: from_plugin: bool = True, stream_id: Optional[str] = None, reply_message: Optional[Dict[str, Any]] = None, + read_mark: float = 0.0, ) -> Tuple[bool, Optional[Dict[str, Any]], Optional[str]]: # sourcery skip: merge-nested-ifs """ @@ -272,6 +272,7 @@ class DefaultReplyer: choosen_actions=choosen_actions, enable_tool=enable_tool, reply_message=reply_message, + read_mark=read_mark, ) if not prompt: @@ -723,10 +724,8 @@ class DefaultReplyer: truncate=True, show_actions=True, ) - core_dialogue_prompt = f"""-------------------------------- -这是你和{sender}的对话,你们正在交流中: + core_dialogue_prompt = f""" {core_dialogue_prompt_str} --------------------------------- """ return core_dialogue_prompt, all_dialogue_prompt @@ -815,6 +814,7 @@ class DefaultReplyer: choosen_actions: Optional[List[Dict[str, Any]]] = None, enable_tool: bool = True, reply_message: Optional[Dict[str, Any]] = None, + read_mark: float = 0.0, ) -> str: """ 构建回复器上下文 @@ -904,7 +904,7 @@ class DefaultReplyer: target = "(无消息内容)" person_info_manager = get_person_info_manager() - person_id = await person_info_manager.get_person_id_by_person_name(sender) + person_id = person_info_manager.get_person_id(platform, reply_message.get("user_id")) if reply_message else None platform = chat_stream.platform target = replace_user_references_sync(target, chat_stream.platform, replace_bot_name=True) @@ -936,7 +936,7 @@ class DefaultReplyer: replace_bot_name=True, merge_messages=False, timestamp_mode="relative", - read_mark=0.0, + read_mark=read_mark, show_actions=True, ) # 获取目标用户信息,用于s4u模式 @@ -1117,6 +1117,7 @@ class DefaultReplyer: reply_target_block=reply_target_block, mood_prompt=mood_prompt, action_descriptions=action_descriptions, + read_mark=read_mark, ) # 使用新的统一Prompt系统 - 使用正确的模板名称 @@ -1203,7 +1204,7 @@ class DefaultReplyer: replace_bot_name=True, merge_messages=False, timestamp_mode="relative", - read_mark=0.0, + read_mark=read_mark, show_actions=True, ) diff --git a/src/chat/utils/chat_message_builder.py b/src/chat/utils/chat_message_builder.py index 1b7f5e876..eca6bca57 100644 --- a/src/chat/utils/chat_message_builder.py +++ b/src/chat/utils/chat_message_builder.py @@ -516,6 +516,7 @@ async def _build_readable_messages_internal( pic_counter: int = 1, show_pic: bool = True, message_id_list: Optional[List[Dict[str, Any]]] = None, + read_mark: float = 0.0, ) -> Tuple[str, List[Tuple[float, str, str]], Dict[str, str], int]: """ 内部辅助函数,构建可读消息字符串和原始消息详情列表。 @@ -721,11 +722,10 @@ async def _build_readable_messages_internal( "is_action": is_action, } continue - # 如果是同一个人发送的连续消息且时间间隔小于等于60秒 if name == current_merge["name"] and (timestamp - current_merge["end_time"] <= 60): current_merge["content"].append(content) - current_merge["end_time"] = timestamp # 更新最后消息时间 + current_merge["end_time"] = timestamp else: # 保存上一个合并块 merged_messages.append(current_merge) @@ -753,8 +753,14 @@ async def _build_readable_messages_internal( # 4 & 5: 格式化为字符串 output_lines = [] + read_mark_inserted = False for _i, merged in enumerate(merged_messages): + # 检查是否需要插入已读标记 + if read_mark > 0 and not read_mark_inserted and merged["start_time"] >= read_mark: + output_lines.append("\n--- 以上消息是你已经看过,请关注以下未读的新消息---\n") + read_mark_inserted = True + # 使用指定的 timestamp_mode 格式化时间 readable_time = translate_timestamp_to_human_readable(merged["start_time"], mode=timestamp_mode) diff --git a/src/chat/utils/prompt.py b/src/chat/utils/prompt.py index db31acfa5..3d97b622e 100644 --- a/src/chat/utils/prompt.py +++ b/src/chat/utils/prompt.py @@ -78,6 +78,7 @@ class PromptParameters: # 可用动作信息 available_actions: Optional[Dict[str, Any]] = None + read_mark: float = 0.0 def validate(self) -> List[str]: """参数验证""" @@ -449,7 +450,8 @@ class Prompt: core_dialogue, background_dialogue = await self._build_s4u_chat_history_prompts( self.parameters.message_list_before_now_long, self.parameters.target_user_info.get("user_id") if self.parameters.target_user_info else "", - self.parameters.sender + self.parameters.sender, + read_mark=self.parameters.read_mark, ) context_data["core_dialogue_prompt"] = core_dialogue @@ -465,7 +467,7 @@ class Prompt: @staticmethod async def _build_s4u_chat_history_prompts( - message_list_before_now: List[Dict[str, Any]], target_user_id: str, sender: str + message_list_before_now: List[Dict[str, Any]], target_user_id: str, sender: str, read_mark: float = 0.0 ) -> Tuple[str, str]: """构建S4U风格的分离对话prompt""" # 实现逻辑与原有SmartPromptBuilder相同 @@ -491,6 +493,7 @@ class Prompt: replace_bot_name=True, timestamp_mode="normal", truncate=True, + read_mark=read_mark, ) all_dialogue_prompt = f"所有用户的发言:\n{all_dialogue_prompt_str}" @@ -510,7 +513,7 @@ class Prompt: replace_bot_name=True, merge_messages=False, timestamp_mode="normal_no_YMD", - read_mark=0.0, + read_mark=read_mark, truncate=True, show_actions=True, ) @@ -764,6 +767,7 @@ class Prompt: "keywords_reaction_prompt": self.parameters.keywords_reaction_prompt or context_data.get("keywords_reaction_prompt", ""), "moderation_prompt": self.parameters.moderation_prompt_block or context_data.get("moderation_prompt", ""), "safety_guidelines_block": self.parameters.safety_guidelines_block or context_data.get("safety_guidelines_block", ""), + "chat_context_type": "群聊" if self.parameters.is_group_chat else "私聊", } def _prepare_normal_params(self, context_data: Dict[str, Any]) -> Dict[str, Any]: diff --git a/src/plugin_system/apis/generator_api.py b/src/plugin_system/apis/generator_api.py index a62ef9c66..8f2e342a0 100644 --- a/src/plugin_system/apis/generator_api.py +++ b/src/plugin_system/apis/generator_api.py @@ -86,6 +86,7 @@ async def generate_reply( return_prompt: bool = False, request_type: str = "generator_api", from_plugin: bool = True, + read_mark: float = 0.0, ) -> Tuple[bool, List[Tuple[str, Any]], Optional[str]]: """生成回复 @@ -138,6 +139,7 @@ async def generate_reply( from_plugin=from_plugin, stream_id=chat_stream.stream_id if chat_stream else chat_id, reply_message=reply_message, + read_mark=read_mark, ) if not success: logger.warning("[GeneratorAPI] 回复生成失败")