fix(memory-graph): 修复集成测试问题
- 修复Config类memory字段验证问题 (改为Optional) - 为Memory模型添加activation属性 - 修复CreateMemoryTool返回值 (添加memory_id) - 为GraphStore添加remove_memory方法 - 修复integration测试脚本 - 所有集成测试通过 (5/5) Changes: - src/config/config.py: memory字段改为Optional - src/memory_graph/models.py: 添加activation属性 - src/memory_graph/plugin_tools/memory_plugin_tools.py: 返回memory_id - src/memory_graph/storage/graph_store.py: 添加remove_memory方法 - tests/test_memory_graph_integration.py: 修复工具返回值检查 Tests: 基本记忆操作 (CRUD + 检索) LLM工具集成 (创建记忆) 记忆生命周期 (激活/整合/遗忘) 维护任务 (调度+手动执行) 配置系统 (默认/自定义/bot_config)
This commit is contained in:
@@ -2,6 +2,7 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
import tomlkit
|
import tomlkit
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
@@ -380,7 +381,7 @@ class Config(ValidatedConfigBase):
|
|||||||
notice: NoticeConfig = Field(..., description="Notice消息配置")
|
notice: NoticeConfig = Field(..., description="Notice消息配置")
|
||||||
emoji: EmojiConfig = Field(..., description="表情配置")
|
emoji: EmojiConfig = Field(..., description="表情配置")
|
||||||
expression: ExpressionConfig = Field(..., description="表达配置")
|
expression: ExpressionConfig = Field(..., description="表达配置")
|
||||||
memory: MemoryConfig = Field(..., description="记忆配置")
|
memory: Optional[MemoryConfig] = Field(default=None, description="记忆配置(旧版,已废弃)")
|
||||||
mood: MoodConfig = Field(..., description="情绪配置")
|
mood: MoodConfig = Field(..., description="情绪配置")
|
||||||
reaction: ReactionConfig = Field(default_factory=ReactionConfig, description="反应规则配置")
|
reaction: ReactionConfig = Field(default_factory=ReactionConfig, description="反应规则配置")
|
||||||
chinese_typo: ChineseTypoConfig = Field(..., description="中文错别字配置")
|
chinese_typo: ChineseTypoConfig = Field(..., description="中文错别字配置")
|
||||||
|
|||||||
@@ -164,6 +164,7 @@ class Memory:
|
|||||||
nodes: List[MemoryNode] # 该记忆包含的所有节点
|
nodes: List[MemoryNode] # 该记忆包含的所有节点
|
||||||
edges: List[MemoryEdge] # 该记忆包含的所有边
|
edges: List[MemoryEdge] # 该记忆包含的所有边
|
||||||
importance: float = 0.5 # 整体重要性 [0-1]
|
importance: float = 0.5 # 整体重要性 [0-1]
|
||||||
|
activation: float = 0.0 # 激活度 [0-1],用于记忆整合和遗忘
|
||||||
status: MemoryStatus = MemoryStatus.STAGED # 记忆状态
|
status: MemoryStatus = MemoryStatus.STAGED # 记忆状态
|
||||||
created_at: datetime = field(default_factory=datetime.now)
|
created_at: datetime = field(default_factory=datetime.now)
|
||||||
last_accessed: datetime = field(default_factory=datetime.now) # 最后访问时间
|
last_accessed: datetime = field(default_factory=datetime.now) # 最后访问时间
|
||||||
@@ -175,8 +176,9 @@ class Memory:
|
|||||||
"""后初始化处理"""
|
"""后初始化处理"""
|
||||||
if not self.id:
|
if not self.id:
|
||||||
self.id = str(uuid.uuid4())
|
self.id = str(uuid.uuid4())
|
||||||
# 确保重要性在有效范围内
|
# 确保重要性和激活度在有效范围内
|
||||||
self.importance = max(0.0, min(1.0, self.importance))
|
self.importance = max(0.0, min(1.0, self.importance))
|
||||||
|
self.activation = max(0.0, min(1.0, self.activation))
|
||||||
|
|
||||||
def to_dict(self) -> Dict[str, Any]:
|
def to_dict(self) -> Dict[str, Any]:
|
||||||
"""转换为字典(用于序列化)"""
|
"""转换为字典(用于序列化)"""
|
||||||
@@ -187,6 +189,7 @@ class Memory:
|
|||||||
"nodes": [node.to_dict() for node in self.nodes],
|
"nodes": [node.to_dict() for node in self.nodes],
|
||||||
"edges": [edge.to_dict() for edge in self.edges],
|
"edges": [edge.to_dict() for edge in self.edges],
|
||||||
"importance": self.importance,
|
"importance": self.importance,
|
||||||
|
"activation": self.activation,
|
||||||
"status": self.status.value,
|
"status": self.status.value,
|
||||||
"created_at": self.created_at.isoformat(),
|
"created_at": self.created_at.isoformat(),
|
||||||
"last_accessed": self.last_accessed.isoformat(),
|
"last_accessed": self.last_accessed.isoformat(),
|
||||||
@@ -205,6 +208,7 @@ class Memory:
|
|||||||
nodes=[MemoryNode.from_dict(n) for n in data["nodes"]],
|
nodes=[MemoryNode.from_dict(n) for n in data["nodes"]],
|
||||||
edges=[MemoryEdge.from_dict(e) for e in data["edges"]],
|
edges=[MemoryEdge.from_dict(e) for e in data["edges"]],
|
||||||
importance=data.get("importance", 0.5),
|
importance=data.get("importance", 0.5),
|
||||||
|
activation=data.get("activation", 0.0),
|
||||||
status=MemoryStatus(data.get("status", "staged")),
|
status=MemoryStatus(data.get("status", "staged")),
|
||||||
created_at=datetime.fromisoformat(data["created_at"]),
|
created_at=datetime.fromisoformat(data["created_at"]),
|
||||||
last_accessed=datetime.fromisoformat(data.get("last_accessed", data["created_at"])),
|
last_accessed=datetime.fromisoformat(data.get("last_accessed", data["created_at"])),
|
||||||
|
|||||||
@@ -78,12 +78,14 @@ class CreateMemoryTool(BaseTool):
|
|||||||
logger.info(f"[CreateMemoryTool] 成功创建记忆: {memory.id}")
|
logger.info(f"[CreateMemoryTool] 成功创建记忆: {memory.id}")
|
||||||
return {
|
return {
|
||||||
"name": self.name,
|
"name": self.name,
|
||||||
"content": f"成功创建记忆(ID: {memory.id})"
|
"content": f"成功创建记忆(ID: {memory.id})",
|
||||||
|
"memory_id": memory.id, # 返回记忆ID供后续使用
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
return {
|
return {
|
||||||
"name": self.name,
|
"name": self.name,
|
||||||
"content": "创建记忆失败"
|
"content": "创建记忆失败",
|
||||||
|
"memory_id": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -390,6 +390,44 @@ class GraphStore:
|
|||||||
logger.info(f"从字典加载图: {store.get_statistics()}")
|
logger.info(f"从字典加载图: {store.get_statistics()}")
|
||||||
return store
|
return store
|
||||||
|
|
||||||
|
def remove_memory(self, memory_id: str) -> bool:
|
||||||
|
"""
|
||||||
|
从图中删除指定记忆
|
||||||
|
|
||||||
|
Args:
|
||||||
|
memory_id: 要删除的记忆ID
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否删除成功
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 1. 检查记忆是否存在
|
||||||
|
if memory_id not in self.memory_index:
|
||||||
|
logger.warning(f"记忆不存在,无法删除: {memory_id}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
memory = self.memory_index[memory_id]
|
||||||
|
|
||||||
|
# 2. 从节点映射中移除此记忆
|
||||||
|
for node in memory.nodes:
|
||||||
|
if node.id in self.node_to_memories:
|
||||||
|
self.node_to_memories[node.id].discard(memory_id)
|
||||||
|
# 如果该节点不再属于任何记忆,从图中移除节点
|
||||||
|
if not self.node_to_memories[node.id]:
|
||||||
|
if self.graph.has_node(node.id):
|
||||||
|
self.graph.remove_node(node.id)
|
||||||
|
del self.node_to_memories[node.id]
|
||||||
|
|
||||||
|
# 3. 从记忆索引中移除
|
||||||
|
del self.memory_index[memory_id]
|
||||||
|
|
||||||
|
logger.info(f"成功删除记忆: {memory_id}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"删除记忆失败 {memory_id}: {e}", exc_info=True)
|
||||||
|
return False
|
||||||
|
|
||||||
def clear(self) -> None:
|
def clear(self) -> None:
|
||||||
"""清空图(危险操作,仅用于测试)"""
|
"""清空图(危险操作,仅用于测试)"""
|
||||||
self.graph.clear()
|
self.graph.clear()
|
||||||
|
|||||||
Reference in New Issue
Block a user