memory.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. """Memory 抽象 —— Agent 的记忆系统
  2. 两种实现:
  3. - ConversationMemory: 列表内存储存最近 N 轮对话
  4. - VectorMemory (future): 基于 Milvus 的长期记忆,语义检索
  5. """
  6. from __future__ import annotations
  7. from abc import ABC, abstractmethod
  8. from dataclasses import dataclass, field
  9. from typing import Any, Dict, List, Optional
  10. # ==================== 消息模型 ====================
  11. @dataclass
  12. class Message:
  13. """单条对话消息"""
  14. role: str # "system" | "user" | "assistant" | "tool"
  15. content: str
  16. metadata: Dict[str, Any] = field(default_factory=dict)
  17. def to_dict(self) -> dict:
  18. return {"role": self.role, "content": self.content}
  19. # ==================== Memory 抽象 ====================
  20. class Memory(ABC):
  21. """Memory 抽象基类
  22. 每种 Memory 实现管理 Agent 的对话历史。
  23. 短期记忆在单次会话内有效,长期记忆可跨会话检索。
  24. """
  25. @abstractmethod
  26. async def add(self, message: Message) -> None:
  27. """添加一条消息到记忆"""
  28. ...
  29. @abstractmethod
  30. async def get(self, n: int = 10) -> List[Message]:
  31. """获取最近 n 条消息"""
  32. ...
  33. @abstractmethod
  34. async def clear(self) -> None:
  35. """清空记忆"""
  36. ...
  37. @abstractmethod
  38. def to_messages(self, n: Optional[int] = None) -> List[dict]:
  39. """导出为 LLM 可用的 messages 格式"""
  40. ...
  41. @property
  42. @abstractmethod
  43. def size(self) -> int:
  44. """当前记忆中的消息数"""
  45. ...
  46. # ==================== 对话记忆实现 ====================
  47. class ConversationMemory(Memory):
  48. """基于列表的短期对话记忆
  49. 适用于单次会话内的上下文窗口管理。
  50. 超出 max_turns 时自动滚动(FIFO 裁剪)。
  51. """
  52. def __init__(self, max_turns: int = 20):
  53. self._messages: List[Message] = []
  54. self.max_turns = max_turns
  55. async def add(self, message: Message) -> None:
  56. self._messages.append(message)
  57. # FIFO 裁剪:超出限制时去掉最早的非 system 消息
  58. if len(self._messages) > self.max_turns:
  59. for i, msg in enumerate(self._messages):
  60. if msg.role != "system":
  61. self._messages.pop(i)
  62. break
  63. async def get(self, n: int = 10) -> List[Message]:
  64. return self._messages[-n:]
  65. async def clear(self) -> None:
  66. self._messages.clear()
  67. def to_messages(self, n: Optional[int] = None) -> List[dict]:
  68. msgs = self._messages if n is None else self._messages[-n:]
  69. return [m.to_dict() for m in msgs]
  70. @property
  71. def size(self) -> int:
  72. return len(self._messages)
  73. # ==================== 向量记忆(Future) ====================
  74. class VectorMemory(Memory):
  75. """基于向量数据库的长期记忆
  76. 通过 Milvus 存储语义向量,支持跨会话检索。
  77. 目前为桩实现,后续通过 MilvusBackend 对接。
  78. """
  79. def __init__(self, collection: str = "agent_memory"):
  80. self.collection = collection
  81. self._messages: List[Message] = [] # 当前会话缓存
  82. self._backend: Any = None # MilvusBackend 实例,由 DI 注入
  83. async def add(self, message: Message) -> None:
  84. self._messages.append(message)
  85. # TODO: embed + insert to Milvus
  86. async def get(self, n: int = 10) -> List[Message]:
  87. return self._messages[-n:]
  88. async def search(self, query: str, top_k: int = 5) -> List[Message]:
  89. """语义检索相关记忆"""
  90. # TODO: embed query → Milvus search → return messages
  91. return []
  92. async def clear(self) -> None:
  93. self._messages.clear()
  94. def to_messages(self, n: Optional[int] = None) -> List[dict]:
  95. msgs = self._messages if n is None else self._messages[-n:]
  96. return [m.to_dict() for m in msgs]
  97. @property
  98. def size(self) -> int:
  99. return len(self._messages)