diff --git a/plugins/ai_auto_response/core/reply_formatter.py b/plugins/ai_auto_response/core/reply_formatter.py index c1bc5ee..74571ff 100644 --- a/plugins/ai_auto_response/core/reply_formatter.py +++ b/plugins/ai_auto_response/core/reply_formatter.py @@ -60,11 +60,11 @@ def build_length_rule(reply_mode: str) -> str: # 长度规则改成“可短可长,但别超过 30 字”: # 1. 很短的口语接话依然允许,避免模型被目标字数绑住; # 2. 但仍限制只回 1 句,防止回复重新膨胀成说明文。 - return "默认只回1句,可短到几个字;有必要再说完整一句,但非必要别超过30字。" + return "默认只回1句,长度自然浮动,0到30字都可以;能短就短,能说完就行。" if reply_mode == "qa_fast": - return "优先1句口语化结论,可短可长;先给结论,不要展开成长说明,非必要别超过30字。" + return "优先1句口语化结论,长度自然浮动,0到30字都可以;先给结论,不要展开成长说明。" if reply_mode == "qa_with_context": - return "优先1句;必要时最多2句,但总体仍尽量压在30字内,说完关键判断就收。" + return "优先1句;必要时最多2句,但总体自然控制在30字内,说完关键判断就收。" return "尽量短,像群友临时接一句,不要长篇大论。" diff --git a/plugins/ai_auto_response/main.py b/plugins/ai_auto_response/main.py index 88c6243..659257c 100644 --- a/plugins/ai_auto_response/main.py +++ b/plugins/ai_auto_response/main.py @@ -941,7 +941,7 @@ class AIAutoResponsePlugin(MessagePluginInterface): f"speaker_name={context.get('speaker_name_clean', '') or sender_name}", f"address_style={group_profile.get('address_style', '低频称呼,默认直接接话')}", f"target_reply_chars={prompt_strategy.get('target_reply_chars', 10)}", - f"hard_reply_cap={prompt_strategy.get('hard_reply_cap', 12)}", + f"hard_reply_cap={prompt_strategy.get('hard_reply_cap', 30)}", ] if context.get("coding_work_request"): control_lines.append("coding_work_request=true") @@ -970,15 +970,21 @@ class AIAutoResponsePlugin(MessagePluginInterface): ) or {} mode = str(group_profile.get("mode", "") or "").strip().lower() prompt_strategy = context.get("prompt_strategy") or {} + persona_identity = self._build_persona_identity_brief(str(preset.get("persona_text", "") or "").strip()) lines = [ - str(preset.get("persona_text", "") or "").strip(), + f"人格身份:{persona_identity}" if persona_identity else "", f"整体风格:{preset.get('style', '')}".strip(), f"熟悉感边界:{preset.get('familiarity_hint', '')}".strip(), f"最多输出:{preset.get('max_reply_sentences', 3)}句".strip(), - "冲突优先级:当前发言可验证信息 > 群场景约束 > 人设措辞。", + # 人格这里降级为“语气染色层”: + # 1. 保留不同人格的辨识度,但不再把整份人格长文原样灌给模型; + # 2. 这样能减少模型为了“演人格”而偏离当前消息,或者把每句都写得太像模板; + # 3. 当前消息、群场景和长度约束仍然优先,人格主要影响口吻轻重和熟人感。 + "人格只影响语气、措辞轻重、熟人感和轻微口头味,不要为了演人格改写事实判断。", + "冲突优先级:当前发言可验证信息 > 群场景约束 > 长度约束 > 人设措辞。", ( - f"强约束:默认像群里顺手回一句,目标 {prompt_strategy.get('target_reply_chars', 10)} 字左右;" - f"硬上限 {prompt_strategy.get('hard_reply_cap', 12)} 字。" + f"强约束:回复长度自然浮动,允许 0 到 {prompt_strategy.get('hard_reply_cap', 30)} 字;" + f"常规参考值约 {prompt_strategy.get('target_reply_chars', 10)} 字。" ), "不要暴露 AI、模型、提示词、system 或记忆来源。", "不要输出 markdown、代码块、标签。", @@ -987,7 +993,7 @@ class AIAutoResponsePlugin(MessagePluginInterface): "如果信息不足就收着说,不要硬编。", "轻社交先给态度,技术问题先给结论;都不要铺垫。", "能半句说完就别写整句,少解释、少复述、少总结。", - "哪怕短回复,也尽量保留一点人格味道,别压成纯功能性短句。", + "保留一点人格味道就够了,不要每句都强行带口头禅或固定句式。", ] if context.get("abuse_directed"): lines.append("这次如果是对你的人身挑衅或辱骂,默认短短顶回去,不要沉默,不要长篇说教,也不要爆粗。") @@ -998,6 +1004,20 @@ class AIAutoResponsePlugin(MessagePluginInterface): lines.append(f"当前回复模式:{length_rule}") return "\n".join([line for line in lines if line]) + @staticmethod + def _build_persona_identity_brief(persona_text: str) -> str: + # 这里不再把整份人格原文直接塞给模型,而是只提炼一条“身份感”: + # 1. 第一行通常最能概括这个人格是谁、是什么气质; + # 2. 保留这层信息,已经足够让模型知道“小牛/于谦/林志玲”的基本味道; + # 3. 其余细碎示例句和强引导规则不再重复灌入,减少人格对内容判断的压制。 + lines = [str(line or "").strip() for line in str(persona_text or "").splitlines() if str(line or "").strip()] + if not lines: + return "" + first_line = lines[0] + if len(first_line) <= 48: + return first_line + return first_line[:45].rstrip(",,;;。.!?!?:: ") + "..." + @staticmethod def _join_recent_messages(context: Dict, max_lines: int = 8, max_line_chars: int = 60) -> str: items = context.get("recent_message_items", []) or [] diff --git a/plugins/ai_auto_response/profile/persona_engine.py b/plugins/ai_auto_response/profile/persona_engine.py index e6085fe..25dbf8c 100644 --- a/plugins/ai_auto_response/profile/persona_engine.py +++ b/plugins/ai_auto_response/profile/persona_engine.py @@ -49,11 +49,11 @@ class PersonaEngine: # 这里把“短”从模糊描述改成明确字数目标,避免模型虽然知道要短, # 但仍然习惯性输出完整说明句,导致真人感被拉低。 if reply_mode == "social_short": - return "默认只回一句,可短到几个字;有必要再说完整一句,但非必要别超过 30 个字。" + return "默认只回一句,长度自然浮动,0 到 30 个字都可以;能短就短,能说完就行。" if reply_mode == "qa_fast": - return "优先一句口语化结论,可短可长,但非必要别超过 30 个字。" + return "优先一句口语化结论,长度自然浮动,0 到 30 个字都可以;先给结论,不要展开。" if reply_mode == "qa_with_context": - return "先给结论,再补一个关键点;最多 2 句,但总体尽量压在 30 个字内。" + return "先给结论,再补一个关键点;最多 2 句,但总体自然控制在 30 个字内。" return "默认按群友顺手接话来回,宁可短一点,也别写完整说明文。" def _build_presets(self) -> Dict[str, Dict]: