内容
# 节省内存
**面向 AI 智能体团队的成本优先内存。** (npm: [`thrift-memory`](https://www.npmjs.com/package/thrift-memory))
> 不隶属于 [Apache Thrift](https://thrift.apache.org/),该 RPC 框架。
> 这是 MCP(多智能体协作平台)的一个内存层,用于 AI 智能体。
节省内存为支持 MCP 的智能体提供了一个小型共享内存层,优化了成本可见性:以低成本存储记忆,仅在硬币预算下回忆相关部分,并为每次回忆记录收据。
```text
savedTokens = baselineTokens - injectedTokens
```
目标是实用的:帮助智能体团队停止为每次运行重新加载相同的广泛上下文而付费。
> 状态:早期 `0.0.x`。API 已实用但仍允许在 `v0.1` 之前更改。
>
## 功能
节省内存有三个方面:
| 方面 | 目的 |
| --- | --- |
| MCP 服务器 | 智能体内存工具:`remember`、`recall`、`search_memory` |
| 本地仪表盘 | 由 meter JSONL 支持的节省 UI,以及所有者控制(固定/禁用,预算,终止开关) |
| 代理 | 可选的 HTTP 网关,修剪实时 LLM 请求并重试速率限制 |
明确划分:
- **MCP 管理内存回忆和代币收据。**
- **`thrift-proxy` 管理实时请求修剪和速率限制重试。**
## 比较
成熟的内存层 — [Mem0](https://github.com/mem0ai/mem0)、[Zep](https://www.getzep.com/)、[Letta](https://www.letta.com/)、[Cognee](https://www.cognee.ai/) — 优化**回忆质量**:LLM 丰富的写入、时间或实体知识图、深度个性化。它们在这些方面非常出色,并且比这个项目更成熟。节省内存并不试图在回忆深度上击败它们。
节省内存优化了一个不同的轴:**成本,本地,具有证明。** 权衡:
| | 节省内存 | 质量优先层(Mem0 / Zep / Letta / Cognee) |
| --- | --- | --- |
| 主要目标 | 削减并**证明**代币成本(预算 + 节省收据) | 最大化回忆质量/推理 |
| 写路径 | 便宜 — 无强制 LLM 丰富 | 通常在写入时进行 LLM 提取/嵌入 |
| 安装 | `npx thrift-memory` — 一个依赖,本地 JSONL,**无 API 密钥,无 DB,无 Docker** | 通常是 LLM 密钥 + 矢量/图数据库(例如 Mem0 自托管:API + Postgres/pgvector + Neo4j) |
| 仪表盘 | **代币节省表** + 所有者控制,本地和读写 | 内存/智能体管理 UI(几个有;目的不同) |
| 回忆深度 | 在硬币预算下范围匹配 | 知识图/时间/语义排名 |
| 成熟度 | 早期 `0.0.x` | 生产级,广泛采用 |
诚实总结:如果您需要最智能的回忆,请使用其他方法。如果您运行一个**智能体群**,并且不断为重新加载广泛的上下文而付费,并且希望**衡量和限制这种成本**,而无需额外的基础设施,那么节省内存就是为您准备的。两者并非相互排斥 — 节省内存可以作为预算/计量层位于更重的存储前面。
## MCP 工具
```text
remember(scope, text, agentId?, sessionId?, tags?)
在组织、智能体或会话范围内存储记忆。
recall(agentId, tokenBudget, task?, tags?)
在硬币预算下返回相关记忆。
还返回 { injectedTokens, baselineTokens, savedTokens }。
search_memory(agentId, task?, tags?, limit?)
浏览匹配的记忆而不应用小回忆预算。
```
## 快速入门
```bash
npm install -g thrift-memory
```
将节省内存添加到支持 MCP 的客户端:
```json
{
"mcpServers": {
"thrift": {
"command": "npx",
"args": ["thrift-memory"]
}
}
}
```
或直接运行 MCP 服务器:
```bash
npx thrift-memory \
--store-path=~/.thrift/memories.jsonl \
--meter-path=~/.thrift/meter.jsonl \
--default-budget=2000
```
## 60 秒演示
无需智能体 — 使用库证明 `remember → recall → receipt` 环路。保存为 `demo.mjs`,然后在 `npm install thrift-memory` 后运行 `node demo.mjs`:
```js
import { JsonlStore, ScopedRetriever } from "thrift-memory";
const store = new JsonlStore({ path: "./demo.jsonl" });
const now = Date.now();
// 1. remember — 存储一些组织记忆(便宜,无 LLM 丰富)
store.add({ scope: "org", text: "所有货币价值都存储为整数分,而不是浮点数。" }, now);
store.add({ scope: "org", text: "我们仅在绿色 CI 上部署;不进行周五晚上发布。" }, now);
store.add({ scope: "org", text: "Postgres 是记录系统;Redis 仅限缓存。" }, now);
// 2. recall — 在硬币预算下仅加载任务所需的内容
const r = new ScopedRetriever().recall(store, {
agentId: "dev",
task: "我应该如何存储货币价值?",
tokenBudget: 40,
});
// 3. 收据
for (const m of r.memories) console.log("•", m.text);
console.log(`注入 ${r.injectedTokens} / 基线 ${r.baselineTokens}(节省 ${r.savedTokens})`);
```
```text
• 所有货币价值都存储为整数分,而不是浮点数。
注入 15 / 基线 43(节省 28)
```
只有相关记忆被注入 — 部署节奏和 Postgres 注释被丢弃,因为它们与任务不匹配,而不仅仅是因为预算(`recall` 应用相关性下限)。该差距,即 `baseline - injected`,正是您每次运行停止支付的费用。这里的相关性是词汇重叠,因此请使用记忆实际使用的词语来表达任务;空结果意味着范围内没有任何内容相关 — 这是诚实的答案,而不是噪音来填充预算。
## 仪表盘
可选仪表盘是本地的。它显示节省内存是否真正节省了代币,以及(从 0.0.3 开始)为所有者控制提供了小写入界面 — 固定/禁用记忆、设置每个智能体的预算、静音智能体和整个舰队的终止开关 — 通过本地 `POST`/`DELETE` 端点提供。相同的控制也可在 `thrift-panel` CLI 上用。
```bash
npx thrift-panel serve \
--store-path=~/.thrift/memories.jsonl \
--meter-path=~/.thrift/meter.jsonl \
--control-path=~/.thrift/control.json \
--port=8585
```
打开 `http://127.0.0.1:8585`。

仪表盘显示:
| 视图 | 证明内容 |
| --- | --- |
| 舰队总结 | 总基线、注入、节省代币和节省率 |
| 每日代币流 | 节省是否在实际天数内持续 |
| 智能体节省 | 哪些智能体昂贵,哪些节省最多 |
| 最近收据 | 最新计量的回忆/代理事件 |
| 审计路径 | 支持数字的本地文件 |
CLI 等价项:
```bash
npx thrift-panel summary --store-path=~/.thrift/memories.jsonl --meter-path=~/.thrift/meter.jsonl
npx thrift-panel agents --store-path=~/.thrift/memories.jsonl --meter-path=~/.thrift/meter.jsonl
npx thrift-panel memories --store-path=~/.thrift/memories.jsonl --scope=org
```
## 衡量性能
每次 `recall` 在配置了计量路径时都会写入收据到 `THRIFT_METER_PATH`:
```json
{"at":1760000000000,"agentId":"dev","injectedTokens":420,"baselineTokens":2100,"savedTokens":1680}
```
定义:
| 字段 | 含义 |
| --- | --- |
| `baselineTokens` | 无节省内存的反事实:所有加载的范围记忆 |
| `injectedTokens` | 节省内存实际返回的切片 |
| `savedTokens` | `baselineTokens - injectedTokens` |
| 节省率 | `savedTokens / baselineTokens` |
推荐的衡量循环:
1. 从自己的 markdown 文件中播种记忆或使用 `remember`。
2. 让实际智能体在正常工作期间调用 `recall`。
3. 查看 `thrift-panel summary` 和 `thrift-panel agents`。
4. 通过将任务结果与完整记忆与节省内存回忆进行比较,单独验证质量。
对于可信的公开报告,发布代币减少和质量证据。例如:“在 200 次实际回忆中节省了 72% 的记忆代币,20 个配对任务中有 19 个产生相同的结果。”
> **考虑 MCP 开销。** 注册任何 MCP 服务器都会在其上下文中为每个智能体添加工具模式负载(通常为几千个代币)。诚实的数字是**净值**:`savings = recall reduction − MCP schema/tool-call overhead`。在上下文繁重的智能体上,通常回忆会以很大的优势获胜 — 但在使用自己的工作负载进行计量之前,请先确认,然后再进行整个舰队的部署,而不是假设。收据的存在正是为了让您不必进行猜测。
## 合成基准
此存储库包含一个小的合成夹具,用户可以在不使用任何私有数据的情况下验证测量管道:
```bash
npm run build
node benchmark/run.mjs
```
它读取:
- `benchmark/fixtures/memories.jsonl`
- `benchmark/fixtures/meter.jsonl`
参见 [docs/case-study.md](./docs/case-study.md) 以获取有关如何解释数字的清理示例。
## 代理和速率限制
代理是可选的。当智能体可以将 LLM `base_url` 指向本地 HTTP 网关时使用。
> **安全性 — 仅在本地运行。** 代理将您的真实提供商 API 密钥不变地转发上游。它默认绑定到 `127.0.0.1`(在代码中强制执行,而不仅仅是文档),因此除非您故意选择 `--host=0.0.0.0` / `THRIFT_PROXY_HOST`,否则无法从主机访问它。切勿在公共接口上公开它或共享端口。它是一个单租户开发工具,而不是一个强化多租户网关。响应也被缓冲,因此 SSE 流尚未通过。
```bash
npx thrift-proxy \
--upstream=https://api.anthropic.com \
--host=127.0.0.1 \
--port=8787 \
--budget=4000 \
--meter-path=~/.thrift/meter.jsonl
```
然后将智能体的 LLM 基本 URL 配置为 `http://localhost:8787` 并继续使用真实提供商 API 密钥。
代理:
- 在硬币预算下修剪实时请求上下文,
- 编写与 MCP 接口相同的节省收据,
- 重试上游 `429` 和 `503 Retry-After` 响应,
- 按提供商限制并发上游请求。
速率限制默认值:
| 设置 | 默认值 | 环境变量 |
| --- | ---: | --- |
| 最大并发 | `5` | `THRIFT_MAX_CONCURRENCY` |
| 最大重试次数 | `5` | `THRIFT_MAX_RETRIES` |
| 回退基准 | `1000ms` | `THRIFT_BACKOFF_BASE_MS` |
| 最大回退 | `60000ms` | `THRIFT_MAX_BACKOFF_MS` |
`thrift-proxy` 在此版本中缓冲响应;流式传递是未来的改进。
## 导入现有记忆
导入脚本是通用且仅限本地的。它可以将 markdown 文件导入 JSONL 存储:
```bash
node scripts/import-memories.mjs \
--source=./memory \
--scope=org \
--store-path=~/.thrift/memories.jsonl \
--dry-run
```
对于智能体范围的记忆,将 markdown 文件放在项目目录下并使用 `--scope=agent`:
```text
memory/
checkout-service/
dev.md
qa.md
docs-site/
writer.md
```
```bash
node scripts/import-memories.mjs --source=./memory --scope=agent
```
## 库使用
```ts
import { JsonlStore, ScopedRetriever, InMemoryMeter, ThriftMcpServer } from "thrift-memory";
const server = new ThriftMcpServer({
store: new JsonlStore({ path: "./memories.jsonl" }),
retriever: new ScopedRetriever(),
meter: new InMemoryMeter(),
defaultTokenBudget: 2000,
});
await server.runStdio();
```
## 开发
```bash
npm install
npm run typecheck
npm run build
npm test
```
## 布局
| 路径 | 目的 |
| --- | --- |
| `src/mcp/` | MCP 标准输入/输出服务器和工具定义 |
| `src/store/` | JSONL 内存存储 |
| `src/retrieval/` | 范围预算有界回忆 |
| `src/meter/` | 代币计量和汇总 |
| `src/control/` | CLI 和本地仪表盘 |
| `src/proxy/` | HTTP 代理,上下文修剪,速率限制重试 |
| `benchmark/fixtures/` | 合成公共基准数据 |
| `docs/` | 公共文档,截图,清理案例研究 |
| `test/` | 单元和集成测试 |
## 许可证
[Apache-2.0](./LICENSE)