内容
# 记忆
自主代理的持久、上下文感知记忆服务。
> 记忆(Jìyì)- 来自中文,意为个人记忆。
记忆存储和检索四种类型的记忆:
- **情景事件** – 带向量嵌入和来源的时间顺序观察。
- **语义事实** – 带有效性窗口的主语/谓语/客体三元组。
- **工作记忆** – 会话级别、短期的键值状态。
- **过程记忆** – 在组装时读取的git支持的剧本文件。
它暴露了HTTP API(`Plug` + `Bandit`)和MCP服务器(`anubis_mcp`),这样调用者可以`context/assemble`排名记忆或`memory/write`新条目。
## 要求
- Elixir ~> 1.17(测试版本为1.19.5)
- Erlang/OTP ~> 27(测试版本为OTP 28)
- PostgreSQL 16+,带有`pgvector`扩展
## 设置
```bash
mix deps.get
# 配置Postgres凭证,然后:
export JIYI_DB_USER="postgres"
export JIYI_DB_PASSWORD="..."
export JIYI_DB_HOST="localhost"
mix ecto.create
mix ecto.migrate
```
默认嵌入维度为`768`。如果使用不同的模型,请在第一次迁移前在`config/config.exs`中更改。
## 快速开始
启动服务(假设Postgres和配置的嵌入端点正在运行):
```bash
export JIYI_API_TOKEN="dev-token-change-me"
mix run --no-halt
```
### 本地嵌入服务器(可选)
记忆可以通过Bumblebee使用`BAAI/bge-base-en-v1.5`可选地捆绑自己的嵌入服务器。这是**可选的**,因为加载转换器模型会增加约400 MB的下载、约500 MB-1 GB的RAM和明显的CPU使用率。在没有单独的嵌入服务时启用它:
```bash
export JIYI_EMBEDDING_SERVER_ENABLED=true
export JIYI_EMBEDDING_ENDPOINT=http://localhost:8001/embed
mix run --no-halt
```
启用后,服务器监听`JIYI_EMBEDDING_SERVER_PORT`(默认为`8001`)并公开`POST /embed`。一旦`JIYI_EMBEDDING_ENDPOINT`指向那里,记忆的断路器将自动使用它。
写入记忆并读取:
```bash
curl -X POST http://localhost:4000/memory/write \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $JIYI_API_TOKEN" \
-d '{
"type": "semantic",
"agent_id": "agent-1",
"session_id": "session-1",
"content": {"subject": "project", "predicate": "uses", "object": "Elixir"},
"provenance": {"source": "user_message", "ingestion_method": "direct_write", "trust_tier": "human_asserted"},
"scope": "session_shared"
}'
curl -X POST http://localhost:4000/context/assemble \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $JIYI_API_TOKEN" \
-d '{"agent_id": "agent-1", "session_id": "session-1", "task": "What does the project use?"}'
```
### MCP
记忆还将相同的操作作为MCP工具公开。使用`stdio`(默认)用于启动服务器进程的客户端,或使用`streamable_http`通过HTTP API访问MCP:
```bash
# stdio
JIYI_MCP_TRANSPORT=stdio mix run --no-halt
# streamable HTTP
JIYI_MCP_TRANSPORT=streamable_http mix run --no-halt
```
使用`streamable_http`时,将MCP客户端指向`http://localhost:4000/mcp`。
## 配置
| 变量 | 默认值 | 目的 |
| --- | --- | --- |
| `JIYI_DB_USER` | `postgres` | Postgres用户名 |
| `JIYI_DB_PASSWORD` | `postgres` | Postgres密码 |
| `JIYI_DB_HOST` | `localhost` | Postgres主机 |
| `JIYI_DB_NAME` | `jiyi_dev` / `jiyi_test` | 数据库名称 |
| `JIYI_HTTP_PORT` | `4000` | HTTP API端口 |
| `JIYI_API_TOKEN` | `dev-token-change-me` | HTTP端点的共享管理员承载令牌 |
| `JIYI_EMBEDDING_ENDPOINT` | `http://localhost:8000/embed`(或启用本地服务器时为`http://localhost:8001/embed`) | 嵌入服务URL |
| `JIYI_EMBEDDING_SERVER_ENABLED` | `false` | 启动捆绑的BGE嵌入服务器 |
| `JIYI_EMBEDDING_SERVER_PORT` | `8001` | 捆绑嵌入服务器的端口 |
| `JIYI_EMBEDDING_MODEL_REPO` | `BAAI/bge-base-en-v1.5` | HuggingFace模型仓库 |
| `JIYI_MCP_TRANSPORT` | `stdio` | MCP传输:`stdio`或`streamable_http` |
| `JIYI_MCP_HTTP_PORT` | `4001` | 启用时的专用MCP流式HTTP端口 |
## 身份验证
记忆支持三种凭证类型:
1. **共享管理员令牌**(`JIYI_API_TOKEN`)— 完全访问;可以断言任何`trust_tier`,包括`human_asserted`。
2. **每代理API密钥** — 存储在`agent_keys`中;与一个`agent_id`加密绑定;上限为`agent_derived`信任层级。
3. **MCP会话令牌** — 通过`POST /auth/mcp-token`颁发的短时(5分钟)令牌;上限为`agent_derived`信任层级。
## 运行
```bash
mix run --no-halt
```
HTTP端点:
- `POST /context/assemble` – 正文:`agent_id`,`session_id`,`task`,可选`org_id`,`token_budget`和`memory_scopes`。
- `POST /memory/write` – 正文:`type`,`agent_id`,`content`,`provenance`,`scope`,可选`session_id`和`org_id`。
- `POST /auth/mcp-token` – 正文:`agent_id`,可选`org_id`。为MCP工具颁发短时会话令牌。
所有HTTP端点都需要`Authorization: Bearer <token>`。令牌可以是共享的管理员令牌或每代理API密钥。
## 记忆范围
可见性在查询时根据调用者的身份而不是写入者的声明范围得出:
- `agent_private` – 当`agent_id`与调用者匹配时可见。
- `session_shared` – 当`session_id`与调用者的会话(任何代理在会话中)匹配时可见。
- `org_shared` – 当`org_id`与调用者的组织匹配时可见。
## 信任层级和隔离区
每个记忆写入在`provenance`中携带一个`trust_tier`:
- `human_asserted` – 最高的信任;只有共享的管理员令牌才能声称这一点。
- `agent_derived` – 每代理密钥和MCP会话令牌的上限信任。
- `external_untrusted` – 始终路由到隔离区进行审查。
内容还会在写入时和上下文组装时扫描异常/指令样短语。命中被路由到`Quarantine`而不是实时记忆表。
## 检索排名
`context/assemble`通过以下方式对候选者进行排名:
```
base_score(trust_tier) × recency_multiplier × relevance_multiplier
```
- 默认情况下,`working`记忆和`procedural`剧本优先级较高。
- 衰减使用指数衰减,带有可配置的半衰期(默认8小时)。
- 相关性来自PostgreSQL全文排名,索引内容。
## 测试
```bash
# 运行套件(需要配置的测试数据库)
mix test
# 快速运行测试子集(仍需要测试数据库)
mix test test/jiyi_test.exs test/jiyi/api/router_test.exs test/jiyi/retrieval_test.exs
```
## 扩展MCP提供者
记忆默认使用Anubis进行客户端MCP适配器和服务器端MCP服务器,但双方都是抽象的,因此可以在不更改业务逻辑的情况下添加新的提供者。
1. **服务器端**:使用新框架的`use`宏创建`lib/jiyi/api/mcp_server_<provider>.ex`。公开两个工具(`context_assemble`和`memory_write`),其执行处理程序委托给`Jiyi.MCP.Tools.context_assemble/1`和`Jiyi.MCP.Tools.memory_write/1`,带有字符串键入的参数映射。
2. **客户端**:创建`lib/jiyi/agent/mcp/<provider>_adapter.ex`,实现`@behaviour Jiyi.Agent.MCP.Adapter`。将特定于框架的`start_link`、`await_ready`、`call_tool`和传输构建代码移动到那里。
3. **连接**:在启动记忆时设置环境变量:
```bash
export JIYI_MCP_SERVER_MODULE=Jiyi.API.MCPServerMyProvider
export JIYI_MCP_CLIENT_ADAPTER=Jiyi.Agent.MCP.MyProviderAdapter
```
无需更改现有模块。
## 架构
参见`TASK.md`了解实现阶段,参见`AGENTS.md`了解贡献者/代理约定。