From d228d119f51724f236f0591f0d93251ee636ac2e Mon Sep 17 00:00:00 2001 From: root Date: Tue, 28 Apr 2026 20:09:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=20persona=5Fremove?= =?UTF-8?q?=20=E5=B7=A5=E5=85=B7=EF=BC=88=E5=88=A0=E9=99=A4=E5=8D=95?= =?UTF-8?q?=E6=9D=A1=E4=BA=BA=E8=AE=BE=E5=B1=9E=E6=80=A7=EF=BC=89=EF=BC=8C?= =?UTF-8?q?=E6=94=B9=E8=BF=9B=20persona=5Fclear=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E6=9F=A5=E8=AF=A2=E6=89=80=E6=9C=89=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/prompts/templates/system_prompt.md | 5 +- core/tool_executor.py | 99 +++++++++++++++++-------- core/tool_limiter.py | 2 +- core/tools/memory_tools.py | 24 +++++- 4 files changed, 93 insertions(+), 37 deletions(-) diff --git a/core/prompts/templates/system_prompt.md b/core/prompts/templates/system_prompt.md index 5a062e0..38f5dfb 100644 --- a/core/prompts/templates/system_prompt.md +++ b/core/prompts/templates/system_prompt.md @@ -97,8 +97,9 @@ subject, relation, object 每个字段必须是一个**短关键字**(1~5个 ### 人设工具 | 工具 | 时机 | 说明 | |------|------|------| -| `persona_update` | AI自身角色改变 | 更新AI的角色、性格、说话风格、能力。**注意**:这是设定你自己的属性,不是记录用户信息 | -| `persona_clear` | 需要重置人设 | 清除所有AI人设属性 | +| `persona_update` | AI自身角色改变 | 更新AI的角色、性格、说话风格、能力。`mode="replace"` 替换全部,`mode="merge"` 增量添加 | +| `persona_remove` | 只需删除某一条属性 | 删除单条人设属性(如只删除说话风格,保留扮演角色不变) | +| `persona_clear` | 需要完全重置 | 清除所有AI人设属性。**此操作不可逆,需要 confirm=true** | ### 任务工具(生命周期管理) | 工具 | 时机 | 说明 | diff --git a/core/tool_executor.py b/core/tool_executor.py index 8415132..695ddab 100644 --- a/core/tool_executor.py +++ b/core/tool_executor.py @@ -75,6 +75,11 @@ def execute_tool(graph: Any, tool_name: str, arguments: dict) -> str: result = execute_persona_update(graph, arguments) return json.dumps(result, ensure_ascii=False, default=str) + elif tool_name == "persona_remove": + recorder.record("delete", tool_name, arguments.get("attribute", "")) + result = execute_persona_remove(graph, arguments) + return json.dumps(result, ensure_ascii=False, default=str) + elif tool_name == "persona_clear": recorder.record("delete", tool_name, "所有人设") result = execute_persona_clear(graph, arguments) @@ -203,40 +208,74 @@ def execute_persona_update(graph: Any, arguments: dict) -> dict: } +def execute_persona_remove(graph: Any, arguments: dict) -> dict: + """删除单条人设属性""" + attribute = arguments.get("attribute") + if not attribute: + return {"status": "error", "message": "请指定要删除的属性名"} + + # 查询当前AI的所有人设关系,找到匹配属性名的 + recall_result = graph.recall(query_intent="AI,人设,角色", depth=1) + found = False + deleted_count = 0 + + for rel in recall_result.get("relations", []): + if rel.get("source") == "AI" and rel.get("type") == attribute: + result = graph.purge( + criteria={"subject_contains": "AI", "relation_type": attribute}, + mode="soft" + ) + deleted_count += result.get("deleted_count", 0) + found = True + + if not found: + # 也许属性名不完全匹配,尝试直接用这个类型删除 + result = graph.purge( + criteria={"subject_contains": "AI", "relation_type": attribute}, + mode="soft" + ) + deleted_count = result.get("deleted_count", 0) + + return { + "status": "success" if deleted_count > 0 else "not_found", + "deleted_attribute": attribute, + "deleted_count": deleted_count, + "message": f"已删除属性「{attribute}」" if deleted_count > 0 else f"未找到属性「{attribute}」" + } + + def execute_persona_clear(graph: Any, arguments: dict) -> dict: - """清除人设""" - if not arguments.get("confirm", True): - return {"status": "cancelled", "message": "需要确认才能清除人设"} - - # 删除所有人设相关关系 - result1 = graph.purge( - criteria={"subject_contains": "AI", "relation_type": "扮演角色"}, - mode="soft" - ) - result2 = graph.purge( - criteria={"subject_contains": "AI", "relation_type": "说话风格"}, - mode="soft" - ) - result3 = graph.purge( - criteria={"subject_contains": "AI", "relation_type": "性格特点"}, - mode="soft" - ) - result4 = graph.purge( - criteria={"subject_contains": "AI", "relation_type": "语气特征"}, - mode="soft" - ) - - total_deleted = ( - result1.get("deleted_count", 0) + - result2.get("deleted_count", 0) + - result3.get("deleted_count", 0) + - result4.get("deleted_count", 0) - ) - + """清除所有人设""" + if not arguments.get("confirm"): + return {"status": "cancelled", "message": "请设置 confirm=true 确认清除人设"} + + # 先查询AI的所有人设关系 + recall_result = graph.recall(query_intent="AI,人设,角色", depth=1) + + # 收集所有AI到其他实体的关系类型 + relation_types = set() + for rel in recall_result.get("relations", []): + if rel.get("source") == "AI" and rel.get("type"): + relation_types.add(rel.get("type")) + + total_deleted = 0 + deleted_types = [] + + for rtype in relation_types: + result = graph.purge( + criteria={"subject_contains": "AI", "relation_type": rtype}, + mode="soft" + ) + count = result.get("deleted_count", 0) + if count > 0: + total_deleted += count + deleted_types.append(rtype) + return { "status": "success", "deleted_count": total_deleted, - "message": "人设已清除,恢复默认身份" + "deleted_types": deleted_types, + "message": f"人设已清除,恢复默认身份(删除了 {len(deleted_types)} 类属性)" } diff --git a/core/tool_limiter.py b/core/tool_limiter.py index 2089fa8..ca76b73 100644 --- a/core/tool_limiter.py +++ b/core/tool_limiter.py @@ -39,7 +39,7 @@ class ToolLimiter: category: 'persona', 'task', 'memory' operation: 'query', 'update' """ - if tool_name in ('persona_update', 'persona_clear'): + if tool_name in ('persona_update', 'persona_remove', 'persona_clear'): return ('persona', 'update') if tool_name in ('task_create', 'task_set_state', 'task_delete', 'task_link_info'): diff --git a/core/tools/memory_tools.py b/core/tools/memory_tools.py index c3fdce4..de9b6f2 100644 --- a/core/tools/memory_tools.py +++ b/core/tools/memory_tools.py @@ -332,21 +332,37 @@ PERSONA_TOOLS = [ } } }, + { + "type": "function", + "function": { + "name": "persona_remove", + "description": "删除单条人设属性。删除指定的属性(如说话风格、扮演角色等),保留其他人设不变。", + "parameters": { + "type": "object", + "properties": { + "attribute": { + "type": "string", + "description": "要删除的属性名(如:扮演角色、说话风格、性格特点、口头禅)" + } + }, + "required": ["attribute"] + } + } + }, { "type": "function", "function": { "name": "persona_clear", - "description": "清除人设。删除AI的角色设定,恢复默认身份。", + "description": "清除人设。删除AI所有角色设定,恢复默认身份。注意:此操作不可逆。", "parameters": { "type": "object", "properties": { "confirm": { "type": "boolean", - "description": "确认清除", - "default": True + "description": "确认清除全部人设" } }, - "required": [] + "required": ["confirm"] } } }