diff --git a/src/plugins/built_in/kokoro_flow_chatter/prompt/builder.py b/src/plugins/built_in/kokoro_flow_chatter/prompt/builder.py index d4ca624fe..cf14e06e1 100644 --- a/src/plugins/built_in/kokoro_flow_chatter/prompt/builder.py +++ b/src/plugins/built_in/kokoro_flow_chatter/prompt/builder.py @@ -1027,7 +1027,7 @@ class PromptBuilder: {"type": "kfc_reply", "content": "你的回复内容"} ], "expected_reaction": "你期待对方的反应是什么", - "max_wait_seconds": 等待时间(秒),0 表示不等待 + "max_wait_seconds": "预估的等待时间(秒)" } ``` @@ -1035,7 +1035,10 @@ class PromptBuilder: - `thought`:你的内心独白,记录你此刻的想法和感受。要自然,不要技术性语言。 - `actions`:你要执行的动作列表。对于 `kfc_reply` 动作,**必须**填写 `content` 字段,写上你要说的话。 - `expected_reaction`:你期待对方如何回应(用于判断是否需要等待) -- `max_wait_seconds`:设定等待时间(秒),0 表示不等待,超时后你会考虑是否要主动说点什么 +- `max_wait_seconds`:预估的等待时间(秒),这很关键,请根据对话节奏来判断: + - 如果你刚问了一个开放性问题(比如"你觉得呢?"、"后来怎么样了?"),或者对话明显还在兴头上,设置一个等待时间(比如 60-180 秒),给对方思考和打字的时间。 + - 如果对话感觉自然结束了(比如晚安、拜拜),或者你给出了一个总结性的陈述,那就设置为 0,表示你觉得可以告一段落了。 + - 不要总是设为 0,那会显得你很急着结束对话。 ### 注意事项 - kfc_reply 的 content 字段是必填的,直接写你要发送的消息内容 diff --git a/src/plugins/built_in/kokoro_flow_chatter/prompt/prompts.py b/src/plugins/built_in/kokoro_flow_chatter/prompt/prompts.py index f9fc218e0..9f5956415 100644 --- a/src/plugins/built_in/kokoro_flow_chatter/prompt/prompts.py +++ b/src/plugins/built_in/kokoro_flow_chatter/prompt/prompts.py @@ -124,11 +124,24 @@ kfc_SITUATION_TIMEOUT = Prompt( 你原本打算最多等 {max_wait_minutes:.1f} 分钟,现在已经等了 {elapsed_minutes:.1f} 分钟了,对方还是没回。 你当时期待的反应是:"{expected_reaction}" {timeout_context} -你需要决定: -1. 继续等待(设置新的 max_wait_seconds) -2. 主动说点什么打破沉默 -3. 做点别的事情(执行其他动作) -4. 算了不等了(max_wait_seconds = 0) + +**决策指导:** +- **评估话题**:你上一条消息是结束性的,还是开启性的?是陈述句,还是疑问句? +- **考虑关系**:你们的关系有多亲近?频繁追问是否会打扰到对方? +- **保持自然**:像真人一样思考,对方可能只是暂时在忙。 + +**决策选项:** +1. **再等等看**:如果觉得话题还没结束,或者对方可能只是需要多点时间,可以选择再等一会。 + - 使用 `do_nothing`,并设置一个新的、合理的 `max_wait_seconds`(比如 60-300 秒)。 + +2. **开启新话题**:如果感觉之前的话题已经告一段落,或者想轻松地打破沉默,可以主动开启一个轻松的新话题。 + - 使用 `kfc_reply` 发送一条新的、不相关的问候或分享。 + +3. **轻轻追问**:如果你们正在讨论一件很重要的事,或者你发的上一条是关键问题,可以委婉地追问一下。 + - 使用 `kfc_reply` 发送一条温柔的提醒,例如"在忙吗?"或者"刚才说到哪啦?"。 + +4. **结束等待**:如果你觉得对话确实已经结束,或者不想再打扰对方,就自然地结束等待。 + - 使用 `do_nothing`,并将 `max_wait_seconds` 设为 0。 【注意】如果已经连续多次超时,对方可能暂时不方便回复。频繁主动发消息可能会打扰到对方。 考虑是否应该暂时放下期待,让对方有空间。""", @@ -228,7 +241,7 @@ kfc_PLANNER_OUTPUT_FORMAT = Prompt( {{"type": "动作名称", ...动作参数}} ], "expected_reaction": "你期待对方的反应是什么", - "max_wait_seconds": 等待时间(秒),0 表示不等待 + "max_wait_seconds": "预估的等待时间(秒)" }} ``` @@ -237,7 +250,10 @@ kfc_PLANNER_OUTPUT_FORMAT = Prompt( - `actions`:你要执行的动作列表。每个动作是一个对象,必须包含 `type` 字段指定动作类型,其他字段根据动作类型不同而不同(参考上面每个动作的示例)。 - 对于 `kfc_reply` 动作,只需要指定 `{{"type": "kfc_reply"}}`,不需要填写 `content` 字段(回复内容会单独生成) - `expected_reaction`:你期待对方如何回应(用于判断是否需要等待) -- `max_wait_seconds`:设定等待时间(秒),0 表示不等待,超时后你会考虑是否要主动说点什么 +- `max_wait_seconds`:预估的等待时间(秒),这很关键,请根据对话节奏来判断: + - 如果你刚问了一个开放性问题(比如"你觉得呢?"、"后来怎么样了?"),或者对话明显还在兴头上,设置一个等待时间(比如 60-180 秒),给对方思考和打字的时间。 + - 如果对话感觉自然结束了(比如晚安、拜拜),或者你给出了一个总结性的陈述,那就设置为 0,表示你觉得可以告一段落了。 + - 不要总是设为 0,那会显得你很急着结束对话。 ### 注意事项 - 动作参数直接写在动作对象里,不需要 `action_data` 包装 @@ -378,7 +394,7 @@ kfc_UNIFIED_OUTPUT_FORMAT = Prompt( {{"type": "kfc_reply", "content": "你的回复内容"}} ], "expected_reaction": "你期待对方的反应是什么", - "max_wait_seconds": 等待时间(秒),0 表示不等待 + "max_wait_seconds": "预估的等待时间(秒)" }} ``` @@ -386,7 +402,10 @@ kfc_UNIFIED_OUTPUT_FORMAT = Prompt( - `thought`:你的内心独白,记录你此刻的想法和感受。要自然,不要技术性语言。 - `actions`:你要执行的动作列表。对于 `kfc_reply` 动作,**必须**填写 `content` 字段,写上你要说的话。 - `expected_reaction`:你期待对方如何回应(用于判断是否需要等待) -- `max_wait_seconds`:设定等待时间(秒),0 表示不等待,超时后你会考虑是否要主动说点什么。如果你认为聊天没有继续的必要,或不想打扰对方,可以设为 0。 +- `max_wait_seconds`:预估的等待时间(秒),这很关键,请根据对话节奏来判断: + - 如果你刚问了一个开放性问题(比如"你觉得呢?"、"后来怎么样了?"),或者对话明显还在兴头上,设置一个等待时间(比如 60-180 秒),给对方思考和打字的时间。 + - 如果对话感觉自然结束了(比如晚安、拜拜),或者你给出了一个总结性的陈述,那就设置为 0,表示你觉得可以告一段落了。 + - 不要总是设为 0,那会显得你很急着结束对话。 ### 注意事项 - kfc_reply 的 content 字段是**必填**的,直接写你要发送的消息内容 diff --git a/src/plugins/built_in/kokoro_flow_chatter/prompt_modules_unified.py b/src/plugins/built_in/kokoro_flow_chatter/prompt_modules_unified.py index e5f80982b..64f2b5377 100644 --- a/src/plugins/built_in/kokoro_flow_chatter/prompt_modules_unified.py +++ b/src/plugins/built_in/kokoro_flow_chatter/prompt_modules_unified.py @@ -266,13 +266,18 @@ def build_output_module(context_data: Optional[dict[str, str]] = None) -> str: { "thought": "你心里的真实想法,像日记一样自然", "expected_user_reaction": "猜猜对方看到会怎么想", - "max_wait_seconds": 等多久(60-900),不等就填0, + "max_wait_seconds": "预估的等待时间(秒)", "actions": [ {"type": "kfc_reply", "content": "你要说的话"} ] } ``` +关于 max_wait_seconds(等待时间): +- 如果你刚问了一个开放性问题(比如"你觉得呢?"、"后来怎么样了?"),或者对话明显还在兴头上,设置一个等待时间(比如 60-180 秒),给对方思考和打字的时间。 +- 如果对话感觉自然结束了(比如晚安、拜拜),或者你给出了一个总结性的陈述,那就设置为 0,表示你觉得可以告一段落了。 +- 不要总是设为 0,那会显得你很急着结束对话。 + 关于 thought(内心想法): - 写你真正在想的,不是在分析任务 - 像心里嘀咕一样,比如"这家伙又来撒娇了~" "有点困了但还想再聊会儿" @@ -375,20 +380,31 @@ TIMEOUT_DECISION_USER_PROMPT_TEMPLATE = """## 聊天记录 ## 现在的情况 你发了消息,等了 {wait_duration_seconds:.0f} 秒({wait_duration_minutes:.1f} 分钟),对方还没回。 你之前觉得对方可能会:{expected_user_reaction} - {followup_warning} - -你发的最后一条:{last_bot_message} +你发的最后一条消息是:「{last_bot_message}」 --- 你拿起手机看了一眼,发现对方还没回复。你想怎么办? -选项: -1. **继续等** - 用 `do_nothing`,设个 `max_wait_seconds` 等一会儿再看 -2. **发消息** - 用 `reply`,不过别太频繁追问 -3. **算了不等了** - 用 `do_nothing`,`max_wait_seconds` 设为 0 +**决策指导:** +- **评估话题**:你上一条消息是结束性的,还是开启性的?是陈述句,还是疑问句? +- **考虑关系**:你们的关系有多亲近?频繁追问是否会打扰到对方? +- **保持自然**:像真人一样思考,对方可能只是暂时在忙。 -用 JSON 输出你的想法和决策。""" +**决策选项:** +1. **再等等看**:如果觉得话题还没结束,或者对方可能只是需要多点时间,可以选择再等一会。 + - **动作**:使用 `do_nothing`,并设置一个新的、合理的 `max_wait_seconds`(比如 60-300 秒)。 + +2. **开启新话题**:如果感觉之前的话题已经告一段落,或者想轻松地打破沉默,可以主动开启一个轻松的新话题。 + - **动作**:使用 `kfc_reply` 发送一条新的、不相关的问候或分享。 + +3. **轻轻追问**:如果你们正在讨论一件很重要的事,或者你发的上一条是关键问题,可以委婉地追问一下。 + - **动作**:使用 `kfc_reply` 发送一条温柔的提醒,例如"在忙吗?"或者"刚才说到哪啦?"。 + +4. **结束等待**:如果你觉得对话确实已经结束,或者不想再打扰对方,就自然地结束等待。 + - **动作**:使用 `do_nothing`,并将 `max_wait_seconds` 设为 0。 + +用 JSON 输出你的想法和最终决策。""" PROACTIVE_THINKING_USER_PROMPT_TEMPLATE = """## 聊天记录 diff --git a/src/plugins/built_in/kokoro_flow_chatter/unified.py b/src/plugins/built_in/kokoro_flow_chatter/unified.py index bfe0bd1fc..e6b7a46b3 100644 --- a/src/plugins/built_in/kokoro_flow_chatter/unified.py +++ b/src/plugins/built_in/kokoro_flow_chatter/unified.py @@ -561,7 +561,7 @@ def _log_pretty_response(response: LLMResponse, stream_id: str | None = None) -> for i, reply in enumerate(replies): if len(replies) > 1: - logger.info(f"[KFC] 💬[{i+1}] {reply}") + logger.info(f"[KFC] 💬 [{i+1}] {reply}") else: logger.info(f"[KFC] 💬 {reply}") @@ -569,7 +569,7 @@ def _log_pretty_response(response: LLMResponse, stream_id: str | None = None) -> logger.info(f"[KFC] 🎯 {', '.join(actions)}") if response.max_wait_seconds > 0 or response.expected_reaction: - meta = f"⏱{response.max_wait_seconds}s" if response.max_wait_seconds > 0 else "" + meta = f"⏱ {response.max_wait_seconds}s" if response.max_wait_seconds > 0 else "" if response.expected_reaction: meta += f" 预期: {response.expected_reaction}" logger.info(f"[KFC] {meta.strip()}") \ No newline at end of file diff --git a/src/plugins/built_in/napcat_adapter/src/handlers/to_napcat/send_handler.py b/src/plugins/built_in/napcat_adapter/src/handlers/to_napcat/send_handler.py index f2a985974..e2ffc068d 100644 --- a/src/plugins/built_in/napcat_adapter/src/handlers/to_napcat/send_handler.py +++ b/src/plugins/built_in/napcat_adapter/src/handlers/to_napcat/send_handler.py @@ -90,6 +90,11 @@ class SendHandler: logger.critical("现在暂时不支持解析此回复!") return None + # 🔧 确保 reply 消息段始终在列表最前面 + # 排序原则:reply 类型优先级最高(排序值为 0),其他类型保持原有顺序(排序值为 1) + # 使用 stable sort 确保非 reply 元素的相对顺序不变 + processed_message.sort(key=lambda seg: 0 if isinstance(seg, dict) and seg.get("type") == "reply" else 1) + if group_info and group_info.get("group_id"): logger.debug("发送群聊消息") target_id = int(group_info["group_id"])