leon f62db54db0 docs: 补充项目说明和核心流程注释 1 місяць тому
..
app f62db54db0 docs: 补充项目说明和核心流程注释 1 місяць тому
tests 11df0af97a init 1 місяць тому
README.md f62db54db0 docs: 补充项目说明和核心流程注释 1 місяць тому
pyproject.toml 11df0af97a init 1 місяць тому
requirements-frameworks.txt 11df0af97a init 1 місяць тому

README.md

Memory Agents API

这是一个用统一 HTTP 接口对比 Agent 记忆方案的后端项目。当前接入了 Text2Mem、Mem0、Letta、ReMe 和 memU。五个系统都通过 MemoryAgent 暴露相同的对话、记忆查询、删除、审计和重置能力,前端不需要关心各 SDK 的接口差异。

建议第一次阅读时先运行内置的 Text2Mem。它不依赖第三方记忆 SDK,未配置模型和 PostgreSQL 时也能通过本地规则及 JSON 文件工作。

环境要求

  • Python 3.11+
  • PostgreSQL(可选,生产存储;需要安装 pgvector 扩展)
  • OpenAI 兼容的 Chat Completions 和 Embeddings 服务(可选)

快速启动

在当前目录执行:

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 请求的处理过程:

  1. app/main.py:chat() 根据请求中的 system 从注册表取出适配器。
  2. 适配器的 chat() 决定是否写入记忆,并执行该系统自己的检索流程。
  3. 公共数据通过 MemoryRepository 写入 PostgreSQL;数据库不可用时写入本地 JSON。
  4. 需要语义检索时,embedding_client 生成查询向量,存储层计算相似度。
  5. 召回内容交给 llm 生成回答;Text2Mem 在模型不可用时返回本地证据。
  6. 写入、检索、删除等动作通过 _audit() 留下审计记录。

Text2Mem

Text2Mem 最适合用来理解项目。_should_encode() 先判断输入是陈述还是问题;陈述由 _memory_type() 分为语义、情景、流程和任务状态四类。_encode() 负责去重和持久化,_retrieve() 将词面重合、记忆类型加分和向量相似度合并排序。

这里的规则是教学实现,不是通用中文意图识别器。调整正则时应同时补充 tests/test_text2mem.py,避免普通问题被误写入长期记忆。

ReMe

ReMe 把 Markdown 文件作为真实记忆源。每轮对话按需执行自动记忆和重建索引,再通过规则扩展、可选模型改写、ReMe 文件检索和 pgvector 检索合并证据。后台定时任务被显式关闭,目的是让文件变化和模型费用都由请求触发。

删除 ReMe 记忆时会删除文件、清理公共向量并重建索引;全量重置还会移除 ReMe 工作目录。

存储层

MemoryRepository 维护三类数据:memory_itemsaudit_eventsmemory_embeddings。PostgreSQL 使用 HNSW 索引做向量近邻搜索;本地模式使用 JSON 保存数据,并在进程内计算余弦相似度。

本地 JSON 主要用于快速体验和测试,不适合并发写入。部署环境应使用 PostgreSQL,并确保 pgvector 列维度与 EMBEDDING_DIMENSIONS 一致。

API 一览

方法 路径 用途
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。新增适配器时,至少需要覆盖系统状态、不可用提示、写入/检索、删除和重置行为。

新增一个记忆适配器

  1. app/adapters/ 下新增类并继承 MemoryAgent
  2. 设置唯一的 idSystemDescriptor,实现 chat()
  3. 如果使用公共存储,复用 self.repo;外部存储需要重写 memories()delete_memory()reset()
  4. SystemName 中加入系统 ID,并在 build_registry() 注册实例。
  5. 为启用条件、失败降级和数据清理补充测试。

适配器返回的 ChatResponse 中,memory_context 是本轮使用或可展示的记忆,memory_events 描述本轮写入和检索动作,audit_events 用于排查实际执行路径。三者含义不要混用。