|
|
il y a 1 mois | |
|---|---|---|
| .. | ||
| app | il y a 1 mois | |
| tests | il y a 1 mois | |
| README.md | il y a 1 mois | |
| pyproject.toml | il y a 1 mois | |
| requirements-frameworks.txt | il y a 1 mois | |
这是一个用统一 HTTP 接口对比 Agent 记忆方案的后端项目。当前接入了 Text2Mem、Mem0、Letta、ReMe 和 memU。五个系统都通过 MemoryAgent 暴露相同的对话、记忆查询、删除、审计和重置能力,前端不需要关心各 SDK 的接口差异。
建议第一次阅读时先运行内置的 Text2Mem。它不依赖第三方记忆 SDK,未配置模型和 PostgreSQL 时也能通过本地规则及 JSON 文件工作。
在当前目录执行:
python3.11 -m venv .venv
source .venv/bin/activate
pip install -e .
pip install pytest pytest-asyncio ruff
uvicorn app.main:app --reload --port 8000
打开 http://127.0.0.1:8000/docs 可以直接调试接口。先检查服务状态:
curl http://127.0.0.1:8000/api/health
curl http://127.0.0.1:8000/api/systems
默认情况下,PostgreSQL 连接失败会自动退回 local-json,Text2Mem 仍可使用。可以用下面的请求验证完整流程:
curl -X POST http://127.0.0.1:8000/api/chat \
-H 'Content-Type: application/json' \
-d '{"system":"text2mem","message":"记住:项目数据库使用 PostgreSQL"}'
curl -X POST http://127.0.0.1:8000/api/chat \
-H 'Content-Type: application/json' \
-d '{"system":"text2mem","message":"项目使用什么数据库?"}'
项目通过环境变量配置,常用变量如下:
| 变量 | 默认值 | 说明 |
|---|---|---|
WORKSPACE_ID |
local-workspace |
数据隔离使用的工作区标识 |
DATA_DIR |
MemoryAgents/data |
本地 JSON、ReMe、memU 文件目录 |
DATABASE_URL |
postgresql://memory:memory@localhost:54329/memory_agents |
PostgreSQL 连接串 |
LLM_BASE_URL |
https://api.openai.com/v1 |
对话模型接口地址 |
LLM_API_KEY |
空 | 对话模型密钥 |
LLM_MODEL |
gpt-4o-mini |
对话模型名 |
EMBEDDING_BASE_URL |
https://api.openai.com/v1 |
向量接口地址 |
EMBEDDING_API_KEY |
空 | 向量接口密钥 |
EMBEDDING_MODEL |
text-embedding-3-small |
向量模型名 |
EMBEDDING_DIMENSIONS |
1536 |
向量维度,必须和模型、数据库表一致 |
EMBEDDING_MIN_SCORE |
0.35 |
语义召回最低相似度 |
REME_ENABLED 等 |
false |
是否启用对应第三方适配器 |
开发时可以先在 shell 中 export,也可以按 app/config.py 的加载路径放置 .env。建议显式设置 DATA_DIR,避免从不同目录启动时混淆数据位置。
启用第三方实现前,需要安装对应依赖:
pip install -e '.[reme]'
pip install -e '.[mem0]'
pip install -e '.[letta]'
pip install -e '.[memu]'
Mem0、Letta 和 memU 目前仍是适配骨架,代码中的 setup_hint 列出了尚未闭环的能力,默认不要开启。ReMe 已实现文件记忆、词面检索和 pgvector 语义召回。
backend/
├── app/
│ ├── main.py # FastAPI 入口和路由
│ ├── config.py # 环境变量与 SDK 兼容配置
│ ├── schemas.py # 请求、响应、记忆和审计模型
│ ├── registry.py # 记忆适配器注册表
│ ├── db.py # PostgreSQL / 本地 JSON 统一存储
│ ├── llm.py # OpenAI 兼容对话客户端
│ ├── embeddings.py # OpenAI 兼容向量客户端
│ └── adapters/
│ ├── base.py # 所有适配器的公共契约
│ ├── text2mem.py # 内置教学实现
│ ├── reme.py # ReMe 文件记忆实现
│ ├── mem0.py # Mem0 适配器
│ ├── letta.py # Letta 适配器
│ └── memu.py # memU 适配器
└── tests/ # 核心写入、检索和重置测试
一次 /api/chat 请求的处理过程:
app/main.py:chat() 根据请求中的 system 从注册表取出适配器。chat() 决定是否写入记忆,并执行该系统自己的检索流程。MemoryRepository 写入 PostgreSQL;数据库不可用时写入本地 JSON。embedding_client 生成查询向量,存储层计算相似度。llm 生成回答;Text2Mem 在模型不可用时返回本地证据。_audit() 留下审计记录。Text2Mem 最适合用来理解项目。_should_encode() 先判断输入是陈述还是问题;陈述由 _memory_type() 分为语义、情景、流程和任务状态四类。_encode() 负责去重和持久化,_retrieve() 将词面重合、记忆类型加分和向量相似度合并排序。
这里的规则是教学实现,不是通用中文意图识别器。调整正则时应同时补充 tests/test_text2mem.py,避免普通问题被误写入长期记忆。
ReMe 把 Markdown 文件作为真实记忆源。每轮对话按需执行自动记忆和重建索引,再通过规则扩展、可选模型改写、ReMe 文件检索和 pgvector 检索合并证据。后台定时任务被显式关闭,目的是让文件变化和模型费用都由请求触发。
删除 ReMe 记忆时会删除文件、清理公共向量并重建索引;全量重置还会移除 ReMe 工作目录。
MemoryRepository 维护三类数据:memory_items、audit_events 和 memory_embeddings。PostgreSQL 使用 HNSW 索引做向量近邻搜索;本地模式使用 JSON 保存数据,并在进程内计算余弦相似度。
本地 JSON 主要用于快速体验和测试,不适合并发写入。部署环境应使用 PostgreSQL,并确保 pgvector 列维度与 EMBEDDING_DIMENSIONS 一致。
| 方法 | 路径 | 用途 |
|---|---|---|
GET |
/api/health |
检查存储、模型和向量配置 |
GET |
/api/systems |
查看五个记忆系统的可用状态 |
POST |
/api/chat |
指定记忆系统进行对话 |
GET |
/api/memories |
查询某个系统的记忆 |
DELETE |
/api/memories/{memory_id} |
删除指定记忆 |
GET |
/api/audit |
查询操作审计记录 |
POST |
/api/reset |
重置单个系统或全部系统 |
POST /api/reset 不传 system 会逐个调用所有适配器。这个行为不能简单替换为清空公共表,因为 ReMe 等适配器还有自己的文件或索引。
pytest
ruff check app tests
测试默认使用临时本地存储,不要求 PostgreSQL、模型或第三方记忆 SDK。新增适配器时,至少需要覆盖系统状态、不可用提示、写入/检索、删除和重置行为。
app/adapters/ 下新增类并继承 MemoryAgent。id 和 SystemDescriptor,实现 chat()。self.repo;外部存储需要重写 memories()、delete_memory() 和 reset()。SystemName 中加入系统 ID,并在 build_registry() 注册实例。适配器返回的 ChatResponse 中,memory_context 是本轮使用或可展示的记忆,memory_events 描述本轮写入和检索动作,audit_events 用于排查实际执行路径。三者含义不要混用。