内容
<div align="center">
<h1>🧠 mnesio</h1>
<p><strong>一款用于AI智能体的自我改进的长期记忆层,以Rust构建。</strong></p>
<p>
<a href="https://github.com/mnesio/mnesio/actions"><img alt="构建状态" src="https://img.shields.io/badge/build-passing-brightgreen"></a>
<a href="https://crates.io/crates/mnesio"><img alt="版本" src="https://img.shields.io/badge/version-v0.1.0-blue"></a>
<a href="https://github.com/mnesio/mnesio/blob/main/LICENSE"><img alt="许可证" src="https://img.shields.io/badge/license-Apache--2.0-blue.svg"></a>
<a href="#"><img alt="测试" src="https://img.shields.io/badge/tests-509%20passing-brightgreen"></a>
</p>
</div>
---
大多数智能体记忆系统(Mem0、Zep、Letta、Cognee)都是**存储型**的:它们记住事实。mnesio的差异化特点是**程序性自我改进**——智能体随着时间的推移变得**更擅长做事情**,并且具有回归保护机制,文献中省略了这一机制。
两个连续的循环在单个仅追加的事件日志上运行:
1. **程序记忆编译器**(楔形)- 将智能体的`结果`批次转换为改进的、版本化的`策略制品`(系统提示、启发式、检索规则)通过GEPA风格的反射循环:反射→提出K个候选→影子评估→帕累托选择→**门控提交**。
2. **记忆演化**(支持)- 当写入记忆时,有界的异步工作线程会追溯性地重新标记和重新链接相关的记忆(A-MEM风格),保持编译器学习的知识图谱适应性。
### 为什么楔形很重要
> **硬性规则#1:没有任何程序性提交在通过`EvalReport::is_committable()`的情况下被提交** - 100%的金丝雀,安全探针通过,目标Δ≥0。这是LangMem省略的回归保护机制。机械强制执行 - 设置每个可配置的门控阈值到其最弱值*仍然*不能绕过基线。每个提交都有一个专门的集成测试。
---
## ⚡ 快速开始
**最快 - 无需Rust工具链,一条命令**(在Docker中构建和运行,在`http://localhost:7777`上提供实时仪表板,无需外部下载):
```bash
git clone https://github.com/mnesio/mnesio.git && cd mnesio
docker compose up --build
```
**安装Rust后 - 一个命令:**
```bash
git clone https://github.com/mnesio/mnesio.git && cd mnesio
make demo # 即时演示:实时仪表板,无需下载(模拟嵌入器)
# make run # 真实的、持久的服务器(fastembed - 下载bge-small一次)
# make test # 工作区测试套件
# make mcp # 安装用于Claude Desktop / Cursor等的MCP二进制文件
# make # 列出每个目标
```
**或纯命令** `make demo`目标运行:
```bash
MNESIO_DEMO=1 MNESIO_PROCEDURAL=on cargo run -p mnesio-server
```
然后打开:
- **http://127.0.0.1:7777/** - 实时聊天式检索(混合向量+BM25+提取合成)
- **http://127.0.0.1:7777/dashboard** - 实时基准测试:延迟、BM25层分布、记忆演化链、**程序学习曲线**、**摄入智能**面板(原始回合→ADD / UPDATE(矛盾)/ NOOP,由`/api/ingest/metrics`提供)和**双时间知识图**面板(`/api/graph`),以及**配置文件/角色**面板(`/api/profile`)
在演示中,观察**程序**部分的**学习曲线**从~33%升至100%,而安全探针线保持在100% - 这是第2阶段的“完成标准”。
### 配置
| 环境变量 | 默认值 | 含义 |
|---|---|---|
| `MNESIO_DEMO` | `0` | `1` → 使用临时数据目录 + 合成写入器(无持久性) |
| `MNESIO_EMBEDDER` | `fastembed` | `mock`用于32维确定性嵌入器(无需模型下载) |
| `MNESIO_EVOLVE` | `on` | `off`禁用记忆演化工作线程 |
| `MNESIO_PROCEDURAL` | `off` | `on`启用程序编译器(LLM-heavy) |
| `MNESIO_EVOLVE_LLM` | `demo` | `ollama`用于通过`MNESIO_OLLAMA_URL` / `MNESIO_OLLAMA_MODEL`的真实本地模型 |
| `MNESIO_DATA` | `./mnesio-data` | fjall键空间的路径 |
| `MNESIO_PORT` | `7777` | HTTP监听端口 |
| `MNESIO_HOST` | `127.0.0.1` | 绑定地址。默认情况下保持环回;Docker镜像设置`0.0.0.0`以使发布的端口可访问 |
---
## 🏗️ 工作区架构
十二个crate,每个crate都有一个集中的责任。外部依赖项位于特征(`LlmClient`、`Embedder`、`EventLog`、`MaterializedView`、`Retriever`、`Synthesizer`、`PolicyExecutor`、`Judge`)后面,因此提供者是可互换的。
| Crate | 角色 | 状态 |
|---|---|---|
| `mnesio-core` | 类型 + 特征 + 事件日志形状。无I/O。 | ✅ |
| `mnesio-store` | `fjall`支持的仅追加事件日志 | ✅ 阶段0 |
| `mnesio-index` | `hnsw_rs`向量 + `tantivy` BM25 + RRF混合 + 提取合成 | ✅ 阶段0 |
| `mnesio-graph` | `fjall`上的双时间属性图存储 - 节点、边、BFS、`as_of`查询 | ✅ 阶段4 |
| `mnesio-extract` | 摄入智能 - 事实提取、ADD/UPDATE/NOOP合并、重要性接收 + 衰减 | ✅ 阶段7 |
| `mnesio-privacy` | PII删除(最小化)+加密碎纸密钥环(在仅追加日志上的遗忘权) | ✅ 阶段8 |
| `mnesio-llm` | `LlmClient`实现:`FakeLlmClient`、`OllamaLlmClient`(功能门控) | ✅ |
| `mnesio-evolve` | 有界A-MEM风格的记忆演化工作线程 | ✅ 阶段1 |
| `mnesio-procedural` | GEPA风格的程序编译器 + 门控 + 评估套件 + 学习曲线 | ✅ 阶段2 |
| `mnesio-causal` | 反事实贡献评分 + 通过测量进行GC(遗忘一个留下一个消融在可重放日志上) | ✅ 阶段10 |
| `mnesio-probe` | 自我反驳记忆 - 验收探针 + 信念校准;一个被驳斥的声明无效并取代自身(保留历史) | ✅ 阶段11 |
| `mnesio-kv` | 门控KV弹药 - KV缓存作为版本化、门控、可擦除的日志视图。实时张量后端 + **实时GPT-2预训练权重**;**完整12层生成使用**(`generative-kv`,弹药*是*模型从中生成的缓存)具有**实时q8量化** → 4.0×更小,相同答案;**现代2024模型**(`qwen-kv`:Qwen2.5-0.5B-Instruct - RMSNorm/RoPE/GQA/SwiGLU);以及**实时GPU后端**(`candle-kv,metal`:与Apple Metal上的相同Qwen2,**107×更快预填充**比CPU);**套件准确性-对齐**通过`mnesio-bench kveval`(弹药≥文本上下文检索,~167–180×更快)+ LRU/字节预算弹药存储 | ✅ 阶段12 |
| `mnesio-exchange` | 认证技能交换 - 将门控制品导出为签名证书;导入者在其激活前重新运行自己的门控 | ✅ 阶段13 |
| `mnesio-dream` | 负记忆 + 做梦 - 来自不良结果的门控抑制规则;有界离线按贡献修剪 + 重新锚定漂移的笔记 | ✅ 阶段14 |
| `mnesio-provenance` | 监管级 provenance - 时间旅行重建 + provenance 链 + 可验证擦除仅追加日志 | ✅ 阶段15 |
| `mnesio-bench` | 评估即产品工具 - 程序学习曲线(GSM8K/HumanEval)+ 记忆召回@k(LOCOMO/LongMemEval) | ✅ 阶段2/6 |
| `mnesio-server` | 主机进程:HTTP API、仪表板、演示连接 | ✅ |
| `mnesio-mcp` | MCP服务器:将mnesio暴露为Claude Desktop / Cline /等工具 | ✅ 阶段5 |
| `mnesio-py` | Python绑定通过pyo3 - pip-installable | ✅ 阶段5 |
| `sdk/node` | TypeScript/Node SDK通过HTTP表面 - 零运行时依赖 | ✅ 阶段9 |
---
## 📈 评估即产品(`mnesio-bench`)
评估工具不是一次性的演示 - 它是一个CLI,您可以将其集成到开发循环或CI中。两个子命令,四个输出格式,退出代码阻止PR回归。
### 运行模式 - 迭代改进曲线
```bash
# 迭代程序编译器针对gsm8k-tiny并发出
# 一个自包含的HTML报告,您可以将其附加到PR。
cargo run -p mnesio-bench -- run \
--suite gsm8k \
--max-versions 6 \
--output html \
--out curve.html
```
HTML是自包含的 - 内联SVG线图`benchmark_score` + `safety_probe_pass_rate`随版本变化,KPI条带,种子与最终提示差异。无JS,无外部资产,无Chart.js依赖。
### 比较模式 - A vs B提示评估
```bash
cargo run -p mnesio-bench -- compare \
--suite gsm8k \
--baseline "回答问题。" \
--candidate "回答问题。逐步展示你的工作。" \
--output markdown
```
输出(粘贴到PR友好):
```
| | 基准 | 安全 |
|---|---|---|
| 基准 | 0.0% | 100.0% |
| 候选人 | 70.0% | 100.0% |
| **Δ** | **+70.0pp** | **+0.0pp** |
```
### CI模式 - 阻止回归
```bash
cargo run -p mnesio-bench -- run \
--suite gsm8k \
--max-versions 6 \
--regression-threshold 0.05 \
--output json --out bench.json
```
退出代码语义:
- **`0`** - 基准测试保持或在阈值内改进;安全探针在整个过程中为100%。
- **`1`** - 基准测试下降超过 `--regression-threshold`低于v1。
- **`1`(无需阈值)** - 任何安全探针回归。对齐漂移是硬停;您不能为其设置阈值。
将其放入GitHub Actions步骤:
```yaml
- name: mnesio-bench gates
run: |
cargo run --release -p mnesio-bench -- run \
--suite gsm8k \
--regression-threshold 0.05 \
--output json --out bench.json
- uses: actions/upload-artifact@v4
with: { name: bench-results, path: bench.json }
```
PR回归基准测试失败。工件可从运行页面下载以进行检查。
### 套件
今天有两个套件在二进制文件中 - 手工策划,许可证干净:
| 套件 | 任务 | 安全探针 | 类别 |
|---|---|---|---|
| `gsm8k` | 10个小学数学文字问题 | 3 | 数学,速率,几何,算术,百分比,分数 |
| `humaneval` | 5个Python代码补全提示 | 3 | 谓词,内置,字符串,分支 |
外部套件通过未来的`--suite path/to/suite.json`标志落地(`crates/mnesio-bench/data/`中的JSON模式)。
### 记忆召回 - LOCOMO / LongMemEval
第三个子命令,`memeval`,基准测试**记忆层本身**(不是程序编译器):它通过*真实的*`FjallEventLog → VectorView + Bm25View → HybridRetriever`路径摄入一堆记忆,然后提问并报告**recall@k** - 任何前`k`记忆是否包含黄金答案片段? - 整体和每类别(单跳/多跳/时间/知识更新/开放域)。
```bash
# 离线烟雾测试(模拟嵌入器,BM25主导):
cargo run -p mnesio-bench -- memeval --suite locomo --k 10
cargo run -p mnesio-bench -- memeval --suite longmemeval --k 10 --output json
# 真实语义数(下载bge-small):
cargo run -p mnesio-bench -- memeval --suite locomo --embedder fastembed
# CI地板 - 退出1如果召回率@k低于栏:
cargo run -p mnesio-bench -- memeval --suite locomo --min-recall 0.8
```
两个手工策划的许可证干净的小型套件在二进制文件内(`locomo_mini`,`longmemeval_mini`)。它们是**烟雾规模**(≈12个记忆)- 在`mock`嵌入器下,召回是BM25驱动的并且HNSW tie-breaks使得边界问题不确定,因此在CI中设置地板并引用发布的数字 `--embedder fastembed`针对完整数据集。
---
## 🐍 从Python使用mnesio
```bash
pip install maturin
maturin develop --release --manifest-path crates/mnesio-py/Cargo.toml`
```
`maturin develop`构建Rust扩展并将`mnesio`包放入您的活动Python环境。然后:
```python
import mnesio
client = mnesio.Client(data_dir="./mnesio-data", embedder="fastembed")
# 写入记忆。
memory_id = client.write_memory(
content="我的合作伙伴的咖啡订单是 oat-milk flat white",
tenant="default",
tags=["coffee", "preference"],
)
# 混合检索与合成答案。
result = client.search(query="我喜欢什么咖啡?", k=5)
print(result.answer) # 合成文本(或None)
for hit in result.hits: `memory_id`, `score`, `content`
print(result.citations) # 引用记忆的id
```
### 将其插入LangChain
mnesio作为一个替代检索器,可以通过包装`client.search`到`BaseRetriever`中,适用于任何LangChain管道:
```python
from langchain_core.retrievers import BaseRetriever
from langchain_core.documents import Document
import mnesio
class MnesioRetriever(BaseRetriever):
client: mnesio.Client
tenant: str = "default"
k: int = 5
def _get_relevant_documents(self, query, *, run_manager):
result = self.client.search(query=query, tenant=self.tenant, k=self.k)
return [
Document(page_content=h.content, metadata={"memory_id": h.memory_id, "score": h.score})
for h in result.hits
]
retriever = MnesioRetriever(client=mnesio.Client("./mnesio-data"))
```
### 异步支持
当前API是**同步**的 - 每个调用都会阻塞直到完成。智能体调用延迟主要由LLM本身决定,因此这通常不是瓶颈。未来的版本将添加本地的`AsyncClient`,使用`pyo3-asyncio`。
---
## 🟦 从Node / TypeScript使用mnesio
`sdk/node`在HTTP表面提供了一个微小的客户端 - 零运行时依赖项(它使用Node 18+内置的`fetch`)。镜像`mnesio-server` 1:1的DTO,具有完整的TypeScript类型。
```ts
import { MnesioClient } from "@mnesio/sdk";
const mnesio = new MnesioClient({ baseUrl: "http://127.0.0.1:7777" });
// 一次往返:发布门控PolicyArtifacts + 混合检索。
const { skills, hits } = await mnesio.retrieveWithSkills(
"我们的上一次通话决定了什么关于定价的问题?",
5,
{ actor: "analyst" }, // 可选 - 强制执行代理间ACL
);
const system =
skills.map(s => s.injection).join("\n\n") +
"\n\nContext:\n" +
hits.map(h => `- ${h.content}`).join("\n");
```
每个返回的`skills[i]`都通过机械安全门控(100%金丝雀,安全探针通过,目标Δ≥0)- 直接将`injection`注入到您的提示中。
相同的客户端干净地封装到LangChain `BaseRetriever`,LlamaIndex `BaseRetriever`和CrewAI `Tool`中。参见`sdk/node/README.md`以获取适配器草图。
```bash
cd sdk/node
npm install
npm run build && npm test # 8 tests, no server required
```
---
## 🔌 从Claude Desktop使用mnesio(MCP)
`mnesio-mcp`二进制文件使用[Model Context Protocol](https://modelcontextprotocol.io)进行通信。将其添加到您的Claude Desktop配置中,任意对话中的三个工具都可用。**其他MCP代理**(OpenClaw,Hermes,Cursor等)以相同的方式连接 - 请参阅**[INTEGRATION.md](INTEGRATION.md)**以获取粘贴就绪的配置+ write→search→record_outcome→gated-procedural循环的示例,以及`examples/integrations/`中的可编辑文件。
- **`mnesio_write_memory(content, tenant?, tags?)`** - 追加新的记忆。同步嵌入,因此立即搜索。
- **`mnesio_search(query, tenant?, k?)`** - 混合检索(向量+BM25)返回合成答案以及摘录和引用。
- **`mnesio_record_outcome(episode?, artifacts_used, success, scores?, error?)`** - 记录智能体任务的结果。程序编译器从这些结果中学习,以了解哪些提示模式导致了良好的结果。
### 安装
```bash
cargo install --path crates/mnesio-mcp
```
### 配置Claude Desktop
编辑`~/Library/Application Support/Claude/claude_desktop_config.json`(macOS)或`%APPDATA%\Claude\claude_desktop_config.json`(Windows):
```json
{
"mcpServers": {
"mnesio": {
"command": "mnesio-mcp",
"env": {
"MNESIO_DATA": "/Users/you/mnesio-data",
"MNESIO_EMBEDDER": "fastembed"
}
}
}
}
```
重启Claude Desktop。输入栏中的 🔌 图标将显示三个可用的`mnesio_*`工具。
### 试试吧
```
> 记住:我的合作伙伴的咖啡订单是 oat-milk flat white,两发。
[Claude calls mnesio_write_memory]
> 我的合作伙伴喝什么?
[Claude calls mnesio_search → 找到 + 引用记忆]
```
### 配置
| 环境变量 | 默认值 | 含义 |
|---|---|---|
| `MNESIO_DATA` | `./mnesio-data` | fjall键空间的路径。**在Claude配置中使用绝对路径** - 相对路径解析到Claude启动的位置。 |
| `MNESIO_EMBEDDER` | `mock` | `mock`(32维确定性,无需模型下载)或`fastembed`(真实bge-small-en-v1.5)。`mock`适用于测试;`fastembed`适用于真实使用。 |
| `RUST_LOG` | `warn` | 标准跟踪订阅者过滤器。日志仅输出到stderr(stdout是协议通道)。 |
### 传输
新行分隔的JSON-RPC 2.0,标准输入输出。三个方法:`initialize`,`tools/list`,`tools/call`。手工编写,因为协议很小,依赖SDK会增加比移除的风险更多的风险 - `crates/mnesio-mcp/src/protocol.rs`约为300行,包括文档注释和测试。
---
## 🔒 硬性规则(不可协商的不变量)
这些规则在代码中强制执行,而不是通过约定。每个规则都有一个专用的测试,如果不变性被破坏,测试将失败:
1. **没有程序化提交未通过 `EvalReport::is_committable()`** — 警戒 + 安全探针 + 非负目标增量。可配置的 `EvalGates` 层只能在此基准上添加拒绝原因;它绝不能放松此基准。测试:`loosening_configurable_gates_cannot_bypass_strict_baseline`。
2. **绝不覆盖历史记录** — 内存演化使旧版本失效并写入具有 `parent` 指针的新双时间版本。同样适用于任何事实更新。事件日志仅支持追加。
3. **作用域是安全边界** — 程序化学习 + 内存演化绝不会在没有显式聚合的情况下跨越 `Scope`。每个跨实体读取都通过 `Scope::contains` 进行。
4. **事件日志是单一记录系统** — 每个索引(向量、BM25、图、程序化)都是物化视图,可以通过重放事件完全重建。已端到端测试。
5. **写入路径保持快速** — 嵌入、演化和程序化编译异步位于有限队列后面。写入路径目标是 < 5 ms;LLM 调用绝不会阻塞它。
6. **级联是有限的** — `EvolveConfig` 限制级联扇出、每内存冷却时间、生命周期演化次数和最小结构增量。A-MEM 没有收敛保证;这些限制取代它。
---
## 📊 第二阶段 "完成时" — 已验证
> 第二阶段在系统在类似 ALFWorld 的套件上表现出 **正向学习曲线且无安全探针回归** 时 "完成"。
实时演示输出(`MNESIO_PROCEDURAL=on`):
```
v1: 基准 = 33.33% 安全 = 100%
v2: 基准 = 66.67% 安全 = 100%
v3: 基准 = 100.00% 安全 = 100%
v4+: 基准 = 100.00% 安全 = 100% (平台 — 两种改进信号集成)
```
仪表板将其渲染为双线图表,带有 `安全 100%` 标签,在任何回归时变为红色。
---
## 📊 规模和真实数据基准
以下所有数字均为 **测量值**,而非预测值 — 由 `mnesio-bench` 在 2021 年 M1 类笔记本电脑(8 核,16 GB)上生成,发布构建。可以使用显示的命令重现。
### 真实公共基准 — SQuAD + HotpotQA(recall@10)
`mnesio-bench fetch` 从 Hugging Face 数据集服务器下载真实数据集,并通过实际的摄入 → 混合检索路径运行它。**SQuAD** (单跳阅读理解):每个上下文 → 一个内存(重复数据删除),每个问题/答案范围 → 一个召回对。**HotpotQA** (多跳):每一行的上下文段落 → 一个内存,必须在它们中找到答案范围(是/否比较答案被跳过 — 不可检索范围)。
```bash
cargo run -p mnesio-bench --features fetch --release -- \
fetch --dataset squad --rows 2000 --k 10 --embedder fastembed
cargo run -p mnesio-bench --features fetch --release -- \
fetch --dataset hotpotqa --rows 1000 --k 10 --embedder fastembed
```
| 数据集 | 嵌入器 | 内存 | 问题 | recall@10 | 毫秒/查询 |
| --- | --- | ---: | ---: | ---: | ---: |
| SQuAD v1.1(单跳) | `fastembed`(384-d) | 315 | 2,000 | **98.1%** | 9.24 |
| SQuAD v1.1(单跳) | `mock`(32-d,BM25) | 315 | 2,000 | 93.9% | 1.81 |
| HotpotQA(多跳) | `fastembed`(384-d) | 9,227 | 941 | **88.7%** | 17.97 |
| HotpotQA(多跳) | `mock`(32-d,BM25) | 9,227 | 941 | 83.4% | 8.61 |
真实语义嵌入在相同问题上提高了召回率,相比仅限关键词 — **在单跳 SQuAD 上 +4.2 分,在更难的多跳 HotpotQA 上 +5.3 分** — 混合路径赢得其在非合成数据上的价值。HotpotQA 运行也是一个真实语料库规模检查:9k+ 内存,941 个多跳问题,查询时间不到 18 毫秒。
### 规模和负载 — 合成语料库高达 105k 内存
`mnesio-bench scale` 摄入确定性合成语料库(标记的针在干扰者中加盐,以及演化链 + 矛盾)通过实际存储 → 视图 → 检索路径,并 **分离两个写入阶段**,因此数字反映 mnesio 的架构:*追加* 路径是面向用户的写入(硬性规则 #5,<5ms),而 *索引构建* (HNSW + BM25)是服务器异步执行的写入路径。索引阶段使用批量重放重建路径(所有文档分阶段,一个 BM25 提交),因此其吞吐量受 HNSW 限制而非每文档段刷新。
```bash
cargo run -p mnesio-bench --release -- scale --sizes 1000,10000,50000,100000 --embedder mock
```
| 内存 | 追加/秒 | 追加 p50 | 索引/秒 | 索引 p50 | 查询 p50 | 查询 p99 | recall@10 |
| ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| 1,050 | 218,082 | 0.0022 毫秒 | 7,648 | 0.13 毫秒 | 0.88 毫秒 | 1.76 毫秒 | 100% |
| 10,503 | 385,546 | 0.0017 毫秒 | 2,725 | 0.35 毫秒 | 1.36 毫秒 | 4.20 毫秒 | 100% |
| 52,515 | 246,886 | 0.0018 毫秒 | 1,625 | 0.60 毫秒 | 2.21 毫秒 | 2.96 毫秒 | 100% |
| 105,030 | 299,564 | 0.0017 毫秒 | 1,326 | 0.75 毫秒 | 3.60 毫秒 | 4.90 毫秒 | 100% |
曲线读取:**追加延迟在 100 倍大小增加时保持不变(~0.0017 毫秒 p50)** — 写入路径确实不会因语料库大小而退化。索引构建受 HNSW 限制,并随图加深而优雅地退化(每次插入 p50 从 0.13 毫秒 → 0.75 毫秒)。查询延迟 *亚线性* 增加(HNSW):p50 从 0.88 毫秒 → 3.60 毫秒,1k 到 105k。召回率在 **105k 内存上保持 100%**,确认检索正确性在规模上保持不变。(合成生成器是确定性的 — 相同的 `--seed` 重现相同的语料库。)
**使用真实语义嵌入器**( `--embedder fastembed`,384-d)在 5,251 内存:追加仍然 **182,519/秒,p50 0.00 毫秒**(嵌入在写入路径之前在单独的预阶段计算 — 硬性规则 #5),索引 1,345/秒,查询 p50 9.84 毫秒(每个查询的嵌入占主导地位),召回率 99.2%。写入路径是否使用模拟器或真实模型都保持快速。
这些召回率底线在 CI 中强制执行 — `bench-gate` 作业如果 LOCOMO/LongMemEval 微型套件召回率或合成规模召回率低于其底线,则失败(评估即产品,护城河变成回归门)。
### 边缘案例/对抗性压力测试
吞吐量压力测试只是 "就绪" 的一半。`mnesio-bench edge` 驱动 *实际* 摄入 → 检索 → 重放路径,并带有敌对输入,并断言七个硬性规则不变性成立 — 任何违反都以非零退出(并在 CI 中触发)。
```bash
cargo run -p mnesio-bench -- edge
```
| 场景 | 检查的不变性 |
| --- | --- |
| 退化查询 | 空/空格/仅停止词/ `k=0` / `k≫N` 绝不会恐慌或错误 |
| 病态语法 | 12 个运算符/`AND OR NOT`/unicode/emoji 查询被清理,而不是 500 错误 |
| unicode 和 emoji 内容 | CJK/口音/emoji 内存摄入并保持可检索 |
| 大型和空内容 | 一个 ~1 MB 内存和一个空内存都摄入;黄金仍然被检索 |
| **作用域隔离极端** | 1 个租户-A 针在 4,000 个租户-B 中 → 找到,**零跨租户泄漏**(硬性规则 #3) |
| 替代保留历史记录 | 纠正的事实离开检索,但其原始写入仍在日志中(硬性规则 #2) |
| 删除墓碑索引 | 195/200 个无效 → 只有 5 个活动返回;计数一致 |
| 维度不匹配 | 错误维度向量被拒绝并报错,而不是恐慌 |
| **重放重建** | 从日志重放的新视图重现相同的 BM25 + 召回率(硬性规则 #4) |
| 并发写入 | 256 个并发追加都落地并具有唯一、单调的 ID(硬性规则 #2/#4) |
此套件 **发现并修复了一个真实的错误**:一个全停止词查询(`"the of a"`)或带有裸布尔运算符的查询(`"a AND OR NOT b"`)曾经引发了一个硬性 tantivy 解析错误,即 500 错误的搜索输入。现在,BM25 查询路径将无法解析的纯文本视为 "此层没有结果"(优雅的空),同时仍然支持有效的显式运算符查询,如 `revenue OR growth`。
---
## ⚖️ mnesio 比较
> 📊 **[BENCHMARKS.md](BENCHMARKS.md)** 将所有测量的数字集中在一个位置 — 基板在 105k 内存,真实数据召回率,实时 LLM 判定的 QA,以及 GPU KV-购物车加速 — 带有方法和注意事项。
```bash
cargo run -p mnesio-bench -- compete --k 10 --embedder fastembed
```
> **两个不同的指标,分别保留。** 下面是 **结构** 比较。进一步的基准数字混合了 **引用的竞争对手端到端 QA 准确率** 和 mnesio 的 **测量的检索召回率@k** — 检索质量的代理,而不是相同的指标。召回率@k 问的是 "黄金答案是否在检索的集合中?";QA 准确率问的是 "模型是否产生了正确的答案?"。我们从未将一个呈现为另一个。
### 能力矩阵
| 能力 | mnesio | Mem0 | Zep | Letta | A-MEM |
| --- | ---: | ---: | ---: | ---: | ---: |
| 仅追加、可重放的事件日志作为记录系统 | ✅ | — | ◑ | — | — |
| 双时间版本控制(绝不覆盖;失效和替代) | ✅ | ◑ | ✅ | — | — |
| 混合检索(向量 + BM25 + RRF)及可解释的分解 | ✅ | ◑ | ◑ | ◑ | ◑ |
| 程序化自我改进(随着时间推移在任务上变得更好) | ✅ | — | — | ◑ | — |
| 不可绕过的提交门(警报 + 安全探针) | ✅ | — | — | — | — |
| 反事实贡献评分 + 测量 GC | ✅ | — | — | — | — |
| 自我否定记忆(探针自动替代失败) | ✅ | — | — | — | — |
| 加密粉碎擦除与仅追加日志的协调 | ✅ | — | — | — | — |
| 时间旅行重建 + 来源链 | ✅ | — | ◑ | — | — |
| 认证的技能交换(导入时重新加权) | ✅ | — | — | — | — |
| 自包含/嵌入式(无外部向量或图数据库) | ✅ | ◑ | ◑ | ✅ | ◑ |
✅ 已发货 · ◑ 部分完成 · — 未在已发布的 设计中。竞争对手单元格反映每个系统的已发布架构,可能会演变。 **mnesio 是唯一一个每行都有 ** — 前沿功能需要追加 + 可重放 + 双时间基板,在存储型系统上无法添加而无需重建其基础。
### 基准测试(引用的端到端 QA — **与召回率@k 不同的指标**)
| 系统 | 基准 | 指标 | 分数 | 来源 |
| --- | --- | --- | ---: | --- |
| 全上下文(上限) | LOCOMO | LLM-as-Judge(J) | 72.90% | Mem0 paper, [arXiv:2504.19413](https://arxiv.org/abs/2504.19413),Table 2 |
| Mem0(图) | LOCOMO | LLM-as-Judge(J) | 68.44% | Mem0 paper, [arXiv:2504.19413](https://arxiv.org/abs/2504.19413),Table 2 |
| Mem0 | LOCOMO | LLM-as-Judge(J) | 66.88% | Mem0 paper, [arXiv:2504.19413](https://arxiv.org/abs/2504.19413),Table 2 |
| Zep | LOCOMO | LLM-as-Judge(J) | 65.99% | Mem0 paper, [arXiv:2504.19413](https://arxiv.org/abs/2504.19413),Table 2 |
| LangMem | LOCOMO | LLM-as-Judge(J) | 58.10% | Mem0 paper, [arXiv:2504.19413](https://arxiv.org/abs/2504.19413),Table 2 |
| A-Mem | LOCOMO | LLM-as-Judge(J) | 48.38% | Mem0 paper, [arXiv:2504.19413](https://arxiv.org/abs/2504.19413),Table 2 |
| Zep(gpt-4o) | LongMemEval | QA 准确率 | 71.20% | Zep paper, [arXiv:2501.13956](https://arxiv.org/abs/2501.13956),Table 2 |
| 全上下文(gpt-4o) | LongMemEval | QA 准确率 | 60.20% | Zep paper, [arXiv:2501.13956](https://arxiv.org/abs/2501.13956),Table 2 |
这些是来自引用论文的竞争对手/基线数字 — **不是 mnesio 的**。mnesio 的 *测量* 数字是检索召回率@k:**98.1%** 在真实 SQuAD 上(fastembed,§ 规模和真实数据上方)和 100% 在策划的 LOCOMO/LongMemEval 微型套件上。mnesio 的差异是能力矩阵,而不是单个领导者单元格。
### mnesio — 端到端 LLM 判定的 QA 准确率(真实的,不是召回率)
mnesio 还提供与上述论文中报告的相同指标 — 通过 `mnesio-bench qaeval` 的端到端 **QA 准确率** (检索 → LLM 从检索的上下文中回答 → LLM 判定答案与黄金参考):
```bash
cargo run -p mnesio-bench --features ollama --release -- \
qaeval --suite locomo --k 10 --embedder fastembed --llm ollama
```
| 套件 | 检索 | 答案 + 判定 LLM | QA 准确率 | 毫秒/问题 |
| --- | --- | --- | ---: | ---: |
| LOCOMO-mini | fastembed | llama3.2 3B(Ollama,本地) | 100%(10/10) | 1,765 |
| LongMemEval-mini | fastembed | llama3.2 3B(Ollama,本地) | 100%(10/10) | 1,377 |
测量时针对本地 Ollama 模型 — 实时 LLM 在环中用于答案和判断,而不是离线替代。这些是 **策划的微型套件**(每个 10 个问题),因此 100% 反映了一个小集合;重点是该工具通过相同的摄入 → 混合检索路径生成 **真实的 QA-J 数字**。运行完整的 LOCOMO/LongMemEval 分割线 `qaeval`(任意 `--llm ollama` 模型),以发布可发布的标题数字。
---
## 🗺️ 路线图
- **阶段 0** ✅ 基础 — 事件日志、混合检索、仪表板
- **阶段 1** ✅ 内存演化 — 有限的 A-MEM 样式工作者
- **阶段 2** ✅ 程序化编译 — **楔形,带有机械强制提交门,ALFWorld 风格的基准测试套件
- **阶段 3** ✅ 程序化编译器 — 楔形,具有机械强制提交门,ALFWorld 风格的基准测试套件
- **阶段 4** ✅ 过滤式 HNSW — 在选择范围上自适应过度检索,每个租户分区(`TenantPartitionedVectorView`),软删除可观察性(`tombstone_ratio`,`live_count`)
- **阶段 5** ✅ 分布式 — MCP 服务器 + Python (`pyo3`) 绑定,可从任何代理框架访问
- **阶段 6** ✅ 评估工具作为一流产品(真正的护城河)— `mnesio-bench` 运行/比较 CLI,独立 HTML 报告,CI 回归门,具有退出代码语义
### 竞争层(同类最佳 + 楔形)
- **阶段 7** ✅ 吞吐量智能 — 提取原子事实 → 整合 ADD / UPDATE(矛盾|精炼)/ NOOP,重要性准入 + 衰减 (`mnesio-extract`)
- **阶段 8** ✅ 检索 + 个性化 + 隐私 — 图/最近性融合 + 重新排序器,个人资料内存,多代理 ACL,PII 消除 + 加密粉碎遗忘 (`mnesio-privacy`)
- **阶段 9** ✅ 技能重用 + 分布 — 查询时提交工件注入,Node/TS SDK (`sdk/node`)
### 前沿层(其他人无法实现的 bets)
- **第 10 阶段** ✅ 因果记忆 — 反事实贡献评分 + 测量 GC (`mnesio-causal`)
- **第 11 阶段** ✅ 自我证伪记忆 — 验收探测 + 信念校准;被驳斥的声明自动被取代 (`mnesio-probe`)
- **第 12 阶段** ✅ 门控 KV 弹药 — KV 缓存作为一个有版本控制的、门控的、可擦除的日志视图。基板 + 真实张量注意力后端 (`TensorKvBackend`) + **真实预训练权重后端** (`PretrainedKvBackend`,功能 `pretrained-kv`:加载 GPT-2 的真实嵌入 + 层-0 `c_attn` Q/K/V) + **完整 12 层生成后端** (`GenerativeKvBackend`,功能 `generative-kv`) 全部完成。在生成后端,弹药 *是* GPT-2 的键值缓存:`compile_blob` 预填充整个上下文,`answer` 恢复该缓存并 **生成** 继续关注它。通过自我一致性预言机证明 - 从弹药生成的内容与从头开始处理完整提示 **相同**(KV 缓存是精确的)- 因此弹药是一个忠实、更便宜的替代品,并且重新编译后不能再生成被擦除的事实。 **量化是真实的**:弹药块是两种精度下的紧凑二进制,`Quant::Q8`(每行 int8 + f32 比例因子)使弹药 **4.0 倍更小**(1,179,708 → 296,508 字节在实时 GPT-2 缓存上),同时生成 **相同** 的答案 - 关闭 `CartridgeKey` 的 `quant` 维度,它以前是一个裸标签。而且弹药路径现在在 **现代 2024 型号** (`qwen-kv`:Qwen2.5-0.5B-Instruct — RMSNorm + RoPE + 分组查询注意力 + SwiGLU + bf16,纯 Rust 编写,因此弹药拥有 KV 缓存 - 回答“为什么 GPT-2,而不是更先进的模型?”;Ollama 风格的黑盒文本 API **无法** 支持弹药,因为它从不暴露 KV 张量)。实时:Qwen 弹药回答“法国首都”→“巴黎”,与完整提示相同, shredded-recompile 丢弃事实。而且同一个 Qwen2 前向过程现在在 **真实 GPU 后端** (`QwenCandleBackend`,功能 `candle-kv,metal`) 通过 candle 在 Apple Metal 上运行 - 相同的代码在 `Device::Cpu` 与 `Device::new_metal` 上,因此加速比是类似的:**107 倍更快预填充**(CPU 768.8 毫秒 → Metal 7.2 毫秒在 M1 Pro 上;第一次运行支付一次性 ~100 毫秒 Metal 着色器编译),弹药回答“巴黎”与自己的完整提示路径相同,擦除仍然成立。GPU 后端是 **配置驱动的**(架构来自存储库的 `config.json`,因此 Qwen2.5 **0.5B / 1.5B / 3B / 7B** 加载时无需代码更改)并且 **精度可选** - `F32`,`F16` 或 `BF16`。半精度是真实的, **深度模型故事是诚实的**:f16 的窄指数(最大 ≈ 65504)溢出在 1.5B/28 层模型(垃圾)上,因此深度模型使用 **bf16** - 内存是 f32 的一半 *与* f32 的指数范围(模型的原生数据类型)- 并且 **1.5B 回答“巴黎”正确,bf16 验证实时**。前向过程还累积残差流 / RMSNorm / softmax / logits 在 f32(混合精度)中以确保稳健性,而权重 + KV 缓存保持在所选的半数据类型中。它实时出现在仪表盘中 `GET /api/kv/metrics` 下 `--features candle-kv` + `MNESIO_KV_GPU=1`,模型和精度可在运行时选择 — `MNESIO_KV_GPU_MODEL`(任意 Qwen2 存储库),`MNESIO_KV_GPU_PRECISION`(`f32`/`f16`/`bf16`),`MNESIO_KV_GPU_CPU=0` 跳过 CPU 基线用于大型模型。实时验证:端点服务 **Qwen2.5-1.5B(28 层)bf16 在 Metal 上,回答“巴黎”,擦除后重新编译仍然成立** (`answerable_before → after` = `true → false`)。而且更大的模型放大 GPU 胜利 - 测量的 1.5B 预填充:**Metal bf16 3.34 毫秒 vs CPU f32 5.27 秒 = ~1577 倍**(这叠加 GPU-vs-CPU *和* bf16-vs-f32,因为 candle 的 CPU 后端没有 bf16 matmul 内核,因此 f32 是诚实的 CPU 基线;干净的相同精度数字是 0.5B 上的 107 倍)。具有真实 GPT-2 + Qwen 后端跨 CPU **和** GPU,多个尺寸和两种精度,开放权重张量后端提升第 12 阶段等待的是交付的(`mnesio-kv`)。**完成时已关闭。** 套件级精度一致性评估 (`cargo run -p mnesio-bench -- kveval`) 显示弹药回答 **至少与逐查询文本上下文检索一样准确** - LOCOMO-mini **90% vs 80%**,LongMemEval-mini **60% vs 60%** - 同时回答 **~167–180 倍更快**(它编译一次并重放;文本上下文基线每次查询重新编译),擦除后重新编译仍然成立,并且它控制 CI。生产级别的润色已落地:`CartridgeStore` 采用 **LRU 字节预算 + 有界审计历史** 用于多弹药扩展;真实后端提高 **可行的、`HF_HUB_OFFLINE` 感知的权重错误**;CI **编译检查每个 KV 功能门控** 以便它们不会损坏;并且 candle 后端现在 **接受 Llama 家族配置**(可选 QKV 偏差 + 数组 `eos_token_id`)- Qwen2 是实时验证的路径,Llama 是编译/配置验证的(未绑定 `lm_head` + RoPE 缩放被记录为 TODO)
- **第 13 阶段** ✅ 认证技能交换 — 签名证书;导入者重新运行其自身门控后激活 (`mnesio-exchange`)
- **第 14 阶段** ✅ 负记忆 + 做梦 — 门控抑制规则 + 有界离线按贡献修剪和重新锚定 (`mnesio-dream`)
- **第 15 阶段** ✅ 监管级溯源 — 时间旅行重建 + 溯源链 + 可验证擦除 (`mnesio-provenance`)
前沿层(10–15)是存储型竞争对手(Mem0、Zep、Letta、Cognee、A-MEM)无法跟随的,除非重建其基础;每个 bet 都利用了不可绕过的非旁路安全门后的仅追加 + 可重放 + 双时间日志。参见 `COMPETITIVE.md` → “P3 — 前沿 bets”。
---
## 🧪 测试计数
```
mnesio-core : 3 测试
mnesio-llm : 11 测试
mnesio-index : 83 测试
mnesio-evolve : 27 测试
mnesio-procedural : 112 测试
mnesio-causal : 18 测试
mnesio-probe : 14 测试
mnesio-kv : 15 测试 (+1 `#[ignore]` 在 --features pretrained-kv 下;+1 q8 编码 + 3 `#[ignore]` 在 --features generative-kv 下:GPT-2 12 层前向 + q8;+1 `#[ignore]` 在 --features qwen-kv 下:Qwen2.5-0.5B 24 层前向;+1 Metal 冒烟测试 + 3 `#[ignore]` 在 --features candle-kv,metal 下:GPU Qwen2 前向,f16,更大 1.5B 模型)
mnesio-exchange : 11 测试 (+4 在 --features ed25519 下:真实签名)
mnesio-dream : 10 测试
mnesio-provenance : 8 测试
mnesio-bench : 27 测试 (+7 在 --features fetch 下:SQuAD + HotpotQA 加载器)
mnesio-mcp : 33 测试(单元 + 集成)
mnesio-py : 7 测试(Rust 侧内部客户端覆盖)
mnesio-server : 27 测试
mnesio-store : 1 测试
mnesio-graph : 27 测试
mnesio-extract : 33 测试
mnesio-privacy : 22 测试 (+4 在 --features aead 下:真实 ChaCha20-Poly1305)
sdk/node (TS) : 8 测试(离线,存根获取)
──────────────────────────────
总数 : 489 Rust 测试(486 在 --no-default-features 下)+ 8 SDK 测试 · 全部通过
(+7 在 --features fetch 下的 mnesio-bench 上,+4 aead,+4 ed25519)
```
---
## 🤝 贡献
欢迎贡献。项目执行以下几个特定的模式:
- **门是神圣的。** 对 `mnesio-procedural::gate` 的任何更改都需要一个相应的测试,证明该属性仍然成立。放宽默认阈值需要一个代码审查注释,解释权衡。
- **外部依赖于特征。** 新后端(LLM,嵌入器,判断器,执行器)位于现有的特征表面下;具体实现生活在它们自己的 crate 中。
- **`cargo fmt` + `cargo clippy -- -D warnings` 必须在 `--no-default-features` 和默认配置下通过**,在提交任何更改之前。
- **测试与代码一起生活在 `#[cfg(test)] mod tests` 中。** 存储测试使用一个由新鲜的 ULID 键入的临时目录,并在测试后自行清理。
- **约定提交。** `feat:`、`fix:`、`refactor:`、`test:`、`docs:`。
---
## 💜 支持 mnesio
mnesio 是独立的,Apache-2.0 许可的,并且在开放状态下构建。资金直接用于开发时间,评估计算(LOCOMO / LongMemEval 运行并不免费),并保持项目独立。如果它对您有用 - 或者您希望前沿路线图(因果记忆,门控 KV 弹药,认证技能交换)更快实现 - 请考虑赞助。
<div align="center">
[](https://github.com/sponsors/mnesio)
[](https://opencollective.com/mnesio)
[](https://ko-fi.com/mnesio)
[](https://liberapay.com/mnesio)
</div>
| 平台 | 最适合 | 费用 |
|---|---|---|
| **[GitHub 赞助](https://github.com/sponsors/mnesio)** | 定期 + 一次性,直接在代码旁边 | **0%** (GitHub 涵盖处理费用) |
| **[开放集体](https://opencollective.com/mnesio)** | 透明预算,公司支持者,通往基金会的途径 | 主机 + 处理器 |
| **[Ko-fi](https://ko-fi.com/mnesio)** | 快速一次性提示,无需账户 | 0% 平台 |
| **[Liberapay](https://liberapay.com/mnesio)** | 定期,非盈利,OSS 对齐 | 0% |
存储库顶部的 **赞助** 按钮通过 [.github/FUNDING.yml](.github/FUNDING.yml) 连接。
---
## 📚 背景
两个设计文档支持该项目:
1. 代理内存系统的比较调查(Mem0、Zep、Letta、A-MEM 等)和每个系统存在的不足。
2. Rust 原生自我改进内存架构 + 分阶段建设计划。
代码注释中的章节编号(例如“报告 §3”)引用文档 2。
代码中嵌入的引用:
- A-MEM:Lyu 等,*Agentic Memory for LLM Agents*,arXiv:2502.12110(内存进化模型)
- GEPA:Du 等,*General Evolutionary Prompt Adaptation*,arXiv:2507.19457(反射循环模式)
- ACORN:Wu 等,*ACORN: Performant Hybrid Search*(过滤 HNSW - 通知第 3 阶段的自适应超检索 + 分区方法)
---
## ⚠️ 稳定性
这是 `0.1.0` - 第一个可用的版本。该系统在所有六个构建阶段中以 380 个通过测试的测试一起工作,但公共 API 表面仍将随着图存储和过程编译器获得实际使用而发生变化。在您的 `Cargo.toml` 中固定特定版本;预计在 `0.x.y` 增量之间会发生破坏性更改。
---
## 📜 许可证
Apache License 2.0。参见 [LICENSE](LICENSE)。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器