"""Memory 抽象基类 - 统一记忆接口""" from abc import ABC, abstractmethod from dataclasses import dataclass, field from datetime import datetime, timezone from typing import Any @dataclass class MemoryItem: """记忆条目""" key: str value: Any metadata: dict[str, Any] = field(default_factory=dict) score: float = 1.0 created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc)) def to_dict(self) -> dict: return { "key": self.key, "value": self.value, "metadata": self.metadata, "score": self.score, "created_at": self.created_at.isoformat(), } class Memory(ABC): """记忆抽象基类 三层记忆系统的统一接口: - WorkingMemory: 当前任务上下文(Redis, 短生命周期) - EpisodicMemory: 任务经验(pgvector+PG, 永久) - SemanticMemory: 知识库(RAG+Graph, 永久) """ @abstractmethod async def store(self, key: str, value: Any, metadata: dict[str, Any] | None = None) -> None: """存储记忆""" ... @abstractmethod async def retrieve(self, key: str) -> MemoryItem | None: """按 key 精确检索""" ... @abstractmethod async def search(self, query: str, top_k: int = 5, filters: dict[str, Any] | None = None) -> list[MemoryItem]: """语义检索""" ... @abstractmethod async def delete(self, key: str) -> bool: """删除记忆""" ... async def store_batch(self, items: list[tuple[str, Any, dict | None]]) -> None: """批量存储""" for key, value, metadata in items: await self.store(key, value, metadata) async def get_context(self, query: str, token_budget: int = 3000) -> str: """获取格式化的上下文字符串(用于注入 Prompt)""" items = await self.search(query, top_k=10) context_parts = [] total_tokens = 0 for item in items: text = str(item.value) estimated_tokens = len(text) // 4 # 粗略估算 if total_tokens + estimated_tokens > token_budget: break context_parts.append(text) total_tokens += estimated_tokens return "\n".join(context_parts)