agentscope-ai/ReMe

GitHub: agentscope-ai/ReMe

一个为 AI Agent 构建的记忆管理框架,解决长对话上下文截断和跨会话无状态问题,支持文件和向量双重存储。

Stars: 1390 | Forks: 121

ReMe Logo

Python Version PyPI Version PyPI Downloads GitHub commit activity

License English 简体中文 GitHub Stars

一个面向 AI Agents 的记忆管理工具包 —— 记住我,提炼我。

🧠 ReMe 是一个为 **AI agents** 构建的 **记忆管理框架**,提供 **基于文件** 和 **基于向量** 的记忆系统。 它解决了 Agent 记忆的两个核心问题:**有限的上下文窗口**(在长对话中早期信息被截断或丢失)和 **无状态会话**(新对话无法继承历史,总是从头开始)。 ReMe 赋予 Agents **真正的记忆** —— 旧对话被自动浓缩,重要信息被持久化,下次对话能自动召回。 ## 📁 基于文件的 CoPaw 记忆系统 将 **记忆视为文件** —— 可读、可编辑、可移植。[CoPaw](https://github.com/agentscope-ai/CoPaw) 通过 [MemoryManager](https://github.com/agentscope-ai/CoPaw/blob/main/src/copaw/agents/memory/memory_manager.py) 集成此记忆系统,它继承了 `ReMeCopaw` 并暴露记忆管理能力。 | 传统记忆系统 | 基于文件的 ReMe | |----------------------------|--------------------| | 🗄️ 数据库存储 | 📝 Markdown 文件 | | 🔒 不透明 | 👀 随时可读 | | ❌ 难以修改 | ✏️ 直接编辑 | | 🚫 难以迁移 | 📦 复制即可迁移 | ``` working_dir/ ├── MEMORY.md # Long-term memory: user preferences, project config, etc. ├── memory/ │ └── YYYY-MM-DD.md # Daily summary logs: written automatically after conversation ends └── tool_result/ # Cache for oversized tool outputs (auto-managed, auto-cleaned when expired) └── .txt ``` ### 核心能力 [ReMeCopaw](reme/reme_copaw.py) 是该记忆系统的核心类,为 AI Agents 提供完整的记忆管理能力: | Method | Function | Key Components | |--------------------------|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `start` | 🚀 启动记忆系统 | 初始化文件存储、文件监视器、Embedding 缓存;清理过期的工具结果文件 | | `close` | 📕 关闭并清理 | 清理工具结果文件、停止文件监视器、保存 Embedding 缓存 | | `compact_memory` | 📦 将历史压缩为摘要 | [Compactor](reme/memory/file_based_copaw/compactor.py) — ReActAgent 生成结构化的上下文检查点 | | `summary_memory` | 📝 将重要记忆写入文件 | [Summarizer](reme/memory/file_based_copaw/summarizer.py) — ReActAgent + 文件工具 (read / write / edit) | | `compact_tool_result` | ✂️ 压缩过大的工具输出 | [ToolResultCompactor](reme/memory/file_based_copaw/tool_result_compactor.py) — 截断并保存至 `tool_result/`,在消息中保留文件引用 | | `add_async_summary_task` | ⚡ 提交后台摘要任务 | `asyncio.create_task`,摘要不阻塞主对话流 | | `await_summary_tasks` | ⏳ 等待后台任务 | 收集所有后台摘要任务的结果,关闭前调用以确保写入完成 | | `memory_search` | 🔍 语义记忆搜索 | [MemorySearch](reme/memory/tools/chunk/memory_search.py) — 向量 + BM25 混合检索 | | `get_in_memory_memory` | 🗂️ 创建内存实例 | [CoPawInMemoryMemory](reme/memory/file_based_copaw/copaw_in_memory_memory.py) — 感知 Token 的记忆管理,支持压缩摘要和状态序列化 | | `update_params` | ⚙️ 更新运行时参数 | 运行时调整 `max_input_length`、`memory_compact_ratio`、`language` | ## 🗃️ 基于向量的 ReMe [ReMe Vector Based](reme/reme.py) 是基于向量的记忆系统的核心类,支持统一管理三种记忆类型: | Memory Type | Purpose | Usage Context | |------------------------------|-----------------------------------------------------|---------------| | **Personal memory** | 用户偏好、习惯 | `user_name` | | **Task / procedural memory** | 任务执行经验、成功/失败模式 | `task_name` | | **Tool memory** | 工具使用经验、参数调整 | `tool_name` | ### 核心能力 | Method | Function | Description | |--------------------|---------------------|-----------------------------------------------------------| | `summarize_memory` | 🧠 摘要记忆 | 自动从对话中提取并存储记忆 | | `retrieve_memory` | 🔍 检索记忆 | 根据查询检索相关记忆 | | `add_memory` | ➕ 添加记忆 | 手动向向量存储添加记忆 | | `get_memory` | 📖 获取记忆 | 根据 ID 获取单条记忆 | | `update_memory` | ✏️ 更新记忆 | 更新已有记忆的内容或元数据 | | `delete_memory` | 🗑️ 删除记忆 | 删除指定记忆 | | `list_memory` | 📋 列出记忆 | 列出记忆,支持过滤和排序 | ## 💻 ReMeCli:具备文件记忆的终端助手






### 何时写入记忆? | Scenario | Written to | Trigger | |---------------------------------------------|------------------------|------------------------------------| | 上下文过长时自动压缩 | `memory/YYYY-MM-DD.md` | 后台自动执行 | | 用户运行 `/compact` | `memory/YYYY-MM-DD.md` | 手动压缩 + 后台保存 | | 用户运行 `/new` | `memory/YYYY-MM-DD.md` | 新对话 + 后台保存 | | 用户说“记住这个” | `MEMORY.md` 或日志 | Agent 通过 `write` 工具写入 | | Agent 发现重要决策/偏好 | `MEMORY.md` | Agent 主动写入 | ### 记忆检索工具 | Method | Tool | When to use | Example | |-----------------|-----------------|----------------------------------|---------------------------------------| | 语义搜索 | `memory_search` | 不确定位置,模糊查找 | "之前关于部署的讨论" | | 直接读取 | `read` | 知道日期或文件 | 读取 `memory/2025-02-13.md` | 搜索使用 **向量 + BM25 混合检索**(向量权重 0.7,BM25 权重 0.3),因此使用自然语言和精确关键词的查询都能匹配。 ### 内置工具 | Tool | Function | Details | |-----------------|----------------|------------------------------------------------------------| | `memory_search` | 搜索记忆 | 对 MEMORY.md 和 memory/*.md 进行向量 + BM25 混合搜索 | | `bash` | 运行命令 | 执行 bash 命令,支持超时和输出截断 | | `ls` | 列出目录 | 显示目录结构 | | `read` | 读取文件 | 支持文本和图像,支持分段阅读 | | `edit` | 编辑文件 | 精确文本匹配后替换 | | `write` | 写入文件 | 创建或覆盖,自动创建目录 | | `execute_code` | 运行 Python | 执行代码片段 | | `web_search` | 网页搜索 | 通过 Tavily 搜索 | ## 🚀 快速开始 ### 安装 ``` pip install -U reme-ai ``` ### 环境变量 API keys 通过环境变量设置;你可以将它们放在项目根目录的 `.env` 文件中: | Variable | Description | Example | |---------------------------|----------------------------------|-----------------------------------------------------| | `REME_LLM_API_KEY` | LLM API key | `sk-xxx` | | `REME_LLM_BASE_URL` | LLM base URL | `https://dashscope.aliyuncs.com/compatible-mode/v1` | | `REME_EMBEDDING_API_KEY` | Embedding API key | `sk-xxx` | | `REME_EMBEDDING_BASE_URL` | Embedding base URL | `https://dashscope.aliyuncs.com/compatible-mode/v1` | | `TAVILY_API_KEY` | Tavily 搜索 API key (可选) | `tvly-xxx` | ### 使用 ReMeCli #### 启动 ReMeCli ``` remecli config=cli ``` #### ReMeCli 系统命令 以 `/` 开头的命令用于控制会话状态: | Command | Description | Waits for response | |------------|--------------------------------------------------------------------|--------------------| | `/compact` | 手动压缩当前对话并保存到长期记忆 | Yes | | `/new` | 开始新对话;历史保存到长期记忆 | No | | `/clear` | 清除所有内容,**不保存** | No | | `/history` | 查看当前对话中未压缩的消息 | No | | `/help` | 显示命令列表 | No | | `/exit` | 退出 | No | **三个命令的区别** | Command | Compact summary | Long-term memory | Message history | |------------|-----------------|------------------|-----------------| | `/compact` | 新摘要 | 已保存 | 保留最近的 | | `/new` | 已清除 | 已保存 | 已清除 | | `/clear` | 已清除 | 未保存 | 已清除 | ### 使用 ReMe 包 #### 基于文件的 ReMe (CoPaw 记忆系统) `ReMeCopaw` 接收 AgentScope 组件,如 `ChatModelBase`、`Formatter`、`Toolkit`,并通过环境变量配置 Embedding 和存储后端: | Environment Variable | Description | Default | |----------------------------|-----------------------------------------------|-----------------------------------------------------| | `EMBEDDING_API_KEY` | Embedding 服务 API Key | `""` (若未配置则禁用向量搜索) | | `EMBEDDING_BASE_URL` | Embedding 服务 Base URL | `https://dashscope.aliyuncs.com/compatible-mode/v1` | | `EMBEDDING_MODEL_NAME` | Embedding 模型名称 | `""` | | `EMBEDDING_DIMENSIONS` | 向量维度 | `1024` | | `EMBEDDING_CACHE_ENABLED` | 是否启用 Embedding 缓存 | `true` | | `EMBEDDING_MAX_CACHE_SIZE` | 最大缓存条目 | `2000` | | `FTS_ENABLED` | 是否启用全文搜索 (BM25) | `true` | | `MEMORY_STORE_BACKEND` | 存储后端 (`auto` / `chroma` / `local`) | `auto` (Windows 上为 local,其他为 chroma) | ``` import asyncio from agentscope.formatter import ClaudeFormatter from agentscope.model import get_model from agentscope.token import HuggingFaceTokenCounter from agentscope.tool import Toolkit from reme.reme_copaw import ReMeCopaw async def main(): # Prepare AgentScope core components chat_model = get_model(config={"backend": "openai", "model_name": "qwen3.5-plus"}) formatter = ClaudeFormatter() token_counter = HuggingFaceTokenCounter() toolkit = Toolkit() # Can register additional tools # Initialize ReMeCopaw reme = ReMeCopaw( working_dir=".reme", # Memory file storage directory chat_model=chat_model, formatter=formatter, token_counter=token_counter, toolkit=toolkit, max_input_length=128000, # Model context window (tokens) memory_compact_ratio=0.7, # Trigger compaction when reaching max_input_length * 0.7 language="zh", # Summary language (zh / "") tool_result_threshold=1000, # Auto-save tool outputs exceeding this character count retention_days=7, # tool_result/ file retention days ) await reme.start() messages = [...] # list[Msg], conversation history # 1. Compact oversized tool outputs (prevent tool results from overflowing context) messages = await reme.compact_tool_result(messages) # 2. Compact history to structured summary (trigger: context approaching limit) summary = await reme.compact_memory( messages=messages, previous_summary="", # Can pass previous summary for incremental update ) print(f"Compact summary:\n{summary}") # 3. Submit async summary task in background (non-blocking, writes to memory/YYYY-MM-DD.md) reme.add_async_summary_task(messages=messages) # 4. Semantic memory search (Vector + BM25 hybrid retrieval) result = await reme.memory_search(query="Python version preference", max_results=5) print(f"Search results: {result}") # 5. Get in-memory instance (CoPawInMemoryMemory, manages single conversation context) memory = reme.get_in_memory_memory() token_stats = await memory.estimate_tokens() print(f"Current context usage: {token_stats['context_usage_ratio']:.1f}%") # 6. Wait for background tasks before closing await reme.await_summary_tasks() await reme.close() if __name__ == "__main__": asyncio.run(main()) ``` #### 基于向量的 ReMe ``` import asyncio from reme import ReMe async def main(): # Initialize ReMe reme = ReMe( working_dir=".reme", default_llm_config={ "backend": "openai", "model_name": "qwen3.5-plus", }, default_embedding_model_config={ "backend": "openai", "model_name": "text-embedding-v4", "dimensions": 1024, }, default_vector_store_config={ "backend": "local", # Supports local/chroma/qdrant/elasticsearch }, ) await reme.start() messages = [ {"role": "user", "content": "Help me write a Python script", "time_created": "2026-02-28 10:00:00"}, {"role": "assistant", "content": "Sure, I'll help you write it", "time_created": "2026-02-28 10:00:05"}, ] # 1. Summarize memory from conversation (auto-extract user preferences, task experience, etc.) result = await reme.summarize_memory( messages=messages, user_name="alice", # Personal memory # task_name="code_writing", # Task memory ) print(f"Summarize result: {result}") # 2. Retrieve relevant memory memories = await reme.retrieve_memory( query="Python programming", user_name="alice", # task_name="code_writing", ) print(f"Retrieve result: {memories}") # 3. Manually add memory memory_node = await reme.add_memory( memory_content="User prefers concise code style", user_name="alice", ) print(f"Added memory: {memory_node}") memory_id = memory_node.memory_id # 4. Get single memory by ID fetched_memory = await reme.get_memory(memory_id=memory_id) print(f"Fetched memory: {fetched_memory}") # 5. Update memory content updated_memory = await reme.update_memory( memory_id=memory_id, user_name="alice", memory_content="User prefers concise, well-commented code style", ) print(f"Updated memory: {updated_memory}") # 6. List all memories for user (with filtering and sorting) all_memories = await reme.list_memory( user_name="alice", limit=10, sort_key="time_created", reverse=True, ) print(f"User memory list: {all_memories}") # 7. Delete specified memory await reme.delete_memory(memory_id=memory_id) print(f"Deleted memory: {memory_id}") # 8. Delete all memories (use with caution) # await reme.delete_all() await reme.close() if __name__ == "__main__": asyncio.run(main()) ``` ## 🏛️ 技术架构 ### 基于文件的 CoPaw 记忆系统架构 [CoPaw MemoryManager](https://github.com/agentscope-ai/CoPaw/blob/main/src/copaw/agents/memory/memory_manager.py) 继承 `ReMeCopaw` 并将记忆能力集成到 Agent 推理流中: ``` graph TB CoPaw["CoPaw MemoryManager\n(inherits ReMeCopaw)"] -->|pre_reasoning hook| Hook[MemoryCompactionHook] CoPaw --> ReMeCopaw[ReMeCopaw] Hook -->|exceeds threshold| ReMeCopaw ReMeCopaw --> CompactMemory[compact_memory\nHistory compaction] ReMeCopaw --> SummaryMemory[summary_memory\nWrite memory to files] ReMeCopaw --> CompactToolResult[compact_tool_result\nOversized tool output compaction] ReMeCopaw --> MemSearch[memory_search\nSemantic search] ReMeCopaw --> InMemory[get_in_memory_memory\nCoPawInMemoryMemory] CompactMemory --> Compactor[Compactor\nReActAgent] SummaryMemory --> Summarizer[Summarizer\nReActAgent + file tools] CompactToolResult --> ToolResultCompactor[ToolResultCompactor\nTruncate + save to file] Summarizer --> FileIO[FileIO\nread / write / edit] FileIO --> MemoryFiles[memory/YYYY-MM-DD.md] ToolResultCompactor --> ToolResultFiles[tool_result/*.txt] MemoryFiles -.->|File change| FileWatcher[Async File Watcher] FileWatcher -->|Update index| FileStore[Local DB] MemSearch --> FileStore ``` #### 自动压缩触发流程 `MemoryCompactionHook` 在每次推理步骤前检查上下文 Token 使用量,当超过阈值时自动触发压缩: ``` graph LR A[pre_reasoning] --> B{Token exceeds threshold?} B -->|No| Z[Continue reasoning] B -->|Yes| C[compact_tool_result\nCompact oversized tool outputs in recent messages] C --> D[compact_memory\nGenerate structured context checkpoint] D --> E[Mark old messages as COMPRESSED] E --> F[add_async_summary_task\nBackground write to memory file] F --> Z ``` #### 上下文压缩摘要格式 [Compactor](reme/memory/file_based_copaw/compactor.py) 使用 ReActAgent 将历史压缩为结构化的 **上下文检查点**: | Field | Description | |-----------------------|--------------------------------------------------| | `## Goal` | 🎯 用户目标(可以是多个) | | `## Constraints` | ⚙️ 用户提到的约束和偏好 | | `## Progress` | 📈 已完成 / 进行中 / 受阻的任务 | | `## Key Decisions` | 🔑 做出的决策及简短原因 | | `## Next Steps` | 🗺️ 下一步行动计划(有序列表) | | `## Critical Context` | 📌 文件路径、函数名、错误消息 | 支持 **增量更新**:当传入 `previous_summary` 时,自动将新对话与旧摘要合并,保留历史进度。 #### 工具结果压缩 [ToolResultCompactor](reme/memory/file_based_copaw/tool_result_compactor.py) 解决因工具输出过大导致的上下文溢出: B{Think: What's worth recording?} B --> C[Act: read memory/YYYY-MM-DD.md] C --> D{Think: How to merge with existing content?} D --> E[Act: edit to update file] E --> F{Think: Anything missing?} F -->|Yes| B F -->|No| G[Done] ``` [FileIO](reme/memory/file_based_copaw/file_io.py) 提供文件操作工具: | Tool | Function | Use case | |---------|--------------------------------|-----------------------------------------| | `read` | 读取文件内容(行范围) | 查看已有记忆,避免重复 | | `write` | 覆盖文件 | 创建新记忆文件或重大重写 | | `edit` | 精确匹配后替换 | 追加或修改特定部分 | #### 内存会话管理 [CoPawInMemoryMemory](reme/memory/file_based_copaw/copaw_in_memory_memory.py) 扩展了 AgentScope 的 `InMemoryMemory`: | Feature | Description | |----------------------------------|---------------------------------------------------------------------| | `get_memory` | 按标记过滤消息,自动前置压缩摘要 | | `estimate_tokens` | 精确估算当前上下文 Token 使用量和比例 | | `get_history_str` | 生成人类可读的对话摘要(含 Token 统计) | | `state_dict` / `load_state_dict` | 支持状态序列化 / 反序列化(会话持久化) | #### 记忆检索 [MemorySearch](reme/memory/tools/chunk/memory_search.py) 提供 **向量 + BM25 混合检索**: | Retrieval | Strength | Weakness | |---------------------|-------------------------------------------------|----------------------------------------| | **Vector semantic** | 捕获不同措辞下的相似语义 | 精确 Token 匹配较弱 | | **BM25 full-text** | 精确 Token 匹配能力强 | 不理解同义词或改写 | **融合**:同时使用两种检索路径;通过加权和(向量 0.7 + BM25 0.3)合并结果,因此自然语言查询和精确查找都能获得可靠结果。 ``` graph LR Q[Search query] --> V[Vector search × 0.7] Q --> B[BM25 × 0.3] V --> M[Dedupe + weighted merge] B --> M M --> R[Top-N results] ``` ### 基于向量的 ReMe 核心架构 ``` graph TB User[User / Agent] --> ReMe[Vector Based ReMe] ReMe --> Summarize[Memory Summarize] ReMe --> Retrieve[Memory Retrieve] ReMe --> CRUD[CRUD] Summarize --> PersonalSum[PersonalSummarizer] Summarize --> ProceduralSum[ProceduralSummarizer] Summarize --> ToolSum[ToolSummarizer] Retrieve --> PersonalRet[PersonalRetriever] Retrieve --> ProceduralRet[ProceduralRetriever] Retrieve --> ToolRet[ToolRetriever] PersonalSum --> VectorStore[Vector DB] ProceduralSum --> VectorStore ToolSum --> VectorStore PersonalRet --> VectorStore ProceduralRet --> VectorStore ToolRet --> VectorStore ``` ## 📄 引用 ``` @software{AgentscopeReMe2025, title = {AgentscopeReMe: Memory Management Kit for Agents}, author = {ReMe Team}, url = {https://reme.agentscope.io}, year = {2025} } ``` ## ⚖️ 许可证 本项目基于 Apache License 2.0 开源。详见 [LICENSE](./LICENSE) 文件。 ## 📈 Star 历史 [![Star History Chart](https://api.star-history.com/svg?repos=agentscope-ai/ReMe&type=Date)](https://www.star-history.com/#agentscope-ai/ReMe&Date)
标签:Agent框架, DNS解析, LLM, PyPI, Python, RAG, Unmanaged PE, 上下文窗口, 人工智能, 向量数据库, 大模型Agent, 开源项目, 文件系统, 无后门, 智能体会话, 状态管理, 用户模式Hook绕过, 记忆存储, 记忆提炼, 记忆管理, 记忆系统, 逆向工具, 长期记忆, 防御加固