feat: 增加AI智能拆分功能

pull/1472/head
watercatlxh 2025-12-31 20:27:34 +08:00
parent c5276ce629
commit 6fa7bc3615
No known key found for this signature in database
5 changed files with 109 additions and 1 deletions

View File

@ -945,7 +945,7 @@ class DefaultReplyer:
else:
reply_target_block = ""
dialogue_prompt = ""
if message_list_before_now_long:
latest_msgs = message_list_before_now_long[-int(global_config.chat.max_context_size) :]
dialogue_prompt = build_readable_messages(
@ -979,6 +979,30 @@ class DefaultReplyer:
# 兜底:即使 multiple_reply_style 配置异常也不影响正常回复
reply_style = global_config.personality.reply_style
if global_config.response_splitter.enable_ai_segmentation:
style: str = global_config.response_splitter.ai_segmentation_style
max_segments: int = global_config.response_splitter.max_sentence_num
style_guides: Dict[str, str] = {
"natural": "在话题转换、语气变化等重要停顿处切分。一个完整的意思放在一段里,不要过度切分。",
"conservative": "尽量少切分,只在明显话题转换处切分。多个句子可以放在同一段。",
"active": "切分更细致,在语气转换、情绪变化处也可切分,但仍要保持语义完整。"
}
segmentation_prompt: str = f"""
请将你的回复切分成多段模拟真人发消息节奏
{style_guides.get(style, style_guides["natural"])}
重要规则
- 不要在每个标点都切分只在重要的语义停顿处切分
- 相关的句子应该保持在同一段
- 最多切分成 {max_segments}
- 切分时可以删除切分点的逗号句号顿号
- 保留感叹号问号省略号波浪号等情绪标点
- 保持原文内容和语气不变
- 使用 "|||SPLIT|||" 作为分段标记例如"第一段内容|||SPLIT|||第二段内容"
"""
reply_style += segmentation_prompt
return await global_prompt_manager.format_prompt(
prompt_name,
expression_habits_block=expression_habits_block,
@ -1085,6 +1109,30 @@ class DefaultReplyer:
except Exception:
reply_style = global_config.personality.reply_style
if global_config.response_splitter.enable_ai_segmentation:
style: str = global_config.response_splitter.ai_segmentation_style
max_segments: int = global_config.response_splitter.max_sentence_num
style_guides: Dict[str, str] = {
"natural": "在话题转换、语气变化等重要停顿处切分。一个完整的意思放在一段里,不要过度切分。",
"conservative": "尽量少切分,只在明显话题转换处切分。多个句子可以放在同一段。",
"active": "切分更细致,在语气转换、情绪变化处也可切分,但仍要保持语义完整。"
}
segmentation_prompt: str = f"""
请将你的回复切分成多段模拟真人发消息节奏
{style_guides.get(style, style_guides["natural"])}
重要规则
- 不要在每个标点都切分只在重要的语义停顿处切分
- 相关的句子应该保持在同一段
- 最多切分成 {max_segments}
- 切分时可以删除切分点的逗号句号顿号
- 保留感叹号问号省略号波浪号等情绪标点
- 保持原文内容和语气不变
- 使用 "|||SPLIT|||" 作为分段标记例如"第一段内容|||SPLIT|||第二段内容"
"""
reply_style += segmentation_prompt
return await global_prompt_manager.format_prompt(
template_name,
expression_habits_block=expression_habits_block,

View File

@ -821,6 +821,30 @@ class PrivateReplyer:
# 兜底:即使 multiple_reply_style 配置异常也不影响正常回复
reply_style = global_config.personality.reply_style
if global_config.response_splitter.enable_ai_segmentation:
style: str = global_config.response_splitter.ai_segmentation_style
max_segments: int = global_config.response_splitter.max_sentence_num
style_guides: Dict[str, str] = {
"natural": "在话题转换、语气变化等重要停顿处切分。一个完整的意思放在一段里,不要过度切分。",
"conservative": "尽量少切分,只在明显话题转换处切分。多个句子可以放在同一段。",
"active": "切分更细致,在语气转换、情绪变化处也可切分,但仍要保持语义完整。"
}
segmentation_prompt: str = f"""
请将你的回复切分成多段模拟真人发消息节奏
{style_guides.get(style, style_guides["natural"])}
重要规则
- 不要在每个标点都切分只在重要的语义停顿处切分
- 相关的句子应该保持在同一段
- 最多切分成 {max_segments}
- 切分时可以删除切分点的逗号句号顿号
- 保留感叹号问号省略号波浪号等情绪标点
- 保持原文内容和语气不变
- 使用 "|||SPLIT|||" 作为分段标记例如"第一段内容|||SPLIT|||第二段内容"
"""
reply_style += segmentation_prompt
# 使用统一的 is_bot_self 函数判断是否是机器人自己(支持多平台,包括 WebUI
if is_bot_self(platform, user_id):
return await global_prompt_manager.format_prompt(
@ -954,6 +978,30 @@ class PrivateReplyer:
# 兜底:即使 multiple_reply_style 配置异常也不影响正常回复
reply_style = global_config.personality.reply_style
if global_config.response_splitter.enable_ai_segmentation:
style: str = global_config.response_splitter.ai_segmentation_style
max_segments: int = global_config.response_splitter.max_sentence_num
style_guides: Dict[str, str] = {
"natural": "在话题转换、语气变化等重要停顿处切分。一个完整的意思放在一段里,不要过度切分。",
"conservative": "尽量少切分,只在明显话题转换处切分。多个句子可以放在同一段。",
"active": "切分更细致,在语气转换、情绪变化处也可切分,但仍要保持语义完整。"
}
segmentation_prompt: str = f"""
请将你的回复切分成多段模拟真人发消息节奏
{style_guides.get(style, style_guides["natural"])}
重要规则
- 不要在每个标点都切分只在重要的语义停顿处切分
- 相关的句子应该保持在同一段
- 最多切分成 {max_segments}
- 切分时可以删除切分点的逗号句号顿号
- 保留感叹号问号省略号波浪号等情绪标点
- 保持原文内容和语气不变
- 使用 "|||SPLIT|||" 作为分段标记例如"第一段内容|||SPLIT|||第二段内容"
"""
reply_style += segmentation_prompt
return await global_prompt_manager.format_prompt(
template_name,
expression_habits_block=expression_habits_block,

View File

@ -447,6 +447,10 @@ def process_llm_response(text: str, enable_splitter: bool = True, enable_chinese
if not global_config.response_post_process.enable_response_post_process:
return [text]
# 检查分隔符
if "|||SPLIT|||" in text and global_config.response_splitter.enable_ai_segmentation:
return [s.strip() for s in text.split("|||SPLIT|||") if s.strip()]
# 先保护颜文字
if global_config.response_splitter.enable_kaomoji_protection:
protected_text, kaomoji_mapping = protect_kaomoji(text)

View File

@ -645,6 +645,12 @@ class ResponseSplitterConfig(ConfigBase):
enable_overflow_return_all: bool = False
"""是否在超出句子数量限制时合并后一次性返回"""
enable_ai_segmentation: bool = False
"""是否启用AI智能分段"""
ai_segmentation_style: str = "natural"
"""AI智能分段风格natural(自然), conservative(保守), active(活跃)"""
@dataclass
class TelemetryConfig(ConfigBase):

View File

@ -245,6 +245,8 @@ max_length = 512 # 回复允许的最大长度
max_sentence_num = 8 # 回复允许的最大句子数
enable_kaomoji_protection = false # 是否启用颜文字保护
enable_overflow_return_all = false # 是否在句子数量超出回复允许的最大句子数时一次性返回全部内容
enable_ai_segmentation = false # 是否启用AI智能分段
ai_segmentation_style = "natural" # AI智能分段风格natural(自然), conservative(保守), active(活跃)
[log]
date_style = "m-d H:i:s" # 日期格式