From 0cb2fa3373f9ece0f517d4c7a2dada2c37bad60d Mon Sep 17 00:00:00 2001 From: tt-P607 <68868379+tt-P607@users.noreply.github.com> Date: Thu, 11 Sep 2025 17:12:01 +0800 Subject: [PATCH] =?UTF-8?q?feat(chat):=20=E4=B8=BA=E5=9B=9E=E5=A4=8D?= =?UTF-8?q?=E5=88=86=E5=89=B2=E5=99=A8=E6=B7=BB=E5=8A=A0=20`llm`=20?= =?UTF-8?q?=E4=B8=8E=20`punctuation`=20=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 本次更新重构了回复分割功能,引入了 `split_mode` 配置项,允许用户在两种分割模式之间进行选择,提供了更大的灵活性。 - **`llm` 模式**: 延续了由大语言模型通过 `[SPLIT]` 标记决定断句的功能。此模式下的提示词(Prompt)已进一步优化,以引导模型做出更自然的分割。 - **`punctuation` 模式**: 恢复了传统的基于标点符号的分割逻辑。这已设为新的默认模式,确保用户更新后行为与旧版本保持一致。 此外,`at_user` 插件也进行了适配,以正确处理由 `llm` 模式可能产生的多段消息。 --- src/chat/replyer/default_generator.py | 18 +++++++++++------- src/chat/utils/utils.py | 18 ++++++++++++------ src/config/official_configs.py | 1 + src/plugins/built_in/at_user_plugin/plugin.py | 15 ++++++++++----- template/bot_config_template.toml | 3 ++- 5 files changed, 36 insertions(+), 19 deletions(-) diff --git a/src/chat/replyer/default_generator.py b/src/chat/replyer/default_generator.py index 3ad209aa4..0217f18e6 100644 --- a/src/chat/replyer/default_generator.py +++ b/src/chat/replyer/default_generator.py @@ -1025,14 +1025,18 @@ class DefaultReplyer: prompt_text = await prompt.build() # --- 动态添加分割指令 --- - if global_config.response_splitter.enable: + if global_config.response_splitter.enable and global_config.response_splitter.split_mode == "llm": split_instruction = """ -## 分割指令 -你正在通过一个即时聊天软件发送消息。请模仿一个真实人类的打字和发送习惯: -- **简洁明了**: 如果一句话能说清楚,就一次性发出去,不要添加任何标记。 -- **自然断句**: 当你想表达一个转折、一个停顿,或者想补充说明时,就像正常人会先发一部分再发另一部分一样,请在断句处插入 `[SPLIT]` 标记。 -- **动机**: 使用 `[SPLIT]` 的目的是为了让对话节奏更自然,更有层次感,而不是为了分割而分割。 -示例: "我刚刚看到一个超好笑的视频![SPLIT]等我找找发给你~" +## 消息分段艺术 +为了模仿真实人类的聊天节奏,你可以在需要时将一条回复分成几段发送。 + +**核心原则**: 只有当分段能**增强表达效果**或**控制信息节奏**时,才在断句处使用 `[SPLIT]` 标记。 + +**参考场景**: +- 当你想表达一个转折或停顿时。 +- 当你想先说结论,再补充说明时。 + +**任务**: 请结合你的智慧和人设,自然地决定是否需要分段。如果需要,请在最恰当的位置插入 `[SPLIT]` 标记。 """ # 在 "现在,你说:" 之前插入 parts = prompt_text.rsplit("现在,你说:", 1) diff --git a/src/chat/utils/utils.py b/src/chat/utils/utils.py index 19f3ced99..675bf4b85 100644 --- a/src/chat/utils/utils.py +++ b/src/chat/utils/utils.py @@ -331,15 +331,21 @@ def process_llm_response(text: str, enable_splitter: bool = True, enable_chinese ) if global_config.response_splitter.enable and enable_splitter: - logger.info("回复分割器已启用。") - if "[SPLIT]" in cleaned_text: + logger.info(f"回复分割器已启用,模式: {global_config.response_splitter.split_mode}。") + + split_mode = global_config.response_splitter.split_mode + + if split_mode == "llm" and "[SPLIT]" in cleaned_text: + logger.debug("检测到 [SPLIT] 标记,使用 LLM 自定义分割。") split_sentences_raw = cleaned_text.split("[SPLIT]") - # 清理每个句子首尾可能由LLM添加的空格或换行符,并移除空句子 split_sentences = [s.strip() for s in split_sentences_raw if s.strip()] - logger.debug(f"LLM 自定义分割结果: {split_sentences}") else: - # 如果没有 [SPLIT] 标记,则不进行任何分割 - split_sentences = [cleaned_text] + if split_mode == "llm": + logger.debug("未检测到 [SPLIT] 标记,本次不进行分割。") + split_sentences = [cleaned_text] + else: # mode == "punctuation" + logger.debug("使用基于标点的传统模式进行分割。") + split_sentences = split_into_sentences_w_remove_punctuation(cleaned_text) else: logger.debug("回复分割器已禁用。") split_sentences = [cleaned_text] diff --git a/src/config/official_configs.py b/src/config/official_configs.py index b97b5443f..1de98b6cc 100644 --- a/src/config/official_configs.py +++ b/src/config/official_configs.py @@ -475,6 +475,7 @@ class ResponseSplitterConfig(ValidatedConfigBase): """回复分割器配置类""" enable: bool = Field(default=True, description="启用") + split_mode: str = Field(default="llm", description="分割模式: 'llm' 或 'punctuation'") max_length: int = Field(default=256, description="最大长度") max_sentence_num: int = Field(default=3, description="最大句子数") enable_kaomoji_protection: bool = Field(default=False, description="启用颜文字保护") diff --git a/src/plugins/built_in/at_user_plugin/plugin.py b/src/plugins/built_in/at_user_plugin/plugin.py index 6d67b994c..1cac44fcc 100644 --- a/src/plugins/built_in/at_user_plugin/plugin.py +++ b/src/plugins/built_in/at_user_plugin/plugin.py @@ -28,9 +28,9 @@ class AtAction(BaseAction): # === 功能描述(必须填写)=== action_parameters = {"user_name": "需要艾特用户的名字", "at_message": "艾特用户时要发送的消息"} action_require = [ - "当需要艾特某个用户时使用", - "当你需要提醒特定用户查看消息时使用", - "在回复中需要明确指向某个用户时使用", + "当用户明确要求你去'叫'、'喊'、'提醒'或'艾特'某人时使用", + "当你判断,为了让特定的人看到消息,需要代表用户去呼叫他/她时使用", + "例如:'你去叫一下张三','提醒一下李四开会'", ] llm_judge_prompt = """ 判定是否需要使用艾特用户动作的条件: @@ -150,11 +150,16 @@ class AtAction(BaseAction): logger.error("回复器生成回复失败") return False, "回复生成失败" - final_message = llm_response.get("content", "") - if not final_message: + final_message_raw = llm_response.get("content", "") + if not final_message_raw: logger.warning("回复器生成了空内容") return False, "回复内容为空" + # 对LLM生成的内容进行后处理,解析[SPLIT]标记并将分段消息合并 + from src.chat.utils.utils import process_llm_response + final_message_segments = process_llm_response(final_message_raw, enable_splitter=True, enable_chinese_typo=False) + final_message = " ".join(final_message_segments) + await self.send_command( "SEND_AT_MESSAGE", args={"group_id": self.chat_stream.group_info.group_id, "qq_id": user_id, "text": final_message}, diff --git a/template/bot_config_template.toml b/template/bot_config_template.toml index 3a7ed77de..a11ce6816 100644 --- a/template/bot_config_template.toml +++ b/template/bot_config_template.toml @@ -1,5 +1,5 @@ [inner] -version = "6.8.2" +version = "6.8.3" #----以下是给开发人员阅读的,如果你只是部署了MoFox-Bot,不需要阅读---- #如果你想要修改配置文件,请递增version的值 @@ -321,6 +321,7 @@ word_replace_rate=0.006 # 整词替换概率 [response_splitter] enable = true # 是否启用回复分割器 +split_mode = "punctuation" # 分割模式: "llm" - 由语言模型决定, "punctuation" - 基于标点符号 max_length = 512 # 回复允许的最大长度 max_sentence_num = 8 # 回复允许的最大句子数 enable_kaomoji_protection = false # 是否启用颜文字保护