增加常驻群长期记忆与成员轻画像输入

This commit is contained in:
liuwei
2026-04-24 15:44:03 +08:00
parent d0480691c3
commit 0ea7b61951
3 changed files with 79 additions and 6 deletions

View File

@@ -72,8 +72,14 @@ default_char_limit = 30
default_total_limit = 30
[prompt_compact]
group_profile_max_chars = 220
group_profile_max_lines = 6
# 这里改成“常驻轻背景 + 相关增强”后,群长期摘要和成员轻画像都会稳定带给模型:
# 1. group_profile 放宽,让群长期摘要不会总被前面的模式/知识域说明挤掉;
# 2. member_profile_brief_* 新增为常驻轻画像额度,每次都给当前发言人一小段稳定画像;
# 3. 更重的成员记忆、群事实、向量记忆仍然保留独立额度,并继续走按需增强。
group_profile_max_chars = 420
group_profile_max_lines = 10
member_profile_brief_max_chars = 260
member_profile_brief_max_lines = 6
# 最近上下文现在要真实交给模型 30 条,因此这里同步放宽整体上下文裁剪阈值:
# 1. recent_message_max_lines 提到 30避免“窗口明明有 30提示词里只留下 4 条”;
# 2. context_max_lines/context_max_chars 一起抬高,避免最近消息刚拼进去又被整体截断;
@@ -86,8 +92,8 @@ at_member_profile_max_chars = 160
at_member_profile_max_lines = 5
member_memory_max_chars = 180
member_memory_max_lines = 6
memory_max_chars = 240
memory_max_lines = 8
memory_max_chars = 520
memory_max_lines = 14
strict_memory_relevance = true
[image]

View File

@@ -59,6 +59,7 @@ class ContextBuilder:
"trigger_type": trigger.get("trigger_type", "none"),
"reply_mode": reply_mode,
"flow_state": flow_state,
"member_profile_brief_prompt": self._build_member_profile_brief_prompt(member_context or {}),
"memory_prompt": self._build_member_memory_prompt(member_context, member_memory_focus or []),
"at_member_profile_prompt": self._build_at_member_profile_prompt(
member_context=member_context or {},
@@ -69,6 +70,7 @@ class ContextBuilder:
"vector_memory_prompt": self._build_vector_memory_prompt(vector_memories),
"social_memory_prompt": self._build_social_memory_prompt(social_memory or {}),
"group_facts_prompt": self._build_group_facts_prompt(group_facts or {}),
"group_long_memory_prompt": self._build_group_long_memory_prompt(group_profile or {}),
"group_profile_prompt": self._build_group_profile_prompt(group_profile or {}),
"quote_prompt": self._build_quote_prompt(quote_context or {}),
"image_prompt": self._build_image_prompt(image_context or {}),
@@ -207,6 +209,35 @@ class ContextBuilder:
text = re.sub(r"[^\u4e00-\u9fffA-Za-z0-9_]", "", text)
return text[:8]
@staticmethod
def _build_member_profile_brief_prompt(member_context: Dict) -> str:
# 这份摘要是“常驻给模型看的轻画像”:
# 1. 不要求当前一定是 @ 或强定向,因为用户希望每次回答都能带上对这个人的基本认识;
# 2. 这里只保留少量稳定信息,避免画像太重把当前问题压住;
# 3. 更细的成员记忆、近期相关记忆,仍走后面的按需增强链路。
if not member_context:
return ""
meta = member_context.get("meta", {}) or {}
summary = str(member_context.get("summary_text", "") or "").strip()
interaction_style = str(member_context.get("interaction_style", "") or "").strip()
response_hint = str(member_context.get("response_style_hint", "") or "").strip()
topics = ContextBuilder._stringify_items(member_context.get("topics_of_interest", []) or [], 3)
recent_focus = ContextBuilder._stringify_items(member_context.get("recent_focus", []) or [], 2)
skills = ContextBuilder._stringify_items(meta.get("skill_profile", []) or [], 2)
reply_prefs = ContextBuilder._stringify_items(meta.get("long_term_reply_preferences", []) or [], 2)
lines = [
"当前发言人轻画像:",
f"成员摘要:{summary}" if summary else "",
f"互动风格:{interaction_style}" if interaction_style else "",
f"偏好回复方式:{response_hint}" if response_hint else "",
f"长期兴趣:{topics}" if topics else "",
f"近期关注:{recent_focus}" if recent_focus else "",
f"技能侧重点:{skills}" if skills else "",
f"回复偏好:{reply_prefs}" if reply_prefs else "",
"这些信息只用于帮助理解提问方式和回答切口,不要像在背档案。",
]
return "\n".join([line for line in lines if line])
@staticmethod
def _build_member_memory_prompt(member_context: Dict, focus_lines: List[str] | None = None) -> str:
if not member_context:
@@ -320,6 +351,25 @@ class ContextBuilder:
def _build_group_facts_prompt(group_facts: Dict) -> str:
return str((group_facts or {}).get("prompt", "") or "").strip()
@staticmethod
def _build_group_long_memory_prompt(group_profile: Dict) -> str:
# 这份摘要是“群长期背景常驻层”:
# 1. 每次都给一小段,帮助模型知道这个群长期在聊什么、什么风格更合适;
# 2. 不把完整群画像整段塞进去,避免大量通用风格描述把 token 吃满;
# 3. 更细的群事实、群关系仍走相关性增强链路。
if not group_profile:
return ""
summary = ContextBuilder._compact_group_summary(str(group_profile.get("group_memory_summary", "") or ""), max_chars=220, max_sentences=4)
focus = ", ".join(group_profile.get("knowledge_focus", [])[:4])
memory_style = ContextBuilder._build_style_summary(group_profile.get("group_memory_style", {}))
lines = [
"群长期背景:",
f"长期摘要:{summary}" if summary else "",
f"常聊方向:{focus}" if focus else "",
f"历史社交风格:{memory_style}" if memory_style else "",
]
return "\n".join([line for line in lines if line])
@staticmethod
def _build_group_profile_prompt(group_profile: Dict) -> str:
if not group_profile:

View File

@@ -911,8 +911,12 @@ class AIAutoResponsePlugin(MessagePluginInterface):
memory_hints=memory_hints,
)
persona = self._compose_dify_persona_text(group_profile, context)
group_profile_parts = [
self._string_block("群长期记忆(常驻)", context.get("group_long_memory_prompt", "")),
self._string_block("群当前画像", context.get("group_profile_prompt", "")),
]
group_profile_text = self._compact_text(
str(context.get("group_profile_prompt", "") or "").strip() or "当前群没有特殊画像。",
"\n\n".join([part for part in group_profile_parts if part]).strip() or "当前群没有特殊画像。",
max_chars=int(self.prompt_compact_config.get("group_profile_max_chars", 220) or 220),
max_lines=int(self.prompt_compact_config.get("group_profile_max_lines", 6) or 6),
)
@@ -945,6 +949,14 @@ class AIAutoResponsePlugin(MessagePluginInterface):
max_lines=int(self.prompt_compact_config.get("context_max_lines", 10) or 10),
)
# 成员画像拆成两层:
# 1. 常驻轻画像:每次都带,帮助模型理解这个人的提问方式、风格和切口;
# 2. 定向增强画像:只有明确 @ / 强定向 / followup 时再额外补,避免平时过度套人设。
member_profile_brief_text = self._compact_text(
str(context.get("member_profile_brief_prompt", "") or ""),
max_chars=int(self.prompt_compact_config.get("member_profile_brief_max_chars", 260) or 260),
max_lines=int(self.prompt_compact_config.get("member_profile_brief_max_lines", 6) or 6),
)
at_member_profile_text = ""
if bool(prompt_strategy.get("allow_member_memory")):
at_member_profile_text = self._compact_text(
@@ -962,6 +974,7 @@ class AIAutoResponsePlugin(MessagePluginInterface):
member_memory_text = self._remove_overlap_lines(member_memory_text, at_member_profile_text)
memory_parts = [
self._string_block("当前发言人画像(常驻)", member_profile_brief_text),
self._string_block("本次@发起者画像(优先)", at_member_profile_text),
self._string_block("成员记忆", member_memory_text),
self._string_block(
@@ -1214,7 +1227,11 @@ class AIAutoResponsePlugin(MessagePluginInterface):
}
allow_member_memory = strong_directed or is_followup or returning_state in {"returning_member", "long_absent_member"}
allow_social_memory = is_question_like and strong_directed
# 群关系记忆继续按需开放,但问答模式下不再必须“强定向”才允许:
# 1. 用户希望回答能带上群里的长期背景和互动关系;
# 2. 关系记忆仍会经过相关性过滤,所以放宽入口不会直接把无关关系灌进去;
# 3. 这样技术问答里也更容易利用“谁经常和谁接话、谁常问哪类问题”的弱背景。
allow_social_memory = is_question_like
allow_group_facts = reply_mode == "qa_with_context"
allow_vector_memory = reply_mode == "qa_with_context" or returning_state == "long_absent_member"