feat(chat): 为回复分割器添加 llm 与 punctuation 模式
本次更新重构了回复分割功能,引入了 `split_mode` 配置项,允许用户在两种分割模式之间进行选择,提供了更大的灵活性。 - **`llm` 模式**: 延续了由大语言模型通过 `[SPLIT]` 标记决定断句的功能。此模式下的提示词(Prompt)已进一步优化,以引导模型做出更自然的分割。 - **`punctuation` 模式**: 恢复了传统的基于标点符号的分割逻辑。这已设为新的默认模式,确保用户更新后行为与旧版本保持一致。 此外,`at_user` 插件也进行了适配,以正确处理由 `llm` 模式可能产生的多段消息。
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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="启用颜文字保护")
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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 # 是否启用颜文字保护
|
||||
|
||||
Reference in New Issue
Block a user