From 535fca933a3744b3f334a476f7df46a7ec404ea2 Mon Sep 17 00:00:00 2001 From: JianFeeeee <109188060+JianFeeeee@users.noreply.github.com> Date: Thu, 16 Apr 2026 08:35:54 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E9=99=90=E5=88=B6=E5=99=A8=E8=AF=AF=E5=88=A4?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E5=B9=B6=E4=BC=98=E5=8C=96=E8=AE=B0=E5=BF=86?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 工具调用限制器修复 - 移除memory_recall关键词智能分类,统一归类为一般记忆查询 2. 工作记忆链限制调整 - 修改限制从2次/轮到5次/轮 3. 广度优先搜索实现 - 修复depth参数被忽略问题,添加深度标注 4. 提示词优化 - 新增强制执行顺序说明,明确task_link_info使用场景 Generated with CodeArts Agent --- core/embedded_db.py | 80 ++++++++++++++++++++++--- core/prompts/templates/system_prompt.md | 51 +++++++++++++--- core/server.py | 2 +- core/tool_limiter.py | 17 ++---- core/tools/memory_tools.py | 22 +++---- 5 files changed, 133 insertions(+), 39 deletions(-) diff --git a/core/embedded_db.py b/core/embedded_db.py index 411d090..ccaf5cb 100644 --- a/core/embedded_db.py +++ b/core/embedded_db.py @@ -150,14 +150,26 @@ class EmbeddedGraphDB: 'mention_count': row['mention_count'] }) - # 搜索关系 + # 广度优先搜索(BFS)扩展实体和关系 relations = [] + visited_entity_ids = set(entity_ids) # 已访问的实体 + current_layer_ids = set(entity_ids) # 当前层的实体 - if entity_ids: - placeholders = ','.join('?' * len(entity_ids)) + # 记录每个实体的深度 + entity_depths = {} # entity_id -> depth + for eid in entity_ids: + entity_depths[eid] = 0 + + for layer in range(depth): + if not current_layer_ids: + break + + # 查询当前层实体的所有关系 + placeholders = ','.join('?' * len(current_layer_ids)) query = f""" - SELECT r.id, e1.name as source, e2.name as target, + SELECT r.id, r.source_id, r.target_id, + e1.name as source, e2.name as target, r.relation_type as type, r.confidence, r.session_id, r.turn_id, r.created_at, r.status FROM relations r @@ -167,7 +179,7 @@ class EmbeddedGraphDB: AND r.status = 'active' """ - params = list(entity_ids) + list(entity_ids) + params = list(current_layer_ids) + list(current_layer_ids) if session_filter: query += " AND r.session_id = ?" @@ -175,8 +187,18 @@ class EmbeddedGraphDB: cursor.execute(query, params) + # 收集下一层的实体 + next_layer_ids = set() + current_layer_relations = [] # 当前层的关系 + for row in cursor.fetchall(): - relations.append({ + # 计算关系的深度(取两端实体深度的最大值+1) + source_depth = entity_depths.get(row['source_id'], layer) + target_depth = entity_depths.get(row['target_id'], layer) + relation_depth = max(source_depth, target_depth) + 1 + + # 添加关系(带深度标注) + current_layer_relations.append({ 'source': row['source'], 'target': row['target'], 'type': row['type'], @@ -184,8 +206,52 @@ class EmbeddedGraphDB: 'session_id': row['session_id'], 'turn_id': row['turn_id'], 'created_at': row['created_at'], - 'status': row['status'] + 'status': row['status'], + 'depth': relation_depth }) + + # 收集新实体(未访问过的) + source_id = row['source_id'] + target_id = row['target_id'] + + if source_id not in visited_entity_ids: + next_layer_ids.add(source_id) + visited_entity_ids.add(source_id) + entity_depths[source_id] = layer + 1 + + if target_id not in visited_entity_ids: + next_layer_ids.add(target_id) + visited_entity_ids.add(target_id) + entity_depths[target_id] = layer + 1 + + relations.extend(current_layer_relations) + + # 查询下一层实体的详细信息 + if next_layer_ids: + placeholders = ','.join('?' * len(next_layer_ids)) + cursor.execute(f""" + SELECT id, name, type, mention_count + FROM entities + WHERE id IN ({placeholders}) + """, list(next_layer_ids)) + + for row in cursor.fetchall(): + entities.append({ + 'name': row['name'], + 'type': row['type'] or 'unknown', + 'mention_count': row['mention_count'], + 'depth': entity_depths.get(row['id'], layer + 1) + }) + + # 移动到下一层 + current_layer_ids = next_layer_ids + + # 为种子实体添加深度标注(depth=0) + if entity_ids: + # 重新标注种子实体的深度 + for entity in entities: + if entity.get('depth') is None: + entity['depth'] = 0 return { "entities": entities, diff --git a/core/prompts/templates/system_prompt.md b/core/prompts/templates/system_prompt.md index ea608c3..d7e2a74 100644 --- a/core/prompts/templates/system_prompt.md +++ b/core/prompts/templates/system_prompt.md @@ -2,6 +2,24 @@ 你是TrulyMEM,一个拥有长期记忆能力的AI助手。 +## ⚠️ 最高优先级:强制执行顺序 + +**每轮对话必须严格按以下顺序执行,不可跳过任何步骤!** + +``` +步骤1: memory_recall (查询人设图) → 必须首先执行 +步骤2: memory_recall (查询工作记忆链) → 必须第二步执行 +步骤3: 处理对话内容 +步骤4: 更新工作记忆链 +``` + +**违反顺序的后果**: +- 跳过步骤1 → 无法获取人设,回复风格错误 +- 跳过步骤2 → 无法获取上下文,对话不连贯 +- 顺序错误 → 系统状态混乱 + +--- + ## ⚠️ 最高优先级:只回复一次 **每轮对话只能回复一次!** @@ -121,15 +139,34 @@ - 执行其他必要的记忆操作 #### 步骤4: 更新工作记忆链 + +**重要**: 工作记忆链有两种关联机制: +1. **时间链(NEXT_TASK)**: 系统自动维护,连接TaskNode形成时间序列 +2. **信息关联(CONTAINS_INFO)**: 模型主动决定,将TaskNode链接到相关的一般记忆节点 + +**执行步骤**: +1. 使用 `memory_commit` 写入本轮重要信息(用户偏好、事实等) +2. 使用 `task_create` 创建任务节点(系统自动维护时间链) +3. 使用 `task_link_info` 将相关记忆节点关联到任务节点 + +**task_link_info 使用场景**: +- 本轮写入了新的记忆节点 → 关联到当前任务 +- 讨论了之前的话题 → 关联到相关记忆节点 +- 用户提到相关概念 → 关联到相关记忆节点 + +**示例**: ``` -必须调用: task_create -参数: { - "task_id": "Task_当前轮次ID", - "description": "本轮对话概述", - "info_nodes": ["相关记忆节点"] -} +用户: "我还是更喜欢罗辑,他的角色深度很让我着迷" + +AI操作: +1. memory_commit: 写入 "用户喜欢罗辑"、"罗辑角色深度" +2. task_create: 创建 "Task_讨论罗辑" +3. task_link_info: 关联 ["用户喜欢罗辑", "罗辑角色深度"] ``` -**目的**: 记录本轮对话,维持时间链。 + +**目的**: +- 时间链维持对话连贯性(系统自动) +- 信息关联实现"由一件事回忆起相关事情"(模型决定) --- diff --git a/core/server.py b/core/server.py index 0df9084..cbbd1e6 100644 --- a/core/server.py +++ b/core/server.py @@ -122,7 +122,7 @@ class BackendServer: persona_query_max=self._tool_limits.get("persona_query_max", 1), persona_update_max=self._tool_limits.get("persona_update_max", 1), task_query_max=self._tool_limits.get("task_query_max", 4), - task_update_max=self._tool_limits.get("task_update_max", 2), + task_update_max=self._tool_limits.get("task_update_max", 5), memory_query_max=self._tool_limits.get("memory_query_max", 20), memory_update_max=self._tool_limits.get("memory_update_max", 10), ) diff --git a/core/tool_limiter.py b/core/tool_limiter.py index 9f0f614..fad6b34 100644 --- a/core/tool_limiter.py +++ b/core/tool_limiter.py @@ -14,7 +14,7 @@ class ToolLimits: # 工作记忆链限制 task_query_max: int = 4 # 每轮最多查询4次工作记忆链 - task_update_max: int = 2 # 每轮最多修改2次工作记忆链 + task_update_max: int = 5 # 每轮最多修改5次工作记忆链 # 一般记忆限制 memory_query_max: int = 20 # 每轮最多查询20次一般记忆 @@ -62,18 +62,9 @@ class ToolLimiter: # 一般记忆工具 if tool_name == 'memory_recall': - # 判断是查询人设图、工作记忆链还是一般记忆 - query_intent = arguments.get('query_intent', '').lower() - - # 检查是否查询人设图 - if any(kw in query_intent for kw in ['人设', '角色', '性格', '语气', '说话风格', '扮演']): - return ('persona', 'query') - - # 检查是否查询工作记忆链 - if any(kw in query_intent for kw in ['tasknode', '工作记忆', '任务链', '任务', 'task']): - return ('task', 'query') - - # 一般记忆查询 + # 所有 memory_recall 统一归为一般记忆查询 + # 因为 query_intent 内容不可控,无法准确判断查询类型 + # 写入操作通过工具名称明确区分,不受此影响 return ('memory', 'query') if tool_name == 'memory_commit': diff --git a/core/tools/memory_tools.py b/core/tools/memory_tools.py index d480120..d80be7d 100644 --- a/core/tools/memory_tools.py +++ b/core/tools/memory_tools.py @@ -11,26 +11,26 @@ MEMORY_TOOLS = [ "name": "memory_recall", "description": """检索记忆。支持关键词、时间范围、会话过滤。返回相关实体和关系。 -【使用示例】 -1. 查询人设图(每轮必须首先执行): +【⚠️ 强制执行顺序 - 每轮必须严格遵守】 +1. 步骤1(必须首先执行): 查询人设图 {"query_intent": "AI,人设,角色,性格,语气,说话风格", "depth": 2} - -2. 查询工作记忆链(每轮必须第二步执行): + +2. 步骤2(必须第二步执行): 查询工作记忆链 {"query_intent": "TaskNode,工作记忆,任务链", "depth": 2} -3. 查询用户偏好: +3. 步骤3: 根据需要查询其他记忆 + +【使用示例】 +1. 查询用户偏好: {"query_intent": "用户,喜欢,偏好", "seed_entities": ["用户"]} -4. 查询特定主题: +2. 查询特定主题: {"query_intent": "Python,编程,项目", "seed_entities": ["Python"]} -5. 查询最近7天的记忆: +3. 查询最近7天的记忆: {"query_intent": "任务,工作", "time_range": {"days": 7}} -【重要】每轮对话必须按顺序执行: -- 步骤1: 查询人设图(最高优先级) -- 步骤2: 查询工作记忆链(维持对话连贯性) -- 步骤3: 根据需要查询其他记忆""", +【重要】跳过步骤1或步骤2将导致系统错误!""", "parameters": { "type": "object", "properties": {