agentscope-ai/ReMe
GitHub: agentscope-ai/ReMe
一个为 AI Agent 构建的记忆管理框架,解决长对话上下文截断和跨会话无状态问题,支持文件和向量双重存储。
Stars: 1390 | Forks: 121
一个面向 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 历史
[](https://www.star-history.com/#agentscope-ai/ReMe&Date)标签:Agent框架, DNS解析, LLM, PyPI, Python, RAG, Unmanaged PE, 上下文窗口, 人工智能, 向量数据库, 大模型Agent, 开源项目, 文件系统, 无后门, 智能体会话, 状态管理, 用户模式Hook绕过, 记忆存储, 记忆提炼, 记忆管理, 记忆系统, 逆向工具, 长期记忆, 防御加固