接入成员画像 Dify 工作流并清理旧提取逻辑

- 新增 member_context 专用 DifyClient,统一兼容 completion 与 workflow 两种调用模式
- 将成员画像插件默认切换到 Dify workflow 模式,配置改用新的 workflow 应用与 workflows/run 接口
- 生成可直接导入 Dify 的成员画像工作流 DSL 文件,方便后台一键导入和发布
- 补充 Dify 工作流接入说明文档,明确输入字段、输出字段、发布步骤与插件消费方式
- 清理旧的单成员日摘要提取链路,日级画像统一收敛到群日批量提取路径,减少无效分支和历史残留
- 去除 member_context 内部多处旧 requests 直连调用,统一改为通过 DifyClient 调用 AI 服务
- 优化群日批量结果解析逻辑,只按 wxid 作为唯一主键识别成员,不再依赖昵称做唯一判断
- 新增按 wxid 的结果去重与完整度评分逻辑,遇到重复成员结果时优先保留字段更完整、置信度更高的一条
- 保留现有初始化、增量、周/月聚合与最终画像生成链路,同时剔除 workflow 接入后已无效或低价值的旧逻辑
- 为后续继续收紧 fallback 标记、增强后台质量诊断和优化工作流输出稳定性打下基础
This commit is contained in:
liuwei
2026-04-02 14:25:50 +08:00
parent 75dc3b289d
commit bfd0dbc15c
7 changed files with 673 additions and 185 deletions

View File

@@ -58,57 +58,6 @@ class MemberContextPromptBuilder:
"压缩后的群聊记录:\n" + compressed_chat
)
@staticmethod
def build_daily_digest_prompt(chatroom_id: str, wxid: str, display_name: str,
digest_date: str, messages: List[Dict]) -> str:
lines = []
for msg in messages[-80:]:
ts = str(msg.get("timestamp", ""))[11:16]
content = (msg.get("content") or "").replace("\n", " ").strip()[:180]
if content:
lines.append(f"[{ts}] {content}")
return (
"你是微信群后台的成员日观察摘要生成器。\n"
"请仅基于给定的当日公开聊天记录,提取对后续互动有帮助的中性行为观察。\n"
"不要做人格诊断、隐私猜测、负面评价,不要脑补群外信息。\n"
"这些日观察会被后续系统按周、按月持续累积,所以应优先输出长期可验证的行为线索,而不是一次性情绪。\n"
"输出严格 JSON不要 markdown。\n"
"{"
"\"topics\":[\"主题1\"],"
"\"identity_clues\":[\"身份线索1\"],"
"\"skill_signals\":[\"技能信号1\"],"
"\"family_signals\":[\"家庭线索1\"],"
"\"life_stage_signals\":[\"阶段线索1\"],"
"\"value_preferences\":[\"价值偏好1\"],"
"\"interaction_style\":\"一句中文\","
"\"message_pattern\":\"一句中文\","
"\"response_style_hint\":\"一句中文\","
"\"habit_signals\":[\"信号1\"],"
"\"engagement_traits\":[\"特征1\"],"
"\"decision_style\":\"一句中文\","
"\"social_role\":\"一句中文\","
"\"reply_taboos\":[\"避坑1\"],"
"\"temperament_signal\":\"一句中文,描述当天显露的沟通倾向,必须克制\","
"\"summary_text\":\"一段不超过100字的日摘要\","
"\"representative_messages\":[\"原话1\",\"原话2\"],"
"\"confidence\":0.0"
"}\n"
"要求:\n"
"1. topics、identity_clues、skill_signals、family_signals、life_stage_signals、value_preferences、habit_signals、engagement_traits 最多4个reply_taboos 最多3个。\n"
"2. temperament_signal 只能写当日可观察到的沟通倾向,不可上升为长期性格判断。\n"
"3. representative_messages 保留最能代表当天风格的短句最多3条。\n"
"4. identity_clues、family_signals、life_stage_signals 只能写线索,不可写成确定事实。\n"
"5. skill_signals 重点描述专业能力、工具熟练度、信息组织能力、问题解决能力等当天显露出的信号。\n"
"6. topics 尽量写持续关注方向避免写一次性插话habit_signals 只写当天已明显出现的表达或互动习惯。\n"
"7. value_preferences 只保留公开表达出的判断偏好,如效率优先、先验证再决策、重成本、重稳定。\n"
"8. summary_text 要像后台备注,不要像对话回复。\n"
f"成员: {display_name} ({wxid})\n"
f"群ID: {chatroom_id}\n"
f"日期: {digest_date}\n"
"当日消息:\n" + ("\n".join(lines) or "暂无")
)
@staticmethod
def build_period_digest_prompt(digest_type: str, chatroom_id: str, wxid: str,
display_name: str, period_key: str, items: List[Dict]) -> str: